Annotation of src/usr.bin/vim/getchar.c, Revision 1.1.1.1
1.1 downsj 1: /* $OpenBSD$ */
2: /* vi:set ts=4 sw=4:
3: *
4: * VIM - Vi IMproved by Bram Moolenaar
5: *
6: * Do ":help uganda" in Vim to read copying and usage conditions.
7: * Do ":help credits" in Vim to see a list of people who contributed.
8: */
9:
10: /*
11: * getchar.c
12: *
13: * functions related with getting a character from the user/mapping/redo/...
14: *
15: * manipulations with redo buffer and stuff buffer
16: * mappings and abbreviations
17: */
18:
19: #include "vim.h"
20: #include "globals.h"
21: #include "proto.h"
22: #include "option.h"
23:
24: /*
25: * structure used to store one block of the stuff/redo/macro buffers
26: */
27: struct bufblock
28: {
29: struct bufblock *b_next; /* pointer to next bufblock */
30: char_u b_str[1]; /* contents (actually longer) */
31: };
32:
33: #define MINIMAL_SIZE 20 /* minimal size for b_str */
34:
35: /*
36: * header used for the stuff buffer and the redo buffer
37: */
38: struct buffheader
39: {
40: struct bufblock bh_first; /* first (dummy) block of list */
41: struct bufblock *bh_curr; /* bufblock for appending */
42: int bh_index; /* index for reading */
43: int bh_space; /* space in bh_curr for appending */
44: };
45:
46: static struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
47: static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
48: static struct buffheader old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
49: static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
50:
51: /*
52: * when block_redo is TRUE redo buffer will not be changed
53: * used by edit() to repeat insertions and 'V' command for redoing
54: */
55: static int block_redo = FALSE;
56:
57: /*
58: * structure used for mapping
59: */
60: struct mapblock
61: {
62: struct mapblock *m_next; /* next mapblock */
63: char_u *m_keys; /* mapped from */
64: int m_keylen; /* strlen(m_keys) */
65: char_u *m_str; /* mapped to */
66: int m_mode; /* valid mode */
67: int m_noremap; /* if non-zero no re-mapping for m_str */
68: };
69:
70: static struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
71: /* first dummy entry in maplist */
72:
73: /*
74: * variables used by vgetorpeek() and flush_buffers()
75: *
76: * typebuf[] contains all characters that are not consumed yet.
77: * typebuf[typeoff] is the first valid character in typebuf[].
78: * typebuf[typeoff + typelen - 1] is the last valid char.
79: * typebuf[typeoff + typelen] must be NUL.
80: * The part in front may contain the result of mappings, abbreviations and
81: * @a commands. The length of this part is typemaplen.
82: * After it are characters that come from the terminal.
83: * no_abbr_cnt is the number of characters in typebuf that should not be
84: * considered for abbreviations.
85: * Some parts of typebuf may not be mapped. These parts are remembered in
86: * noremapbuf, which is the same length as typebuf and contains TRUE for the
87: * characters that are not to be remapped. noremapbuf[typeoff] is the first
88: * valid flag.
89: * (typebuf has been put in globals.h, because check_termcode() needs it).
90: */
91: static char_u *noremapbuf = NULL; /* flags for typeahead characters */
92: #define TYPELEN_INIT (3 * (MAXMAPLEN + 3))
93: static char_u typebuf_init[TYPELEN_INIT]; /* initial typebuf */
94: static char_u noremapbuf_init[TYPELEN_INIT]; /* initial noremapbuf */
95:
96: static int typemaplen = 0; /* nr of mapped characters in typebuf */
97: static int no_abbr_cnt = 0; /* nr of chars without abbrev. in typebuf */
98: static int last_recorded_len = 0; /* number of last recorded chars */
99:
100: static void free_buff __ARGS((struct buffheader *));
101: static char_u *get_bufcont __ARGS((struct buffheader *, int));
102: static void add_buff __ARGS((struct buffheader *, char_u *));
103: static void add_num_buff __ARGS((struct buffheader *, long));
104: static void add_char_buff __ARGS((struct buffheader *, int));
105: static int read_stuff __ARGS((int));
106: static void start_stuff __ARGS((void));
107: static int read_redo __ARGS((int, int));
108: static void copy_redo __ARGS((int));
109: static void init_typebuf __ARGS((void));
110: static void gotchars __ARGS((char_u *, int));
111: static int vgetorpeek __ARGS((int));
112: static int inchar __ARGS((char_u *, int, long));
113: static void map_free __ARGS((struct mapblock *));
114: static void showmap __ARGS((struct mapblock *));
115:
116: /*
117: * free and clear a buffer
118: */
119: static void
120: free_buff(buf)
121: struct buffheader *buf;
122: {
123: register struct bufblock *p, *np;
124:
125: for (p = buf->bh_first.b_next; p != NULL; p = np)
126: {
127: np = p->b_next;
128: vim_free(p);
129: }
130: buf->bh_first.b_next = NULL;
131: }
132:
133: /*
134: * return the contents of a buffer as a single string
135: */
136: static char_u *
137: get_bufcont(buffer, dozero)
138: struct buffheader *buffer;
139: int dozero; /* count == zero is not an error */
140: {
141: long_u count = 0;
142: char_u *p = NULL;
143: char_u *p2;
144: char_u *str;
145: struct bufblock *bp;
146:
147: /* compute the total length of the string */
148: for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
149: count += STRLEN(bp->b_str);
150:
151: if ((count || dozero) && (p = lalloc(count + 1, TRUE)) != NULL)
152: {
153: p2 = p;
154: for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
155: for (str = bp->b_str; *str; )
156: *p2++ = *str++;
157: *p2 = NUL;
158: }
159: return (p);
160: }
161:
162: /*
163: * return the contents of the record buffer as a single string
164: * and clear the record buffer
165: */
166: char_u *
167: get_recorded()
168: {
169: char_u *p;
170: size_t len;
171:
172: p = get_bufcont(&recordbuff, TRUE);
173: free_buff(&recordbuff);
174: /*
175: * Remove the characters that were added the last time, these must be the
176: * (possibly mapped) characters that stopped recording.
177: */
178: len = STRLEN(p);
179: if ((int)len >= last_recorded_len)
180: p[len - last_recorded_len] = NUL;
181: return (p);
182: }
183:
184: /*
185: * return the contents of the redo buffer as a single string
186: */
187: char_u *
188: get_inserted()
189: {
190: return(get_bufcont(&redobuff, FALSE));
191: }
192:
193: /*
194: * add string "s" after the current block of buffer "buf"
195: */
196: static void
197: add_buff(buf, s)
198: register struct buffheader *buf;
199: char_u *s;
200: {
201: struct bufblock *p;
202: long_u n;
203: long_u len;
204:
205: if ((n = STRLEN(s)) == 0) /* don't add empty strings */
206: return;
207:
208: if (buf->bh_first.b_next == NULL) /* first add to list */
209: {
210: buf->bh_space = 0;
211: buf->bh_curr = &(buf->bh_first);
212: }
213: else if (buf->bh_curr == NULL) /* buffer has already been read */
214: {
215: EMSG("Add to read buffer");
216: return;
217: }
218: else if (buf->bh_index != 0)
219: STRCPY(buf->bh_first.b_next->b_str,
220: buf->bh_first.b_next->b_str + buf->bh_index);
221: buf->bh_index = 0;
222:
223: if (buf->bh_space >= (int)n)
224: {
225: strcat((char *)buf->bh_curr->b_str, (char *)s);
226: buf->bh_space -= n;
227: }
228: else
229: {
230: if (n < MINIMAL_SIZE)
231: len = MINIMAL_SIZE;
232: else
233: len = n;
234: p = (struct bufblock *)lalloc((long_u)(sizeof(struct bufblock) + len), TRUE);
235: if (p == NULL)
236: return; /* no space, just forget it */
237: buf->bh_space = len - n;
238: STRCPY(p->b_str, s);
239:
240: p->b_next = buf->bh_curr->b_next;
241: buf->bh_curr->b_next = p;
242: buf->bh_curr = p;
243: }
244: return;
245: }
246:
247: static void
248: add_num_buff(buf, n)
249: struct buffheader *buf;
250: long n;
251: {
252: char_u number[32];
253:
254: sprintf((char *)number, "%ld", n);
255: add_buff(buf, number);
256: }
257:
258: static void
259: add_char_buff(buf, c)
260: struct buffheader *buf;
261: int c;
262: {
263: char_u temp[4];
264:
265: /*
266: * translate special key code into three byte sequence
267: */
268: if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL)
269: {
270: temp[0] = K_SPECIAL;
271: temp[1] = K_SECOND(c);
272: temp[2] = K_THIRD(c);
273: temp[3] = NUL;
274: }
275: else
276: {
277: temp[0] = c;
278: temp[1] = NUL;
279: }
280: add_buff(buf, temp);
281: }
282:
283: /*
284: * get one character from the stuff buffer
285: * If advance == TRUE go to the next char.
286: */
287: static int
288: read_stuff(advance)
289: int advance;
290: {
291: register char_u c;
292: register struct bufblock *curr;
293:
294:
295: if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */
296: return NUL;
297:
298: curr = stuffbuff.bh_first.b_next;
299: c = curr->b_str[stuffbuff.bh_index];
300:
301: if (advance)
302: {
303: if (curr->b_str[++stuffbuff.bh_index] == NUL)
304: {
305: stuffbuff.bh_first.b_next = curr->b_next;
306: vim_free(curr);
307: stuffbuff.bh_index = 0;
308: }
309: }
310: return c;
311: }
312:
313: /*
314: * prepare stuff buffer for reading (if it contains something)
315: */
316: static void
317: start_stuff()
318: {
319: if (stuffbuff.bh_first.b_next != NULL)
320: {
321: stuffbuff.bh_curr = &(stuffbuff.bh_first);
322: stuffbuff.bh_space = 0;
323: }
324: }
325:
326: /*
327: * check if the stuff buffer is empty
328: */
329: int
330: stuff_empty()
331: {
332: return (stuffbuff.bh_first.b_next == NULL);
333: }
334:
335: /*
336: * Remove the contents of the stuff buffer and the mapped characters in the
337: * typeahead buffer (used in case of an error). If 'typeahead' is true,
338: * flush all typeahead characters (used when interrupted by a CTRL-C).
339: */
340: void
341: flush_buffers(typeahead)
342: int typeahead;
343: {
344: init_typebuf();
345:
346: start_stuff();
347: while (read_stuff(TRUE) != NUL)
348: ;
349:
350: if (typeahead) /* remove all typeahead */
351: {
352: /*
353: * We have to get all characters, because we may delete the first
354: * part of an escape sequence.
355: * In an xterm we get one char at a time and we have to get them
356: * all.
357: */
358: while (inchar(typebuf, MAXMAPLEN, 10L))
359: ;
360: typeoff = MAXMAPLEN;
361: typelen = 0;
362: }
363: else /* remove mapped characters only */
364: {
365: typeoff += typemaplen;
366: typelen -= typemaplen;
367: }
368: typemaplen = 0;
369: no_abbr_cnt = 0;
370: }
371:
372: /*
373: * The previous contents of the redo buffer is kept in old_redobuffer.
374: * This is used for the CTRL-O <.> command in insert mode.
375: */
376: void
377: ResetRedobuff()
378: {
379: if (!block_redo)
380: {
381: free_buff(&old_redobuff);
382: old_redobuff = redobuff;
383: redobuff.bh_first.b_next = NULL;
384: }
385: }
386:
387: void
388: AppendToRedobuff(s)
389: char_u *s;
390: {
391: if (!block_redo)
392: add_buff(&redobuff, s);
393: }
394:
395: void
396: AppendCharToRedobuff(c)
397: int c;
398: {
399: if (!block_redo)
400: add_char_buff(&redobuff, c);
401: }
402:
403: void
404: AppendNumberToRedobuff(n)
405: long n;
406: {
407: if (!block_redo)
408: add_num_buff(&redobuff, n);
409: }
410:
411: void
412: stuffReadbuff(s)
413: char_u *s;
414: {
415: add_buff(&stuffbuff, s);
416: }
417:
418: void
419: stuffcharReadbuff(c)
420: int c;
421: {
422: add_char_buff(&stuffbuff, c);
423: }
424:
425: void
426: stuffnumReadbuff(n)
427: long n;
428: {
429: add_num_buff(&stuffbuff, n);
430: }
431:
432: /*
433: * Read a character from the redo buffer.
434: * The redo buffer is left as it is.
435: * if init is TRUE, prepare for redo, return FAIL if nothing to redo, OK
436: * otherwise
437: * if old is TRUE, use old_redobuff instead of redobuff
438: */
439: static int
440: read_redo(init, old_redo)
441: int init;
442: int old_redo;
443: {
444: static struct bufblock *bp;
445: static char_u *p;
446: int c;
447:
448: if (init)
449: {
450: if (old_redo)
451: bp = old_redobuff.bh_first.b_next;
452: else
453: bp = redobuff.bh_first.b_next;
454: if (bp == NULL)
455: return FAIL;
456: p = bp->b_str;
457: return OK;
458: }
459: if ((c = *p) != NUL)
460: {
461: if (c == K_SPECIAL)
462: {
463: c = TO_SPECIAL(p[1], p[2]);
464: p += 2;
465: }
466: if (*++p == NUL && bp->b_next != NULL)
467: {
468: bp = bp->b_next;
469: p = bp->b_str;
470: }
471: }
472: return c;
473: }
474:
475: /*
476: * copy the rest of the redo buffer into the stuff buffer (could be done faster)
477: * if old_redo is TRUE, use old_redobuff instead of redobuff
478: */
479: static void
480: copy_redo(old_redo)
481: int old_redo;
482: {
483: register int c;
484:
485: while ((c = read_redo(FALSE, old_redo)) != NUL)
486: stuffcharReadbuff(c);
487: }
488:
489: /*
490: * Stuff the redo buffer into the stuffbuff.
491: * Insert the redo count into the command.
492: * If 'old_redo' is TRUE, the last but one command is repeated
493: * instead of the last command (inserting text). This is used for
494: * CTRL-O <.> in insert mode
495: *
496: * return FAIL for failure, OK otherwise
497: */
498: int
499: start_redo(count, old_redo)
500: long count;
501: int old_redo;
502: {
503: register int c;
504:
505: if (read_redo(TRUE, old_redo) == FAIL) /* init the pointers; return if nothing to redo */
506: return FAIL;
507:
508: c = read_redo(FALSE, old_redo);
509:
510: /* copy the buffer name, if present */
511: if (c == '"')
512: {
513: add_buff(&stuffbuff, (char_u *)"\"");
514: c = read_redo(FALSE, old_redo);
515:
516: /* if a numbered buffer is used, increment the number */
517: if (c >= '1' && c < '9')
518: ++c;
519: add_char_buff(&stuffbuff, c);
520: c = read_redo(FALSE, old_redo);
521: }
522:
523: if (c == 'v') /* redo Visual */
524: {
525: VIsual = curwin->w_cursor;
526: VIsual_active = TRUE;
527: redo_VIsual_busy = TRUE;
528: c = read_redo(FALSE, old_redo);
529: }
530:
531: /* try to enter the count (in place of a previous count) */
532: if (count)
533: {
534: while (isdigit(c)) /* skip "old" count */
535: c = read_redo(FALSE, old_redo);
536: add_num_buff(&stuffbuff, count);
537: }
538:
539: /* copy from the redo buffer into the stuff buffer */
540: add_char_buff(&stuffbuff, c);
541: copy_redo(old_redo);
542: return OK;
543: }
544:
545: /*
546: * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
547: * the redo buffer into the stuffbuff.
548: * return FAIL for failure, OK otherwise
549: */
550: int
551: start_redo_ins()
552: {
553: register int c;
554:
555: if (read_redo(TRUE, FALSE) == FAIL)
556: return FAIL;
557: start_stuff();
558:
559: /* skip the count and the command character */
560: while ((c = read_redo(FALSE, FALSE)) != NUL)
561: {
562: c = TO_UPPER(c);
563: if (vim_strchr((char_u *)"AIRO", c) != NULL)
564: {
565: if (c == 'O')
566: stuffReadbuff(NL_STR);
567: break;
568: }
569: }
570:
571: /* copy the typed text from the redo buffer into the stuff buffer */
572: copy_redo(FALSE);
573: block_redo = TRUE;
574: return OK;
575: }
576:
577: void
578: set_redo_ins()
579: {
580: block_redo = TRUE;
581: }
582:
583: void
584: stop_redo_ins()
585: {
586: block_redo = FALSE;
587: }
588:
589: /*
590: * Initialize typebuf to point to typebuf_init.
591: * Alloc() cannot be used here: In out-of-memory situations it would
592: * be impossible to type anything.
593: */
594: static void
595: init_typebuf()
596: {
597: if (typebuf == NULL)
598: {
599: typebuf = typebuf_init;
600: noremapbuf = noremapbuf_init;
601: typebuflen = TYPELEN_INIT;
602: typelen = 0;
603: typeoff = 0;
604: }
605: }
606:
607: /*
608: * insert a string in position 'offset' in the typeahead buffer (for "@r"
609: * and ":normal" command, vgetorpeek() and check_termcode())
610: *
611: * If noremap is 0, new string can be mapped again.
612: * If noremap is -1, new string cannot be mapped again.
613: * If noremap is >0, that many characters of the new string cannot be mapped.
614: *
615: * If nottyped is TRUE, the string does not return KeyTyped (don't use when
616: * offset is non-zero!).
617: *
618: * return FAIL for failure, OK otherwise
619: */
620: int
621: ins_typebuf(str, noremap, offset, nottyped)
622: char_u *str;
623: int noremap;
624: int offset;
625: int nottyped;
626: {
627: register char_u *s1, *s2;
628: register int newlen;
629: register int addlen;
630: register int i;
631: register int newoff;
632:
633: init_typebuf();
634:
635: addlen = STRLEN(str);
636: /*
637: * Easy case: there is room in front of typebuf[typeoff]
638: */
639: if (offset == 0 && addlen <= typeoff)
640: {
641: typeoff -= addlen;
642: vim_memmove(typebuf + typeoff, str, (size_t)addlen);
643: }
644: /*
645: * Need to allocate new buffer.
646: * In typebuf there must always be room for MAXMAPLEN + 4 characters.
647: * We add some extra room to avoid having to allocate too often.
648: */
649: else
650: {
651: newoff = MAXMAPLEN + 4;
652: newlen = typelen + addlen + newoff + 2 * (MAXMAPLEN + 4);
653: if (newlen < 0) /* string is getting too long */
654: {
655: emsg(e_toocompl); /* also calls flush_buffers */
656: setcursor();
657: return FAIL;
658: }
659: s1 = alloc(newlen);
660: if (s1 == NULL) /* out of memory */
661: return FAIL;
662: s2 = alloc(newlen);
663: if (s2 == NULL) /* out of memory */
664: {
665: vim_free(s1);
666: return FAIL;
667: }
668: typebuflen = newlen;
669:
670: /* copy the old chars, before the insertion point */
671: vim_memmove(s1 + newoff, typebuf + typeoff, (size_t)offset);
672: /* copy the new chars */
673: vim_memmove(s1 + newoff + offset, str, (size_t)addlen);
674: /* copy the old chars, after the insertion point, including
675: * the NUL at the end */
676: vim_memmove(s1 + newoff + offset + addlen, typebuf + typeoff + offset,
677: (size_t)(typelen - offset + 1));
678: if (typebuf != typebuf_init)
679: vim_free(typebuf);
680: typebuf = s1;
681:
682: vim_memmove(s2 + newoff, noremapbuf + typeoff, (size_t)offset);
683: vim_memmove(s2 + newoff + offset + addlen,
684: noremapbuf + typeoff + offset, (size_t)(typelen - offset));
685: if (noremapbuf != noremapbuf_init)
686: vim_free(noremapbuf);
687: noremapbuf = s2;
688:
689: typeoff = newoff;
690: }
691: typelen += addlen;
692:
693: /*
694: * Adjust noremapbuf[] for the new characters:
695: * If noremap < 0: all the new characters are flagged not remappable
696: * If noremap == 0: all the new characters are flagged mappable
697: * If noremap > 0: 'noremap' characters are flagged not remappable, the
698: * rest mappable
699: */
700: if (noremap < 0) /* length not specified */
701: noremap = addlen;
702: for (i = 0; i < addlen; ++i)
703: noremapbuf[typeoff + i + offset] = (noremap-- > 0);
704:
705: /* this is only correct for offset == 0! */
706: if (nottyped) /* the inserted string is not typed */
707: typemaplen += addlen;
708: if (no_abbr_cnt && offset == 0) /* and not used for abbreviations */
709: no_abbr_cnt += addlen;
710:
711: return OK;
712: }
713:
714: /*
715: * Return TRUE if there are no characters in the typeahead buffer that have
716: * not been typed (result from a mapping or come from ":normal").
717: */
718: int
719: typebuf_typed()
720: {
721: return typemaplen == 0;
722: }
723:
724: /*
725: * remove "len" characters from typebuf[typeoff + offset]
726: */
727: void
728: del_typebuf(len, offset)
729: int len;
730: int offset;
731: {
732: int i;
733:
734: typelen -= len;
735: /*
736: * Easy case: Just increase typeoff.
737: */
738: if (offset == 0 && typebuflen - (typeoff + len) >= MAXMAPLEN + 3)
739: typeoff += len;
740: /*
741: * Have to move the characters in typebuf[] and noremapbuf[]
742: */
743: else
744: {
745: i = typeoff + offset;
746: /*
747: * Leave some extra room at the end to avoid reallocation.
748: */
749: if (typeoff > MAXMAPLEN)
750: {
751: vim_memmove(typebuf + MAXMAPLEN, typebuf + typeoff, (size_t)offset);
752: vim_memmove(noremapbuf + MAXMAPLEN, noremapbuf + typeoff,
753: (size_t)offset);
754: typeoff = MAXMAPLEN;
755: }
756: /* adjust typebuf (include the NUL at the end) */
757: vim_memmove(typebuf + typeoff + offset, typebuf + i + len,
758: (size_t)(typelen - offset + 1));
759: /* adjust noremapbuf[] */
760: vim_memmove(noremapbuf + typeoff + offset, noremapbuf + i + len,
761: (size_t)(typelen - offset));
762: }
763:
764: if (typemaplen > offset) /* adjust typemaplen */
765: {
766: if (typemaplen < offset + len)
767: typemaplen = offset;
768: else
769: typemaplen -= len;
770: }
771: if (no_abbr_cnt > offset) /* adjust no_abbr_cnt */
772: {
773: if (no_abbr_cnt < offset + len)
774: no_abbr_cnt = offset;
775: else
776: no_abbr_cnt -= len;
777: }
778: }
779:
780: /*
781: * Write typed characters to script file.
782: * If recording is on put the character in the recordbuffer.
783: */
784: static void
785: gotchars(s, len)
786: char_u *s;
787: int len;
788: {
789: int c;
790: char_u buf[2];
791:
792: /* remember how many chars were last recorded */
793: if (Recording)
794: last_recorded_len += len;
795:
796: buf[1] = NUL;
797: while (len--)
798: {
799: c = *s++;
800: updatescript(c);
801:
802: if (Recording)
803: {
804: buf[0] = c;
805: add_buff(&recordbuff, buf);
806: }
807: }
808:
809: /*
810: * Do not sync in insert mode, unless cursor key has been used.
811: * Also don't sync while reading a script file.
812: */
813: if ((!(State & (INSERT + CMDLINE)) || arrow_used) &&
814: scriptin[curscript] == NULL)
815: u_sync();
816: }
817:
818: /*
819: * open new script file for ":so!" command
820: * return OK on success, FAIL on error
821: */
822: int
823: openscript(name)
824: char_u *name;
825: {
826: int oldcurscript;
827:
828: if (curscript + 1 == NSCRIPT)
829: {
830: emsg(e_nesting);
831: return FAIL;
832: }
833: else
834: {
835: if (scriptin[curscript] != NULL) /* already reading script */
836: ++curscript;
837: /* use NameBuff for expanded name */
838: expand_env(name, NameBuff, MAXPATHL);
839: if ((scriptin[curscript] = fopen((char *)NameBuff, READBIN)) == NULL)
840: {
841: emsg2(e_notopen, name);
842: if (curscript)
843: --curscript;
844: return FAIL;
845: }
846: /*
847: * With command ":g/pat/so! file" we have to execute the
848: * commands from the file now.
849: */
850: if (global_busy)
851: {
852: State = NORMAL;
853: oldcurscript = curscript;
854: do
855: {
856: normal();
857: vpeekc(); /* check for end of file */
858: }
859: while (scriptin[oldcurscript]);
860: State = CMDLINE;
861: }
862: }
863: return OK;
864: }
865:
866: /*
867: * updatescipt() is called when a character can be written into the script file
868: * or when we have waited some time for a character (c == 0)
869: *
870: * All the changed memfiles are synced if c == 0 or when the number of typed
871: * characters reaches 'updatecount' and 'updatecount' is non-zero.
872: */
873: void
874: updatescript(c)
875: int c;
876: {
877: static int count = 0;
878:
879: if (c && scriptout)
880: putc(c, scriptout);
881: if (c == 0 || (p_uc > 0 && ++count >= p_uc))
882: {
883: ml_sync_all(c == 0, TRUE);
884: count = 0;
885: }
886: }
887:
888: #define K_NEEDMORET -1 /* keylen value for incomplete key-code */
889: #define M_NEEDMORET -2 /* keylen value for incomplete mapping */
890:
891: static int old_char = -1; /* ungotten character */
892:
893: int
894: vgetc()
895: {
896: int c, c2;
897:
898: mod_mask = 0x0;
899: last_recorded_len = 0;
900: for (;;) /* this is done twice if there are modifiers */
901: {
902: if (mod_mask) /* no mapping after modifier has been read */
903: {
904: ++no_mapping;
905: ++allow_keys;
906: }
907: c = vgetorpeek(TRUE);
908: if (mod_mask)
909: {
910: --no_mapping;
911: --allow_keys;
912: }
913:
914: /* Get two extra bytes for special keys */
915: if (c == K_SPECIAL)
916: {
917: ++no_mapping;
918: c2 = vgetorpeek(TRUE); /* no mapping for these chars */
919: c = vgetorpeek(TRUE);
920: --no_mapping;
921: if (c2 == KS_MODIFIER)
922: {
923: mod_mask = c;
924: continue;
925: }
926: c = TO_SPECIAL(c2, c);
927: }
928: #ifdef MSDOS
929: /*
930: * If K_NUL was typed, it is replaced by K_NUL, 3 in mch_inchar().
931: * Delete the 3 here.
932: */
933: else if (c == K_NUL && vpeekc() == 3)
934: (void)vgetorpeek(TRUE);
935: #endif
936:
937: return check_shifted_spec_key(c);
938: }
939: }
940:
941: int
942: vpeekc()
943: {
944: return (vgetorpeek(FALSE));
945: }
946:
947: /*
948: * Call vpeekc() without causing anything to be mapped.
949: * Return TRUE if a character is available, FALSE otherwise.
950: */
951: int
952: char_avail()
953: {
954: int retval;
955:
956: ++no_mapping;
957: retval = vgetorpeek(FALSE);
958: --no_mapping;
959: return (retval != NUL);
960: }
961:
962: void
963: vungetc(c) /* unget one character (can only be done once!) */
964: int c;
965: {
966: old_char = c;
967: }
968:
969: /*
970: * get a character: 1. from a previously ungotten character
971: * 2. from the stuffbuffer
972: * 3. from the typeahead buffer
973: * 4. from the user
974: *
975: * if "advance" is TRUE (vgetc()):
976: * really get the character.
977: * KeyTyped is set to TRUE in the case the user typed the key.
978: * KeyStuffed is TRUE if the character comes from the stuff buffer.
979: * if "advance" is FALSE (vpeekc()):
980: * just look whether there is a character available.
981: */
982:
983: static int
984: vgetorpeek(advance)
985: int advance;
986: {
987: register int c, c1;
988: int keylen = 0; /* init for gcc */
989: #ifdef AMIGA
990: char_u *s;
991: #endif
992: register struct mapblock *mp;
993: int timedout = FALSE; /* waited for more than 1 second
994: for mapping to complete */
995: int mapdepth = 0; /* check for recursive mapping */
996: int mode_deleted = FALSE; /* set when mode has been deleted */
997: int local_State;
998: register int mlen;
999: int max_mlen;
1000: int i;
1001: #ifdef USE_GUI
1002: int idx;
1003: #endif
1004:
1005: /*
1006: * VISUAL state is never set, it is used only here, therefore a check is
1007: * made if NORMAL state is actually VISUAL state.
1008: */
1009: local_State = State;
1010: if ((State & NORMAL) && VIsual_active)
1011: local_State = VISUAL;
1012:
1013: /*
1014: * get a character: 1. from a previously ungotten character
1015: */
1016: if (old_char >= 0)
1017: {
1018: c = old_char;
1019: if (advance)
1020: old_char = -1;
1021: return c;
1022: }
1023:
1024: if (advance)
1025: KeyStuffed = FALSE;
1026:
1027: init_typebuf();
1028: start_stuff();
1029: if (advance && typemaplen == 0)
1030: Exec_reg = FALSE;
1031: do
1032: {
1033: /*
1034: * get a character: 2. from the stuffbuffer
1035: */
1036: c = read_stuff(advance);
1037: if (c != NUL && !got_int)
1038: {
1039: if (advance)
1040: {
1041: KeyTyped = FALSE;
1042: KeyStuffed = TRUE;
1043: }
1044: if (no_abbr_cnt == 0)
1045: no_abbr_cnt = 1; /* no abbreviations now */
1046: }
1047: else
1048: {
1049: /*
1050: * Loop until we either find a matching mapped key, or we
1051: * are sure that it is not a mapped key.
1052: * If a mapped key sequence is found we go back to the start to
1053: * try re-mapping.
1054: */
1055:
1056: for (;;)
1057: {
1058: mch_breakcheck(); /* check for CTRL-C */
1059: if (got_int)
1060: {
1061: c = inchar(typebuf, MAXMAPLEN, 0L); /* flush all input */
1062: /*
1063: * If inchar returns TRUE (script file was active) or we are
1064: * inside a mapping, get out of insert mode.
1065: * Otherwise we behave like having gotten a CTRL-C.
1066: * As a result typing CTRL-C in insert mode will
1067: * really insert a CTRL-C.
1068: */
1069: if ((c || typemaplen) && (State & (INSERT + CMDLINE)))
1070: c = ESC;
1071: else
1072: c = Ctrl('C');
1073: flush_buffers(TRUE); /* flush all typeahead */
1074: break;
1075: }
1076: else if (typelen > 0) /* check for a mappable key sequence */
1077: {
1078: /*
1079: * walk through the maplist until we find an
1080: * entry that matches.
1081: *
1082: * Don't look for mappings if:
1083: * - timed out
1084: * - no_mapping set: mapping disabled (e.g. for CTRL-V)
1085: * - typebuf[typeoff] should not be remapped
1086: * - in insert or cmdline mode and 'paste' option set
1087: * - waiting for "hit return to continue" and CR or SPACE
1088: * typed
1089: * - waiting for a char with --more--
1090: * - in Ctrl-X mode, and we get a valid char for that mode
1091: */
1092: mp = NULL;
1093: max_mlen = 0;
1094: if (!timedout && no_mapping == 0 && (typemaplen == 0 ||
1095: (p_remap && noremapbuf[typeoff] == FALSE))
1096: && !(p_paste && (State & (INSERT + CMDLINE)))
1097: && !(State == HITRETURN && (typebuf[typeoff] == CR
1098: || typebuf[typeoff] == ' '))
1099: && State != ASKMORE
1100: #ifdef INSERT_EXPAND
1101: && !(ctrl_x_mode && is_ctrl_x_key(typebuf[typeoff]))
1102: #endif
1103: )
1104: {
1105: c1 = typebuf[typeoff];
1106: #ifdef HAVE_LANGMAP
1107: LANGMAP_ADJUST(c1, TRUE);
1108: #endif
1109: for (mp = maplist.m_next; mp; mp = mp->m_next)
1110: {
1111: /*
1112: * Only consider an entry if
1113: * - the first character matches and
1114: * - it is not an abbreviation and
1115: * - it is for the current state
1116: */
1117: if ( mp->m_keys[0] == c1 &&
1118: !(mp->m_mode & ABBREV) &&
1119: (mp->m_mode & local_State))
1120: {
1121: int n;
1122: #ifdef HAVE_LANGMAP
1123: int c2;
1124: #endif
1125:
1126: /* find the match length of this mapping */
1127: for (mlen = 1; mlen < typelen; ++mlen)
1128: {
1129: #ifdef HAVE_LANGMAP
1130: c2 = typebuf[typeoff + mlen];
1131: LANGMAP_ADJUST(c2, TRUE);
1132: if (mp->m_keys[mlen] != c2)
1133: #else
1134: if (mp->m_keys[mlen] !=
1135: typebuf[typeoff + mlen])
1136: #endif
1137: break;
1138: }
1139:
1140: /* if one of the typed keys cannot be
1141: * remapped, skip the entry */
1142: for (n = 0; n < mlen; ++n)
1143: if (noremapbuf[typeoff + n] == TRUE)
1144: break;
1145: if (n != mlen)
1146: continue;
1147:
1148: /* (partly) match found */
1149: keylen = mp->m_keylen;
1150: if (mlen == (keylen > typelen ?
1151: typelen : keylen))
1152: {
1153: /* partial match, need more chars */
1154: if (keylen > typelen)
1155: keylen = M_NEEDMORET;
1156: break;
1157: }
1158: /* no match, may have to check for
1159: * termcode at next character */
1160: if (max_mlen < mlen)
1161: max_mlen = mlen;
1162: }
1163: }
1164: }
1165: if (mp == NULL) /* no match found */
1166: {
1167: /*
1168: * check if we have a terminal code, when
1169: * mapping is allowed,
1170: * keys have not been mapped,
1171: * and not an ESC sequence, not in insert mode or
1172: * p_ek is on,
1173: * and when not timed out,
1174: */
1175: if ((no_mapping == 0 || allow_keys != 0) &&
1176: (typemaplen == 0 ||
1177: (p_remap && noremapbuf[typeoff] == FALSE)) &&
1178: !timedout)
1179: keylen = check_termcode(max_mlen + 1);
1180: else
1181: keylen = 0;
1182: if (keylen == 0) /* no matching terminal code */
1183: {
1184: #ifdef AMIGA /* check for window bounds report */
1185: if (typemaplen == 0 &&
1186: (typebuf[typeoff] & 0xff) == CSI)
1187: {
1188: for (s = typebuf + typeoff + 1;
1189: s < typebuf + typeoff + typelen &&
1190: (isdigit(*s) || *s == ';' || *s == ' ');
1191: ++s)
1192: ;
1193: if (*s == 'r' || *s == '|') /* found one */
1194: {
1195: del_typebuf((int)(s + 1 -
1196: (typebuf + typeoff)), 0);
1197: /* get size and redraw screen */
1198: set_winsize(0, 0, FALSE);
1199: continue;
1200: }
1201: if (*s == NUL) /* need more characters */
1202: keylen = K_NEEDMORET;
1203: }
1204: if (keylen >= 0)
1205: #endif
1206: {
1207: /*
1208: * get a character: 3. from the typeahead buffer
1209: */
1210: c = typebuf[typeoff] & 255;
1211: if (advance) /* remove chars from typebuf */
1212: {
1213: if (typemaplen)
1214: KeyTyped = FALSE;
1215: else
1216: {
1217: KeyTyped = TRUE;
1218: /* write char to script file(s) */
1219: gotchars(typebuf + typeoff, 1);
1220: }
1221: del_typebuf(1, 0);
1222: }
1223: break; /* got character, break for loop */
1224: }
1225: }
1226: if (keylen > 0) /* full matching terminal code */
1227: {
1228: #ifdef USE_GUI
1229: if (typebuf[typeoff] == K_SPECIAL &&
1230: typebuf[typeoff + 1] == KS_MENU)
1231: {
1232: /*
1233: * Using a menu causes a break in undo!
1234: */
1235: u_sync();
1236: del_typebuf(3, 0);
1237: idx = gui_get_menu_index(current_menu,
1238: local_State);
1239: if (idx != MENU_INDEX_INVALID)
1240: {
1241: ins_typebuf(current_menu->strings[idx],
1242: current_menu->noremap[idx] ? -1 : 0,
1243: 0, TRUE);
1244: }
1245: }
1246: #endif /* USE_GUI */
1247: continue; /* try mapping again */
1248: }
1249:
1250: /* partial match: get some more characters */
1251: keylen = K_NEEDMORET;
1252: }
1253: /* complete match */
1254: if (keylen >= 0 && keylen <= typelen)
1255: {
1256: /* write chars to script file(s) */
1257: if (keylen > typemaplen)
1258: gotchars(typebuf + typeoff + typemaplen,
1259: keylen - typemaplen);
1260:
1261: del_typebuf(keylen, 0); /* remove the mapped keys */
1262:
1263: /*
1264: * Put the replacement string in front of mapstr.
1265: * The depth check catches ":map x y" and ":map y x".
1266: */
1267: if (++mapdepth >= p_mmd)
1268: {
1269: EMSG("recursive mapping");
1270: if (State == CMDLINE)
1271: redrawcmdline();
1272: else
1273: setcursor();
1274: flush_buffers(FALSE);
1275: mapdepth = 0; /* for next one */
1276: c = -1;
1277: break;
1278: }
1279: /*
1280: * Insert the 'to' part in the typebuf.
1281: * If 'from' field is the same as the start of the
1282: * 'to' field, don't remap this part.
1283: * If m_noremap is set, don't remap the whole 'to'
1284: * part.
1285: */
1286: if (ins_typebuf(mp->m_str, mp->m_noremap ? -1 :
1287: STRNCMP(mp->m_str, mp->m_keys,
1288: (size_t)keylen) ? 0 : keylen,
1289: 0, TRUE) == FAIL)
1290: {
1291: c = -1;
1292: break;
1293: }
1294: continue;
1295: }
1296: }
1297: /*
1298: * special case: if we get an <ESC> in insert mode and there
1299: * are no more characters at once, we pretend to go out of
1300: * insert mode. This prevents the one second delay after
1301: * typing an <ESC>. If we get something after all, we may
1302: * have to redisplay the mode. That the cursor is in the wrong
1303: * place does not matter.
1304: */
1305: c = 0;
1306: if (advance && typelen == 1 && typebuf[typeoff] == ESC &&
1307: !no_mapping && typemaplen == 0 && (State & INSERT) &&
1308: (p_timeout || (keylen == K_NEEDMORET && p_ttimeout)) &&
1309: (c = inchar(typebuf + typeoff + typelen, 3, 0L)) == 0)
1310: {
1311: if (p_smd)
1312: {
1313: delmode();
1314: mode_deleted = TRUE;
1315: }
1316: if (curwin->w_cursor.col != 0) /* move cursor one left if
1317: possible */
1318: {
1319: if (curwin->w_col)
1320: {
1321: if (did_ai)
1322: {
1323: /*
1324: * We are expecting to truncate the trailing
1325: * white-space, so find the last non-white
1326: * character -- webb
1327: */
1328: colnr_t col, vcol;
1329: char_u *ptr;
1330:
1331: col = vcol = curwin->w_col = 0;
1332: ptr = ml_get_curline();
1333: while (col < curwin->w_cursor.col)
1334: {
1335: if (!vim_iswhite(ptr[col]))
1336: curwin->w_col = vcol;
1337: vcol += lbr_chartabsize(ptr + col,
1338: (colnr_t)vcol);
1339: ++col;
1340: }
1341: if (curwin->w_p_nu)
1342: curwin->w_col += 8;
1343: }
1344: else
1345: --curwin->w_col;
1346: }
1347: else if (curwin->w_p_wrap && curwin->w_row)
1348: {
1349: --curwin->w_row;
1350: curwin->w_col = Columns - 1;
1351: }
1352: }
1353: setcursor();
1354: flushbuf();
1355: }
1356: typelen += c;
1357: /* buffer full, don't map */
1358: if (typelen >= typemaplen + MAXMAPLEN)
1359: {
1360: timedout = TRUE;
1361: continue;
1362: }
1363: /*
1364: * get a character: 4. from the user
1365: */
1366: /*
1367: * If we have a partial match (and are going to wait for more
1368: * input from the user), show the partially matched characters
1369: * to the user with showcmd -- webb.
1370: */
1371: i = 0;
1372: if (typelen > 0 && (State & (NORMAL | INSERT)) && advance)
1373: {
1374: push_showcmd();
1375: while (i < typelen)
1376: (void)add_to_showcmd(typebuf[typeoff + i++], TRUE);
1377: }
1378:
1379: c = inchar(typebuf + typeoff + typelen,
1380: typemaplen + MAXMAPLEN - typelen,
1381: !advance
1382: ? 0
1383: : ((typelen == 0 || !(p_timeout || (p_ttimeout &&
1384: keylen == K_NEEDMORET)))
1385: ? -1L
1386: : ((keylen == K_NEEDMORET && p_ttm >= 0)
1387: ? p_ttm
1388: : p_tm)));
1389:
1390: if (i)
1391: pop_showcmd();
1392:
1393: if (c <= NUL) /* no character available */
1394: {
1395: if (!advance)
1396: break;
1397: if (typelen) /* timed out */
1398: {
1399: timedout = TRUE;
1400: continue;
1401: }
1402: }
1403: else
1404: { /* allow mapping for just typed characters */
1405: while (typebuf[typeoff + typelen] != NUL)
1406: noremapbuf[typeoff + typelen++] = FALSE;
1407: }
1408: } /* for (;;) */
1409: } /* if (!character from stuffbuf) */
1410:
1411: /* if advance is FALSE don't loop on NULs */
1412: } while (c < 0 || (advance && c == NUL));
1413:
1414: /*
1415: * The "INSERT" message is taken care of here:
1416: * if we return an ESC to exit insert mode, the message is deleted
1417: * if we don't return an ESC but deleted the message before, redisplay it
1418: */
1419: if (p_smd && (State & INSERT))
1420: {
1421: if (c == ESC && !mode_deleted && !no_mapping)
1422: delmode();
1423: else if (c != ESC && mode_deleted)
1424: showmode();
1425: }
1426:
1427: return c;
1428: }
1429:
1430: /*
1431: * inchar() - get one character from
1432: * 1. a scriptfile
1433: * 2. the keyboard
1434: *
1435: * As much characters as we can get (upto 'maxlen') are put in buf and
1436: * NUL terminated (buffer length must be 'maxlen' + 1).
1437: * Minimum for 'maxlen' is 3!!!!
1438: *
1439: * If we got an interrupt all input is read until none is available.
1440: *
1441: * If wait_time == 0 there is no waiting for the char.
1442: * If wait_time == n we wait for n msec for a character to arrive.
1443: * If wait_time == -1 we wait forever for a character to arrive.
1444: *
1445: * Return the number of obtained characters.
1446: */
1447:
1448: static int
1449: inchar(buf, maxlen, wait_time)
1450: char_u *buf;
1451: int maxlen;
1452: long wait_time; /* milli seconds */
1453: {
1454: int len = 0; /* init for GCC */
1455: int retesc = FALSE; /* return ESC with gotint */
1456: register int c;
1457: register int i;
1458:
1459: if (wait_time == -1L || wait_time > 100L) /* flush output before waiting */
1460: {
1461: cursor_on();
1462: flushbuf();
1463: }
1464: /*
1465: * Don't reset these when at the hit-return prompt, otherwise a endless
1466: * recursive loop may result (write error in swapfile, hit-return, timeout
1467: * on char wait, flush swapfile, write error....).
1468: */
1469: if (State != HITRETURN)
1470: {
1471: did_outofmem_msg = FALSE; /* display out of memory message (again) */
1472: did_swapwrite_msg = FALSE; /* display swap file write error again */
1473: }
1474: undo_off = FALSE; /* restart undo now */
1475:
1476: /*
1477: * first try script file
1478: * If interrupted: Stop reading script files.
1479: */
1480: c = -1;
1481: while (scriptin[curscript] != NULL && c < 0)
1482: {
1483: if (got_int || (c = getc(scriptin[curscript])) < 0) /* reached EOF */
1484: {
1485: /* when reading script file is interrupted, return an ESC to
1486: get back to normal mode */
1487: if (got_int)
1488: retesc = TRUE;
1489: fclose(scriptin[curscript]);
1490: scriptin[curscript] = NULL;
1491: if (curscript > 0)
1492: --curscript;
1493: }
1494: else
1495: {
1496: buf[0] = c;
1497: len = 1;
1498: }
1499: }
1500:
1501: if (c < 0) /* did not get a character from script */
1502: {
1503: /*
1504: * If we got an interrupt, skip all previously typed characters and
1505: * return TRUE if quit reading script file.
1506: */
1507: if (got_int) /* skip typed characters */
1508: {
1509: while (mch_inchar(buf, maxlen, 0L))
1510: ;
1511: return retesc;
1512: }
1513: /* fill up to a third of the buffer, because each character may be
1514: * tripled below */
1515: len = mch_inchar(buf, maxlen / 3, wait_time);
1516: }
1517:
1518: /*
1519: * Two characters are special: NUL and K_SPECIAL.
1520: * Replace NUL by K_SPECIAL KS_ZERO K_FILLER
1521: * Replace K_SPECIAL by K_SPECIAL KS_SPECIAL K_FILLER
1522: * Don't replace K_SPECIAL when reading a script file.
1523: */
1524: for (i = len; --i >= 0; ++buf)
1525: {
1526: if (buf[0] == NUL || (buf[0] == K_SPECIAL && c < 0))
1527: {
1528: vim_memmove(buf + 3, buf + 1, (size_t)i);
1529: buf[2] = K_THIRD(buf[0]);
1530: buf[1] = K_SECOND(buf[0]);
1531: buf[0] = K_SPECIAL;
1532: buf += 2;
1533: len += 2;
1534: }
1535: }
1536: *buf = NUL; /* add trailing NUL */
1537: return len;
1538: }
1539:
1540: /*
1541: * map[!] : show all key mappings
1542: * map[!] {lhs} : show key mapping for {lhs}
1543: * map[!] {lhs} {rhs} : set key mapping for {lhs} to {rhs}
1544: * noremap[!] {lhs} {rhs} : same, but no remapping for {rhs}
1545: * unmap[!] {lhs} : remove key mapping for {lhs}
1546: * abbr : show all abbreviations
1547: * abbr {lhs} : show abbreviations for {lhs}
1548: * abbr {lhs} {rhs} : set abbreviation for {lhs} to {rhs}
1549: * noreabbr {lhs} {rhs} : same, but no remapping for {rhs}
1550: * unabbr {lhs} : remove abbreviation for {lhs}
1551: *
1552: * maptype == 1 for unmap command, 2 for noremap command.
1553: *
1554: * keys is pointer to any arguments. Note: keys cannot be a read-only string,
1555: * it will be modified.
1556: *
1557: * for :map mode is NORMAL + VISUAL
1558: * for :map! mode is INSERT + CMDLINE
1559: * for :cmap mode is CMDLINE
1560: * for :imap mode is INSERT
1561: * for :nmap mode is NORMAL
1562: * for :vmap mode is VISUAL
1563: * for :abbr mode is INSERT + CMDLINE + ABBREV
1564: * for :iabbr mode is INSERT + ABBREV
1565: * for :cabbr mode is CMDLINE + ABBREV
1566: *
1567: * Return 0 for success
1568: * 1 for invalid arguments
1569: * 2 for no match
1570: * 3 for ambiguety
1571: * 4 for out of mem
1572: */
1573: int
1574: do_map(maptype, keys, mode)
1575: int maptype;
1576: char_u *keys;
1577: int mode;
1578: {
1579: struct mapblock *mp, *mprev;
1580: char_u *arg;
1581: char_u *p;
1582: int n;
1583: int len = 0; /* init for GCC */
1584: char_u *newstr;
1585: int hasarg;
1586: int haskey;
1587: int did_it = FALSE;
1588: int abbrev = 0;
1589: int round;
1590: char_u *keys_buf = NULL;
1591: char_u *arg_buf = NULL;
1592: int retval = 0;
1593: int do_backslash;
1594:
1595: if (mode & ABBREV) /* not a mapping but an abbreviation */
1596: {
1597: abbrev = ABBREV;
1598: mode &= ~ABBREV;
1599: }
1600: /*
1601: * find end of keys and skip CTRL-Vs (and backslashes) in it
1602: * Accept backslash like CTRL-V when 'cpoptions' does not contain 'B'.
1603: * with :unmap white space is included in the keys, no argument possible
1604: */
1605: p = keys;
1606: do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
1607: while (*p && (maptype == 1 || !vim_iswhite(*p)))
1608: {
1609: if ((p[0] == Ctrl('V') || (do_backslash && p[0] == '\\')) &&
1610: p[1] != NUL)
1611: ++p; /* skip CTRL-V or backslash */
1612: ++p;
1613: }
1614: if (*p != NUL)
1615: *p++ = NUL;
1616: p = skipwhite(p);
1617: arg = p;
1618: hasarg = (*arg != NUL);
1619: haskey = (*keys != NUL);
1620:
1621: /* check for :unmap without argument */
1622: if (maptype == 1 && !haskey)
1623: {
1624: retval = 1;
1625: goto theend;
1626: }
1627:
1628: /*
1629: * If mapping has been given as ^V<C_UP> say, then replace the term codes
1630: * with the appropriate two bytes. If it is a shifted special key, unshift
1631: * it too, giving another two bytes.
1632: * replace_termcodes() may move the result to allocated memory, which
1633: * needs to be freed later (*keys_buf and *arg_buf).
1634: * replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
1635: */
1636: if (haskey)
1637: keys = replace_termcodes(keys, &keys_buf, TRUE);
1638: if (hasarg)
1639: arg = replace_termcodes(arg, &arg_buf, FALSE);
1640:
1641: /*
1642: * check arguments and translate function keys
1643: */
1644: if (haskey)
1645: {
1646: len = STRLEN(keys);
1647: if (len > MAXMAPLEN) /* maximum length of MAXMAPLEN chars */
1648: {
1649: retval = 1;
1650: goto theend;
1651: }
1652:
1653: if (abbrev)
1654: {
1655: /*
1656: * If an abbreviation ends in a keyword character, the
1657: * rest must be all keyword-char or all non-keyword-char.
1658: * Otherwise we won't be able to find the start of it in a
1659: * vi-compatible way.
1660: * An abbrevation cannot contain white space.
1661: */
1662: if (iswordchar(keys[len - 1])) /* ends in keyword char */
1663: for (n = 0; n < len - 2; ++n)
1664: if (iswordchar(keys[n]) != iswordchar(keys[len - 2]))
1665: {
1666: retval = 1;
1667: goto theend;
1668: }
1669: for (n = 0; n < len; ++n)
1670: if (vim_iswhite(keys[n]))
1671: {
1672: retval = 1;
1673: goto theend;
1674: }
1675: }
1676: }
1677:
1678: if (haskey && hasarg && abbrev) /* if we will add an abbreviation */
1679: no_abbr = FALSE; /* reset flag that indicates there are
1680: no abbreviations */
1681:
1682: if (!haskey || (maptype != 1 && !hasarg))
1683: msg_start();
1684: /*
1685: * Find an entry in the maplist that matches.
1686: * For :unmap we may loop two times: once to try to unmap an entry with a
1687: * matching 'from' part, a second time, if the first fails, to unmap an
1688: * entry with a matching 'to' part. This was done to allow ":ab foo bar" to be
1689: * unmapped by typing ":unab foo", where "foo" will be replaced by "bar" because
1690: * of the abbreviation.
1691: */
1692: for (round = 0; (round == 0 || maptype == 1) && round <= 1 &&
1693: !did_it && !got_int; ++round)
1694: {
1695: for (mp = maplist.m_next, mprev = &maplist; mp && !got_int;
1696: mprev = mp, mp = mp->m_next)
1697: {
1698: /* skip entries with wrong mode */
1699: if (!(mp->m_mode & mode) || (mp->m_mode & ABBREV) != abbrev)
1700: continue;
1701: if (!haskey) /* show all entries */
1702: {
1703: showmap(mp);
1704: did_it = TRUE;
1705: }
1706: else /* do we have a match? */
1707: {
1708: if (round) /* second round: try 'to' string for unmap */
1709: {
1710: n = STRLEN(mp->m_str);
1711: p = mp->m_str;
1712: }
1713: else
1714: {
1715: n = mp->m_keylen;
1716: p = mp->m_keys;
1717: }
1718: if (!STRNCMP(p, keys, (size_t)(n < len ? n : len)))
1719: {
1720: if (maptype == 1) /* delete entry */
1721: {
1722: if (n != len) /* not a full match */
1723: continue;
1724: /*
1725: * We reset the indicated mode bits. If nothing is
1726: * left the entry is deleted below.
1727: */
1728: mp->m_mode &= (~mode | ABBREV);
1729: did_it = TRUE; /* remember that we did something */
1730: }
1731: else if (!hasarg) /* show matching entry */
1732: {
1733: showmap(mp);
1734: did_it = TRUE;
1735: }
1736: else if (n != len) /* new entry is ambigious */
1737: {
1738: if (abbrev) /* for abbreviations that's ok */
1739: continue;
1740: retval = 3;
1741: goto theend;
1742: }
1743: else
1744: {
1745: mp->m_mode &= (~mode | ABBREV); /* remove mode bits */
1746: if (!(mp->m_mode & ~ABBREV) && !did_it) /* reuse existing entry */
1747: {
1748: newstr = strsave(arg);
1749: if (newstr == NULL)
1750: {
1751: retval = 4; /* no mem */
1752: goto theend;
1753: }
1754: vim_free(mp->m_str);
1755: mp->m_str = newstr;
1756: mp->m_noremap = maptype;
1757: mp->m_mode = mode + abbrev;
1758: did_it = TRUE;
1759: }
1760: }
1761: if (!(mp->m_mode & ~ABBREV)) /* entry can be deleted */
1762: {
1763: map_free(mprev);
1764: mp = mprev; /* continue with next entry */
1765: }
1766: }
1767: }
1768: }
1769: }
1770:
1771: if (maptype == 1) /* delete entry */
1772: {
1773: if (!did_it)
1774: retval = 2; /* no match */
1775: goto theend;
1776: }
1777:
1778: if (!haskey || !hasarg) /* print entries */
1779: {
1780: if (!did_it)
1781: {
1782: if (abbrev)
1783: MSG("No abbreviation found");
1784: else
1785: MSG("No mapping found");
1786: }
1787: goto theend; /* listing finished */
1788: }
1789:
1790: if (did_it) /* have added the new entry already */
1791: goto theend;
1792: /*
1793: * get here when we have to add a new entry
1794: */
1795: /* allocate a new entry for the maplist */
1796: mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
1797: if (mp == NULL)
1798: {
1799: retval = 4; /* no mem */
1800: goto theend;
1801: }
1802: mp->m_keys = strsave(keys);
1803: mp->m_str = strsave(arg);
1804: if (mp->m_keys == NULL || mp->m_str == NULL)
1805: {
1806: vim_free(mp->m_keys);
1807: vim_free(mp->m_str);
1808: vim_free(mp);
1809: retval = 4; /* no mem */
1810: goto theend;
1811: }
1812: mp->m_keylen = STRLEN(mp->m_keys);
1813: mp->m_noremap = maptype;
1814: mp->m_mode = mode + abbrev;
1815:
1816: /* add the new entry in front of the maplist */
1817: mp->m_next = maplist.m_next;
1818: maplist.m_next = mp;
1819:
1820: theend:
1821: vim_free(keys_buf);
1822: vim_free(arg_buf);
1823: return retval;
1824: }
1825:
1826: /*
1827: * Delete one entry from the maplist.
1828: * The argument is a pointer to the PREVIOUS entry!
1829: */
1830: static void
1831: map_free(mprev)
1832: struct mapblock *mprev;
1833: {
1834: struct mapblock *mp;
1835:
1836: mp = mprev->m_next;
1837: vim_free(mp->m_keys);
1838: vim_free(mp->m_str);
1839: mprev->m_next = mp->m_next;
1840: vim_free(mp);
1841: }
1842:
1843: /*
1844: * Clear all mappings or abbreviations.
1845: * 'abbr' should be FALSE for mappings, TRUE for abbreviations.
1846: */
1847: void
1848: map_clear(modec, force, abbr)
1849: int modec;
1850: int force;
1851: int abbr;
1852: {
1853: struct mapblock *mp;
1854: int mode;
1855:
1856: if (force) /* :mapclear! */
1857: mode = INSERT + CMDLINE;
1858: else if (modec == 'i')
1859: mode = INSERT;
1860: else if (modec == 'n')
1861: mode = NORMAL;
1862: else if (modec == 'c')
1863: mode = CMDLINE;
1864: else if (modec == 'v')
1865: mode = VISUAL;
1866: else
1867: mode = VISUAL + NORMAL;
1868:
1869: for (mp = &maplist; mp->m_next != NULL; )
1870: {
1871: if (abbr != !(mp->m_next->m_mode & ABBREV) && mp->m_next->m_mode & mode)
1872: {
1873: mp->m_next->m_mode &= ~mode;
1874: if ((mp->m_next->m_mode & ~ABBREV) == 0) /* entry can be deleted */
1875: {
1876: map_free(mp);
1877: continue;
1878: }
1879: }
1880: mp = mp->m_next;
1881: }
1882: }
1883:
1884: static void
1885: showmap(mp)
1886: struct mapblock *mp;
1887: {
1888: int len;
1889:
1890: if (msg_didout)
1891: msg_outchar('\n');
1892: if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
1893: MSG_OUTSTR("! ");
1894: else if (mp->m_mode & INSERT)
1895: MSG_OUTSTR("i ");
1896: else if (mp->m_mode & CMDLINE)
1897: MSG_OUTSTR("c ");
1898: else if (!(mp->m_mode & VISUAL))
1899: MSG_OUTSTR("n ");
1900: else if (!(mp->m_mode & NORMAL))
1901: MSG_OUTSTR("v ");
1902: else
1903: MSG_OUTSTR(" ");
1904: /* Get length of what we write */
1905: len = msg_outtrans_special(mp->m_keys, TRUE);
1906: do
1907: {
1908: msg_outchar(' '); /* padd with blanks */
1909: ++len;
1910: } while (len < 12);
1911: if (mp->m_noremap)
1912: msg_outchar('*');
1913: else
1914: msg_outchar(' ');
1915: /* Use FALSE below if we only want things like <Up> to show up as such on
1916: * the rhs, and not M-x etc, TRUE gets both -- webb
1917: */
1918: msg_outtrans_special(mp->m_str, TRUE);
1919: flushbuf(); /* show one line at a time */
1920: }
1921:
1922: /*
1923: * Check for an abbreviation.
1924: * Cursor is at ptr[col]. When inserting, mincol is where insert started.
1925: * "c" is the character typed before check_abbr was called.
1926: *
1927: * Historic vi practice: The last character of an abbreviation must be an id
1928: * character ([a-zA-Z0-9_]). The characters in front of it must be all id
1929: * characters or all non-id characters. This allows for abbr. "#i" to
1930: * "#include".
1931: *
1932: * Vim addition: Allow for abbreviations that end in a non-keyword character.
1933: * Then there must be white space before the abbr.
1934: *
1935: * return TRUE if there is an abbreviation, FALSE if not
1936: */
1937: int
1938: check_abbr(c, ptr, col, mincol)
1939: int c;
1940: char_u *ptr;
1941: int col;
1942: int mincol;
1943: {
1944: int len;
1945: int j;
1946: char_u tb[4];
1947: struct mapblock *mp;
1948: int is_id = TRUE;
1949: int vim_abbr;
1950:
1951: if (no_abbr_cnt) /* abbrev. are not recursive */
1952: return FALSE;
1953:
1954: /*
1955: * Check for word before the cursor: If it ends in a keyword char all
1956: * chars before it must be al keyword chars or non-keyword chars, but not
1957: * white space. If it ends in a non-keyword char we accept any characters
1958: * before it except white space.
1959: */
1960: if (col == 0) /* cannot be an abbr. */
1961: return FALSE;
1962:
1963: if (!iswordchar(ptr[col - 1]))
1964: vim_abbr = TRUE; /* Vim added abbr. */
1965: else
1966: {
1967: vim_abbr = FALSE; /* vi compatible abbr. */
1968: if (col > 1)
1969: is_id = iswordchar(ptr[col - 2]);
1970: }
1971: for (len = col - 1; len > 0 && !vim_isspace(ptr[len - 1]) &&
1972: (vim_abbr || is_id == iswordchar(ptr[len - 1])); --len)
1973: ;
1974:
1975: if (len < mincol)
1976: len = mincol;
1977: if (len < col) /* there is a word in front of the cursor */
1978: {
1979: ptr += len;
1980: len = col - len;
1981: for (mp = maplist.m_next; mp; mp = mp->m_next)
1982: {
1983: /* find entries with right mode and keys */
1984: if ((mp->m_mode & ABBREV) == ABBREV &&
1985: (mp->m_mode & State) &&
1986: mp->m_keylen == len &&
1987: !STRNCMP(mp->m_keys, ptr, (size_t)len))
1988: break;
1989: }
1990: if (mp)
1991: {
1992: /*
1993: * Found a match:
1994: * Insert the rest of the abbreviation in typebuf[].
1995: * This goes from end to start.
1996: *
1997: * Characters 0x000 - 0x100: normal chars, may need CTRL-V,
1998: * except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL K_FILLER
1999: * Characters where IS_SPECIAL() == TRUE: key codes, need
2000: * K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
2001: */
2002: j = 0;
2003: /* special key code, split up */
2004: if (IS_SPECIAL(c) || c == K_SPECIAL)
2005: {
2006: tb[j++] = K_SPECIAL;
2007: tb[j++] = K_SECOND(c);
2008: c = K_THIRD(c);
2009: }
2010: else if (c < 0x100 && (c < ' ' || c > '~'))
2011: tb[j++] = Ctrl('V'); /* special char needs CTRL-V */
2012: tb[j++] = c;
2013: tb[j] = NUL;
2014: /* insert the last typed char */
2015: (void)ins_typebuf(tb, TRUE, 0, TRUE);
2016: /* insert the to string */
2017: (void)ins_typebuf(mp->m_str, mp->m_noremap, 0, TRUE);
2018: /* no abbrev. for these chars */
2019: no_abbr_cnt += STRLEN(mp->m_str) + j + 1;
2020:
2021: tb[0] = Ctrl('H');
2022: tb[1] = NUL;
2023: while (len--) /* delete the from string */
2024: (void)ins_typebuf(tb, TRUE, 0, TRUE);
2025: return TRUE;
2026: }
2027: }
2028: return FALSE;
2029: }
2030:
2031: /*
2032: * Write map commands for the current mappings to an .exrc file.
2033: * Return FAIL on error, OK otherwise.
2034: */
2035: int
2036: makemap(fd)
2037: FILE *fd;
2038: {
2039: struct mapblock *mp;
2040: char_u c1;
2041: char_u *p;
2042:
2043: for (mp = maplist.m_next; mp; mp = mp->m_next)
2044: {
2045: c1 = NUL;
2046: p = (char_u *)"map";
2047: switch (mp->m_mode)
2048: {
2049: case NORMAL + VISUAL:
2050: break;
2051: case NORMAL:
2052: c1 = 'n';
2053: break;
2054: case VISUAL:
2055: c1 = 'v';
2056: break;
2057: case CMDLINE + INSERT:
2058: p = (char_u *)"map!";
2059: break;
2060: case CMDLINE:
2061: c1 = 'c';
2062: break;
2063: case INSERT:
2064: c1 = 'i';
2065: break;
2066: case INSERT + CMDLINE + ABBREV:
2067: p = (char_u *)"abbr";
2068: break;
2069: case CMDLINE + ABBREV:
2070: c1 = 'c';
2071: p = (char_u *)"abbr";
2072: break;
2073: case INSERT + ABBREV:
2074: c1 = 'i';
2075: p = (char_u *)"abbr";
2076: break;
2077: default:
2078: EMSG("makemap: Illegal mode");
2079: return FAIL;
2080: }
2081: if (c1 && putc(c1, fd) < 0)
2082: return FAIL;
2083: if (mp->m_noremap && fprintf(fd, "nore") < 0)
2084: return FAIL;
2085: if (fprintf(fd, (char *)p) < 0)
2086: return FAIL;
2087:
2088: if ( putc(' ', fd) < 0 || putescstr(fd, mp->m_keys, FALSE) == FAIL ||
2089: putc(' ', fd) < 0 || putescstr(fd, mp->m_str, FALSE) == FAIL ||
2090: #ifdef USE_CRNL
2091: putc('\r', fd) < 0 ||
2092: #endif
2093: putc('\n', fd) < 0)
2094: return FAIL;
2095: }
2096: return OK;
2097: }
2098:
2099: /*
2100: * write escape string to file
2101: *
2102: * return FAIL for failure, OK otherwise
2103: */
2104: int
2105: putescstr(fd, str, set)
2106: FILE *fd;
2107: char_u *str;
2108: int set; /* TRUE for makeset, FALSE for makemap */
2109: {
2110: int c;
2111: int modifiers;
2112:
2113: for ( ; *str; ++str)
2114: {
2115: c = *str;
2116: /*
2117: * Special key codes have to be translated to be able to make sense
2118: * when they are read back.
2119: */
2120: if (c == K_SPECIAL && !set)
2121: {
2122: modifiers = 0x0;
2123: if (str[1] == KS_MODIFIER)
2124: {
2125: modifiers = str[2];
2126: str += 3;
2127: c = *str;
2128: }
2129: if (c == K_SPECIAL)
2130: {
2131: c = TO_SPECIAL(str[1], str[2]);
2132: str += 2;
2133: }
2134: if (IS_SPECIAL(c) || modifiers) /* special key */
2135: {
2136: fprintf(fd, (char *)get_special_key_name(c, modifiers));
2137: continue;
2138: }
2139: }
2140: /*
2141: * A '\n' in a map command should be written as <NL>.
2142: * A '\n' in a set command should be written as \^V^J.
2143: */
2144: if (c == NL)
2145: {
2146: if (set)
2147: fprintf(fd, "\\\026\n");
2148: else
2149: fprintf(fd, "<NL>");
2150: continue;
2151: }
2152: /*
2153: * some characters have to be escaped with CTRL-V to
2154: * prevent them from misinterpreted in DoOneCmd().
2155: * A space, Tab and '"' has to be escaped with a backslash to
2156: * prevent it to be misinterpreted in do_set().
2157: */
2158: if (set && (vim_iswhite(c) || c == '"' || c == '\\'))
2159: {
2160: if (putc('\\', fd) < 0)
2161: return FAIL;
2162: }
2163: else if (c < ' ' || c > '~' || c == '|')
2164: {
2165: if (putc(Ctrl('V'), fd) < 0)
2166: return FAIL;
2167: }
2168: if (putc(c, fd) < 0)
2169: return FAIL;
2170: }
2171: return OK;
2172: }
2173:
2174: /*
2175: * Check all mappings for the presence of special key codes.
2176: * Used after ":set term=xxx".
2177: */
2178: void
2179: check_map_keycodes()
2180: {
2181: struct mapblock *mp;
2182: char_u *p;
2183: int i;
2184: char_u buf[3];
2185: char_u *save_name;
2186:
2187: save_name = sourcing_name;
2188: sourcing_name = (char_u *)"mappings";/* don't give error messages */
2189: for (mp = maplist.m_next; mp != NULL; mp = mp->m_next)
2190: {
2191: for (i = 0; i <= 1; ++i) /* do this twice */
2192: {
2193: if (i == 0)
2194: p = mp->m_keys; /* once for the "from" part */
2195: else
2196: p = mp->m_str; /* and once for the "to" part */
2197: while (*p)
2198: {
2199: if (*p == K_SPECIAL)
2200: {
2201: ++p;
2202: if (*p < 128) /* only for "normal" termcap entries */
2203: {
2204: buf[0] = p[0];
2205: buf[1] = p[1];
2206: buf[2] = NUL;
2207: (void)add_termcap_entry(buf, FALSE);
2208: }
2209: ++p;
2210: }
2211: ++p;
2212: }
2213: }
2214: }
2215: sourcing_name = save_name;
2216: }