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

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