[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.2

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