1// This is an open source non-commercial project. Dear PVS-Studio, please check
2// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
4/*
5 * getchar.c
6 *
7 * functions related with getting a character from the user/mapping/redo/...
8 *
9 * manipulations with redo buffer and stuff buffer
10 * mappings and abbreviations
11 */
12
13#include <assert.h>
14#include <stdbool.h>
15#include <string.h>
16#include <inttypes.h>
17
18#include "nvim/assert.h"
19#include "nvim/vim.h"
20#include "nvim/ascii.h"
21#include "nvim/getchar.h"
22#include "nvim/buffer_defs.h"
23#include "nvim/charset.h"
24#include "nvim/cursor.h"
25#include "nvim/edit.h"
26#include "nvim/eval.h"
27#include "nvim/ex_docmd.h"
28#include "nvim/ex_getln.h"
29#include "nvim/func_attr.h"
30#include "nvim/main.h"
31#include "nvim/mbyte.h"
32#include "nvim/memline.h"
33#include "nvim/memory.h"
34#include "nvim/message.h"
35#include "nvim/misc1.h"
36#include "nvim/keymap.h"
37#include "nvim/garray.h"
38#include "nvim/move.h"
39#include "nvim/normal.h"
40#include "nvim/ops.h"
41#include "nvim/option.h"
42#include "nvim/regexp.h"
43#include "nvim/screen.h"
44#include "nvim/state.h"
45#include "nvim/strings.h"
46#include "nvim/ui.h"
47#include "nvim/undo.h"
48#include "nvim/event/loop.h"
49#include "nvim/os/input.h"
50#include "nvim/os/os.h"
51#include "nvim/os/fileio.h"
52#include "nvim/api/private/handle.h"
53
54
55/// Index in scriptin
56static int curscript = 0;
57FileDescriptor *scriptin[NSCRIPT] = { NULL };
58
59/*
60 * These buffers are used for storing:
61 * - stuffed characters: A command that is translated into another command.
62 * - redo characters: will redo the last change.
63 * - recorded characters: for the "q" command.
64 *
65 * The bytes are stored like in the typeahead buffer:
66 * - K_SPECIAL introduces a special key (two more bytes follow). A literal
67 * K_SPECIAL is stored as K_SPECIAL KS_SPECIAL KE_FILLER.
68 * - CSI introduces a GUI termcap code (also when gui.in_use is FALSE,
69 * otherwise switching the GUI on would make mappings invalid).
70 * A literal CSI is stored as CSI KS_EXTRA KE_CSI.
71 * These translations are also done on multi-byte characters!
72 *
73 * Escaping CSI bytes is done by the system-specific input functions, called
74 * by ui_inchar().
75 * Escaping K_SPECIAL is done by inchar().
76 * Un-escaping is done by vgetc().
77 */
78
79#define MINIMAL_SIZE 20 /* minimal size for b_str */
80
81static buffheader_T redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
82static buffheader_T old_redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
83static buffheader_T recordbuff = { { NULL, { NUL } }, NULL, 0, 0 };
84
85// First read ahead buffer. Used for translated commands.
86static buffheader_T readbuf1 = { { NULL, { NUL } }, NULL, 0, 0 };
87
88// Second read ahead buffer. Used for redo.
89static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
90
91static int typeahead_char = 0; /* typeahead char that's not flushed */
92
93/*
94 * when block_redo is TRUE redo buffer will not be changed
95 * used by edit() to repeat insertions and 'V' command for redoing
96 */
97static int block_redo = FALSE;
98
99// Make a hash value for a mapping.
100// "mode" is the lower 4 bits of the State for the mapping.
101// "c1" is the first character of the "lhs".
102// Returns a value between 0 and 255, index in maphash.
103// Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode.
104#define MAP_HASH(mode, \
105 c1) (((mode) & \
106 (NORMAL + VISUAL + SELECTMODE + \
107 OP_PENDING + TERM_FOCUS)) ? (c1) : ((c1) ^ 0x80))
108
109// Each mapping is put in one of the MAX_MAPHASH hash lists,
110// to speed up finding it.
111static mapblock_T *(maphash[MAX_MAPHASH]);
112static bool maphash_valid = false;
113
114/*
115 * List used for abbreviations.
116 */
117static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */
118
119static int KeyNoremap = 0; /* remapping flags */
120
121/*
122 * Variables used by vgetorpeek() and flush_buffers()
123 *
124 * typebuf.tb_buf[] contains all characters that are not consumed yet.
125 * typebuf.tb_buf[typebuf.tb_off] is the first valid character.
126 * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char.
127 * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL.
128 * The head of the buffer may contain the result of mappings, abbreviations
129 * and @a commands. The length of this part is typebuf.tb_maplen.
130 * typebuf.tb_silent is the part where <silent> applies.
131 * After the head are characters that come from the terminal.
132 * typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that
133 * should not be considered for abbreviations.
134 * Some parts of typebuf.tb_buf may not be mapped. These parts are remembered
135 * in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and
136 * contains RM_NONE for the characters that are not to be remapped.
137 * typebuf.tb_noremap[typebuf.tb_off] is the first valid flag.
138 * (typebuf has been put in globals.h, because check_termcode() needs it).
139 */
140#define RM_YES 0 /* tb_noremap: remap */
141#define RM_NONE 1 /* tb_noremap: don't remap */
142#define RM_SCRIPT 2 /* tb_noremap: remap local script mappings */
143#define RM_ABBR 4 /* tb_noremap: don't remap, do abbrev. */
144
145/* typebuf.tb_buf has three parts: room in front (for result of mappings), the
146 * middle for typeahead and room for new characters (which needs to be 3 *
147 * MAXMAPLEN) for the Amiga).
148 */
149#define TYPELEN_INIT (5 * (MAXMAPLEN + 3))
150static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf.tb_buf */
151static char_u noremapbuf_init[TYPELEN_INIT]; /* initial typebuf.tb_noremap */
152
153static size_t last_recorded_len = 0; // number of last recorded chars
154
155#ifdef INCLUDE_GENERATED_DECLARATIONS
156# include "getchar.c.generated.h"
157#endif
158
159/*
160 * Free and clear a buffer.
161 */
162void free_buff(buffheader_T *buf)
163{
164 buffblock_T *p, *np;
165
166 for (p = buf->bh_first.b_next; p != NULL; p = np) {
167 np = p->b_next;
168 xfree(p);
169 }
170 buf->bh_first.b_next = NULL;
171}
172
173/*
174 * Return the contents of a buffer as a single string.
175 * K_SPECIAL and CSI in the returned string are escaped.
176 */
177static char_u *get_buffcont(buffheader_T *buffer,
178 int dozero // count == zero is not an error
179 )
180{
181 size_t count = 0;
182 char_u *p = NULL;
183 char_u *p2;
184
185 // compute the total length of the string
186 for (const buffblock_T *bp = buffer->bh_first.b_next;
187 bp != NULL; bp = bp->b_next) {
188 count += STRLEN(bp->b_str);
189 }
190
191 if (count || dozero) {
192 p = xmalloc(count + 1);
193 p2 = p;
194 for (const buffblock_T *bp = buffer->bh_first.b_next;
195 bp != NULL; bp = bp->b_next) {
196 for (const char_u *str = bp->b_str; *str;) {
197 *p2++ = *str++;
198 }
199 }
200 *p2 = NUL;
201 }
202 return p;
203}
204
205/*
206 * Return the contents of the record buffer as a single string
207 * and clear the record buffer.
208 * K_SPECIAL and CSI in the returned string are escaped.
209 */
210char_u *get_recorded(void)
211{
212 char_u *p;
213 size_t len;
214
215 p = get_buffcont(&recordbuff, TRUE);
216 free_buff(&recordbuff);
217
218 /*
219 * Remove the characters that were added the last time, these must be the
220 * (possibly mapped) characters that stopped the recording.
221 */
222 len = STRLEN(p);
223 if (len >= last_recorded_len) {
224 len -= last_recorded_len;
225 p[len] = NUL;
226 }
227
228 /*
229 * When stopping recording from Insert mode with CTRL-O q, also remove the
230 * CTRL-O.
231 */
232 if (len > 0 && restart_edit != 0 && p[len - 1] == Ctrl_O)
233 p[len - 1] = NUL;
234
235 return p;
236}
237
238/*
239 * Return the contents of the redo buffer as a single string.
240 * K_SPECIAL and CSI in the returned string are escaped.
241 */
242char_u *get_inserted(void)
243{
244 return get_buffcont(&redobuff, FALSE);
245}
246
247/// Add string after the current block of the given buffer
248///
249/// K_SPECIAL and CSI should have been escaped already.
250///
251/// @param[out] buf Buffer to add to.
252/// @param[in] s String to add.
253/// @param[in] slen String length or -1 for NUL-terminated string.
254static void add_buff(buffheader_T *const buf, const char *const s,
255 ptrdiff_t slen)
256{
257 if (slen < 0) {
258 slen = (ptrdiff_t)strlen(s);
259 }
260 if (slen == 0) { // don't add empty strings
261 return;
262 }
263
264 if (buf->bh_first.b_next == NULL) { // first add to list
265 buf->bh_space = 0;
266 buf->bh_curr = &(buf->bh_first);
267 } else if (buf->bh_curr == NULL) { // buffer has already been read
268 IEMSG(_("E222: Add to read buffer"));
269 return;
270 } else if (buf->bh_index != 0) {
271 memmove(buf->bh_first.b_next->b_str,
272 buf->bh_first.b_next->b_str + buf->bh_index,
273 STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1);
274 }
275 buf->bh_index = 0;
276
277 size_t len;
278 if (buf->bh_space >= (size_t)slen) {
279 len = STRLEN(buf->bh_curr->b_str);
280 STRLCPY(buf->bh_curr->b_str + len, s, slen + 1);
281 buf->bh_space -= (size_t)slen;
282 } else {
283 if (slen < MINIMAL_SIZE) {
284 len = MINIMAL_SIZE;
285 } else {
286 len = (size_t)slen;
287 }
288 buffblock_T *p = xmalloc(sizeof(buffblock_T) + len);
289 buf->bh_space = len - (size_t)slen;
290 STRLCPY(p->b_str, s, slen + 1);
291
292 p->b_next = buf->bh_curr->b_next;
293 buf->bh_curr->b_next = p;
294 buf->bh_curr = p;
295 }
296 return;
297}
298
299/*
300 * Add number "n" to buffer "buf".
301 */
302static void add_num_buff(buffheader_T *buf, long n)
303{
304 char number[32];
305 snprintf(number, sizeof(number), "%ld", n);
306 add_buff(buf, number, -1L);
307}
308
309/*
310 * Add character 'c' to buffer "buf".
311 * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
312 */
313static void add_char_buff(buffheader_T *buf, int c)
314{
315 uint8_t bytes[MB_MAXBYTES + 1];
316
317 int len;
318 if (IS_SPECIAL(c)) {
319 len = 1;
320 } else {
321 len = utf_char2bytes(c, bytes);
322 }
323
324 for (int i = 0; i < len; i++) {
325 if (!IS_SPECIAL(c)) {
326 c = bytes[i];
327 }
328
329 char temp[4];
330 if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
331 // Translate special key code into three byte sequence.
332 temp[0] = (char)K_SPECIAL;
333 temp[1] = (char)K_SECOND(c);
334 temp[2] = (char)K_THIRD(c);
335 temp[3] = NUL;
336 } else {
337 temp[0] = (char)c;
338 temp[1] = NUL;
339 }
340 add_buff(buf, temp, -1L);
341 }
342}
343
344/*
345 * Get one byte from the read buffers. Use readbuf1 one first, use readbuf2
346 * if that one is empty.
347 * If advance == TRUE go to the next char.
348 * No translation is done K_SPECIAL and CSI are escaped.
349 */
350static int read_readbuffers(int advance)
351{
352 int c;
353
354 c = read_readbuf(&readbuf1, advance);
355 if (c == NUL)
356 c = read_readbuf(&readbuf2, advance);
357 return c;
358}
359
360static int read_readbuf(buffheader_T *buf, int advance)
361{
362 char_u c;
363
364 if (buf->bh_first.b_next == NULL) { // buffer is empty
365 return NUL;
366 }
367
368 buffblock_T *const curr = buf->bh_first.b_next;
369 c = curr->b_str[buf->bh_index];
370
371 if (advance) {
372 if (curr->b_str[++buf->bh_index] == NUL) {
373 buf->bh_first.b_next = curr->b_next;
374 xfree(curr);
375 buf->bh_index = 0;
376 }
377 }
378 return c;
379}
380
381/*
382 * Prepare the read buffers for reading (if they contain something).
383 */
384static void start_stuff(void)
385{
386 if (readbuf1.bh_first.b_next != NULL) {
387 readbuf1.bh_curr = &(readbuf1.bh_first);
388 readbuf1.bh_space = 0;
389 }
390 if (readbuf2.bh_first.b_next != NULL) {
391 readbuf2.bh_curr = &(readbuf2.bh_first);
392 readbuf2.bh_space = 0;
393 }
394}
395
396/*
397 * Return TRUE if the stuff buffer is empty.
398 */
399int stuff_empty(void)
400{
401 return (readbuf1.bh_first.b_next == NULL && readbuf2.bh_first.b_next == NULL);
402}
403
404/*
405 * Return TRUE if readbuf1 is empty. There may still be redo characters in
406 * redbuf2.
407 */
408int readbuf1_empty(void)
409{
410 return (readbuf1.bh_first.b_next == NULL);
411}
412
413/*
414 * Set a typeahead character that won't be flushed.
415 */
416void typeahead_noflush(int c)
417{
418 typeahead_char = c;
419}
420
421/*
422 * Remove the contents of the stuff buffer and the mapped characters in the
423 * typeahead buffer (used in case of an error). If "flush_typeahead" is true,
424 * flush all typeahead characters (used when interrupted by a CTRL-C).
425 */
426void flush_buffers(flush_buffers_T flush_typeahead)
427{
428 init_typebuf();
429
430 start_stuff();
431 while (read_readbuffers(TRUE) != NUL) {
432 }
433
434 if (flush_typeahead == FLUSH_MINIMAL) {
435 // remove mapped characters at the start only
436 typebuf.tb_off += typebuf.tb_maplen;
437 typebuf.tb_len -= typebuf.tb_maplen;
438 } else {
439 // remove typeahead
440 if (flush_typeahead == FLUSH_INPUT) {
441 // We have to get all characters, because we may delete the first
442 // part of an escape sequence. In an xterm we get one char at a
443 // time and we have to get them all.
444 while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L) != 0) {
445 }
446 }
447 typebuf.tb_off = MAXMAPLEN;
448 typebuf.tb_len = 0;
449 // Reset the flag that text received from a client or from feedkeys()
450 // was inserted in the typeahead buffer.
451 typebuf_was_filled = false;
452 }
453 typebuf.tb_maplen = 0;
454 typebuf.tb_silent = 0;
455 cmd_silent = false;
456 typebuf.tb_no_abbr_cnt = 0;
457}
458
459/*
460 * The previous contents of the redo buffer is kept in old_redobuffer.
461 * This is used for the CTRL-O <.> command in insert mode.
462 */
463void ResetRedobuff(void)
464{
465 if (!block_redo) {
466 free_buff(&old_redobuff);
467 old_redobuff = redobuff;
468 redobuff.bh_first.b_next = NULL;
469 }
470}
471
472/*
473 * Discard the contents of the redo buffer and restore the previous redo
474 * buffer.
475 */
476void CancelRedo(void)
477{
478 if (!block_redo) {
479 free_buff(&redobuff);
480 redobuff = old_redobuff;
481 old_redobuff.bh_first.b_next = NULL;
482 start_stuff();
483 while (read_readbuffers(TRUE) != NUL) {
484 }
485 }
486}
487
488/// Save redobuff and old_redobuff to save_redobuff and save_old_redobuff.
489/// Used before executing autocommands and user functions.
490void saveRedobuff(save_redo_T *save_redo)
491{
492 save_redo->sr_redobuff = redobuff;
493 redobuff.bh_first.b_next = NULL;
494 save_redo->sr_old_redobuff = old_redobuff;
495 old_redobuff.bh_first.b_next = NULL;
496
497 // Make a copy, so that ":normal ." in a function works.
498 char *const s = (char *)get_buffcont(&save_redo->sr_redobuff, false);
499 if (s != NULL) {
500 add_buff(&redobuff, s, -1L);
501 xfree(s);
502 }
503}
504
505/// Restore redobuff and old_redobuff from save_redobuff and save_old_redobuff.
506/// Used after executing autocommands and user functions.
507void restoreRedobuff(save_redo_T *save_redo)
508{
509 free_buff(&redobuff);
510 redobuff = save_redo->sr_redobuff;
511 free_buff(&old_redobuff);
512 old_redobuff = save_redo->sr_old_redobuff;
513}
514
515/*
516 * Append "s" to the redo buffer.
517 * K_SPECIAL and CSI should already have been escaped.
518 */
519void AppendToRedobuff(const char *s)
520{
521 if (!block_redo) {
522 add_buff(&redobuff, (const char *)s, -1L);
523 }
524}
525
526/// Append to Redo buffer literally, escaping special characters with CTRL-V.
527/// K_SPECIAL and CSI are escaped as well.
528///
529/// @param str String to append
530/// @param len Length of `str` or -1 for up to the NUL.
531void AppendToRedobuffLit(const char_u *str, int len)
532{
533 if (block_redo) {
534 return;
535 }
536
537 const char *s = (const char *)str;
538 while (len < 0 ? *s != NUL : s - (const char *)str < len) {
539 // Put a string of normal characters in the redo buffer (that's
540 // faster).
541 const char *start = s;
542 while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) {
543 s++;
544 }
545
546 // Don't put '0' or '^' as last character, just in case a CTRL-D is
547 // typed next.
548 if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) {
549 s--;
550 }
551 if (s > start) {
552 add_buff(&redobuff, start, (long)(s - start));
553 }
554
555 if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) {
556 break;
557 }
558
559 // Handle a special or multibyte character.
560 // Composing chars separately are handled separately.
561 const int c = (has_mbyte
562 ? mb_cptr2char_adv((const char_u **)&s)
563 : (uint8_t)(*s++));
564 if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
565 add_char_buff(&redobuff, Ctrl_V);
566 }
567
568 // CTRL-V '0' must be inserted as CTRL-V 048.
569 if (*s == NUL && c == '0') {
570 add_buff(&redobuff, "048", 3L);
571 } else {
572 add_char_buff(&redobuff, c);
573 }
574 }
575}
576
577/*
578 * Append a character to the redo buffer.
579 * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
580 */
581void AppendCharToRedobuff(int c)
582{
583 if (!block_redo)
584 add_char_buff(&redobuff, c);
585}
586
587/*
588 * Append a number to the redo buffer.
589 */
590void AppendNumberToRedobuff(long n)
591{
592 if (!block_redo)
593 add_num_buff(&redobuff, n);
594}
595
596/*
597 * Append string "s" to the stuff buffer.
598 * CSI and K_SPECIAL must already have been escaped.
599 */
600void stuffReadbuff(const char *s)
601{
602 add_buff(&readbuf1, s, -1L);
603}
604
605/// Append string "s" to the redo stuff buffer.
606/// @remark CSI and K_SPECIAL must already have been escaped.
607void stuffRedoReadbuff(const char *s)
608{
609 add_buff(&readbuf2, s, -1L);
610}
611
612void stuffReadbuffLen(const char *s, long len)
613{
614 add_buff(&readbuf1, s, len);
615}
616
617/*
618 * Stuff "s" into the stuff buffer, leaving special key codes unmodified and
619 * escaping other K_SPECIAL and CSI bytes.
620 * Change CR, LF and ESC into a space.
621 */
622void stuffReadbuffSpec(const char *s)
623{
624 while (*s != NUL) {
625 if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
626 // Insert special key literally.
627 stuffReadbuffLen(s, 3);
628 s += 3;
629 } else {
630 int c = mb_ptr2char_adv((const char_u **)&s);
631 if (c == CAR || c == NL || c == ESC) {
632 c = ' ';
633 }
634 stuffcharReadbuff(c);
635 }
636 }
637}
638
639/*
640 * Append a character to the stuff buffer.
641 * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
642 */
643void stuffcharReadbuff(int c)
644{
645 add_char_buff(&readbuf1, c);
646}
647
648/*
649 * Append a number to the stuff buffer.
650 */
651void stuffnumReadbuff(long n)
652{
653 add_num_buff(&readbuf1, n);
654}
655
656// Read a character from the redo buffer. Translates K_SPECIAL, CSI and
657// multibyte characters.
658// The redo buffer is left as it is.
659// If init is true, prepare for redo, return FAIL if nothing to redo, OK
660// otherwise.
661// If old_redo is true, use old_redobuff instead of redobuff.
662static int read_redo(bool init, bool old_redo)
663{
664 static buffblock_T *bp;
665 static char_u *p;
666 int c;
667 int n;
668 char_u buf[MB_MAXBYTES + 1];
669 int i;
670
671 if (init) {
672 bp = old_redo ? old_redobuff.bh_first.b_next : redobuff.bh_first.b_next;
673 if (bp == NULL) {
674 return FAIL;
675 }
676 p = bp->b_str;
677 return OK;
678 }
679 if ((c = *p) == NUL) {
680 return c;
681 }
682 /* Reverse the conversion done by add_char_buff() */
683 /* For a multi-byte character get all the bytes and return the
684 * converted character. */
685 if (has_mbyte && (c != K_SPECIAL || p[1] == KS_SPECIAL))
686 n = MB_BYTE2LEN_CHECK(c);
687 else
688 n = 1;
689 for (i = 0;; ++i) {
690 if (c == K_SPECIAL) { /* special key or escaped K_SPECIAL */
691 c = TO_SPECIAL(p[1], p[2]);
692 p += 2;
693 }
694 if (*++p == NUL && bp->b_next != NULL) {
695 bp = bp->b_next;
696 p = bp->b_str;
697 }
698 buf[i] = (char_u)c;
699 if (i == n - 1) { // last byte of a character
700 if (n != 1) {
701 c = utf_ptr2char(buf);
702 }
703 break;
704 }
705 c = *p;
706 if (c == NUL) /* cannot happen? */
707 break;
708 }
709
710 return c;
711}
712
713// Copy the rest of the redo buffer into the stuff buffer (in a slow way).
714// If old_redo is true, use old_redobuff instead of redobuff.
715// The escaped K_SPECIAL and CSI are copied without translation.
716static void copy_redo(bool old_redo)
717{
718 int c;
719
720 while ((c = read_redo(false, old_redo)) != NUL) {
721 add_char_buff(&readbuf2, c);
722 }
723}
724
725// Stuff the redo buffer into readbuf2.
726// Insert the redo count into the command.
727// If "old_redo" is true, the last but one command is repeated
728// instead of the last command (inserting text). This is used for
729// CTRL-O <.> in insert mode
730//
731// return FAIL for failure, OK otherwise
732int start_redo(long count, bool old_redo)
733{
734 int c;
735
736 // init the pointers; return if nothing to redo
737 if (read_redo(true, old_redo) == FAIL) {
738 return FAIL;
739 }
740
741 c = read_redo(false, old_redo);
742
743 /* copy the buffer name, if present */
744 if (c == '"') {
745 add_buff(&readbuf2, "\"", 1L);
746 c = read_redo(false, old_redo);
747
748 /* if a numbered buffer is used, increment the number */
749 if (c >= '1' && c < '9')
750 ++c;
751 add_char_buff(&readbuf2, c);
752
753 // the expression register should be re-evaluated
754 if (c == '=') {
755 add_char_buff(&readbuf2, CAR);
756 cmd_silent = true;
757 }
758
759 c = read_redo(false, old_redo);
760 }
761
762 if (c == 'v') { /* redo Visual */
763 VIsual = curwin->w_cursor;
764 VIsual_active = true;
765 VIsual_select = false;
766 VIsual_reselect = true;
767 redo_VIsual_busy = true;
768 c = read_redo(false, old_redo);
769 }
770
771 // try to enter the count (in place of a previous count)
772 if (count) {
773 while (ascii_isdigit(c)) { // skip "old" count
774 c = read_redo(false, old_redo);
775 }
776 add_num_buff(&readbuf2, count);
777 }
778
779 /* copy from the redo buffer into the stuff buffer */
780 add_char_buff(&readbuf2, c);
781 copy_redo(old_redo);
782 return OK;
783}
784
785/*
786 * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
787 * the redo buffer into readbuf2.
788 * return FAIL for failure, OK otherwise
789 */
790int start_redo_ins(void)
791{
792 int c;
793
794 if (read_redo(true, false) == FAIL) {
795 return FAIL;
796 }
797 start_stuff();
798
799 // skip the count and the command character
800 while ((c = read_redo(false, false)) != NUL) {
801 if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL) {
802 if (c == 'O' || c == 'o') {
803 add_buff(&readbuf2, NL_STR, -1L);
804 }
805 break;
806 }
807 }
808
809 // copy the typed text from the redo buffer into the stuff buffer
810 copy_redo(false);
811 block_redo = true;
812 return OK;
813}
814
815void stop_redo_ins(void)
816{
817 block_redo = FALSE;
818}
819
820/*
821 * Initialize typebuf.tb_buf to point to typebuf_init.
822 * alloc() cannot be used here: In out-of-memory situations it would
823 * be impossible to type anything.
824 */
825static void init_typebuf(void)
826{
827 if (typebuf.tb_buf == NULL) {
828 typebuf.tb_buf = typebuf_init;
829 typebuf.tb_noremap = noremapbuf_init;
830 typebuf.tb_buflen = TYPELEN_INIT;
831 typebuf.tb_len = 0;
832 typebuf.tb_off = MAXMAPLEN + 4;
833 typebuf.tb_change_cnt = 1;
834 }
835}
836
837/*
838 * insert a string in position 'offset' in the typeahead buffer (for "@r"
839 * and ":normal" command, vgetorpeek() and check_termcode())
840 *
841 * If noremap is REMAP_YES, new string can be mapped again.
842 * If noremap is REMAP_NONE, new string cannot be mapped again.
843 * If noremap is REMAP_SKIP, fist char of new string cannot be mapped again,
844 * but abbreviations are allowed.
845 * If noremap is REMAP_SCRIPT, new string cannot be mapped again, except for
846 * script-local mappings.
847 * If noremap is > 0, that many characters of the new string cannot be mapped.
848 *
849 * If nottyped is TRUE, the string does not return KeyTyped (don't use when
850 * offset is non-zero!).
851 *
852 * If silent is true, cmd_silent is set when the characters are obtained.
853 *
854 * return FAIL for failure, OK otherwise
855 */
856int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
857{
858 char_u *s1, *s2;
859 int newlen;
860 int addlen;
861 int i;
862 int newoff;
863 int val;
864 int nrm;
865
866 init_typebuf();
867 if (++typebuf.tb_change_cnt == 0)
868 typebuf.tb_change_cnt = 1;
869
870 addlen = (int)STRLEN(str);
871
872 if (offset == 0 && addlen <= typebuf.tb_off) {
873 // Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
874 typebuf.tb_off -= addlen;
875 memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
876 } else if (typebuf.tb_len == 0
877 && typebuf.tb_buflen >= addlen + 3 * (MAXMAPLEN + 4)) {
878 // Buffer is empty and string fits in the existing buffer.
879 // Leave some space before and after, if possible.
880 typebuf.tb_off = (typebuf.tb_buflen - addlen - 3 * (MAXMAPLEN + 4)) / 2;
881 memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
882 } else {
883 // Need to allocate a new buffer.
884 // In typebuf.tb_buf there must always be room for 3 * (MAXMAPLEN + 4)
885 // characters. We add some extra room to avoid having to allocate too
886 // often.
887 newoff = MAXMAPLEN + 4;
888 newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
889 if (newlen < 0) { /* string is getting too long */
890 EMSG(_(e_toocompl)); /* also calls flush_buffers */
891 setcursor();
892 return FAIL;
893 }
894 s1 = xmalloc((size_t)newlen);
895 s2 = xmalloc((size_t)newlen);
896 typebuf.tb_buflen = newlen;
897
898 // copy the old chars, before the insertion point
899 memmove(s1 + newoff, typebuf.tb_buf + typebuf.tb_off, (size_t)offset);
900 // copy the new chars
901 memmove(s1 + newoff + offset, str, (size_t)addlen);
902 // copy the old chars, after the insertion point, including the NUL at
903 // the end
904 int bytes = typebuf.tb_len - offset + 1;
905 assert(bytes > 0);
906 memmove(s1 + newoff + offset + addlen,
907 typebuf.tb_buf + typebuf.tb_off + offset, (size_t)bytes);
908 if (typebuf.tb_buf != typebuf_init) {
909 xfree(typebuf.tb_buf);
910 }
911 typebuf.tb_buf = s1;
912
913 memmove(s2 + newoff, typebuf.tb_noremap + typebuf.tb_off,
914 (size_t)offset);
915 memmove(s2 + newoff + offset + addlen,
916 typebuf.tb_noremap + typebuf.tb_off + offset,
917 (size_t)(typebuf.tb_len - offset));
918 if (typebuf.tb_noremap != noremapbuf_init)
919 xfree(typebuf.tb_noremap);
920 typebuf.tb_noremap = s2;
921
922 typebuf.tb_off = newoff;
923 }
924 typebuf.tb_len += addlen;
925
926 /* If noremap == REMAP_SCRIPT: do remap script-local mappings. */
927 if (noremap == REMAP_SCRIPT)
928 val = RM_SCRIPT;
929 else if (noremap == REMAP_SKIP)
930 val = RM_ABBR;
931 else
932 val = RM_NONE;
933
934 /*
935 * Adjust typebuf.tb_noremap[] for the new characters:
936 * If noremap == REMAP_NONE or REMAP_SCRIPT: new characters are
937 * (sometimes) not remappable
938 * If noremap == REMAP_YES: all the new characters are mappable
939 * If noremap > 0: "noremap" characters are not remappable, the rest
940 * mappable
941 */
942 if (noremap == REMAP_SKIP)
943 nrm = 1;
944 else if (noremap < 0)
945 nrm = addlen;
946 else
947 nrm = noremap;
948 for (i = 0; i < addlen; ++i)
949 typebuf.tb_noremap[typebuf.tb_off + i + offset] =
950 (char_u)((--nrm >= 0) ? val : RM_YES);
951
952 /* tb_maplen and tb_silent only remember the length of mapped and/or
953 * silent mappings at the start of the buffer, assuming that a mapped
954 * sequence doesn't result in typed characters. */
955 if (nottyped || typebuf.tb_maplen > offset)
956 typebuf.tb_maplen += addlen;
957 if (silent || typebuf.tb_silent > offset) {
958 typebuf.tb_silent += addlen;
959 cmd_silent = true;
960 }
961 if (typebuf.tb_no_abbr_cnt && offset == 0) /* and not used for abbrev.s */
962 typebuf.tb_no_abbr_cnt += addlen;
963
964 return OK;
965}
966
967/*
968 * Put character "c" back into the typeahead buffer.
969 * Can be used for a character obtained by vgetc() that needs to be put back.
970 * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
971 * the char.
972 */
973void ins_char_typebuf(int c)
974{
975 char_u buf[MB_MAXBYTES + 1];
976 if (IS_SPECIAL(c)) {
977 buf[0] = K_SPECIAL;
978 buf[1] = (char_u)K_SECOND(c);
979 buf[2] = (char_u)K_THIRD(c);
980 buf[3] = NUL;
981 } else {
982 buf[utf_char2bytes(c, buf)] = NUL;
983 }
984 (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
985}
986
987/*
988 * Return TRUE if the typeahead buffer was changed (while waiting for a
989 * character to arrive). Happens when a message was received from a client or
990 * from feedkeys().
991 * But check in a more generic way to avoid trouble: When "typebuf.tb_buf"
992 * changed it was reallocated and the old pointer can no longer be used.
993 * Or "typebuf.tb_off" may have been changed and we would overwrite characters
994 * that was just added.
995 */
996int
997typebuf_changed (
998 int tb_change_cnt /* old value of typebuf.tb_change_cnt */
999)
1000{
1001 return tb_change_cnt != 0 && (typebuf.tb_change_cnt != tb_change_cnt
1002 || typebuf_was_filled
1003 );
1004}
1005
1006/*
1007 * Return TRUE if there are no characters in the typeahead buffer that have
1008 * not been typed (result from a mapping or come from ":normal").
1009 */
1010int typebuf_typed(void)
1011{
1012 return typebuf.tb_maplen == 0;
1013}
1014
1015/*
1016 * Return the number of characters that are mapped (or not typed).
1017 */
1018int typebuf_maplen(void)
1019{
1020 return typebuf.tb_maplen;
1021}
1022
1023/*
1024 * remove "len" characters from typebuf.tb_buf[typebuf.tb_off + offset]
1025 */
1026void del_typebuf(int len, int offset)
1027{
1028 int i;
1029
1030 if (len == 0)
1031 return; /* nothing to do */
1032
1033 typebuf.tb_len -= len;
1034
1035 /*
1036 * Easy case: Just increase typebuf.tb_off.
1037 */
1038 if (offset == 0 && typebuf.tb_buflen - (typebuf.tb_off + len)
1039 >= 3 * MAXMAPLEN + 3)
1040 typebuf.tb_off += len;
1041 /*
1042 * Have to move the characters in typebuf.tb_buf[] and typebuf.tb_noremap[]
1043 */
1044 else {
1045 i = typebuf.tb_off + offset;
1046 /*
1047 * Leave some extra room at the end to avoid reallocation.
1048 */
1049 if (typebuf.tb_off > MAXMAPLEN) {
1050 memmove(typebuf.tb_buf + MAXMAPLEN,
1051 typebuf.tb_buf + typebuf.tb_off, (size_t)offset);
1052 memmove(typebuf.tb_noremap + MAXMAPLEN,
1053 typebuf.tb_noremap + typebuf.tb_off, (size_t)offset);
1054 typebuf.tb_off = MAXMAPLEN;
1055 }
1056 // adjust typebuf.tb_buf (include the NUL at the end)
1057 int bytes = typebuf.tb_len - offset + 1;
1058 assert(bytes > 0);
1059 memmove(typebuf.tb_buf + typebuf.tb_off + offset,
1060 typebuf.tb_buf + i + len, (size_t)bytes);
1061 // adjust typebuf.tb_noremap[]
1062 memmove(typebuf.tb_noremap + typebuf.tb_off + offset,
1063 typebuf.tb_noremap + i + len,
1064 (size_t)(typebuf.tb_len - offset));
1065 }
1066
1067 if (typebuf.tb_maplen > offset) { /* adjust tb_maplen */
1068 if (typebuf.tb_maplen < offset + len)
1069 typebuf.tb_maplen = offset;
1070 else
1071 typebuf.tb_maplen -= len;
1072 }
1073 if (typebuf.tb_silent > offset) { /* adjust tb_silent */
1074 if (typebuf.tb_silent < offset + len)
1075 typebuf.tb_silent = offset;
1076 else
1077 typebuf.tb_silent -= len;
1078 }
1079 if (typebuf.tb_no_abbr_cnt > offset) { /* adjust tb_no_abbr_cnt */
1080 if (typebuf.tb_no_abbr_cnt < offset + len)
1081 typebuf.tb_no_abbr_cnt = offset;
1082 else
1083 typebuf.tb_no_abbr_cnt -= len;
1084 }
1085
1086 /* Reset the flag that text received from a client or from feedkeys()
1087 * was inserted in the typeahead buffer. */
1088 typebuf_was_filled = false;
1089 if (++typebuf.tb_change_cnt == 0) {
1090 typebuf.tb_change_cnt = 1;
1091 }
1092}
1093
1094/*
1095 * Write typed characters to script file.
1096 * If recording is on put the character in the recordbuffer.
1097 */
1098static void gotchars(char_u *chars, size_t len)
1099{
1100 char_u *s = chars;
1101 int c;
1102
1103 // remember how many chars were last recorded
1104 if (reg_recording != 0) {
1105 last_recorded_len += len;
1106 }
1107
1108 while (len--) {
1109 // Handle one byte at a time; no translation to be done.
1110 c = *s++;
1111 updatescript(c);
1112
1113 if (reg_recording != 0) {
1114 char buf[2] = { (char)c, NUL };
1115 add_buff(&recordbuff, buf, 1L);
1116 }
1117 }
1118 may_sync_undo();
1119
1120 /* output "debug mode" message next time in debug mode */
1121 debug_did_msg = FALSE;
1122
1123 /* Since characters have been typed, consider the following to be in
1124 * another mapping. Search string will be kept in history. */
1125 ++maptick;
1126}
1127
1128/*
1129 * Sync undo. Called when typed characters are obtained from the typeahead
1130 * buffer, or when a menu is used.
1131 * Do not sync:
1132 * - In Insert mode, unless cursor key has been used.
1133 * - While reading a script file.
1134 * - When no_u_sync is non-zero.
1135 */
1136void may_sync_undo(void)
1137{
1138 if ((!(State & (INSERT + CMDLINE)) || arrow_used)
1139 && scriptin[curscript] == NULL)
1140 u_sync(FALSE);
1141}
1142
1143/*
1144 * Make "typebuf" empty and allocate new buffers.
1145 */
1146void alloc_typebuf(void)
1147{
1148 typebuf.tb_buf = xmalloc(TYPELEN_INIT);
1149 typebuf.tb_noremap = xmalloc(TYPELEN_INIT);
1150 typebuf.tb_buflen = TYPELEN_INIT;
1151 typebuf.tb_off = MAXMAPLEN + 4; // can insert without realloc
1152 typebuf.tb_len = 0;
1153 typebuf.tb_maplen = 0;
1154 typebuf.tb_silent = 0;
1155 typebuf.tb_no_abbr_cnt = 0;
1156 if (++typebuf.tb_change_cnt == 0)
1157 typebuf.tb_change_cnt = 1;
1158}
1159
1160/*
1161 * Free the buffers of "typebuf".
1162 */
1163void free_typebuf(void)
1164{
1165 if (typebuf.tb_buf == typebuf_init) {
1166 internal_error("Free typebuf 1");
1167 } else {
1168 xfree(typebuf.tb_buf);
1169 }
1170 if (typebuf.tb_noremap == noremapbuf_init) {
1171 internal_error("Free typebuf 2");
1172 } else {
1173 xfree(typebuf.tb_noremap);
1174 }
1175}
1176
1177/*
1178 * When doing ":so! file", the current typeahead needs to be saved, and
1179 * restored when "file" has been read completely.
1180 */
1181static typebuf_T saved_typebuf[NSCRIPT];
1182
1183void save_typebuf(void)
1184{
1185 init_typebuf();
1186 saved_typebuf[curscript] = typebuf;
1187 alloc_typebuf();
1188}
1189
1190static int old_char = -1; // character put back by vungetc()
1191static int old_mod_mask; // mod_mask for ungotten character
1192static int old_mouse_grid; // mouse_grid related to old_char
1193static int old_mouse_row; // mouse_row related to old_char
1194static int old_mouse_col; // mouse_col related to old_char
1195
1196
1197/*
1198 * Save all three kinds of typeahead, so that the user must type at a prompt.
1199 */
1200void save_typeahead(tasave_T *tp)
1201{
1202 tp->save_typebuf = typebuf;
1203 alloc_typebuf();
1204 tp->typebuf_valid = TRUE;
1205 tp->old_char = old_char;
1206 tp->old_mod_mask = old_mod_mask;
1207 old_char = -1;
1208
1209 tp->save_readbuf1 = readbuf1;
1210 readbuf1.bh_first.b_next = NULL;
1211 tp->save_readbuf2 = readbuf2;
1212 readbuf2.bh_first.b_next = NULL;
1213}
1214
1215/*
1216 * Restore the typeahead to what it was before calling save_typeahead().
1217 * The allocated memory is freed, can only be called once!
1218 */
1219void restore_typeahead(tasave_T *tp)
1220{
1221 if (tp->typebuf_valid) {
1222 free_typebuf();
1223 typebuf = tp->save_typebuf;
1224 }
1225
1226 old_char = tp->old_char;
1227 old_mod_mask = tp->old_mod_mask;
1228
1229 free_buff(&readbuf1);
1230 readbuf1 = tp->save_readbuf1;
1231 free_buff(&readbuf2);
1232 readbuf2 = tp->save_readbuf2;
1233}
1234
1235/*
1236 * Open a new script file for the ":source!" command.
1237 */
1238void
1239openscript (
1240 char_u *name,
1241 int directly /* when TRUE execute directly */
1242)
1243{
1244 if (curscript + 1 == NSCRIPT) {
1245 EMSG(_(e_nesting));
1246 return;
1247 }
1248
1249 // Disallow sourcing a file in the sandbox, the commands would be executed
1250 // later, possibly outside of the sandbox.
1251 if (check_secure()) {
1252 return;
1253 }
1254
1255 if (ignore_script) {
1256 // Not reading from script, also don't open one. Warning message?
1257 return;
1258 }
1259
1260 if (scriptin[curscript] != NULL) /* already reading script */
1261 ++curscript;
1262 /* use NameBuff for expanded name */
1263 expand_env(name, NameBuff, MAXPATHL);
1264 int error;
1265 if ((scriptin[curscript] = file_open_new(&error, (char *)NameBuff,
1266 kFileReadOnly, 0)) == NULL) {
1267 emsgf(_(e_notopen_2), name, os_strerror(error));
1268 if (curscript) {
1269 curscript--;
1270 }
1271 return;
1272 }
1273 save_typebuf();
1274
1275 /*
1276 * Execute the commands from the file right now when using ":source!"
1277 * after ":global" or ":argdo" or in a loop. Also when another command
1278 * follows. This means the display won't be updated. Don't do this
1279 * always, "make test" would fail.
1280 */
1281 if (directly) {
1282 oparg_T oa;
1283 int oldcurscript;
1284 int save_State = State;
1285 int save_restart_edit = restart_edit;
1286 int save_insertmode = p_im;
1287 int save_finish_op = finish_op;
1288 int save_msg_scroll = msg_scroll;
1289
1290 State = NORMAL;
1291 msg_scroll = FALSE; /* no msg scrolling in Normal mode */
1292 restart_edit = 0; /* don't go to Insert mode */
1293 p_im = FALSE; /* don't use 'insertmode' */
1294 clear_oparg(&oa);
1295 finish_op = FALSE;
1296
1297 oldcurscript = curscript;
1298 do {
1299 update_topline_cursor(); // update cursor position and topline
1300 normal_cmd(&oa, false); // execute one command
1301 vpeekc(); // check for end of file
1302 } while (scriptin[oldcurscript] != NULL);
1303
1304 State = save_State;
1305 msg_scroll = save_msg_scroll;
1306 restart_edit = save_restart_edit;
1307 p_im = save_insertmode;
1308 finish_op = save_finish_op;
1309 }
1310}
1311
1312/*
1313 * Close the currently active input script.
1314 */
1315static void closescript(void)
1316{
1317 free_typebuf();
1318 typebuf = saved_typebuf[curscript];
1319
1320 file_free(scriptin[curscript], false);
1321 scriptin[curscript] = NULL;
1322 if (curscript > 0)
1323 --curscript;
1324}
1325
1326#if defined(EXITFREE)
1327void close_all_scripts(void)
1328{
1329 while (scriptin[0] != NULL)
1330 closescript();
1331}
1332
1333#endif
1334
1335/*
1336 * Return TRUE when reading keys from a script file.
1337 */
1338int using_script(void)
1339{
1340 return scriptin[curscript] != NULL;
1341}
1342
1343/// This function is called just before doing a blocking wait. Thus after
1344/// waiting 'updatetime' for a character to arrive.
1345void before_blocking(void)
1346{
1347 updatescript(0);
1348 if (may_garbage_collect) {
1349 garbage_collect(false);
1350 }
1351}
1352
1353/// updatescript() is called when a character can be written to the script file
1354/// or when we have waited some time for a character (c == 0).
1355///
1356/// All the changed memfiles are synced if c == 0 or when the number of typed
1357/// characters reaches 'updatecount' and 'updatecount' is non-zero.
1358static void updatescript(int c)
1359{
1360 static int count = 0;
1361
1362 if (c && scriptout) {
1363 putc(c, scriptout);
1364 }
1365 bool idle = (c == 0);
1366 if (idle || (p_uc > 0 && ++count >= p_uc)) {
1367 ml_sync_all(idle, true,
1368 (!!p_fs || idle)); // Always fsync at idle (CursorHold).
1369 count = 0;
1370 }
1371}
1372
1373/*
1374 * Get the next input character.
1375 * Can return a special key or a multi-byte character.
1376 * Can return NUL when called recursively, use safe_vgetc() if that's not
1377 * wanted.
1378 * This translates escaped K_SPECIAL and CSI bytes to a K_SPECIAL or CSI byte.
1379 * Collects the bytes of a multibyte character into the whole character.
1380 * Returns the modifiers in the global "mod_mask".
1381 */
1382int vgetc(void)
1383{
1384 int c, c2;
1385 int n;
1386 char_u buf[MB_MAXBYTES + 1];
1387 int i;
1388
1389 // Do garbage collection when garbagecollect() was called previously and
1390 // we are now at the toplevel.
1391 if (may_garbage_collect && want_garbage_collect) {
1392 garbage_collect(false);
1393 }
1394
1395 /*
1396 * If a character was put back with vungetc, it was already processed.
1397 * Return it directly.
1398 */
1399 if (old_char != -1) {
1400 c = old_char;
1401 old_char = -1;
1402 mod_mask = old_mod_mask;
1403 mouse_grid = old_mouse_grid;
1404 mouse_row = old_mouse_row;
1405 mouse_col = old_mouse_col;
1406 } else {
1407 mod_mask = 0x0;
1408 last_recorded_len = 0;
1409 for (;; ) { // this is done twice if there are modifiers
1410 bool did_inc = false;
1411 if (mod_mask) { // no mapping after modifier has been read
1412 no_mapping++;
1413 did_inc = true; // mod_mask may change value
1414 }
1415 c = vgetorpeek(true);
1416 if (did_inc) {
1417 no_mapping--;
1418 }
1419
1420 // Get two extra bytes for special keys
1421 if (c == K_SPECIAL) {
1422 no_mapping++;
1423 c2 = vgetorpeek(true); // no mapping for these chars
1424 c = vgetorpeek(true);
1425 no_mapping--;
1426 if (c2 == KS_MODIFIER) {
1427 mod_mask = c;
1428 continue;
1429 }
1430 c = TO_SPECIAL(c2, c);
1431
1432 }
1433
1434 // a keypad or special function key was not mapped, use it like
1435 // its ASCII equivalent
1436 switch (c) {
1437 case K_KPLUS: c = '+'; break;
1438 case K_KMINUS: c = '-'; break;
1439 case K_KDIVIDE: c = '/'; break;
1440 case K_KMULTIPLY: c = '*'; break;
1441 case K_KENTER: c = CAR; break;
1442 case K_KPOINT: c = '.'; break;
1443 case K_KCOMMA: c = ','; break;
1444 case K_KEQUAL: c = '='; break;
1445 case K_K0: c = '0'; break;
1446 case K_K1: c = '1'; break;
1447 case K_K2: c = '2'; break;
1448 case K_K3: c = '3'; break;
1449 case K_K4: c = '4'; break;
1450 case K_K5: c = '5'; break;
1451 case K_K6: c = '6'; break;
1452 case K_K7: c = '7'; break;
1453 case K_K8: c = '8'; break;
1454 case K_K9: c = '9'; break;
1455
1456 case K_XHOME:
1457 case K_ZHOME:
1458 if (mod_mask == MOD_MASK_SHIFT) {
1459 c = K_S_HOME;
1460 mod_mask = 0;
1461 } else if (mod_mask == MOD_MASK_CTRL) {
1462 c = K_C_HOME;
1463 mod_mask = 0;
1464 } else {
1465 c = K_HOME;
1466 }
1467 break;
1468 case K_XEND:
1469 case K_ZEND:
1470 if (mod_mask == MOD_MASK_SHIFT) {
1471 c = K_S_END;
1472 mod_mask = 0;
1473 } else if (mod_mask == MOD_MASK_CTRL) {
1474 c = K_C_END;
1475 mod_mask = 0;
1476 } else {
1477 c = K_END;
1478 }
1479 break;
1480
1481 case K_XUP: c = K_UP; break;
1482 case K_XDOWN: c = K_DOWN; break;
1483 case K_XLEFT: c = K_LEFT; break;
1484 case K_XRIGHT: c = K_RIGHT; break;
1485 }
1486
1487 // For a multi-byte character get all the bytes and return the
1488 // converted character.
1489 // Note: This will loop until enough bytes are received!
1490 if ((n = MB_BYTE2LEN_CHECK(c)) > 1) {
1491 no_mapping++;
1492 buf[0] = (char_u)c;
1493 for (i = 1; i < n; i++) {
1494 buf[i] = (char_u)vgetorpeek(true);
1495 if (buf[i] == K_SPECIAL
1496 ) {
1497 // Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence,
1498 // which represents a K_SPECIAL (0x80),
1499 // or a CSI - KS_EXTRA - KE_CSI sequence, which represents
1500 // a CSI (0x9B),
1501 // of a K_SPECIAL - KS_EXTRA - KE_CSI, which is CSI too.
1502 c = vgetorpeek(true);
1503 if (vgetorpeek(true) == (int)KE_CSI && c == KS_EXTRA) {
1504 buf[i] = CSI;
1505 }
1506 }
1507 }
1508 no_mapping--;
1509 c = utf_ptr2char(buf);
1510 }
1511
1512 break;
1513 }
1514 }
1515
1516 /*
1517 * In the main loop "may_garbage_collect" can be set to do garbage
1518 * collection in the first next vgetc(). It's disabled after that to
1519 * avoid internally used Lists and Dicts to be freed.
1520 */
1521 may_garbage_collect = FALSE;
1522
1523 return c;
1524}
1525
1526/*
1527 * Like vgetc(), but never return a NUL when called recursively, get a key
1528 * directly from the user (ignoring typeahead).
1529 */
1530int safe_vgetc(void)
1531{
1532 int c;
1533
1534 c = vgetc();
1535 if (c == NUL) {
1536 c = get_keystroke(NULL);
1537 }
1538 return c;
1539}
1540
1541/*
1542 * Like safe_vgetc(), but loop to handle K_IGNORE.
1543 * Also ignore scrollbar events.
1544 */
1545int plain_vgetc(void)
1546{
1547 int c;
1548
1549 do {
1550 c = safe_vgetc();
1551 } while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR);
1552 return c;
1553}
1554
1555/*
1556 * Check if a character is available, such that vgetc() will not block.
1557 * If the next character is a special character or multi-byte, the returned
1558 * character is not valid!.
1559 * Returns NUL if no character is available.
1560 */
1561int vpeekc(void)
1562{
1563 if (old_char != -1)
1564 return old_char;
1565 return vgetorpeek(FALSE);
1566}
1567
1568/*
1569 * Check if any character is available, also half an escape sequence.
1570 * Trick: when no typeahead found, but there is something in the typeahead
1571 * buffer, it must be an ESC that is recognized as the start of a key code.
1572 */
1573int vpeekc_any(void)
1574{
1575 int c;
1576
1577 c = vpeekc();
1578 if (c == NUL && typebuf.tb_len > 0)
1579 c = ESC;
1580 return c;
1581}
1582
1583/*
1584 * Call vpeekc() without causing anything to be mapped.
1585 * Return TRUE if a character is available, FALSE otherwise.
1586 */
1587int char_avail(void)
1588{
1589 int retval;
1590
1591 no_mapping++;
1592 retval = vpeekc();
1593 no_mapping--;
1594 return retval != NUL;
1595}
1596
1597void
1598vungetc ( /* unget one character (can only be done once!) */
1599 int c
1600)
1601{
1602 old_char = c;
1603 old_mod_mask = mod_mask;
1604 old_mouse_grid = mouse_grid;
1605 old_mouse_row = mouse_row;
1606 old_mouse_col = mouse_col;
1607}
1608
1609/// Gets a character:
1610/// 1. from the stuffbuffer
1611/// This is used for abbreviated commands like "D" -> "d$".
1612/// Also used to redo a command for ".".
1613/// 2. from the typeahead buffer
1614/// Stores text obtained previously but not used yet.
1615/// Also stores the result of mappings.
1616/// Also used for the ":normal" command.
1617/// 3. from the user
1618/// This may do a blocking wait if "advance" is TRUE.
1619///
1620/// if "advance" is TRUE (vgetc()):
1621/// Really get the character.
1622/// KeyTyped is set to TRUE in the case the user typed the key.
1623/// KeyStuffed is TRUE if the character comes from the stuff buffer.
1624/// if "advance" is FALSE (vpeekc()):
1625/// Just look whether there is a character available.
1626/// Return NUL if not.
1627///
1628/// When `no_mapping` (global) is zero, checks for mappings in the current mode.
1629/// Only returns one byte (of a multi-byte character).
1630/// K_SPECIAL and CSI may be escaped, need to get two more bytes then.
1631static int vgetorpeek(int advance)
1632{
1633 int c, c1;
1634 int keylen;
1635 char_u *s;
1636 mapblock_T *mp;
1637 mapblock_T *mp2;
1638 mapblock_T *mp_match;
1639 int mp_match_len = 0;
1640 int timedout = FALSE; /* waited for more than 1 second
1641 for mapping to complete */
1642 int mapdepth = 0; /* check for recursive mapping */
1643 int mode_deleted = FALSE; /* set when mode has been deleted */
1644 int local_State;
1645 int mlen;
1646 int max_mlen;
1647 int i;
1648 int new_wcol, new_wrow;
1649 int n;
1650 int nolmaplen;
1651 int old_wcol, old_wrow;
1652 int wait_tb_len;
1653
1654 /*
1655 * This function doesn't work very well when called recursively. This may
1656 * happen though, because of:
1657 * 1. The call to add_to_showcmd(). char_avail() is then used to check if
1658 * there is a character available, which calls this function. In that
1659 * case we must return NUL, to indicate no character is available.
1660 * 2. A GUI callback function writes to the screen, causing a
1661 * wait_return().
1662 * Using ":normal" can also do this, but it saves the typeahead buffer,
1663 * thus it should be OK. But don't get a key from the user then.
1664 */
1665 if (vgetc_busy > 0
1666 && ex_normal_busy == 0
1667 )
1668 return NUL;
1669
1670 local_State = get_real_state();
1671
1672 ++vgetc_busy;
1673
1674 if (advance)
1675 KeyStuffed = FALSE;
1676
1677 init_typebuf();
1678 start_stuff();
1679 if (advance && typebuf.tb_maplen == 0) {
1680 reg_executing = 0;
1681 }
1682 do {
1683 /*
1684 * get a character: 1. from the stuffbuffer
1685 */
1686 if (typeahead_char != 0) {
1687 c = typeahead_char;
1688 if (advance)
1689 typeahead_char = 0;
1690 } else {
1691 c = read_readbuffers(advance);
1692 }
1693 if (c != NUL && !got_int) {
1694 if (advance) {
1695 // KeyTyped = false; When the command that stuffed something
1696 // was typed, behave like the stuffed command was typed.
1697 // needed for CTRL-W CTRL-] to open a fold, for example.
1698 KeyStuffed = true;
1699 }
1700 if (typebuf.tb_no_abbr_cnt == 0)
1701 typebuf.tb_no_abbr_cnt = 1; /* no abbreviations now */
1702 } else {
1703 /*
1704 * Loop until we either find a matching mapped key, or we
1705 * are sure that it is not a mapped key.
1706 * If a mapped key sequence is found we go back to the start to
1707 * try re-mapping.
1708 */
1709 for (;; ) {
1710 /*
1711 * os_breakcheck() is slow, don't use it too often when
1712 * inside a mapping. But call it each time for typed
1713 * characters.
1714 */
1715 if (typebuf.tb_maplen)
1716 line_breakcheck();
1717 else
1718 os_breakcheck(); /* check for CTRL-C */
1719 keylen = 0;
1720 if (got_int) {
1721 // flush all input
1722 c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L);
1723 // If inchar() returns TRUE (script file was active) or we
1724 // are inside a mapping, get out of insert mode.
1725 // Otherwise we behave like having gotten a CTRL-C.
1726 // As a result typing CTRL-C in insert mode will
1727 // really insert a CTRL-C.
1728 if ((c || typebuf.tb_maplen)
1729 && (State & (INSERT + CMDLINE))) {
1730 c = ESC;
1731 } else {
1732 c = Ctrl_C;
1733 }
1734 flush_buffers(FLUSH_INPUT); // flush all typeahead
1735
1736 if (advance) {
1737 /* Also record this character, it might be needed to
1738 * get out of Insert mode. */
1739 *typebuf.tb_buf = (char_u)c;
1740 gotchars(typebuf.tb_buf, 1);
1741 }
1742 cmd_silent = false;
1743
1744 break;
1745 } else if (typebuf.tb_len > 0) {
1746 /*
1747 * Check for a mappable key sequence.
1748 * Walk through one maphash[] list until we find an
1749 * entry that matches.
1750 *
1751 * Don't look for mappings if:
1752 * - no_mapping set: mapping disabled (e.g. for CTRL-V)
1753 * - maphash_valid not set: no mappings present.
1754 * - typebuf.tb_buf[typebuf.tb_off] should not be remapped
1755 * - in insert or cmdline mode and 'paste' option set
1756 * - waiting for "hit return to continue" and CR or SPACE
1757 * typed
1758 * - waiting for a char with --more--
1759 * - in Ctrl-X mode, and we get a valid char for that mode
1760 */
1761 mp = NULL;
1762 max_mlen = 0;
1763 c1 = typebuf.tb_buf[typebuf.tb_off];
1764 if (no_mapping == 0 && maphash_valid
1765 && (no_zero_mapping == 0 || c1 != '0')
1766 && (typebuf.tb_maplen == 0
1767 || (p_remap
1768 && (typebuf.tb_noremap[typebuf.tb_off]
1769 & (RM_NONE|RM_ABBR)) == 0))
1770 && !(p_paste && (State & (INSERT + CMDLINE)))
1771 && !(State == HITRETURN && (c1 == CAR || c1 == ' '))
1772 && State != ASKMORE
1773 && State != CONFIRM
1774 && !((ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c1))
1775 || ((compl_cont_status & CONT_LOCAL)
1776 && (c1 == Ctrl_N || c1 == Ctrl_P)))
1777 ) {
1778 if (c1 == K_SPECIAL) {
1779 nolmaplen = 2;
1780 } else {
1781 LANGMAP_ADJUST(c1, (State & (CMDLINE | INSERT)) == 0
1782 && get_real_state() != SELECTMODE);
1783 nolmaplen = 0;
1784 }
1785 /* First try buffer-local mappings. */
1786 mp = curbuf->b_maphash[MAP_HASH(local_State, c1)];
1787 mp2 = maphash[MAP_HASH(local_State, c1)];
1788 if (mp == NULL) {
1789 /* There are no buffer-local mappings. */
1790 mp = mp2;
1791 mp2 = NULL;
1792 }
1793 /*
1794 * Loop until a partly matching mapping is found or
1795 * all (local) mappings have been checked.
1796 * The longest full match is remembered in "mp_match".
1797 * A full match is only accepted if there is no partly
1798 * match, so "aa" and "aaa" can both be mapped.
1799 */
1800 mp_match = NULL;
1801 mp_match_len = 0;
1802 for (; mp != NULL;
1803 mp->m_next == NULL ? (mp = mp2, mp2 = NULL) :
1804 (mp = mp->m_next)) {
1805 /*
1806 * Only consider an entry if the first character
1807 * matches and it is for the current state.
1808 * Skip ":lmap" mappings if keys were mapped.
1809 */
1810 if (mp->m_keys[0] == c1
1811 && (mp->m_mode & local_State)
1812 && ((mp->m_mode & LANGMAP) == 0
1813 || typebuf.tb_maplen == 0)) {
1814 int nomap = nolmaplen;
1815 int c2;
1816 /* find the match length of this mapping */
1817 for (mlen = 1; mlen < typebuf.tb_len; ++mlen) {
1818 c2 = typebuf.tb_buf[typebuf.tb_off + mlen];
1819 if (nomap > 0)
1820 --nomap;
1821 else if (c2 == K_SPECIAL)
1822 nomap = 2;
1823 else
1824 LANGMAP_ADJUST(c2, TRUE);
1825 if (mp->m_keys[mlen] != c2)
1826 break;
1827 }
1828
1829 /* Don't allow mapping the first byte(s) of a
1830 * multi-byte char. Happens when mapping
1831 * <M-a> and then changing 'encoding'. Beware
1832 * that 0x80 is escaped. */
1833 char_u *p1 = mp->m_keys;
1834 char_u *p2 = (char_u *)mb_unescape((const char **)&p1);
1835
1836 if (has_mbyte && p2 != NULL && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2))
1837 mlen = 0;
1838 /*
1839 * Check an entry whether it matches.
1840 * - Full match: mlen == keylen
1841 * - Partly match: mlen == typebuf.tb_len
1842 */
1843 keylen = mp->m_keylen;
1844 if (mlen == keylen
1845 || (mlen == typebuf.tb_len
1846 && typebuf.tb_len < keylen)) {
1847 /*
1848 * If only script-local mappings are
1849 * allowed, check if the mapping starts
1850 * with K_SNR.
1851 */
1852 s = typebuf.tb_noremap + typebuf.tb_off;
1853 if (*s == RM_SCRIPT
1854 && (mp->m_keys[0] != K_SPECIAL
1855 || mp->m_keys[1] != KS_EXTRA
1856 || mp->m_keys[2]
1857 != (int)KE_SNR))
1858 continue;
1859 /*
1860 * If one of the typed keys cannot be
1861 * remapped, skip the entry.
1862 */
1863 for (n = mlen; --n >= 0; )
1864 if (*s++ & (RM_NONE|RM_ABBR))
1865 break;
1866 if (n >= 0)
1867 continue;
1868
1869 if (keylen > typebuf.tb_len) {
1870 if (!timedout && !(mp_match != NULL
1871 && mp_match->m_nowait)) {
1872 /* break at a partly match */
1873 keylen = KEYLEN_PART_MAP;
1874 break;
1875 }
1876 } else if (keylen > mp_match_len
1877 || (keylen == mp_match_len
1878 && mp_match != NULL
1879 && (mp_match->m_mode & LANGMAP) == 0
1880 && (mp->m_mode & LANGMAP) != 0)) {
1881 // found a longer match
1882 mp_match = mp;
1883 mp_match_len = keylen;
1884 }
1885 } else {
1886 // No match; may have to check for termcode at next character.
1887 if (max_mlen < mlen) {
1888 max_mlen = mlen;
1889 }
1890 }
1891 }
1892 }
1893
1894 /* If no partly match found, use the longest full
1895 * match. */
1896 if (keylen != KEYLEN_PART_MAP) {
1897 mp = mp_match;
1898 keylen = mp_match_len;
1899 }
1900 }
1901
1902 if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL))) {
1903 bool match = typebuf_match_len(p_pt, &mlen);
1904 if (match) {
1905 // write chars to script file(s)
1906 if (mlen > typebuf.tb_maplen) {
1907 gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
1908 (size_t)(mlen - typebuf.tb_maplen));
1909 }
1910
1911 del_typebuf(mlen, 0); // Remove the chars.
1912 set_option_value("paste", !p_paste, NULL, 0);
1913 if (!(State & INSERT)) {
1914 msg_col = 0;
1915 msg_row = Rows - 1;
1916 msg_clr_eos(); // clear ruler
1917 }
1918 status_redraw_all();
1919 redraw_statuslines();
1920 showmode();
1921 setcursor();
1922 continue;
1923 }
1924 /* Need more chars for partly match. */
1925 if (mlen == typebuf.tb_len)
1926 keylen = KEYLEN_PART_KEY;
1927 else if (max_mlen < mlen)
1928 /* no match, may have to check for termcode at
1929 * next character */
1930 max_mlen = mlen + 1;
1931 }
1932
1933 if ((mp == NULL || max_mlen >= mp_match_len)
1934 && keylen != KEYLEN_PART_MAP) {
1935 // No matching mapping found or found a non-matching mapping that
1936 // matches at least what the matching mapping matched
1937 keylen = 0;
1938 (void)keylen; // suppress clang/dead assignment
1939 // If there was no mapping, use the character from the typeahead
1940 // buffer right here. Otherwise, use the mapping (loop around).
1941 if (mp == NULL) {
1942 // get a character: 2. from the typeahead buffer
1943 c = typebuf.tb_buf[typebuf.tb_off] & 255;
1944 if (advance) { // remove chars from tb_buf
1945 cmd_silent = (typebuf.tb_silent > 0);
1946 if (typebuf.tb_maplen > 0) {
1947 KeyTyped = false;
1948 } else {
1949 KeyTyped = true;
1950 // write char to script file(s)
1951 gotchars(typebuf.tb_buf + typebuf.tb_off, 1);
1952 }
1953 KeyNoremap = typebuf.tb_noremap[typebuf.tb_off];
1954 del_typebuf(1, 0);
1955 }
1956 break; // got character, break for loop
1957 } else {
1958 keylen = mp_match_len;
1959 }
1960 }
1961
1962 /* complete match */
1963 if (keylen >= 0 && keylen <= typebuf.tb_len) {
1964 int save_m_expr;
1965 int save_m_noremap;
1966 int save_m_silent;
1967 char_u *save_m_keys;
1968 char_u *save_m_str;
1969
1970 // Write chars to script file(s)
1971 // Note: :lmap mappings are written *after* being applied. #5658
1972 if (keylen > typebuf.tb_maplen && (mp->m_mode & LANGMAP) == 0) {
1973 gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen,
1974 (size_t)(keylen - typebuf.tb_maplen));
1975 }
1976
1977 cmd_silent = (typebuf.tb_silent > 0);
1978 del_typebuf(keylen, 0); /* remove the mapped keys */
1979
1980 /*
1981 * Put the replacement string in front of mapstr.
1982 * The depth check catches ":map x y" and ":map y x".
1983 */
1984 if (++mapdepth >= p_mmd) {
1985 EMSG(_("E223: recursive mapping"));
1986 if (State & CMDLINE)
1987 redrawcmdline();
1988 else
1989 setcursor();
1990 flush_buffers(FLUSH_MINIMAL);
1991 mapdepth = 0; // for next one
1992 c = -1;
1993 break;
1994 }
1995
1996 /*
1997 * In Select mode and a Visual mode mapping is used:
1998 * Switch to Visual mode temporarily. Append K_SELECT
1999 * to switch back to Select mode.
2000 */
2001 if (VIsual_active && VIsual_select
2002 && (mp->m_mode & VISUAL)) {
2003 VIsual_select = FALSE;
2004 (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE,
2005 0, TRUE, FALSE);
2006 }
2007
2008 /* Copy the values from *mp that are used, because
2009 * evaluating the expression may invoke a function
2010 * that redefines the mapping, thereby making *mp
2011 * invalid. */
2012 save_m_expr = mp->m_expr;
2013 save_m_noremap = mp->m_noremap;
2014 save_m_silent = mp->m_silent;
2015 save_m_keys = NULL; /* only saved when needed */
2016 save_m_str = NULL; /* only saved when needed */
2017
2018 /*
2019 * Handle ":map <expr>": evaluate the {rhs} as an
2020 * expression. Also save and restore the command line
2021 * for "normal :".
2022 */
2023 if (mp->m_expr) {
2024 int save_vgetc_busy = vgetc_busy;
2025
2026 vgetc_busy = 0;
2027 save_m_keys = vim_strsave(mp->m_keys);
2028 save_m_str = vim_strsave(mp->m_str);
2029 s = eval_map_expr(save_m_str, NUL);
2030 vgetc_busy = save_vgetc_busy;
2031 } else
2032 s = mp->m_str;
2033
2034 /*
2035 * Insert the 'to' part in the typebuf.tb_buf.
2036 * If 'from' field is the same as the start of the
2037 * 'to' field, don't remap the first character (but do
2038 * allow abbreviations).
2039 * If m_noremap is set, don't remap the whole 'to'
2040 * part.
2041 */
2042 if (s == NULL)
2043 i = FAIL;
2044 else {
2045 int noremap;
2046
2047 // If this is a LANGMAP mapping, then we didn't record the keys
2048 // at the start of the function and have to record them now.
2049 if (keylen > typebuf.tb_maplen && (mp->m_mode & LANGMAP) != 0) {
2050 gotchars(s, STRLEN(s));
2051 }
2052
2053 if (save_m_noremap != REMAP_YES)
2054 noremap = save_m_noremap;
2055 else if (
2056 STRNCMP(s, save_m_keys != NULL
2057 ? save_m_keys : mp->m_keys,
2058 (size_t)keylen)
2059 != 0)
2060 noremap = REMAP_YES;
2061 else
2062 noremap = REMAP_SKIP;
2063 i = ins_typebuf(s, noremap,
2064 0, TRUE, cmd_silent || save_m_silent);
2065 if (save_m_expr)
2066 xfree(s);
2067 }
2068 xfree(save_m_keys);
2069 xfree(save_m_str);
2070 if (i == FAIL) {
2071 c = -1;
2072 break;
2073 }
2074 continue;
2075 }
2076 }
2077
2078 /*
2079 * get a character: 3. from the user - handle <Esc> in Insert mode
2080 */
2081 /*
2082 * special case: if we get an <ESC> in insert mode and there
2083 * are no more characters at once, we pretend to go out of
2084 * insert mode. This prevents the one second delay after
2085 * typing an <ESC>. If we get something after all, we may
2086 * have to redisplay the mode. That the cursor is in the wrong
2087 * place does not matter.
2088 */
2089 c = 0;
2090 new_wcol = curwin->w_wcol;
2091 new_wrow = curwin->w_wrow;
2092 if (advance
2093 && typebuf.tb_len == 1
2094 && typebuf.tb_buf[typebuf.tb_off] == ESC
2095 && !no_mapping
2096 && ex_normal_busy == 0
2097 && typebuf.tb_maplen == 0
2098 && (State & INSERT)
2099 && (p_timeout
2100 || (keylen == KEYLEN_PART_KEY && p_ttimeout))
2101 && (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len,
2102 3, 25L)) == 0) {
2103 colnr_T col = 0, vcol;
2104 char_u *ptr;
2105
2106 if (mode_displayed) {
2107 unshowmode(TRUE);
2108 mode_deleted = TRUE;
2109 }
2110 validate_cursor();
2111 old_wcol = curwin->w_wcol;
2112 old_wrow = curwin->w_wrow;
2113
2114 /* move cursor left, if possible */
2115 if (curwin->w_cursor.col != 0) {
2116 if (curwin->w_wcol > 0) {
2117 if (did_ai) {
2118 /*
2119 * We are expecting to truncate the trailing
2120 * white-space, so find the last non-white
2121 * character -- webb
2122 */
2123 col = vcol = curwin->w_wcol = 0;
2124 ptr = get_cursor_line_ptr();
2125 while (col < curwin->w_cursor.col) {
2126 if (!ascii_iswhite(ptr[col]))
2127 curwin->w_wcol = vcol;
2128 vcol += lbr_chartabsize(ptr, ptr + col,
2129 (colnr_T)vcol);
2130 if (has_mbyte)
2131 col += (*mb_ptr2len)(ptr + col);
2132 else
2133 ++col;
2134 }
2135 curwin->w_wrow = curwin->w_cline_row
2136 + curwin->w_wcol / curwin->w_width_inner;
2137 curwin->w_wcol %= curwin->w_width_inner;
2138 curwin->w_wcol += curwin_col_off();
2139 col = 0; /* no correction needed */
2140 } else {
2141 --curwin->w_wcol;
2142 col = curwin->w_cursor.col - 1;
2143 }
2144 } else if (curwin->w_p_wrap && curwin->w_wrow) {
2145 curwin->w_wrow--;
2146 curwin->w_wcol = curwin->w_width_inner - 1;
2147 col = curwin->w_cursor.col - 1;
2148 }
2149 if (col > 0 && curwin->w_wcol > 0) {
2150 // Correct when the cursor is on the right halve
2151 // of a double-wide character.
2152 ptr = get_cursor_line_ptr();
2153 col -= utf_head_off(ptr, ptr + col);
2154 if (utf_ptr2cells(ptr + col) > 1) {
2155 curwin->w_wcol--;
2156 }
2157 }
2158 }
2159 setcursor();
2160 ui_flush();
2161 new_wcol = curwin->w_wcol;
2162 new_wrow = curwin->w_wrow;
2163 curwin->w_wcol = old_wcol;
2164 curwin->w_wrow = old_wrow;
2165 }
2166 if (c < 0)
2167 continue; /* end of input script reached */
2168
2169 // Allow mapping for just typed characters. When we get here c
2170 // is the number of extra bytes and typebuf.tb_len is 1.
2171 for (n = 1; n <= c; n++) {
2172 typebuf.tb_noremap[typebuf.tb_off + n] = RM_YES;
2173 }
2174 typebuf.tb_len += c;
2175
2176 /* buffer full, don't map */
2177 if (typebuf.tb_len >= typebuf.tb_maplen + MAXMAPLEN) {
2178 timedout = TRUE;
2179 continue;
2180 }
2181
2182 if (ex_normal_busy > 0) {
2183 static int tc = 0;
2184
2185 /* No typeahead left and inside ":normal". Must return
2186 * something to avoid getting stuck. When an incomplete
2187 * mapping is present, behave like it timed out. */
2188 if (typebuf.tb_len > 0) {
2189 timedout = TRUE;
2190 continue;
2191 }
2192 /* When 'insertmode' is set, ESC just beeps in Insert
2193 * mode. Use CTRL-L to make edit() return.
2194 * For the command line only CTRL-C always breaks it.
2195 * For the cmdline window: Alternate between ESC and
2196 * CTRL-C: ESC for most situations and CTRL-C to close the
2197 * cmdline window. */
2198 if (p_im && (State & INSERT))
2199 c = Ctrl_L;
2200 else if ((State & CMDLINE)
2201 || (cmdwin_type > 0 && tc == ESC)
2202 )
2203 c = Ctrl_C;
2204 else
2205 c = ESC;
2206 tc = c;
2207 break;
2208 }
2209
2210 /*
2211 * get a character: 3. from the user - update display
2212 */
2213 /* In insert mode a screen update is skipped when characters
2214 * are still available. But when those available characters
2215 * are part of a mapping, and we are going to do a blocking
2216 * wait here. Need to update the screen to display the
2217 * changed text so far. Also for when 'lazyredraw' is set and
2218 * redrawing was postponed because there was something in the
2219 * input buffer (e.g., termresponse). */
2220 if (((State & INSERT) != 0 || p_lz) && (State & CMDLINE) == 0
2221 && advance && must_redraw != 0 && !need_wait_return) {
2222 update_screen(0);
2223 setcursor(); /* put cursor back where it belongs */
2224 }
2225
2226 /*
2227 * If we have a partial match (and are going to wait for more
2228 * input from the user), show the partially matched characters
2229 * to the user with showcmd.
2230 */
2231 i = 0;
2232 c1 = 0;
2233 if (typebuf.tb_len > 0 && advance && !exmode_active) {
2234 if (((State & (NORMAL | INSERT)) || State == LANGMAP)
2235 && State != HITRETURN) {
2236 /* this looks nice when typing a dead character map */
2237 if (State & INSERT
2238 && ptr2cells(typebuf.tb_buf + typebuf.tb_off
2239 + typebuf.tb_len - 1) == 1) {
2240 edit_putchar(typebuf.tb_buf[typebuf.tb_off
2241 + typebuf.tb_len - 1], FALSE);
2242 setcursor(); /* put cursor back where it belongs */
2243 c1 = 1;
2244 }
2245 /* need to use the col and row from above here */
2246 old_wcol = curwin->w_wcol;
2247 old_wrow = curwin->w_wrow;
2248 curwin->w_wcol = new_wcol;
2249 curwin->w_wrow = new_wrow;
2250 push_showcmd();
2251 if (typebuf.tb_len > SHOWCMD_COLS)
2252 i = typebuf.tb_len - SHOWCMD_COLS;
2253 while (i < typebuf.tb_len)
2254 (void)add_to_showcmd(typebuf.tb_buf[typebuf.tb_off
2255 + i++]);
2256 curwin->w_wcol = old_wcol;
2257 curwin->w_wrow = old_wrow;
2258 }
2259
2260 // this looks nice when typing a dead character map
2261 if ((State & CMDLINE) && cmdline_star == 0) {
2262 char_u *p = typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len - 1;
2263 if (ptr2cells(p) == 1 && *p < 128) {
2264 putcmdline((char)(*p), false);
2265 c1 = 1;
2266 }
2267 }
2268 }
2269
2270 /*
2271 * get a character: 3. from the user - get it
2272 */
2273 if (typebuf.tb_len == 0) {
2274 // timedout may have been set while waiting for a mapping
2275 // that has a <Nop> RHS.
2276 timedout = false;
2277 }
2278
2279 long wait_time = 0;
2280
2281 if (advance) {
2282 if (typebuf.tb_len == 0
2283 || !(p_timeout || (p_ttimeout && keylen == KEYLEN_PART_KEY))) {
2284 // blocking wait
2285 wait_time = -1L;
2286 } else if (keylen == KEYLEN_PART_KEY && p_ttm >= 0) {
2287 wait_time = p_ttm;
2288 } else {
2289 wait_time = p_tm;
2290 }
2291 }
2292
2293 wait_tb_len = typebuf.tb_len;
2294 c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len,
2295 typebuf.tb_buflen - typebuf.tb_off - typebuf.tb_len - 1,
2296 wait_time);
2297
2298 if (i != 0)
2299 pop_showcmd();
2300 if (c1 == 1) {
2301 if (State & INSERT)
2302 edit_unputchar();
2303 if (State & CMDLINE)
2304 unputcmdline();
2305 else
2306 setcursor(); /* put cursor back where it belongs */
2307 }
2308
2309 if (c < 0)
2310 continue; /* end of input script reached */
2311 if (c == NUL) { /* no character available */
2312 if (!advance)
2313 break;
2314 if (wait_tb_len > 0) { /* timed out */
2315 timedout = TRUE;
2316 continue;
2317 }
2318 } else { /* allow mapping for just typed characters */
2319 while (typebuf.tb_buf[typebuf.tb_off
2320 + typebuf.tb_len] != NUL)
2321 typebuf.tb_noremap[typebuf.tb_off
2322 + typebuf.tb_len++] = RM_YES;
2323 }
2324 } /* for (;;) */
2325 } /* if (!character from stuffbuf) */
2326
2327 /* if advance is FALSE don't loop on NULs */
2328 } while (c < 0 || (advance && c == NUL));
2329
2330 /*
2331 * The "INSERT" message is taken care of here:
2332 * if we return an ESC to exit insert mode, the message is deleted
2333 * if we don't return an ESC but deleted the message before, redisplay it
2334 */
2335 if (advance && p_smd && msg_silent == 0 && (State & INSERT)) {
2336 if (c == ESC && !mode_deleted && !no_mapping && mode_displayed) {
2337 if (typebuf.tb_len && !KeyTyped)
2338 redraw_cmdline = TRUE; /* delete mode later */
2339 else
2340 unshowmode(FALSE);
2341 } else if (c != ESC && mode_deleted) {
2342 if (typebuf.tb_len && !KeyTyped)
2343 redraw_cmdline = TRUE; /* show mode later */
2344 else
2345 showmode();
2346 }
2347 }
2348
2349 if (timedout && c == ESC) {
2350 char_u nop_buf[3];
2351
2352 // When recording there will be no timeout. Add a <Nop> after the ESC
2353 // to avoid that it forms a key code with following characters.
2354 nop_buf[0] = K_SPECIAL;
2355 nop_buf[1] = KS_EXTRA;
2356 nop_buf[2] = KE_NOP;
2357 gotchars(nop_buf, 3);
2358 }
2359
2360 --vgetc_busy;
2361
2362 return c;
2363}
2364
2365/*
2366 * inchar() - get one character from
2367 * 1. a scriptfile
2368 * 2. the keyboard
2369 *
2370 * As much characters as we can get (upto 'maxlen') are put in "buf" and
2371 * NUL terminated (buffer length must be 'maxlen' + 1).
2372 * Minimum for "maxlen" is 3!!!!
2373 *
2374 * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
2375 * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
2376 * from a remote client) "buf" can no longer be used. "tb_change_cnt" is 0
2377 * otherwise.
2378 *
2379 * If we got an interrupt all input is read until none is available.
2380 *
2381 * If wait_time == 0 there is no waiting for the char.
2382 * If wait_time == n we wait for n msec for a character to arrive.
2383 * If wait_time == -1 we wait forever for a character to arrive.
2384 *
2385 * Return the number of obtained characters.
2386 * Return -1 when end of input script reached.
2387 */
2388int inchar(
2389 char_u *buf,
2390 int maxlen,
2391 long wait_time // milli seconds
2392)
2393{
2394 int len = 0; // Init for GCC.
2395 int retesc = false; // Return ESC with gotint.
2396 const int tb_change_cnt = typebuf.tb_change_cnt;
2397
2398 if (wait_time == -1L || wait_time > 100L) {
2399 // flush output before waiting
2400 ui_flush();
2401 }
2402
2403 /*
2404 * Don't reset these when at the hit-return prompt, otherwise an endless
2405 * recursive loop may result (write error in swapfile, hit-return, timeout
2406 * on char wait, flush swapfile, write error....).
2407 */
2408 if (State != HITRETURN) {
2409 did_outofmem_msg = FALSE; /* display out of memory message (again) */
2410 did_swapwrite_msg = FALSE; /* display swap file write error again */
2411 }
2412 undo_off = FALSE; /* restart undo now */
2413
2414 // Get a character from a script file if there is one.
2415 // If interrupted: Stop reading script files, close them all.
2416 ptrdiff_t read_size = -1;
2417 while (scriptin[curscript] != NULL && read_size <= 0 && !ignore_script) {
2418 char script_char;
2419 if (got_int
2420 || (read_size = file_read(scriptin[curscript], &script_char, 1)) != 1) {
2421 // Reached EOF or some error occurred.
2422 // Careful: closescript() frees typebuf.tb_buf[] and buf[] may
2423 // point inside typebuf.tb_buf[]. Don't use buf[] after this!
2424 closescript();
2425 // When reading script file is interrupted, return an ESC to get
2426 // back to normal mode.
2427 // Otherwise return -1, because typebuf.tb_buf[] has changed.
2428 if (got_int) {
2429 retesc = true;
2430 } else {
2431 return -1;
2432 }
2433 } else {
2434 buf[0] = (char_u)script_char;
2435 len = 1;
2436 }
2437 }
2438
2439 if (read_size <= 0) { // Did not get a character from script.
2440 // If we got an interrupt, skip all previously typed characters and
2441 // return TRUE if quit reading script file.
2442 // Stop reading typeahead when a single CTRL-C was read,
2443 // fill_input_buf() returns this when not able to read from stdin.
2444 // Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
2445 // and buf may be pointing inside typebuf.tb_buf[].
2446 if (got_int) {
2447#define DUM_LEN MAXMAPLEN * 3 + 3
2448 char_u dum[DUM_LEN + 1];
2449
2450 for (;; ) {
2451 len = os_inchar(dum, DUM_LEN, 0L, 0, NULL);
2452 if (len == 0 || (len == 1 && dum[0] == 3)) {
2453 break;
2454 }
2455 }
2456 return retesc;
2457 }
2458
2459 // Always flush the output characters when getting input characters
2460 // from the user.
2461 ui_flush();
2462
2463 // Fill up to a third of the buffer, because each character may be
2464 // tripled below.
2465 len = os_inchar(buf, maxlen / 3, (int)wait_time, tb_change_cnt, NULL);
2466 }
2467
2468 // If the typebuf was changed further down, it is like nothing was added by
2469 // this call.
2470 if (typebuf_changed(tb_change_cnt)) {
2471 return 0;
2472 }
2473
2474 // Note the change in the typeahead buffer, this matters for when
2475 // vgetorpeek() is called recursively, e.g. using getchar(1) in a timer
2476 // function.
2477 if (len > 0 && ++typebuf.tb_change_cnt == 0) {
2478 typebuf.tb_change_cnt = 1;
2479 }
2480
2481 return fix_input_buffer(buf, len);
2482}
2483
2484/*
2485 * Fix typed characters for use by vgetc() and check_termcode().
2486 * buf[] must have room to triple the number of bytes!
2487 * Returns the new length.
2488 */
2489int fix_input_buffer(char_u *buf, int len)
2490{
2491 if (!using_script()) {
2492 // Should not escape K_SPECIAL/CSI reading input from the user because vim
2493 // key codes keys are processed in input.c/input_enqueue.
2494 buf[len] = NUL;
2495 return len;
2496 }
2497
2498 // Reading from script, need to process special bytes
2499 int i;
2500 char_u *p = buf;
2501
2502 // Two characters are special: NUL and K_SPECIAL.
2503 // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER
2504 // Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER
2505 // Replace CSI by K_SPECIAL KS_EXTRA KE_CSI
2506 for (i = len; --i >= 0; ++p) {
2507 if (p[0] == NUL
2508 || (p[0] == K_SPECIAL
2509 && (i < 2 || p[1] != KS_EXTRA))) {
2510 memmove(p + 3, p + 1, (size_t)i);
2511 p[2] = (char_u)K_THIRD(p[0]);
2512 p[1] = (char_u)K_SECOND(p[0]);
2513 p[0] = K_SPECIAL;
2514 p += 2;
2515 len += 2;
2516 }
2517 }
2518 *p = NUL; // add trailing NUL
2519 return len;
2520}
2521
2522/// Replace termcodes in the given LHS and RHS and store the results into the
2523/// `lhs` and `rhs` of the given @ref MapArguments struct.
2524///
2525/// `rhs` and `orig_rhs` will both point to new allocated buffers. `orig_rhs`
2526/// will hold a copy of the given `orig_rhs`.
2527///
2528/// The `*_len` variables will be set appropriately. If the length of
2529/// the final `lhs` exceeds `MAXMAPLEN`, `lhs_len` will be set equal to the
2530/// original larger length and `lhs` will be truncated.
2531///
2532/// If RHS is equal to "<Nop>", `rhs` will be the empty string, `rhs_len`
2533/// will be zero, and `rhs_is_noop` will be set to true.
2534///
2535/// Any memory allocated by @ref replace_termcodes is freed before this function
2536/// returns.
2537///
2538/// @param[in] orig_lhs Original mapping LHS, with characters to replace.
2539/// @param[in] orig_lhs_len `strlen` of orig_lhs.
2540/// @param[in] orig_rhs Original mapping RHS, with characters to replace.
2541/// @param[in] orig_rhs_len `strlen` of orig_rhs.
2542/// @param[in] cpo_flags See param docs for @ref replace_termcodes.
2543/// @param[out] mapargs MapArguments struct holding the replaced strings.
2544void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len,
2545 const char_u *orig_rhs, const size_t orig_rhs_len,
2546 int cpo_flags, MapArguments *mapargs)
2547{
2548 char_u *lhs_buf = NULL;
2549 char_u *rhs_buf = NULL;
2550
2551 // If mapping has been given as ^V<C_UP> say, then replace the term codes
2552 // with the appropriate two bytes. If it is a shifted special key, unshift
2553 // it too, giving another two bytes.
2554 //
2555 // replace_termcodes() may move the result to allocated memory, which
2556 // needs to be freed later (*lhs_buf and *rhs_buf).
2557 // replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
2558 char_u *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &lhs_buf,
2559 true, true, true, cpo_flags);
2560 mapargs->lhs_len = STRLEN(replaced);
2561 xstrlcpy((char *)mapargs->lhs, (char *)replaced, sizeof(mapargs->lhs));
2562
2563 mapargs->orig_rhs_len = orig_rhs_len;
2564 mapargs->orig_rhs = xcalloc(mapargs->orig_rhs_len + 1, sizeof(char_u));
2565 xstrlcpy((char *)mapargs->orig_rhs, (char *)orig_rhs,
2566 mapargs->orig_rhs_len + 1);
2567
2568 if (STRICMP(orig_rhs, "<nop>") == 0) { // "<Nop>" means nothing
2569 mapargs->rhs = xcalloc(1, sizeof(char_u)); // single null-char
2570 mapargs->rhs_len = 0;
2571 mapargs->rhs_is_noop = true;
2572 } else {
2573 replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf,
2574 false, true, true, cpo_flags);
2575 mapargs->rhs_len = STRLEN(replaced);
2576 mapargs->rhs_is_noop = false;
2577 mapargs->rhs = xcalloc(mapargs->rhs_len + 1, sizeof(char_u));
2578 xstrlcpy((char *)mapargs->rhs, (char *)replaced, mapargs->rhs_len + 1);
2579 }
2580
2581 xfree(lhs_buf);
2582 xfree(rhs_buf);
2583}
2584
2585/// Parse a string of |:map-arguments| into a @ref MapArguments struct.
2586///
2587/// Termcodes, backslashes, CTRL-V's, etc. inside the extracted {lhs} and
2588/// {rhs} are replaced by @ref set_maparg_lhs_rhs.
2589///
2590/// rhs and orig_rhs in the returned mapargs will be set to null or a pointer
2591/// to allocated memory and should be freed even on error.
2592///
2593/// @param[in] strargs String of map args, e.g. "<buffer> <expr><silent>".
2594/// May contain leading or trailing whitespace.
2595/// @param[in] is_unmap True, if strargs should be parsed like an |:unmap|
2596/// command. |:unmap| commands interpret *all* text to the
2597/// right of the last map argument as the {lhs} of the
2598/// mapping, i.e. a literal ' ' character is treated like
2599/// a "<space>", rather than separating the {lhs} from the
2600/// {rhs}.
2601/// @param[out] mapargs MapArguments struct holding all extracted argument
2602/// values.
2603/// @return 0 on success, 1 if invalid arguments are detected.
2604int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *mapargs)
2605{
2606 const char_u *to_parse = strargs;
2607 to_parse = skipwhite(to_parse);
2608 MapArguments parsed_args; // copy these into mapargs "all at once" when done
2609 memset(&parsed_args, 0, sizeof(parsed_args));
2610
2611 // Accept <buffer>, <nowait>, <silent>, <expr>, <script>, and <unique> in
2612 // any order.
2613 while (true) {
2614 if (STRNCMP(to_parse, "<buffer>", 8) == 0) {
2615 to_parse = skipwhite(to_parse + 8);
2616 parsed_args.buffer = true;
2617 continue;
2618 }
2619
2620 if (STRNCMP(to_parse, "<nowait>", 8) == 0) {
2621 to_parse = skipwhite(to_parse + 8);
2622 parsed_args.nowait = true;
2623 continue;
2624 }
2625
2626 if (STRNCMP(to_parse, "<silent>", 8) == 0) {
2627 to_parse = skipwhite(to_parse + 8);
2628 parsed_args.silent = true;
2629 continue;
2630 }
2631
2632 // Ignore obsolete "<special>" modifier.
2633 if (STRNCMP(to_parse, "<special>", 9) == 0) {
2634 to_parse = skipwhite(to_parse + 9);
2635 continue;
2636 }
2637
2638 if (STRNCMP(to_parse, "<script>", 8) == 0) {
2639 to_parse = skipwhite(to_parse + 8);
2640 parsed_args.script = true;
2641 continue;
2642 }
2643
2644 if (STRNCMP(to_parse, "<expr>", 6) == 0) {
2645 to_parse = skipwhite(to_parse + 6);
2646 parsed_args.expr = true;
2647 continue;
2648 }
2649
2650 if (STRNCMP(to_parse, "<unique>", 8) == 0) {
2651 to_parse = skipwhite(to_parse + 8);
2652 parsed_args.unique = true;
2653 continue;
2654 }
2655 break;
2656 }
2657
2658 // Find the next whitespace character, call that the end of {lhs}.
2659 //
2660 // If a character (e.g. whitespace) is immediately preceded by a CTRL-V,
2661 // "scan past" that character, i.e. don't "terminate" LHS with that character
2662 // if it's whitespace.
2663 //
2664 // Treat backslash like CTRL-V when 'cpoptions' does not contain 'B'.
2665 //
2666 // With :unmap, literal white space is included in the {lhs}; there is no
2667 // separate {rhs}.
2668 const char_u *lhs_end = to_parse;
2669 bool do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
2670 while (*lhs_end && (is_unmap || !ascii_iswhite(*lhs_end))) {
2671 if ((lhs_end[0] == Ctrl_V || (do_backslash && lhs_end[0] == '\\'))
2672 && lhs_end[1] != NUL) {
2673 lhs_end++; // skip CTRL-V or backslash
2674 }
2675 lhs_end++;
2676 }
2677
2678 // {lhs_end} is a pointer to the "terminating whitespace" after {lhs}.
2679 // Use that to initialize {rhs_start}.
2680 const char_u *rhs_start = skipwhite(lhs_end);
2681
2682 // Given {lhs} might be larger than MAXMAPLEN before replace_termcodes
2683 // (e.g. "<Space>" is longer than ' '), so first copy into a buffer.
2684 size_t orig_lhs_len = (size_t)(lhs_end - to_parse);
2685 char_u *lhs_to_replace = xcalloc(orig_lhs_len + 1, sizeof(char_u));
2686 xstrlcpy((char *)lhs_to_replace, (char *)to_parse, orig_lhs_len + 1);
2687
2688 size_t orig_rhs_len = STRLEN(rhs_start);
2689 set_maparg_lhs_rhs(lhs_to_replace, orig_lhs_len,
2690 rhs_start, orig_rhs_len,
2691 CPO_TO_CPO_FLAGS, &parsed_args);
2692
2693 xfree(lhs_to_replace);
2694
2695 *mapargs = parsed_args;
2696
2697 if (parsed_args.lhs_len > MAXMAPLEN) {
2698 return 1;
2699 }
2700 return 0;
2701}
2702
2703/// Sets or removes a mapping or abbreviation in buffer `buf`.
2704///
2705/// @param maptype @see do_map
2706/// @param args Fully parsed and "preprocessed" arguments for the
2707/// (un)map/abbrev command. Termcodes should have already been
2708/// replaced; whitespace, `<` and `>` signs, etc. in {lhs} and
2709/// {rhs} are assumed to be literal components of the mapping.
2710/// @param mode @see do_map
2711/// @param is_abbrev @see do_map
2712/// @param buf Target Buffer
2713int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
2714 buf_T *buf)
2715{
2716 mapblock_T *mp, **mpp;
2717 char_u *p;
2718 int n;
2719 int len = 0; // init for GCC
2720 int did_it = false;
2721 int did_local = false;
2722 int round;
2723 int retval = 0;
2724 int hash;
2725 int new_hash;
2726 mapblock_T **abbr_table;
2727 mapblock_T **map_table;
2728 int noremap;
2729
2730 map_table = maphash;
2731 abbr_table = &first_abbr;
2732
2733 // For ":noremap" don't remap, otherwise do remap.
2734 if (maptype == 2) {
2735 noremap = REMAP_NONE;
2736 } else {
2737 noremap = REMAP_YES;
2738 }
2739
2740 if (args->buffer) {
2741 // If <buffer> was given, we'll be searching through the buffer's
2742 // mappings/abbreviations, not the globals.
2743 map_table = buf->b_maphash;
2744 abbr_table = &buf->b_first_abbr;
2745 }
2746 if (args->script) {
2747 noremap = REMAP_SCRIPT;
2748 }
2749
2750 validate_maphash();
2751
2752 bool has_lhs = (args->lhs[0] != NUL);
2753 bool has_rhs = (args->rhs[0] != NUL) || args->rhs_is_noop;
2754
2755 // check for :unmap without argument
2756 if (maptype == 1 && !has_lhs) {
2757 retval = 1;
2758 goto theend;
2759 }
2760
2761 char_u *lhs = (char_u *)&args->lhs;
2762 char_u *rhs = (char_u *)args->rhs;
2763 char_u *orig_rhs = args->orig_rhs;
2764
2765 // check arguments and translate function keys
2766 if (has_lhs) {
2767 len = (int)args->lhs_len;
2768 if (len > MAXMAPLEN) {
2769 retval = 1;
2770 goto theend;
2771 }
2772
2773 if (is_abbrev && maptype != 1) {
2774 //
2775 // If an abbreviation ends in a keyword character, the
2776 // rest must be all keyword-char or all non-keyword-char.
2777 // Otherwise we won't be able to find the start of it in a
2778 // vi-compatible way.
2779 //
2780 if (has_mbyte) {
2781 int first, last;
2782 int same = -1;
2783
2784 first = vim_iswordp(lhs);
2785 last = first;
2786 p = lhs + (*mb_ptr2len)(lhs);
2787 n = 1;
2788 while (p < lhs + len) {
2789 n++; // nr of (multi-byte) chars
2790 last = vim_iswordp(p); // type of last char
2791 if (same == -1 && last != first) {
2792 same = n - 1; // count of same char type
2793 }
2794 p += (*mb_ptr2len)(p);
2795 }
2796 if (last && n > 2 && same >= 0 && same < n - 1) {
2797 retval = 1;
2798 goto theend;
2799 }
2800 } else if (vim_iswordc(lhs[len - 1])) { // ends in keyword char
2801 for (n = 0; n < len - 2; n++) {
2802 if (vim_iswordc(lhs[n]) != vim_iswordc(lhs[len - 2])) {
2803 retval = 1;
2804 goto theend;
2805 }
2806 } // for
2807 }
2808 // An abbreviation cannot contain white space.
2809 for (n = 0; n < len; n++) {
2810 if (ascii_iswhite(lhs[n])) {
2811 retval = 1;
2812 goto theend;
2813 }
2814 } // for
2815 }
2816 }
2817
2818 if (has_lhs && has_rhs && is_abbrev) { // if we will add an abbreviation,
2819 no_abbr = false; // reset flag that indicates there are no abbreviations
2820 }
2821
2822 if (!has_lhs || (maptype != 1 && !has_rhs)) {
2823 msg_start();
2824 }
2825
2826 // Check if a new local mapping wasn't already defined globally.
2827 if (map_table == buf->b_maphash && has_lhs && has_rhs && maptype != 1) {
2828 // need to loop over all global hash lists
2829 for (hash = 0; hash < 256 && !got_int; hash++) {
2830 if (is_abbrev) {
2831 if (hash != 0) { // there is only one abbreviation list
2832 break;
2833 }
2834 mp = first_abbr;
2835 } else {
2836 mp = maphash[hash];
2837 }
2838 for (; mp != NULL && !got_int; mp = mp->m_next) {
2839 // check entries with the same mode
2840 if ((mp->m_mode & mode) != 0
2841 && mp->m_keylen == len
2842 && args->unique
2843 && STRNCMP(mp->m_keys, lhs, (size_t)len) == 0) {
2844 if (is_abbrev) {
2845 EMSG2(_("E224: global abbreviation already exists for %s"),
2846 mp->m_keys);
2847 } else {
2848 EMSG2(_("E225: global mapping already exists for %s"), mp->m_keys);
2849 }
2850 retval = 5;
2851 goto theend;
2852 }
2853 }
2854 }
2855 }
2856
2857 // When listing global mappings, also list buffer-local ones here.
2858 if (map_table != buf->b_maphash && !has_rhs && maptype != 1) {
2859 // need to loop over all global hash lists
2860 for (hash = 0; hash < 256 && !got_int; hash++) {
2861 if (is_abbrev) {
2862 if (hash != 0) { // there is only one abbreviation list
2863 break;
2864 }
2865 mp = buf->b_first_abbr;
2866 } else {
2867 mp = buf->b_maphash[hash];
2868 }
2869 for (; mp != NULL && !got_int; mp = mp->m_next) {
2870 // check entries with the same mode
2871 if ((mp->m_mode & mode) != 0) {
2872 if (!has_lhs) { // show all entries
2873 showmap(mp, true);
2874 did_local = true;
2875 } else {
2876 n = mp->m_keylen;
2877 if (STRNCMP(mp->m_keys, lhs, (size_t)(n < len ? n : len)) == 0) {
2878 showmap(mp, true);
2879 did_local = true;
2880 }
2881 }
2882 }
2883 }
2884 }
2885 }
2886
2887 // Find an entry in the maphash[] list that matches.
2888 // For :unmap we may loop two times: once to try to unmap an entry with a
2889 // matching 'from' part, a second time, if the first fails, to unmap an
2890 // entry with a matching 'to' part. This was done to allow ":ab foo bar"
2891 // to be unmapped by typing ":unab foo", where "foo" will be replaced by
2892 // "bar" because of the abbreviation.
2893 for (round = 0; (round == 0 || maptype == 1) && round <= 1
2894 && !did_it && !got_int; round++) {
2895 // need to loop over all hash lists
2896 for (hash = 0; hash < 256 && !got_int; hash++) {
2897 if (is_abbrev) {
2898 if (hash > 0) { // there is only one abbreviation list
2899 break;
2900 }
2901 mpp = abbr_table;
2902 } else {
2903 mpp = &(map_table[hash]);
2904 }
2905 for (mp = *mpp; mp != NULL && !got_int; mp = *mpp) {
2906 if (!(mp->m_mode & mode)) { // skip entries with wrong mode
2907 mpp = &(mp->m_next);
2908 continue;
2909 }
2910 if (!has_lhs) { // show all entries
2911 showmap(mp, map_table != maphash);
2912 did_it = true;
2913 } else { // do we have a match?
2914 if (round) { // second round: Try unmap "rhs" string
2915 n = (int)STRLEN(mp->m_str);
2916 p = mp->m_str;
2917 } else {
2918 n = mp->m_keylen;
2919 p = mp->m_keys;
2920 }
2921 if (STRNCMP(p, lhs, (size_t)(n < len ? n : len)) == 0) {
2922 if (maptype == 1) { // delete entry
2923 // Only accept a full match. For abbreviations we
2924 // ignore trailing space when matching with the
2925 // "lhs", since an abbreviation can't have
2926 // trailing space.
2927 if (n != len && (!is_abbrev || round || n > len
2928 || *skipwhite(lhs + n) != NUL)) {
2929 mpp = &(mp->m_next);
2930 continue;
2931 }
2932 // We reset the indicated mode bits. If nothing is
2933 // left the entry is deleted below.
2934 mp->m_mode &= ~mode;
2935 did_it = true; // remember we did something
2936 } else if (!has_rhs) { // show matching entry
2937 showmap(mp, map_table != maphash);
2938 did_it = true;
2939 } else if (n != len) { // new entry is ambiguous
2940 mpp = &(mp->m_next);
2941 continue;
2942 } else if (args->unique) {
2943 if (is_abbrev) {
2944 EMSG2(_("E226: abbreviation already exists for %s"), p);
2945 } else {
2946 EMSG2(_("E227: mapping already exists for %s"), p);
2947 }
2948 retval = 5;
2949 goto theend;
2950 } else { // new rhs for existing entry
2951 mp->m_mode &= ~mode; // remove mode bits
2952 if (mp->m_mode == 0 && !did_it) { // reuse entry
2953 xfree(mp->m_str);
2954 mp->m_str = vim_strsave(rhs);
2955 xfree(mp->m_orig_str);
2956 mp->m_orig_str = vim_strsave(orig_rhs);
2957 mp->m_noremap = noremap;
2958 mp->m_nowait = args->nowait;
2959 mp->m_silent = args->silent;
2960 mp->m_mode = mode;
2961 mp->m_expr = args->expr;
2962 mp->m_script_ctx = current_sctx;
2963 mp->m_script_ctx.sc_lnum += sourcing_lnum;
2964 did_it = true;
2965 }
2966 }
2967 if (mp->m_mode == 0) { // entry can be deleted
2968 mapblock_free(mpp);
2969 continue; // continue with *mpp
2970 }
2971
2972 // May need to put this entry into another hash list.
2973 new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
2974 if (!is_abbrev && new_hash != hash) {
2975 *mpp = mp->m_next;
2976 mp->m_next = map_table[new_hash];
2977 map_table[new_hash] = mp;
2978
2979 continue; // continue with *mpp
2980 }
2981 }
2982 }
2983 mpp = &(mp->m_next);
2984 }
2985 }
2986 }
2987
2988 if (maptype == 1) { // delete entry
2989 if (!did_it) {
2990 retval = 2; // no match
2991 } else if (*lhs == Ctrl_C) {
2992 // If CTRL-C has been unmapped, reuse it for Interrupting.
2993 if (map_table == buf->b_maphash) {
2994 buf->b_mapped_ctrl_c &= ~mode;
2995 } else {
2996 mapped_ctrl_c &= ~mode;
2997 }
2998 }
2999 goto theend;
3000 }
3001
3002 if (!has_lhs || !has_rhs) { // print entries
3003 if (!did_it && !did_local) {
3004 if (is_abbrev) {
3005 MSG(_("No abbreviation found"));
3006 } else {
3007 MSG(_("No mapping found"));
3008 }
3009 }
3010 goto theend; // listing finished
3011 }
3012
3013 if (did_it) { // have added the new entry already
3014 goto theend;
3015 }
3016
3017 // Get here when adding a new entry to the maphash[] list or abbrlist.
3018 mp = xmalloc(sizeof(mapblock_T));
3019
3020 // If CTRL-C has been mapped, don't always use it for Interrupting.
3021 if (*lhs == Ctrl_C) {
3022 if (map_table == buf->b_maphash) {
3023 buf->b_mapped_ctrl_c |= mode;
3024 } else {
3025 mapped_ctrl_c |= mode;
3026 }
3027 }
3028
3029 mp->m_keys = vim_strsave(lhs);
3030 mp->m_str = vim_strsave(rhs);
3031 mp->m_orig_str = vim_strsave(orig_rhs);
3032 mp->m_keylen = (int)STRLEN(mp->m_keys);
3033 mp->m_noremap = noremap;
3034 mp->m_nowait = args->nowait;
3035 mp->m_silent = args->silent;
3036 mp->m_mode = mode;
3037 mp->m_expr = args->expr;
3038 mp->m_script_ctx = current_sctx;
3039 mp->m_script_ctx.sc_lnum += sourcing_lnum;
3040
3041 // add the new entry in front of the abbrlist or maphash[] list
3042 if (is_abbrev) {
3043 mp->m_next = *abbr_table;
3044 *abbr_table = mp;
3045 } else {
3046 n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
3047 mp->m_next = map_table[n];
3048 map_table[n] = mp;
3049 }
3050
3051theend:
3052 return retval;
3053}
3054
3055
3056/// Set or remove a mapping or an abbreviation in the current buffer, OR
3057/// display (matching) mappings/abbreviations.
3058///
3059/// ```vim
3060/// map[!] " show all key mappings
3061/// map[!] {lhs} " show key mapping for {lhs}
3062/// map[!] {lhs} {rhs} " set key mapping for {lhs} to {rhs}
3063/// noremap[!] {lhs} {rhs} " same, but no remapping for {rhs}
3064/// unmap[!] {lhs} " remove key mapping for {lhs}
3065/// abbr " show all abbreviations
3066/// abbr {lhs} " show abbreviations for {lhs}
3067/// abbr {lhs} {rhs} " set abbreviation for {lhs} to {rhs}
3068/// noreabbr {lhs} {rhs} " same, but no remapping for {rhs}
3069/// unabbr {lhs} " remove abbreviation for {lhs}
3070///
3071/// for :map mode is NORMAL + VISUAL + SELECTMODE + OP_PENDING
3072/// for :map! mode is INSERT + CMDLINE
3073/// for :cmap mode is CMDLINE
3074/// for :imap mode is INSERT
3075/// for :lmap mode is LANGMAP
3076/// for :nmap mode is NORMAL
3077/// for :vmap mode is VISUAL + SELECTMODE
3078/// for :xmap mode is VISUAL
3079/// for :smap mode is SELECTMODE
3080/// for :omap mode is OP_PENDING
3081/// for :tmap mode is TERM_FOCUS
3082///
3083/// for :abbr mode is INSERT + CMDLINE
3084/// for :iabbr mode is INSERT
3085/// for :cabbr mode is CMDLINE
3086/// ```
3087///
3088/// @param maptype 0 for |:map|, 1 for |:unmap|, 2 for |noremap|.
3089/// @param arg C-string containing the arguments of the map/abbrev
3090/// command, i.e. everything except the initial `:[X][nore]map`.
3091/// - Cannot be a read-only string; it will be modified.
3092/// @param mode Bitflags representing the mode in which to set the mapping.
3093/// See @ref get_map_mode.
3094/// @param is_abbrev True if setting an abbreviation, false otherwise.
3095///
3096/// @return 0 on success. On failure, will return one of the following:
3097/// - 1 for invalid arguments
3098/// - 2 for no match
3099/// - 4 for out of mem (deprecated, WON'T HAPPEN)
3100/// - 5 for entry not unique
3101///
3102int do_map(int maptype, char_u *arg, int mode, bool is_abbrev)
3103{
3104 MapArguments parsed_args;
3105 int result = str_to_mapargs(arg, maptype == 1, &parsed_args);
3106 switch (result) {
3107 case 0:
3108 break;
3109 case 1:
3110 result = 1; // invalid arguments
3111 goto free_and_return;
3112 default:
3113 assert(false && "Unknown return code from str_to_mapargs!");
3114 result = -1;
3115 goto free_and_return;
3116 } // switch
3117
3118 result = buf_do_map(maptype, &parsed_args, mode, is_abbrev, curbuf);
3119
3120free_and_return:
3121 xfree(parsed_args.rhs);
3122 xfree(parsed_args.orig_rhs);
3123 return result;
3124}
3125
3126/*
3127 * Delete one entry from the abbrlist or maphash[].
3128 * "mpp" is a pointer to the m_next field of the PREVIOUS entry!
3129 */
3130static void mapblock_free(mapblock_T **mpp)
3131{
3132 mapblock_T *mp;
3133
3134 mp = *mpp;
3135 xfree(mp->m_keys);
3136 xfree(mp->m_str);
3137 xfree(mp->m_orig_str);
3138 *mpp = mp->m_next;
3139 xfree(mp);
3140}
3141
3142/*
3143 * Initialize maphash[] for first use.
3144 */
3145static void validate_maphash(void)
3146{
3147 if (!maphash_valid) {
3148 memset(maphash, 0, sizeof(maphash));
3149 maphash_valid = TRUE;
3150 }
3151}
3152
3153/*
3154 * Get the mapping mode from the command name.
3155 */
3156int get_map_mode(char_u **cmdp, int forceit)
3157{
3158 char_u *p;
3159 int modec;
3160 int mode;
3161
3162 p = *cmdp;
3163 modec = *p++;
3164 if (modec == 'i')
3165 mode = INSERT; /* :imap */
3166 else if (modec == 'l')
3167 mode = LANGMAP; /* :lmap */
3168 else if (modec == 'c')
3169 mode = CMDLINE; /* :cmap */
3170 else if (modec == 'n' && *p != 'o') /* avoid :noremap */
3171 mode = NORMAL; /* :nmap */
3172 else if (modec == 'v')
3173 mode = VISUAL + SELECTMODE; /* :vmap */
3174 else if (modec == 'x')
3175 mode = VISUAL; /* :xmap */
3176 else if (modec == 's')
3177 mode = SELECTMODE; /* :smap */
3178 else if (modec == 'o')
3179 mode = OP_PENDING; /* :omap */
3180 else if (modec == 't')
3181 mode = TERM_FOCUS; // :tmap
3182 else {
3183 --p;
3184 if (forceit)
3185 mode = INSERT + CMDLINE; /* :map ! */
3186 else
3187 mode = VISUAL + SELECTMODE + NORMAL + OP_PENDING; /* :map */
3188 }
3189
3190 *cmdp = p;
3191 return mode;
3192}
3193
3194/*
3195 * Clear all mappings or abbreviations.
3196 * 'abbr' should be FALSE for mappings, TRUE for abbreviations.
3197 */
3198void map_clear_mode(char_u *cmdp, char_u *arg, int forceit, int abbr)
3199{
3200 int mode;
3201 int local;
3202
3203 local = (STRCMP(arg, "<buffer>") == 0);
3204 if (!local && *arg != NUL) {
3205 EMSG(_(e_invarg));
3206 return;
3207 }
3208
3209 mode = get_map_mode(&cmdp, forceit);
3210 map_clear_int(curbuf, mode,
3211 local,
3212 abbr);
3213}
3214
3215/*
3216 * Clear all mappings in "mode".
3217 */
3218void
3219map_clear_int (
3220 buf_T *buf, /* buffer for local mappings */
3221 int mode, /* mode in which to delete */
3222 int local, /* TRUE for buffer-local mappings */
3223 int abbr /* TRUE for abbreviations */
3224)
3225{
3226 mapblock_T *mp, **mpp;
3227 int hash;
3228 int new_hash;
3229
3230 validate_maphash();
3231
3232 for (hash = 0; hash < 256; ++hash) {
3233 if (abbr) {
3234 if (hash > 0) /* there is only one abbrlist */
3235 break;
3236 if (local)
3237 mpp = &buf->b_first_abbr;
3238 else
3239 mpp = &first_abbr;
3240 } else {
3241 if (local)
3242 mpp = &buf->b_maphash[hash];
3243 else
3244 mpp = &maphash[hash];
3245 }
3246 while (*mpp != NULL) {
3247 mp = *mpp;
3248 if (mp->m_mode & mode) {
3249 mp->m_mode &= ~mode;
3250 if (mp->m_mode == 0) { // entry can be deleted
3251 mapblock_free(mpp);
3252 continue;
3253 }
3254 /*
3255 * May need to put this entry into another hash list.
3256 */
3257 new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
3258 if (!abbr && new_hash != hash) {
3259 *mpp = mp->m_next;
3260 if (local) {
3261 mp->m_next = buf->b_maphash[new_hash];
3262 buf->b_maphash[new_hash] = mp;
3263 } else {
3264 mp->m_next = maphash[new_hash];
3265 maphash[new_hash] = mp;
3266 }
3267 continue; /* continue with *mpp */
3268 }
3269 }
3270 mpp = &(mp->m_next);
3271 }
3272 }
3273}
3274
3275/// Return characters to represent the map mode in an allocated string
3276///
3277/// @return [allocated] NUL-terminated string with characters.
3278char *map_mode_to_chars(int mode)
3279 FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET
3280{
3281 garray_T mapmode;
3282
3283 ga_init(&mapmode, 1, 7);
3284
3285 if ((mode & (INSERT + CMDLINE)) == INSERT + CMDLINE) {
3286 ga_append(&mapmode, '!'); // :map!
3287 } else if (mode & INSERT) {
3288 ga_append(&mapmode, 'i'); // :imap
3289 } else if (mode & LANGMAP) {
3290 ga_append(&mapmode, 'l'); // :lmap
3291 } else if (mode & CMDLINE) {
3292 ga_append(&mapmode, 'c'); // :cmap
3293 } else if ((mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING))
3294 == NORMAL + VISUAL + SELECTMODE + OP_PENDING) {
3295 ga_append(&mapmode, ' '); // :map
3296 } else {
3297 if (mode & NORMAL) {
3298 ga_append(&mapmode, 'n'); // :nmap
3299 }
3300 if (mode & OP_PENDING) {
3301 ga_append(&mapmode, 'o'); // :omap
3302 }
3303 if (mode & TERM_FOCUS) {
3304 ga_append(&mapmode, 't'); // :tmap
3305 }
3306 if ((mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE) {
3307 ga_append(&mapmode, 'v'); // :vmap
3308 } else {
3309 if (mode & VISUAL) {
3310 ga_append(&mapmode, 'x'); // :xmap
3311 }
3312 if (mode & SELECTMODE) {
3313 ga_append(&mapmode, 's'); // :smap
3314 }
3315 }
3316 }
3317
3318 ga_append(&mapmode, NUL);
3319 return (char *)mapmode.ga_data;
3320}
3321
3322static void
3323showmap (
3324 mapblock_T *mp,
3325 int local /* TRUE for buffer-local map */
3326)
3327{
3328 size_t len = 1;
3329
3330 if (message_filtered(mp->m_keys) && message_filtered(mp->m_str)) {
3331 return;
3332 }
3333
3334 if (msg_didout || msg_silent != 0) {
3335 msg_putchar('\n');
3336 if (got_int) /* 'q' typed at MORE prompt */
3337 return;
3338 }
3339
3340 {
3341 char *const mapchars = map_mode_to_chars(mp->m_mode);
3342 msg_puts(mapchars);
3343 len = strlen(mapchars);
3344 xfree(mapchars);
3345 }
3346
3347 while (++len <= 3)
3348 msg_putchar(' ');
3349
3350 // Display the LHS. Get length of what we write.
3351 len = (size_t)msg_outtrans_special(mp->m_keys, true);
3352 do {
3353 msg_putchar(' '); /* padd with blanks */
3354 ++len;
3355 } while (len < 12);
3356
3357 if (mp->m_noremap == REMAP_NONE) {
3358 msg_puts_attr("*", HL_ATTR(HLF_8));
3359 } else if (mp->m_noremap == REMAP_SCRIPT) {
3360 msg_puts_attr("&", HL_ATTR(HLF_8));
3361 } else {
3362 msg_putchar(' ');
3363 }
3364
3365 if (local)
3366 msg_putchar('@');
3367 else
3368 msg_putchar(' ');
3369
3370 /* Use FALSE below if we only want things like <Up> to show up as such on
3371 * the rhs, and not M-x etc, TRUE gets both -- webb */
3372 if (*mp->m_str == NUL) {
3373 msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
3374 } else {
3375 // Remove escaping of CSI, because "m_str" is in a format to be used
3376 // as typeahead.
3377 char_u *s = vim_strsave(mp->m_str);
3378 vim_unescape_csi(s);
3379 msg_outtrans_special(s, FALSE);
3380 xfree(s);
3381 }
3382 if (p_verbose > 0) {
3383 last_set_msg(mp->m_script_ctx);
3384 }
3385 ui_flush(); // show one line at a time
3386}
3387
3388/// Check if a map exists that has given string in the rhs
3389///
3390/// Also checks mappings local to the current buffer.
3391///
3392/// @param[in] str String which mapping must have in the rhs. Termcap codes
3393/// are recognized in this argument.
3394/// @param[in] modechars Mode(s) in which mappings are checked.
3395/// @param[in] abbr true if checking abbreviations in place of mappings.
3396///
3397/// @return true if there is at least one mapping with given parameters.
3398bool map_to_exists(const char *const str, const char *const modechars,
3399 const bool abbr)
3400 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
3401{
3402 int mode = 0;
3403 int retval;
3404
3405 char_u *buf;
3406 char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf,
3407 false, true, true,
3408 CPO_TO_CPO_FLAGS);
3409
3410#define MAPMODE(mode, modechars, chr, modeflags) \
3411 do { \
3412 if (strchr(modechars, chr) != NULL) { \
3413 mode |= modeflags; \
3414 } \
3415 } while (0)
3416 MAPMODE(mode, modechars, 'n', NORMAL);
3417 MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE);
3418 MAPMODE(mode, modechars, 'x', VISUAL);
3419 MAPMODE(mode, modechars, 's', SELECTMODE);
3420 MAPMODE(mode, modechars, 'o', OP_PENDING);
3421 MAPMODE(mode, modechars, 'i', INSERT);
3422 MAPMODE(mode, modechars, 'l', LANGMAP);
3423 MAPMODE(mode, modechars, 'c', CMDLINE);
3424#undef MAPMODE
3425
3426 retval = map_to_exists_mode((const char *)rhs, mode, abbr);
3427 xfree(buf);
3428
3429 return retval;
3430}
3431
3432/// Check if a map exists that has given string in the rhs
3433///
3434/// Also checks mappings local to the current buffer.
3435///
3436/// @param[in] rhs String which mapping must have in the rhs. Termcap codes
3437/// are recognized in this argument.
3438/// @param[in] mode Mode(s) in which mappings are checked.
3439/// @param[in] abbr true if checking abbreviations in place of mappings.
3440///
3441/// @return true if there is at least one mapping with given parameters.
3442int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
3443{
3444 mapblock_T *mp;
3445 int hash;
3446 bool exp_buffer = false;
3447
3448 validate_maphash();
3449
3450 // Do it twice: once for global maps and once for local maps.
3451 for (;;) {
3452 for (hash = 0; hash < 256; hash++) {
3453 if (abbr) {
3454 if (hash > 0) { // There is only one abbr list.
3455 break;
3456 }
3457 if (exp_buffer) {
3458 mp = curbuf->b_first_abbr;
3459 } else {
3460 mp = first_abbr;
3461 }
3462 } else if (exp_buffer) {
3463 mp = curbuf->b_maphash[hash];
3464 } else {
3465 mp = maphash[hash];
3466 }
3467 for (; mp; mp = mp->m_next) {
3468 if ((mp->m_mode & mode)
3469 && strstr((char *)mp->m_str, rhs) != NULL) {
3470 return true;
3471 }
3472 }
3473 }
3474 if (exp_buffer) {
3475 break;
3476 }
3477 exp_buffer = true;
3478 }
3479
3480 return false;
3481}
3482
3483/*
3484 * Used below when expanding mapping/abbreviation names.
3485 */
3486static int expand_mapmodes = 0;
3487static int expand_isabbrev = 0;
3488static int expand_buffer = FALSE;
3489
3490/*
3491 * Work out what to complete when doing command line completion of mapping
3492 * or abbreviation names.
3493 */
3494char_u *
3495set_context_in_map_cmd (
3496 expand_T *xp,
3497 char_u *cmd,
3498 char_u *arg,
3499 int forceit, /* TRUE if '!' given */
3500 int isabbrev, /* TRUE if abbreviation */
3501 int isunmap, /* TRUE if unmap/unabbrev command */
3502 cmdidx_T cmdidx
3503)
3504{
3505 if (forceit && cmdidx != CMD_map && cmdidx != CMD_unmap)
3506 xp->xp_context = EXPAND_NOTHING;
3507 else {
3508 if (isunmap)
3509 expand_mapmodes = get_map_mode(&cmd, forceit || isabbrev);
3510 else {
3511 expand_mapmodes = INSERT + CMDLINE;
3512 if (!isabbrev)
3513 expand_mapmodes += VISUAL + SELECTMODE + NORMAL + OP_PENDING;
3514 }
3515 expand_isabbrev = isabbrev;
3516 xp->xp_context = EXPAND_MAPPINGS;
3517 expand_buffer = FALSE;
3518 for (;; ) {
3519 if (STRNCMP(arg, "<buffer>", 8) == 0) {
3520 expand_buffer = TRUE;
3521 arg = skipwhite(arg + 8);
3522 continue;
3523 }
3524 if (STRNCMP(arg, "<unique>", 8) == 0) {
3525 arg = skipwhite(arg + 8);
3526 continue;
3527 }
3528 if (STRNCMP(arg, "<nowait>", 8) == 0) {
3529 arg = skipwhite(arg + 8);
3530 continue;
3531 }
3532 if (STRNCMP(arg, "<silent>", 8) == 0) {
3533 arg = skipwhite(arg + 8);
3534 continue;
3535 }
3536 if (STRNCMP(arg, "<special>", 9) == 0) {
3537 arg = skipwhite(arg + 9);
3538 continue;
3539 }
3540 if (STRNCMP(arg, "<script>", 8) == 0) {
3541 arg = skipwhite(arg + 8);
3542 continue;
3543 }
3544 if (STRNCMP(arg, "<expr>", 6) == 0) {
3545 arg = skipwhite(arg + 6);
3546 continue;
3547 }
3548 break;
3549 }
3550 xp->xp_pattern = arg;
3551 }
3552
3553 return NULL;
3554}
3555
3556// Find all mapping/abbreviation names that match regexp "regmatch".
3557// For command line expansion of ":[un]map" and ":[un]abbrev" in all modes.
3558// Return OK if matches found, FAIL otherwise.
3559int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file)
3560{
3561 mapblock_T *mp;
3562 int hash;
3563 int count;
3564 int round;
3565 char_u *p;
3566 int i;
3567
3568 validate_maphash();
3569
3570 *num_file = 0; /* return values in case of FAIL */
3571 *file = NULL;
3572
3573 /*
3574 * round == 1: Count the matches.
3575 * round == 2: Build the array to keep the matches.
3576 */
3577 for (round = 1; round <= 2; ++round) {
3578 count = 0;
3579
3580 for (i = 0; i < 7; i++) {
3581 if (i == 0) {
3582 p = (char_u *)"<silent>";
3583 } else if (i == 1) {
3584 p = (char_u *)"<unique>";
3585 } else if (i == 2) {
3586 p = (char_u *)"<script>";
3587 } else if (i == 3) {
3588 p = (char_u *)"<expr>";
3589 } else if (i == 4 && !expand_buffer) {
3590 p = (char_u *)"<buffer>";
3591 } else if (i == 5) {
3592 p = (char_u *)"<nowait>";
3593 } else if (i == 6) {
3594 p = (char_u *)"<special>";
3595 } else {
3596 continue;
3597 }
3598
3599 if (vim_regexec(regmatch, p, (colnr_T)0)) {
3600 if (round == 1)
3601 ++count;
3602 else
3603 (*file)[count++] = vim_strsave(p);
3604 }
3605 }
3606
3607 for (hash = 0; hash < 256; ++hash) {
3608 if (expand_isabbrev) {
3609 if (hash > 0) /* only one abbrev list */
3610 break; /* for (hash) */
3611 mp = first_abbr;
3612 } else if (expand_buffer)
3613 mp = curbuf->b_maphash[hash];
3614 else
3615 mp = maphash[hash];
3616 for (; mp; mp = mp->m_next) {
3617 if (mp->m_mode & expand_mapmodes) {
3618 p = translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS);
3619 if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) {
3620 if (round == 1)
3621 ++count;
3622 else {
3623 (*file)[count++] = p;
3624 p = NULL;
3625 }
3626 }
3627 xfree(p);
3628 }
3629 } /* for (mp) */
3630 } /* for (hash) */
3631
3632 if (count == 0) /* no match found */
3633 break; /* for (round) */
3634
3635 if (round == 1) {
3636 *file = (char_u **)xmalloc((size_t)count * sizeof(char_u *));
3637 }
3638 } /* for (round) */
3639
3640 if (count > 1) {
3641 char_u **ptr1;
3642 char_u **ptr2;
3643 char_u **ptr3;
3644
3645 /* Sort the matches */
3646 sort_strings(*file, count);
3647
3648 /* Remove multiple entries */
3649 ptr1 = *file;
3650 ptr2 = ptr1 + 1;
3651 ptr3 = ptr1 + count;
3652
3653 while (ptr2 < ptr3) {
3654 if (STRCMP(*ptr1, *ptr2))
3655 *++ptr1 = *ptr2++;
3656 else {
3657 xfree(*ptr2++);
3658 count--;
3659 }
3660 }
3661 }
3662
3663 *num_file = count;
3664 return count == 0 ? FAIL : OK;
3665}
3666
3667/*
3668 * Check for an abbreviation.
3669 * Cursor is at ptr[col].
3670 * When inserting, mincol is where insert started.
3671 * For the command line, mincol is what is to be skipped over.
3672 * "c" is the character typed before check_abbr was called. It may have
3673 * ABBR_OFF added to avoid prepending a CTRL-V to it.
3674 *
3675 * Historic vi practice: The last character of an abbreviation must be an id
3676 * character ([a-zA-Z0-9_]). The characters in front of it must be all id
3677 * characters or all non-id characters. This allows for abbr. "#i" to
3678 * "#include".
3679 *
3680 * Vim addition: Allow for abbreviations that end in a non-keyword character.
3681 * Then there must be white space before the abbr.
3682 *
3683 * return TRUE if there is an abbreviation, FALSE if not
3684 */
3685int check_abbr(int c, char_u *ptr, int col, int mincol)
3686{
3687 int len;
3688 int scol; /* starting column of the abbr. */
3689 int j;
3690 char_u *s;
3691 char_u tb[MB_MAXBYTES + 4];
3692 mapblock_T *mp;
3693 mapblock_T *mp2;
3694 int clen = 0; /* length in characters */
3695 int is_id = TRUE;
3696 int vim_abbr;
3697
3698 if (typebuf.tb_no_abbr_cnt) /* abbrev. are not recursive */
3699 return FALSE;
3700
3701 /* no remapping implies no abbreviation, except for CTRL-] */
3702 if ((KeyNoremap & (RM_NONE|RM_SCRIPT)) != 0 && c != Ctrl_RSB)
3703 return FALSE;
3704
3705 /*
3706 * Check for word before the cursor: If it ends in a keyword char all
3707 * chars before it must be keyword chars or non-keyword chars, but not
3708 * white space. If it ends in a non-keyword char we accept any characters
3709 * before it except white space.
3710 */
3711 if (col == 0) /* cannot be an abbr. */
3712 return FALSE;
3713
3714 if (has_mbyte) {
3715 char_u *p;
3716
3717 p = mb_prevptr(ptr, ptr + col);
3718 if (!vim_iswordp(p))
3719 vim_abbr = TRUE; /* Vim added abbr. */
3720 else {
3721 vim_abbr = FALSE; /* vi compatible abbr. */
3722 if (p > ptr)
3723 is_id = vim_iswordp(mb_prevptr(ptr, p));
3724 }
3725 clen = 1;
3726 while (p > ptr + mincol) {
3727 p = mb_prevptr(ptr, p);
3728 if (ascii_isspace(*p) || (!vim_abbr && is_id != vim_iswordp(p))) {
3729 p += (*mb_ptr2len)(p);
3730 break;
3731 }
3732 ++clen;
3733 }
3734 scol = (int)(p - ptr);
3735 } else {
3736 if (!vim_iswordc(ptr[col - 1]))
3737 vim_abbr = TRUE; /* Vim added abbr. */
3738 else {
3739 vim_abbr = FALSE; /* vi compatible abbr. */
3740 if (col > 1)
3741 is_id = vim_iswordc(ptr[col - 2]);
3742 }
3743 for (scol = col - 1; scol > 0 && !ascii_isspace(ptr[scol - 1])
3744 && (vim_abbr || is_id == vim_iswordc(ptr[scol - 1])); --scol)
3745 ;
3746 }
3747
3748 if (scol < mincol)
3749 scol = mincol;
3750 if (scol < col) { /* there is a word in front of the cursor */
3751 ptr += scol;
3752 len = col - scol;
3753 mp = curbuf->b_first_abbr;
3754 mp2 = first_abbr;
3755 if (mp == NULL) {
3756 mp = mp2;
3757 mp2 = NULL;
3758 }
3759 for (; mp;
3760 mp->m_next == NULL ? (mp = mp2, mp2 = NULL) :
3761 (mp = mp->m_next)) {
3762 int qlen = mp->m_keylen;
3763 char_u *q = mp->m_keys;
3764 int match;
3765
3766 if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) {
3767 // Might have CSI escaped mp->m_keys.
3768 q = vim_strsave(mp->m_keys);
3769 vim_unescape_csi(q);
3770 qlen = (int)STRLEN(q);
3771 }
3772 /* find entries with right mode and keys */
3773 match = (mp->m_mode & State)
3774 && qlen == len
3775 && !STRNCMP(q, ptr, (size_t)len);
3776 if (q != mp->m_keys) {
3777 xfree(q);
3778 }
3779 if (match) {
3780 break;
3781 }
3782 }
3783 if (mp != NULL) {
3784 /*
3785 * Found a match:
3786 * Insert the rest of the abbreviation in typebuf.tb_buf[].
3787 * This goes from end to start.
3788 *
3789 * Characters 0x000 - 0x100: normal chars, may need CTRL-V,
3790 * except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL KE_FILLER
3791 * Characters where IS_SPECIAL() == TRUE: key codes, need
3792 * K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
3793 *
3794 * Character CTRL-] is treated specially - it completes the
3795 * abbreviation, but is not inserted into the input stream.
3796 */
3797 j = 0;
3798 if (c != Ctrl_RSB) {
3799 /* special key code, split up */
3800 if (IS_SPECIAL(c) || c == K_SPECIAL) {
3801 tb[j++] = K_SPECIAL;
3802 tb[j++] = (char_u)K_SECOND(c);
3803 tb[j++] = (char_u)K_THIRD(c);
3804 } else {
3805 if (c < ABBR_OFF && (c < ' ' || c > '~')) {
3806 tb[j++] = Ctrl_V; // special char needs CTRL-V
3807 }
3808 // if ABBR_OFF has been added, remove it here.
3809 if (c >= ABBR_OFF) {
3810 c -= ABBR_OFF;
3811 }
3812 j += utf_char2bytes(c, tb + j);
3813 }
3814 tb[j] = NUL;
3815 /* insert the last typed char */
3816 (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
3817 }
3818 if (mp->m_expr)
3819 s = eval_map_expr(mp->m_str, c);
3820 else
3821 s = mp->m_str;
3822 if (s != NULL) {
3823 /* insert the to string */
3824 (void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent);
3825 /* no abbrev. for these chars */
3826 typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1;
3827 if (mp->m_expr)
3828 xfree(s);
3829 }
3830
3831 tb[0] = Ctrl_H;
3832 tb[1] = NUL;
3833 if (has_mbyte)
3834 len = clen; /* Delete characters instead of bytes */
3835 while (len-- > 0) /* delete the from string */
3836 (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
3837 return TRUE;
3838 }
3839 }
3840 return FALSE;
3841}
3842
3843/*
3844 * Evaluate the RHS of a mapping or abbreviations and take care of escaping
3845 * special characters.
3846 */
3847static char_u *
3848eval_map_expr (
3849 char_u *str,
3850 int c /* NUL or typed character for abbreviation */
3851)
3852{
3853 char_u *res;
3854 char_u *p;
3855 char_u *expr;
3856 char_u *save_cmd;
3857 pos_T save_cursor;
3858 int save_msg_col;
3859 int save_msg_row;
3860
3861 /* Remove escaping of CSI, because "str" is in a format to be used as
3862 * typeahead. */
3863 expr = vim_strsave(str);
3864 vim_unescape_csi(expr);
3865
3866 save_cmd = save_cmdline_alloc();
3867
3868 /* Forbid changing text or using ":normal" to avoid most of the bad side
3869 * effects. Also restore the cursor position. */
3870 ++textlock;
3871 ++ex_normal_lock;
3872 set_vim_var_char(c); /* set v:char to the typed character */
3873 save_cursor = curwin->w_cursor;
3874 save_msg_col = msg_col;
3875 save_msg_row = msg_row;
3876 p = eval_to_string(expr, NULL, FALSE);
3877 --textlock;
3878 --ex_normal_lock;
3879 curwin->w_cursor = save_cursor;
3880 msg_col = save_msg_col;
3881 msg_row = save_msg_row;
3882
3883 restore_cmdline_alloc(save_cmd);
3884 xfree(expr);
3885
3886 if (p == NULL)
3887 return NULL;
3888 /* Escape CSI in the result to be able to use the string as typeahead. */
3889 res = vim_strsave_escape_csi(p);
3890 xfree(p);
3891
3892 return res;
3893}
3894
3895/*
3896 * Copy "p" to allocated memory, escaping K_SPECIAL and CSI so that the result
3897 * can be put in the typeahead buffer.
3898 */
3899char_u *vim_strsave_escape_csi(char_u *p)
3900{
3901 // Need a buffer to hold up to three times as much. Four in case of an
3902 // illegal utf-8 byte:
3903 // 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER
3904 char_u *res = xmalloc(STRLEN(p) * 4 + 1);
3905 char_u *d = res;
3906 for (char_u *s = p; *s != NUL; ) {
3907 if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
3908 /* Copy special key unmodified. */
3909 *d++ = *s++;
3910 *d++ = *s++;
3911 *d++ = *s++;
3912 } else {
3913 // Add character, possibly multi-byte to destination, escaping
3914 // CSI and K_SPECIAL. Be careful, it can be an illegal byte!
3915 d = add_char2buf(PTR2CHAR(s), d);
3916 s += MB_CPTR2LEN(s);
3917 }
3918 }
3919 *d = NUL;
3920
3921 return res;
3922}
3923
3924/*
3925 * Remove escaping from CSI and K_SPECIAL characters. Reverse of
3926 * vim_strsave_escape_csi(). Works in-place.
3927 */
3928void vim_unescape_csi(char_u *p)
3929{
3930 char_u *s = p, *d = p;
3931
3932 while (*s != NUL) {
3933 if (s[0] == K_SPECIAL && s[1] == KS_SPECIAL && s[2] == KE_FILLER) {
3934 *d++ = K_SPECIAL;
3935 s += 3;
3936 } else if ((s[0] == K_SPECIAL || s[0] == CSI)
3937 && s[1] == KS_EXTRA && s[2] == (int)KE_CSI) {
3938 *d++ = CSI;
3939 s += 3;
3940 } else
3941 *d++ = *s++;
3942 }
3943 *d = NUL;
3944}
3945
3946/*
3947 * Write map commands for the current mappings to an .exrc file.
3948 * Return FAIL on error, OK otherwise.
3949 */
3950int
3951makemap(
3952 FILE *fd,
3953 buf_T *buf // buffer for local mappings or NULL
3954)
3955{
3956 mapblock_T *mp;
3957 char_u c1, c2, c3;
3958 char_u *p;
3959 char *cmd;
3960 int abbr;
3961 int hash;
3962 bool did_cpo = false;
3963
3964 validate_maphash();
3965
3966 // Do the loop twice: Once for mappings, once for abbreviations.
3967 // Then loop over all map hash lists.
3968 for (abbr = 0; abbr < 2; abbr++) {
3969 for (hash = 0; hash < 256; hash++) {
3970 if (abbr) {
3971 if (hash > 0) { // there is only one abbr list
3972 break;
3973 }
3974 if (buf != NULL) {
3975 mp = buf->b_first_abbr;
3976 } else {
3977 mp = first_abbr;
3978 }
3979 } else {
3980 if (buf != NULL) {
3981 mp = buf->b_maphash[hash];
3982 } else {
3983 mp = maphash[hash];
3984 }
3985 }
3986
3987 for (; mp; mp = mp->m_next) {
3988 // skip script-local mappings
3989 if (mp->m_noremap == REMAP_SCRIPT) {
3990 continue;
3991 }
3992
3993 // skip mappings that contain a <SNR> (script-local thing),
3994 // they probably don't work when loaded again
3995 for (p = mp->m_str; *p != NUL; p++) {
3996 if (p[0] == K_SPECIAL && p[1] == KS_EXTRA
3997 && p[2] == (int)KE_SNR) {
3998 break;
3999 }
4000 }
4001 if (*p != NUL) {
4002 continue;
4003 }
4004
4005 // It's possible to create a mapping and then ":unmap" certain
4006 // modes. We recreate this here by mapping the individual
4007 // modes, which requires up to three of them.
4008 c1 = NUL;
4009 c2 = NUL;
4010 c3 = NUL;
4011 if (abbr) {
4012 cmd = "abbr";
4013 } else {
4014 cmd = "map";
4015 }
4016 switch (mp->m_mode) {
4017 case NORMAL + VISUAL + SELECTMODE + OP_PENDING:
4018 break;
4019 case NORMAL:
4020 c1 = 'n';
4021 break;
4022 case VISUAL:
4023 c1 = 'x';
4024 break;
4025 case SELECTMODE:
4026 c1 = 's';
4027 break;
4028 case OP_PENDING:
4029 c1 = 'o';
4030 break;
4031 case NORMAL + VISUAL:
4032 c1 = 'n';
4033 c2 = 'x';
4034 break;
4035 case NORMAL + SELECTMODE:
4036 c1 = 'n';
4037 c2 = 's';
4038 break;
4039 case NORMAL + OP_PENDING:
4040 c1 = 'n';
4041 c2 = 'o';
4042 break;
4043 case VISUAL + SELECTMODE:
4044 c1 = 'v';
4045 break;
4046 case VISUAL + OP_PENDING:
4047 c1 = 'x';
4048 c2 = 'o';
4049 break;
4050 case SELECTMODE + OP_PENDING:
4051 c1 = 's';
4052 c2 = 'o';
4053 break;
4054 case NORMAL + VISUAL + SELECTMODE:
4055 c1 = 'n';
4056 c2 = 'v';
4057 break;
4058 case NORMAL + VISUAL + OP_PENDING:
4059 c1 = 'n';
4060 c2 = 'x';
4061 c3 = 'o';
4062 break;
4063 case NORMAL + SELECTMODE + OP_PENDING:
4064 c1 = 'n';
4065 c2 = 's';
4066 c3 = 'o';
4067 break;
4068 case VISUAL + SELECTMODE + OP_PENDING:
4069 c1 = 'v';
4070 c2 = 'o';
4071 break;
4072 case CMDLINE + INSERT:
4073 if (!abbr) {
4074 cmd = "map!";
4075 }
4076 break;
4077 case CMDLINE:
4078 c1 = 'c';
4079 break;
4080 case INSERT:
4081 c1 = 'i';
4082 break;
4083 case LANGMAP:
4084 c1 = 'l';
4085 break;
4086 case TERM_FOCUS:
4087 c1 = 't';
4088 break;
4089 default:
4090 IEMSG(_("E228: makemap: Illegal mode"));
4091 return FAIL;
4092 }
4093 do {
4094 // do this twice if c2 is set, 3 times with c3 */
4095 // When outputting <> form, need to make sure that 'cpo'
4096 // is set to the Vim default.
4097 if (!did_cpo) {
4098 if (*mp->m_str == NUL) { // Will use <Nop>.
4099 did_cpo = true;
4100 } else {
4101 const char specials[] = { (char)(uint8_t)K_SPECIAL, NL, NUL };
4102 if (strpbrk((const char *)mp->m_str, specials) != NULL
4103 || strpbrk((const char *)mp->m_keys, specials) != NULL) {
4104 did_cpo = true;
4105 }
4106 }
4107 if (did_cpo) {
4108 if (fprintf(fd, "let s:cpo_save=&cpo") < 0
4109 || put_eol(fd) < 0
4110 || fprintf(fd, "set cpo&vim") < 0
4111 || put_eol(fd) < 0) {
4112 return FAIL;
4113 }
4114 }
4115 }
4116 if (c1 && putc(c1, fd) < 0) {
4117 return FAIL;
4118 }
4119 if (mp->m_noremap != REMAP_YES && fprintf(fd, "nore") < 0) {
4120 return FAIL;
4121 }
4122 if (fputs(cmd, fd) < 0) {
4123 return FAIL;
4124 }
4125 if (buf != NULL && fputs(" <buffer>", fd) < 0) {
4126 return FAIL;
4127 }
4128 if (mp->m_nowait && fputs(" <nowait>", fd) < 0) {
4129 return FAIL;
4130 }
4131 if (mp->m_silent && fputs(" <silent>", fd) < 0) {
4132 return FAIL;
4133 }
4134 if (mp->m_expr && fputs(" <expr>", fd) < 0) {
4135 return FAIL;
4136 }
4137
4138 if (putc(' ', fd) < 0
4139 || put_escstr(fd, mp->m_keys, 0) == FAIL
4140 || putc(' ', fd) < 0
4141 || put_escstr(fd, mp->m_str, 1) == FAIL
4142 || put_eol(fd) < 0) {
4143 return FAIL;
4144 }
4145 c1 = c2;
4146 c2 = c3;
4147 c3 = NUL;
4148 } while (c1 != NUL);
4149 }
4150 }
4151 }
4152 if (did_cpo) {
4153 if (fprintf(fd, "let &cpo=s:cpo_save") < 0
4154 || put_eol(fd) < 0
4155 || fprintf(fd, "unlet s:cpo_save") < 0
4156 || put_eol(fd) < 0) {
4157 return FAIL;
4158 }
4159 }
4160 return OK;
4161}
4162
4163// write escape string to file
4164// "what": 0 for :map lhs, 1 for :map rhs, 2 for :set
4165//
4166// return FAIL for failure, OK otherwise
4167int put_escstr(FILE *fd, char_u *strstart, int what)
4168{
4169 char_u *str = strstart;
4170 int c;
4171 int modifiers;
4172
4173 // :map xx <Nop>
4174 if (*str == NUL && what == 1) {
4175 if (fprintf(fd, "<Nop>") < 0)
4176 return FAIL;
4177 return OK;
4178 }
4179
4180 for (; *str != NUL; str++) {
4181 // Check for a multi-byte character, which may contain escaped
4182 // K_SPECIAL and CSI bytes.
4183 const char *p = mb_unescape((const char **)&str);
4184 if (p != NULL) {
4185 while (*p != NUL)
4186 if (fputc(*p++, fd) < 0)
4187 return FAIL;
4188 --str;
4189 continue;
4190 }
4191
4192 c = *str;
4193 /*
4194 * Special key codes have to be translated to be able to make sense
4195 * when they are read back.
4196 */
4197 if (c == K_SPECIAL && what != 2) {
4198 modifiers = 0x0;
4199 if (str[1] == KS_MODIFIER) {
4200 modifiers = str[2];
4201 str += 3;
4202 c = *str;
4203 }
4204 if (c == K_SPECIAL) {
4205 c = TO_SPECIAL(str[1], str[2]);
4206 str += 2;
4207 }
4208 if (IS_SPECIAL(c) || modifiers) { /* special key */
4209 if (fputs((char *)get_special_key_name(c, modifiers), fd) < 0)
4210 return FAIL;
4211 continue;
4212 }
4213 }
4214
4215 /*
4216 * A '\n' in a map command should be written as <NL>.
4217 * A '\n' in a set command should be written as \^V^J.
4218 */
4219 if (c == NL) {
4220 if (what == 2) {
4221 if (fprintf(fd, "\\\026\n") < 0)
4222 return FAIL;
4223 } else {
4224 if (fprintf(fd, "<NL>") < 0)
4225 return FAIL;
4226 }
4227 continue;
4228 }
4229
4230 /*
4231 * Some characters have to be escaped with CTRL-V to
4232 * prevent them from misinterpreted in DoOneCmd().
4233 * A space, Tab and '"' has to be escaped with a backslash to
4234 * prevent it to be misinterpreted in do_set().
4235 * A space has to be escaped with a CTRL-V when it's at the start of a
4236 * ":map" rhs.
4237 * A '<' has to be escaped with a CTRL-V to prevent it being
4238 * interpreted as the start of a special key name.
4239 * A space in the lhs of a :map needs a CTRL-V.
4240 */
4241 if (what == 2 && (ascii_iswhite(c) || c == '"' || c == '\\')) {
4242 if (putc('\\', fd) < 0)
4243 return FAIL;
4244 } else if (c < ' ' || c > '~' || c == '|'
4245 || (what == 0 && c == ' ')
4246 || (what == 1 && str == strstart && c == ' ')
4247 || (what != 2 && c == '<')) {
4248 if (putc(Ctrl_V, fd) < 0)
4249 return FAIL;
4250 }
4251 if (putc(c, fd) < 0)
4252 return FAIL;
4253 }
4254 return OK;
4255}
4256
4257/*
4258 * Check the string "keys" against the lhs of all mappings.
4259 * Return pointer to rhs of mapping (mapblock->m_str).
4260 * NULL when no mapping found.
4261 */
4262char_u *
4263check_map (
4264 char_u *keys,
4265 int mode,
4266 int exact, /* require exact match */
4267 int ign_mod, /* ignore preceding modifier */
4268 int abbr, /* do abbreviations */
4269 mapblock_T **mp_ptr, /* return: pointer to mapblock or NULL */
4270 int *local_ptr /* return: buffer-local mapping or NULL */
4271)
4272{
4273 int hash;
4274 int len, minlen;
4275 mapblock_T *mp;
4276 int local;
4277
4278 validate_maphash();
4279
4280 len = (int)STRLEN(keys);
4281 for (local = 1; local >= 0; --local)
4282 /* loop over all hash lists */
4283 for (hash = 0; hash < 256; ++hash) {
4284 if (abbr) {
4285 if (hash > 0) /* there is only one list. */
4286 break;
4287 if (local)
4288 mp = curbuf->b_first_abbr;
4289 else
4290 mp = first_abbr;
4291 } else if (local)
4292 mp = curbuf->b_maphash[hash];
4293 else
4294 mp = maphash[hash];
4295 for (; mp != NULL; mp = mp->m_next) {
4296 /* skip entries with wrong mode, wrong length and not matching
4297 * ones */
4298 if ((mp->m_mode & mode) && (!exact || mp->m_keylen == len)) {
4299 char_u *s = mp->m_keys;
4300 int keylen = mp->m_keylen;
4301 if (ign_mod && keylen >= 3
4302 && s[0] == K_SPECIAL && s[1] == KS_MODIFIER) {
4303 s += 3;
4304 keylen -= 3;
4305 }
4306 minlen = keylen < len ? keylen : len;
4307 if (STRNCMP(s, keys, minlen) == 0) {
4308 if (mp_ptr != NULL)
4309 *mp_ptr = mp;
4310 if (local_ptr != NULL)
4311 *local_ptr = local;
4312 return mp->m_str;
4313 }
4314 }
4315 }
4316 }
4317
4318 return NULL;
4319}
4320
4321
4322/*
4323 * Add a mapping "map" for mode "mode".
4324 * Need to put string in allocated memory, because do_map() will modify it.
4325 */
4326void add_map(char_u *map, int mode)
4327{
4328 char_u *s;
4329 char_u *cpo_save = p_cpo;
4330
4331 p_cpo = (char_u *)""; /* Allow <> notation */
4332 s = vim_strsave(map);
4333 (void)do_map(0, s, mode, FALSE);
4334 xfree(s);
4335 p_cpo = cpo_save;
4336}
4337
4338// Translate an internal mapping/abbreviation representation into the
4339// corresponding external one recognized by :map/:abbrev commands.
4340//
4341// This function is called when expanding mappings/abbreviations on the
4342// command-line.
4343//
4344// It uses a growarray to build the translation string since the latter can be
4345// wider than the original description. The caller has to free the string
4346// afterwards.
4347//
4348// Returns NULL when there is a problem.
4349static char_u * translate_mapping (
4350 char_u *str,
4351 int cpo_flags // Value of various flags present in &cpo
4352)
4353{
4354 garray_T ga;
4355 ga_init(&ga, 1, 40);
4356
4357 bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH);
4358
4359 for (; *str; ++str) {
4360 int c = *str;
4361 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
4362 int modifiers = 0;
4363 if (str[1] == KS_MODIFIER) {
4364 str++;
4365 modifiers = *++str;
4366 c = *++str;
4367 }
4368
4369 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) {
4370 c = TO_SPECIAL(str[1], str[2]);
4371 if (c == K_ZERO) {
4372 // display <Nul> as ^@
4373 c = NUL;
4374 }
4375 str += 2;
4376 }
4377 if (IS_SPECIAL(c) || modifiers) { // special key
4378 ga_concat(&ga, get_special_key_name(c, modifiers));
4379 continue; /* for (str) */
4380 }
4381 }
4382
4383 if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V
4384 || (c == '\\' && !cpo_bslash)) {
4385 ga_append(&ga, cpo_bslash ? Ctrl_V : '\\');
4386 }
4387
4388 if (c) {
4389 ga_append(&ga, (char)c);
4390 }
4391 }
4392 ga_append(&ga, NUL);
4393 return (char_u *)(ga.ga_data);
4394}
4395
4396static bool typebuf_match_len(const uint8_t *str, int *mlen)
4397{
4398 int i;
4399 for (i = 0; i < typebuf.tb_len && str[i]; i++) {
4400 if (str[i] != typebuf.tb_buf[typebuf.tb_off + i])
4401 break;
4402 }
4403 *mlen = i;
4404 return str[i] == NUL; // matched the whole string
4405}
4406
4407/// Retrieve the mapblock at the index either globally or for a certain buffer
4408///
4409/// @param index The index in the maphash[]
4410/// @param buf The buffer to get the maphash from. NULL for global
4411mapblock_T *get_maphash(int index, buf_T *buf)
4412 FUNC_ATTR_PURE
4413{
4414 if (index >= MAX_MAPHASH) {
4415 return NULL;
4416 }
4417
4418 return (buf == NULL) ? maphash[index] : buf->b_maphash[index];
4419}
4420
4421/// Get command argument for <Cmd> key
4422char_u * getcmdkeycmd(int promptc, void *cookie, int indent)
4423{
4424 garray_T line_ga;
4425 int c1 = -1, c2;
4426 int cmod = 0;
4427 bool aborted = false;
4428
4429 ga_init(&line_ga, 1, 32);
4430
4431 no_mapping++;
4432
4433 got_int = false;
4434 while (c1 != NUL && !aborted) {
4435 ga_grow(&line_ga, 32);
4436
4437 if (vgetorpeek(false) == NUL) {
4438 // incomplete <Cmd> is an error, because there is not much the user
4439 // could do in this state.
4440 EMSG(e_cmdmap_err);
4441 aborted = true;
4442 break;
4443 }
4444
4445 // Get one character at a time.
4446 c1 = vgetorpeek(true);
4447 // Get two extra bytes for special keys
4448 if (c1 == K_SPECIAL) {
4449 c1 = vgetorpeek(true); // no mapping for these chars
4450 c2 = vgetorpeek(true);
4451 if (c1 == KS_MODIFIER) {
4452 cmod = c2;
4453 continue;
4454 }
4455 c1 = TO_SPECIAL(c1, c2);
4456 }
4457
4458
4459 if (got_int) {
4460 aborted = true;
4461 } else if (c1 == '\r' || c1 == '\n') {
4462 c1 = NUL; // end the line
4463 } else if (c1 == ESC) {
4464 aborted = true;
4465 } else if (c1 == K_COMMAND) {
4466 // special case to give nicer error message
4467 EMSG(e_cmdmap_repeated);
4468 aborted = true;
4469 } else if (IS_SPECIAL(c1)) {
4470 if (c1 == K_SNR) {
4471 ga_append(&line_ga, (char)K_SPECIAL);
4472 ga_append(&line_ga, (char)KS_EXTRA);
4473 ga_append(&line_ga, (char)KE_SNR);
4474 } else {
4475 EMSG2(e_cmdmap_key, get_special_key_name(c1, cmod));
4476 aborted = true;
4477 }
4478 } else {
4479 ga_append(&line_ga, (char)c1);
4480 }
4481
4482 cmod = 0;
4483 }
4484
4485 no_mapping--;
4486
4487 if (aborted) {
4488 ga_clear(&line_ga);
4489 }
4490
4491 return (char_u *)line_ga.ga_data;
4492}
4493