home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / amiga / vim46src.lha / vim-4.6 / src / getchar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-06  |  51.3 KB  |  2,234 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * getchar.c
  11.  *
  12.  * functions related with getting a character from the user/mapping/redo/...
  13.  *
  14.  * manipulations with redo buffer and stuff buffer
  15.  * mappings and abbreviations
  16.  */
  17.  
  18. #include "vim.h"
  19. #include "globals.h"
  20. #include "proto.h"
  21. #include "option.h"
  22.  
  23. /*
  24.  * structure used to store one block of the stuff/redo/macro buffers
  25.  */
  26. struct bufblock
  27. {
  28.         struct bufblock *b_next;        /* pointer to next bufblock */
  29.         char_u            b_str[1];        /* contents (actually longer) */
  30. };
  31.  
  32. #define MINIMAL_SIZE 20                 /* minimal size for b_str */
  33.  
  34. /*
  35.  * header used for the stuff buffer and the redo buffer
  36.  */
  37. struct buffheader
  38. {
  39.         struct bufblock bh_first;        /* first (dummy) block of list */
  40.         struct bufblock *bh_curr;        /* bufblock for appending */
  41.         int             bh_index;        /* index for reading */
  42.         int             bh_space;        /* space in bh_curr for appending */
  43. };
  44.  
  45. static struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
  46. static struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
  47. static struct buffheader old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
  48. static struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
  49.  
  50. /*
  51.  * when block_redo is TRUE redo buffer will not be changed
  52.  * used by edit() to repeat insertions and 'V' command for redoing
  53.  */
  54. static int        block_redo = FALSE;
  55.  
  56. /*
  57.  * structure used for mapping
  58.  */
  59. struct mapblock
  60. {
  61.     struct mapblock *m_next;        /* next mapblock */
  62.     char_u            *m_keys;        /* mapped from */
  63.     int                 m_keylen;        /* strlen(m_keys) */
  64.     char_u            *m_str;         /* mapped to */
  65.     int              m_mode;        /* valid mode */
  66.     int                 m_noremap;        /* if non-zero no re-mapping for m_str */
  67. };
  68.  
  69. static struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
  70.                                     /* first dummy entry in maplist */
  71.  
  72. /*
  73.  * variables used by vgetorpeek() and flush_buffers()
  74.  *
  75.  * typebuf[] contains all characters that are not consumed yet.
  76.  * typebuf[typeoff] is the first valid character in typebuf[].
  77.  * typebuf[typeoff + typelen - 1] is the last valid char.
  78.  * typebuf[typeoff + typelen] must be NUL.
  79.  * The part in front may contain the result of mappings, abbreviations and
  80.  * @a commands. The length of this part is typemaplen.
  81.  * After it are characters that come from the terminal.
  82.  * no_abbr_cnt is the number of characters in typebuf that should not be
  83.  * considered for abbreviations.
  84.  * Some parts of typebuf may not be mapped. These parts are remembered in
  85.  * noremapbuf, which is the same length as typebuf and contains TRUE for the
  86.  * characters that are not to be remapped. noremapbuf[typeoff] is the first
  87.  * valid flag.
  88.  * (typebuf has been put in globals.h, because check_termcode() needs it).
  89.  */
  90. static char_u    *noremapbuf = NULL;       /* flags for typeahead characters */
  91. #define TYPELEN_INIT    (3 * (MAXMAPLEN + 3))
  92. static char_u    typebuf_init[TYPELEN_INIT];            /* initial typebuf */
  93. static char_u    noremapbuf_init[TYPELEN_INIT];        /* initial noremapbuf */
  94.  
  95. static int        typemaplen = 0;        /* nr of mapped characters in typebuf */
  96. static int        no_abbr_cnt = 0;    /* nr of chars without abbrev. in typebuf */
  97. static int        last_recorded_len = 0;    /* number of last recorded chars */
  98.  
  99. static void        free_buff __ARGS((struct buffheader *));
  100. static char_u    *get_bufcont __ARGS((struct buffheader *, int));
  101. static void        add_buff __ARGS((struct buffheader *, char_u *));
  102. static void        add_num_buff __ARGS((struct buffheader *, long));
  103. static void        add_char_buff __ARGS((struct buffheader *, int));
  104. static int        read_stuff __ARGS((int));
  105. static void        start_stuff __ARGS((void));
  106. static int        read_redo __ARGS((int, int));
  107. static void        copy_redo __ARGS((int));
  108. static void        init_typebuf __ARGS((void));
  109. static void        gotchars __ARGS((char_u *, int));
  110. static void        may_sync_undo __ARGS((void));
  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.     may_sync_undo();
  809. }
  810.  
  811. /*
  812.  * Sync undo.  Called when typed characters are obtained from the typeahead
  813.  * buffer, or when a menu is used.
  814.  * Do not sync in insert mode, unless cursor key has been used.
  815.  * Also don't sync while reading a script file.
  816.  */
  817.     static void
  818. may_sync_undo()
  819. {
  820.     if ((!(State & (INSERT + CMDLINE)) || arrow_used) &&
  821.                                                   scriptin[curscript] == NULL)
  822.         u_sync();
  823. }
  824.  
  825. /*
  826.  * open new script file for ":so!" command
  827.  * return OK on success, FAIL on error
  828.  */
  829.     int
  830. openscript(name)
  831.     char_u *name;
  832. {
  833.     int oldcurscript;
  834.  
  835.     if (curscript + 1 == NSCRIPT)
  836.     {
  837.         emsg(e_nesting);
  838.         return FAIL;
  839.     }
  840.     else
  841.     {
  842.         if (scriptin[curscript] != NULL)    /* already reading script */
  843.             ++curscript;
  844.                                     /* use NameBuff for expanded name */
  845.         expand_env(name, NameBuff, MAXPATHL);
  846.         if ((scriptin[curscript] = fopen((char *)NameBuff, READBIN)) == NULL)
  847.         {
  848.             emsg2(e_notopen, name);
  849.             if (curscript)
  850.                 --curscript;
  851.             return FAIL;
  852.         }
  853.         /*
  854.          * With command ":g/pat/so! file" we have to execute the
  855.          * commands from the file now.
  856.          */
  857.         if (global_busy)
  858.         {
  859.             State = NORMAL;
  860.             oldcurscript = curscript;
  861.             do
  862.             {
  863.                 normal();
  864.                 vpeekc();            /* check for end of file */
  865.             }
  866.             while (scriptin[oldcurscript]);
  867.             State = CMDLINE;
  868.         }
  869.     }
  870.     return OK;
  871. }
  872.  
  873. /*
  874.  * updatescipt() is called when a character can be written into the script file
  875.  * or when we have waited some time for a character (c == 0)
  876.  *
  877.  * All the changed memfiles are synced if c == 0 or when the number of typed
  878.  * characters reaches 'updatecount' and 'updatecount' is non-zero.
  879.  */
  880.     void
  881. updatescript(c)
  882.     int c;
  883. {
  884.     static int        count = 0;
  885.  
  886.     if (c && scriptout)
  887.         putc(c, scriptout);
  888.     if (c == 0 || (p_uc > 0 && ++count >= p_uc))
  889.     {
  890.         ml_sync_all(c == 0, TRUE);
  891.         count = 0;
  892.     }
  893. }
  894.  
  895. #define K_NEEDMORET -1            /* keylen value for incomplete key-code */
  896. #define M_NEEDMORET -2            /* keylen value for incomplete mapping */
  897.  
  898. static int old_char = -1;        /* ungotten character */
  899.  
  900.     int
  901. vgetc()
  902. {
  903.     int        c, c2;
  904.  
  905.     mod_mask = 0x0;
  906.     last_recorded_len = 0;
  907.     for (;;)                    /* this is done twice if there are modifiers */
  908.     {
  909.         if (mod_mask)            /* no mapping after modifier has been read */
  910.         {
  911.             ++no_mapping;
  912.             ++allow_keys;
  913.         }
  914.         c = vgetorpeek(TRUE);
  915.         if (mod_mask)
  916.         {
  917.             --no_mapping;
  918.             --allow_keys;
  919.         }
  920.  
  921.         /* Get two extra bytes for special keys */
  922.         if (c == K_SPECIAL)
  923.         {
  924.             ++no_mapping;
  925.             c2 = vgetorpeek(TRUE);        /* no mapping for these chars */
  926.             c = vgetorpeek(TRUE);
  927.             --no_mapping;
  928.             if (c2 == KS_MODIFIER)
  929.             {
  930.                 mod_mask = c;
  931.                 continue;
  932.             }
  933.             c = TO_SPECIAL(c2, c);
  934.         }
  935. #ifdef MSDOS
  936.         /*
  937.          * If K_NUL was typed, it is replaced by K_NUL, 3 in mch_inchar().
  938.          * Delete the 3 here.
  939.          */
  940.         else if (c == K_NUL && vpeekc() == 3)
  941.             (void)vgetorpeek(TRUE);
  942. #endif
  943.  
  944.         return check_shifted_spec_key(c);
  945.     }
  946. }
  947.  
  948.     int
  949. vpeekc()
  950. {
  951.     return (vgetorpeek(FALSE));
  952. }
  953.  
  954. /*
  955.  * Call vpeekc() without causing anything to be mapped.
  956.  * Return TRUE if a character is available, FALSE otherwise.
  957.  */
  958.     int
  959. char_avail()
  960. {
  961.     int        retval;
  962.  
  963.     ++no_mapping;
  964.     retval = vgetorpeek(FALSE);
  965.     --no_mapping;
  966.     return (retval != NUL);
  967. }
  968.  
  969.     void
  970. vungetc(c)        /* unget one character (can only be done once!) */
  971.     int        c;
  972. {
  973.     old_char = c;
  974. }
  975.  
  976. /*
  977.  * get a character: 1. from a previously ungotten character
  978.  *                    2. from the stuffbuffer
  979.  *                    3. from the typeahead buffer
  980.  *                    4. from the user
  981.  *
  982.  * if "advance" is TRUE (vgetc()):
  983.  *        really get the character.
  984.  *        KeyTyped is set to TRUE in the case the user typed the key.
  985.  *        KeyStuffed is TRUE if the character comes from the stuff buffer.
  986.  * if "advance" is FALSE (vpeekc()):
  987.  *        just look whether there is a character available.
  988.  */
  989.  
  990.     static int
  991. vgetorpeek(advance)
  992.     int        advance;
  993. {
  994.     register int    c, c1;
  995.     int                keylen = 0;                /* init for gcc */
  996. #ifdef AMIGA
  997.     char_u            *s;
  998. #endif
  999.     register struct mapblock *mp;
  1000.     int                timedout = FALSE;        /* waited for more than 1 second
  1001.                                                 for mapping to complete */
  1002.     int                mapdepth = 0;            /* check for recursive mapping */
  1003.     int                mode_deleted = FALSE;    /* set when mode has been deleted */
  1004.     int                local_State;
  1005.     register int    mlen;
  1006.     int                max_mlen;
  1007.     int                i;
  1008. #ifdef USE_GUI
  1009.     int                idx;
  1010. #endif
  1011.  
  1012.     /*
  1013.      * VISUAL state is never set, it is used only here, therefore a check is
  1014.      * made if NORMAL state is actually VISUAL state.
  1015.      */
  1016.     local_State = State;
  1017.     if ((State & NORMAL) && VIsual_active)
  1018.         local_State = VISUAL;
  1019.  
  1020. /*
  1021.  * get a character: 1. from a previously ungotten character
  1022.  */
  1023.     if (old_char >= 0)
  1024.     {
  1025.         c = old_char;
  1026.         if (advance)
  1027.             old_char = -1;
  1028.         return c;
  1029.     }
  1030.  
  1031.     if (advance)
  1032.         KeyStuffed = FALSE;
  1033.  
  1034.     init_typebuf();
  1035.     start_stuff();
  1036.     if (advance && typemaplen == 0)
  1037.         Exec_reg = FALSE;
  1038.     do
  1039.     {
  1040. /*
  1041.  * get a character: 2. from the stuffbuffer
  1042.  */
  1043.         c = read_stuff(advance);
  1044.         if (c != NUL && !got_int)
  1045.         {
  1046.             if (advance)
  1047.             {
  1048.                 KeyTyped = FALSE;
  1049.                 KeyStuffed = TRUE;
  1050.             }
  1051.             if (no_abbr_cnt == 0)
  1052.                 no_abbr_cnt = 1;        /* no abbreviations now */
  1053.         }
  1054.         else
  1055.         {
  1056.             /*
  1057.              * Loop until we either find a matching mapped key, or we
  1058.              * are sure that it is not a mapped key.
  1059.              * If a mapped key sequence is found we go back to the start to
  1060.              * try re-mapping.
  1061.              */
  1062.  
  1063.             for (;;)
  1064.             {
  1065.                 /*
  1066.                  * mch_breakcheck() is slow, don't use it too often when
  1067.                  * inside a mapping.  But call it each time for typed
  1068.                  * characters.
  1069.                  */
  1070.                 if (typemaplen)
  1071.                     line_breakcheck();
  1072.                 else
  1073.                     mch_breakcheck();            /* check for CTRL-C */
  1074.                 if (got_int)
  1075.                 {
  1076.                     c = inchar(typebuf, MAXMAPLEN, 0L);    /* flush all input */
  1077.                     /*
  1078.                      * If inchar returns TRUE (script file was active) or we are
  1079.                      * inside a mapping, get out of insert mode.
  1080.                      * Otherwise we behave like having gotten a CTRL-C.
  1081.                      * As a result typing CTRL-C in insert mode will
  1082.                      * really insert a CTRL-C.
  1083.                      */
  1084.                     if ((c || typemaplen) && (State & (INSERT + CMDLINE)))
  1085.                         c = ESC;
  1086.                     else
  1087.                         c = Ctrl('C');
  1088.                     flush_buffers(TRUE);        /* flush all typeahead */
  1089.                     break;
  1090.                 }
  1091.                 else if (typelen > 0)    /* check for a mappable key sequence */
  1092.                 {
  1093.                     /*
  1094.                      * walk through the maplist until we find an
  1095.                      * entry that matches.
  1096.                      *
  1097.                      * Don't look for mappings if:
  1098.                      * - timed out
  1099.                      * - no_mapping set: mapping disabled (e.g. for CTRL-V)
  1100.                      * - typebuf[typeoff] should not be remapped
  1101.                      * - in insert or cmdline mode and 'paste' option set
  1102.                      * - waiting for "hit return to continue" and CR or SPACE
  1103.                      *   typed
  1104.                      * - waiting for a char with --more--
  1105.                      * - in Ctrl-X mode, and we get a valid char for that mode
  1106.                      */
  1107.                     mp = NULL;
  1108.                     max_mlen = 0;
  1109.                     if (!timedout && no_mapping == 0 && (typemaplen == 0 ||
  1110.                                 (p_remap && noremapbuf[typeoff] == FALSE))
  1111.                             && !(p_paste && (State & (INSERT + CMDLINE)))
  1112.                             && !(State == HITRETURN && (typebuf[typeoff] == CR
  1113.                                 || typebuf[typeoff] == ' '))
  1114.                             && State != ASKMORE
  1115. #ifdef INSERT_EXPAND
  1116.                             && !(ctrl_x_mode && is_ctrl_x_key(typebuf[typeoff]))
  1117. #endif
  1118.                             )
  1119.                     {
  1120.                         c1 = typebuf[typeoff];
  1121. #ifdef HAVE_LANGMAP
  1122.                         LANGMAP_ADJUST(c1, TRUE);
  1123. #endif
  1124.                         for (mp = maplist.m_next; mp; mp = mp->m_next)
  1125.                         {
  1126.                             /*
  1127.                              * Only consider an entry if
  1128.                              * - the first character matches and
  1129.                              * - it is not an abbreviation and
  1130.                              * - it is for the current state
  1131.                              */
  1132.                             if (        mp->m_keys[0] == c1 &&
  1133.                                         !(mp->m_mode & ABBREV) &&
  1134.                                         (mp->m_mode & local_State))
  1135.                             {
  1136.                                 int        n;
  1137. #ifdef HAVE_LANGMAP
  1138.                                 int        c2;
  1139. #endif
  1140.  
  1141.                                     /* find the match length of this mapping */
  1142.                                 for (mlen = 1; mlen < typelen; ++mlen)
  1143.                                 {
  1144. #ifdef HAVE_LANGMAP
  1145.                                     c2 = typebuf[typeoff + mlen];
  1146.                                     LANGMAP_ADJUST(c2, TRUE);
  1147.                                     if (mp->m_keys[mlen] != c2)
  1148. #else
  1149.                                     if (mp->m_keys[mlen] !=
  1150.                                                     typebuf[typeoff + mlen])
  1151. #endif
  1152.                                         break;
  1153.                                 }
  1154.  
  1155.                                     /* if one of the typed keys cannot be
  1156.                                      * remapped, skip the entry */
  1157.                                 for (n = 0; n < mlen; ++n)
  1158.                                     if (noremapbuf[typeoff + n] == TRUE)
  1159.                                         break;
  1160.                                 if (n != mlen)
  1161.                                     continue;
  1162.  
  1163.                                     /* (partly) match found */
  1164.                                 keylen = mp->m_keylen;
  1165.                                 if (mlen == (keylen > typelen ?
  1166.                                                     typelen : keylen))
  1167.                                 {
  1168.                                         /* partial match, need more chars */
  1169.                                     if (keylen > typelen)
  1170.                                         keylen = M_NEEDMORET;
  1171.                                     break;    
  1172.                                 }
  1173.                                     /* no match, may have to check for
  1174.                                      * termcode at next character */
  1175.                                 if (max_mlen < mlen)
  1176.                                     max_mlen = mlen;
  1177.                             }
  1178.                         }
  1179.                     }
  1180.                     if (mp == NULL)                    /* no match found */
  1181.                     {
  1182.                             /*
  1183.                              * check if we have a terminal code, when
  1184.                              *    mapping is allowed,
  1185.                              *  keys have not been mapped,
  1186.                              *    and not an ESC sequence, not in insert mode or
  1187.                              *        p_ek is on,
  1188.                              *    and when not timed out,
  1189.                              */
  1190.                         if ((no_mapping == 0 || allow_keys != 0) &&
  1191.                                                            (typemaplen == 0 ||
  1192.                                 (p_remap && noremapbuf[typeoff] == FALSE)) &&
  1193.                                             !timedout)
  1194.                             keylen = check_termcode(max_mlen + 1);
  1195.                         else
  1196.                             keylen = 0;
  1197.                         if (keylen == 0)        /* no matching terminal code */
  1198.                         {
  1199. #ifdef AMIGA                    /* check for window bounds report */
  1200.                             if (typemaplen == 0 &&
  1201.                                             (typebuf[typeoff] & 0xff) == CSI)
  1202.                             {
  1203.                                 for (s = typebuf + typeoff + 1;
  1204.                                         s < typebuf + typeoff + typelen &&
  1205.                                         (isdigit(*s) || *s == ';' || *s == ' ');
  1206.                                         ++s)
  1207.                                     ;
  1208.                                 if (*s == 'r' || *s == '|')    /* found one */
  1209.                                 {
  1210.                                     del_typebuf((int)(s + 1 -
  1211.                                                        (typebuf + typeoff)), 0);
  1212.                                         /* get size and redraw screen */
  1213.                                     set_winsize(0, 0, FALSE);
  1214.                                     continue;
  1215.                                 }
  1216.                                 if (*s == NUL)        /* need more characters */
  1217.                                     keylen = K_NEEDMORET;
  1218.                             }
  1219.                             if (keylen >= 0)
  1220. #endif
  1221.                             {
  1222. /*
  1223.  * get a character: 3. from the typeahead buffer
  1224.  */
  1225.                                 c = typebuf[typeoff] & 255;
  1226.                                 if (advance)    /* remove chars from typebuf */
  1227.                                 {
  1228.                                     if (typemaplen)
  1229.                                         KeyTyped = FALSE;
  1230.                                     else
  1231.                                     {
  1232.                                         KeyTyped = TRUE;
  1233.                                         /* write char to script file(s) */
  1234.                                         gotchars(typebuf + typeoff, 1);
  1235.                                     }
  1236.                                     del_typebuf(1, 0);
  1237.                                 }
  1238.                                 break;        /* got character, break for loop */
  1239.                             }
  1240.                         }
  1241.                         if (keylen > 0)        /* full matching terminal code */
  1242.                         {
  1243. #ifdef USE_GUI
  1244.                             if (typebuf[typeoff] == K_SPECIAL &&
  1245.                                               typebuf[typeoff + 1] == KS_MENU)
  1246.                             {
  1247.                                 /*
  1248.                                  * Using a menu may cause a break in undo!
  1249.                                  * It's like using gotchars(), but without
  1250.                                  * recording or writing to a script file.
  1251.                                  */
  1252.                                 may_sync_undo();
  1253.                                 del_typebuf(3, 0);
  1254.                                 idx = gui_get_menu_index(current_menu,
  1255.                                                                  local_State);
  1256.                                 if (idx != MENU_INDEX_INVALID)
  1257.                                 {
  1258.                                     ins_typebuf(current_menu->strings[idx],
  1259.                                         current_menu->noremap[idx] ? -1 : 0,
  1260.                                         0, TRUE);
  1261.                                 }
  1262.                             }
  1263. #endif /* USE_GUI */
  1264.                             continue;    /* try mapping again */
  1265.                         }
  1266.  
  1267.                         /* partial match: get some more characters */
  1268.                         keylen = K_NEEDMORET;
  1269.                     }
  1270.                         /* complete match */
  1271.                     if (keylen >= 0 && keylen <= typelen)
  1272.                     {
  1273.                                         /* write chars to script file(s) */
  1274.                         if (keylen > typemaplen)
  1275.                             gotchars(typebuf + typeoff + typemaplen,
  1276.                                                         keylen - typemaplen);
  1277.  
  1278.                         del_typebuf(keylen, 0);    /* remove the mapped keys */
  1279.  
  1280.                         /*
  1281.                          * Put the replacement string in front of mapstr.
  1282.                          * The depth check catches ":map x y" and ":map y x".
  1283.                          */
  1284.                         if (++mapdepth >= p_mmd)
  1285.                         {
  1286.                             EMSG("recursive mapping");
  1287.                             if (State == CMDLINE)
  1288.                                 redrawcmdline();
  1289.                             else
  1290.                                 setcursor();
  1291.                             flush_buffers(FALSE);
  1292.                             mapdepth = 0;        /* for next one */
  1293.                             c = -1;
  1294.                             break;
  1295.                         }
  1296.                         /*
  1297.                          * Insert the 'to' part in the typebuf.
  1298.                          * If 'from' field is the same as the start of the
  1299.                          * 'to' field, don't remap the first character.
  1300.                          * If m_noremap is set, don't remap the whole 'to'
  1301.                          * part.
  1302.                          */
  1303.                         if (ins_typebuf(mp->m_str, mp->m_noremap ? -1 :
  1304.                                                   STRNCMP(mp->m_str, mp->m_keys,
  1305.                                                       (size_t)keylen) ? 0 : 1,
  1306.                                                                0, TRUE) == FAIL)
  1307.                         {
  1308.                             c = -1;
  1309.                             break;
  1310.                         }
  1311.                         continue;
  1312.                     }
  1313.                 }
  1314.                 /*
  1315.                  * special case: if we get an <ESC> in insert mode and there
  1316.                  * are no more characters at once, we pretend to go out of
  1317.                  * insert mode.  This prevents the one second delay after
  1318.                  * typing an <ESC>.  If we get something after all, we may
  1319.                  * have to redisplay the mode. That the cursor is in the wrong
  1320.                  * place does not matter.
  1321.                  */
  1322.                 c = 0;
  1323.                 if (advance && typelen == 1 && typebuf[typeoff] == ESC &&
  1324.                          !no_mapping && typemaplen == 0 && (State & INSERT) &&
  1325.                        (p_timeout || (keylen == K_NEEDMORET && p_ttimeout)) &&
  1326.                         (c = inchar(typebuf + typeoff + typelen, 3, 0L)) == 0)
  1327.                 {
  1328.                     if (p_smd)
  1329.                     {
  1330.                         delmode();
  1331.                         mode_deleted = TRUE;
  1332.                     }
  1333.                     if (curwin->w_cursor.col != 0)    /* move cursor one left if
  1334.                                                         possible */
  1335.                     {
  1336.                         if (curwin->w_col)
  1337.                         {
  1338.                             if (did_ai)
  1339.                             {
  1340.                                 /*
  1341.                                  * We are expecting to truncate the trailing
  1342.                                  * white-space, so find the last non-white
  1343.                                  * character -- webb
  1344.                                  */
  1345.                                 colnr_t        col, vcol;
  1346.                                 char_u        *ptr;
  1347.  
  1348.                                 col = vcol = curwin->w_col = 0;
  1349.                                 ptr = ml_get_curline();
  1350.                                 while (col < curwin->w_cursor.col)
  1351.                                 {
  1352.                                     if (!vim_iswhite(ptr[col]))
  1353.                                         curwin->w_col = vcol;
  1354.                                     vcol += lbr_chartabsize(ptr + col,
  1355.                                                                (colnr_t)vcol);
  1356.                                     ++col;
  1357.                                 }
  1358.                                   if (curwin->w_p_nu)
  1359.                                     curwin->w_col += 8;
  1360.                             }
  1361.                             else
  1362.                                 --curwin->w_col;
  1363.                         }
  1364.                         else if (curwin->w_p_wrap && curwin->w_row)
  1365.                         {
  1366.                                 --curwin->w_row;
  1367.                                 curwin->w_col = Columns - 1;
  1368.                         }
  1369.                     }
  1370.                     setcursor();
  1371.                     flushbuf();
  1372.                 }
  1373.                 typelen += c;
  1374.                                                     /* buffer full, don't map */
  1375.                 if (typelen >= typemaplen + MAXMAPLEN)
  1376.                 {
  1377.                     timedout = TRUE;
  1378.                     continue;
  1379.                 }
  1380. /*
  1381.  * get a character: 4. from the user
  1382.  */
  1383.                 /*
  1384.                  * If we have a partial match (and are going to wait for more
  1385.                  * input from the user), show the partially matched characters
  1386.                  * to the user with showcmd -- webb.
  1387.                  */
  1388.                 i = 0;
  1389.                 if (typelen > 0 && (State & (NORMAL | INSERT)) && advance)
  1390.                 {
  1391.                     push_showcmd();
  1392.                     while (i < typelen)
  1393.                         (void)add_to_showcmd(typebuf[typeoff + i++], TRUE);
  1394.                 }
  1395.  
  1396.                 c = inchar(typebuf + typeoff + typelen,
  1397.                         typemaplen + MAXMAPLEN - typelen,
  1398.                         !advance
  1399.                             ? 0
  1400.                             : ((typelen == 0 || !(p_timeout || (p_ttimeout &&
  1401.                                         keylen == K_NEEDMORET)))
  1402.                                     ? -1L
  1403.                                     : ((keylen == K_NEEDMORET && p_ttm >= 0)
  1404.                                             ? p_ttm
  1405.                                             : p_tm)));
  1406.  
  1407.                 if (i)
  1408.                     pop_showcmd();
  1409.  
  1410.                 if (c <= NUL)        /* no character available */
  1411.                 {
  1412.                     if (!advance)
  1413.                         break;
  1414.                     if (typelen)                /* timed out */
  1415.                     {
  1416.                         timedout = TRUE;
  1417.                         continue;
  1418.                     }
  1419.                 }
  1420.                 else
  1421.                 {            /* allow mapping for just typed characters */
  1422.                     while (typebuf[typeoff + typelen] != NUL)
  1423.                         noremapbuf[typeoff + typelen++] = FALSE;
  1424.                 }
  1425.             }        /* for (;;) */
  1426.         }        /* if (!character from stuffbuf) */
  1427.  
  1428.                         /* if advance is FALSE don't loop on NULs */
  1429.     } while (c < 0 || (advance && c == NUL));
  1430.  
  1431.     /*
  1432.      * The "INSERT" message is taken care of here:
  1433.      *   if we return an ESC to exit insert mode, the message is deleted
  1434.      *   if we don't return an ESC but deleted the message before, redisplay it
  1435.      */
  1436.     if (advance && p_smd && (State & INSERT))
  1437.     {
  1438.         if (c == ESC && !mode_deleted && !no_mapping)
  1439.             delmode();
  1440.         else if (c != ESC && mode_deleted)
  1441.             showmode();
  1442.     }
  1443.  
  1444.     return c;
  1445. }
  1446.  
  1447. /*
  1448.  * inchar() - get one character from
  1449.  *        1. a scriptfile
  1450.  *        2. the keyboard
  1451.  *
  1452.  *  As much characters as we can get (upto 'maxlen') are put in buf and
  1453.  *  NUL terminated (buffer length must be 'maxlen' + 1).
  1454.  *  Minimum for 'maxlen' is 3!!!!
  1455.  *
  1456.  *    If we got an interrupt all input is read until none is available.
  1457.  *
  1458.  *  If wait_time == 0  there is no waiting for the char.
  1459.  *  If wait_time == n  we wait for n msec for a character to arrive.
  1460.  *  If wait_time == -1 we wait forever for a character to arrive.
  1461.  *
  1462.  *  Return the number of obtained characters.
  1463.  */
  1464.  
  1465.     static int
  1466. inchar(buf, maxlen, wait_time)
  1467.     char_u    *buf;
  1468.     int        maxlen;
  1469.     long    wait_time;                        /* milli seconds */
  1470. {
  1471.     int                len = 0;            /* init for GCC */
  1472.     int                retesc = FALSE;        /* return ESC with gotint */
  1473.     register int     c;
  1474.     register int    i;
  1475.  
  1476.     if (wait_time == -1L || wait_time > 100L)  /* flush output before waiting */
  1477.     {
  1478.         cursor_on();
  1479.         flushbuf();
  1480.     }
  1481.     /*
  1482.      * Don't reset these when at the hit-return prompt, otherwise a endless
  1483.      * recursive loop may result (write error in swapfile, hit-return, timeout
  1484.      * on char wait, flush swapfile, write error....).
  1485.      */
  1486.     if (State != HITRETURN)
  1487.     {
  1488.         did_outofmem_msg = FALSE;    /* display out of memory message (again) */
  1489.         did_swapwrite_msg = FALSE;    /* display swap file write error again */
  1490.     }
  1491.     undo_off = FALSE;            /* restart undo now */
  1492.  
  1493. /*
  1494.  * first try script file
  1495.  *    If interrupted: Stop reading script files.
  1496.  */
  1497.     c = -1;
  1498.     while (scriptin[curscript] != NULL && c < 0)
  1499.     {
  1500.         if (got_int || (c = getc(scriptin[curscript])) < 0)    /* reached EOF */
  1501.         {
  1502.                 /* when reading script file is interrupted, return an ESC to
  1503.                                     get back to normal mode */
  1504.             if (got_int)
  1505.                 retesc = TRUE;
  1506.             fclose(scriptin[curscript]);
  1507.             scriptin[curscript] = NULL;
  1508.             if (curscript > 0)
  1509.                 --curscript;
  1510.         }
  1511.         else
  1512.         {
  1513.             buf[0] = c;
  1514.             len = 1;
  1515.         }
  1516.     }
  1517.  
  1518.     if (c < 0)            /* did not get a character from script */
  1519.     {
  1520.     /*
  1521.      * If we got an interrupt, skip all previously typed characters and
  1522.      * return TRUE if quit reading script file.
  1523.      */
  1524.         if (got_int)            /* skip typed characters */
  1525.         {
  1526.             while (mch_inchar(buf, maxlen, 0L))
  1527.                 ;
  1528.             return retesc;
  1529.         }
  1530.             /* fill up to a third of the buffer, because each character may be
  1531.              * tripled below */
  1532.         len = mch_inchar(buf, maxlen / 3, wait_time);
  1533.     }
  1534.  
  1535.     /*
  1536.      * Two characters are special: NUL and K_SPECIAL.
  1537.      * Replace       NUL by K_SPECIAL KS_ZERO     K_FILLER
  1538.      * Replace K_SPECIAL by K_SPECIAL KS_SPECIAL K_FILLER
  1539.      * Don't replace K_SPECIAL when reading a script file.
  1540.      */
  1541.     for (i = len; --i >= 0; ++buf)
  1542.     {
  1543.         if (buf[0] == NUL || (buf[0] == K_SPECIAL && c < 0))
  1544.         {
  1545.             vim_memmove(buf + 3, buf + 1, (size_t)i);
  1546.             buf[2] = K_THIRD(buf[0]);
  1547.             buf[1] = K_SECOND(buf[0]);
  1548.             buf[0] = K_SPECIAL;
  1549.             buf += 2;
  1550.             len += 2;
  1551.         }
  1552.     }
  1553.     *buf = NUL;                                /* add trailing NUL */
  1554.     return len;
  1555. }
  1556.  
  1557. /*
  1558.  * map[!]                    : show all key mappings
  1559.  * map[!] {lhs}                : show key mapping for {lhs}
  1560.  * map[!] {lhs} {rhs}        : set key mapping for {lhs} to {rhs}
  1561.  * noremap[!] {lhs} {rhs}    : same, but no remapping for {rhs}
  1562.  * unmap[!] {lhs}            : remove key mapping for {lhs}
  1563.  * abbr                        : show all abbreviations
  1564.  * abbr {lhs}                : show abbreviations for {lhs}
  1565.  * abbr {lhs} {rhs}            : set abbreviation for {lhs} to {rhs}
  1566.  * noreabbr {lhs} {rhs}        : same, but no remapping for {rhs}
  1567.  * unabbr {lhs}                : remove abbreviation for {lhs}
  1568.  *
  1569.  * maptype == 1 for unmap command, 2 for noremap command.
  1570.  *
  1571.  * keys is pointer to any arguments. Note: keys cannot be a read-only string,
  1572.  * it will be modified.
  1573.  *
  1574.  * for :map      mode is NORMAL + VISUAL
  1575.  * for :map!  mode is INSERT + CMDLINE
  1576.  * for :cmap  mode is CMDLINE
  1577.  * for :imap  mode is INSERT 
  1578.  * for :nmap  mode is NORMAL
  1579.  * for :vmap  mode is VISUAL
  1580.  * for :abbr  mode is INSERT + CMDLINE + ABBREV
  1581.  * for :iabbr mode is INSERT + ABBREV
  1582.  * for :cabbr mode is CMDLINE + ABBREV
  1583.  * 
  1584.  * Return 0 for success
  1585.  *          1 for invalid arguments
  1586.  *          2 for no match
  1587.  *          3 for ambiguety
  1588.  *          4 for out of mem
  1589.  */
  1590.     int
  1591. do_map(maptype, keys, mode)
  1592.     int        maptype;
  1593.     char_u    *keys;
  1594.     int        mode;
  1595. {
  1596.     struct mapblock        *mp, *mprev;
  1597.     char_u                *arg;
  1598.     char_u                *p;
  1599.     int                    n;
  1600.     int                    len = 0;        /* init for GCC */
  1601.     char_u                *newstr;
  1602.     int                    hasarg;
  1603.     int                    haskey;
  1604.     int                    did_it = FALSE;
  1605.     int                    abbrev = 0;
  1606.     int                    round;
  1607.     char_u                *keys_buf = NULL;
  1608.     char_u                *arg_buf = NULL;
  1609.     int                    retval = 0;
  1610.     int                    do_backslash;
  1611.  
  1612.     if (mode & ABBREV)        /* not a mapping but an abbreviation */
  1613.     {
  1614.         abbrev = ABBREV;
  1615.         mode &= ~ABBREV;
  1616.     }
  1617. /*
  1618.  * find end of keys and skip CTRL-Vs (and backslashes) in it
  1619.  * Accept backslash like CTRL-V when 'cpoptions' does not contain 'B'.
  1620.  * with :unmap white space is included in the keys, no argument possible
  1621.  */
  1622.     p = keys;
  1623.     do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
  1624.     while (*p && (maptype == 1 || !vim_iswhite(*p)))
  1625.     {
  1626.         if ((p[0] == Ctrl('V') || (do_backslash && p[0] == '\\')) &&
  1627.                                                                   p[1] != NUL)
  1628.             ++p;                /* skip CTRL-V or backslash */
  1629.         ++p;
  1630.     }
  1631.     if (*p != NUL)
  1632.         *p++ = NUL;
  1633.     p = skipwhite(p);
  1634.     arg = p;
  1635.     hasarg = (*arg != NUL);
  1636.     haskey = (*keys != NUL);
  1637.  
  1638.         /* check for :unmap without argument */
  1639.     if (maptype == 1 && !haskey)    
  1640.     {
  1641.         retval = 1;
  1642.         goto theend;
  1643.     }
  1644.  
  1645.     /*
  1646.      * If mapping has been given as ^V<C_UP> say, then replace the term codes
  1647.      * with the appropriate two bytes. If it is a shifted special key, unshift
  1648.      * it too, giving another two bytes.
  1649.      * replace_termcodes() may move the result to allocated memory, which
  1650.      * needs to be freed later (*keys_buf and *arg_buf).
  1651.      * replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
  1652.      */
  1653.     if (haskey)
  1654.         keys = replace_termcodes(keys, &keys_buf, TRUE);
  1655.     if (hasarg)
  1656.         arg = replace_termcodes(arg, &arg_buf, FALSE);
  1657.  
  1658. /*
  1659.  * check arguments and translate function keys
  1660.  */
  1661.     if (haskey)
  1662.     {
  1663.         len = STRLEN(keys);
  1664.         if (len > MAXMAPLEN)            /* maximum length of MAXMAPLEN chars */
  1665.         {
  1666.             retval = 1;
  1667.             goto theend;
  1668.         }
  1669.  
  1670.         if (abbrev)
  1671.         {
  1672.             /*
  1673.              * If an abbreviation ends in a keyword character, the
  1674.              * rest must be all keyword-char or all non-keyword-char.
  1675.              * Otherwise we won't be able to find the start of it in a
  1676.              * vi-compatible way.
  1677.              * An abbrevation cannot contain white space.
  1678.              */
  1679.             if (iswordchar(keys[len - 1]))      /* ends in keyword char */
  1680.                 for (n = 0; n < len - 2; ++n)
  1681.                     if (iswordchar(keys[n]) != iswordchar(keys[len - 2]))
  1682.                     {
  1683.                         retval = 1;
  1684.                         goto theend;
  1685.                     }
  1686.             for (n = 0; n < len; ++n)
  1687.                 if (vim_iswhite(keys[n]))
  1688.                 {
  1689.                     retval = 1;
  1690.                     goto theend;
  1691.                 }
  1692.         }
  1693.     }
  1694.  
  1695.     if (haskey && hasarg && abbrev)        /* if we will add an abbreviation */
  1696.         no_abbr = FALSE;                /* reset flag that indicates there are
  1697.                                                             no abbreviations */
  1698.  
  1699.     if (!haskey || (maptype != 1 && !hasarg))
  1700.         msg_start();
  1701. /*
  1702.  * Find an entry in the maplist that matches.
  1703.  * For :unmap we may loop two times: once to try to unmap an entry with a
  1704.  * matching 'from' part, a second time, if the first fails, to unmap an
  1705.  * entry with a matching 'to' part. This was done to allow ":ab foo bar" to be
  1706.  * unmapped by typing ":unab foo", where "foo" will be replaced by "bar" because
  1707.  * of the abbreviation.
  1708.  */
  1709.     for (round = 0; (round == 0 || maptype == 1) && round <= 1 &&
  1710.                                                  !did_it && !got_int; ++round)
  1711.     {
  1712.         for (mp = maplist.m_next, mprev = &maplist; mp && !got_int;
  1713.                                                   mprev = mp, mp = mp->m_next)
  1714.         {
  1715.                                         /* skip entries with wrong mode */
  1716.             if (!(mp->m_mode & mode) || (mp->m_mode & ABBREV) != abbrev)
  1717.                 continue;
  1718.             if (!haskey)                        /* show all entries */
  1719.             {
  1720.                 showmap(mp);
  1721.                 did_it = TRUE;
  1722.             }
  1723.             else                                /* do we have a match? */
  1724.             {
  1725.                 if (round)        /* second round: try 'to' string for unmap */
  1726.                 {
  1727.                     n = STRLEN(mp->m_str);
  1728.                     p = mp->m_str;
  1729.                 }
  1730.                 else
  1731.                 {
  1732.                     n = mp->m_keylen;
  1733.                     p = mp->m_keys;
  1734.                 }
  1735.                 if (!STRNCMP(p, keys, (size_t)(n < len ? n : len)))
  1736.                 {
  1737.                     if (maptype == 1)            /* delete entry */
  1738.                     {
  1739.                         if (n != len)            /* not a full match */
  1740.                             continue;
  1741.                         /*
  1742.                          * We reset the indicated mode bits. If nothing is
  1743.                          * left the entry is deleted below.
  1744.                          */
  1745.                         mp->m_mode &= (~mode | ABBREV);
  1746.                         did_it = TRUE;            /* remember that we did something */
  1747.                     }
  1748.                     else if (!hasarg)            /* show matching entry */
  1749.                     {
  1750.                         showmap(mp);
  1751.                         did_it = TRUE;
  1752.                     }
  1753.                     else if (n != len)            /* new entry is ambigious */
  1754.                     {
  1755.                         if (abbrev)                /* for abbreviations that's ok */
  1756.                             continue;
  1757.                         retval = 3;
  1758.                         goto theend;
  1759.                     }
  1760.                     else
  1761.                     {
  1762.                         mp->m_mode &= (~mode | ABBREV);        /* remove mode bits */
  1763.                         if (!(mp->m_mode & ~ABBREV) && !did_it)    /* reuse existing entry */
  1764.                         {
  1765.                             newstr = strsave(arg);
  1766.                             if (newstr == NULL)
  1767.                             {
  1768.                                 retval = 4;            /* no mem */
  1769.                                 goto theend;
  1770.                             }
  1771.                             vim_free(mp->m_str);
  1772.                             mp->m_str = newstr;
  1773.                             mp->m_noremap = maptype;
  1774.                             mp->m_mode = mode + abbrev;
  1775.                             did_it = TRUE;
  1776.                         }
  1777.                     }
  1778.                     if (!(mp->m_mode & ~ABBREV))    /* entry can be deleted */
  1779.                     {
  1780.                         map_free(mprev);
  1781.                         mp = mprev;                /* continue with next entry */
  1782.                     }
  1783.                 }
  1784.             }
  1785.         }
  1786.     }
  1787.  
  1788.     if (maptype == 1)                        /* delete entry */
  1789.     {
  1790.         if (!did_it)
  1791.             retval = 2;                        /* no match */
  1792.         goto theend;
  1793.     }
  1794.  
  1795.     if (!haskey || !hasarg)                    /* print entries */
  1796.     {
  1797.         if (!did_it)
  1798.         {
  1799.             if (abbrev)
  1800.                 MSG("No abbreviation found");
  1801.             else
  1802.                 MSG("No mapping found");
  1803.         }
  1804.         goto theend;                        /* listing finished */
  1805.     }
  1806.  
  1807.     if (did_it)                    /* have added the new entry already */
  1808.         goto theend;
  1809. /*
  1810.  * get here when we have to add a new entry
  1811.  */
  1812.         /* allocate a new entry for the maplist */
  1813.     mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
  1814.     if (mp == NULL)
  1815.     {
  1816.         retval = 4;            /* no mem */
  1817.         goto theend;
  1818.     }
  1819.     mp->m_keys = strsave(keys);
  1820.     mp->m_str = strsave(arg);
  1821.     if (mp->m_keys == NULL || mp->m_str == NULL)
  1822.     {
  1823.         vim_free(mp->m_keys);
  1824.         vim_free(mp->m_str);
  1825.         vim_free(mp);
  1826.         retval = 4;        /* no mem */
  1827.         goto theend;
  1828.     }
  1829.     mp->m_keylen = STRLEN(mp->m_keys);
  1830.     mp->m_noremap = maptype;
  1831.     mp->m_mode = mode + abbrev;
  1832.  
  1833.     /* add the new entry in front of the maplist */
  1834.     mp->m_next = maplist.m_next;
  1835.     maplist.m_next = mp;
  1836.  
  1837. theend:
  1838.     vim_free(keys_buf);
  1839.     vim_free(arg_buf);
  1840.     return retval;
  1841. }
  1842.  
  1843. /*
  1844.  * Delete one entry from the maplist.
  1845.  * The argument is a pointer to the PREVIOUS entry!
  1846.  */
  1847.     static void
  1848. map_free(mprev)
  1849.     struct mapblock        *mprev;
  1850. {
  1851.     struct mapblock        *mp;
  1852.     
  1853.     mp = mprev->m_next;
  1854.     vim_free(mp->m_keys);
  1855.     vim_free(mp->m_str);
  1856.     mprev->m_next = mp->m_next;
  1857.     vim_free(mp);
  1858. }
  1859.  
  1860. /*
  1861.  * Clear all mappings or abbreviations.
  1862.  * 'abbr' should be FALSE for mappings, TRUE for abbreviations.
  1863.  */
  1864.     void
  1865. map_clear(modec, forceit, abbr)
  1866.     int        modec;
  1867.     int        forceit;
  1868.     int        abbr;
  1869. {
  1870.     struct mapblock        *mp;
  1871.     int        mode;
  1872.  
  1873.     if (forceit)            /* :mapclear! */
  1874.         mode = INSERT + CMDLINE;
  1875.     else if (modec == 'i')
  1876.         mode = INSERT;
  1877.     else if (modec == 'n')
  1878.         mode = NORMAL;
  1879.     else if (modec == 'c')
  1880.         mode = CMDLINE;
  1881.     else if (modec == 'v')
  1882.         mode = VISUAL;
  1883.     else
  1884.         mode = VISUAL + NORMAL;
  1885.  
  1886.     for (mp = &maplist; mp->m_next != NULL; )
  1887.     {
  1888.         if (abbr != !(mp->m_next->m_mode & ABBREV) && mp->m_next->m_mode & mode)
  1889.         {
  1890.             mp->m_next->m_mode &= ~mode;
  1891.             if ((mp->m_next->m_mode & ~ABBREV) == 0) /* entry can be deleted */
  1892.             {
  1893.                 map_free(mp);
  1894.                 continue;
  1895.             }
  1896.         }
  1897.         mp = mp->m_next;
  1898.     }
  1899. }
  1900.  
  1901.     static void
  1902. showmap(mp)
  1903.     struct mapblock *mp;
  1904. {
  1905.     int len;
  1906.  
  1907.     if (msg_didout)
  1908.         msg_outchar('\n');
  1909.     if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
  1910.         MSG_OUTSTR("! ");
  1911.     else if (mp->m_mode & INSERT)
  1912.         MSG_OUTSTR("i ");
  1913.     else if (mp->m_mode & CMDLINE)
  1914.         MSG_OUTSTR("c ");
  1915.     else if (!(mp->m_mode & VISUAL))
  1916.         MSG_OUTSTR("n ");
  1917.     else if (!(mp->m_mode & NORMAL))
  1918.         MSG_OUTSTR("v ");
  1919.     else
  1920.         MSG_OUTSTR("  ");
  1921.     /* Get length of what we write */
  1922.     len = msg_outtrans_special(mp->m_keys, TRUE);
  1923.     do
  1924.     {
  1925.         msg_outchar(' ');                /* padd with blanks */
  1926.         ++len;
  1927.     } while (len < 12);
  1928.     if (mp->m_noremap)
  1929.         msg_outchar('*');
  1930.     else
  1931.         msg_outchar(' ');
  1932.     /* Use FALSE below if we only want things like <Up> to show up as such on
  1933.      * the rhs, and not M-x etc, TRUE gets both -- webb
  1934.      */
  1935.     msg_outtrans_special(mp->m_str, TRUE);
  1936.     flushbuf();                            /* show one line at a time */
  1937. }
  1938.  
  1939. /*
  1940.  * Check for an abbreviation.
  1941.  * Cursor is at ptr[col]. When inserting, mincol is where insert started.
  1942.  * "c" is the character typed before check_abbr was called.
  1943.  *
  1944.  * Historic vi practice: The last character of an abbreviation must be an id
  1945.  * character ([a-zA-Z0-9_]). The characters in front of it must be all id
  1946.  * characters or all non-id characters. This allows for abbr. "#i" to
  1947.  * "#include".
  1948.  *
  1949.  * Vim addition: Allow for abbreviations that end in a non-keyword character.
  1950.  * Then there must be white space before the abbr.
  1951.  *
  1952.  * return TRUE if there is an abbreviation, FALSE if not
  1953.  */
  1954.     int
  1955. check_abbr(c, ptr, col, mincol)
  1956.     int        c;
  1957.     char_u    *ptr;
  1958.     int        col;
  1959.     int        mincol;
  1960. {
  1961.     int                len;
  1962.     int                j;
  1963.     char_u            tb[4];
  1964.     struct mapblock *mp;
  1965.     int                is_id = TRUE;
  1966.     int                vim_abbr;
  1967.  
  1968.     if (no_abbr_cnt)        /* abbrev. are not recursive */
  1969.         return FALSE;
  1970.  
  1971.     /*
  1972.      * Check for word before the cursor: If it ends in a keyword char all
  1973.      * chars before it must be al keyword chars or non-keyword chars, but not
  1974.      * white space. If it ends in a non-keyword char we accept any characters
  1975.      * before it except white space.
  1976.      */
  1977.     if (col == 0)                                /* cannot be an abbr. */
  1978.         return FALSE;
  1979.  
  1980.     if (!iswordchar(ptr[col - 1]))
  1981.         vim_abbr = TRUE;                        /* Vim added abbr. */
  1982.     else
  1983.     {
  1984.         vim_abbr = FALSE;                        /* vi compatible abbr. */
  1985.         if (col > 1)
  1986.             is_id = iswordchar(ptr[col - 2]);
  1987.     }
  1988.     for (len = col - 1; len > 0 && !vim_isspace(ptr[len - 1]) &&
  1989.                        (vim_abbr || is_id == iswordchar(ptr[len - 1])); --len)
  1990.         ;
  1991.  
  1992.     if (len < mincol)
  1993.         len = mincol;
  1994.     if (len < col)                /* there is a word in front of the cursor */
  1995.     {
  1996.         ptr += len;
  1997.         len = col - len;
  1998.         for (mp = maplist.m_next; mp; mp = mp->m_next)
  1999.         {
  2000.                     /* find entries with right mode and keys */
  2001.             if ((mp->m_mode & ABBREV) == ABBREV &&
  2002.                         (mp->m_mode & State) &&
  2003.                         mp->m_keylen == len &&
  2004.                         !STRNCMP(mp->m_keys, ptr, (size_t)len))
  2005.                 break;
  2006.         }
  2007.         if (mp)
  2008.         {
  2009.             /*
  2010.              * Found a match:
  2011.              * Insert the rest of the abbreviation in typebuf[].
  2012.              * This goes from end to start.
  2013.              *
  2014.              * Characters 0x000 - 0x100: normal chars, may need CTRL-V,
  2015.              * except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL K_FILLER
  2016.              * Characters where IS_SPECIAL() == TRUE: key codes, need
  2017.              * K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
  2018.              */
  2019.             j = 0;
  2020.                                             /* special key code, split up */
  2021.             if (IS_SPECIAL(c) || c == K_SPECIAL)
  2022.             {
  2023.                 tb[j++] = K_SPECIAL;
  2024.                 tb[j++] = K_SECOND(c);
  2025.                 c = K_THIRD(c);
  2026.             }
  2027.             else if (c < 0x100  && (c < ' ' || c > '~'))
  2028.                 tb[j++] = Ctrl('V');        /* special char needs CTRL-V */
  2029.             tb[j++] = c;
  2030.             tb[j] = NUL;
  2031.                                             /* insert the last typed char */
  2032.             (void)ins_typebuf(tb, TRUE, 0, TRUE);
  2033.                                             /* insert the to string */
  2034.             (void)ins_typebuf(mp->m_str, mp->m_noremap ? -1 : 0, 0, TRUE);
  2035.                                             /* no abbrev. for these chars */
  2036.             no_abbr_cnt += STRLEN(mp->m_str) + j + 1;
  2037.  
  2038.             tb[0] = Ctrl('H');
  2039.             tb[1] = NUL;
  2040.             while (len--)                    /* delete the from string */
  2041.                 (void)ins_typebuf(tb, TRUE, 0, TRUE);
  2042.             return TRUE;
  2043.         }
  2044.     }
  2045.     return FALSE;
  2046. }
  2047.  
  2048. /*
  2049.  * Write map commands for the current mappings to an .exrc file.
  2050.  * Return FAIL on error, OK otherwise.
  2051.  */
  2052.     int
  2053. makemap(fd)
  2054.     FILE *fd;
  2055. {
  2056.     struct mapblock *mp;
  2057.     char_u            c1;
  2058.     char_u             *p;
  2059.  
  2060.     for (mp = maplist.m_next; mp; mp = mp->m_next)
  2061.     {
  2062.         c1 = NUL;
  2063.         p = (char_u *)"map";
  2064.         switch (mp->m_mode)
  2065.         {
  2066.         case NORMAL + VISUAL:
  2067.             break;
  2068.         case NORMAL:
  2069.             c1 = 'n';
  2070.             break;
  2071.         case VISUAL:
  2072.             c1 = 'v';
  2073.             break;
  2074.         case CMDLINE + INSERT:
  2075.             p = (char_u *)"map!";
  2076.             break;
  2077.         case CMDLINE:
  2078.             c1 = 'c';
  2079.             break;
  2080.         case INSERT:
  2081.             c1 = 'i';
  2082.             break;
  2083.         case INSERT + CMDLINE + ABBREV:
  2084.             p = (char_u *)"abbr";
  2085.             break;
  2086.         case CMDLINE + ABBREV:
  2087.             c1 = 'c';
  2088.             p = (char_u *)"abbr";
  2089.             break;
  2090.         case INSERT + ABBREV:
  2091.             c1 = 'i';
  2092.             p = (char_u *)"abbr";
  2093.             break;
  2094.         default:
  2095.             EMSG("makemap: Illegal mode");
  2096.             return FAIL;
  2097.         }
  2098.         if (c1 && putc(c1, fd) < 0)
  2099.             return FAIL;
  2100.         if (mp->m_noremap && fprintf(fd, "nore") < 0)
  2101.             return FAIL;
  2102.         if (fprintf(fd, (char *)p) < 0)
  2103.             return FAIL;
  2104.  
  2105.         if (    putc(' ', fd) < 0 || putescstr(fd, mp->m_keys, FALSE) == FAIL ||
  2106.                 putc(' ', fd) < 0 || putescstr(fd, mp->m_str, FALSE) == FAIL ||
  2107. #ifdef USE_CRNL
  2108.                 putc('\r', fd) < 0 ||
  2109. #endif
  2110.                 putc('\n', fd) < 0)
  2111.             return FAIL;
  2112.     }
  2113.     return OK;
  2114. }
  2115.  
  2116. /*
  2117.  * write escape string to file
  2118.  *
  2119.  * return FAIL for failure, OK otherwise
  2120.  */
  2121.     int
  2122. putescstr(fd, str, set)
  2123.     FILE        *fd;
  2124.     char_u        *str;
  2125.     int            set;        /* TRUE for makeset, FALSE for makemap */
  2126. {
  2127.     int        c;
  2128.     int        modifiers;
  2129.  
  2130.     for ( ; *str; ++str)
  2131.     {
  2132.         c = *str;
  2133.         /*
  2134.          * Special key codes have to be translated to be able to make sense
  2135.          * when they are read back.
  2136.          */
  2137.         if (c == K_SPECIAL && !set)
  2138.         {
  2139.             modifiers = 0x0;
  2140.             if (str[1] == KS_MODIFIER)
  2141.             {
  2142.                 modifiers = str[2];
  2143.                 str += 3;
  2144.                 c = *str;
  2145.             }
  2146.             if (c == K_SPECIAL)
  2147.             {
  2148.                 c = TO_SPECIAL(str[1], str[2]);
  2149.                 str += 2;
  2150.             }
  2151.             if (IS_SPECIAL(c) || modifiers)        /* special key */
  2152.             {
  2153.                 fprintf(fd, (char *)get_special_key_name(c, modifiers));
  2154.                 continue;
  2155.             }
  2156.         }
  2157.         /*
  2158.          * A '\n' in a map command should be written as <NL>.
  2159.          * A '\n' in a set command should be written as \^V^J.
  2160.          */
  2161.         if (c == NL)
  2162.         {
  2163.             if (set)
  2164.                 fprintf(fd, "\\\026\n");
  2165.             else
  2166.                 fprintf(fd, "<NL>");
  2167.             continue;
  2168.         }
  2169.         /*
  2170.          * some characters have to be escaped with CTRL-V to
  2171.          * prevent them from misinterpreted in DoOneCmd().
  2172.          * A space, Tab and '"' has to be escaped with a backslash to
  2173.          * prevent it to be misinterpreted in do_set().
  2174.          */
  2175.         if (set && (vim_iswhite(c) || c == '"' || c == '\\'))
  2176.         {
  2177.             if (putc('\\', fd) < 0)
  2178.                 return FAIL;
  2179.         }
  2180.         else if (c < ' ' || c > '~' || c == '|')
  2181.         {
  2182.             if (putc(Ctrl('V'), fd) < 0)
  2183.                 return FAIL;
  2184.         }
  2185.         if (putc(c, fd) < 0)
  2186.             return FAIL;
  2187.     }
  2188.     return OK;
  2189. }
  2190.  
  2191. /*
  2192.  * Check all mappings for the presence of special key codes.
  2193.  * Used after ":set term=xxx".
  2194.  */
  2195.     void
  2196. check_map_keycodes()
  2197. {
  2198.     struct mapblock *mp;
  2199.     char_u             *p;
  2200.     int                i;
  2201.     char_u            buf[3];
  2202.     char_u            *save_name;
  2203.  
  2204.     save_name = sourcing_name;
  2205.     sourcing_name = (char_u *)"mappings";/* don't give error messages */
  2206.     for (mp = maplist.m_next; mp != NULL; mp = mp->m_next)
  2207.     {
  2208.         for (i = 0; i <= 1; ++i)        /* do this twice */
  2209.         {
  2210.             if (i == 0)
  2211.                 p = mp->m_keys;            /* once for the "from" part */
  2212.             else
  2213.                 p = mp->m_str;            /* and once for the "to" part */
  2214.             while (*p)
  2215.             {
  2216.                 if (*p == K_SPECIAL)
  2217.                 {
  2218.                     ++p;
  2219.                     if (*p < 128)        /* only for "normal" termcap entries */
  2220.                     {
  2221.                         buf[0] = p[0];
  2222.                         buf[1] = p[1];
  2223.                         buf[2] = NUL;
  2224.                         (void)add_termcap_entry(buf, FALSE);
  2225.                     }
  2226.                     ++p;
  2227.                 }
  2228.                 ++p;
  2229.             }
  2230.         }
  2231.     }
  2232.     sourcing_name = save_name;
  2233. }
  2234.