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

Annotation of src/usr.bin/vim/cmdline.c, Revision 1.1.1.1

1.1       downsj      1: /* $OpenBSD$   */
                      2: /* vi:set ts=4 sw=4:
                      3:  *
                      4:  * VIM - Vi IMproved       by Bram Moolenaar
                      5:  *
                      6:  * Do ":help uganda"  in Vim to read copying and usage conditions.
                      7:  * Do ":help credits" in Vim to see a list of people who contributed.
                      8:  */
                      9:
                     10: /*
                     11:  * cmdline.c: functions for reading in the command line and executing it
                     12:  */
                     13:
                     14: #include "vim.h"
                     15: #include "globals.h"
                     16: #include "proto.h"
                     17: #include "option.h"
                     18: #include "cmdtab.h"
                     19: #include "ops.h"           /* included because we call functions in ops.c */
                     20: #ifdef HAVE_FCNTL_H
                     21: # include <fcntl.h>            /* for chdir() */
                     22: #endif
                     23:
                     24: /*
                     25:  * variables shared between getcmdline() and redrawcmdline()
                     26:  */
                     27: static char_u  *cmdbuff;       /* pointer to command line buffer */
                     28: static int      cmdbufflen;    /* length of cmdbuff */
                     29: static int      cmdlen;        /* number of chars on command line */
                     30: static int      cmdpos;        /* current cursor position */
                     31: static int      cmdspos;       /* cursor column on screen */
                     32: static int      cmdfirstc;     /* ':', '/' or '?' */
                     33:
                     34: /*
                     35:  * Typing mode on the command line.  Shared by getcmdline() and
                     36:  * put_on_cmdline().
                     37:  */
                     38: static int     overstrike = FALSE; /* typing mode */
                     39:
                     40: /*
                     41:  * The next two variables contain the bounds of any range given in a command.
                     42:  * They are set by do_cmdline().
                     43:  */
                     44: static linenr_t    line1, line2;
                     45:
                     46: static int         forceit;
                     47: static int         regname;
                     48: static int         quitmore = 0;
                     49: static int         cmd_numfiles = -1;    /* number of files found by
                     50:                                                    filename completion */
                     51: /*
                     52:  * There are two history tables:
                     53:  * 0: colon commands
                     54:  * 1: search commands
                     55:  */
                     56: static char_u      **(history[2]) = {NULL, NULL};  /* history tables */
                     57: static int         hisidx[2] = {-1, -1};           /* last entered entry */
                     58: static int         hislen = 0;         /* actual lengt of history tables */
                     59:
                     60: #ifdef RIGHTLEFT
                     61: static int         cmd_hkmap = 0;      /* Hebrew mapping during command line */
                     62: #endif
                     63:
                     64: static void        init_history __ARGS((void));
                     65:
                     66: static int     is_in_history __ARGS((int, char_u *, int));
                     67: static void        putcmdline __ARGS((int));
                     68: static void        redrawcmd __ARGS((void));
                     69: static void        cursorcmd __ARGS((void));
                     70: static int     ccheck_abbr __ARGS((int));
                     71: static char_u  *do_one_cmd __ARGS((char_u **, int *, int));
                     72: static int     buf_write_all __ARGS((BUF *));
                     73: static int     do_write __ARGS((char_u *, int));
                     74: static char_u  *getargcmd __ARGS((char_u **));
                     75: static void        backslash_halve __ARGS((char_u *p, int expand_wildcards));
                     76: static void        do_make __ARGS((char_u *));
                     77: static int     do_arglist __ARGS((char_u *));
                     78: static int     is_backslash __ARGS((char_u *str));
                     79: static int     check_readonly __ARGS((void));
                     80: static int     check_changed __ARGS((BUF *, int, int));
                     81: static int     check_changed_any __ARGS((void));
                     82: static int     check_more __ARGS((int));
                     83: static void        vim_strncpy __ARGS((char_u *, char_u *, int));
                     84: static int     nextwild __ARGS((int));
                     85: static int     showmatches __ARGS((char_u *));
                     86: static linenr_t get_address __ARGS((char_u **));
                     87: static void        set_expand_context __ARGS((int, char_u *));
                     88: static char_u  *set_one_cmd_context __ARGS((int, char_u *));
                     89: static int     ExpandFromContext __ARGS((char_u *, int *, char_u ***, int, int));
                     90: static int     ExpandCommands __ARGS((regexp *, int *, char_u ***));
                     91:
                     92: /*
                     93:  * init_history() - initialize the command line history
                     94:  */
                     95:    static void
                     96: init_history()
                     97: {
                     98:    int     newlen;         /* new length of history table */
                     99:    char_u  **temp;
                    100:    register int i;
                    101:    int     j;
                    102:    int     type;
                    103:
                    104:    /*
                    105:     * If size of history table changed, reallocate it
                    106:     */
                    107:    newlen = (int)p_hi;
                    108:    if (newlen != hislen)                       /* history length changed */
                    109:    {
                    110:        for (type = 0; type <= 1; ++type)       /* adjust both history tables */
                    111:        {
                    112:            if (newlen)
                    113:                temp = (char_u **)lalloc((long_u)(newlen * sizeof(char_u *)),
                    114:                                    TRUE);
                    115:            else
                    116:                temp = NULL;
                    117:            if (newlen == 0 || temp != NULL)
                    118:            {
                    119:                if (hisidx[type] < 0)           /* there are no entries yet */
                    120:                {
                    121:                    for (i = 0; i < newlen; ++i)
                    122:                        temp[i] = NULL;
                    123:                }
                    124:                else if (newlen > hislen)       /* array becomes bigger */
                    125:                {
                    126:                    for (i = 0; i <= hisidx[type]; ++i)
                    127:                        temp[i] = history[type][i];
                    128:                    j = i;
                    129:                    for ( ; i <= newlen - (hislen - hisidx[type]); ++i)
                    130:                        temp[i] = NULL;
                    131:                    for ( ; j < hislen; ++i, ++j)
                    132:                        temp[i] = history[type][j];
                    133:                }
                    134:                else                            /* array becomes smaller or 0 */
                    135:                {
                    136:                    j = hisidx[type];
                    137:                    for (i = newlen - 1; ; --i)
                    138:                    {
                    139:                        if (i >= 0)             /* copy newest entries */
                    140:                            temp[i] = history[type][j];
                    141:                        else                    /* remove older entries */
                    142:                            vim_free(history[type][j]);
                    143:                        if (--j < 0)
                    144:                            j = hislen - 1;
                    145:                        if (j == hisidx[type])
                    146:                            break;
                    147:                    }
                    148:                    hisidx[type] = newlen - 1;
                    149:                }
                    150:                vim_free(history[type]);
                    151:                history[type] = temp;
                    152:            }
                    153:        }
                    154:        hislen = newlen;
                    155:    }
                    156: }
                    157:
                    158: /*
                    159:  * check if command line 'str' is already in history
                    160:  * 'type' is 0 for ':' commands, '1' for search commands
                    161:  * if 'move_to_front' is TRUE, matching entry is moved to end of history
                    162:  */
                    163:    static int
                    164: is_in_history(type, str, move_to_front)
                    165:    int     type;
                    166:    char_u  *str;
                    167:    int     move_to_front;      /* Move the entry to the front if it exists */
                    168: {
                    169:    int     i;
                    170:    int     last_i = -1;
                    171:
                    172:    if (hisidx[type] < 0)
                    173:        return FALSE;
                    174:    i = hisidx[type];
                    175:    do
                    176:    {
                    177:        if (history[type][i] == NULL)
                    178:            return FALSE;
                    179:        if (STRCMP(str, history[type][i]) == 0)
                    180:        {
                    181:            if (!move_to_front)
                    182:                return TRUE;
                    183:            last_i = i;
                    184:            break;
                    185:        }
                    186:        if (--i < 0)
                    187:            i = hislen - 1;
                    188:    } while (i != hisidx[type]);
                    189:
                    190:    if (last_i >= 0)
                    191:    {
                    192:        str = history[type][i];
                    193:        while (i != hisidx[type])
                    194:        {
                    195:            if (++i >= hislen)
                    196:                i = 0;
                    197:            history[type][last_i] = history[type][i];
                    198:            last_i = i;
                    199:        }
                    200:        history[type][i] = str;
                    201:        return TRUE;
                    202:    }
                    203:    return FALSE;
                    204: }
                    205:
                    206: /*
                    207:  * Add the given string to the given history.  If the string is already in the
                    208:  * history then it is moved to the front.  histype may be 0 for the ':'
                    209:  * history, or 1 for the '/' history.
                    210:  */
                    211:    void
                    212: add_to_history(histype, new_entry)
                    213:    int     histype;
                    214:    char_u  *new_entry;
                    215: {
                    216:    if (hislen != 0 && !is_in_history(histype, new_entry, TRUE))
                    217:    {
                    218:        if (++hisidx[histype] == hislen)
                    219:            hisidx[histype] = 0;
                    220:        vim_free(history[histype][hisidx[histype]]);
                    221:        history[histype][hisidx[histype]] = strsave(new_entry);
                    222:    }
                    223: }
                    224:
                    225:
                    226: /*
                    227:  * getcmdline() - accept a command line starting with ':', '/', or '?'
                    228:  *
                    229:  * The line is collected in cmdbuff, which is reallocated to fit the command
                    230:  * line.
                    231:  *
                    232:  * Return pointer to allocated string if there is a commandline, NULL
                    233:  * otherwise.
                    234:  */
                    235:
                    236:    char_u *
                    237: getcmdline(firstc, count)
                    238:    int         firstc;     /* either ':', '/', or '?' */
                    239:    long        count;      /* only used for incremental search */
                    240: {
                    241:    register int        c;
                    242: #ifdef DIGRAPHS
                    243:             int        cc;
                    244: #endif
                    245:    register int        i;
                    246:             int        j;
                    247:             char_u     *p;
                    248:             int        hiscnt;             /* current history line in use */
                    249:             char_u     *lookfor = NULL;    /* string to match */
                    250:             int        gotesc = FALSE;     /* TRUE when <ESC> just typed */
                    251:             int        do_abbr;            /* when TRUE check for abbr. */
                    252:             int        histype;            /* history type to be used */
                    253:             FPOS       old_cursor;
                    254:             colnr_t    old_curswant;
                    255:             int        did_incsearch = FALSE;
                    256:             int        incsearch_postponed = FALSE;
                    257:             int        save_msg_scroll = msg_scroll;
                    258:             int        some_key_typed = FALSE; /* one of the keys was typed */
                    259: #ifdef USE_MOUSE
                    260:             /* mouse drag and release events are ignored, unless they are
                    261:              * preceded with a mouse down event */
                    262:             int        ignore_drag_release = TRUE;
                    263: #endif
                    264:
                    265:    overstrike = FALSE;                     /* always start in insert mode */
                    266:    old_cursor = curwin->w_cursor;          /* needs to be restored later */
                    267:    old_curswant = curwin->w_curswant;
                    268: /*
                    269:  * set some variables for redrawcmd()
                    270:  */
                    271:    cmdfirstc = firstc;
                    272:    alloc_cmdbuff(0);                   /* allocate initial cmdbuff */
                    273:    if (cmdbuff == NULL)
                    274:        return NULL;                    /* out of memory */
                    275:    cmdlen = cmdpos = 0;
                    276:    cmdspos = 1;
                    277:    State = CMDLINE;
                    278: #ifdef USE_MOUSE
                    279:    setmouse();
                    280: #endif
                    281:    gotocmdline(TRUE);
                    282:    msg_outchar(firstc);
                    283:    /*
                    284:     * Avoid scrolling when called by a recursive do_cmdline(), e.g. when doing
                    285:     * ":@0" when register 0 doesn't contain a CR.
                    286:     */
                    287:    msg_scroll = FALSE;
                    288:
                    289:    init_history();
                    290:    hiscnt = hislen;            /* set hiscnt to impossible history value */
                    291:    histype = (firstc == ':' ? 0 : 1);
                    292:
                    293: #ifdef DIGRAPHS
                    294:    do_digraph(-1);             /* init digraph typahead */
                    295: #endif
                    296:
                    297:    /* collect the command string, handling editing keys */
                    298:    for (;;)
                    299:    {
                    300:        cursorcmd();            /* set the cursor on the right spot */
                    301:        c = vgetc();
                    302:        if (KeyTyped)
                    303:        {
                    304:            some_key_typed = TRUE;
                    305: #ifdef RIGHTLEFT
                    306:            if (cmd_hkmap)
                    307:                c = hkmap(c);
                    308: #endif
                    309:        }
                    310:        if (c == Ctrl('C'))
                    311:            got_int = FALSE;    /* ignore got_int when CTRL-C was typed here */
                    312:
                    313:            /* free old command line when finished moving around in the
                    314:             * history list */
                    315:        if (lookfor && c != K_S_DOWN && c != K_S_UP &&
                    316:                c != K_DOWN && c != K_UP &&
                    317:                c != K_PAGEDOWN && c != K_PAGEUP &&
                    318:                (cmd_numfiles > 0 || (c != Ctrl('P') && c != Ctrl('N'))))
                    319:        {
                    320:            vim_free(lookfor);
                    321:            lookfor = NULL;
                    322:        }
                    323:
                    324:        /*
                    325:         * <S-Tab> works like CTRL-P (unless 'wc' is <S-Tab>).
                    326:         */
                    327:        if (c != p_wc && c == K_S_TAB)
                    328:            c = Ctrl('P');
                    329:
                    330:            /* free expanded names when finished walking through matches */
                    331:        if (cmd_numfiles != -1 && !(c == p_wc && KeyTyped) && c != Ctrl('N') &&
                    332:                        c != Ctrl('P') && c != Ctrl('A') && c != Ctrl('L'))
                    333:            (void)ExpandOne(NULL, NULL, 0, WILD_FREE);
                    334:
                    335: #ifdef DIGRAPHS
                    336:        c = do_digraph(c);
                    337: #endif
                    338:
                    339:        if (c == '\n' || c == '\r' || (c == ESC && (!KeyTyped ||
                    340:                                         vim_strchr(p_cpo, CPO_ESC) != NULL)))
                    341:        {
                    342:            if (ccheck_abbr(c + ABBR_OFF))
                    343:                goto cmdline_changed;
                    344:            outchar('\r');      /* show that we got the return */
                    345:            screen_cur_col = 0;
                    346:            flushbuf();
                    347:            break;
                    348:        }
                    349:
                    350:            /* hitting <ESC> twice means: abandon command line */
                    351:            /* wildcard expansion is only done when the key is really typed,
                    352:             * not when it comes from a macro */
                    353:        if (c == p_wc && !gotesc && KeyTyped)
                    354:        {
                    355:            if (cmd_numfiles > 0)   /* typed p_wc twice */
                    356:                i = nextwild(WILD_NEXT);
                    357:            else                    /* typed p_wc first time */
                    358:                i = nextwild(WILD_EXPAND_KEEP);
                    359:            if (c == ESC)
                    360:                gotesc = TRUE;
                    361:            if (i)
                    362:                goto cmdline_changed;
                    363:        }
                    364:        gotesc = FALSE;
                    365:
                    366:        if (c == NUL || c == K_ZERO)        /* NUL is stored as NL */
                    367:            c = NL;
                    368:
                    369:        do_abbr = TRUE;         /* default: check for abbreviation */
                    370:        switch (c)
                    371:        {
                    372:        case K_BS:
                    373:        case Ctrl('H'):
                    374:        case K_DEL:
                    375:        case Ctrl('W'):
                    376:                /*
                    377:                 * delete current character is the same as backspace on next
                    378:                 * character, except at end of line
                    379:                 */
                    380:                if (c == K_DEL && cmdpos != cmdlen)
                    381:                    ++cmdpos;
                    382:                if (cmdpos > 0)
                    383:                {
                    384:                    j = cmdpos;
                    385:                    if (c == Ctrl('W'))
                    386:                    {
                    387:                        while (cmdpos && vim_isspace(cmdbuff[cmdpos - 1]))
                    388:                            --cmdpos;
                    389:                        i = iswordchar(cmdbuff[cmdpos - 1]);
                    390:                        while (cmdpos && !vim_isspace(cmdbuff[cmdpos - 1]) &&
                    391:                                         iswordchar(cmdbuff[cmdpos - 1]) == i)
                    392:                            --cmdpos;
                    393:                    }
                    394:                    else
                    395:                        --cmdpos;
                    396:                    cmdlen -= j - cmdpos;
                    397:                    i = cmdpos;
                    398:                    while (i < cmdlen)
                    399:                        cmdbuff[i++] = cmdbuff[j++];
                    400:                    redrawcmd();
                    401:                }
                    402:                else if (cmdlen == 0 && c != Ctrl('W'))
                    403:                {
                    404:                    vim_free(cmdbuff);      /* no commandline to return */
                    405:                    cmdbuff = NULL;
                    406:                    msg_pos(-1, 0);
                    407:                    msg_outchar(' ');   /* delete ':' */
                    408:                    redraw_cmdline = TRUE;
                    409:                    goto returncmd;     /* back to cmd mode */
                    410:                }
                    411:                goto cmdline_changed;
                    412:
                    413:        case K_INS:
                    414:                overstrike = !overstrike;
                    415:                /* should change shape of cursor */
                    416:                goto cmdline_not_changed;
                    417:
                    418: /*     case '@':   only in very old vi */
                    419:        case Ctrl('U'):
                    420:                cmdpos = 0;
                    421:                cmdlen = 0;
                    422:                cmdspos = 1;
                    423:                redrawcmd();
                    424:                goto cmdline_changed;
                    425:
                    426:        case ESC:       /* get here if p_wc != ESC or when ESC typed twice */
                    427:        case Ctrl('C'):
                    428:                gotesc = TRUE;      /* will free cmdbuff after putting it in
                    429:                                        history */
                    430:                goto returncmd;     /* back to cmd mode */
                    431:
                    432:        case Ctrl('R'):             /* insert register */
                    433:                putcmdline('"');
                    434:                ++no_mapping;
                    435:                c = vgetc();
                    436:                --no_mapping;
                    437:                if (c != ESC)       /* use ESC to cancel inserting register */
                    438:                    cmdline_paste(c);
                    439:                redrawcmd();
                    440:                goto cmdline_changed;
                    441:
                    442:        case Ctrl('D'):
                    443:            {
                    444:                if (showmatches(cmdbuff) == FAIL)
                    445:                    break;      /* Use ^D as normal char instead */
                    446:
                    447:                redrawcmd();
                    448:                continue;       /* don't do incremental search now */
                    449:            }
                    450:
                    451:        case K_RIGHT:
                    452:        case K_S_RIGHT:
                    453:                do
                    454:                {
                    455:                        if (cmdpos >= cmdlen)
                    456:                                break;
                    457:                        cmdspos += charsize(cmdbuff[cmdpos]);
                    458:                        ++cmdpos;
                    459:                }
                    460:                while (c == K_S_RIGHT && cmdbuff[cmdpos] != ' ');
                    461:                goto cmdline_not_changed;
                    462:
                    463:        case K_LEFT:
                    464:        case K_S_LEFT:
                    465:                do
                    466:                {
                    467:                        if (cmdpos <= 0)
                    468:                                break;
                    469:                        --cmdpos;
                    470:                        cmdspos -= charsize(cmdbuff[cmdpos]);
                    471:                }
                    472:                while (c == K_S_LEFT && cmdbuff[cmdpos - 1] != ' ');
                    473:                goto cmdline_not_changed;
                    474:
                    475: #ifdef USE_MOUSE
                    476:        case K_MIDDLEDRAG:
                    477:        case K_MIDDLERELEASE:
                    478:        case K_IGNORE:
                    479:                goto cmdline_not_changed;   /* Ignore mouse */
                    480:
                    481:        case K_MIDDLEMOUSE:
                    482: # ifdef USE_GUI
                    483:                /* When GUI is active, also paste when 'mouse' is empty */
                    484:                if (!gui.in_use)
                    485: # endif
                    486:                    if (!mouse_has(MOUSE_COMMAND))
                    487:                        goto cmdline_not_changed;   /* Ignore mouse */
                    488: # ifdef USE_GUI
                    489:                if (gui.in_use && yankbuffer == 0)
                    490:                    cmdline_paste('*');
                    491:                else
                    492: # endif
                    493:                    cmdline_paste(yankbuffer);
                    494:                redrawcmd();
                    495:                goto cmdline_changed;
                    496:
                    497:        case K_LEFTDRAG:
                    498:        case K_LEFTRELEASE:
                    499:        case K_RIGHTDRAG:
                    500:        case K_RIGHTRELEASE:
                    501:                if (ignore_drag_release)
                    502:                    goto cmdline_not_changed;
                    503:                /* FALLTHROUGH */
                    504:        case K_LEFTMOUSE:
                    505:        case K_RIGHTMOUSE:
                    506:                if (c == K_LEFTRELEASE || c == K_RIGHTRELEASE)
                    507:                    ignore_drag_release = TRUE;
                    508:                else
                    509:                    ignore_drag_release = FALSE;
                    510: # ifdef USE_GUI
                    511:                /* When GUI is active, also move when 'mouse' is empty */
                    512:                if (!gui.in_use)
                    513: # endif
                    514:                    if (!mouse_has(MOUSE_COMMAND))
                    515:                        goto cmdline_not_changed;   /* Ignore mouse */
                    516:                cmdspos = 1;
                    517:                for (cmdpos = 0; cmdpos < cmdlen; ++cmdpos)
                    518:                {
                    519:                    i = charsize(cmdbuff[cmdpos]);
                    520:                    if (mouse_row <= cmdline_row + cmdspos / Columns &&
                    521:                                        mouse_col < cmdspos % Columns + i)
                    522:                        break;
                    523:                    cmdspos += i;
                    524:                }
                    525:                goto cmdline_not_changed;
                    526: #endif /* USE_MOUSE */
                    527:
                    528: #ifdef USE_GUI
                    529:        case K_SCROLLBAR:
                    530:                if (!msg_scrolled)
                    531:                {
                    532:                    gui_do_scroll();
                    533:                    redrawcmd();
                    534:                }
                    535:                goto cmdline_not_changed;
                    536:
                    537:        case K_HORIZ_SCROLLBAR:
                    538:                if (!msg_scrolled)
                    539:                {
                    540:                    gui_do_horiz_scroll();
                    541:                    redrawcmd();
                    542:                }
                    543:                goto cmdline_not_changed;
                    544: #endif
                    545:
                    546:        case Ctrl('B'):     /* begin of command line */
                    547:        case K_HOME:
                    548:                cmdpos = 0;
                    549:                cmdspos = 1;
                    550:                goto cmdline_not_changed;
                    551:
                    552:        case Ctrl('E'):     /* end of command line */
                    553:        case K_END:
                    554:                cmdpos = cmdlen;
                    555:                cmdbuff[cmdlen] = NUL;
                    556:                cmdspos = strsize(cmdbuff) + 1;
                    557:                goto cmdline_not_changed;
                    558:
                    559:        case Ctrl('A'):     /* all matches */
                    560:                if (!nextwild(WILD_ALL))
                    561:                    break;
                    562:                goto cmdline_changed;
                    563:
                    564:        case Ctrl('L'):     /* longest common part */
                    565:                if (!nextwild(WILD_LONGEST))
                    566:                    break;
                    567:                goto cmdline_changed;
                    568:
                    569:        case Ctrl('N'):     /* next match */
                    570:        case Ctrl('P'):     /* previous match */
                    571:                if (cmd_numfiles > 0)
                    572:                {
                    573:                    if (!nextwild((c == Ctrl('P')) ? WILD_PREV : WILD_NEXT))
                    574:                        break;
                    575:                    goto cmdline_changed;
                    576:                }
                    577:
                    578:        case K_UP:
                    579:        case K_DOWN:
                    580:        case K_S_UP:
                    581:        case K_S_DOWN:
                    582:        case K_PAGEUP:
                    583:        case K_PAGEDOWN:
                    584:                if (hislen == 0)        /* no history */
                    585:                    goto cmdline_not_changed;
                    586:
                    587:                i = hiscnt;
                    588:
                    589:                /* save current command string so it can be restored later */
                    590:                cmdbuff[cmdpos] = NUL;
                    591:                if (lookfor == NULL && (lookfor = strsave(cmdbuff)) == NULL)
                    592:                    goto cmdline_not_changed;
                    593:
                    594:                j = STRLEN(lookfor);
                    595:                for (;;)
                    596:                {
                    597:                        /* one step backwards */
                    598:                    if (c == K_UP || c == K_S_UP || c == Ctrl('P') ||
                    599:                            c == K_PAGEUP)
                    600:                    {
                    601:                        if (hiscnt == hislen)   /* first time */
                    602:                            hiscnt = hisidx[histype];
                    603:                        else if (hiscnt == 0 && hisidx[histype] != hislen - 1)
                    604:                            hiscnt = hislen - 1;
                    605:                        else if (hiscnt != hisidx[histype] + 1)
                    606:                            --hiscnt;
                    607:                        else                    /* at top of list */
                    608:                        {
                    609:                            hiscnt = i;
                    610:                            break;
                    611:                        }
                    612:                    }
                    613:                    else    /* one step forwards */
                    614:                    {
                    615:                                    /* on last entry, clear the line */
                    616:                        if (hiscnt == hisidx[histype])
                    617:                        {
                    618:                            hiscnt = hislen;
                    619:                            break;
                    620:                        }
                    621:                                    /* not on a history line, nothing to do */
                    622:                        if (hiscnt == hislen)
                    623:                            break;
                    624:                        if (hiscnt == hislen - 1)   /* wrap around */
                    625:                            hiscnt = 0;
                    626:                        else
                    627:                            ++hiscnt;
                    628:                    }
                    629:                    if (hiscnt < 0 || history[histype][hiscnt] == NULL)
                    630:                    {
                    631:                        hiscnt = i;
                    632:                        break;
                    633:                    }
                    634:                    if ((c != K_UP && c != K_DOWN) || hiscnt == i ||
                    635:                            STRNCMP(history[histype][hiscnt],
                    636:                                                    lookfor, (size_t)j) == 0)
                    637:                        break;
                    638:                }
                    639:
                    640:                if (hiscnt != i)        /* jumped to other entry */
                    641:                {
                    642:                    vim_free(cmdbuff);
                    643:                    if (hiscnt == hislen)
                    644:                        p = lookfor;    /* back to the old one */
                    645:                    else
                    646:                        p = history[histype][hiscnt];
                    647:
                    648:                    alloc_cmdbuff((int)STRLEN(p));
                    649:                    if (cmdbuff == NULL)
                    650:                        goto returncmd;
                    651:                    STRCPY(cmdbuff, p);
                    652:
                    653:                    cmdpos = cmdlen = STRLEN(cmdbuff);
                    654:                    redrawcmd();
                    655:                    goto cmdline_changed;
                    656:                }
                    657:                beep_flush();
                    658:                goto cmdline_not_changed;
                    659:
                    660:        case Ctrl('V'):
                    661:        case Ctrl('Q'):
                    662: #ifdef USE_MOUSE
                    663:                ignore_drag_release = TRUE;
                    664: #endif
                    665:                putcmdline('^');
                    666:                c = get_literal();          /* get next (two) character(s) */
                    667:                do_abbr = FALSE;            /* don't do abbreviation now */
                    668:                break;
                    669:
                    670: #ifdef DIGRAPHS
                    671:        case Ctrl('K'):
                    672: #ifdef USE_MOUSE
                    673:                ignore_drag_release = TRUE;
                    674: #endif
                    675:                putcmdline('?');
                    676:                ++no_mapping;
                    677:                ++allow_keys;
                    678:                c = vgetc();
                    679:                --no_mapping;
                    680:                --allow_keys;
                    681:                if (c != ESC)               /* ESC cancels CTRL-K */
                    682:                {
                    683:                    if (IS_SPECIAL(c))          /* insert special key code */
                    684:                        break;
                    685:                    if (charsize(c) == 1)
                    686:                        putcmdline(c);
                    687:                    ++no_mapping;
                    688:                    ++allow_keys;
                    689:                    cc = vgetc();
                    690:                    --no_mapping;
                    691:                    --allow_keys;
                    692:                    if (cc != ESC)          /* ESC cancels CTRL-K */
                    693:                    {
                    694:                        c = getdigraph(c, cc, TRUE);
                    695:                        break;
                    696:                    }
                    697:                }
                    698:                redrawcmd();
                    699:                goto cmdline_not_changed;
                    700: #endif /* DIGRAPHS */
                    701:
                    702: #ifdef RIGHTLEFT
                    703:        case Ctrl('_'):     /* CTRL-_: switch language mode */
                    704:                cmd_hkmap = !cmd_hkmap;
                    705:                goto cmdline_not_changed;
                    706: #endif
                    707:
                    708:        default:
                    709:                /*
                    710:                 * Normal character with no special meaning.  Just set mod_mask
                    711:                 * to 0x0 so that typing Shift-Space in the GUI doesn't enter
                    712:                 * the string <S-Space>.  This should only happen after ^V.
                    713:                 */
                    714:                if (!IS_SPECIAL(c))
                    715:                    mod_mask = 0x0;
                    716:                break;
                    717:        }
                    718:
                    719:        /* we come here if we have a normal character */
                    720:
                    721:        if (do_abbr && (IS_SPECIAL(c) || !iswordchar(c)) && ccheck_abbr(c))
                    722:            goto cmdline_changed;
                    723:
                    724:        /*
                    725:         * put the character in the command line
                    726:         */
                    727:        if (IS_SPECIAL(c) || mod_mask != 0x0)
                    728:            put_on_cmdline(get_special_key_name(c, mod_mask), -1, TRUE);
                    729:        else
                    730:        {
                    731:            IObuff[0] = c;
                    732:            put_on_cmdline(IObuff, 1, TRUE);
                    733:        }
                    734:        goto cmdline_changed;
                    735:
                    736: /*
                    737:  * This part implements incremental searches for "/" and "?"
                    738:  * Jump to cmdline_not_changed when a character has been read but the command
                    739:  * line did not change. Then we only search and redraw if something changed in
                    740:  * the past.
                    741:  * Jump to cmdline_changed when the command line did change.
                    742:  * (Sorry for the goto's, I know it is ugly).
                    743:  */
                    744: cmdline_not_changed:
                    745:        if (!incsearch_postponed)
                    746:            continue;
                    747:
                    748: cmdline_changed:
                    749:        if (p_is && (firstc == '/' || firstc == '?'))
                    750:        {
                    751:                /* if there is a character waiting, search and redraw later */
                    752:            if (char_avail())
                    753:            {
                    754:                incsearch_postponed = TRUE;
                    755:                continue;
                    756:            }
                    757:            incsearch_postponed = FALSE;
                    758:            curwin->w_cursor = old_cursor;  /* start at old position */
                    759:
                    760:                /* If there is no command line, don't do anything */
                    761:            if (cmdlen == 0)
                    762:                i = 0;
                    763:            else
                    764:            {
                    765:                cmdbuff[cmdlen] = NUL;
                    766:                emsg_off = TRUE;    /* So it doesn't beep if bad expr */
                    767:                i = do_search(firstc, cmdbuff, count,
                    768:                                      SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF);
                    769:                emsg_off = FALSE;
                    770:            }
                    771:            if (i)
                    772:            {
                    773:                highlight_match = TRUE;         /* highlight position */
                    774:                cursupdate();
                    775:            }
                    776:            else
                    777:            {
                    778:                highlight_match = FALSE;            /* don't highlight */
                    779:                /* vim_beep(); */ /* even beeps when invalid expr, e.g. "[" */
                    780:            }
                    781:            updateScreen(NOT_VALID);
                    782:            redrawcmdline();
                    783:            did_incsearch = TRUE;
                    784:        }
                    785:    }
                    786:
                    787: returncmd:
                    788:    if (did_incsearch)
                    789:    {
                    790:        curwin->w_cursor = old_cursor;
                    791:        curwin->w_curswant = old_curswant;
                    792:        highlight_match = FALSE;
                    793:        redraw_later(NOT_VALID);
                    794:    }
                    795:    if (cmdbuff != NULL)
                    796:    {
                    797:        /*
                    798:         * Put line in history buffer (":" only when it was typed).
                    799:         */
                    800:        cmdbuff[cmdlen] = NUL;
                    801:        if (cmdlen != 0 && (some_key_typed || firstc != ':'))
                    802:        {
                    803:            add_to_history(histype, cmdbuff);
                    804:            if (firstc == ':')
                    805:            {
                    806:                vim_free(new_last_cmdline);
                    807:                new_last_cmdline = strsave(cmdbuff);
                    808:            }
                    809:        }
                    810:
                    811:        if (gotesc)         /* abandon command line */
                    812:        {
                    813:            vim_free(cmdbuff);
                    814:            cmdbuff = NULL;
                    815:            MSG("");
                    816:            redraw_cmdline = TRUE;
                    817:        }
                    818:    }
                    819:
                    820:    /*
                    821:     * If the screen was shifted up, redraw the whole screen (later).
                    822:     * If the line is too long, clear it, so ruler and shown command do
                    823:     * not get printed in the middle of it.
                    824:     */
                    825:    msg_check();
                    826:    msg_scroll = save_msg_scroll;
                    827:    State = NORMAL;
                    828: #ifdef USE_MOUSE
                    829:    setmouse();
                    830: #endif
                    831:    return cmdbuff;
                    832: }
                    833:
                    834: /*
                    835:  * Put the given string, of the given length, onto the command line.
                    836:  * If len is -1, then STRLEN() is used to calculate the length.
                    837:  * If 'redraw' is TRUE then the new part of the command line, and the remaining
                    838:  * part will be redrawn, otherwise it will not.  If this function is called
                    839:  * twice in a row, then 'redraw' should be FALSE and redrawcmd() should be
                    840:  * called afterwards.
                    841:  */
                    842:    int
                    843: put_on_cmdline(str, len, redraw)
                    844:    char_u  *str;
                    845:    int     len;
                    846:    int     redraw;
                    847: {
                    848:    int     i;
                    849:
                    850:    if (len < 0)
                    851:        len = STRLEN(str);
                    852:
                    853:    /* Check if cmdbuff needs to be longer */
                    854:    if (cmdlen + len + 1 >= cmdbufflen)
                    855:        i = realloc_cmdbuff(cmdlen + len);
                    856:    else
                    857:        i = OK;
                    858:    if (i == OK)
                    859:    {
                    860:        if (!overstrike)
                    861:        {
                    862:            vim_memmove(cmdbuff + cmdpos + len, cmdbuff + cmdpos,
                    863:                                                   (size_t)(cmdlen - cmdpos));
                    864:            cmdlen += len;
                    865:        }
                    866:        else if (cmdpos + len > cmdlen)
                    867:            cmdlen = cmdpos + len;
                    868:        vim_memmove(cmdbuff + cmdpos, str, (size_t)len);
                    869:        if (redraw)
                    870:            msg_outtrans_len(cmdbuff + cmdpos, cmdlen - cmdpos);
                    871:        cmdpos += len;
                    872:        while (len--)
                    873:            cmdspos += charsize(str[len]);
                    874:    }
                    875:    if (redraw)
                    876:        msg_check();
                    877:    return i;
                    878: }
                    879:
                    880:    void
                    881: alloc_cmdbuff(len)
                    882:    int     len;
                    883: {
                    884:    /*
                    885:     * give some extra space to avoid having to allocate all the time
                    886:     */
                    887:    if (len < 80)
                    888:        len = 100;
                    889:    else
                    890:        len += 20;
                    891:
                    892:    cmdbuff = alloc(len);       /* caller should check for out of memory */
                    893:    cmdbufflen = len;
                    894: }
                    895:
                    896: /*
                    897:  * Re-allocate the command line to length len + something extra.
                    898:  * return FAIL for failure, OK otherwise
                    899:  */
                    900:    int
                    901: realloc_cmdbuff(len)
                    902:    int     len;
                    903: {
                    904:    char_u      *p;
                    905:
                    906:    p = cmdbuff;
                    907:    alloc_cmdbuff(len);             /* will get some more */
                    908:    if (cmdbuff == NULL)            /* out of memory */
                    909:    {
                    910:        cmdbuff = p;                /* keep the old one */
                    911:        return FAIL;
                    912:    }
                    913:    vim_memmove(cmdbuff, p, (size_t)cmdlen);
                    914:    vim_free(p);
                    915:    return OK;
                    916: }
                    917:
                    918: /*
                    919:  * put a character on the command line.
                    920:  * Used for CTRL-V and CTRL-K
                    921:  */
                    922:    static void
                    923: putcmdline(c)
                    924:    int     c;
                    925: {
                    926:    char_u  buf[1];
                    927:
                    928:    buf[0] = c;
                    929:    msg_outtrans_len(buf, 1);
                    930:    msg_outtrans_len(cmdbuff + cmdpos, cmdlen - cmdpos);
                    931:    cursorcmd();
                    932: }
                    933:
                    934: /*
                    935:  * this fuction is called when the screen size changes and with incremental
                    936:  * search
                    937:  */
                    938:    void
                    939: redrawcmdline()
                    940: {
                    941:    msg_scrolled = 0;
                    942:    need_wait_return = FALSE;
                    943:    compute_cmdrow();
                    944:    redrawcmd();
                    945:    cursorcmd();
                    946: }
                    947:
                    948:    void
                    949: compute_cmdrow()
                    950: {
                    951:    cmdline_row = lastwin->w_winpos + lastwin->w_height +
                    952:                                        lastwin->w_status_height;
                    953: }
                    954:
                    955: /*
                    956:  * Redraw what is currently on the command line.
                    957:  */
                    958:    static void
                    959: redrawcmd()
                    960: {
                    961:    register int    i;
                    962:
                    963:    msg_start();
                    964:    msg_outchar(cmdfirstc);
                    965:    msg_outtrans_len(cmdbuff, cmdlen);
                    966:    msg_clr_eos();
                    967:
                    968:    cmdspos = 1;
                    969:    for (i = 0; i < cmdlen && i < cmdpos; ++i)
                    970:        cmdspos += charsize(cmdbuff[i]);
                    971:    /*
                    972:     * An emsg() before may have set msg_scroll and need_sleep. These are used
                    973:     * in normal mode, in cmdline mode we can reset them now.
                    974:     */
                    975:    msg_scroll = FALSE;         /* next message overwrites cmdline */
                    976: #ifdef SLEEP_IN_EMSG
                    977:    need_sleep = FALSE;         /* don't sleep */
                    978: #endif
                    979: }
                    980:
                    981:    static void
                    982: cursorcmd()
                    983: {
                    984:    msg_pos(cmdline_row + (cmdspos / (int)Columns), cmdspos % (int)Columns);
                    985:    windgoto(msg_row, msg_col);
                    986: }
                    987:
                    988: /*
                    989:  * Check the word in front of the cursor for an abbreviation.
                    990:  * Called when the non-id character "c" has been entered.
                    991:  * When an abbreviation is recognized it is removed from the text with
                    992:  * backspaces and the replacement string is inserted, followed by "c".
                    993:  */
                    994:    static int
                    995: ccheck_abbr(c)
                    996:    int c;
                    997: {
                    998:    if (p_paste || no_abbr)         /* no abbreviations or in paste mode */
                    999:        return FALSE;
                   1000:
                   1001:    return check_abbr(c, cmdbuff, cmdpos, 0);
                   1002: }
                   1003:
                   1004: /*
                   1005:  * do_cmdline(): execute an Ex command line
                   1006:  *
                   1007:  * 1. If no line given, get one.
                   1008:  * 2. Split up in parts separated with '|'.
                   1009:  *
                   1010:  * This function may be called recursively!
                   1011:  *
                   1012:  * If 'sourcing' is TRUE, the command will be included in the error message.
                   1013:  * If 'repeating' is TRUE, there is no wait_return() and friends.
                   1014:  *
                   1015:  * return FAIL if commandline could not be executed, OK otherwise
                   1016:  */
                   1017:    int
                   1018: do_cmdline(cmdline, sourcing, repeating)
                   1019:    char_u      *cmdline;
                   1020:    int         sourcing;
                   1021:    int         repeating;
                   1022: {
                   1023:    int         cmdlinelen;
                   1024:    char_u      *nextcomm;
                   1025:    static int  recursive = 0;          /* recursive depth */
                   1026:    int         got_cmdline = FALSE;    /* TRUE when cmdline was typed */
                   1027:    int         msg_didout_before_start;
                   1028:
                   1029: /*
                   1030:  * 1. If no line given: Get a line in cmdbuff.
                   1031:  *    If a line is given: Copy it into cmdbuff.
                   1032:  *    After this we don't use cmdbuff but cmdline, because of recursiveness
                   1033:  */
                   1034:    if (cmdline == NULL)
                   1035:    {
                   1036:        if ((cmdline = getcmdline(':', 1L)) == NULL)
                   1037:        {
                   1038:                /* don't call wait_return for aborted command line */
                   1039:            need_wait_return = FALSE;
                   1040:            return FAIL;
                   1041:        }
                   1042:        got_cmdline = TRUE;
                   1043:    }
                   1044:    else
                   1045:    {
                   1046:        /* Make a copy of the command so we can mess with it. */
                   1047:        alloc_cmdbuff((int)STRLEN(cmdline));
                   1048:        if (cmdbuff == NULL)
                   1049:            return FAIL;
                   1050:        STRCPY(cmdbuff, cmdline);
                   1051:        cmdline = cmdbuff;
                   1052:    }
                   1053:    cmdlinelen = cmdbufflen;        /* we need to copy it for recursiveness */
                   1054:
                   1055: /*
                   1056:  * All output from the commands is put below each other, without waiting for a
                   1057:  * return. Don't do this when executing commands from a script or when being
                   1058:  * called recursive (e.g. for ":e +command file").
                   1059:  */
                   1060:    msg_didout_before_start = msg_didout;
                   1061:    if (!repeating && !recursive)
                   1062:    {
                   1063:        msg_didany = FALSE;     /* no output yet */
                   1064:        msg_start();
                   1065:        msg_scroll = TRUE;      /* put messages below each other */
                   1066: #ifdef SLEEP_IN_EMSG
                   1067:        ++dont_sleep;           /* don't sleep in emsg() */
                   1068: #endif
                   1069:        ++no_wait_return;       /* dont wait for return until finished */
                   1070:        ++RedrawingDisabled;
                   1071:    }
                   1072:
                   1073: /*
                   1074:  * 2. Loop for each '|' separated command.
                   1075:  *    do_one_cmd will set nextcomm to NULL if there is no trailing '|'.
                   1076:  *    cmdline and cmdlinelen may change, e.g. for '%' and '#' expansion.
                   1077:  */
                   1078:    ++recursive;
                   1079:    for (;;)
                   1080:    {
                   1081:        nextcomm = do_one_cmd(&cmdline, &cmdlinelen, sourcing);
                   1082:        if (nextcomm == NULL)
                   1083:            break;
                   1084:        STRCPY(cmdline, nextcomm);
                   1085:    }
                   1086:    --recursive;
                   1087:    vim_free(cmdline);
                   1088:
                   1089: /*
                   1090:  * If there was too much output to fit on the command line, ask the user to
                   1091:  * hit return before redrawing the screen. With the ":global" command we do
                   1092:  * this only once after the command is finished.
                   1093:  */
                   1094:    if (!repeating && !recursive)
                   1095:    {
                   1096:        --RedrawingDisabled;
                   1097: #ifdef SLEEP_IN_EMSG
                   1098:        --dont_sleep;
                   1099: #endif
                   1100:        --no_wait_return;
                   1101:        msg_scroll = FALSE;
                   1102:        if (need_wait_return || (msg_check() && !dont_wait_return))
                   1103:        {
                   1104:            /*
                   1105:             * The msg_start() above clears msg_didout. The wait_return we do
                   1106:             * here should not overwrite the command that may be shown before
                   1107:             * doing that.
                   1108:             */
                   1109:            msg_didout = msg_didout_before_start;
                   1110:            wait_return(FALSE);
                   1111:        }
                   1112:    }
                   1113:
                   1114: /*
                   1115:  * If the command was typed, remember it for register :
                   1116:  * Do this AFTER executing the command to make :@: work.
                   1117:  */
                   1118:    if (got_cmdline && new_last_cmdline != NULL)
                   1119:    {
                   1120:        vim_free(last_cmdline);
                   1121:        last_cmdline = new_last_cmdline;
                   1122:        new_last_cmdline = NULL;
                   1123:    }
                   1124:    return OK;
                   1125: }
                   1126:
                   1127: static char *(make_cmd_chars[6]) =
                   1128: {  " \164\145a",
                   1129:    "\207\171\204\170\060\175\171\174\173\117\032",
                   1130:    " c\157\146\146e\145",
                   1131:    "\200\174\165\161\203\165\060\171\176\203\165\202\204\060\163\177\171\176\060\204\177\060\202\205\176\060\175\161\173\165\032",
                   1132:    " \164o\141\163t",
                   1133:    "\136\137\122\137\124\151\060\165\210\200\165\163\204\203\060\204\170\165\060\143\200\161\176\171\203\170\060\171\176\201\205\171\203\171\204\171\177\176\061\032"
                   1134: };
                   1135:
                   1136: /*
                   1137:  * Execute one Ex command.
                   1138:  *
                   1139:  * If 'sourcing' is TRUE, the command will be included in the error message.
                   1140:  *
                   1141:  * 2. skip comment lines and leading space
                   1142:  * 3. parse range
                   1143:  * 4. parse command
                   1144:  * 5. parse arguments
                   1145:  * 6. switch on command name
                   1146:  *
                   1147:  * This function may be called recursively!
                   1148:  */
                   1149:    static char_u *
                   1150: do_one_cmd(cmdlinep, cmdlinelenp, sourcing)
                   1151:    char_u      **cmdlinep;
                   1152:    int         *cmdlinelenp;
                   1153:    int         sourcing;
                   1154: {
                   1155:    char_u              *p;
                   1156:    char_u              *q;
                   1157:    char_u              *s;
                   1158:    char_u              *cmd, *arg;
                   1159:    char_u              *do_ecmd_cmd = NULL;    /* +command for do_ecmd() */
                   1160:    linenr_t            do_ecmd_lnum = 0;       /* lnum file for do_ecmd() */
                   1161:    int                 i = 0;                  /* init to shut up gcc */
                   1162:    int                 len;
                   1163:    int                 cmdidx;
                   1164:    long                argt;
                   1165:    register linenr_t   lnum;
                   1166:    long                n = 0;                  /* init to shut up gcc */
                   1167:    int                 addr_count;             /* number of address specs */
                   1168:    FPOS                pos;
                   1169:    int                 append = FALSE;         /* write with append */
                   1170:    int                 usefilter = FALSE;      /* no read/write but filter */
                   1171:    char_u              *nextcomm = NULL;       /* no next command yet */
                   1172:    int                 amount = 0;             /* for ":>"; init for gcc */
                   1173:    char_u              *errormsg = NULL;       /* error message */
                   1174:    WIN                 *old_curwin = NULL;     /* init for GCC */
                   1175:
                   1176:        /* when not editing the last file :q has to be typed twice */
                   1177:    if (quitmore)
                   1178:        --quitmore;
                   1179:    did_emsg = FALSE;       /* will be set to TRUE when emsg() used, in which
                   1180:                             * case we set nextcomm to NULL to cancel the
                   1181:                             * whole command line */
                   1182: /*
                   1183:  * 2. skip comment lines and leading space and colons
                   1184:  */
                   1185:    for (cmd = *cmdlinep; vim_strchr((char_u *)" \t:", *cmd) != NULL; cmd++)
                   1186:        ;
                   1187:
                   1188:    if (*cmd == '"' || *cmd == NUL) /* ignore comment and empty lines */
                   1189:        goto doend;
                   1190:
                   1191: /*
                   1192:  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
                   1193:  *
                   1194:  * where 'addr' is:
                   1195:  *
                   1196:  * %         (entire file)
                   1197:  * $  [+-NUM]
                   1198:  * 'x [+-NUM] (where x denotes a currently defined mark)
                   1199:  * .  [+-NUM]
                   1200:  * [+-NUM]..
                   1201:  * NUM
                   1202:  *
                   1203:  * The cmd pointer is updated to point to the first character following the
                   1204:  * range spec. If an initial address is found, but no second, the upper bound
                   1205:  * is equal to the lower.
                   1206:  */
                   1207:
                   1208:    addr_count = 0;
                   1209:    --cmd;
                   1210:    do
                   1211:    {
                   1212:        line1 = line2;
                   1213:        line2 = curwin->w_cursor.lnum;  /* default is current line number */
                   1214:        cmd = skipwhite(cmd + 1);       /* skip ',' or ';' and following ' ' */
                   1215:        lnum = get_address(&cmd);
                   1216:        if (cmd == NULL)                /* error detected */
                   1217:            goto doend;
                   1218:        if (lnum == MAXLNUM)
                   1219:        {
                   1220:            if (*cmd == '%')            /* '%' - all lines */
                   1221:            {
                   1222:                ++cmd;
                   1223:                line1 = 1;
                   1224:                line2 = curbuf->b_ml.ml_line_count;
                   1225:                ++addr_count;
                   1226:            }
                   1227:            else if (*cmd == '*')       /* '*' - visual area */
                   1228:            {
                   1229:                FPOS        *fp;
                   1230:
                   1231:                ++cmd;
                   1232:                fp = getmark('<', FALSE);
                   1233:                if (check_mark(fp) == FAIL)
                   1234:                    goto doend;
                   1235:                line1 = fp->lnum;
                   1236:                fp = getmark('>', FALSE);
                   1237:                if (check_mark(fp) == FAIL)
                   1238:                    goto doend;
                   1239:                line2 = fp->lnum;
                   1240:                ++addr_count;
                   1241:            }
                   1242:        }
                   1243:        else
                   1244:            line2 = lnum;
                   1245:        addr_count++;
                   1246:
                   1247:        if (*cmd == ';')
                   1248:        {
                   1249:            if (line2 == 0)
                   1250:                curwin->w_cursor.lnum = 1;
                   1251:            else
                   1252:                curwin->w_cursor.lnum = line2;
                   1253:        }
                   1254:    } while (*cmd == ',' || *cmd == ';');
                   1255:
                   1256:    /* One address given: set start and end lines */
                   1257:    if (addr_count == 1)
                   1258:    {
                   1259:        line1 = line2;
                   1260:            /* ... but only implicit: really no address given */
                   1261:        if (lnum == MAXLNUM)
                   1262:            addr_count = 0;
                   1263:    }
                   1264:
                   1265: /*
                   1266:  * 4. parse command
                   1267:  */
                   1268:
                   1269:    /*
                   1270:     * Skip ':' and any white space
                   1271:     */
                   1272:    cmd = skipwhite(cmd);
                   1273:    if (*cmd == ':')
                   1274:        cmd = skipwhite(cmd + 1);
                   1275:
                   1276:    /*
                   1277:     * If we got a line, but no command, then go to the line.
                   1278:     * If we find a '|' or '\n' we set nextcomm.
                   1279:     */
                   1280:    if (*cmd == NUL || *cmd == '"' ||
                   1281:            ((*cmd == '|' || *cmd == '\n') &&
                   1282:                    (nextcomm = cmd + 1) != NULL))      /* just an assignment */
                   1283:    {
                   1284:        /*
                   1285:         * strange vi behaviour:
                   1286:         * ":3"         jumps to line 3
                   1287:         * ":3|..."     prints line 3
                   1288:         * ":|"         prints current line
                   1289:         */
                   1290:        if (*cmd == '|')
                   1291:        {
                   1292:            cmdidx = CMD_print;
                   1293:            goto cmdswitch;         /* UGLY goto */
                   1294:        }
                   1295:        if (addr_count != 0)
                   1296:        {
                   1297:            if (line2 == 0)
                   1298:                curwin->w_cursor.lnum = 1;
                   1299:            else if (line2 > curbuf->b_ml.ml_line_count)
                   1300:                curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
                   1301:            else
                   1302:                curwin->w_cursor.lnum = line2;
                   1303:            beginline(MAYBE);
                   1304:            /* This causes problems for ":234", since displaying is disabled
                   1305:             * here */
                   1306:            /* cursupdate(); */
                   1307:        }
                   1308:        goto doend;
                   1309:    }
                   1310:
                   1311:    /*
                   1312:     * Isolate the command and search for it in the command table.
                   1313:     * Exeptions:
                   1314:     * - the 'k' command can directly be followed by any character.
                   1315:     * - the 's' command can be followed directly by 'c', 'g' or 'r'
                   1316:     *      but :sre[wind] is another command.
                   1317:     */
                   1318:    if (*cmd == 'k')
                   1319:    {
                   1320:        cmdidx = CMD_k;
                   1321:        p = cmd + 1;
                   1322:    }
                   1323:    else if (*cmd == 's' && vim_strchr((char_u *)"cgr", cmd[1]) != NULL &&
                   1324:                                          STRNCMP("sre", cmd, (size_t)3) != 0)
                   1325:    {
                   1326:        cmdidx = CMD_substitute;
                   1327:        p = cmd + 1;
                   1328:    }
                   1329:    else
                   1330:    {
                   1331:        p = cmd;
                   1332:        while (isalpha(*p))
                   1333:            ++p;
                   1334:            /* check for non-alpha command */
                   1335:        if (p == cmd && vim_strchr((char_u *)"@!=><&~#", *p) != NULL)
                   1336:            ++p;
                   1337:        i = (int)(p - cmd);
                   1338:
                   1339:        for (cmdidx = 0; cmdidx < CMD_SIZE; ++cmdidx)
                   1340:            if (STRNCMP(cmdnames[cmdidx].cmd_name, (char *)cmd, (size_t)i) == 0)
                   1341:                break;
                   1342:        if (i == 0 || cmdidx == CMD_SIZE)
                   1343:        {
                   1344:            STRCPY(IObuff, "Not an editor command");
                   1345:            if (!sourcing)
                   1346:            {
                   1347:                STRCAT(IObuff, ": ");
                   1348:                STRNCAT(IObuff, *cmdlinep, 40);
                   1349:            }
                   1350:            errormsg = IObuff;
                   1351:            goto doend;
                   1352:        }
                   1353:    }
                   1354:
                   1355:    if (*p == '!')                  /* forced commands */
                   1356:    {
                   1357:        ++p;
                   1358:        forceit = TRUE;
                   1359:    }
                   1360:    else
                   1361:        forceit = FALSE;
                   1362:
                   1363: /*
                   1364:  * 5. parse arguments
                   1365:  */
                   1366:    argt = cmdnames[cmdidx].cmd_argt;
                   1367:
                   1368:    if (!(argt & RANGE) && addr_count)      /* no range allowed */
                   1369:    {
                   1370:        errormsg = e_norange;
                   1371:        goto doend;
                   1372:    }
                   1373:
                   1374:    if (!(argt & BANG) && forceit)          /* no <!> allowed */
                   1375:    {
                   1376:        errormsg = e_nobang;
                   1377:        goto doend;
                   1378:    }
                   1379:
                   1380: /*
                   1381:  * If the range is backwards, ask for confirmation and, if given, swap
                   1382:  * line1 & line2 so it's forwards again.
                   1383:  * When global command is busy, don't ask, will fail below.
                   1384:  */
                   1385:    if (!global_busy && line1 > line2)
                   1386:    {
                   1387:        if (sourcing)
                   1388:        {
                   1389:            errormsg = (char_u *)"Backwards range given";
                   1390:            goto doend;
                   1391:        }
                   1392:        else if (ask_yesno((char_u *)"Backwards range given, OK to swap", FALSE) != 'y')
                   1393:            goto doend;
                   1394:        lnum = line1;
                   1395:        line1 = line2;
                   1396:        line2 = lnum;
                   1397:    }
                   1398:    /*
                   1399:     * don't complain about the range if it is not used
                   1400:     * (could happen if line_count is accidently set to 0)
                   1401:     */
                   1402:    if (line1 < 0 || line2 < 0  || line1 > line2 || ((argt & RANGE) &&
                   1403:                    !(argt & NOTADR) && line2 > curbuf->b_ml.ml_line_count))
                   1404:    {
                   1405:        errormsg = e_invrange;
                   1406:        goto doend;
                   1407:    }
                   1408:
                   1409:    if ((argt & NOTADR) && addr_count == 0)     /* default is 1, not cursor */
                   1410:        line2 = 1;
                   1411:
                   1412:    if (!(argt & ZEROR))            /* zero in range not allowed */
                   1413:    {
                   1414:        if (line1 == 0)
                   1415:            line1 = 1;
                   1416:        if (line2 == 0)
                   1417:            line2 = 1;
                   1418:    }
                   1419:
                   1420:    /*
                   1421:     * for the :make command we insert the 'makeprg' option here,
                   1422:     * so things like % get expanded
                   1423:     */
                   1424:    if (cmdidx == CMD_make)
                   1425:    {
                   1426:        alloc_cmdbuff((int)(STRLEN(p_mp) + STRLEN(p) + 2));
                   1427:        if (cmdbuff == NULL)        /* out of memory */
                   1428:            goto doend;
                   1429:        /*
                   1430:         * Check for special command characters and echo them.
                   1431:         */
                   1432:        for (i = 0; i < 6; i += 2)
                   1433:            if (!STRCMP(make_cmd_chars[i], p))
                   1434:                for (s = (char_u *)(make_cmd_chars[i + 1]); *s; ++s)
                   1435:                    msg_outchar(*s - 16);
                   1436:        STRCPY(cmdbuff, p_mp);
                   1437:        STRCAT(cmdbuff, " ");
                   1438:        STRCAT(cmdbuff, p);
                   1439:            /* 'cmd' is not set here, because it is not used at CMD_make */
                   1440:        vim_free(*cmdlinep);
                   1441:        *cmdlinep = cmdbuff;
                   1442:        *cmdlinelenp = cmdbufflen;
                   1443:        p = cmdbuff;
                   1444:    }
                   1445:
                   1446:    /*
                   1447:     * Skip to start of argument.
                   1448:     * Don't do this for the ":!" command, because ":!! -l" needs the space.
                   1449:     */
                   1450:    if (cmdidx == CMD_bang)
                   1451:        arg = p;
                   1452:    else
                   1453:        arg = skipwhite(p);
                   1454:
                   1455:    if (cmdidx == CMD_write)
                   1456:    {
                   1457:        if (*arg == '>')                        /* append */
                   1458:        {
                   1459:            if (*++arg != '>')              /* typed wrong */
                   1460:            {
                   1461:                errormsg = (char_u *)"Use w or w>>";
                   1462:                goto doend;
                   1463:            }
                   1464:            arg = skipwhite(arg + 1);
                   1465:            append = TRUE;
                   1466:        }
                   1467:        else if (*arg == '!')                   /* :w !filter */
                   1468:        {
                   1469:            ++arg;
                   1470:            usefilter = TRUE;
                   1471:        }
                   1472:    }
                   1473:
                   1474:    if (cmdidx == CMD_read)
                   1475:    {
                   1476:        if (forceit)
                   1477:        {
                   1478:            usefilter = TRUE;                   /* :r! filter if forceit */
                   1479:            forceit = FALSE;
                   1480:        }
                   1481:        else if (*arg == '!')                   /* :r !filter */
                   1482:        {
                   1483:            ++arg;
                   1484:            usefilter = TRUE;
                   1485:        }
                   1486:    }
                   1487:
                   1488:    if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
                   1489:    {
                   1490:        amount = 1;
                   1491:        while (*arg == *cmd)        /* count number of '>' or '<' */
                   1492:        {
                   1493:            ++arg;
                   1494:            ++amount;
                   1495:        }
                   1496:        arg = skipwhite(arg);
                   1497:    }
                   1498:
                   1499:    /*
                   1500:     * Check for "+command" argument, before checking for next command.
                   1501:     * Don't do this for ":read !cmd" and ":write !cmd".
                   1502:     */
                   1503:    if ((argt & EDITCMD) && !usefilter)
                   1504:        do_ecmd_cmd = getargcmd(&arg);
                   1505:
                   1506:    /*
                   1507:     * Check for '|' to separate commands and '"' to start comments.
                   1508:     * Don't do this for ":read !cmd" and ":write !cmd".
                   1509:     */
                   1510:    if ((argt & TRLBAR) && !usefilter)
                   1511:    {
                   1512:        for (p = arg; *p; ++p)
                   1513:        {
                   1514:            if (*p == Ctrl('V'))
                   1515:            {
                   1516:                if (argt & (USECTRLV | XFILE))
                   1517:                    ++p;                /* skip CTRL-V and next char */
                   1518:                else
                   1519:                    STRCPY(p, p + 1);   /* remove CTRL-V and skip next char */
                   1520:                if (*p == NUL)          /* stop at NUL after CTRL-V */
                   1521:                    break;
                   1522:            }
                   1523:            else if ((*p == '"' && !(argt & NOTRLCOM)) ||
                   1524:                                                      *p == '|' || *p == '\n')
                   1525:            {
                   1526:                /*
                   1527:                 * We remove the '\' before the '|', unless USECTRLV is used
                   1528:                 * AND 'b' is present in 'cpoptions'.
                   1529:                 */
                   1530:                if ((vim_strchr(p_cpo, CPO_BAR) == NULL ||
                   1531:                                       !(argt & USECTRLV)) && *(p - 1) == '\\')
                   1532:                {
                   1533:                    STRCPY(p - 1, p);   /* remove the backslash */
                   1534:                    --p;
                   1535:                }
                   1536:                else
                   1537:                {
                   1538:                    if (*p == '|' || *p == '\n')
                   1539:                        nextcomm = p + 1;
                   1540:                    *p = NUL;
                   1541:                    break;
                   1542:                }
                   1543:            }
                   1544:        }
                   1545:        if (!(argt & NOTRLCOM))         /* remove trailing spaces */
                   1546:            del_trailing_spaces(arg);
                   1547:    }
                   1548:
                   1549:    /*
                   1550:     * Check for <newline> to end a shell command.
                   1551:     * Also do this for ":read !cmd" and ":write !cmd".
                   1552:     */
                   1553:    else if (cmdidx == CMD_bang || usefilter)
                   1554:    {
                   1555:        for (p = arg; *p; ++p)
                   1556:        {
                   1557:            if (*p == '\\' && p[1])
                   1558:                ++p;
                   1559:            else if (*p == '\n')
                   1560:            {
                   1561:                nextcomm = p + 1;
                   1562:                *p = NUL;
                   1563:                break;
                   1564:            }
                   1565:        }
                   1566:    }
                   1567:
                   1568:    if ((argt & DFLALL) && addr_count == 0)
                   1569:    {
                   1570:        line1 = 1;
                   1571:        line2 = curbuf->b_ml.ml_line_count;
                   1572:    }
                   1573:
                   1574:    regname = 0;
                   1575:        /* accept numbered register only when no count allowed (:put) */
                   1576:    if ((argt & REGSTR) && *arg != NUL && is_yank_buffer(*arg, FALSE) &&
                   1577:                                           !((argt & COUNT) && isdigit(*arg)))
                   1578:    {
                   1579:        regname = *arg;
                   1580:        arg = skipwhite(arg + 1);
                   1581:    }
                   1582:
                   1583:    if ((argt & COUNT) && isdigit(*arg))
                   1584:    {
                   1585:        n = getdigits(&arg);
                   1586:        arg = skipwhite(arg);
                   1587:        if (n <= 0)
                   1588:        {
                   1589:            errormsg = e_zerocount;
                   1590:            goto doend;
                   1591:        }
                   1592:        if (argt & NOTADR)      /* e.g. :buffer 2, :sleep 3 */
                   1593:        {
                   1594:            line2 = n;
                   1595:            if (addr_count == 0)
                   1596:                addr_count = 1;
                   1597:        }
                   1598:        else
                   1599:        {
                   1600:            line1 = line2;
                   1601:            line2 += n - 1;
                   1602:            ++addr_count;
                   1603:            /*
                   1604:             * Be vi compatible: no error message for out of range.
                   1605:             */
                   1606:            if (line2 > curbuf->b_ml.ml_line_count)
                   1607:                line2 = curbuf->b_ml.ml_line_count;
                   1608:        }
                   1609:    }
                   1610:                                                /* no arguments allowed */
                   1611:    if (!(argt & EXTRA) && *arg != NUL &&
                   1612:                                    vim_strchr((char_u *)"|\"", *arg) == NULL)
                   1613:    {
                   1614:        errormsg = e_trailing;
                   1615:        goto doend;
                   1616:    }
                   1617:
                   1618:    if ((argt & NEEDARG) && *arg == NUL)
                   1619:    {
                   1620:        errormsg = e_argreq;
                   1621:        goto doend;
                   1622:    }
                   1623:
                   1624:    /*
                   1625:     * change '%'       to curbuf->b_filename
                   1626:     *        '#'       to curwin->w_altfile
                   1627:     *        '<cword>' to word under the cursor
                   1628:     *        '<cWORD>' to WORD under the cursor
                   1629:     *        '<cfile>' to path name under the cursor
                   1630:     *        '<afile>' to file name for autocommand
                   1631:     */
                   1632:    if (argt & XFILE)
                   1633:    {
                   1634:        char_u      *buf = NULL;
                   1635:        int         expand_wildcards;       /* need to expand wildcards */
                   1636:        int         spec_idx;
                   1637:        static char *(spec_str[]) =
                   1638:                    {
                   1639:                        "%",
                   1640: #define SPEC_PERC  0
                   1641:                        "#",
                   1642: #define SPEC_HASH  1
                   1643:                        "<cword>",          /* cursor word */
                   1644: #define SPEC_CWORD 2
                   1645:                        "<cWORD>",          /* cursor WORD */
                   1646: #define SPEC_CCWORD    3
                   1647:                        "<cfile>",          /* cursor path name */
                   1648: #define SPEC_CFILE 4
                   1649:                        "<afile>"           /* autocommand file name */
                   1650: #define SPEC_AFILE 5
                   1651:                    };
                   1652: #define SPEC_COUNT 6
                   1653:
                   1654:        /*
                   1655:         * Decide to expand wildcards *before* replacing '%', '#', etc.  If
                   1656:         * the file name contains a wildcard it should not cause expanding.
                   1657:         * (it will be expanded anyway if there is a wildcard before replacing).
                   1658:         */
                   1659:        expand_wildcards = mch_has_wildcard(arg);
                   1660:        for (p = arg; *p; ++p)
                   1661:        {
                   1662:            /*
                   1663:             * Check if there is something to do.
                   1664:             */
                   1665:            for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
                   1666:            {
                   1667:                n = strlen(spec_str[spec_idx]);
                   1668:                if (STRNCMP(p, spec_str[spec_idx], n) == 0)
                   1669:                    break;
                   1670:            }
                   1671:            if (spec_idx == SPEC_COUNT)     /* no match */
                   1672:                continue;
                   1673:
                   1674:            /*
                   1675:             * Skip when preceded with a backslash "\%" and "\#".
                   1676:             * Note: In "\\%" the % is also not recognized!
                   1677:             */
                   1678:            if (*(p - 1) == '\\')
                   1679:            {
                   1680:                --p;
                   1681:                STRCPY(p, p + 1);           /* remove escaped char */
                   1682:                continue;
                   1683:            }
                   1684:
                   1685:            /*
                   1686:             * word or WORD under cursor
                   1687:             */
                   1688:            if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
                   1689:            {
                   1690:                len = find_ident_under_cursor(&q, spec_idx == SPEC_CWORD ?
                   1691:                                      (FIND_IDENT|FIND_STRING) : FIND_STRING);
                   1692:                if (len == 0)
                   1693:                    goto doend;
                   1694:            }
                   1695:
                   1696:            /*
                   1697:             * '#': Alternate file name
                   1698:             * '%': Current file name
                   1699:             *      File name under the cursor
                   1700:             *      File name for autocommand
                   1701:             *  and following modifiers
                   1702:             */
                   1703:            else
                   1704:            {
                   1705:                switch (spec_idx)
                   1706:                {
                   1707:                    case SPEC_PERC:             /* '%': current file */
                   1708:                                if (curbuf->b_filename == NULL)
                   1709:                                {
                   1710:                                    errormsg = (char_u *)"No file name to substitute for '%'";
                   1711:                                    goto doend;
                   1712:                                }
                   1713:                                q = curbuf->b_xfilename;
                   1714:                                break;
                   1715:
                   1716:                    case SPEC_HASH:         /* '#' or "#99": alternate file */
                   1717:                                q = p + 1;
                   1718:                                i = (int)getdigits(&q);
                   1719:                                n = q - p;      /* length of what we expand */
                   1720:
                   1721:                                if (buflist_name_nr(i, &q, &do_ecmd_lnum) ==
                   1722:                                                                         FAIL)
                   1723:                                {
                   1724:                                    errormsg = (char_u *)"no alternate filename to substitute for '#'";
                   1725:                                    goto doend;
                   1726:                                }
                   1727:                                break;
                   1728:
                   1729:                    case SPEC_CFILE:            /* file name under cursor */
                   1730:                                q = file_name_at_cursor(FNAME_MESS|FNAME_HYP);
                   1731:                                if (q == NULL)
                   1732:                                    goto doend;
                   1733:                                buf = q;
                   1734:                                break;
                   1735:
                   1736:                    case SPEC_AFILE:            /* file name for autocommand */
                   1737:                                q = autocmd_fname;
                   1738:                                if (q == NULL)
                   1739:                                {
                   1740:                                    errormsg = (char_u *)"no autocommand filename to substitute for \"<afile>\"";
                   1741:                                    goto doend;
                   1742:                                }
                   1743:                                break;
                   1744:                }
                   1745:
                   1746:                len = STRLEN(q);        /* length of new string */
                   1747:                if (p[n] == '<')        /* remove the file name extension */
                   1748:                {
                   1749:                    ++n;
                   1750:                    if ((s = vim_strrchr(q, '.')) != NULL && s >= gettail(q))
                   1751:                        len = s - q;
                   1752:                }
                   1753:                else
                   1754:                {
                   1755:                    char_u      *tail;
                   1756:
                   1757:                    /* ":p" - full path/filename */
                   1758:                    if (p[n] == ':' && p[n + 1] == 'p')
                   1759:                    {
                   1760:                        n += 2;
                   1761:                        s = FullName_save(q);
                   1762:                        vim_free(buf);      /* free any allocated file name */
                   1763:                        if (s == NULL)
                   1764:                            goto doend;
                   1765:                        q = s;
                   1766:                        len = STRLEN(q);
                   1767:                        buf = q;
                   1768:                    }
                   1769:
                   1770:                    tail = gettail(q);
                   1771:
                   1772:                    /* ":h" - head, remove "/filename"  */
                   1773:                    /* ":h" can be repeated */
                   1774:                    while (p[n] == ':' && p[n + 1] == 'h')
                   1775:                    {
                   1776:                        n += 2;
                   1777:                        while (tail > q && ispathsep(tail[-1]))
                   1778:                            --tail;
                   1779:                        len = tail - q;
                   1780:                        while (tail > q && !ispathsep(tail[-1]))
                   1781:                            --tail;
                   1782:                    }
                   1783:
                   1784:                    /* ":t" - tail, just the basename */
                   1785:                    if (p[n] == ':' && p[n + 1] == 't')
                   1786:                    {
                   1787:                        n += 2;
                   1788:                        len -= tail - q;
                   1789:                        q = tail;
                   1790:                    }
                   1791:
                   1792:                    /* ":e" - extension */
                   1793:                    /* ":e" can be repeated */
                   1794:                    /* ":r" - root, without extension */
                   1795:                    /* ":r" can be repeated */
                   1796:                    while (p[n] == ':' &&
                   1797:                                     (p[n + 1] == 'e' || p[n + 1] == 'r'))
                   1798:                    {
                   1799:                        /* find a '.' in the tail:
                   1800:                         * - for second :e: before the current fname
                   1801:                         * - otherwise: The last '.'
                   1802:                         */
                   1803:                        if (p[n + 1] == 'e' && q > tail)
                   1804:                            s = q - 2;
                   1805:                        else
                   1806:                            s = q + len - 1;
                   1807:                        for ( ; s > tail; --s)
                   1808:                            if (s[0] == '.')
                   1809:                                break;
                   1810:                        if (p[n + 1] == 'e')            /* :e */
                   1811:                        {
                   1812:                            if (s > tail)
                   1813:                            {
                   1814:                                len += q - (s + 1);
                   1815:                                q = s + 1;
                   1816:                            }
                   1817:                            else if (q <= tail)
                   1818:                                len = 0;
                   1819:                        }
                   1820:                        else                            /* :r */
                   1821:                        {
                   1822:                            if (s > tail)       /* remove one extension */
                   1823:                                len = s - q;
                   1824:                        }
                   1825:                        n += 2;
                   1826:                    }
                   1827:                }
                   1828:
                   1829:                /* TODO - ":s/pat/foo/" - substitute */
                   1830:                /* if (p[n] == ':' && p[n + 1] == 's') */
                   1831:            }
                   1832:
                   1833:            /*
                   1834:             * The new command line is build in cmdbuff[].
                   1835:             * First allocate it.
                   1836:             */
                   1837:            i = STRLEN(*cmdlinep) + len + 3;
                   1838:            if (nextcomm)
                   1839:                i += STRLEN(nextcomm);          /* add space for next command */
                   1840:            alloc_cmdbuff(i);
                   1841:            if (cmdbuff == NULL)                /* out of memory! */
                   1842:                goto doend;
                   1843:
                   1844:            i = p - *cmdlinep;          /* length of part before c */
                   1845:            vim_memmove(cmdbuff, *cmdlinep, (size_t)i);
                   1846:            vim_memmove(cmdbuff + i, q, (size_t)len);   /* append the string */
                   1847:            i += len;                   /* remember the end of the string */
                   1848:            STRCPY(cmdbuff + i, p + n); /* append what is after '#' or '%' */
                   1849:            p = cmdbuff + i - 1;        /* remember where to continue */
                   1850:            vim_free(buf);              /* free any allocated string */
                   1851:
                   1852:            if (nextcomm)               /* append next command */
                   1853:            {
                   1854:                i = STRLEN(cmdbuff) + 1;
                   1855:                STRCPY(cmdbuff + i, nextcomm);
                   1856:                nextcomm = cmdbuff + i;
                   1857:            }
                   1858:            cmd = cmdbuff + (cmd - *cmdlinep);
                   1859:            arg = cmdbuff + (arg - *cmdlinep);
                   1860:            vim_free(*cmdlinep);
                   1861:            *cmdlinep = cmdbuff;
                   1862:            *cmdlinelenp = cmdbufflen;
                   1863:        }
                   1864:
                   1865:        /*
                   1866:         * One file argument: expand wildcards.
                   1867:         * Don't do this with ":r !command" or ":w !command".
                   1868:         */
                   1869:        if ((argt & NOSPC) && !usefilter)
                   1870:        {
                   1871: #if defined(UNIX)
                   1872:            /*
                   1873:             * Only for Unix we check for more than one file name.
                   1874:             * For other systems spaces are considered to be part
                   1875:             * of the file name.
                   1876:             * Only check here if there is no wildcard, otherwise ExpandOne
                   1877:             * will check for errors. This allows ":e `ls ve*.c`" on Unix.
                   1878:             */
                   1879:            if (!expand_wildcards)
                   1880:                for (p = arg; *p; ++p)
                   1881:                {
                   1882:                                /* skip escaped characters */
                   1883:                    if (p[1] && (*p == '\\' || *p == Ctrl('V')))
                   1884:                        ++p;
                   1885:                    else if (vim_iswhite(*p))
                   1886:                    {
                   1887:                        errormsg = (char_u *)"Only one file name allowed";
                   1888:                        goto doend;
                   1889:                    }
                   1890:                }
                   1891: #endif
                   1892:            /*
                   1893:             * halve the number of backslashes (this is vi compatible)
                   1894:             */
                   1895:            backslash_halve(arg, expand_wildcards);
                   1896:
                   1897:            if (expand_wildcards)
                   1898:            {
                   1899:                if ((p = ExpandOne(arg, NULL, WILD_LIST_NOTFOUND,
                   1900:                                                   WILD_EXPAND_FREE)) == NULL)
                   1901:                    goto doend;
                   1902:                n = arg - *cmdlinep;
                   1903:                i = STRLEN(p) + n;
                   1904:                if (nextcomm)
                   1905:                    i += STRLEN(nextcomm);
                   1906:                alloc_cmdbuff(i);
                   1907:                if (cmdbuff != NULL)
                   1908:                {
                   1909:                    STRNCPY(cmdbuff, *cmdlinep, n);
                   1910:                    STRCPY(cmdbuff + n, p);
                   1911:                    if (nextcomm)               /* append next command */
                   1912:                    {
                   1913:                        i = STRLEN(cmdbuff) + 1;
                   1914:                        STRCPY(cmdbuff + i, nextcomm);
                   1915:                        nextcomm = cmdbuff + i;
                   1916:                    }
                   1917:                    cmd = cmdbuff + (cmd - *cmdlinep);
                   1918:                    arg = cmdbuff + n;
                   1919:                    vim_free(*cmdlinep);
                   1920:                    *cmdlinep = cmdbuff;
                   1921:                    *cmdlinelenp = cmdbufflen;
                   1922:                }
                   1923:                vim_free(p);
                   1924:            }
                   1925:        }
                   1926:    }
                   1927:
                   1928:    /*
                   1929:     * Accept buffer name.  Cannot be used at the same time with a buffer
                   1930:     * number.
                   1931:     */
                   1932:    if ((argt & BUFNAME) && *arg && addr_count == 0)
                   1933:    {
                   1934:        /*
                   1935:         * :bdelete and :bunload take several arguments, separated by spaces:
                   1936:         * find next space (skipping over escaped characters).
                   1937:         * The others take one argument: ignore trailing spaces.
                   1938:         */
                   1939:        if (cmdidx == CMD_bdelete || cmdidx == CMD_bunload)
                   1940:            p = skiptowhite_esc(arg);
                   1941:        else
                   1942:        {
                   1943:            p = arg + STRLEN(arg);
                   1944:            while (p > arg && vim_iswhite(p[-1]))
                   1945:                --p;
                   1946:        }
                   1947:        line2 = buflist_findpat(arg, p);
                   1948:        if (line2 < 0)          /* failed */
                   1949:            goto doend;
                   1950:        addr_count = 1;
                   1951:        arg = skipwhite(p);
                   1952:    }
                   1953:
                   1954: /*
                   1955:  * 6. switch on command name
                   1956:  *    arg      points to the argument of the command
                   1957:  *    nextcomm points to the next command (if any)
                   1958:  *   cmd       points to the name of the command (except for :make)
                   1959:  *   cmdidx    is the index for the command
                   1960:  *   forceit   is TRUE if ! present
                   1961:  *   addr_count is the number of addresses given
                   1962:  *   line1     is the first line number
                   1963:  *   line2     is the second line number or count
                   1964:  *   do_ecmd_cmd   is +command argument to be used in edited file
                   1965:  *   do_ecmd_lnum  is the line number in edited file
                   1966:  *   append    is TRUE with ":w >>file" command
                   1967:  *   usefilter is TRUE with ":w !command" and ":r!command"
                   1968:  *   amount    is number of '>' or '<' for shift command
                   1969:  */
                   1970: cmdswitch:
                   1971:    switch (cmdidx)
                   1972:    {
                   1973:        /*
                   1974:         * quit current window, quit Vim if closed the last window
                   1975:         */
                   1976:        case CMD_quit:
                   1977:                        /* if more files or windows we won't exit */
                   1978:                if (check_more(FALSE) == OK && only_one_window())
                   1979:                    exiting = TRUE;
                   1980:                if (check_changed(curbuf, FALSE, FALSE) ||
                   1981:                            check_more(TRUE) == FAIL ||
                   1982:                            (only_one_window() && check_changed_any()))
                   1983:                {
                   1984:                    exiting = FALSE;
                   1985:                    settmode(1);
                   1986:                    break;
                   1987:                }
                   1988:                if (only_one_window())  /* quit last window */
                   1989:                    getout(0);
                   1990:                close_window(curwin, TRUE); /* may free buffer */
                   1991:                break;
                   1992:
                   1993:        /*
                   1994:         * try to quit all windows
                   1995:         */
                   1996:        case CMD_qall:
                   1997:                exiting = TRUE;
                   1998:                if (!check_changed_any())
                   1999:                    getout(0);
                   2000:                exiting = FALSE;
                   2001:                settmode(1);
                   2002:                break;
                   2003:
                   2004:        /*
                   2005:         * close current window, unless it is the last one
                   2006:         */
                   2007:        case CMD_close:
                   2008:                close_window(curwin, FALSE);    /* don't free buffer */
                   2009:                break;
                   2010:
                   2011:        /*
                   2012:         * close all but current window, unless it is the last one
                   2013:         */
                   2014:        case CMD_only:
                   2015:                close_others(TRUE);
                   2016:                break;
                   2017:
                   2018:        case CMD_stop:
                   2019:        case CMD_suspend:
                   2020: #ifdef WIN32
                   2021:                /*
                   2022:                 * Check if external commands are allowed now.
                   2023:                 */
                   2024:                if (can_end_termcap_mode(TRUE) == FALSE)
                   2025:                    break;
                   2026: #endif
                   2027:                if (!forceit)
                   2028:                    autowrite_all();
                   2029:                windgoto((int)Rows - 1, 0);
                   2030:                outchar('\n');
                   2031:                flushbuf();
                   2032:                stoptermcap();
                   2033:                mch_restore_title(3);   /* restore window titles */
                   2034:                mch_suspend();          /* call machine specific function */
                   2035:                maketitle();
                   2036:                starttermcap();
                   2037:                scroll_start();         /* scroll screen before redrawing */
                   2038:                must_redraw = CLEAR;
                   2039:                set_winsize(0, 0, FALSE); /* May have resized window -- webb */
                   2040:                break;
                   2041:
                   2042:        case CMD_exit:
                   2043:        case CMD_xit:
                   2044:        case CMD_wq:
                   2045:                            /* if more files or windows we won't exit */
                   2046:                if (check_more(FALSE) == OK && only_one_window())
                   2047:                    exiting = TRUE;
                   2048:                if (((cmdidx == CMD_wq || curbuf->b_changed) &&
                   2049:                                              do_write(arg, FALSE) == FAIL) ||
                   2050:                                                   check_more(TRUE) == FAIL ||
                   2051:                            (only_one_window() && check_changed_any()))
                   2052:                {
                   2053:                    exiting = FALSE;
                   2054:                    settmode(1);
                   2055:                    break;
                   2056:                }
                   2057:                if (only_one_window())  /* quit last window, exit Vim */
                   2058:                    getout(0);
                   2059:                close_window(curwin, TRUE); /* quit current window, may free buffer */
                   2060:                break;
                   2061:
                   2062:        case CMD_xall:      /* write all changed files and exit */
                   2063:        case CMD_wqall:     /* write all changed files and quit */
                   2064:                exiting = TRUE;
                   2065:                /* FALLTHROUGH */
                   2066:
                   2067:        case CMD_wall:      /* write all changed files */
                   2068:                {
                   2069:                    BUF     *buf;
                   2070:                    int     error = 0;
                   2071:
                   2072:                    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                   2073:                    {
                   2074:                        if (buf->b_changed)
                   2075:                        {
                   2076:                            if (buf->b_filename == NULL)
                   2077:                            {
                   2078:                                emsg(e_noname);
                   2079:                                ++error;
                   2080:                            }
                   2081:                            else if (!forceit && buf->b_p_ro)
                   2082:                            {
                   2083:                                EMSG2("\"%s\" is readonly, use ! to write anyway", buf->b_xfilename);
                   2084:                                ++error;
                   2085:                            }
                   2086:                            else if (buf_write_all(buf) == FAIL)
                   2087:                                ++error;
                   2088:                        }
                   2089:                    }
                   2090:                    if (exiting)
                   2091:                    {
                   2092:                        if (!error)
                   2093:                            getout(0);          /* exit Vim */
                   2094:                        exiting = FALSE;
                   2095:                        settmode(1);
                   2096:                    }
                   2097:                }
                   2098:                break;
                   2099:
                   2100:        case CMD_preserve:                  /* put everything in .swp file */
                   2101:                ml_preserve(curbuf, TRUE);
                   2102:                break;
                   2103:
                   2104:        case CMD_recover:                   /* recover file */
                   2105:                recoverymode = TRUE;
                   2106:                if (!check_changed(curbuf, FALSE, TRUE) &&
                   2107:                            (*arg == NUL || setfname(arg, NULL, TRUE) == OK))
                   2108:                    ml_recover();
                   2109:                recoverymode = FALSE;
                   2110:                break;
                   2111:
                   2112:        case CMD_args:
                   2113:                    /*
                   2114:                     * ":args file": handle like :next
                   2115:                     */
                   2116:                if (*arg != NUL && *arg != '|' && *arg != '\n')
                   2117:                    goto do_next;
                   2118:
                   2119:                if (arg_count == 0)             /* no file name list */
                   2120:                {
                   2121:                    if (check_fname() == OK)    /* check for no file name */
                   2122:                        smsg((char_u *)"[%s]", curbuf->b_filename);
                   2123:                    break;
                   2124:                }
                   2125:                /*
                   2126:                 * Overwrite the command, in most cases there is no scrolling
                   2127:                 * required and no wait_return().
                   2128:                 */
                   2129:                gotocmdline(TRUE);
                   2130:                for (i = 0; i < arg_count; ++i)
                   2131:                {
                   2132:                    if (i == curwin->w_arg_idx)
                   2133:                        msg_outchar('[');
                   2134:                    msg_outtrans(arg_files[i]);
                   2135:                    if (i == curwin->w_arg_idx)
                   2136:                        msg_outchar(']');
                   2137:                    msg_outchar(' ');
                   2138:                }
                   2139:                break;
                   2140:
                   2141:        case CMD_wnext:
                   2142:        case CMD_wNext:
                   2143:        case CMD_wprevious:
                   2144:                if (cmd[1] == 'n')
                   2145:                    i = curwin->w_arg_idx + (int)line2;
                   2146:                else
                   2147:                    i = curwin->w_arg_idx - (int)line2;
                   2148:                line1 = 1;
                   2149:                line2 = curbuf->b_ml.ml_line_count;
                   2150:                if (do_write(arg, FALSE) == FAIL)
                   2151:                    break;
                   2152:                goto donextfile;
                   2153:
                   2154:        case CMD_next:
                   2155:        case CMD_snext:
                   2156: do_next:
                   2157:                    /*
                   2158:                     * check for changed buffer now, if this fails the
                   2159:                     * argument list is not redefined.
                   2160:                     */
                   2161:                if (!(p_hid || cmdidx == CMD_snext) &&
                   2162:                                check_changed(curbuf, TRUE, FALSE))
                   2163:                    break;
                   2164:
                   2165:                if (*arg != NUL)                /* redefine file list */
                   2166:                {
                   2167:                    if (do_arglist(arg) == FAIL)
                   2168:                        break;
                   2169:                    i = 0;
                   2170:                }
                   2171:                else
                   2172:                    i = curwin->w_arg_idx + (int)line2;
                   2173:
                   2174: donextfile:        if (i < 0 || i >= arg_count)
                   2175:                {
                   2176:                    if (arg_count <= 1)
                   2177:                        EMSG("There is only one file to edit");
                   2178:                    else if (i < 0)
                   2179:                        EMSG("Cannot go before first file");
                   2180:                    else
                   2181:                        EMSG("Cannot go beyond last file");
                   2182:                    break;
                   2183:                }
                   2184:                setpcmark();
                   2185:                if (*cmd == 's')        /* split window first */
                   2186:                {
                   2187:                    if (win_split(0, FALSE) == FAIL)
                   2188:                        break;
                   2189:                }
                   2190:                else
                   2191:                {
                   2192:                    register int other;
                   2193:
                   2194:                    /*
                   2195:                     * if 'hidden' set, only check for changed file when
                   2196:                     * re-editing the same buffer
                   2197:                     */
                   2198:                    other = TRUE;
                   2199:                    if (p_hid)
                   2200:                        other = otherfile(fix_fname(arg_files[i]));
                   2201:                    if ((!p_hid || !other) &&
                   2202:                                        check_changed(curbuf, TRUE, !other))
                   2203:                    break;
                   2204:                }
                   2205:                curwin->w_arg_idx = i;
                   2206:                if (i == arg_count - 1)
                   2207:                    arg_had_last = TRUE;
                   2208:                (void)do_ecmd(0, arg_files[curwin->w_arg_idx],
                   2209:                               NULL, do_ecmd_cmd, p_hid, do_ecmd_lnum, FALSE);
                   2210:                break;
                   2211:
                   2212:        case CMD_previous:
                   2213:        case CMD_sprevious:
                   2214:        case CMD_Next:
                   2215:        case CMD_sNext:
                   2216:                i = curwin->w_arg_idx - (int)line2;
                   2217:                goto donextfile;
                   2218:
                   2219:        case CMD_rewind:
                   2220:        case CMD_srewind:
                   2221:                i = 0;
                   2222:                goto donextfile;
                   2223:
                   2224:        case CMD_last:
                   2225:        case CMD_slast:
                   2226:                i = arg_count - 1;
                   2227:                goto donextfile;
                   2228:
                   2229:        case CMD_argument:
                   2230:        case CMD_sargument:
                   2231:                if (addr_count)
                   2232:                    i = line2 - 1;
                   2233:                else
                   2234:                    i = curwin->w_arg_idx;
                   2235:                goto donextfile;
                   2236:
                   2237:        case CMD_all:
                   2238:        case CMD_sall:
                   2239:                if (addr_count == 0)
                   2240:                    line2 = 9999;
                   2241:                do_arg_all((int)line2); /* open a window for each argument */
                   2242:                break;
                   2243:
                   2244:        case CMD_buffer:            /* :[N]buffer [N]    to buffer N */
                   2245:        case CMD_sbuffer:           /* :[N]sbuffer [N]   to buffer N */
                   2246:                if (*arg)
                   2247:                {
                   2248:                    errormsg = e_trailing;
                   2249:                    break;
                   2250:                }
                   2251:                if (addr_count == 0)        /* default is current buffer */
                   2252:                    (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2253:                                                DOBUF_CURRENT, FORWARD, 0, 0);
                   2254:                else
                   2255:                    (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2256:                                         DOBUF_FIRST, FORWARD, (int)line2, 0);
                   2257:                break;
                   2258:
                   2259:        case CMD_bmodified:         /* :[N]bmod [N]   to next modified buffer */
                   2260:        case CMD_sbmodified:        /* :[N]sbmod [N]  to next modified buffer */
                   2261:                (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2262:                                           DOBUF_MOD, FORWARD, (int)line2, 0);
                   2263:                break;
                   2264:
                   2265:        case CMD_bnext:             /* :[N]bnext [N]     to next buffer */
                   2266:        case CMD_sbnext:            /* :[N]sbnext [N]    to next buffer */
                   2267:                (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2268:                                       DOBUF_CURRENT, FORWARD, (int)line2, 0);
                   2269:                break;
                   2270:
                   2271:        case CMD_bNext:             /* :[N]bNext [N]     to previous buffer */
                   2272:        case CMD_bprevious:         /* :[N]bprevious [N] to previous buffer */
                   2273:        case CMD_sbNext:            /* :[N]sbNext [N]     to previous buffer */
                   2274:        case CMD_sbprevious:        /* :[N]sbprevious [N] to previous buffer */
                   2275:                (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2276:                                      DOBUF_CURRENT, BACKWARD, (int)line2, 0);
                   2277:                break;
                   2278:
                   2279:        case CMD_brewind:           /* :brewind          to first buffer */
                   2280:        case CMD_sbrewind:          /* :sbrewind         to first buffer */
                   2281:                (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2282:                                                  DOBUF_FIRST, FORWARD, 0, 0);
                   2283:                break;
                   2284:
                   2285:        case CMD_blast:             /* :blast            to last buffer */
                   2286:        case CMD_sblast:            /* :sblast           to last buffer */
                   2287:                (void)do_buffer(*cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
                   2288:                                                   DOBUF_LAST, FORWARD, 0, 0);
                   2289:                break;
                   2290:
                   2291:        case CMD_bunload:       /* :[N]bunload[!] [N] [bufname] unload buffer */
                   2292:        case CMD_bdelete:       /* :[N]bdelete[!] [N] [bufname] delete buffer */
                   2293:                errormsg = do_bufdel(
                   2294:                            cmdidx == CMD_bdelete ? DOBUF_DEL : DOBUF_UNLOAD,
                   2295:                            arg, addr_count, (int)line1, (int)line2, forceit);
                   2296:                break;
                   2297:
                   2298:        case CMD_unhide:
                   2299:        case CMD_sunhide:   /* open a window for loaded buffers */
                   2300:                if (addr_count == 0)
                   2301:                    line2 = 9999;
                   2302:                (void)do_buffer_all((int)line2, FALSE);
                   2303:                break;
                   2304:
                   2305:        case CMD_ball:
                   2306:        case CMD_sball:     /* open a window for every buffer */
                   2307:                if (addr_count == 0)
                   2308:                    line2 = 9999;
                   2309:                (void)do_buffer_all((int)line2, TRUE);
                   2310:                break;
                   2311:
                   2312:        case CMD_buffers:
                   2313:        case CMD_files:
                   2314:        case CMD_ls:
                   2315:                buflist_list();
                   2316:                break;
                   2317:
                   2318:        case CMD_write:
                   2319:                if (usefilter)      /* input lines to shell command */
                   2320:                    do_bang(1, line1, line2, FALSE, arg, TRUE, FALSE);
                   2321:                else
                   2322:                    (void)do_write(arg, append);
                   2323:                break;
                   2324:
                   2325:            /*
                   2326:             * set screen mode
                   2327:             * if no argument given, just get the screen size and redraw
                   2328:             */
                   2329:        case CMD_mode:
                   2330:                if (*arg == NUL || mch_screenmode(arg) != FAIL)
                   2331:                    set_winsize(0, 0, FALSE);
                   2332:                break;
                   2333:
                   2334:                /*
                   2335:                 * set, increment or decrement current window height
                   2336:                 */
                   2337:        case CMD_resize:
                   2338:                n = atol((char *)arg);
                   2339:                if (*arg == '-' || *arg == '+')
                   2340:                    win_setheight(curwin->w_height + (int)n);
                   2341:                else
                   2342:                {
                   2343:                    if (n == 0)     /* default is very high */
                   2344:                        n = 9999;
                   2345:                    win_setheight((int)n);
                   2346:                }
                   2347:                break;
                   2348:
                   2349:                /*
                   2350:                 * :sview [+command] file    split window with new file, ro
                   2351:                 * :split [[+command] file]  split window with current or new file
                   2352:                 * :new [[+command] file]    split window with no or new file
                   2353:                 */
                   2354:        case CMD_sview:
                   2355:        case CMD_split:
                   2356:        case CMD_new:
                   2357:                old_curwin = curwin;
                   2358:                if (win_split(addr_count ? (int)line2 : 0, FALSE) == FAIL)
                   2359:                    break;
                   2360:                /*FALLTHROUGH*/
                   2361:
                   2362:        case CMD_edit:
                   2363:        case CMD_ex:
                   2364:        case CMD_visual:
                   2365:        case CMD_view:
                   2366:                if ((cmdidx == CMD_new) && *arg == NUL)
                   2367:                {
                   2368:                    setpcmark();
                   2369:                    (void)do_ecmd(0, NULL, NULL, do_ecmd_cmd, TRUE,
                   2370:                                                          (linenr_t)1, FALSE);
                   2371:                }
                   2372:                else if (cmdidx != CMD_split || *arg != NUL)
                   2373:                {
                   2374:                    n = readonlymode;
                   2375:                    if (cmdidx == CMD_view || cmdidx == CMD_sview)
                   2376:                        readonlymode = TRUE;
                   2377:                    setpcmark();
                   2378:                    (void)do_ecmd(0, arg, NULL, do_ecmd_cmd, p_hid,
                   2379:                                                           do_ecmd_lnum, FALSE);
                   2380:                    readonlymode = n;
                   2381:                }
                   2382:                else
                   2383:                    updateScreen(NOT_VALID);
                   2384:                    /* if ":split file" worked, set alternate filename in
                   2385:                     * old window to new file */
                   2386:                if ((cmdidx == CMD_new || cmdidx == CMD_split) &&
                   2387:                                *arg != NUL && curwin != old_curwin &&
                   2388:                                old_curwin->w_buffer != curbuf)
                   2389:                    old_curwin->w_alt_fnum = curbuf->b_fnum;
                   2390:                break;
                   2391:
                   2392: #ifdef USE_GUI
                   2393:        /*
                   2394:         * Change from the terminal version to the GUI version.  File names may
                   2395:         * be given to redefine the args list -- webb
                   2396:         */
                   2397:        case CMD_gvim:
                   2398:        case CMD_gui:
                   2399:                if (arg[0] == '-' && arg[1] == 'f' &&
                   2400:                                       (arg[2] == NUL || vim_iswhite(arg[2])))
                   2401:                {
                   2402:                    gui.dofork = FALSE;
                   2403:                    arg = skipwhite(arg + 2);
                   2404:                }
                   2405:                else
                   2406:                    gui.dofork = TRUE;
                   2407:                if (!gui.in_use)
                   2408:                    gui_start();
                   2409:                if (*arg != NUL && *arg != '|' && *arg != '\n')
                   2410:                    goto do_next;
                   2411:                break;
                   2412: #endif
                   2413:
                   2414:        case CMD_file:
                   2415:                do_file(arg, forceit);
                   2416:                break;
                   2417:
                   2418:        case CMD_swapname:
                   2419:                if (curbuf->b_ml.ml_mfp == NULL ||
                   2420:                                (p = curbuf->b_ml.ml_mfp->mf_fname) == NULL)
                   2421:                    MSG("No swap file");
                   2422:                else
                   2423:                    msg(p);
                   2424:                break;
                   2425:
                   2426:        case CMD_mfstat:        /* print memfile statistics, for debugging */
                   2427:                mf_statistics();
                   2428:                break;
                   2429:
                   2430:        case CMD_read:
                   2431:                if (usefilter)                  /* :r!cmd */
                   2432:                {
                   2433:                    do_bang(1, line1, line2, FALSE, arg, FALSE, TRUE);
                   2434:                    break;
                   2435:                }
                   2436:                if (u_save(line2, (linenr_t)(line2 + 1)) == FAIL)
                   2437:                    break;
                   2438:                if (*arg == NUL)
                   2439:                {
                   2440:                    if (check_fname() == FAIL)  /* check for no file name */
                   2441:                        break;
                   2442:                    i = readfile(curbuf->b_filename, curbuf->b_sfilename,
                   2443:                                    line2, FALSE, (linenr_t)0, MAXLNUM, FALSE);
                   2444:                }
                   2445:                else
                   2446:                {
                   2447:                    i = readfile(arg, NULL,
                   2448:                                    line2, FALSE, (linenr_t)0, MAXLNUM, FALSE);
                   2449:                }
                   2450:                if (i == FAIL)
                   2451:                {
                   2452:                    emsg2(e_notopen, arg);
                   2453:                    break;
                   2454:                }
                   2455:
                   2456:                updateScreen(NOT_VALID);
                   2457:                break;
                   2458:
                   2459:        case CMD_cd:
                   2460:        case CMD_chdir:
                   2461: #ifdef UNIX
                   2462:                /*
                   2463:                 * for UNIX ":cd" means: go to home directory
                   2464:                 */
                   2465:                if (*arg == NUL)     /* use NameBuff for home directory name */
                   2466:                {
                   2467:                    expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
                   2468:                    arg = NameBuff;
                   2469:                }
                   2470: #endif
                   2471:                if (*arg != NUL)
                   2472:                {
                   2473:                    if (!did_cd)
                   2474:                    {
                   2475:                        BUF     *buf;
                   2476:
                   2477:                            /* use full path from now on for names of files
                   2478:                             * being edited and swap files */
                   2479:                        for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                   2480:                        {
                   2481:                            buf->b_xfilename = buf->b_filename;
                   2482:                            mf_fullname(buf->b_ml.ml_mfp);
                   2483:                        }
                   2484:                        status_redraw_all();
                   2485:                    }
                   2486:                    did_cd = TRUE;
                   2487:                    if (vim_chdir((char *)arg))
                   2488:                        emsg(e_failed);
                   2489:                    break;
                   2490:                }
                   2491:                /*FALLTHROUGH*/
                   2492:
                   2493:        case CMD_pwd:
                   2494:                if (mch_dirname(NameBuff, MAXPATHL) == OK)
                   2495:                    msg(NameBuff);
                   2496:                else
                   2497:                    emsg(e_unknown);
                   2498:                break;
                   2499:
                   2500:        case CMD_equal:
                   2501:                smsg((char_u *)"line %ld", (long)line2);
                   2502:                break;
                   2503:
                   2504:        case CMD_list:
                   2505:                i = curwin->w_p_list;
                   2506:                curwin->w_p_list = 1;
                   2507:        case CMD_number:                /* :nu */
                   2508:        case CMD_pound:                 /* :# */
                   2509:        case CMD_print:                 /* :p */
                   2510:                for ( ;!got_int; mch_breakcheck())
                   2511:                {
                   2512:                    print_line(line1,
                   2513:                               (cmdidx == CMD_number || cmdidx == CMD_pound));
                   2514:                    if (++line1 > line2)
                   2515:                        break;
                   2516:                    flushbuf();         /* show one line at a time */
                   2517:                }
                   2518:                setpcmark();
                   2519:                curwin->w_cursor.lnum = line2;  /* put cursor at last line */
                   2520:
                   2521:                if (cmdidx == CMD_list)
                   2522:                    curwin->w_p_list = i;
                   2523:
                   2524:                break;
                   2525:
                   2526:        case CMD_shell:
                   2527:                do_shell(NULL);
                   2528:                break;
                   2529:
                   2530:        case CMD_sleep:
                   2531:                n = curwin->w_winpos + curwin->w_row - msg_scrolled;
                   2532:                if (n >= 0)
                   2533:                {
                   2534:                    windgoto((int)n, curwin->w_col);
                   2535:                    flushbuf();
                   2536:                }
                   2537:                mch_delay(line2 * 1000L, TRUE);
                   2538:                break;
                   2539:
                   2540:        case CMD_stag:
                   2541:                postponed_split = TRUE;
                   2542:                /*FALLTHROUGH*/
                   2543:        case CMD_tag:
                   2544:                do_tag(arg, 0, addr_count ? (int)line2 : 1);
                   2545:                break;
                   2546:
                   2547:        case CMD_pop:
                   2548:                do_tag((char_u *)"", 1, addr_count ? (int)line2 : 1);
                   2549:                break;
                   2550:
                   2551:        case CMD_tags:
                   2552:                do_tags();
                   2553:                break;
                   2554:
                   2555:        case CMD_marks:
                   2556:                do_marks(arg);
                   2557:                break;
                   2558:
                   2559:        case CMD_jumps:
                   2560:                do_jumps();
                   2561:                break;
                   2562:
                   2563:        case CMD_ascii:
                   2564:                do_ascii();
                   2565:                break;
                   2566:
                   2567:        case CMD_checkpath:
                   2568:                find_pattern_in_path(NULL, 0, FALSE, FALSE, CHECK_PATH, 1L,
                   2569:                                      forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
                   2570:                                            (linenr_t)1, (linenr_t)MAXLNUM);
                   2571:                break;
                   2572:
                   2573:        case CMD_digraphs:
                   2574: #ifdef DIGRAPHS
                   2575:                if (*arg)
                   2576:                    putdigraph(arg);
                   2577:                else
                   2578:                    listdigraphs();
                   2579: #else
                   2580:                EMSG("No digraphs in this version");
                   2581: #endif /* DIGRAPHS */
                   2582:                break;
                   2583:
                   2584:        case CMD_set:
                   2585:                (void)do_set(arg);
                   2586:                break;
                   2587:
                   2588:        case CMD_fixdel:
                   2589:                do_fixdel();
                   2590:                break;
                   2591:
                   2592: #ifdef AUTOCMD
                   2593:        case CMD_autocmd:
                   2594:                /*
                   2595:                 * Disallow auto commands from .exrc and .vimrc in current
                   2596:                 * directory for security reasons.
                   2597:                 */
                   2598:                if (secure)
                   2599:                {
                   2600:                    secure = 2;
                   2601:                    errormsg = e_curdir;
                   2602:                }
                   2603:                else
                   2604:                    do_autocmd(arg, forceit);   /* handle the auto commands */
                   2605:                break;
                   2606:
                   2607:        case CMD_doautocmd:
                   2608:                do_doautocmd(arg);      /* apply the automatic commands */
                   2609:                do_modelines();
                   2610:                break;
                   2611: #endif
                   2612:
                   2613:        case CMD_abbreviate:
                   2614:        case CMD_cabbrev:
                   2615:        case CMD_iabbrev:
                   2616:        case CMD_cnoreabbrev:
                   2617:        case CMD_inoreabbrev:
                   2618:        case CMD_noreabbrev:
                   2619:        case CMD_unabbreviate:
                   2620:        case CMD_cunabbrev:
                   2621:        case CMD_iunabbrev:
                   2622:                i = ABBREV;
                   2623:                goto doabbr;        /* almost the same as mapping */
                   2624:
                   2625:        case CMD_nmap:
                   2626:        case CMD_vmap:
                   2627:        case CMD_cmap:
                   2628:        case CMD_imap:
                   2629:        case CMD_map:
                   2630:        case CMD_nnoremap:
                   2631:        case CMD_vnoremap:
                   2632:        case CMD_cnoremap:
                   2633:        case CMD_inoremap:
                   2634:        case CMD_noremap:
                   2635:                /*
                   2636:                 * If we are sourcing .exrc or .vimrc in current directory we
                   2637:                 * print the mappings for security reasons.
                   2638:                 */
                   2639:                if (secure)
                   2640:                {
                   2641:                    secure = 2;
                   2642:                    msg_outtrans(cmd);
                   2643:                    msg_outchar('\n');
                   2644:                }
                   2645:        case CMD_nunmap:
                   2646:        case CMD_vunmap:
                   2647:        case CMD_cunmap:
                   2648:        case CMD_iunmap:
                   2649:        case CMD_unmap:
                   2650:                i = 0;
                   2651: doabbr:
                   2652:                if (*cmd == 'c')            /* cmap, cunmap, cnoremap, etc. */
                   2653:                {
                   2654:                    i += CMDLINE;
                   2655:                    ++cmd;
                   2656:                }
                   2657:                else if (*cmd == 'i')       /* imap, iunmap, inoremap, etc. */
                   2658:                {
                   2659:                    i += INSERT;
                   2660:                    ++cmd;
                   2661:                }
                   2662:                                            /* nmap, nunmap, nnoremap */
                   2663:                else if (*cmd == 'n' && *(cmd + 1) != 'o')
                   2664:                {
                   2665:                    i += NORMAL;
                   2666:                    ++cmd;
                   2667:                }
                   2668:                else if (*cmd == 'v')       /* vmap, vunmap, vnoremap */
                   2669:                {
                   2670:                    i += VISUAL;
                   2671:                    ++cmd;
                   2672:                }
                   2673:                else if (forceit || i)      /* map!, unmap!, noremap!, abbrev */
                   2674:                    i += INSERT + CMDLINE;
                   2675:                else                        /* map, unmap, noremap */
                   2676:                    i += NORMAL + VISUAL;
                   2677:                switch (do_map((*cmd == 'n') ? 2 : (*cmd == 'u'), arg, i))
                   2678:                {
                   2679:                    case 1: emsg(e_invarg);
                   2680:                            break;
                   2681:                    case 2: emsg(e_nomap);
                   2682:                            break;
                   2683:                    case 3: emsg(e_ambmap);
                   2684:                            break;
                   2685:                }
                   2686:                break;
                   2687:
                   2688:        case CMD_mapclear:
                   2689:        case CMD_imapclear:
                   2690:        case CMD_nmapclear:
                   2691:        case CMD_vmapclear:
                   2692:        case CMD_cmapclear:
                   2693:                map_clear(*cmd, forceit, FALSE);
                   2694:                break;
                   2695:
                   2696:        case CMD_abclear:
                   2697:        case CMD_iabclear:
                   2698:        case CMD_cabclear:
                   2699:                map_clear(*cmd, FALSE, TRUE);
                   2700:                break;
                   2701:
                   2702: #ifdef USE_GUI
                   2703:        case CMD_menu:      case CMD_noremenu:      case CMD_unmenu:
                   2704:        case CMD_nmenu:     case CMD_nnoremenu:     case CMD_nunmenu:
                   2705:        case CMD_vmenu:     case CMD_vnoremenu:     case CMD_vunmenu:
                   2706:        case CMD_imenu:     case CMD_inoremenu:     case CMD_iunmenu:
                   2707:        case CMD_cmenu:     case CMD_cnoremenu:     case CMD_cunmenu:
                   2708:                gui_do_menu(cmd, arg, forceit);
                   2709:                break;
                   2710: #endif /* USE_GUI */
                   2711:
                   2712:        case CMD_display:
                   2713:        case CMD_registers:
                   2714:                do_dis(arg);        /* display buffer contents */
                   2715:                break;
                   2716:
                   2717:        case CMD_help:
                   2718:                do_help(arg);
                   2719:                break;
                   2720:
                   2721:        case CMD_version:
                   2722:                do_version(arg);
                   2723:                break;
                   2724:
                   2725:        case CMD_winsize:                   /* obsolete command */
                   2726:                line1 = getdigits(&arg);
                   2727:                arg = skipwhite(arg);
                   2728:                line2 = getdigits(&arg);
                   2729:                set_winsize((int)line1, (int)line2, TRUE);
                   2730:                break;
                   2731:
                   2732:        case CMD_delete:
                   2733:        case CMD_yank:
                   2734:        case CMD_rshift:
                   2735:        case CMD_lshift:
                   2736:                yankbuffer = regname;
                   2737:                curbuf->b_op_start.lnum = line1;
                   2738:                curbuf->b_op_end.lnum = line2;
                   2739:                op_line_count = line2 - line1 + 1;
                   2740:                op_motion_type = MLINE;
                   2741:                if (cmdidx != CMD_yank)     /* set cursor position for undo */
                   2742:                {
                   2743:                    setpcmark();
                   2744:                    curwin->w_cursor.lnum = line1;
                   2745:                    beginline(MAYBE);
                   2746:                }
                   2747:                switch (cmdidx)
                   2748:                {
                   2749:                case CMD_delete:
                   2750:                    do_delete();
                   2751:                    break;
                   2752:                case CMD_yank:
                   2753:                    (void)do_yank(FALSE, TRUE);
                   2754:                    break;
                   2755: #ifdef RIGHTLEFT
                   2756:                case CMD_rshift:
                   2757:                    do_shift(curwin->w_p_rl ? LSHIFT : RSHIFT, FALSE, amount);
                   2758:                    break;
                   2759:                case CMD_lshift:
                   2760:                    do_shift(curwin->w_p_rl ? RSHIFT : LSHIFT, FALSE, amount);
                   2761:                    break;
                   2762: #else
                   2763:                case CMD_rshift:
                   2764:                    do_shift(RSHIFT, FALSE, amount);
                   2765:                    break;
                   2766:                case CMD_lshift:
                   2767:                    do_shift(LSHIFT, FALSE, amount);
                   2768:                    break;
                   2769: #endif
                   2770:                }
                   2771:                break;
                   2772:
                   2773:        case CMD_put:
                   2774:                yankbuffer = regname;
                   2775:                curwin->w_cursor.lnum = line2;
                   2776:                do_put(forceit ? BACKWARD : FORWARD, -1L, FALSE);
                   2777:                break;
                   2778:
                   2779:        case CMD_t:
                   2780:        case CMD_copy:
                   2781:        case CMD_move:
                   2782:                n = get_address(&arg);
                   2783:                if (arg == NULL)            /* error detected */
                   2784:                {
                   2785:                    nextcomm = NULL;
                   2786:                    break;
                   2787:                }
                   2788:                /*
                   2789:                 * move or copy lines from 'line1'-'line2' to below line 'n'
                   2790:                 */
                   2791:                if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
                   2792:                {
                   2793:                    emsg(e_invaddr);
                   2794:                    break;
                   2795:                }
                   2796:
                   2797:                if (cmdidx == CMD_move)
                   2798:                {
                   2799:                    if (do_move(line1, line2, n) == FAIL)
                   2800:                        break;
                   2801:                }
                   2802:                else
                   2803:                    do_copy(line1, line2, n);
                   2804:                u_clearline();
                   2805:                beginline(MAYBE);
                   2806:                updateScreen(NOT_VALID);
                   2807:                break;
                   2808:
                   2809:        case CMD_and:           /* :& */
                   2810:        case CMD_tilde:         /* :~ */
                   2811:        case CMD_substitute:    /* :s */
                   2812:                do_sub(line1, line2, arg, &nextcomm,
                   2813:                            cmdidx == CMD_substitute ? 0 :
                   2814:                            cmdidx == CMD_and ? 1 : 2);
                   2815:                break;
                   2816:
                   2817:        case CMD_join:
                   2818:                curwin->w_cursor.lnum = line1;
                   2819:                if (line1 == line2)
                   2820:                {
                   2821:                    if (addr_count >= 2)    /* :2,2join does nothing */
                   2822:                        break;
                   2823:                    if (line2 == curbuf->b_ml.ml_line_count)
                   2824:                    {
                   2825:                        beep_flush();
                   2826:                        break;
                   2827:                    }
                   2828:                    ++line2;
                   2829:                }
                   2830:                do_do_join(line2 - line1 + 1, !forceit, FALSE);
                   2831:                beginline(TRUE);
                   2832:                break;
                   2833:
                   2834:        case CMD_global:
                   2835:                if (forceit)
                   2836:                    *cmd = 'v';
                   2837:        case CMD_vglobal:
                   2838:                do_glob(*cmd, line1, line2, arg);
                   2839:                break;
                   2840:
                   2841:        case CMD_at:                /* :[addr]@r */
                   2842:                curwin->w_cursor.lnum = line2;
                   2843:                                    /* put the register in mapbuf */
                   2844:                if (do_execbuf(*arg, TRUE,
                   2845:                              vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
                   2846:                    beep_flush();
                   2847:                else
                   2848:                                    /* execute from the mapbuf */
                   2849:                    while (vpeekc() == ':')
                   2850:                    {
                   2851:                        (void)vgetc();
                   2852:                        (void)do_cmdline((char_u *)NULL, TRUE, TRUE);
                   2853:                    }
                   2854:                break;
                   2855:
                   2856:        case CMD_bang:
                   2857:                do_bang(addr_count, line1, line2, forceit, arg, TRUE, TRUE);
                   2858:                break;
                   2859:
                   2860:        case CMD_undo:
                   2861:                u_undo(1);
                   2862:                break;
                   2863:
                   2864:        case CMD_redo:
                   2865:                u_redo(1);
                   2866:                break;
                   2867:
                   2868:        case CMD_source:
                   2869:                if (forceit)                    /* :so! read vi commands */
                   2870:                    (void)openscript(arg);
                   2871:                                                /* :so read ex commands */
                   2872:                else if (do_source(arg, FALSE) == FAIL)
                   2873:                    emsg2(e_notopen, arg);
                   2874:                break;
                   2875:
                   2876: #ifdef VIMINFO
                   2877:        case CMD_rviminfo:
                   2878:                p = p_viminfo;
                   2879:                if (*p_viminfo == NUL)
                   2880:                    p_viminfo = (char_u *)"'100";
                   2881:                if (read_viminfo(arg, TRUE, TRUE, forceit) == FAIL)
                   2882:                    EMSG("Cannot open viminfo file for reading");
                   2883:                p_viminfo = p;
                   2884:                break;
                   2885:
                   2886:        case CMD_wviminfo:
                   2887:                p = p_viminfo;
                   2888:                if (*p_viminfo == NUL)
                   2889:                    p_viminfo = (char_u *)"'100";
                   2890:                write_viminfo(arg, forceit);
                   2891:                p_viminfo = p;
                   2892:                break;
                   2893: #endif /* VIMINFO */
                   2894:
                   2895:        case CMD_mkvimrc:
                   2896:                if (*arg == NUL)
                   2897:                    arg = (char_u *)VIMRC_FILE;
                   2898:                /*FALLTHROUGH*/
                   2899:
                   2900:        case CMD_mkexrc:
                   2901:                {
                   2902:                    FILE    *fd;
                   2903:
                   2904:                    if (*arg == NUL)
                   2905:                        arg = (char_u *)EXRC_FILE;
                   2906: #ifdef UNIX
                   2907:                    /* with Unix it is possible to open a directory */
                   2908:                    if (mch_isdir(arg))
                   2909:                    {
                   2910:                        EMSG2("\"%s\" is a directory", arg);
                   2911:                        break;
                   2912:                    }
                   2913: #endif
                   2914:                    if (!forceit && vim_fexists(arg))
                   2915:                    {
                   2916:                        EMSG2("\"%s\" exists (use ! to override)", arg);
                   2917:                        break;
                   2918:                    }
                   2919:
                   2920:                    if ((fd = fopen((char *)arg, WRITEBIN)) == NULL)
                   2921:                    {
                   2922:                        EMSG2("Cannot open \"%s\" for writing", arg);
                   2923:                        break;
                   2924:                    }
                   2925:
                   2926:                    /* Write the version command for :mkvimrc */
                   2927:                    if (cmdidx == CMD_mkvimrc)
                   2928:                    {
                   2929: #ifdef USE_CRNL
                   2930:                        fprintf(fd, "version 4.0\r\n");
                   2931: #else
                   2932:                        fprintf(fd, "version 4.0\n");
                   2933: #endif
                   2934:                    }
                   2935:
                   2936:                    if (makemap(fd) == FAIL || makeset(fd) == FAIL ||
                   2937:                                                                   fclose(fd))
                   2938:                        emsg(e_write);
                   2939:                    break;
                   2940:                }
                   2941:
                   2942:        case CMD_cc:
                   2943:                    qf_jump(0, addr_count ? (int)line2 : 0);
                   2944:                    break;
                   2945:
                   2946:        case CMD_cfile:
                   2947:                    if (*arg != NUL)
                   2948:                    {
                   2949:                        /*
                   2950:                         * Great trick: Insert 'ef=' before arg.
                   2951:                         * Always ok, because "cf " must be there.
                   2952:                         */
                   2953:                        arg -= 3;
                   2954:                        arg[0] = 'e';
                   2955:                        arg[1] = 'f';
                   2956:                        arg[2] = '=';
                   2957:                        (void)do_set(arg);
                   2958:                    }
                   2959:                    if (qf_init() == OK)
                   2960:                        qf_jump(0, 0);          /* display first error */
                   2961:                    break;
                   2962:
                   2963:        case CMD_clist:
                   2964:                    qf_list(forceit);
                   2965:                    break;
                   2966:
                   2967:        case CMD_cnext:
                   2968:                    qf_jump(FORWARD, addr_count ? (int)line2 : 1);
                   2969:                    break;
                   2970:
                   2971:        case CMD_cNext:
                   2972:        case CMD_cprevious:
                   2973:                    qf_jump(BACKWARD, addr_count ? (int)line2 : 1);
                   2974:                    break;
                   2975:
                   2976:        case CMD_cquit:
                   2977:                    getout(1);      /* this does not always work. why? */
                   2978:
                   2979:        case CMD_mark:
                   2980:        case CMD_k:
                   2981:                    pos = curwin->w_cursor;         /* save curwin->w_cursor */
                   2982:                    curwin->w_cursor.lnum = line2;
                   2983:                    beginline(MAYBE);
                   2984:                    (void)setmark(*arg);            /* set mark */
                   2985:                    curwin->w_cursor = pos;         /* restore curwin->w_cursor */
                   2986:                    break;
                   2987:
                   2988:        case CMD_center:
                   2989:        case CMD_right:
                   2990:        case CMD_left:
                   2991:                    do_align(line1, line2, atoi((char *)arg),
                   2992:                            cmdidx == CMD_center ? 0 : cmdidx == CMD_right ? 1 : -1);
                   2993:                    break;
                   2994:
                   2995:        case CMD_retab:
                   2996:                n = getdigits(&arg);
                   2997:                do_retab(line1, line2, (int)n, forceit);
                   2998:                u_clearline();
                   2999:                updateScreen(NOT_VALID);
                   3000:                break;
                   3001:
                   3002:        case CMD_make:
                   3003:                do_make(arg);
                   3004:                break;
                   3005:
                   3006:                /*
                   3007:                 * :normal[!] {commands} - execute normal mode commands
                   3008:                 * Mostly used for ":autocmd".
                   3009:                 */
                   3010:        case CMD_normal:
                   3011:                /*
                   3012:                 * Stuff the argument into the typeahead buffer.
                   3013:                 * Execute normal() until there is no more typeahead than
                   3014:                 * there was before this command.
                   3015:                 */
                   3016:                len = typelen;
                   3017:                ins_typebuf(arg, forceit ? -1 : 0, 0, TRUE);
                   3018:                while ((!stuff_empty() ||
                   3019:                             (!typebuf_typed() && typelen > len)) && !got_int)
                   3020:                {
                   3021:                    adjust_cursor();    /* put cursor on an existing line */
                   3022:                    cursupdate();       /* update cursor position */
                   3023:                    normal();    /* get and execute a normal mode command */
                   3024:                }
                   3025:                break;
                   3026:
                   3027:        case CMD_isearch:
                   3028:        case CMD_dsearch:
                   3029:                i = ACTION_SHOW;
                   3030:                goto find_pat;
                   3031:
                   3032:        case CMD_ilist:
                   3033:        case CMD_dlist:
                   3034:                i = ACTION_SHOW_ALL;
                   3035:                goto find_pat;
                   3036:
                   3037:        case CMD_ijump:
                   3038:        case CMD_djump:
                   3039:                i = ACTION_GOTO;
                   3040:                goto find_pat;
                   3041:
                   3042:        case CMD_isplit:
                   3043:        case CMD_dsplit:
                   3044:                i = ACTION_SPLIT;
                   3045: find_pat:
                   3046:                {
                   3047:                    int     whole = TRUE;
                   3048:
                   3049:                    n = 1;
                   3050:                    if (isdigit(*arg))      /* get count */
                   3051:                    {
                   3052:                        n = getdigits(&arg);
                   3053:                        arg = skipwhite(arg);
                   3054:                    }
                   3055:                    if (*arg == '/')    /* Match regexp, not just whole words */
                   3056:                    {
                   3057:                        whole = FALSE;
                   3058:                        ++arg;
                   3059:                        for (p = arg; *p && *p != '/'; p++)
                   3060:                            if (*p == '\\' && p[1] != NUL)
                   3061:                                p++;
                   3062:                        if (*p)
                   3063:                        {
                   3064:                            *p++ = NUL;
                   3065:                            p = skipwhite(p);
                   3066:
                   3067:                            /* Check for trailing illegal characters */
                   3068:                            if (*p && vim_strchr((char_u *)"|\"\n", *p) == NULL)
                   3069:                                errormsg = e_trailing;
                   3070:                            else
                   3071:                                nextcomm = p;
                   3072:                        }
                   3073:                    }
                   3074:                    find_pattern_in_path(arg, (int)STRLEN(arg), whole, !forceit,
                   3075:                        *cmd == 'd' ?  FIND_DEFINE : FIND_ANY,
                   3076:                        n, i, line1, line2);
                   3077:                }
                   3078:                break;
                   3079:
                   3080:        default:
                   3081:                    /* Normal illegal commands have already been handled */
                   3082:                errormsg = (char_u *)"Sorry, this command is not implemented";
                   3083:    }
                   3084:
                   3085:
                   3086: doend:
                   3087:    if (errormsg != NULL)
                   3088:    {
                   3089:        emsg(errormsg);
                   3090:        if (sourcing)
                   3091:        {
                   3092:            MSG_OUTSTR(": ");
                   3093:            msg_outtrans(*cmdlinep);
                   3094:        }
                   3095:    }
                   3096:    if (did_emsg)
                   3097:        nextcomm = NULL;                /* cancel nextcomm at an error */
                   3098:    forceit = FALSE;        /* reset now so it can be used in getfile() */
                   3099:    if (nextcomm && *nextcomm == NUL)       /* not really a next command */
                   3100:        nextcomm = NULL;
                   3101:    return nextcomm;
                   3102: }
                   3103:
                   3104: /*
                   3105:  * If 'autowrite' option set, try to write the file.
                   3106:  *
                   3107:  * return FAIL for failure, OK otherwise
                   3108:  */
                   3109:    int
                   3110: autowrite(buf)
                   3111:    BUF     *buf;
                   3112: {
                   3113:    if (!p_aw || (!forceit && buf->b_p_ro) || buf->b_filename == NULL)
                   3114:        return FAIL;
                   3115:    return buf_write_all(buf);
                   3116: }
                   3117:
                   3118: /*
                   3119:  * flush all buffers, except the ones that are readonly
                   3120:  */
                   3121:    void
                   3122: autowrite_all()
                   3123: {
                   3124:    BUF     *buf;
                   3125:
                   3126:    if (!p_aw)
                   3127:        return;
                   3128:    for (buf = firstbuf; buf; buf = buf->b_next)
                   3129:        if (buf->b_changed && !buf->b_p_ro)
                   3130:            (void)buf_write_all(buf);
                   3131: }
                   3132:
                   3133: /*
                   3134:  * flush the contents of a buffer, unless it has no file name
                   3135:  *
                   3136:  * return FAIL for failure, OK otherwise
                   3137:  */
                   3138:    static int
                   3139: buf_write_all(buf)
                   3140:    BUF     *buf;
                   3141: {
                   3142:    return (buf_write(buf, buf->b_filename, buf->b_sfilename,
                   3143:                     (linenr_t)1, buf->b_ml.ml_line_count, 0, 0, TRUE, FALSE));
                   3144: }
                   3145:
                   3146: /*
                   3147:  * write current buffer to file 'fname'
                   3148:  * if 'append' is TRUE, append to the file
                   3149:  *
                   3150:  * if *fname == NUL write to current file
                   3151:  * if b_notedited is TRUE, check for overwriting current file
                   3152:  *
                   3153:  * return FAIL for failure, OK otherwise
                   3154:  */
                   3155:    static int
                   3156: do_write(fname, append)
                   3157:    char_u  *fname;
                   3158:    int     append;
                   3159: {
                   3160:    int     other;
                   3161:    char_u  *sfname = NULL;             /* init to shut up gcc */
                   3162:
                   3163:    if (*fname == NUL)
                   3164:        other = FALSE;
                   3165:    else
                   3166:    {
                   3167:        sfname = fname;
                   3168:        fname = fix_fname(fname);
                   3169:        other = otherfile(fname);
                   3170:    }
                   3171:
                   3172:    /*
                   3173:     * if we have a new file name put it in the list of alternate file names
                   3174:     */
                   3175:    if (other)
                   3176:        setaltfname(fname, sfname, (linenr_t)1);
                   3177:
                   3178:    /*
                   3179:     * writing to the current file is not allowed in readonly mode
                   3180:     * and need a file name
                   3181:     */
                   3182:    if (!other && (check_readonly() || check_fname() == FAIL))
                   3183:        return FAIL;
                   3184:
                   3185:    if (!other)
                   3186:    {
                   3187:        fname = curbuf->b_filename;
                   3188:        sfname = curbuf->b_sfilename;
                   3189:        /*
                   3190:         * Not writing the whole file is only allowed with '!'.
                   3191:         */
                   3192:        if ((line1 != 1 || line2 != curbuf->b_ml.ml_line_count) &&
                   3193:                                                 !forceit && !append && !p_wa)
                   3194:        {
                   3195:            EMSG("Use ! to write partial buffer");
                   3196:            return FAIL;
                   3197:        }
                   3198:    }
                   3199:
                   3200:    /*
                   3201:     * write to other file or b_notedited set or not writing the whole file:
                   3202:     * overwriting only allowed with '!'
                   3203:     */
                   3204:    if ((other || curbuf->b_notedited) && !forceit &&
                   3205:                                       !append && !p_wa && vim_fexists(fname))
                   3206:    {                               /* don't overwrite existing file */
                   3207: #ifdef UNIX
                   3208:            /* with UNIX it is possible to open a directory */
                   3209:        if (mch_isdir(fname))
                   3210:            EMSG2("\"%s\" is a directory", fname);
                   3211:        else
                   3212: #endif
                   3213:            emsg(e_exists);
                   3214:        return FAIL;
                   3215:    }
                   3216:    return (buf_write(curbuf, fname, sfname, line1, line2,
                   3217:                                                append, forceit, TRUE, FALSE));
                   3218: }
                   3219:
                   3220: /*
                   3221:  * start editing a new file
                   3222:  *
                   3223:  *     fnum: file number; if zero use fname/sfname
                   3224:  *    fname: the file name
                   3225:  *             - full path if sfname used,
                   3226:  *             - any file name if sfname is NULL
                   3227:  *             - empty string to re-edit with the same file name (but may be
                   3228:  *                 in a different directory)
                   3229:  *             - NULL to start an empty buffer
                   3230:  *   sfname: the short file name (or NULL)
                   3231:  *  command: the command to be executed after loading the file
                   3232:  *     hide: if TRUE don't free the current buffer
                   3233:  *  newlnum: put cursor on this line number (if possible)
                   3234:  * set_help: set b_help flag of (new) buffer before opening file
                   3235:  *
                   3236:  * return FAIL for failure, OK otherwise
                   3237:  */
                   3238:    int
                   3239: do_ecmd(fnum, fname, sfname, command, hide, newlnum, set_help)
                   3240:    int         fnum;
                   3241:    char_u      *fname;
                   3242:    char_u      *sfname;
                   3243:    char_u      *command;
                   3244:    int         hide;
                   3245:    linenr_t    newlnum;
                   3246:    int         set_help;
                   3247: {
                   3248:    int         other_file;             /* TRUE if editing another file */
                   3249:    int         oldbuf = FALSE;         /* TRUE if using existing buffer */
                   3250:    BUF         *buf;
                   3251:
                   3252:    if (fnum != 0)
                   3253:    {
                   3254:        if (fnum == curbuf->b_fnum)     /* file is already being edited */
                   3255:            return OK;                  /* nothing to do */
                   3256:        other_file = TRUE;
                   3257:    }
                   3258:    else
                   3259:    {
                   3260:            /* if no short name given, use fname for short name */
                   3261:        if (sfname == NULL)
                   3262:            sfname = fname;
                   3263: #ifdef USE_FNAME_CASE
                   3264: # ifdef USE_LONG_FNAME
                   3265:        if (USE_LONG_FNAME)
                   3266: # endif
                   3267:            fname_case(sfname);         /* set correct case for short filename */
                   3268: #endif
                   3269:
                   3270:        if (fname == NULL)
                   3271:            other_file = TRUE;
                   3272:                                            /* there is no file name */
                   3273:        else if (*fname == NUL && curbuf->b_filename == NULL)
                   3274:            other_file = FALSE;
                   3275:        else
                   3276:        {
                   3277:            if (*fname == NUL)              /* re-edit with same file name */
                   3278:            {
                   3279:                fname = curbuf->b_filename;
                   3280:                sfname = curbuf->b_sfilename;
                   3281:            }
                   3282:            fname = fix_fname(fname);       /* may expand to full path name */
                   3283:            other_file = otherfile(fname);
                   3284:        }
                   3285:    }
                   3286: /*
                   3287:  * if the file was changed we may not be allowed to abandon it
                   3288:  * - if we are going to re-edit the same file
                   3289:  * - or if we are the only window on this file and if hide is FALSE
                   3290:  */
                   3291:    if ((!other_file || (curbuf->b_nwindows == 1 && !hide)) &&
                   3292:                        check_changed(curbuf, FALSE, !other_file))
                   3293:    {
                   3294:        if (fnum == 0 && other_file && fname != NULL)
                   3295:            setaltfname(fname, sfname, (linenr_t)1);
                   3296:        return FAIL;
                   3297:    }
                   3298:
                   3299: /*
                   3300:  * End Visual mode before switching to another buffer, so the text can be
                   3301:  * copied into the GUI selection buffer.
                   3302:  */
                   3303:    if (VIsual_active)
                   3304:        end_visual_mode();
                   3305:
                   3306: /*
                   3307:  * If we are starting to edit another file, open a (new) buffer.
                   3308:  * Otherwise we re-use the current buffer.
                   3309:  */
                   3310:    if (other_file)
                   3311:    {
                   3312:        curwin->w_alt_fnum = curbuf->b_fnum;
                   3313:        buflist_altlnum();
                   3314:
                   3315:        if (fnum)
                   3316:            buf = buflist_findnr(fnum);
                   3317:        else
                   3318:            buf = buflist_new(fname, sfname, 1L, TRUE);
                   3319:        if (buf == NULL)
                   3320:            return FAIL;
                   3321:        if (buf->b_ml.ml_mfp == NULL)       /* no memfile yet */
                   3322:        {
                   3323:            oldbuf = FALSE;
                   3324:            buf->b_nwindows = 1;
                   3325:        }
                   3326:        else                                /* existing memfile */
                   3327:        {
                   3328:            oldbuf = TRUE;
                   3329:            ++buf->b_nwindows;
                   3330:            buf_check_timestamp(buf);
                   3331:        }
                   3332:
                   3333:        /*
                   3334:         * make the (new) buffer the one used by the current window
                   3335:         * if the old buffer becomes unused, free it if hide is FALSE
                   3336:         * If the current buffer was empty and has no file name, curbuf
                   3337:         * is returned by buflist_new().
                   3338:         */
                   3339:        if (buf != curbuf)
                   3340:        {
                   3341: #ifdef AUTOCMD
                   3342:            apply_autocmds(EVENT_BUFLEAVE, NULL, NULL);
                   3343: #endif
                   3344: #ifdef VIMINFO
                   3345:            curbuf->b_last_cursor = curwin->w_cursor;
                   3346: #endif
                   3347:            buf_copy_options(curbuf, buf, TRUE);
                   3348:            close_buffer(curwin, curbuf, !hide, FALSE);
                   3349:            curwin->w_buffer = buf;
                   3350:            curbuf = buf;
                   3351:        }
                   3352:
                   3353:        curwin->w_pcmark.lnum = 1;
                   3354:        curwin->w_pcmark.col = 0;
                   3355:    }
                   3356:    else if (check_fname() == FAIL)
                   3357:        return FAIL;
                   3358:
                   3359: /*
                   3360:  * If we get here we are sure to start editing
                   3361:  */
                   3362:        /* don't redraw until the cursor is in the right line */
                   3363:    ++RedrawingDisabled;
                   3364:    if (set_help)
                   3365:        curbuf->b_help = TRUE;
                   3366:
                   3367: /*
                   3368:  * other_file  oldbuf
                   3369:  * FALSE       FALSE       re-edit same file, buffer is re-used
                   3370:  * FALSE       TRUE        not posible
                   3371:  *  TRUE       FALSE       start editing new file, new buffer
                   3372:  *  TRUE       TRUE        start editing in existing buffer (nothing to do)
                   3373:  */
                   3374:    if (!other_file)                    /* re-use the buffer */
                   3375:    {
                   3376:        if (newlnum == 0)
                   3377:            newlnum = curwin->w_cursor.lnum;
                   3378:        buf_freeall(curbuf);            /* free all things for buffer */
                   3379:        buf_clear(curbuf);
                   3380:        curbuf->b_op_start.lnum = 0;    /* clear '[ and '] marks */
                   3381:        curbuf->b_op_end.lnum = 0;
                   3382:    }
                   3383:
                   3384:    /*
                   3385:     * Check if we are editing the w_arg_idx file in the argument list.
                   3386:     */
                   3387:    check_arg_idx();
                   3388:
                   3389:    if (!oldbuf)                        /* need to read the file */
                   3390:        (void)open_buffer();
                   3391: #ifdef AUTOCMD
                   3392:    else
                   3393:        apply_autocmds(EVENT_BUFENTER, NULL, NULL);
                   3394: #endif
                   3395:    win_init(curwin);
                   3396:    maketitle();
                   3397:
                   3398:    if (command == NULL)
                   3399:    {
                   3400:        if (newlnum)
                   3401:        {
                   3402:            curwin->w_cursor.lnum = newlnum;
                   3403:            check_cursor();
                   3404:            beginline(MAYBE);
                   3405:        }
                   3406:        else
                   3407:            beginline(TRUE);
                   3408:    }
                   3409:
                   3410:    /*
                   3411:     * Did not read the file, need to show some info about the file.
                   3412:     * Do this after setting the cursor.
                   3413:     */
                   3414:    if (oldbuf)
                   3415:        fileinfo(did_cd, TRUE, FALSE);
                   3416:
                   3417:    if (command != NULL)
                   3418:        do_cmdline(command, TRUE, FALSE);
                   3419:    --RedrawingDisabled;
                   3420:    if (!skip_redraw)
                   3421:        updateScreen(CURSUPD);          /* redraw now */
                   3422:
                   3423:    if (p_im)
                   3424:        need_start_insertmode = TRUE;
                   3425:    return OK;
                   3426: }
                   3427:
                   3428: /*
                   3429:  * get + command from ex argument
                   3430:  */
                   3431:    static char_u *
                   3432: getargcmd(argp)
                   3433:    char_u **argp;
                   3434: {
                   3435:    char_u *arg = *argp;
                   3436:    char_u *command = NULL;
                   3437:
                   3438:    if (*arg == '+')        /* +[command] */
                   3439:    {
                   3440:        ++arg;
                   3441:        if (vim_isspace(*arg))
                   3442:            command = (char_u *)"$";
                   3443:        else
                   3444:        {
                   3445:            /*
                   3446:             * should check for "\ " (but vi has a bug that prevents it to work)
                   3447:             */
                   3448:            command = arg;
                   3449:            arg = skiptowhite(command);
                   3450:            if (*arg)
                   3451:                *arg++ = NUL;   /* terminate command with NUL */
                   3452:        }
                   3453:
                   3454:        arg = skipwhite(arg);   /* skip over spaces */
                   3455:        *argp = arg;
                   3456:    }
                   3457:    return command;
                   3458: }
                   3459:
                   3460: /*
                   3461:  * Halve the number of backslashes in a file name argument.
                   3462:  * For MS-DOS we only do this if the character after the backslash
                   3463:  * is not a normal file character.
                   3464:  * For Unix, when wildcards are going to be expanded, don't remove
                   3465:  * backslashes before special characters.
                   3466:  */
                   3467:    static void
                   3468: backslash_halve(p, expand_wildcards)
                   3469:    char_u  *p;
                   3470:    int     expand_wildcards;       /* going to expand wildcards later */
                   3471: {
                   3472:    for ( ; *p; ++p)
                   3473:        if (is_backslash(p)
                   3474: #if defined(MSDOS) || defined(WIN32)
                   3475:                && p[1] != '*' && p[1] != '?'
                   3476: #endif
                   3477: #if defined(UNIX) || defined(OS2)
                   3478:                && !(expand_wildcards &&
                   3479:                        vim_strchr((char_u *)" *?[{`$\\", p[1]))
                   3480: #endif
                   3481:                                               )
                   3482:            STRCPY(p, p + 1);
                   3483: }
                   3484:
                   3485:    static void
                   3486: do_make(arg)
                   3487:    char_u *arg;
                   3488: {
                   3489:    if (*p_ef == NUL)
                   3490:    {
                   3491:        EMSG("errorfile option not set");
                   3492:        return;
                   3493:    }
                   3494:
                   3495:    autowrite_all();
                   3496:    vim_remove(p_ef);
                   3497:
                   3498:    sprintf((char *)IObuff, "%s %s %s", arg, p_sp, p_ef);
                   3499:    MSG_OUTSTR(":!");
                   3500:    msg_outtrans(IObuff);               /* show what we are doing */
                   3501:    do_shell(IObuff);
                   3502:
                   3503: #ifdef AMIGA
                   3504:    flushbuf();
                   3505:                /* read window status report and redraw before message */
                   3506:    (void)char_avail();
                   3507: #endif
                   3508:
                   3509:    if (qf_init() == OK)
                   3510:        qf_jump(0, 0);          /* display first error */
                   3511:
                   3512:    vim_remove(p_ef);
                   3513: }
                   3514:
                   3515: /*
                   3516:  * Redefine the argument list to 'str'.
                   3517:  *
                   3518:  * Return FAIL for failure, OK otherwise.
                   3519:  */
                   3520:    static int
                   3521: do_arglist(str)
                   3522:    char_u *str;
                   3523: {
                   3524:    int     new_count = 0;
                   3525:    char_u  **new_files = NULL;
                   3526:    int     exp_count;
                   3527:    char_u  **exp_files;
                   3528:    char_u  **t;
                   3529:    char_u  *p;
                   3530:    int     inquote;
                   3531:    int     i;
                   3532:
                   3533:    while (*str)
                   3534:    {
                   3535:        /*
                   3536:         * create a new entry in new_files[]
                   3537:         */
                   3538:        t = (char_u **)lalloc((long_u)(sizeof(char_u *) * (new_count + 1)), TRUE);
                   3539:        if (t != NULL)
                   3540:            for (i = new_count; --i >= 0; )
                   3541:                t[i] = new_files[i];
                   3542:        vim_free(new_files);
                   3543:        if (t == NULL)
                   3544:            return FAIL;
                   3545:        new_files = t;
                   3546:        new_files[new_count++] = str;
                   3547:
                   3548:        /*
                   3549:         * isolate one argument, taking quotes
                   3550:         */
                   3551:        inquote = FALSE;
                   3552:        for (p = str; *str; ++str)
                   3553:        {
                   3554:            /*
                   3555:             * for MSDOS et.al. a backslash is part of a file name.
                   3556:             * Only skip ", space and tab.
                   3557:             */
                   3558:            if (is_backslash(str))
                   3559:                *p++ = *++str;
                   3560:            else
                   3561:            {
                   3562:                if (!inquote && vim_isspace(*str))
                   3563:                    break;
                   3564:                if (*str == '"')
                   3565:                    inquote ^= TRUE;
                   3566:                else
                   3567:                    *p++ = *str;
                   3568:            }
                   3569:        }
                   3570:        str = skipwhite(str);
                   3571:        *p = NUL;
                   3572:    }
                   3573:
                   3574:    i = ExpandWildCards(new_count, new_files, &exp_count,
                   3575:                                                &exp_files, FALSE, TRUE);
                   3576:    vim_free(new_files);
                   3577:    if (i == FAIL)
                   3578:        return FAIL;
                   3579:    if (exp_count == 0)
                   3580:    {
                   3581:        emsg(e_nomatch);
                   3582:        return FAIL;
                   3583:    }
                   3584:    if (arg_exp)                /* arg_files[] has been allocated, free it */
                   3585:        FreeWild(arg_count, arg_files);
                   3586:    else
                   3587:        arg_exp = TRUE;
                   3588:    arg_files = exp_files;
                   3589:    arg_count = exp_count;
                   3590:    arg_had_last = FALSE;
                   3591:
                   3592:    /*
                   3593:     * put all file names in the buffer list
                   3594:     */
                   3595:    for (i = 0; i < arg_count; ++i)
                   3596:        (void)buflist_add(arg_files[i]);
                   3597:
                   3598:    return OK;
                   3599: }
                   3600:
                   3601: /*
                   3602:  * Return TRUE if "str" starts with a backslash that should be removed.
                   3603:  * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
                   3604:  * backslash is not a normal file name character.
                   3605:  */
                   3606:    static int
                   3607: is_backslash(str)
                   3608:    char_u  *str;
                   3609: {
                   3610: #ifdef BACKSLASH_IN_FILENAME
                   3611:    return (str[0] == '\\' && str[1] != NUL &&
                   3612:                                     !(isfilechar(str[1]) && str[1] != '\\'));
                   3613: #else
                   3614:    return (str[0] == '\\' && str[1] != NUL);
                   3615: #endif
                   3616: }
                   3617:
                   3618: /*
                   3619:  * Check if we are editing the w_arg_idx file in the argument list.
                   3620:  */
                   3621:    void
                   3622: check_arg_idx()
                   3623: {
                   3624:    int     t;
                   3625:
                   3626:    if (arg_count > 1 && (curbuf->b_filename == NULL ||
                   3627:                          curwin->w_arg_idx >= arg_count ||
                   3628:                (t = fullpathcmp(arg_files[curwin->w_arg_idx],
                   3629:                           curbuf->b_filename)) == FPC_DIFF || t == FPC_DIFFX))
                   3630:        curwin->w_arg_idx_invalid = TRUE;
                   3631:    else
                   3632:        curwin->w_arg_idx_invalid = FALSE;
                   3633: }
                   3634:
                   3635:    void
                   3636: gotocmdline(clr)
                   3637:    int             clr;
                   3638: {
                   3639:    msg_start();
                   3640:    if (clr)                /* clear the bottom line(s) */
                   3641:        msg_clr_eos();      /* will reset clear_cmdline */
                   3642:    windgoto(cmdline_row, 0);
                   3643: }
                   3644:
                   3645:    static int
                   3646: check_readonly()
                   3647: {
                   3648:    if (!forceit && curbuf->b_p_ro)
                   3649:    {
                   3650:        emsg(e_readonly);
                   3651:        return TRUE;
                   3652:    }
                   3653:    return FALSE;
                   3654: }
                   3655:
                   3656: /*
                   3657:  * return TRUE if buffer was changed and cannot be abandoned.
                   3658:  */
                   3659:    static int
                   3660: check_changed(buf, checkaw, mult_win)
                   3661:    BUF     *buf;
                   3662:    int     checkaw;        /* do autowrite if buffer was changed */
                   3663:    int     mult_win;       /* check also when several windows for the buffer */
                   3664: {
                   3665:    if (    !forceit &&
                   3666:            buf->b_changed && (mult_win || buf->b_nwindows <= 1) &&
                   3667:            (!checkaw || autowrite(buf) == FAIL))
                   3668:    {
                   3669:        emsg(e_nowrtmsg);
                   3670:        return TRUE;
                   3671:    }
                   3672:    return FALSE;
                   3673: }
                   3674:
                   3675: /*
                   3676:  * return TRUE if any buffer was changed and cannot be abandoned.
                   3677:  * That changed buffer becomes the current buffer.
                   3678:  */
                   3679:    static int
                   3680: check_changed_any()
                   3681: {
                   3682:    BUF     *buf;
                   3683:    int     save;
                   3684:
                   3685:    if (!forceit)
                   3686:    {
                   3687:        for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                   3688:        {
                   3689:            if (buf->b_changed)
                   3690:            {
                   3691:                /* There must be a wait_return for this message, do_buffer
                   3692:                 * will cause a redraw */
                   3693:                exiting = FALSE;
                   3694:                if (EMSG2("No write since last change for buffer \"%s\"",
                   3695:                              buf->b_xfilename == NULL ? (char_u *)"No File" :
                   3696:                                                            buf->b_xfilename))
                   3697:                {
                   3698:                    save = no_wait_return;
                   3699:                    no_wait_return = FALSE;
                   3700:                    wait_return(FALSE);
                   3701:                    no_wait_return = save;
                   3702:                }
                   3703:                (void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD,
                   3704:                                                              buf->b_fnum, 0);
                   3705:                return TRUE;
                   3706:            }
                   3707:        }
                   3708:    }
                   3709:    return FALSE;
                   3710: }
                   3711:
                   3712: /*
                   3713:  * return FAIL if there is no filename, OK if there is one
                   3714:  * give error message for FAIL
                   3715:  */
                   3716:    int
                   3717: check_fname()
                   3718: {
                   3719:    if (curbuf->b_filename == NULL)
                   3720:    {
                   3721:        emsg(e_noname);
                   3722:        return FAIL;
                   3723:    }
                   3724:    return OK;
                   3725: }
                   3726:
                   3727: /*
                   3728:  * - if there are more files to edit
                   3729:  * - and this is the last window
                   3730:  * - and forceit not used
                   3731:  * - and not repeated twice on a row
                   3732:  *   return FAIL and give error message if 'message' TRUE
                   3733:  * return OK otherwise
                   3734:  */
                   3735:    static int
                   3736: check_more(message)
                   3737:    int message;            /* when FALSE check only, no messages */
                   3738: {
                   3739:    if (!forceit && only_one_window() && arg_count > 1 && !arg_had_last &&
                   3740:                                    quitmore == 0)
                   3741:    {
                   3742:        if (message)
                   3743:        {
                   3744:            EMSGN("%ld more files to edit", arg_count - curwin->w_arg_idx - 1);
                   3745:            quitmore = 2;           /* next try to quit is allowed */
                   3746:        }
                   3747:        return FAIL;
                   3748:    }
                   3749:    return OK;
                   3750: }
                   3751:
                   3752: /*
                   3753:  * try to abandon current file and edit a new or existing file
                   3754:  * 'fnum' is the number of the file, if zero use fname/sfname
                   3755:  *
                   3756:  * return 1 for "normal" error, 2 for "not written" error, 0 for success
                   3757:  * -1 for succesfully opening another file
                   3758:  * 'lnum' is the line number for the cursor in the new file (if non-zero).
                   3759:  */
                   3760:    int
                   3761: getfile(fnum, fname, sfname, setpm, lnum)
                   3762:    int         fnum;
                   3763:    char_u      *fname;
                   3764:    char_u      *sfname;
                   3765:    int         setpm;
                   3766:    linenr_t    lnum;
                   3767: {
                   3768:    int other;
                   3769:
                   3770:    if (fnum == 0)
                   3771:    {
                   3772:        fname_expand(&fname, &sfname);  /* make fname full path, set sfname */
                   3773:        other = otherfile(fname);
                   3774:    }
                   3775:    else
                   3776:        other = (fnum != curbuf->b_fnum);
                   3777:
                   3778:    if (other)
                   3779:        ++no_wait_return;           /* don't wait for autowrite message */
                   3780:    if (other && !forceit && curbuf->b_nwindows == 1 &&
                   3781:            !p_hid && curbuf->b_changed && autowrite(curbuf) == FAIL)
                   3782:    {
                   3783:        if (other)
                   3784:            --no_wait_return;
                   3785:        emsg(e_nowrtmsg);
                   3786:        return 2;       /* file has been changed */
                   3787:    }
                   3788:    if (other)
                   3789:        --no_wait_return;
                   3790:    if (setpm)
                   3791:        setpcmark();
                   3792:    if (!other)
                   3793:    {
                   3794:        if (lnum != 0)
                   3795:            curwin->w_cursor.lnum = lnum;
                   3796:        check_cursor();
                   3797:        beginline(MAYBE);
                   3798:
                   3799:        return 0;       /* it's in the same file */
                   3800:    }
                   3801:    if (do_ecmd(fnum, fname, sfname, NULL, p_hid, lnum, FALSE) == OK)
                   3802:        return -1;      /* opened another file */
                   3803:    return 1;           /* error encountered */
                   3804: }
                   3805:
                   3806: /*
                   3807:  * vim_strncpy()
                   3808:  *
                   3809:  * This is here because strncpy() does not guarantee successful results when
                   3810:  * the to and from strings overlap.  It is only currently called from nextwild()
                   3811:  * which copies part of the command line to another part of the command line.
                   3812:  * This produced garbage when expanding files etc in the middle of the command
                   3813:  * line (on my terminal, anyway) -- webb.
                   3814:  */
                   3815:    static void
                   3816: vim_strncpy(to, from, len)
                   3817:    char_u *to;
                   3818:    char_u *from;
                   3819:    int len;
                   3820: {
                   3821:    int i;
                   3822:
                   3823:    if (to <= from)
                   3824:    {
                   3825:        while (len-- && *from)
                   3826:            *to++ = *from++;
                   3827:        if (len >= 0)
                   3828:            *to = *from;    /* Copy NUL */
                   3829:    }
                   3830:    else
                   3831:    {
                   3832:        for (i = 0; i < len; i++)
                   3833:        {
                   3834:            to++;
                   3835:            if (*from++ == NUL)
                   3836:            {
                   3837:                i++;
                   3838:                break;
                   3839:            }
                   3840:        }
                   3841:        for (; i > 0; i--)
                   3842:            *--to = *--from;
                   3843:    }
                   3844: }
                   3845:
                   3846: /*
                   3847:  * Return FALSE if this is not an appropriate context in which to do
                   3848:  * completion of anything, & TRUE if it is (even if there are no matches).
                   3849:  * For the caller, this means that the character is just passed through like a
                   3850:  * normal character (instead of being expanded).  This allows :s/^I^D etc.
                   3851:  */
                   3852:    static int
                   3853: nextwild(type)
                   3854:    int     type;
                   3855: {
                   3856:    int     i;
                   3857:    char_u  *p1;
                   3858:    char_u  *p2;
                   3859:    int     oldlen;
                   3860:    int     difflen;
                   3861:    int     v;
                   3862:
                   3863:    if (cmd_numfiles == -1)
                   3864:        set_expand_context(cmdfirstc, cmdbuff);
                   3865:    if (expand_context == EXPAND_UNSUCCESSFUL)
                   3866:    {
                   3867:        beep_flush();
                   3868:        return OK;  /* Something illegal on command line */
                   3869:    }
                   3870:    if (expand_context == EXPAND_NOTHING)
                   3871:    {
                   3872:        /* Caller can use the character as a normal char instead */
                   3873:        return FAIL;
                   3874:    }
                   3875:    expand_interactively = TRUE;
                   3876:
                   3877:    MSG_OUTSTR("...");      /* show that we are busy */
                   3878:    flushbuf();
                   3879:
                   3880:    i = expand_pattern - cmdbuff;
                   3881:    oldlen = cmdpos - i;
                   3882:
                   3883:    if (type == WILD_NEXT || type == WILD_PREV)
                   3884:    {
                   3885:        /*
                   3886:         * Get next/previous match for a previous expanded pattern.
                   3887:         */
                   3888:        p2 = ExpandOne(NULL, NULL, 0, type);
                   3889:    }
                   3890:    else
                   3891:    {
                   3892:        /*
                   3893:         * Translate string into pattern and expand it.
                   3894:         */
                   3895:        if ((p1 = addstar(&cmdbuff[i], oldlen)) == NULL)
                   3896:            p2 = NULL;
                   3897:        else
                   3898:        {
                   3899:            p2 = ExpandOne(p1, strnsave(&cmdbuff[i], oldlen),
                   3900:                                                     WILD_HOME_REPLACE, type);
                   3901:            vim_free(p1);
                   3902:        }
                   3903:    }
                   3904:
                   3905:    if (p2 != NULL)
                   3906:    {
                   3907:        if (cmdlen + (difflen = STRLEN(p2) - oldlen) > cmdbufflen - 4)
                   3908:            v = realloc_cmdbuff(cmdlen + difflen);
                   3909:        else
                   3910:            v = OK;
                   3911:        if (v == OK)
                   3912:        {
                   3913:            vim_strncpy(&cmdbuff[cmdpos + difflen], &cmdbuff[cmdpos],
                   3914:                    cmdlen - cmdpos);
                   3915:            STRNCPY(&cmdbuff[i], p2, STRLEN(p2));
                   3916:            cmdlen += difflen;
                   3917:            cmdpos += difflen;
                   3918:        }
                   3919:        vim_free(p2);
                   3920:    }
                   3921:
                   3922:    redrawcmd();
                   3923:    if (cmd_numfiles <= 0 && p2 == NULL)
                   3924:        beep_flush();
                   3925:    else if (cmd_numfiles == 1)
                   3926:        (void)ExpandOne(NULL, NULL, 0, WILD_FREE);  /* free expanded pattern */
                   3927:
                   3928:    expand_interactively = FALSE;           /* reset for next call */
                   3929:    return OK;
                   3930: }
                   3931:
                   3932: #define MAXSUFLEN 30       /* maximum length of a file suffix */
                   3933:
                   3934: /*
                   3935:  * Do wildcard expansion on the string 'str'.
                   3936:  * Return a pointer to alloced memory containing the new string.
                   3937:  * Return NULL for failure.
                   3938:  *
                   3939:  * mode = WILD_FREE:       just free previously expanded matches
                   3940:  * mode = WILD_EXPAND_FREE:    normal expansion, do not keep matches
                   3941:  * mode = WILD_EXPAND_KEEP:    normal expansion, keep matches
                   3942:  * mode = WILD_NEXT:       use next match in multiple match, wrap to first
                   3943:  * mode = WILD_PREV:       use previous match in multiple match, wrap to first
                   3944:  * mode = WILD_ALL:            return all matches concatenated
                   3945:  * mode = WILD_LONGEST:        return longest matched part
                   3946:  *
                   3947:  * options = WILD_LIST_NOTFOUND:   list entries without a match
                   3948:  * options = WILD_HOME_REPLACE:        do home_replace() for buffer names
                   3949:  */
                   3950:    char_u *
                   3951: ExpandOne(str, orig, options, mode)
                   3952:    char_u  *str;
                   3953:    char_u  *orig;          /* original string which is expanded */
                   3954:    int     options;
                   3955:    int     mode;
                   3956: {
                   3957:    char_u      *ss = NULL;
                   3958:    static char_u **cmd_files = NULL;   /* list of input files */
                   3959:    static int  findex;
                   3960:    static char_u *orig_save = NULL;    /* kept value of orig */
                   3961:    int         i, found = 0;
                   3962:    int         multmatch = FALSE;
                   3963:    long_u      len;
                   3964:    char_u      *setsuf;
                   3965:    int         fnamelen, setsuflen;
                   3966:    char_u      suf_buf[MAXSUFLEN];
                   3967:    char_u      *p;
                   3968:
                   3969: /*
                   3970:  * first handle the case of using an old match
                   3971:  */
                   3972:    if (mode == WILD_NEXT || mode == WILD_PREV)
                   3973:    {
                   3974:        if (cmd_numfiles > 0)
                   3975:        {
                   3976:            if (mode == WILD_PREV)
                   3977:            {
                   3978:                if (findex == -1)
                   3979:                    findex = cmd_numfiles;
                   3980:                --findex;
                   3981:            }
                   3982:            else    /* mode == WILD_NEXT */
                   3983:                ++findex;
                   3984:
                   3985:            /*
                   3986:             * When wrapping around, return the original string, set findex to
                   3987:             * -1.
                   3988:             */
                   3989:            if (findex < 0)
                   3990:            {
                   3991:                if (orig_save == NULL)
                   3992:                    findex = cmd_numfiles - 1;
                   3993:                else
                   3994:                    findex = -1;
                   3995:            }
                   3996:            if (findex >= cmd_numfiles)
                   3997:            {
                   3998:                if (orig_save == NULL)
                   3999:                    findex = 0;
                   4000:                else
                   4001:                    findex = -1;
                   4002:            }
                   4003:            if (findex == -1)
                   4004:                return strsave(orig_save);
                   4005:            return strsave(cmd_files[findex]);
                   4006:        }
                   4007:        else
                   4008:            return NULL;
                   4009:    }
                   4010:
                   4011: /* free old names */
                   4012:    if (cmd_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST)
                   4013:    {
                   4014:        FreeWild(cmd_numfiles, cmd_files);
                   4015:        cmd_numfiles = -1;
                   4016:        vim_free(orig_save);
                   4017:        orig_save = NULL;
                   4018:    }
                   4019:    findex = 0;
                   4020:
                   4021:    if (mode == WILD_FREE)      /* only release file name */
                   4022:        return NULL;
                   4023:
                   4024:    if (cmd_numfiles == -1)
                   4025:    {
                   4026:        vim_free(orig_save);
                   4027:        orig_save = orig;
                   4028:        if (ExpandFromContext(str, &cmd_numfiles, &cmd_files, FALSE,
                   4029:                                                             options) == FAIL)
                   4030:            /* error: do nothing */;
                   4031:        else if (cmd_numfiles == 0)
                   4032:        {
                   4033:            if (!expand_interactively)
                   4034:                emsg(e_nomatch);
                   4035:        }
                   4036:        else
                   4037:        {
                   4038:            /*
                   4039:             * If the pattern starts with a '~', replace the home diretory
                   4040:             * with '~' again.
                   4041:             */
                   4042:            if (*str == '~' && (options & WILD_HOME_REPLACE))
                   4043:            {
                   4044:                for (i = 0; i < cmd_numfiles; ++i)
                   4045:                {
                   4046:                    p = home_replace_save(NULL, cmd_files[i]);
                   4047:                    if (p != NULL)
                   4048:                    {
                   4049:                        vim_free(cmd_files[i]);
                   4050:                        cmd_files[i] = p;
                   4051:                    }
                   4052:                }
                   4053:            }
                   4054:
                   4055:            /*
                   4056:             * Insert backslashes into a file name before a space, \, %, # and
                   4057:             * wildmatch characters, except '~'.
                   4058:             */
                   4059:            if (expand_interactively &&
                   4060:                    (expand_context == EXPAND_FILES ||
                   4061:                     expand_context == EXPAND_BUFFERS ||
                   4062:                     expand_context == EXPAND_DIRECTORIES))
                   4063:            {
                   4064:                for (i = 0; i < cmd_numfiles; ++i)
                   4065:                {
                   4066:                    p = strsave_escaped(cmd_files[i],
                   4067: #ifdef BACKSLASH_IN_FILENAME
                   4068:                                                    (char_u *)" *?[{`$%#");
                   4069: #else
                   4070:                                                    (char_u *)" *?[{`$\\%#");
                   4071: #endif
                   4072:                    if (p != NULL)
                   4073:                    {
                   4074:                        vim_free(cmd_files[i]);
                   4075:                        cmd_files[i] = p;
                   4076:                    }
                   4077:                }
                   4078:            }
                   4079:
                   4080:            if (mode != WILD_ALL && mode != WILD_LONGEST)
                   4081:            {
                   4082:                if (cmd_numfiles > 1)   /* more than one match; check suffix */
                   4083:                {
                   4084:                    found = -2;
                   4085:                    for (i = 0; i < cmd_numfiles; ++i)
                   4086:                    {
                   4087:                        fnamelen = STRLEN(cmd_files[i]);
                   4088:                        setsuflen = 0;
                   4089:                        for (setsuf = p_su; *setsuf; )
                   4090:                        {
                   4091:                            setsuflen = copy_option_part(&setsuf, suf_buf,
                   4092:                                                              MAXSUFLEN, ".,");
                   4093:                            if (fnamelen >= setsuflen && STRNCMP(suf_buf,
                   4094:                                          cmd_files[i] + fnamelen - setsuflen,
                   4095:                                                      (size_t)setsuflen) == 0)
                   4096:                                break;
                   4097:                            setsuflen = 0;
                   4098:                        }
                   4099:                        if (setsuflen)      /* suffix matched: ignore file */
                   4100:                            continue;
                   4101:                        if (found >= 0)
                   4102:                        {
                   4103:                            multmatch = TRUE;
                   4104:                            break;
                   4105:                        }
                   4106:                        found = i;
                   4107:                    }
                   4108:                }
                   4109:                if (multmatch || found < 0)
                   4110:                {
                   4111:                    /* Can we ever get here unless it's while expanding
                   4112:                     * interactively?  If not, we can get rid of this all
                   4113:                     * together. Don't really want to wait for this message
                   4114:                     * (and possibly have to hit return to continue!).
                   4115:                     */
                   4116:                    if (!expand_interactively)
                   4117:                        emsg(e_toomany);
                   4118:                    else
                   4119:                        beep_flush();
                   4120:                    found = 0;              /* return first one */
                   4121:                    multmatch = TRUE;       /* for found < 0 */
                   4122:                }
                   4123:                if (found >= 0 && !(multmatch && mode == WILD_EXPAND_FREE))
                   4124:                    ss = strsave(cmd_files[found]);
                   4125:            }
                   4126:        }
                   4127:    }
                   4128:
                   4129:    /* Find longest common part */
                   4130:    if (mode == WILD_LONGEST && cmd_numfiles > 0)
                   4131:    {
                   4132:        for (len = 0; cmd_files[0][len]; ++len)
                   4133:        {
                   4134:            for (i = 0; i < cmd_numfiles; ++i)
                   4135:            {
                   4136: #ifdef CASE_INSENSITIVE_FILENAME
                   4137:                if ((expand_context == EXPAND_DIRECTORIES ||
                   4138:                                             expand_context == EXPAND_FILES ||
                   4139:                                          expand_context == EXPAND_BUFFERS) &&
                   4140:                     toupper(cmd_files[i][len]) != toupper(cmd_files[0][len]))
                   4141:                    break;
                   4142:                else
                   4143: #endif
                   4144:                if (cmd_files[i][len] != cmd_files[0][len])
                   4145:                    break;
                   4146:            }
                   4147:            if (i < cmd_numfiles)
                   4148:            {
                   4149:                vim_beep();
                   4150:                break;
                   4151:            }
                   4152:        }
                   4153:        ss = alloc((unsigned)len + 1);
                   4154:        if (ss)
                   4155:        {
                   4156:            STRNCPY(ss, cmd_files[0], len);
                   4157:            ss[len] = NUL;
                   4158:        }
                   4159:        findex = -1;                        /* next p_wc gets first one */
                   4160:    }
                   4161:
                   4162:    /* Concatenate all matching names */
                   4163:    if (mode == WILD_ALL && cmd_numfiles > 0)
                   4164:    {
                   4165:        len = 0;
                   4166:        for (i = 0; i < cmd_numfiles; ++i)
                   4167:            len += STRLEN(cmd_files[i]) + 1;
                   4168:        ss = lalloc(len, TRUE);
                   4169:        if (ss)
                   4170:        {
                   4171:            *ss = NUL;
                   4172:            for (i = 0; i < cmd_numfiles; ++i)
                   4173:            {
                   4174:                STRCAT(ss, cmd_files[i]);
                   4175:                if (i != cmd_numfiles - 1)
                   4176:                    STRCAT(ss, " ");
                   4177:            }
                   4178:        }
                   4179:    }
                   4180:
                   4181:    if (mode == WILD_EXPAND_FREE || mode == WILD_ALL)
                   4182:    {
                   4183:        FreeWild(cmd_numfiles, cmd_files);
                   4184:        cmd_numfiles = -1;
                   4185:    }
                   4186:    return ss;
                   4187: }
                   4188:
                   4189: /*
                   4190:  * show all matches for completion on the command line
                   4191:  */
                   4192:    static int
                   4193: showmatches(buff)
                   4194:    char_u *buff;
                   4195: {
                   4196:    char_u      *file_str;
                   4197:    int         num_files;
                   4198:    char_u      **files_found;
                   4199:    int         i, j, k;
                   4200:    int         maxlen;
                   4201:    int         lines;
                   4202:    int         columns;
                   4203:    char_u      *p;
                   4204:    int         lastlen;
                   4205:
                   4206:    set_expand_context(cmdfirstc, cmdbuff);
                   4207:    if (expand_context == EXPAND_UNSUCCESSFUL)
                   4208:    {
                   4209:        beep_flush();
                   4210:        return OK;  /* Something illegal on command line */
                   4211:    }
                   4212:    if (expand_context == EXPAND_NOTHING)
                   4213:    {
                   4214:        /* Caller can use the character as a normal char instead */
                   4215:        return FAIL;
                   4216:    }
                   4217:    expand_interactively = TRUE;
                   4218:
                   4219:    /* add star to file name, or convert to regexp if not expanding files! */
                   4220:    file_str = addstar(expand_pattern, (int)(buff + cmdpos - expand_pattern));
                   4221:    if (file_str == NULL)
                   4222:    {
                   4223:        expand_interactively = FALSE;
                   4224:        return OK;
                   4225:    }
                   4226:
                   4227:    msg_didany = FALSE;                 /* lines_left will be set */
                   4228:    msg_start();                        /* prepare for paging */
                   4229:    msg_outchar('\n');
                   4230:    flushbuf();
                   4231:    cmdline_row = msg_row;
                   4232:    msg_didany = FALSE;                 /* lines_left will be set again */
                   4233:    msg_start();                        /* prepare for paging */
                   4234:
                   4235:    /* find all files that match the description */
                   4236:    if (ExpandFromContext(file_str, &num_files, &files_found, FALSE, 0) == FAIL)
                   4237:    {
                   4238:        num_files = 0;
                   4239:        files_found = (char_u **)"";
                   4240:    }
                   4241:
                   4242:    /* find the length of the longest file name */
                   4243:    maxlen = 0;
                   4244:    for (i = 0; i < num_files; ++i)
                   4245:    {
                   4246:        if (expand_context == EXPAND_FILES || expand_context == EXPAND_BUFFERS)
                   4247:        {
                   4248:            home_replace(NULL, files_found[i], NameBuff, MAXPATHL);
                   4249:            j = strsize(NameBuff);
                   4250:        }
                   4251:        else
                   4252:            j = strsize(files_found[i]);
                   4253:        if (j > maxlen)
                   4254:            maxlen = j;
                   4255:    }
                   4256:
                   4257:    /* compute the number of columns and lines for the listing */
                   4258:    maxlen += 2;    /* two spaces between file names */
                   4259:    columns = ((int)Columns + 2) / maxlen;
                   4260:    if (columns < 1)
                   4261:        columns = 1;
                   4262:    lines = (num_files + columns - 1) / columns;
                   4263:
                   4264:    (void)set_highlight('d');   /* find out highlight mode for directories */
                   4265:
                   4266:    /* list the files line by line */
                   4267:    for (i = 0; i < lines; ++i)
                   4268:    {
                   4269:        lastlen = 999;
                   4270:        for (k = i; k < num_files; k += lines)
                   4271:        {
                   4272:            for (j = maxlen - lastlen; --j >= 0; )
                   4273:                msg_outchar(' ');
                   4274:            if (expand_context == EXPAND_FILES ||
                   4275:                                             expand_context == EXPAND_BUFFERS)
                   4276:            {
                   4277:                        /* highlight directories */
                   4278:                j = (mch_isdir(files_found[k]));
                   4279:                home_replace(NULL, files_found[k], NameBuff, MAXPATHL);
                   4280:                p = NameBuff;
                   4281:            }
                   4282:            else
                   4283:            {
                   4284:                j = FALSE;
                   4285:                p = files_found[k];
                   4286:            }
                   4287:            if (j)
                   4288:                start_highlight();
                   4289:            lastlen = msg_outtrans(p);
                   4290:            if (j)
                   4291:                stop_highlight();
                   4292:        }
                   4293:        msg_outchar('\n');
                   4294:        flushbuf();                 /* show one line at a time */
                   4295:        if (got_int)
                   4296:        {
                   4297:            got_int = FALSE;
                   4298:            break;
                   4299:        }
                   4300:    }
                   4301:    vim_free(file_str);
                   4302:    FreeWild(num_files, files_found);
                   4303:
                   4304: /*
                   4305:  * we redraw the command below the lines that we have just listed
                   4306:  * This is a bit tricky, but it saves a lot of screen updating.
                   4307:  */
                   4308:    cmdline_row = msg_row;      /* will put it back later */
                   4309:
                   4310:    expand_interactively = FALSE;
                   4311:    return OK;
                   4312: }
                   4313:
                   4314: /*
                   4315:  * Prepare a string for expansion.
                   4316:  * When expanding file names:  The string will be used with ExpandWildCards().
                   4317:  * Copy the file name into allocated memory and add a '*' at the end.
                   4318:  * When expanding other names:  The string will be used with regcomp().  Copy
                   4319:  * the name into allocated memory and add ".*" at the end.
                   4320:  */
                   4321:    char_u *
                   4322: addstar(fname, len)
                   4323:    char_u  *fname;
                   4324:    int     len;
                   4325: {
                   4326:    char_u  *retval;
                   4327:    int     i, j;
                   4328:    int     new_len;
                   4329:    char_u  *tail;
                   4330:
                   4331:    if (expand_interactively && expand_context != EXPAND_FILES &&
                   4332:                                         expand_context != EXPAND_DIRECTORIES)
                   4333:    {
                   4334:        /*
                   4335:         * Matching will be done internally (on something other than files).
                   4336:         * So we convert the file-matching-type wildcards into our kind for
                   4337:         * use with vim_regcomp().  First work out how long it will be:
                   4338:         */
                   4339:
                   4340:        /* for help tags the translation is done in find_help_tags() */
                   4341:        if (expand_context == EXPAND_HELP)
                   4342:            retval = strnsave(fname, len);
                   4343:        else
                   4344:        {
                   4345:            new_len = len + 2;          /* +2 for '^' at start, NUL at end */
                   4346:            for (i = 0; i < len; i++)
                   4347:            {
                   4348:                if (fname[i] == '*' || fname[i] == '~')
                   4349:                    new_len++;          /* '*' needs to be replaced by ".*"
                   4350:                                           '~' needs to be replaced by "\~" */
                   4351:
                   4352:                /* Buffer names are like file names.  "." should be literal */
                   4353:                if (expand_context == EXPAND_BUFFERS && fname[i] == '.')
                   4354:                    new_len++;          /* "." becomes "\." */
                   4355:            }
                   4356:            retval = alloc(new_len);
                   4357:            if (retval != NULL)
                   4358:            {
                   4359:                retval[0] = '^';
                   4360:                j = 1;
                   4361:                for (i = 0; i < len; i++, j++)
                   4362:                {
                   4363:                    if (fname[i] == '\\' && ++i == len) /* skip backslash */
                   4364:                        break;
                   4365:
                   4366:                    switch (fname[i])
                   4367:                    {
                   4368:                        case '*':   retval[j++] = '.';
                   4369:                                    break;
                   4370:                        case '~':   retval[j++] = '\\';
                   4371:                                    break;
                   4372:                        case '?':   retval[j] = '.';
                   4373:                                    continue;
                   4374:                        case '.':   if (expand_context == EXPAND_BUFFERS)
                   4375:                                        retval[j++] = '\\';
                   4376:                                    break;
                   4377:                    }
                   4378:                    retval[j] = fname[i];
                   4379:                }
                   4380:                retval[j] = NUL;
                   4381:            }
                   4382:        }
                   4383:    }
                   4384:    else
                   4385:    {
                   4386:        retval = alloc(len + 4);
                   4387:        if (retval != NULL)
                   4388:        {
                   4389:            STRNCPY(retval, fname, len);
                   4390:            retval[len] = NUL;
                   4391:            backslash_halve(retval, TRUE);      /* remove some backslashes */
                   4392:            len = STRLEN(retval);
                   4393:
                   4394:            /*
                   4395:             * Don't add a star to ~, ~user, $var or `cmd`.
                   4396:             * ~ would be at the start of the tail.
                   4397:             * $ could be anywhere in the tail.
                   4398:             * ` could be anywhere in the file name.
                   4399:             */
                   4400:            tail = gettail(retval);
                   4401:            if (*tail != '~' && vim_strchr(tail, '$') == NULL
                   4402:                                           && vim_strchr(retval, '`') == NULL)
                   4403:            {
                   4404: #ifdef MSDOS
                   4405:                /*
                   4406:                 * if there is no dot in the file name, add "*.*" instead of
                   4407:                 * "*".
                   4408:                 */
                   4409:                for (i = len - 1; i >= 0; --i)
                   4410:                    if (vim_strchr((char_u *)".\\/:", retval[i]) != NULL)
                   4411:                        break;
                   4412:                if (i < 0 || retval[i] != '.')
                   4413:                {
                   4414:                    retval[len++] = '*';
                   4415:                    retval[len++] = '.';
                   4416:                }
                   4417: #endif
                   4418:                retval[len++] = '*';
                   4419:            }
                   4420:            retval[len] = NUL;
                   4421:        }
                   4422:    }
                   4423:    return retval;
                   4424: }
                   4425:
                   4426: /*
                   4427:  * do_source: read the file "fname" and execute its lines as EX commands
                   4428:  *
                   4429:  * This function may be called recursively!
                   4430:  *
                   4431:  * return FAIL if file could not be opened, OK otherwise
                   4432:  */
                   4433:    int
                   4434: do_source(fname, check_other)
                   4435:    register char_u *fname;
                   4436:    int             check_other;        /* check for .vimrc and _vimrc */
                   4437: {
                   4438:    register FILE   *fp;
                   4439:    register int    len;
                   4440: #ifdef USE_CRNL
                   4441:    int             has_cr;
                   4442:    int             textmode = -1;  /* -1 = unknown, 0 = NL, 1 = CR-NL */
                   4443:    int             error = FALSE;
                   4444: #endif
                   4445:                                    /* use NameBuff for expanded name */
                   4446:    expand_env(fname, NameBuff, MAXPATHL);
                   4447:    fp = fopen((char *)NameBuff, READBIN);
                   4448:    if (fp == NULL && check_other)
                   4449:    {
                   4450:        /*
                   4451:         * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa
                   4452:         * (if applicable)
                   4453:         */
                   4454:        len = STRLEN(NameBuff);
                   4455:        if (((len > 6 && ispathsep(NameBuff[len - 7])) || len == 6) &&
                   4456:                     (NameBuff[len - 6] == '.' || NameBuff[len - 6] == '_') &&
                   4457:                                  (STRCMP(&NameBuff[len - 5], "vimrc") == 0))
                   4458:        {
                   4459:            if (NameBuff[len - 6] == '_')
                   4460:                NameBuff[len - 6] = '.';
                   4461:            else
                   4462:                NameBuff[len - 6] = '_';
                   4463:            fp = fopen((char *)NameBuff, READBIN);
                   4464:        }
                   4465:    }
                   4466:
                   4467:    if (fp == NULL)
                   4468:        return FAIL;
                   4469:
                   4470: #ifdef USE_CRNL
                   4471:        /* no automatic textmode: Set default to CR-NL */
                   4472:    if (!p_ta)
                   4473:        textmode = 1;
                   4474: #endif
                   4475:    sourcing_name = fname;
                   4476:    sourcing_lnum = 1;
                   4477: #ifdef SLEEP_IN_EMSG
                   4478:    ++dont_sleep;           /* don't call sleep() in emsg() */
                   4479: #endif
                   4480:    len = 0;
                   4481:    while (fgets((char *)IObuff + len, IOSIZE - len, fp) != NULL && !got_int)
                   4482:    {
                   4483:        len = STRLEN(IObuff) - 1;
                   4484:        if (len >= 0 && IObuff[len] == '\n')    /* remove trailing newline */
                   4485:        {
                   4486: #ifdef USE_CRNL
                   4487:            has_cr = (len > 0 && IObuff[len - 1] == '\r');
                   4488:            if (textmode == -1)
                   4489:            {
                   4490:                if (has_cr)
                   4491:                    textmode = 1;
                   4492:                else
                   4493:                    textmode = 0;
                   4494:            }
                   4495:
                   4496:            if (textmode)
                   4497:            {
                   4498:                if (has_cr)         /* remove trailing CR-LF */
                   4499:                    --len;
                   4500:                else        /* lines like ":map xx yy^M" will have failed */
                   4501:                {
                   4502:                    if (!error)
                   4503:                        EMSG("Warning: Wrong line separator, ^M may be missing");
                   4504:                    error = TRUE;
                   4505:                    textmode = 0;
                   4506:                }
                   4507:            }
                   4508: #endif
                   4509:                /* escaped newline, read more */
                   4510:            if (len > 0 && len < IOSIZE && IObuff[len - 1] == Ctrl('V'))
                   4511:            {
                   4512:                IObuff[len - 1] = '\n';     /* remove CTRL-V */
                   4513:                ++sourcing_lnum;
                   4514:                continue;
                   4515:            }
                   4516:            IObuff[len] = NUL;
                   4517:        }
                   4518:            /* check for ^C here, so recursive :so will be broken */
                   4519:        mch_breakcheck();
                   4520:        do_cmdline(IObuff, TRUE, TRUE);
                   4521:        len = 0;
                   4522:        ++sourcing_lnum;
                   4523:    }
                   4524:    fclose(fp);
                   4525:    if (got_int)
                   4526:        emsg(e_interr);
                   4527: #ifdef SLEEP_IN_EMSG
                   4528:    --dont_sleep;
                   4529: #endif
                   4530:    sourcing_name = NULL;
                   4531:    sourcing_lnum = 0;
                   4532:    return OK;
                   4533: }
                   4534:
                   4535: /*
                   4536:  * get a single EX address
                   4537:  *
                   4538:  * Set ptr to the next character after the part that was interpreted.
                   4539:  * Set ptr to NULL when an error is encountered.
                   4540:  */
                   4541:    static linenr_t
                   4542: get_address(ptr)
                   4543:    char_u      **ptr;
                   4544: {
                   4545:    linenr_t    cursor_lnum = curwin->w_cursor.lnum;
                   4546:    int         c;
                   4547:    int         i;
                   4548:    long        n;
                   4549:    char_u      *cmd;
                   4550:    FPOS        pos;
                   4551:    FPOS        *fp;
                   4552:    linenr_t    lnum;
                   4553:
                   4554:    cmd = skipwhite(*ptr);
                   4555:    lnum = MAXLNUM;
                   4556:    do
                   4557:    {
                   4558:        switch (*cmd)
                   4559:        {
                   4560:            case '.':                       /* '.' - Cursor position */
                   4561:                        ++cmd;
                   4562:                        lnum = cursor_lnum;
                   4563:                        break;
                   4564:
                   4565:            case '$':                       /* '$' - last line */
                   4566:                        ++cmd;
                   4567:                        lnum = curbuf->b_ml.ml_line_count;
                   4568:                        break;
                   4569:
                   4570:            case '\'':                      /* ''' - mark */
                   4571:                        if (*++cmd == NUL || (check_mark(
                   4572:                                        fp = getmark(*cmd++, FALSE)) == FAIL))
                   4573:                            goto error;
                   4574:                        lnum = fp->lnum;
                   4575:                        break;
                   4576:
                   4577:            case '/':
                   4578:            case '?':                       /* '/' or '?' - search */
                   4579:                        c = *cmd++;
                   4580:                        pos = curwin->w_cursor;     /* save curwin->w_cursor */
                   4581:                        if (c == '/')   /* forward search, start on next line */
                   4582:                        {
                   4583:                            ++curwin->w_cursor.lnum;
                   4584:                            curwin->w_cursor.col = 0;
                   4585:                        }
                   4586:                        else           /* backward search, start on prev line */
                   4587:                        {
                   4588:                            --curwin->w_cursor.lnum;
                   4589:                            curwin->w_cursor.col = MAXCOL;
                   4590:                        }
                   4591:                        searchcmdlen = 0;
                   4592:                        if (!do_search(c, cmd, 1L,
                   4593:                                      SEARCH_HIS + SEARCH_MSG + SEARCH_START))
                   4594:                        {
                   4595:                            cmd = NULL;
                   4596:                            curwin->w_cursor = pos;
                   4597:                            goto error;
                   4598:                        }
                   4599:                        lnum = curwin->w_cursor.lnum;
                   4600:                        curwin->w_cursor = pos;
                   4601:                                            /* adjust command string pointer */
                   4602:                        cmd += searchcmdlen;
                   4603:                        break;
                   4604:
                   4605:            case '\\':              /* "\?", "\/" or "\&", repeat search */
                   4606:                        ++cmd;
                   4607:                        if (*cmd == '&')
                   4608:                            i = RE_SUBST;
                   4609:                        else if (*cmd == '?' || *cmd == '/')
                   4610:                            i = RE_SEARCH;
                   4611:                        else
                   4612:                        {
                   4613:                            emsg(e_backslash);
                   4614:                            cmd = NULL;
                   4615:                            goto error;
                   4616:                        }
                   4617:
                   4618:                                    /* forward search, start on next line */
                   4619:                        if (*cmd != '?')
                   4620:                        {
                   4621:                            pos.lnum = curwin->w_cursor.lnum + 1;
                   4622:                            pos.col = 0;
                   4623:                        }
                   4624:                                    /* backward search, start on prev line */
                   4625:                        else
                   4626:                        {
                   4627:                            pos.lnum = curwin->w_cursor.lnum - 1;
                   4628:                            pos.col = MAXCOL;
                   4629:                        }
                   4630:                        if (searchit(&pos, *cmd == '?' ? BACKWARD : FORWARD,
                   4631:                                                             (char_u *)"", 1L,
                   4632:                                          SEARCH_MSG + SEARCH_START, i) == OK)
                   4633:                            lnum = pos.lnum;
                   4634:                        else
                   4635:                        {
                   4636:                            cmd = NULL;
                   4637:                            goto error;
                   4638:                        }
                   4639:                        ++cmd;
                   4640:                        break;
                   4641:
                   4642:            default:
                   4643:                        if (isdigit(*cmd))      /* absolute line number */
                   4644:                            lnum = getdigits(&cmd);
                   4645:        }
                   4646:
                   4647:        for (;;)
                   4648:        {
                   4649:            cmd = skipwhite(cmd);
                   4650:            if (*cmd != '-' && *cmd != '+' && !isdigit(*cmd))
                   4651:                break;
                   4652:
                   4653:            if (lnum == MAXLNUM)
                   4654:                lnum = cursor_lnum;     /* "+1" is same as ".+1" */
                   4655:            if (isdigit(*cmd))
                   4656:                i = '+';                /* "number" is same as "+number" */
                   4657:            else
                   4658:                i = *cmd++;
                   4659:            if (!isdigit(*cmd))         /* '+' is '+1', but '+0' is not '+1' */
                   4660:                n = 1;
                   4661:            else
                   4662:                n = getdigits(&cmd);
                   4663:            if (i == '-')
                   4664:                lnum -= n;
                   4665:            else
                   4666:                lnum += n;
                   4667:        }
                   4668:        cursor_lnum = lnum;
                   4669:    } while (*cmd == '/' || *cmd == '?');
                   4670:
                   4671: error:
                   4672:    *ptr = cmd;
                   4673:    return lnum;
                   4674: }
                   4675:
                   4676:
                   4677: /*
                   4678:  * Must parse the command line so far to work out what context we are in.
                   4679:  * Completion can then be done based on that context.
                   4680:  * This routine sets two global variables:
                   4681:  * char_u *expand_pattern  The start of the pattern to be expanded within
                   4682:  *                             the command line (ends at the cursor).
                   4683:  * int expand_context      The type of thing to expand.  Will be one of:
                   4684:  *
                   4685:  * EXPAND_UNSUCCESSFUL     Used sometimes when there is something illegal on
                   4686:  *                         the command line, like an unknown command.  Caller
                   4687:  *                         should beep.
                   4688:  * EXPAND_NOTHING          Unrecognised context for completion, use char like
                   4689:  *                         a normal char, rather than for completion.  eg
                   4690:  *                         :s/^I/
                   4691:  * EXPAND_COMMANDS         Cursor is still touching the command, so complete
                   4692:  *                         it.
                   4693:  * EXPAND_BUFFERS          Complete file names for :buf and :sbuf commands.
                   4694:  * EXPAND_FILES            After command with XFILE set, or after setting
                   4695:  *                         with P_EXPAND set.  eg :e ^I, :w>>^I
                   4696:  * EXPAND_DIRECTORIES      In some cases this is used instead of the latter
                   4697:  *                         when we know only directories are of interest.  eg
                   4698:  *                         :set dir=^I
                   4699:  * EXPAND_SETTINGS         Complete variable names.  eg :set d^I
                   4700:  * EXPAND_BOOL_SETTINGS    Complete boolean variables only,  eg :set no^I
                   4701:  * EXPAND_TAGS             Complete tags from the files in p_tags.  eg :ta a^I
                   4702:  * EXPAND_HELP             Complete tags from the file 'helpfile'/vim_tags
                   4703:  * EXPAND_EVENTS           Complete event names
                   4704:  *
                   4705:  * -- webb.
                   4706:  */
                   4707:    static void
                   4708: set_expand_context(firstc, buff)
                   4709:    int         firstc;     /* either ':', '/', or '?' */
                   4710:    char_u      *buff;      /* buffer for command string */
                   4711: {
                   4712:    char_u      *nextcomm;
                   4713:    char_u      old_char;
                   4714:
                   4715:    old_char = cmdbuff[cmdpos];
                   4716:    cmdbuff[cmdpos] = NUL;
                   4717:    nextcomm = buff;
                   4718:    while (nextcomm != NULL)
                   4719:        nextcomm = set_one_cmd_context(firstc, nextcomm);
                   4720:    cmdbuff[cmdpos] = old_char;
                   4721: }
                   4722:
                   4723: /*
                   4724:  * This is all pretty much copied from do_one_cmd(), with all the extra stuff
                   4725:  * we don't need/want deleted.  Maybe this could be done better if we didn't
                   4726:  * repeat all this stuff.  The only problem is that they may not stay perfectly
                   4727:  * compatible with each other, but then the command line syntax probably won't
                   4728:  * change that much -- webb.
                   4729:  */
                   4730:    static char_u *
                   4731: set_one_cmd_context(firstc, buff)
                   4732:    int         firstc;     /* either ':', '/', or '?' */
                   4733:    char_u      *buff;      /* buffer for command string */
                   4734: {
                   4735:    char_u              *p;
                   4736:    char_u              *cmd, *arg;
                   4737:    int                 i;
                   4738:    int                 cmdidx;
                   4739:    long                argt;
                   4740:    char_u              delim;
                   4741:    int                 forced = FALSE;
                   4742:    int                 usefilter = FALSE;  /* filter instead of file name */
                   4743:
                   4744:    expand_pattern = buff;
                   4745:    if (firstc != ':')
                   4746:    {
                   4747:        expand_context = EXPAND_NOTHING;
                   4748:        return NULL;
                   4749:    }
                   4750:    expand_context = EXPAND_COMMANDS;   /* Default until we get past command */
                   4751:
                   4752: /*
                   4753:  * 2. skip comment lines and leading space, colons or bars
                   4754:  */
                   4755:    for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
                   4756:        ;
                   4757:    expand_pattern = cmd;
                   4758:
                   4759:    if (*cmd == NUL)
                   4760:        return NULL;
                   4761:    if (*cmd == '"')        /* ignore comment lines */
                   4762:    {
                   4763:        expand_context = EXPAND_NOTHING;
                   4764:        return NULL;
                   4765:    }
                   4766:
                   4767: /*
                   4768:  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
                   4769:  */
                   4770:    /*
                   4771:     * Backslashed delimiters after / or ? will be skipped, and commands will
                   4772:     * not be expanded between /'s and ?'s or after "'". -- webb
                   4773:     */
                   4774:    while (*cmd != NUL && (vim_isspace(*cmd) || isdigit(*cmd) ||
                   4775:                            vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL))
                   4776:    {
                   4777:        if (*cmd == '\'')
                   4778:        {
                   4779:            if (*++cmd == NUL)
                   4780:                expand_context = EXPAND_NOTHING;
                   4781:        }
                   4782:        else if (*cmd == '/' || *cmd == '?')
                   4783:        {
                   4784:            delim = *cmd++;
                   4785:            while (*cmd != NUL && *cmd != delim)
                   4786:                if (*cmd++ == '\\' && *cmd != NUL)
                   4787:                    ++cmd;
                   4788:            if (*cmd == NUL)
                   4789:                expand_context = EXPAND_NOTHING;
                   4790:        }
                   4791:        if (*cmd != NUL)
                   4792:            ++cmd;
                   4793:    }
                   4794:
                   4795: /*
                   4796:  * 4. parse command
                   4797:  */
                   4798:
                   4799:    cmd = skipwhite(cmd);
                   4800:    expand_pattern = cmd;
                   4801:    if (*cmd == NUL)
                   4802:        return NULL;
                   4803:    if (*cmd == '"')
                   4804:    {
                   4805:        expand_context = EXPAND_NOTHING;
                   4806:        return NULL;
                   4807:    }
                   4808:
                   4809:    if (*cmd == '|' || *cmd == '\n')
                   4810:        return cmd + 1;                 /* There's another command */
                   4811:
                   4812:    /*
                   4813:     * Isolate the command and search for it in the command table.
                   4814:     * Exeptions:
                   4815:     * - the 'k' command can directly be followed by any character.
                   4816:     * - the 's' command can be followed directly by 'c', 'g' or 'r'
                   4817:     */
                   4818:    if (*cmd == 'k')
                   4819:    {
                   4820:        cmdidx = CMD_k;
                   4821:        p = cmd + 1;
                   4822:    }
                   4823:    else
                   4824:    {
                   4825:        p = cmd;
                   4826:        while (isalpha(*p) || *p == '*')    /* Allow * wild card */
                   4827:            ++p;
                   4828:            /* check for non-alpha command */
                   4829:        if (p == cmd && vim_strchr((char_u *)"@!=><&~#", *p) != NULL)
                   4830:            ++p;
                   4831:        i = (int)(p - cmd);
                   4832:
                   4833:        if (i == 0)
                   4834:        {
                   4835:            expand_context = EXPAND_UNSUCCESSFUL;
                   4836:            return NULL;
                   4837:        }
                   4838:        for (cmdidx = 0; cmdidx < CMD_SIZE; ++cmdidx)
                   4839:            if (STRNCMP(cmdnames[cmdidx].cmd_name, cmd, (size_t)i) == 0)
                   4840:                break;
                   4841:    }
                   4842:
                   4843:    /*
                   4844:     * If the cursor is touching the command, and it ends in an alphabetic
                   4845:     * character, complete the command name.
                   4846:     */
                   4847:    if (p == cmdbuff + cmdpos && isalpha(p[-1]))
                   4848:        return NULL;
                   4849:
                   4850:    if (cmdidx == CMD_SIZE)
                   4851:    {
                   4852:        if (*cmd == 's' && vim_strchr((char_u *)"cgr", cmd[1]) != NULL)
                   4853:        {
                   4854:            cmdidx = CMD_substitute;
                   4855:            p = cmd + 1;
                   4856:        }
                   4857:        else
                   4858:        {
                   4859:            /* Not still touching the command and it was an illegal command */
                   4860:            expand_context = EXPAND_UNSUCCESSFUL;
                   4861:            return NULL;
                   4862:        }
                   4863:    }
                   4864:
                   4865:    expand_context = EXPAND_NOTHING; /* Default now that we're past command */
                   4866:
                   4867:    if (*p == '!')                  /* forced commands */
                   4868:    {
                   4869:        forced = TRUE;
                   4870:        ++p;
                   4871:    }
                   4872:
                   4873: /*
                   4874:  * 5. parse arguments
                   4875:  */
                   4876:    argt = cmdnames[cmdidx].cmd_argt;
                   4877:
                   4878:    arg = skipwhite(p);
                   4879:
                   4880:    if (cmdidx == CMD_write)
                   4881:    {
                   4882:        if (*arg == '>')                        /* append */
                   4883:        {
                   4884:            if (*++arg == '>')              /* It should be */
                   4885:                ++arg;
                   4886:            arg = skipwhite(arg);
                   4887:        }
                   4888:        else if (*arg == '!')                   /* :w !filter */
                   4889:        {
                   4890:            ++arg;
                   4891:            usefilter = TRUE;
                   4892:        }
                   4893:    }
                   4894:
                   4895:    if (cmdidx == CMD_read)
                   4896:    {
                   4897:        usefilter = forced;                 /* :r! filter if forced */
                   4898:        if (*arg == '!')                        /* :r !filter */
                   4899:        {
                   4900:            ++arg;
                   4901:            usefilter = TRUE;
                   4902:        }
                   4903:    }
                   4904:
                   4905:    if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
                   4906:    {
                   4907:        while (*arg == *cmd)        /* allow any number of '>' or '<' */
                   4908:            ++arg;
                   4909:        arg = skipwhite(arg);
                   4910:    }
                   4911:
                   4912:    /* Does command allow "+command"? */
                   4913:    if ((argt & EDITCMD) && !usefilter && *arg == '+')
                   4914:    {
                   4915:        /* Check if we're in the +command */
                   4916:        p = arg + 1;
                   4917:        arg = skiptowhite(arg);
                   4918:
                   4919:        /* Still touching the command after '+'? */
                   4920:        if (arg >= cmdbuff + cmdpos)
                   4921:            return p;
                   4922:
                   4923:        /* Skip space after +command to get to the real argument */
                   4924:        arg = skipwhite(arg);
                   4925:    }
                   4926:
                   4927:    /*
                   4928:     * Check for '|' to separate commands and '"' to start comments.
                   4929:     * Don't do this for ":read !cmd" and ":write !cmd".
                   4930:     */
                   4931:    if ((argt & TRLBAR) && !usefilter)
                   4932:    {
                   4933:        p = arg;
                   4934:        while (*p)
                   4935:        {
                   4936:            if (*p == Ctrl('V'))
                   4937:            {
                   4938:                if (p[1] != NUL)
                   4939:                    ++p;
                   4940:            }
                   4941:            else if ((*p == '"' && !(argt & NOTRLCOM)) || *p == '|' || *p == '\n')
                   4942:            {
                   4943:                if (*(p - 1) != '\\')
                   4944:                {
                   4945:                    if (*p == '|' || *p == '\n')
                   4946:                        return p + 1;
                   4947:                    return NULL;    /* It's a comment */
                   4948:                }
                   4949:            }
                   4950:            ++p;
                   4951:        }
                   4952:    }
                   4953:
                   4954:                                                /* no arguments allowed */
                   4955:    if (!(argt & EXTRA) && *arg != NUL &&
                   4956:                                    vim_strchr((char_u *)"|\"", *arg) == NULL)
                   4957:        return NULL;
                   4958:
                   4959:    /* Find start of last argument (argument just before cursor): */
                   4960:    p = cmdbuff + cmdpos;
                   4961:    while (p != arg && *p != ' ' && *p != TAB)
                   4962:        p--;
                   4963:    if (*p == ' ' || *p == TAB)
                   4964:        p++;
                   4965:    expand_pattern = p;
                   4966:
                   4967:    if (argt & XFILE)
                   4968:    {
                   4969:        int in_quote = FALSE;
                   4970:        char_u *bow = NULL;     /* Beginning of word */
                   4971:
                   4972:        /*
                   4973:         * Allow spaces within back-quotes to count as part of the argument
                   4974:         * being expanded.
                   4975:         */
                   4976:        expand_pattern = skipwhite(arg);
                   4977:        for (p = expand_pattern; *p; ++p)
                   4978:        {
                   4979:            if (*p == '\\' && p[1])
                   4980:                ++p;
                   4981: #ifdef SPACE_IN_FILENAME
                   4982:            else if (vim_iswhite(*p) && (!(argt & NOSPC) || usefilter))
                   4983: #else
                   4984:            else if (vim_iswhite(*p))
                   4985: #endif
                   4986:            {
                   4987:                p = skipwhite(p);
                   4988:                if (in_quote)
                   4989:                    bow = p;
                   4990:                else
                   4991:                    expand_pattern = p;
                   4992:                --p;
                   4993:            }
                   4994:            else if (*p == '`')
                   4995:            {
                   4996:                if (!in_quote)
                   4997:                {
                   4998:                    expand_pattern = p;
                   4999:                    bow = p + 1;
                   5000:                }
                   5001:                in_quote = !in_quote;
                   5002:            }
                   5003:        }
                   5004:
                   5005:        /*
                   5006:         * If we are still inside the quotes, and we passed a space, just
                   5007:         * expand from there.
                   5008:         */
                   5009:        if (bow != NULL && in_quote)
                   5010:            expand_pattern = bow;
                   5011:        expand_context = EXPAND_FILES;
                   5012:    }
                   5013:
                   5014: /*
                   5015:  * 6. switch on command name
                   5016:  */
                   5017:    switch (cmdidx)
                   5018:    {
                   5019:        case CMD_cd:
                   5020:        case CMD_chdir:
                   5021:            expand_context = EXPAND_DIRECTORIES;
                   5022:            break;
                   5023:        case CMD_global:
                   5024:        case CMD_vglobal:
                   5025:            delim = *arg;           /* get the delimiter */
                   5026:            if (delim)
                   5027:                ++arg;              /* skip delimiter if there is one */
                   5028:
                   5029:            while (arg[0] != NUL && arg[0] != delim)
                   5030:            {
                   5031:                if (arg[0] == '\\' && arg[1] != NUL)
                   5032:                    ++arg;
                   5033:                ++arg;
                   5034:            }
                   5035:            if (arg[0] != NUL)
                   5036:                return arg + 1;
                   5037:            break;
                   5038:        case CMD_and:
                   5039:        case CMD_substitute:
                   5040:            delim = *arg;
                   5041:            if (delim)
                   5042:                ++arg;
                   5043:            for (i = 0; i < 2; i++)
                   5044:            {
                   5045:                while (arg[0] != NUL && arg[0] != delim)
                   5046:                {
                   5047:                    if (arg[0] == '\\' && arg[1] != NUL)
                   5048:                        ++arg;
                   5049:                    ++arg;
                   5050:                }
                   5051:                if (arg[0] != NUL)      /* skip delimiter */
                   5052:                    ++arg;
                   5053:            }
                   5054:            while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
                   5055:                ++arg;
                   5056:            if (arg[0] != NUL)
                   5057:                return arg;
                   5058:            break;
                   5059:        case CMD_isearch:
                   5060:        case CMD_dsearch:
                   5061:        case CMD_ilist:
                   5062:        case CMD_dlist:
                   5063:        case CMD_ijump:
                   5064:        case CMD_djump:
                   5065:        case CMD_isplit:
                   5066:        case CMD_dsplit:
                   5067:            arg = skipwhite(skipdigits(arg));       /* skip count */
                   5068:            if (*arg == '/')    /* Match regexp, not just whole words */
                   5069:            {
                   5070:                for (++arg; *arg && *arg != '/'; arg++)
                   5071:                    if (*arg == '\\' && arg[1] != NUL)
                   5072:                        arg++;
                   5073:                if (*arg)
                   5074:                {
                   5075:                    arg = skipwhite(arg + 1);
                   5076:
                   5077:                    /* Check for trailing illegal characters */
                   5078:                    if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
                   5079:                        expand_context = EXPAND_NOTHING;
                   5080:                    else
                   5081:                        return arg;
                   5082:                }
                   5083:            }
                   5084:            break;
                   5085: #ifdef AUTOCMD
                   5086:        case CMD_autocmd:
                   5087:            return set_context_in_autocmd(arg, FALSE);
                   5088:
                   5089:        case CMD_doautocmd:
                   5090:            return set_context_in_autocmd(arg, TRUE);
                   5091: #endif
                   5092:        case CMD_set:
                   5093:            set_context_in_set_cmd(arg);
                   5094:            break;
                   5095:        case CMD_stag:
                   5096:        case CMD_tag:
                   5097:            expand_context = EXPAND_TAGS;
                   5098:            expand_pattern = arg;
                   5099:            break;
                   5100:        case CMD_help:
                   5101:            expand_context = EXPAND_HELP;
                   5102:            expand_pattern = arg;
                   5103:            break;
                   5104:        case CMD_bdelete:
                   5105:        case CMD_bunload:
                   5106:            while ((expand_pattern = vim_strchr(arg, ' ')) != NULL)
                   5107:                arg = expand_pattern + 1;
                   5108:        case CMD_buffer:
                   5109:        case CMD_sbuffer:
                   5110:            expand_context = EXPAND_BUFFERS;
                   5111:            expand_pattern = arg;
                   5112:            break;
                   5113: #ifdef USE_GUI
                   5114:        case CMD_menu:      case CMD_noremenu:      case CMD_unmenu:
                   5115:        case CMD_nmenu:     case CMD_nnoremenu:     case CMD_nunmenu:
                   5116:        case CMD_vmenu:     case CMD_vnoremenu:     case CMD_vunmenu:
                   5117:        case CMD_imenu:     case CMD_inoremenu:     case CMD_iunmenu:
                   5118:        case CMD_cmenu:     case CMD_cnoremenu:     case CMD_cunmenu:
                   5119:            return gui_set_context_in_menu_cmd(cmd, arg, forced);
                   5120:            break;
                   5121: #endif
                   5122:        default:
                   5123:            break;
                   5124:    }
                   5125:    return NULL;
                   5126: }
                   5127:
                   5128: /*
                   5129:  * Do the expansion based on the global variables expand_context and
                   5130:  * expand_pattern -- webb.
                   5131:  */
                   5132:    static int
                   5133: ExpandFromContext(pat, num_file, file, files_only, options)
                   5134:    char_u  *pat;
                   5135:    int     *num_file;
                   5136:    char_u  ***file;
                   5137:    int     files_only;
                   5138:    int     options;
                   5139: {
                   5140:    regexp  *prog;
                   5141:    int     ret;
                   5142:    int     i;
                   5143:    int     count;
                   5144:
                   5145:    if (!expand_interactively || expand_context == EXPAND_FILES)
                   5146:        return ExpandWildCards(1, &pat, num_file, file, files_only,
                   5147:                                              (options & WILD_LIST_NOTFOUND));
                   5148:    else if (expand_context == EXPAND_DIRECTORIES)
                   5149:    {
                   5150:        if (ExpandWildCards(1, &pat, num_file, file, files_only,
                   5151:                                      (options & WILD_LIST_NOTFOUND)) == FAIL)
                   5152:            return FAIL;
                   5153:        count = 0;
                   5154:        for (i = 0; i < *num_file; i++)
                   5155:            if (mch_isdir((*file)[i]))
                   5156:                (*file)[count++] = (*file)[i];
                   5157:            else
                   5158:                vim_free((*file)[i]);
                   5159:        if (count == 0)
                   5160:        {
                   5161:            vim_free(*file);
                   5162:            *file = (char_u **)"";
                   5163:            *num_file = -1;
                   5164:            return FAIL;
                   5165:        }
                   5166:        *num_file = count;
                   5167:        return OK;
                   5168:    }
                   5169:    *file = (char_u **)"";
                   5170:    *num_file = 0;
                   5171:    if (expand_context == EXPAND_OLD_SETTING)
                   5172:        return ExpandOldSetting(num_file, file);
                   5173:
                   5174:    if (expand_context == EXPAND_HELP)
                   5175:        return find_help_tags(pat, num_file, file);
                   5176:
                   5177:    set_reg_ic(pat);        /* set reg_ic according to p_ic, p_scs and pat */
                   5178: #ifdef AUTOCMD
                   5179:    if (expand_context == EXPAND_EVENTS)
                   5180:        reg_ic = TRUE;      /* always ignore case for events */
                   5181: #endif
                   5182:    reg_magic = p_magic;
                   5183:
                   5184:    if (expand_context == EXPAND_BUFFERS)
                   5185:        return ExpandBufnames(pat, num_file, file, options);
                   5186:
                   5187:    prog = vim_regcomp(pat);
                   5188:    if (prog == NULL)
                   5189:        return FAIL;
                   5190:
                   5191:    if (expand_context == EXPAND_COMMANDS)
                   5192:        ret = ExpandCommands(prog, num_file, file);
                   5193:    else if (expand_context == EXPAND_SETTINGS ||
                   5194:                                       expand_context == EXPAND_BOOL_SETTINGS)
                   5195:        ret = ExpandSettings(prog, num_file, file);
                   5196:    else if (expand_context == EXPAND_TAGS)
                   5197:        ret = find_tags(NULL, prog, num_file, file, FALSE);
                   5198: #ifdef AUTOCMD
                   5199:    else if (expand_context == EXPAND_EVENTS)
                   5200:        ret = ExpandEvents(prog, num_file, file);
                   5201: #endif
                   5202: #ifdef USE_GUI
                   5203:    else if (expand_context == EXPAND_MENUS)
                   5204:        ret = gui_ExpandMenuNames(prog, num_file, file);
                   5205: #endif
                   5206:    else
                   5207:        ret = FAIL;
                   5208:
                   5209:    vim_free(prog);
                   5210:    return ret;
                   5211: }
                   5212:
                   5213:    static int
                   5214: ExpandCommands(prog, num_file, file)
                   5215:    regexp      *prog;
                   5216:    int         *num_file;
                   5217:    char_u      ***file;
                   5218: {
                   5219:    int     cmdidx;
                   5220:    int     count;
                   5221:    int     round;
                   5222:
                   5223:    /*
                   5224:     * round == 1: Count the matches.
                   5225:     * round == 2: Save the matches into the array.
                   5226:     */
                   5227:    for (round = 1; round <= 2; ++round)
                   5228:    {
                   5229:        count = 0;
                   5230:        for (cmdidx = 0; cmdidx < CMD_SIZE; cmdidx++)
                   5231:            if (vim_regexec(prog, cmdnames[cmdidx].cmd_name, TRUE))
                   5232:            {
                   5233:                if (round == 1)
                   5234:                    count++;
                   5235:                else
                   5236:                    (*file)[count++] = strsave(cmdnames[cmdidx].cmd_name);
                   5237:            }
                   5238:        if (round == 1)
                   5239:        {
                   5240:            *num_file = count;
                   5241:            if (count == 0 || (*file = (char_u **)
                   5242:                         alloc((unsigned)(count * sizeof(char_u *)))) == NULL)
                   5243:                return FAIL;
                   5244:        }
                   5245:    }
                   5246:    return OK;
                   5247: }
                   5248:
                   5249: #ifdef VIMINFO
                   5250: static char_u **viminfo_history[2] = {NULL, NULL};
                   5251: static int     viminfo_hisidx[2] = {0, 0};
                   5252: static int     viminfo_hislen = 0;
                   5253: static int     viminfo_add_at_front = FALSE;
                   5254:
                   5255:    void
                   5256: prepare_viminfo_history(len)
                   5257:    int len;
                   5258: {
                   5259:    int i;
                   5260:    int num;
                   5261:    int type;
                   5262:
                   5263:    init_history();
                   5264:    viminfo_add_at_front = (len != 0);
                   5265:    if (len > hislen)
                   5266:        len = hislen;
                   5267:
                   5268:    for (type = 0; type <= 1; ++type)
                   5269:    {
                   5270:        /* If there are more spaces available than we request, then fill them
                   5271:         * up */
                   5272:        for (i = 0, num = 0; i < hislen; i++)
                   5273:            if (history[type][i] == NULL)
                   5274:                num++;
                   5275:        if (num > len)
                   5276:            len = num;
                   5277:        viminfo_hisidx[type] = 0;
                   5278:        if (len <= 0)
                   5279:            viminfo_history[type] = NULL;
                   5280:        else
                   5281:            viminfo_history[type] = (char_u **)lalloc(len * sizeof(char_u *),
                   5282:                                                                       FALSE);
                   5283:    }
                   5284:    viminfo_hislen = len;
                   5285:    if (viminfo_history[0] == NULL || viminfo_history[1] == NULL)
                   5286:        viminfo_hislen = 0;
                   5287: }
                   5288:
                   5289:    int
                   5290: read_viminfo_history(line, fp)
                   5291:    char_u  *line;
                   5292:    FILE    *fp;
                   5293: {
                   5294:    int     type;
                   5295:
                   5296:    type = (line[0] == ':' ? 0 : 1);
                   5297:    if (viminfo_hisidx[type] != viminfo_hislen)
                   5298:    {
                   5299:        viminfo_readstring(line);
                   5300:        if (!is_in_history(type, line + 1, viminfo_add_at_front))
                   5301:            viminfo_history[type][viminfo_hisidx[type]++] = strsave(line + 1);
                   5302:    }
                   5303:    return vim_fgets(line, LSIZE, fp);
                   5304: }
                   5305:
                   5306:    void
                   5307: finish_viminfo_history()
                   5308: {
                   5309:    int idx;
                   5310:    int i;
                   5311:    int type;
                   5312:
                   5313:    for (type = 0; type <= 1; ++type)
                   5314:    {
                   5315:        if (history[type] == NULL)
                   5316:            return;
                   5317:        idx = hisidx[type] + viminfo_hisidx[type];
                   5318:        if (idx >= hislen)
                   5319:            idx -= hislen;
                   5320:        if (viminfo_add_at_front)
                   5321:            hisidx[type] = idx;
                   5322:        else
                   5323:        {
                   5324:            if (hisidx[type] == -1)
                   5325:                hisidx[type] = hislen - 1;
                   5326:            do
                   5327:            {
                   5328:                if (history[type][idx] != NULL)
                   5329:                    break;
                   5330:                if (++idx == hislen)
                   5331:                    idx = 0;
                   5332:            } while (idx != hisidx[type]);
                   5333:            if (idx != hisidx[type] && --idx < 0)
                   5334:                idx = hislen - 1;
                   5335:        }
                   5336:        for (i = 0; i < viminfo_hisidx[type]; i++)
                   5337:        {
                   5338:            history[type][idx] = viminfo_history[type][i];
                   5339:            if (--idx < 0)
                   5340:                idx = hislen - 1;
                   5341:        }
                   5342:        vim_free(viminfo_history[type]);
                   5343:        viminfo_history[type] = NULL;
                   5344:    }
                   5345: }
                   5346:
                   5347:    void
                   5348: write_viminfo_history(fp)
                   5349:    FILE    *fp;
                   5350: {
                   5351:    int     i;
                   5352:    int     type;
                   5353:    int     num_saved;
                   5354:
                   5355:    init_history();
                   5356:    if (hislen == 0)
                   5357:        return;
                   5358:    for (type = 0; type <= 1; ++type)
                   5359:    {
                   5360:        num_saved = get_viminfo_parameter(type == 0 ? ':' : '/');
                   5361:        if (num_saved == 0)
                   5362:            continue;
                   5363:        if (num_saved < 0)  /* Use default */
                   5364:            num_saved = hislen;
                   5365:        fprintf(fp, "\n# %s History (newest to oldest):\n",
                   5366:                            type == 0 ? "Command Line" : "Search String");
                   5367:        if (num_saved > hislen)
                   5368:            num_saved = hislen;
                   5369:        i = hisidx[type];
                   5370:        if (i >= 0)
                   5371:            while (num_saved--)
                   5372:            {
                   5373:                if (history[type][i] != NULL)
                   5374:                {
                   5375:                    putc(type == 0 ? ':' : '?', fp);
                   5376:                    viminfo_writestring(fp, history[type][i]);
                   5377:                }
                   5378:                if (--i < 0)
                   5379:                    i = hislen - 1;
                   5380:            }
                   5381:    }
                   5382: }
                   5383: #endif /* VIMINFO */