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

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