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

Annotation of src/usr.bin/vim/buffer.c, Revision 1.2

1.2     ! downsj      1: /* $OpenBSD: buffer.c,v 1.1.1.1 1996/09/07 21:40:27 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:  * buffer.c: functions for dealing with the buffer structure
                     12:  */
                     13:
                     14: /*
                     15:  * The buffer list is a double linked list of all buffers.
                     16:  * Each buffer can be in one of these states:
                     17:  * never loaded: b_neverloaded == TRUE, only the file name is valid
                     18:  *   not loaded: b_ml.ml_mfp == NULL, no memfile allocated
                     19:  *       hidden: b_nwindows == 0, loaded but not displayed in a window
                     20:  *       normal: loaded and displayed in a window
                     21:  *
                     22:  * Instead of storing file names all over the place, each file name is
                     23:  * stored in the buffer list. It can be referenced by a number.
                     24:  *
                     25:  * The current implementation remembers all file names ever used.
                     26:  */
                     27:
                     28: #include "vim.h"
                     29: #include "globals.h"
                     30: #include "proto.h"
                     31: #include "option.h"
                     32:
                     33: static void        enter_buffer __ARGS((BUF *));
                     34: static char_u  *buflist_match __ARGS((regexp *prog, BUF *buf));
                     35: static void        buflist_setlnum __ARGS((BUF *, linenr_t));
                     36: static linenr_t buflist_findlnum __ARGS((BUF *));
