[BACK]Return to getchar.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

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: }