1.2     ! downsj     37: static int     append_arg_number __ARGS((char_u *, int, int));
1.1       downsj     38:
                     39: /*
                     40:  * Open current buffer, that is: open the memfile and read the file into memory
                     41:  * return FAIL for failure, OK otherwise
                     42:  */
                     43:    int
                     44: open_buffer()
                     45: {
                     46:    int     retval = OK;
1.2     ! downsj     47: #ifdef AUTOCMD
        !            48:    BUF     *old_curbuf;
        !            49:    BUF     *new_curbuf;
        !            50: #endif
1.1       downsj     51:
                     52:    /*
                     53:     * The 'readonly' flag is only set when b_neverloaded is being reset.
                     54:     * When re-entering the same buffer, it should not change, because the
                     55:     * user may have reset the flag by hand.
                     56:     */
                     57:    if (readonlymode && curbuf->b_filename != NULL && curbuf->b_neverloaded)
                     58:        curbuf->b_p_ro = TRUE;
                     59:
                     60:    if (ml_open() == FAIL)
                     61:    {
                     62:        /*
                     63:         * There MUST be a memfile, otherwise we can't do anything
                     64:         * If we can't create one for the current buffer, take another buffer
                     65:         */
                     66:        close_buffer(NULL, curbuf, FALSE, FALSE);
                     67:        for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
                     68:            if (curbuf->b_ml.ml_mfp != NULL)
                     69:                break;
                     70:        /*
                     71:         * if there is no memfile at all, exit
                     72:         * This is OK, since there are no changes to loose.
                     73:         */
                     74:        if (curbuf == NULL)
                     75:        {
                     76:            EMSG("Cannot allocate buffer, exiting...");
                     77:            getout(2);
                     78:        }
                     79:        EMSG("Cannot allocate buffer, using other one...");
                     80:        enter_buffer(curbuf);
                     81:        return FAIL;
                     82:    }
1.2     ! downsj     83: #ifdef AUTOCMD
        !            84:    /* The autocommands in readfile() may change the buffer, but only AFTER
        !            85:     * reading the file. */
        !            86:    old_curbuf = curbuf;
        !            87: #endif
1.1       downsj     88:    if (curbuf->b_filename != NULL)
                     89:        retval = readfile(curbuf->b_filename, curbuf->b_sfilename,
                     90:                              (linenr_t)0, TRUE, (linenr_t)0, MAXLNUM, FALSE);
                     91:    else
                     92:    {
                     93:        MSG("Empty Buffer");
                     94:        msg_col = 0;
                     95:        msg_didout = FALSE;     /* overwrite this message whenever you like */
                     96:    }
                     97:
                     98:    /* if first time loading this buffer, init chartab */
                     99:    if (curbuf->b_neverloaded)
                    100:        init_chartab();
                    101:
                    102:    /*
                    103:     * Reset the Changed flag first, autocmds may change the buffer.
                    104:     * Apply the automatic commands, before processing the modelines.
                    105:     * So the modelines have priority over auto commands.
                    106:     */
                    107:    if (retval != FAIL)
                    108:        UNCHANGED(curbuf);
                    109:
                    110: #ifdef AUTOCMD
                    111:    apply_autocmds(EVENT_BUFENTER, NULL, NULL);
                    112: #endif
                    113:
                    114:    if (retval != FAIL)
                    115:    {
1.2     ! downsj    116: #ifdef AUTOCMD
        !           117:        /*
        !           118:         * The autocommands may have changed the current buffer.  Apply the
        !           119:         * modelines to the correct buffer, if it still exists.
        !           120:         */
        !           121:        if (buf_valid(old_curbuf))
        !           122:        {
        !           123:            new_curbuf = curbuf;
        !           124:            curbuf = old_curbuf;
        !           125:            curwin->w_buffer = old_curbuf;
        !           126: #endif
        !           127:            do_modelines();
        !           128:            curbuf->b_neverloaded = FALSE;
        !           129: #ifdef AUTOCMD
        !           130:            curbuf = new_curbuf;
        !           131:            curwin->w_buffer = new_curbuf;
        !           132:        }
        !           133: #endif
1.1       downsj    134:    }
                    135:
                    136:    return retval;
                    137: }
                    138:
                    139: /*
1.2     ! downsj    140:  * Return TRUE if "buf" points to a valid buffer (in the buffer list).
        !           141:  */
        !           142:    int
        !           143: buf_valid(buf)
        !           144:    BUF     *buf;
        !           145: {
        !           146:    BUF     *bp;
        !           147:
        !           148:    for (bp = firstbuf; bp != NULL; bp = bp->b_next)
        !           149:        if (bp == buf)
        !           150:            return TRUE;
        !           151:    return FALSE;
        !           152: }
        !           153:
        !           154: /*
1.1       downsj    155:  * Close the link to a buffer. If "free_buf" is TRUE free the buffer if it
                    156:  * becomes unreferenced. The caller should get a new buffer very soon!
                    157:  * if 'del_buf' is TRUE, remove the buffer from the buffer list.
                    158:  */
                    159:    void
                    160: close_buffer(win, buf, free_buf, del_buf)
                    161:    WIN     *win;           /* if not NULL, set b_last_cursor */
                    162:    BUF     *buf;
                    163:    int     free_buf;
                    164:    int     del_buf;
                    165: {
                    166:    if (buf->b_nwindows > 0)
                    167:        --buf->b_nwindows;
                    168:    if (buf->b_nwindows == 0 && win != NULL)
                    169:        set_last_cursor(win);   /* may set b_last_cursor */
                    170:    if (buf->b_nwindows > 0 || !free_buf)
                    171:    {
                    172:        if (buf == curbuf)
                    173:            u_sync();       /* sync undo before going to another buffer */
                    174:        return;
                    175:    }
                    176:
                    177:    buf_freeall(buf);       /* free all things allocated for this buffer */
                    178:    /*
                    179:     * If there is no file name, remove the buffer from the list
                    180:     */
                    181:    if (buf->b_filename == NULL || del_buf)
                    182:    {
                    183:        vim_free(buf->b_filename);
                    184:        vim_free(buf->b_sfilename);
                    185:        if (buf->b_prev == NULL)
                    186:            firstbuf = buf->b_next;
                    187:        else
                    188:            buf->b_prev->b_next = buf->b_next;
                    189:        if (buf->b_next == NULL)
                    190:            lastbuf = buf->b_prev;
                    191:        else
                    192:            buf->b_next->b_prev = buf->b_prev;
                    193:        free_buf_options(buf);
1.2     ! downsj    194:        vim_free(buf);
1.1       downsj    195:    }
                    196:    else
                    197:        buf_clear(buf);
                    198: }
                    199:
                    200: /*
                    201:  * buf_clear() - make buffer empty
                    202:  */
                    203:    void
                    204: buf_clear(buf)
                    205:    BUF     *buf;
                    206: {
                    207:    buf->b_ml.ml_line_count = 1;
                    208:    buf->b_changed = FALSE;
                    209: #ifndef SHORT_FNAME
                    210:    buf->b_shortname = FALSE;
                    211: #endif
                    212:    buf->b_p_eol = TRUE;
                    213:    buf->b_ml.ml_mfp = NULL;
                    214:    buf->b_ml.ml_flags = ML_EMPTY;              /* empty buffer */
                    215: }
                    216:
                    217: /*
                    218:  * buf_freeall() - free all things allocated for the buffer
                    219:  */
                    220:    void
                    221: buf_freeall(buf)
                    222:    BUF     *buf;
                    223: {
                    224:    u_blockfree(buf);               /* free the memory allocated for undo */
                    225:    ml_close(buf, TRUE);            /* close and delete the memline/memfile */
                    226:    buf->b_ml.ml_line_count = 0;    /* no lines in buffer */
                    227:    u_clearall(buf);                /* reset all undo information */
                    228: }
                    229:
                    230: /*
                    231:  * do_bufdel() - delete or unload buffer(s)
                    232:  *
                    233:  * addr_count == 0:    ":bdel" - delete current buffer
                    234:  * addr_count == 1: ":N bdel" or ":bdel N [N ..] - first delete
                    235:  *                 buffer "end_bnr", then any other arguments.
                    236:  * addr_count == 2: ":N,N bdel" - delete buffers in range
                    237:  *
                    238:  * command can be DOBUF_UNLOAD (":bunload") or DOBUF_DEL (":bdel")
                    239:  *
                    240:  * Returns error message or NULL
                    241:  */
                    242:    char_u *
                    243: do_bufdel(command, arg, addr_count, start_bnr, end_bnr, forceit)
                    244:    int     command;
                    245:    char_u  *arg;       /* pointer to extra arguments */
                    246:    int     addr_count;
                    247:    int     start_bnr;  /* first buffer number in a range */
                    248:    int     end_bnr;    /* buffer number or last buffer number in a range */
                    249:    int     forceit;
                    250: {
                    251:    int     do_current = 0;     /* delete current buffer? */
                    252:    int     deleted = 0;        /* number of buffers deleted */
                    253:    char_u  *errormsg = NULL;   /* return value */
                    254:    int     bnr;                /* buffer number */
                    255:    char_u  *p;
                    256:
                    257:    if (addr_count == 0)
                    258:        (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
                    259:    else
                    260:    {
                    261:        if (addr_count == 2)
                    262:        {
                    263:            if (*arg)           /* both range and argument is not allowed */
                    264:                return e_trailing;
                    265:            bnr = start_bnr;
                    266:        }
                    267:        else    /* addr_count == 1 */
                    268:            bnr = end_bnr;
                    269:
                    270:        for ( ;!got_int; mch_breakcheck())
                    271:        {
                    272:            /*
                    273:             * delete the current buffer last, otherwise when the
                    274:             * current buffer is deleted, the next buffer becomes
                    275:             * the current one and will be loaded, which may then
                    276:             * also be deleted, etc.
                    277:             */
                    278:            if (bnr == curbuf->b_fnum)
                    279:                do_current = bnr;
                    280:            else if (do_buffer(command, DOBUF_FIRST, FORWARD, (int)bnr,
1.2     ! downsj    281:                                                               forceit) == OK)
1.1       downsj    282:                ++deleted;
                    283:
                    284:            /*
                    285:             * find next buffer number to delete/unload
                    286:             */
                    287:            if (addr_count == 2)
                    288:            {
                    289:                if (++bnr > end_bnr)
                    290:                    break;
                    291:            }
                    292:            else    /* addr_count == 1 */
                    293:            {
                    294:                arg = skipwhite(arg);
                    295:                if (*arg == NUL)
                    296:                    break;
                    297:                if (!isdigit(*arg))
                    298:                {
                    299:                    p = skiptowhite_esc(arg);
                    300:                    bnr = buflist_findpat(arg, p);
                    301:                    if (bnr < 0)            /* failed */
                    302:                        break;
                    303:                    arg = p;
                    304:                }
                    305:                else
                    306:                    bnr = getdigits(&arg);
                    307:            }
                    308:        }
                    309:        if (!got_int && do_current && do_buffer(command, DOBUF_FIRST,
1.2     ! downsj    310:                                          FORWARD, do_current, forceit) == OK)
1.1       downsj    311:            ++deleted;
                    312:
                    313:        if (deleted == 0)
                    314:        {
                    315:            sprintf((char *)IObuff, "No buffers were %s",
                    316:                    command == DOBUF_UNLOAD ? "unloaded" : "deleted");
                    317:            errormsg = IObuff;
                    318:        }
                    319:        else
                    320:            smsg((char_u *)"%d buffer%s %s", deleted,
                    321:                    plural((long)deleted),
                    322:                    command == DOBUF_UNLOAD ? "unloaded" : "deleted");
                    323:    }
                    324:
                    325:    return errormsg;
                    326: }
                    327:
                    328: /*
                    329:  * Implementation of the command for the buffer list
                    330:  *
                    331:  * action == DOBUF_GOTO        go to specified buffer
                    332:  * action == DOBUF_SPLIT   split window and go to specified buffer
                    333:  * action == DOBUF_UNLOAD  unload specified buffer(s)
                    334:  * action == DOBUF_DEL     delete specified buffer(s)
                    335:  *
                    336:  * start == DOBUF_CURRENT  go to "count" buffer from current buffer
                    337:  * start == DOBUF_FIRST        go to "count" buffer from first buffer
                    338:  * start == DOBUF_LAST     go to "count" buffer from last buffer
                    339:  * start == DOBUF_MOD      go to "count" modified buffer from current buffer
                    340:  *
                    341:  * Return FAIL or OK.
                    342:  */
                    343:    int
                    344: do_buffer(action, start, dir, count, forceit)
                    345:    int     action;
                    346:    int     start;
                    347:    int     dir;        /* FORWARD or BACKWARD */
                    348:    int     count;      /* buffer number or number of buffers */
                    349:    int     forceit;    /* TRUE for :bdelete! */
                    350: {
                    351:    BUF     *buf;
                    352:    BUF     *delbuf;
                    353:    int     retval;
                    354:
                    355:    switch (start)
                    356:    {
                    357:        case DOBUF_FIRST:   buf = firstbuf; break;
                    358:        case DOBUF_LAST:    buf = lastbuf;  break;
                    359:        default:            buf = curbuf;   break;
                    360:    }
                    361:    if (start == DOBUF_MOD)         /* find next modified buffer */
                    362:    {
                    363:        while (count-- > 0)
                    364:        {
                    365:            do
                    366:            {
                    367:                buf = buf->b_next;
                    368:                if (buf == NULL)
                    369:                    buf = firstbuf;
                    370:            }
                    371:            while (buf != curbuf && !buf->b_changed);
                    372:        }
                    373:        if (!buf->b_changed)
                    374:        {
                    375:            EMSG("No modified buffer found");
                    376:            return FAIL;
                    377:        }
                    378:    }
                    379:    else if (start == DOBUF_FIRST && count) /* find specified buffer number */
                    380:    {
                    381:        while (buf != NULL && buf->b_fnum != count)
                    382:            buf = buf->b_next;
                    383:    }
                    384:    else
                    385:    {
                    386:        while (count-- > 0)
                    387:        {
                    388:            if (dir == FORWARD)
                    389:            {
                    390:                buf = buf->b_next;
                    391:                if (buf == NULL)
                    392:                    buf = firstbuf;
                    393:            }
                    394:            else
                    395:            {
                    396:                buf = buf->b_prev;
                    397:                if (buf == NULL)
                    398:                    buf = lastbuf;
                    399:            }
                    400:        }
                    401:    }
                    402:
                    403:    if (buf == NULL)        /* could not find it */
                    404:    {
                    405:        if (start == DOBUF_FIRST)
                    406:        {
                    407:                                            /* don't warn when deleting */
                    408:            if (action != DOBUF_UNLOAD && action != DOBUF_DEL)
                    409:                EMSGN("Cannot go to buffer %ld", count);
                    410:        }
                    411:        else if (dir == FORWARD)
                    412:            EMSG("Cannot go beyond last buffer");
                    413:        else
                    414:            EMSG("Cannot go before first buffer");
                    415:        return FAIL;
                    416:    }
                    417:
                    418:    /*
                    419:     * delete buffer buf from memory and/or the list
                    420:     */
                    421:    if (action == DOBUF_UNLOAD || action == DOBUF_DEL)
                    422:    {
                    423:        if (!forceit && buf->b_changed)
                    424:        {
                    425:            EMSGN("No write since last change for buffer %ld (use ! to override)",
                    426:                        buf->b_fnum);
                    427:            return FAIL;
                    428:        }
                    429:
                    430:        /*
                    431:         * If deleting last buffer, make it empty.
                    432:         * The last buffer cannot be unloaded.
                    433:         */
                    434:        if (firstbuf->b_next == NULL)
                    435:        {
                    436:            if (action == DOBUF_UNLOAD)
                    437:            {
                    438:                EMSG("Cannot unload last buffer");
                    439:                return FAIL;
                    440:            }
1.2     ! downsj    441:
        !           442:            /* Close any other windows on this buffer, then make it empty. */
1.1       downsj    443:            close_others(FALSE);
                    444:            buf = curbuf;
                    445:            setpcmark();
1.2     ! downsj    446:            retval = do_ecmd(0, NULL, NULL, NULL, (linenr_t)1,
        !           447:                                                  forceit ? ECMD_FORCEIT : 0);
        !           448:
1.1       downsj    449:            /*
1.2     ! downsj    450:             * do_ecmd() may create a new buffer, then we have to delete
1.1       downsj    451:             * the old one.  But do_ecmd() may have done that already, check
1.2     ! downsj    452:             * if the buffer still exists.
1.1       downsj    453:             */
1.2     ! downsj    454:            if (buf != curbuf && buf_valid(buf))
1.1       downsj    455:                close_buffer(NULL, buf, TRUE, TRUE);
                    456:            return retval;
                    457:        }
                    458:
                    459:        /*
                    460:         * If the deleted buffer is the current one, close the current window
                    461:         * (unless it's the only window).
                    462:         */
                    463:        while (buf == curbuf && firstwin != lastwin)
                    464:            close_window(curwin, FALSE);
                    465:
                    466:        /*
                    467:         * If the buffer to be deleted is not current one, delete it here.
                    468:         */
                    469:        if (buf != curbuf)
                    470:        {
                    471:            close_windows(buf);
1.2     ! downsj    472:            if (buf_valid(buf))
        !           473:                close_buffer(NULL, buf, TRUE, action == DOBUF_DEL);
1.1       downsj    474:            return OK;
                    475:        }
                    476:
                    477:        /*
                    478:         * Deleting the current buffer: Need to find another buffer to go to.
                    479:         * There must be another, otherwise it would have been handled above.
1.2     ! downsj    480:         * First try to find one that is loaded.
1.1       downsj    481:         */
1.2     ! downsj    482:        for (buf = firstbuf; buf != NULL; buf = buf->b_next)
        !           483:            if (buf != curbuf && buf->b_ml.ml_mfp != NULL)
        !           484:                break;
        !           485:        if (buf == NULL)        /* No loaded buffers, just take anyone */
        !           486:        {
        !           487:            if (curbuf->b_next != NULL)
        !           488:                buf = curbuf->b_next;
        !           489:            else
        !           490:                buf = curbuf->b_prev;
        !           491:        }
1.1       downsj    492:    }
                    493:
                    494:    /*
                    495:     * make buf current buffer
                    496:     */
                    497:    if (action == DOBUF_SPLIT)      /* split window first */
                    498:    {
                    499:        if (win_split(0, FALSE) == FAIL)
                    500:            return FAIL;
                    501:    }
1.2     ! downsj    502:
        !           503:    /* go to current buffer - nothing to do */
        !           504:    if (buf == curbuf)
        !           505:        return OK;
        !           506:
        !           507:    setpcmark();
1.1       downsj    508:    curwin->w_alt_fnum = curbuf->b_fnum; /* remember alternate file */
                    509:    buflist_altlnum();                   /* remember curpos.lnum */
                    510:
1.2     ! downsj    511:    /* close_windows() or apply_autocmds() may change curbuf */
        !           512:    delbuf = curbuf;
        !           513:
1.1       downsj    514: #ifdef AUTOCMD
                    515:    apply_autocmds(EVENT_BUFLEAVE, NULL, NULL);
1.2     ! downsj    516:    if (buf_valid(delbuf))
1.1       downsj    517: #endif
1.2     ! downsj    518:    {
        !           519:        if (action == DOBUF_UNLOAD || action == DOBUF_DEL)
        !           520:            close_windows(delbuf);
        !           521:        if (buf_valid(delbuf))
        !           522:            close_buffer(NULL, delbuf, action == DOBUF_UNLOAD ||
        !           523:                                    action == DOBUF_DEL, action == DOBUF_DEL);
        !           524:    }
        !           525: #ifdef AUTOCMD
        !           526:    if (buf_valid(buf))     /* an autocommand may have deleted buf! */
        !           527: #endif
        !           528:        enter_buffer(buf);
1.1       downsj    529:    return OK;
                    530: }
                    531:
                    532: /*
                    533:  * enter a new current buffer.
                    534:  * (old curbuf must have been freed already)
                    535:  */
                    536:    static void
                    537: enter_buffer(buf)
                    538:    BUF     *buf;
                    539: {
1.2     ! downsj    540:    buf_copy_options(curbuf, buf, TRUE, FALSE);
1.1       downsj    541:    curwin->w_buffer = buf;
                    542:    curbuf = buf;
                    543:    ++curbuf->b_nwindows;
                    544:    if (curbuf->b_ml.ml_mfp == NULL)    /* need to load the file */
                    545:        open_buffer();
                    546:    else
                    547:    {
                    548:        need_fileinfo = TRUE;           /* display file info after redraw */
                    549:        buf_check_timestamp(curbuf);    /* check if file has changed */
                    550: #ifdef AUTOCMD
                    551:        apply_autocmds(EVENT_BUFENTER, NULL, NULL);
                    552: #endif
                    553:    }
                    554:    buflist_getlnum();                  /* restore curpos.lnum */
                    555:    check_arg_idx();                    /* check for valid arg_idx */
                    556:    maketitle();
                    557:    scroll_cursor_halfway(FALSE);       /* redisplay at correct position */
                    558:    updateScreen(NOT_VALID);
                    559: }
                    560:
                    561: /*
                    562:  * functions for dealing with the buffer list
                    563:  */
                    564:
                    565: /*
                    566:  * Add a file name to the buffer list. Return a pointer to the buffer.
                    567:  * If the same file name already exists return a pointer to that buffer.
                    568:  * If it does not exist, or if fname == NULL, a new entry is created.
                    569:  * If use_curbuf is TRUE, may use current buffer.
                    570:  * This is the ONLY way to create a new buffer.
                    571:  */
                    572:    BUF *
                    573: buflist_new(fname, sfname, lnum, use_curbuf)
                    574:    char_u      *fname;
                    575:    char_u      *sfname;
                    576:    linenr_t    lnum;
                    577:    int         use_curbuf;
                    578: {
                    579:    static int  top_file_num = 1;           /* highest file number */
                    580:    BUF         *buf;
                    581:
                    582:    fname_expand(&fname, &sfname);
                    583:
                    584: /*
                    585:  * If file name already exists in the list, update the entry
                    586:  */
                    587:    if (fname != NULL && (buf = buflist_findname(fname)) != NULL)
                    588:    {
                    589:        if (lnum != 0)
                    590:            buflist_setlnum(buf, lnum);
                    591:        /* copy the options now, if 'cpo' doesn't have 's' and not done
                    592:         * already */
1.2     ! downsj    593:        buf_copy_options(curbuf, buf, FALSE, FALSE);
1.1       downsj    594:        return buf;
                    595:    }
                    596:
                    597: /*
                    598:  * If the current buffer has no name and no contents, use the current buffer.
                    599:  * Otherwise: Need to allocate a new buffer structure.
                    600:  *
                    601:  * This is the ONLY place where a new buffer structure is allocated!
                    602:  */
                    603:    if (use_curbuf && curbuf != NULL && curbuf->b_filename == NULL &&
                    604:                curbuf->b_nwindows <= 1 &&
                    605:                (curbuf->b_ml.ml_mfp == NULL || bufempty()))
                    606:        buf = curbuf;
                    607:    else
                    608:    {
                    609:        buf = (BUF *)alloc((unsigned)sizeof(BUF));
                    610:        if (buf == NULL)
                    611:            return NULL;
                    612:        (void)vim_memset(buf, 0, sizeof(BUF));
                    613:    }
                    614:
                    615:    if (fname != NULL)
                    616:    {
                    617:        buf->b_filename = strsave(fname);
                    618:        buf->b_sfilename = strsave(sfname);
                    619:    }
                    620:    if (buf->b_winlnum == NULL)
                    621:        buf->b_winlnum = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
                    622:    if ((fname != NULL && (buf->b_filename == NULL ||
                    623:                         buf->b_sfilename == NULL)) || buf->b_winlnum == NULL)
                    624:    {
                    625:        vim_free(buf->b_filename);
                    626:        buf->b_filename = NULL;
                    627:        vim_free(buf->b_sfilename);
                    628:        buf->b_sfilename = NULL;
                    629:        if (buf != curbuf)
                    630:        {
                    631:            vim_free(buf->b_winlnum);
                    632:            free_buf_options(buf);
1.2     ! downsj    633:            vim_free(buf);
1.1       downsj    634:        }
                    635:        return NULL;
                    636:    }
                    637:
                    638:    if (buf == curbuf)
                    639:    {
                    640:        buf_freeall(buf);       /* free all things allocated for this buffer */
                    641:        buf->b_nwindows = 0;
                    642:    }
                    643:    else
                    644:    {
                    645:        /*
                    646:         * put new buffer at the end of the buffer list
                    647:         */
                    648:        buf->b_next = NULL;
                    649:        if (firstbuf == NULL)           /* buffer list is empty */
                    650:        {
                    651:            buf->b_prev = NULL;
                    652:            firstbuf = buf;
                    653:        }
                    654:        else                            /* append new buffer at end of list */
                    655:        {
                    656:            lastbuf->b_next = buf;
                    657:            buf->b_prev = lastbuf;
                    658:        }
                    659:        lastbuf = buf;
                    660:
                    661:        buf->b_fnum = top_file_num++;
                    662:        if (top_file_num < 0)           /* wrap around (may cause duplicates) */
                    663:        {
                    664:            EMSG("Warning: List of file names overflow");
                    665:            mch_delay(3000L, TRUE);     /* make sure it is noticed */
                    666:            top_file_num = 1;
                    667:        }
                    668:
                    669:        buf->b_winlnum->wl_lnum = lnum;
                    670:        buf->b_winlnum->wl_next = NULL;
                    671:        buf->b_winlnum->wl_prev = NULL;
                    672:        buf->b_winlnum->wl_win = curwin;
1.2     ! downsj    673:
        !           674:        /*
        !           675:         * Always copy the options from the current buffer.
        !           676:         */
        !           677:        buf_copy_options(curbuf, buf, FALSE, TRUE);
1.1       downsj    678:    }
                    679:
                    680:    if (did_cd)
                    681:        buf->b_xfilename = buf->b_filename;
                    682:    else
                    683:        buf->b_xfilename = buf->b_sfilename;
                    684:    buf->b_u_synced = TRUE;
                    685:    buf->b_neverloaded = TRUE;
                    686:    buf_clear(buf);
                    687:    clrallmarks(buf);               /* clear marks */
                    688:    fmarks_check_names(buf);        /* check file marks for this file */
                    689:
                    690:    return buf;
                    691: }
                    692:
                    693: /*
1.2     ! downsj    694:  * Free the memory for the options of a buffer.
1.1       downsj    695:  */
1.2     ! downsj    696:    void
1.1       downsj    697: free_buf_options(buf)
                    698:    BUF     *buf;
                    699: {
                    700:    free_string_option(buf->b_p_fo);
                    701:    free_string_option(buf->b_p_isk);
                    702:    free_string_option(buf->b_p_com);
                    703: #ifdef CINDENT
                    704:    free_string_option(buf->b_p_cink);
                    705:    free_string_option(buf->b_p_cino);
                    706: #endif
                    707: #if defined(CINDENT) || defined(SMARTINDENT)
                    708:    free_string_option(buf->b_p_cinw);
                    709: #endif
                    710: }
                    711:
                    712: /*
                    713:  * get alternate file n
                    714:  * set linenr to lnum or altlnum if lnum == 0
                    715:  * if (options & GETF_SETMARK) call setpcmark()
                    716:  * if (options & GETF_ALT) we are jumping to an alternate file.
                    717:  *
                    718:  * return FAIL for failure, OK for success
                    719:  */
                    720:    int
1.2     ! downsj    721: buflist_getfile(n, lnum, options, forceit)
1.1       downsj    722:    int         n;
                    723:    linenr_t    lnum;
                    724:    int         options;
1.2     ! downsj    725:    int         forceit;
1.1       downsj    726: {
                    727:    BUF     *buf;
                    728:
                    729:    buf = buflist_findnr(n);
                    730:    if (buf == NULL)
                    731:    {
                    732:        if ((options & GETF_ALT) && n == 0)
                    733:            emsg(e_noalt);
                    734:        else
                    735:            EMSGN("buffer %ld not found", n);
                    736:        return FAIL;
                    737:    }
                    738:
                    739:    /* if alternate file is the current buffer, nothing to do */
                    740:    if (buf == curbuf)
                    741:        return OK;
                    742:
                    743:    /* altlnum may be changed by getfile(), get it now */
                    744:    if (lnum == 0)
                    745:        lnum = buflist_findlnum(buf);
                    746:    ++RedrawingDisabled;
1.2     ! downsj    747:    if (getfile(buf->b_fnum, NULL, NULL, (options & GETF_SETMARK),
        !           748:                                                          lnum, forceit) <= 0)
1.1       downsj    749:    {
                    750:        --RedrawingDisabled;
                    751:        return OK;
                    752:    }
                    753:    --RedrawingDisabled;
                    754:    return FAIL;
                    755: }
                    756:
                    757: /*
                    758:  * go to the last know line number for the current buffer
                    759:  */
                    760:    void
                    761: buflist_getlnum()
                    762: {
                    763:    linenr_t    lnum;
                    764:
                    765:    curwin->w_cursor.lnum = 1;
                    766:    curwin->w_cursor.col = 0;
                    767:    lnum = buflist_findlnum(curbuf);
                    768:    if (lnum != 0 && lnum <= curbuf->b_ml.ml_line_count)
                    769:        curwin->w_cursor.lnum = lnum;
                    770: }
                    771:
                    772: /*
                    773:  * find file in buffer list by name (it has to be for the current window)
                    774:  * 'fname' must have a full path.
                    775:  */
                    776:    BUF *
                    777: buflist_findname(fname)
                    778:    char_u      *fname;
                    779: {
                    780:    BUF         *buf;
                    781:
                    782:    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                    783:        if (buf->b_filename != NULL && fnamecmp(fname, buf->b_filename) == 0)
                    784:            return (buf);
                    785:    return NULL;
                    786: }
                    787:
                    788: /*
                    789:  * Find file in buffer list by a regexppattern.
                    790:  * Return fnum of the found buffer, < 0 for error.
                    791:  */
                    792:    int
                    793: buflist_findpat(pattern, pattern_end)
                    794:    char_u      *pattern;
                    795:    char_u      *pattern_end;       /* pointer to first char after pattern */
                    796: {
                    797:    BUF         *buf;
                    798:    regexp      *prog;
                    799:    int         fnum = -1;
                    800:    char_u      *pat;
                    801:    char_u      *match;
                    802:    int         attempt;
                    803:    char_u      *p;
                    804:
                    805:    if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#'))
                    806:    {
                    807:        if (*pattern == '%')
                    808:            fnum = curbuf->b_fnum;
                    809:        else
                    810:            fnum = curwin->w_alt_fnum;
                    811:    }
                    812:
                    813:    /*
                    814:     * Try four ways of matching:
                    815:     * attempt == 0: without '^' or '$' (at any position)
                    816:     * attempt == 1: with '^' at start (only at postion 0)
                    817:     * attempt == 2: with '$' at end (only match at end)
                    818:     * attempt == 3: with '^' at start and '$' at end (only full match)
                    819:     */
                    820:    else for (attempt = 0; attempt <= 3; ++attempt)
                    821:    {
                    822:        /* may add '^' and '$' */
                    823:        pat = file_pat_to_reg_pat(pattern, pattern_end, NULL);
                    824:        if (pat == NULL)
                    825:            return -1;
                    826:        if (attempt < 2)
                    827:        {
                    828:            p = pat + STRLEN(pat) - 1;
                    829:            if (p > pat && *p == '$')               /* remove '$' */
                    830:                *p = NUL;
                    831:        }
                    832:        p = pat;
                    833:        if (*p == '^' && !(attempt & 1))            /* remove '^' */
                    834:            ++p;
                    835:        prog = vim_regcomp(p);
                    836:        vim_free(pat);
                    837:        if (prog == NULL)
                    838:            return -1;
                    839:
                    840:        for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                    841:        {
                    842:            match = buflist_match(prog, buf);
                    843:            if (match != NULL)
                    844:            {
                    845:                if (fnum >= 0)          /* already found a match */
                    846:                {
                    847:                    fnum = -2;
                    848:                    break;
                    849:                }
                    850:                fnum = buf->b_fnum;     /* remember first match */
                    851:            }
                    852:        }
                    853:        vim_free(prog);
                    854:        if (fnum >= 0)                  /* found one match */
                    855:            break;
                    856:    }
                    857:
                    858:    if (fnum == -2)
                    859:        EMSG2("More than one match for %s", pattern);
                    860:    if (fnum < 1)
                    861:        EMSG2("No matching buffer for %s", pattern);
                    862:    return fnum;
                    863: }
                    864:
                    865: /*
                    866:  * Find all buffer names that match.
                    867:  * For command line expansion of ":buf" and ":sbuf".
                    868:  * Return OK if matches found, FAIL otherwise.
                    869:  */
                    870:    int
                    871: ExpandBufnames(pat, num_file, file, options)
                    872:    char_u      *pat;
                    873:    int         *num_file;
                    874:    char_u      ***file;
                    875:    int         options;
                    876: {
                    877:    int         count = 0;
                    878:    BUF         *buf;
                    879:    int         round;
                    880:    char_u      *p;
                    881:    int         attempt;
                    882:    regexp      *prog;
                    883:
                    884:    *num_file = 0;                  /* return values in case of FAIL */
                    885:    *file = NULL;
                    886:
                    887:    /*
                    888:     * attempt == 1: try match with    '^', match at start
                    889:     * attempt == 2: try match without '^', match anywhere
                    890:     */
                    891:    for (attempt = 1; attempt <= 2; ++attempt)
                    892:    {
                    893:        if (attempt == 2)
                    894:        {
                    895:            if (*pat != '^')        /* there's no '^', no need to try again */
                    896:                break;
                    897:            ++pat;                  /* skip the '^' */
                    898:        }
                    899:        prog = vim_regcomp(pat);
                    900:        if (prog == NULL)
                    901:            return FAIL;
                    902:
                    903:        /*
                    904:         * round == 1: Count the matches.
                    905:         * round == 2: Build the array to keep the matches.
                    906:         */
                    907:        for (round = 1; round <= 2; ++round)
                    908:        {
                    909:            count = 0;
                    910:            for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                    911:            {
                    912:                p = buflist_match(prog, buf);
                    913:                if (p != NULL)
                    914:                {
                    915:                    if (round == 1)
                    916:                        ++count;
                    917:                    else
                    918:                    {
                    919:                        if (options & WILD_HOME_REPLACE)
                    920:                            p = home_replace_save(buf, p);
                    921:                        else
                    922:                            p = strsave(p);
                    923:                        (*file)[count++] = p;
                    924:                    }
                    925:                }
                    926:            }
                    927:            if (count == 0)     /* no match found, break here */
                    928:                break;
                    929:            if (round == 1)
                    930:            {
                    931:                *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *)));
                    932:                if (*file == NULL)
                    933:                {
                    934:                    vim_free(prog);
                    935:                    return FAIL;
                    936:                }
                    937:            }
                    938:        }
                    939:        vim_free(prog);
                    940:        if (count)              /* match(es) found, break here */
                    941:            break;
                    942:    }
                    943:
                    944:    *num_file = count;
                    945:    return (count == 0 ? FAIL : OK);
                    946: }
                    947:
                    948: /*
                    949:  * Check for a match on the file name for buffer "buf" with regex prog "prog".
                    950:  */
                    951:    static char_u *
                    952: buflist_match(prog, buf)
                    953:    regexp      *prog;
                    954:    BUF         *buf;
                    955: {
                    956:    char_u  *match = NULL;
                    957:
                    958:    if (buf->b_sfilename != NULL &&
                    959:                               vim_regexec(prog, buf->b_sfilename, TRUE) != 0)
                    960:        match = buf->b_sfilename;
                    961:    else if (buf->b_filename != NULL)
                    962:    {
                    963:        if (vim_regexec(prog, buf->b_filename, TRUE) != 0)
                    964:            match = buf->b_filename;
                    965:        else
                    966:        {
                    967:            home_replace(NULL, buf->b_filename, NameBuff, MAXPATHL);
                    968:            if (vim_regexec(prog, NameBuff, TRUE) != 0)
                    969:                match = buf->b_filename;
                    970:        }
                    971:    }
                    972:    return match;
                    973: }
                    974:
                    975: /*
                    976:  * find file in buffer name list by number
                    977:  */
                    978:    BUF *
                    979: buflist_findnr(nr)
                    980:    int         nr;
                    981: {
                    982:    BUF         *buf;
                    983:
                    984:    if (nr == 0)
                    985:        nr = curwin->w_alt_fnum;
                    986:    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                    987:        if (buf->b_fnum == nr)
                    988:            return (buf);
                    989:    return NULL;
                    990: }
                    991:
                    992: /*
                    993:  * get name of file 'n' in the buffer list
                    994:  */
                    995:    char_u *
                    996: buflist_nr2name(n, fullname, helptail)
                    997:    int n;
                    998:    int fullname;
                    999:    int helptail;           /* for help buffers return tail only */
                   1000: {
                   1001:    BUF     *buf;
                   1002:    char_u  *fname;
                   1003:
                   1004:    buf = buflist_findnr(n);
                   1005:    if (buf == NULL)
                   1006:        return NULL;
                   1007:    if (fullname)
                   1008:        fname = buf->b_filename;
                   1009:    else
                   1010:        fname = buf->b_xfilename;
                   1011:    home_replace(helptail ? buf : NULL, fname, NameBuff, MAXPATHL);
                   1012:    return NameBuff;
                   1013: }
                   1014:
                   1015: /*
                   1016:  * set the lnum for the buffer 'buf' and the current window
                   1017:  */
                   1018:    static void
                   1019: buflist_setlnum(buf, lnum)
                   1020:    BUF         *buf;
                   1021:    linenr_t    lnum;
                   1022: {
                   1023:    WINLNUM     *wlp;
                   1024:
                   1025:    for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
                   1026:        if (wlp->wl_win == curwin)
                   1027:            break;
                   1028:    if (wlp == NULL)            /* make new entry */
                   1029:    {
                   1030:        wlp = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
                   1031:        if (wlp == NULL)
                   1032:            return;
                   1033:        wlp->wl_win = curwin;
                   1034:    }
                   1035:    else                        /* remove entry from list */
                   1036:    {
                   1037:        if (wlp->wl_prev)
                   1038:            wlp->wl_prev->wl_next = wlp->wl_next;
                   1039:        else
                   1040:            buf->b_winlnum = wlp->wl_next;
                   1041:        if (wlp->wl_next)
                   1042:            wlp->wl_next->wl_prev = wlp->wl_prev;
                   1043:    }
                   1044:    wlp->wl_lnum = lnum;
                   1045: /*
                   1046:  * insert entry in front of the list
                   1047:  */
                   1048:    wlp->wl_next = buf->b_winlnum;
                   1049:    buf->b_winlnum = wlp;
                   1050:    wlp->wl_prev = NULL;
                   1051:    if (wlp->wl_next)
                   1052:        wlp->wl_next->wl_prev = wlp;
                   1053:
                   1054:    return;
                   1055: }
                   1056:
                   1057: /*
                   1058:  * find the lnum for the buffer 'buf' for the current window
                   1059:  */
                   1060:    static linenr_t
                   1061: buflist_findlnum(buf)
                   1062:    BUF     *buf;
                   1063: {
                   1064:    WINLNUM     *wlp;
                   1065:
                   1066:    for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
                   1067:        if (wlp->wl_win == curwin)
                   1068:            break;
                   1069:
                   1070:    if (wlp == NULL)        /* if no lnum for curwin, use the first in the list */
                   1071:        wlp = buf->b_winlnum;
                   1072:
                   1073:    if (wlp)
                   1074:        return wlp->wl_lnum;
                   1075:    else
                   1076:        return (linenr_t)1;
                   1077: }
                   1078:
                   1079: /*
                   1080:  * list all know file names (for :files and :buffers command)
                   1081:  */
                   1082:    void
                   1083: buflist_list()
                   1084: {
                   1085:    BUF         *buf;
                   1086:    int         len;
                   1087:
                   1088:    for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next)
                   1089:    {
                   1090:        msg_outchar('\n');
                   1091:        if (buf->b_xfilename == NULL)
                   1092:            STRCPY(NameBuff, "No File");
                   1093:        else
                   1094:            /* careful: home_replace calls vim_getenv(), which uses IObuff! */
                   1095:            home_replace(buf, buf->b_xfilename, NameBuff, MAXPATHL);
                   1096:
                   1097:        sprintf((char *)IObuff, "%3d %c%c%c \"",
                   1098:                buf->b_fnum,
                   1099:                buf == curbuf ? '%' :
                   1100:                        (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
                   1101:                buf->b_ml.ml_mfp == NULL ? '-' :
                   1102:                        (buf->b_nwindows == 0 ? 'h' : ' '),
                   1103:                buf->b_changed ? '+' : ' ');
                   1104:
                   1105:        len = STRLEN(IObuff);
                   1106:        STRNCPY(IObuff + len, NameBuff, IOSIZE - 20 - len);
                   1107:
                   1108:        len = STRLEN(IObuff);
                   1109:        IObuff[len++] = '"';
                   1110:        /*
                   1111:         * try to put the "line" strings in column 40
                   1112:         */
                   1113:        do
                   1114:        {
                   1115:            IObuff[len++] = ' ';
                   1116:        } while (len < 40 && len < IOSIZE - 18);
                   1117:        sprintf((char *)IObuff + len, "line %ld",
                   1118:                buf == curbuf ? curwin->w_cursor.lnum :
                   1119:                                (long)buflist_findlnum(buf));
                   1120:        msg_outtrans(IObuff);
                   1121:        flushbuf();         /* output one line at a time */
                   1122:        mch_breakcheck();
                   1123:    }
                   1124: }
                   1125:
                   1126: /*
                   1127:  * get file name and line number for file 'fnum'
                   1128:  * used by DoOneCmd() for translating '%' and '#'
                   1129:  * return FAIL if not found, OK for success
                   1130:  */
                   1131:    int
                   1132: buflist_name_nr(fnum, fname, lnum)
                   1133:    int         fnum;
                   1134:    char_u      **fname;
                   1135:    linenr_t    *lnum;
                   1136: {
                   1137:    BUF         *buf;
                   1138:
                   1139:    buf = buflist_findnr(fnum);
                   1140:    if (buf == NULL || buf->b_filename == NULL)
                   1141:        return FAIL;
                   1142:
                   1143:    if (did_cd)
                   1144:        *fname = buf->b_filename;
                   1145:    else
                   1146:        *fname = buf->b_sfilename;
                   1147:    *lnum = buflist_findlnum(buf);
                   1148:
                   1149:    return OK;
                   1150: }
                   1151:
                   1152: /*
                   1153:  * Set the current file name to 's', short file name to 'ss'.
                   1154:  * The file name with the full path is also remembered, for when :cd is used.
                   1155:  * Returns FAIL for failure (file name already in use by other buffer)
                   1156:  *         OK otherwise.
                   1157:  */
                   1158:    int
                   1159: setfname(fname, sfname, message)
                   1160:    char_u *fname, *sfname;
                   1161:    int     message;
                   1162: {
                   1163:    BUF     *buf;
                   1164:
                   1165:    if (fname == NULL || *fname == NUL)
                   1166:    {
                   1167:        vim_free(curbuf->b_filename);
                   1168:        vim_free(curbuf->b_sfilename);
                   1169:        curbuf->b_filename = NULL;
                   1170:        curbuf->b_sfilename = NULL;
                   1171:    }
                   1172:    else
                   1173:    {
                   1174:        fname_expand(&fname, &sfname);
                   1175: #ifdef USE_FNAME_CASE
                   1176: # ifdef USE_LONG_FNAME
                   1177:        if (USE_LONG_FNAME)
                   1178: # endif
                   1179:            fname_case(sfname);     /* set correct case for short filename */
                   1180: #endif
                   1181:        /*
                   1182:         * if the file name is already used in another buffer:
                   1183:         * - if the buffer is loaded, fail
                   1184:         * - if the buffer is not loaded, delete it from the list
                   1185:         */
                   1186:        buf = buflist_findname(fname);
                   1187:        if (buf != NULL && buf != curbuf)
                   1188:        {
                   1189:            if (buf->b_ml.ml_mfp != NULL)       /* it's loaded, fail */
                   1190:            {
                   1191:                if (message)
                   1192:                    EMSG("Buffer with this name already exists");
                   1193:                return FAIL;
                   1194:            }
                   1195:            close_buffer(NULL, buf, TRUE, TRUE);    /* delete from the list */
                   1196:        }
                   1197:        fname = strsave(fname);
                   1198:        sfname = strsave(sfname);
                   1199:        if (fname == NULL || sfname == NULL)
                   1200:        {
                   1201:            vim_free(sfname);
                   1202:            vim_free(fname);
                   1203:            return FAIL;
                   1204:        }
                   1205:        vim_free(curbuf->b_filename);
                   1206:        vim_free(curbuf->b_sfilename);
                   1207:        curbuf->b_filename = fname;
                   1208:        curbuf->b_sfilename = sfname;
                   1209:    }
                   1210:    if (did_cd)
                   1211:        curbuf->b_xfilename = curbuf->b_filename;
                   1212:    else
                   1213:        curbuf->b_xfilename = curbuf->b_sfilename;
                   1214:
                   1215: #ifndef SHORT_FNAME
                   1216:    curbuf->b_shortname = FALSE;
                   1217: #endif
                   1218:    /*
                   1219:     * If the file name changed, also change the name of the swapfile
                   1220:     */
                   1221:    if (curbuf->b_ml.ml_mfp != NULL)
                   1222:        ml_setname();
                   1223:
                   1224:    check_arg_idx();            /* check file name for arg list */
                   1225:    maketitle();                /* set window title */
                   1226:    status_redraw_all();        /* status lines need to be redrawn */
                   1227:    fmarks_check_names(curbuf); /* check named file marks */
                   1228:    ml_timestamp(curbuf);       /* reset timestamp */
                   1229:    return OK;
                   1230: }
                   1231:
                   1232: /*
                   1233:  * set alternate file name for current window
                   1234:  *
                   1235:  * used by dowrite() and do_ecmd()
                   1236:  */
                   1237:    void
                   1238: setaltfname(fname, sfname, lnum)
                   1239:    char_u      *fname;
                   1240:    char_u      *sfname;
                   1241:    linenr_t    lnum;
                   1242: {
                   1243:    BUF     *buf;
                   1244:
                   1245:    buf = buflist_new(fname, sfname, lnum, FALSE);
                   1246:    if (buf != NULL)
                   1247:        curwin->w_alt_fnum = buf->b_fnum;
                   1248: }
                   1249:
                   1250: /*
                   1251:  * add a file name to the buflist and return its number
                   1252:  *
                   1253:  * used by qf_init(), main() and doarglist()
                   1254:  */
                   1255:    int
                   1256: buflist_add(fname)
                   1257:    char_u      *fname;
                   1258: {
                   1259:    BUF     *buf;
                   1260:
                   1261:    buf = buflist_new(fname, NULL, (linenr_t)0, FALSE);
                   1262:    if (buf != NULL)
                   1263:        return buf->b_fnum;
                   1264:    return 0;
                   1265: }
                   1266:
                   1267: /*
                   1268:  * set alternate lnum for current window
                   1269:  */
                   1270:    void
                   1271: buflist_altlnum()
                   1272: {
                   1273:    buflist_setlnum(curbuf, curwin->w_cursor.lnum);
                   1274: }
                   1275:
                   1276: /*
                   1277:  * return nonzero if 'fname' is not the same file as current file
                   1278:  * fname must have a full path (expanded by FullName)
                   1279:  */
                   1280:    int
                   1281: otherfile(fname)
                   1282:    char_u  *fname;
                   1283: {                                  /* no name is different */
                   1284:    if (fname == NULL || *fname == NUL || curbuf->b_filename == NULL)
                   1285:        return TRUE;
                   1286:    return fnamecmp(fname, curbuf->b_filename);
                   1287: }
                   1288:
                   1289:    void
                   1290: fileinfo(fullname, shorthelp, dont_truncate)
                   1291:    int fullname;
                   1292:    int shorthelp;
                   1293:    int dont_truncate;
                   1294: {
                   1295:    char_u      *name;
                   1296:    int         n;
                   1297:    char_u      *p;
                   1298:    char_u      *buffer;
                   1299:
                   1300:    buffer = alloc(IOSIZE);
                   1301:    if (buffer == NULL)
                   1302:        return;
                   1303:
                   1304:    if (fullname > 1)       /* 2 CTRL-G: include buffer number */
                   1305:    {
                   1306:        sprintf((char *)buffer, "buf %d: ", curbuf->b_fnum);
                   1307:        p = buffer + STRLEN(buffer);
                   1308:    }
                   1309:    else
                   1310:        p = buffer;
                   1311:
                   1312:    *p++ = '"';
                   1313:    if (curbuf->b_filename == NULL)
                   1314:        STRCPY(p, "No File");
                   1315:    else
                   1316:    {
                   1317:        if (!fullname && curbuf->b_sfilename != NULL)
                   1318:            name = curbuf->b_sfilename;
                   1319:        else
                   1320:            name = curbuf->b_filename;
                   1321:        home_replace(shorthelp ? curbuf : NULL, name, p,
                   1322:                                                (int)(IOSIZE - (p - buffer)));
                   1323:    }
                   1324:
                   1325:    sprintf((char *)buffer + STRLEN(buffer),
                   1326:            "\"%s%s%s%s",
                   1327:            curbuf->b_changed ? (shortmess(SHM_MOD) ?
                   1328:                                                " [+]" : " [Modified]") : " ",
                   1329:            curbuf->b_notedited ? "[Not edited]" : "",
                   1330:            curbuf->b_p_ro ? (shortmess(SHM_RO) ? "[RO]" : "[readonly]") : "",
                   1331:            (curbuf->b_changed || curbuf->b_notedited || curbuf->b_p_ro) ?
                   1332:                                                                    " " : "");
                   1333:    n = (int)(((long)curwin->w_cursor.lnum * 100L) /
                   1334:                                            (long)curbuf->b_ml.ml_line_count);
                   1335:    if (curbuf->b_ml.ml_flags & ML_EMPTY)
                   1336:    {
                   1337:        STRCPY(buffer + STRLEN(buffer), no_lines_msg);
                   1338:    }
                   1339:    else if (p_ru)
                   1340:    {
                   1341:        /* Current line and column are already on the screen -- webb */
                   1342:        sprintf((char *)buffer + STRLEN(buffer),
                   1343:            "%ld line%s --%d%%--",
                   1344:            (long)curbuf->b_ml.ml_line_count,
                   1345:            plural((long)curbuf->b_ml.ml_line_count),
                   1346:            n);
                   1347:    }
                   1348:    else
                   1349:    {
                   1350:        sprintf((char *)buffer + STRLEN(buffer),
                   1351:            "line %ld of %ld --%d%%-- col ",
                   1352:            (long)curwin->w_cursor.lnum,
                   1353:            (long)curbuf->b_ml.ml_line_count,
                   1354:            n);
                   1355:        col_print(buffer + STRLEN(buffer),
                   1356:                   (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
                   1357:    }
                   1358:
1.2     ! downsj   1359:    (void)append_arg_number(buffer, !shortmess(SHM_FILE), IOSIZE);
1.1       downsj   1360:
                   1361:    if (dont_truncate)
                   1362:        msg(buffer);
                   1363:    else
                   1364:        msg_trunc(buffer);
                   1365:
                   1366:    vim_free(buffer);
                   1367: }
                   1368:
                   1369: /*
                   1370:  * Give some info about the position of the cursor (for "g CTRL-G").
                   1371:  */
                   1372:    void
                   1373: cursor_pos_info()
                   1374: {
                   1375:    char_u      *p;
                   1376:    char_u      buf1[20];
                   1377:    char_u      buf2[20];
                   1378:    linenr_t    lnum;
                   1379:    long        char_count = 0;
                   1380:    long        char_count_cursor = 0;
                   1381:    int     eol_size;
                   1382:
                   1383:    /*
                   1384:     * Compute the length of the file in characters.
                   1385:     */
                   1386:    if (curbuf->b_ml.ml_flags & ML_EMPTY)
                   1387:    {
                   1388:        MSG(no_lines_msg);
                   1389:    }
                   1390:    else
                   1391:    {
                   1392:        if (curbuf->b_p_tx)
                   1393:            eol_size = 2;
                   1394:        else
                   1395:            eol_size = 1;
                   1396:        for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
                   1397:        {
                   1398:            if (lnum == curwin->w_cursor.lnum)
                   1399:                char_count_cursor = char_count + curwin->w_cursor.col + 1;
                   1400:            char_count += STRLEN(ml_get(lnum)) + eol_size;
                   1401:        }
                   1402:        if (!curbuf->b_p_eol && curbuf->b_p_bin)
                   1403:            char_count -= eol_size;
                   1404:
                   1405:        p = ml_get_curline();
                   1406:        col_print(buf1, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
                   1407:        col_print(buf2, (int)STRLEN(p), linetabsize(p));
                   1408:
                   1409:        sprintf((char *)IObuff, "Col %s of %s; Line %ld of %ld; Char %ld of %ld",
                   1410:                (char *)buf1, (char *)buf2,
                   1411:                (long)curwin->w_cursor.lnum, (long)curbuf->b_ml.ml_line_count,
                   1412:                char_count_cursor, char_count);
                   1413:        msg(IObuff);
                   1414:    }
                   1415: }
                   1416:
                   1417:    void
                   1418: col_print(buf, col, vcol)
                   1419:    char_u  *buf;
                   1420:    int     col;
                   1421:    int     vcol;
                   1422: {
                   1423:    if (col == vcol)
                   1424:        sprintf((char *)buf, "%d", col);
                   1425:    else
                   1426:        sprintf((char *)buf, "%d-%d", col, vcol);
                   1427: }
                   1428:
                   1429: /*
                   1430:  * put filename in title bar of window and in icon title
                   1431:  */
                   1432:
                   1433: static char_u *lasttitle = NULL;
                   1434: static char_u *lasticon = NULL;
                   1435:
                   1436:    void
                   1437: maketitle()
                   1438: {
                   1439:    char_u      *t_name;
                   1440:    char_u      *i_name;
1.2     ! downsj   1441:    int         maxlen;
        !          1442:    int         len;
1.1       downsj   1443:
                   1444:    if (curbuf->b_filename == NULL)
                   1445:    {
1.2     ! downsj   1446:        t_name = (char_u *)"VIM -";
1.1       downsj   1447:        i_name = (char_u *)"No File";
                   1448:    }
                   1449:    else
                   1450:    {
1.2     ! downsj   1451:        STRCPY(IObuff, "VIM - ");
        !          1452:        home_replace(curbuf, curbuf->b_filename, IObuff + 6, IOSIZE - 6);
        !          1453:        append_arg_number(IObuff, FALSE, IOSIZE);
        !          1454:        if (p_titlelen > 0)
        !          1455:        {
        !          1456:            maxlen = p_titlelen * Columns / 100;
        !          1457:            if (maxlen < 10)
        !          1458:                maxlen = 10;
        !          1459:            len = STRLEN(IObuff);
        !          1460:            if (len > maxlen)
        !          1461:            {
        !          1462:                vim_memmove(IObuff + 6, IObuff + 6 + len - maxlen,
        !          1463:                                                          (size_t)maxlen - 5);
        !          1464:                IObuff[5] = '<';
        !          1465:            }
        !          1466:        }
1.1       downsj   1467:        t_name = IObuff;
                   1468:        i_name = gettail(curbuf->b_filename);   /* use filename only for icon */
                   1469:    }
                   1470:
                   1471:    vim_free(lasttitle);
1.2     ! downsj   1472:    if (p_title && (lasttitle = alloc((unsigned)(strsize(t_name) + 1))) != NULL)
1.1       downsj   1473:    {
1.2     ! downsj   1474:        *lasttitle = NUL;
1.1       downsj   1475:        while (*t_name)
                   1476:            STRCAT(lasttitle, transchar(*t_name++));
                   1477:    }
                   1478:    else
                   1479:        lasttitle = NULL;
                   1480:
                   1481:    vim_free(lasticon);
                   1482:    if (p_icon && (lasticon = alloc((unsigned)(strsize(i_name) + 1))) != NULL)
                   1483:    {
                   1484:        *lasticon = NUL;
                   1485:        while (*i_name)
                   1486:            STRCAT(lasticon, transchar(*i_name++));
                   1487:    }
                   1488:    else
                   1489:        lasticon = NULL;
                   1490:
                   1491:    resettitle();
                   1492: }
                   1493:
                   1494: /*
1.2     ! downsj   1495:  * Append (file 2 of 8) to 'buf', if editing more than one file.
        !          1496:  * Return TRUE if it was appended.
1.1       downsj   1497:  */
1.2     ! downsj   1498:    static int
        !          1499: append_arg_number(buf, add_file, maxlen)
1.1       downsj   1500:    char_u  *buf;
1.2     ! downsj   1501:    int     add_file;           /* Add "file" before the arg number */
        !          1502:    int     maxlen;             /* maximum nr of chars in buf */
1.1       downsj   1503: {
1.2     ! downsj   1504:    char_u      *p;
        !          1505:
        !          1506:    if (arg_count <= 1)         /* nothing to do */
        !          1507:        return FALSE;
1.1       downsj   1508:
1.2     ! downsj   1509:    p = buf + STRLEN(buf);      /* go to the end of the buffer */
        !          1510:    if (p - buf + 35 >= maxlen) /* getting too long */
        !          1511:        return FALSE;
        !          1512:    *p++ = ' ';
        !          1513:    *p++ = '(';
1.1       downsj   1514:    if (add_file)
                   1515:    {
1.2     ! downsj   1516:        STRCPY(p, "file ");
        !          1517:        p += 5;
1.1       downsj   1518:    }
1.2     ! downsj   1519:    sprintf((char *)p, curwin->w_arg_idx_invalid ? "(%d) of %d)" :
        !          1520:                               "%d of %d)", curwin->w_arg_idx + 1, arg_count);
        !          1521:    return TRUE;
1.1       downsj   1522: }
                   1523:
                   1524: /*
                   1525:  * Put current window title back (used after calling a shell)
                   1526:  */
                   1527:    void
                   1528: resettitle()
                   1529: {
                   1530:    mch_settitle(lasttitle, lasticon);
                   1531: }
                   1532:
                   1533: /*
                   1534:  * If fname is not a full path, make it a full path
                   1535:  */
                   1536:    char_u  *
                   1537: fix_fname(fname)
                   1538:    char_u  *fname;
                   1539: {
                   1540:    if (fname != NameBuff)          /* if not already expanded */
                   1541:    {
                   1542:        if (!isFullName(fname))
                   1543:        {
                   1544:            (void)FullName(fname, NameBuff, MAXPATHL, FALSE);
                   1545:            fname = NameBuff;
                   1546:        }
                   1547: #ifdef USE_FNAME_CASE
                   1548:        else
                   1549: # ifdef USE_LONG_FNAME
                   1550:            if (USE_LONG_FNAME)
                   1551: # endif
                   1552:        {
                   1553:            STRNCPY(NameBuff, fname, MAXPATHL); /* make copy, it may change */
                   1554:            fname = NameBuff;
                   1555:            fname_case(fname);          /* set correct case for filename */
                   1556:        }
                   1557: #endif
                   1558:    }
                   1559:    return fname;
                   1560: }
                   1561:
                   1562: /*
                   1563:  * make fname a full file name, set sfname to fname if not NULL
                   1564:  */
                   1565:    void
                   1566: fname_expand(fname, sfname)
                   1567:    char_u      **fname;
                   1568:    char_u      **sfname;
                   1569: {
                   1570:    if (*fname == NULL)         /* if no file name given, nothing to do */
                   1571:        return;
                   1572:    if (*sfname == NULL)        /* if no short file name given, use fname */
                   1573:        *sfname = *fname;
                   1574:    *fname = fix_fname(*fname); /* expand to full path */
                   1575: }
                   1576:
                   1577: /*
                   1578:  * do_arg_all: open up to 'count' windows, one for each argument
                   1579:  */
                   1580:    void
                   1581: do_arg_all(count)
                   1582:    int count;
                   1583: {
                   1584:    int     i;
                   1585:
                   1586:    if (arg_count <= 1)
                   1587:    {
                   1588:        /* Don't give this obvious error message. We don't want it when the
                   1589:         * ":all" command is in the .vimrc. */
                   1590:        /* EMSG("Argument list contains less than 2 files"); */
                   1591:        return;
                   1592:    }
1.2     ! downsj   1593:
1.1       downsj   1594:    /*
                   1595:     * 1. close all but first window
                   1596:     * 2. make the desired number of windows
1.2     ! downsj   1597:     * 3. start editing one file in each window
        !          1598:     *    arg_count may change while doing this, because of autocommands.
1.1       downsj   1599:     */
                   1600:    setpcmark();
                   1601:    close_others(FALSE);
                   1602:    curwin->w_arg_idx = 0;
                   1603:    if (count > arg_count || count <= 0)
                   1604:        count = arg_count;
                   1605:    count = make_windows(count);
1.2     ! downsj   1606:
        !          1607: #ifdef AUTOCMD
        !          1608:    /*
        !          1609:     * Don't execute Win/Buf Enter/Leave autocommands here
        !          1610:     */
        !          1611:    ++autocmd_no_enter;
        !          1612:    ++autocmd_no_leave;
        !          1613: #endif
        !          1614:    for (i = 0; i < count && i < arg_count && !got_int; ++i)
1.1       downsj   1615:    {
                   1616:        if (i == arg_count - 1)
                   1617:            arg_had_last = TRUE;
1.2     ! downsj   1618:        curwin->w_arg_idx = i;
        !          1619: #ifdef AUTOCMD
        !          1620:        if (i == 0)     /* first window: do autocmd for leaving this buffer */
        !          1621:            --autocmd_no_leave;
        !          1622: #endif
        !          1623:                                                /* edit file i */
        !          1624:        (void)do_ecmd(0, arg_files[i], NULL, NULL, (linenr_t)1,
        !          1625:                                                     ECMD_HIDE + ECMD_OLDBUF);
        !          1626: #ifdef AUTOCMD
        !          1627:        if (i == 0)
        !          1628:            ++autocmd_no_leave;
        !          1629: #endif
1.1       downsj   1630:        if (curwin->w_next == NULL)             /* just checking */
                   1631:            break;
                   1632:        win_enter(curwin->w_next, FALSE);
1.2     ! downsj   1633:        mch_breakcheck();
1.1       downsj   1634:    }
1.2     ! downsj   1635: #ifdef AUTOCMD
        !          1636:    --autocmd_no_enter;
        !          1637: #endif
1.1       downsj   1638:    win_enter(firstwin, FALSE);                 /* back to first window */
1.2     ! downsj   1639: #ifdef AUTOCMD
        !          1640:    --autocmd_no_leave;
        !          1641: #endif
1.1       downsj   1642: }
                   1643:
                   1644: /*
1.2     ! downsj   1645:  * do_buffer_all: open a window for each buffer
1.1       downsj   1646:  *
                   1647:  * 'count' is the maximum number of windows to open.
                   1648:  * when 'all' is TRUE, also load inactive buffers
                   1649:  */
                   1650:    void
                   1651: do_buffer_all(count, all)
                   1652:    int     count;
                   1653:    int     all;
                   1654: {
                   1655:    int     buf_count;
                   1656:    BUF     *buf;
                   1657:    int     i;
                   1658:
                   1659: /*
                   1660:  * count number of desired windows
                   1661:  */
                   1662:    buf_count = 0;
                   1663:    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
                   1664:        if (all || buf->b_ml.ml_mfp != NULL)
                   1665:            ++buf_count;
                   1666:
                   1667:    if (buf_count == 0)             /* Cannot happen? */
                   1668:    {
                   1669:        EMSG("No relevant entries in buffer list");
                   1670:        return;
                   1671:    }
                   1672:
                   1673:    /*
                   1674:     * 1. close all but first window
                   1675:     * 2. make the desired number of windows
                   1676:     * 3. stuff commands to fill the windows
1.2     ! downsj   1677:     * Watch out for autocommands that delete buffers or windows.
1.1       downsj   1678:     */
                   1679:    close_others(FALSE);
                   1680:    curwin->w_arg_idx = 0;
                   1681:    if (buf_count > count)
                   1682:        buf_count = count;
                   1683:    buf_count = make_windows(buf_count);
1.2     ! downsj   1684:
        !          1685: #ifdef AUTOCMD
        !          1686:    /*
        !          1687:     * Don't execute Win/Buf Enter/Leave autocommands here
        !          1688:     */
        !          1689:    ++autocmd_no_enter;
        !          1690:    ++autocmd_no_leave;
        !          1691: #endif
1.1       downsj   1692:    buf = firstbuf;
                   1693:    for (i = 0; i < buf_count; ++i)
                   1694:    {
1.2     ! downsj   1695:        /* find buffer number to put in this window */
1.1       downsj   1696:        for ( ; buf != NULL; buf = buf->b_next)
                   1697:            if (all || buf->b_ml.ml_mfp != NULL)
                   1698:                break;
                   1699:        if (buf == NULL)            /* Cannot happen? */
                   1700:            break;
1.2     ! downsj   1701:
        !          1702:        /* advance to next window */
1.1       downsj   1703:        if (i != 0)
1.2     ! downsj   1704:        {
        !          1705:            if (curwin->w_next == NULL)         /* just checking */
        !          1706:                break;
        !          1707:            win_enter(curwin->w_next, FALSE);
        !          1708:        }
        !          1709:
        !          1710: #ifdef AUTOCMD
        !          1711:        if (i == 0)     /* first window: do autocmd for leaving this buffer */
        !          1712:            --autocmd_no_leave;
        !          1713: #endif
        !          1714:
        !          1715:        /* get buffer for this window */
        !          1716:        (void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, (int)buf->b_fnum, 0);
        !          1717: #ifdef AUTOCMD
        !          1718:        if (i == 0)
        !          1719:            ++autocmd_no_leave;
        !          1720:        if (!buf_valid(buf))        /* autocommands deleted the buffer!!! */
        !          1721:            break;
        !          1722: #endif
        !          1723:
        !          1724:        mch_breakcheck();
        !          1725:        if (got_int)
        !          1726:        {
        !          1727:            (void)vgetc();      /* only break the file loading, not the rest */
        !          1728:            break;
        !          1729:        }
1.1       downsj   1730:        buf = buf->b_next;
                   1731:    }
1.2     ! downsj   1732: #ifdef AUTOCMD
        !          1733:    --autocmd_no_enter;
        !          1734: #endif
        !          1735:    win_enter(firstwin, FALSE);             /* back to first window */
        !          1736: #ifdef AUTOCMD
        !          1737:    --autocmd_no_leave;
        !          1738: #endif
        !          1739:    if (buf_count > 1)
        !          1740:        win_equal(curwin, FALSE);           /* adjust heights */
1.1       downsj   1741: }
                   1742:
                   1743: /*
                   1744:  * do_modelines() - process mode lines for the current file
                   1745:  *
                   1746:  * Returns immediately if the "ml" option isn't set.
                   1747:  */
                   1748: static int     chk_modeline __ARGS((linenr_t));
                   1749:
                   1750:    void
                   1751: do_modelines()
                   1752: {
                   1753:    linenr_t        lnum;
                   1754:    int             nmlines;
                   1755:
                   1756:    if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
                   1757:        return;
                   1758:
                   1759:    for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines;
                   1760:                                                                       ++lnum)
                   1761:        if (chk_modeline(lnum) == FAIL)
                   1762:            nmlines = 0;
                   1763:
                   1764:    for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines &&
                   1765:                          lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
                   1766:        if (chk_modeline(lnum) == FAIL)
                   1767:            nmlines = 0;
                   1768: }
                   1769:
                   1770: /*
                   1771:  * chk_modeline() - check a single line for a mode string
                   1772:  * Return FAIL if an error encountered.
                   1773:  */
                   1774:    static int
                   1775: chk_modeline(lnum)
                   1776:    linenr_t lnum;
                   1777: {
                   1778:    register char_u *s;
                   1779:    register char_u *e;
                   1780:    char_u          *linecopy;          /* local copy of any modeline found */
                   1781:    int             prev;
                   1782:    int             end;
                   1783:    int             retval = OK;
                   1784:    char_u          *save_sourcing_name;
                   1785:
                   1786:    prev = -1;
                   1787:    for (s = ml_get(lnum); *s != NUL; ++s)
                   1788:    {
                   1789:        if (prev == -1 || vim_isspace(prev))
                   1790:        {
                   1791:            if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0) ||
                   1792:                               STRNCMP(s, "vi:", (size_t)3) == 0 ||
                   1793:                               STRNCMP(s, "vim:", (size_t)4) == 0)
                   1794:                break;
                   1795:        }
                   1796:        prev = *s;
                   1797:    }
                   1798:
                   1799:    if (*s)
                   1800:    {
                   1801:        do                              /* skip over "ex:", "vi:" or "vim:" */
                   1802:            ++s;
                   1803:        while (s[-1] != ':');
                   1804:
                   1805:        s = linecopy = strsave(s);      /* copy the line, it will change */
                   1806:        if (linecopy == NULL)
                   1807:            return FAIL;
                   1808:
                   1809:        sourcing_lnum = lnum;           /* prepare for emsg() */
                   1810:        save_sourcing_name = sourcing_name;
                   1811:        sourcing_name = (char_u *)"modelines";
                   1812:
                   1813:        end = FALSE;
                   1814:        while (end == FALSE)
                   1815:        {
                   1816:            s = skipwhite(s);
                   1817:            if (*s == NUL)
                   1818:                break;
                   1819:
                   1820:            /*
                   1821:             * Find end of set command: ':' or end of line.
                   1822:             */
                   1823:            for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
                   1824:                ;
                   1825:            if (*e == NUL)
                   1826:                end = TRUE;
                   1827:
                   1828:            /*
                   1829:             * If there is a "set" command, require a terminating ':' and
                   1830:             * ignore the stuff after the ':'.
                   1831:             * "vi:set opt opt opt: foo" -- foo not interpreted
                   1832:             * "vi:opt opt opt: foo" -- foo interpreted
                   1833:             */
                   1834:            if (STRNCMP(s, "set ", (size_t)4) == 0)
                   1835:            {
                   1836:                if (*e != ':')          /* no terminating ':'? */
                   1837:                    break;
                   1838:                end = TRUE;
                   1839:                s += 4;
                   1840:            }
                   1841:
                   1842:            *e = NUL;                   /* truncate the set command */
                   1843:            if (do_set(s) == FAIL)      /* stop if error found */
                   1844:            {
                   1845:                retval = FAIL;
                   1846:                break;
                   1847:            }
                   1848:            s = e + 1;                  /* advance to next part */
                   1849:        }
                   1850:
                   1851:        sourcing_lnum = 0;
                   1852:        sourcing_name = save_sourcing_name;
                   1853:
                   1854:        vim_free(linecopy);
                   1855:    }
                   1856:    return retval;
                   1857: }