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

Annotation of src/usr.bin/vim/cmdcmds.c, Revision 1.4

1.4     ! downsj      1: /* $OpenBSD: cmdcmds.c,v 1.3 1996/09/22 01:17:58 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:  * cmdcmds.c: functions for command line commands
                     12:  */
                     13:
                     14: #include "vim.h"
                     15: #include "globals.h"
                     16: #include "proto.h"
                     17: #include "option.h"
                     18:
1.2       downsj     19: static void do_filter __ARGS((linenr_t line1, linenr_t line2,
                     20:                                    char_u *buff, int do_in, int do_out));
1.1       downsj     21: #ifdef VIMINFO
                     22: static char_u *viminfo_filename __ARGS((char_u     *));
1.2       downsj     23: static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info,
                     24:                                             int want_marks, int force_read));
                     25: static int read_viminfo_up_to_marks __ARGS((char_u *line, FILE *fp,
                     26:                                                                int forceit));
1.1       downsj     27: #endif /* VIMINFO */
                     28:
                     29:    void
                     30: do_ascii()
                     31: {
                     32:    int     c;
                     33:    char    buf1[20];
                     34:    char    buf2[20];
                     35:    char_u  buf3[3];
                     36:
                     37:    c = gchar_cursor();
1.2       downsj     38:    if (c == NUL)
                     39:    {
                     40:        MSG("empty line");
                     41:        return;
                     42:    }
1.1       downsj     43:    if (c == NL)            /* NUL is stored as NL */
                     44:        c = NUL;
                     45:    if (isprintchar(c) && (c < ' ' || c > '~'))
                     46:    {
                     47:        transchar_nonprint(buf3, c);
                     48:        sprintf(buf1, "  <%s>", (char *)buf3);
                     49:    }
                     50:    else
                     51:        buf1[0] = NUL;
                     52:    if (c >= 0x80)
                     53:        sprintf(buf2, "  <M-%s>", transchar(c & 0x7f));
                     54:    else
                     55:        buf2[0] = NUL;
                     56:    sprintf((char *)IObuff, "<%s>%s%s  %d,  Hex %02x,  Octal %03o",
                     57:                                           transchar(c), buf1, buf2, c, c, c);
                     58:    msg(IObuff);
                     59: }
                     60:
                     61: /*
                     62:  * align text:
                     63:  * type = -1  left aligned
                     64:  * type = 0   centered
                     65:  * type = 1   right aligned
                     66:  */
                     67:    void
                     68: do_align(start, end, width, type)
                     69:    linenr_t    start;
                     70:    linenr_t    end;
                     71:    int         width;
                     72:    int         type;
                     73: {
                     74:    FPOS    pos;
                     75:    int     len;
                     76:    int     indent = 0;
                     77:    int     new_indent = 0;         /* init for GCC */
                     78:    char_u  *first;
                     79:    char_u  *last;
                     80:    int     save;
                     81:
                     82: #ifdef RIGHTLEFT
                     83:    if (curwin->w_p_rl)
                     84:        type = -type;   /* switch left and right aligning */
                     85: #endif
                     86:
                     87:    pos = curwin->w_cursor;
                     88:    if (type == -1)     /* left align: width is used for new indent */
                     89:    {
                     90:        if (width >= 0)
                     91:            indent = width;
                     92:    }
                     93:    else
                     94:    {
                     95:        /*
                     96:         * if 'textwidth' set, use it
                     97:         * else if 'wrapmargin' set, use it
                     98:         * if invalid value, use 80
                     99:         */
                    100:        if (width <= 0)
                    101:            width = curbuf->b_p_tw;
                    102:        if (width == 0 && curbuf->b_p_wm > 0)
                    103:            width = Columns - curbuf->b_p_wm;
                    104:        if (width <= 0)
                    105:            width = 80;
                    106:    }
                    107:
                    108:    if (u_save((linenr_t)(start - 1), (linenr_t)(end + 1)) == FAIL)
                    109:        return;
                    110:    for (curwin->w_cursor.lnum = start;
                    111:                        curwin->w_cursor.lnum <= end; ++curwin->w_cursor.lnum)
                    112:    {
                    113:            /* find the first non-blank character */
                    114:        first = skipwhite(ml_get_curline());
                    115:            /* find the character after the last non-blank character */
                    116:        for (last = first + STRLEN(first);
                    117:                                last > first && vim_iswhite(last[-1]); --last)
                    118:            ;
                    119:        save = *last;
                    120:        *last = NUL;
                    121:        len = linetabsize(first);                   /* get line length */
                    122:        *last = save;
                    123:        if (len == 0)                               /* skip blank lines */
                    124:            continue;
                    125:        switch (type)
                    126:        {
                    127:            case -1:    new_indent = indent;            /* left align */
                    128:                        break;
                    129:            case 0:     new_indent = (width - len) / 2; /* center */
                    130:                        break;
                    131:            case 1:     new_indent = width - len;       /* right align */
                    132:                        break;
                    133:        }
                    134:        if (new_indent < 0)
                    135:            new_indent = 0;
                    136:        set_indent(new_indent, TRUE);           /* set indent */
                    137:    }
                    138:    curwin->w_cursor = pos;
                    139:    beginline(TRUE);
                    140:    updateScreen(NOT_VALID);
                    141: }
                    142:
                    143:    void
1.2       downsj    144: do_retab(start, end, new_ts, forceit)
1.1       downsj    145:    linenr_t    start;
                    146:    linenr_t    end;
                    147:    int         new_ts;
1.2       downsj    148:    int         forceit;
1.1       downsj    149: {
                    150:    linenr_t    lnum;
                    151:    int         got_tab = FALSE;
                    152:    long        num_spaces = 0;
                    153:    long        num_tabs;
                    154:    long        len;
                    155:    long        col;
                    156:    long        vcol;
                    157:    long        start_col = 0;          /* For start of white-space string */
                    158:    long        start_vcol = 0;         /* For start of white-space string */
                    159:    int         temp;
                    160:    long        old_len;
                    161:    char_u      *ptr;
                    162:    char_u      *new_line = (char_u *)1;    /* init to non-NULL */
                    163:    int         did_something = FALSE;
                    164:    int         did_undo;               /* called u_save for current line */
                    165:
                    166:    if (new_ts == 0)
                    167:        new_ts = curbuf->b_p_ts;
                    168:    for (lnum = start; !got_int && lnum <= end; ++lnum)
                    169:    {
                    170:        ptr = ml_get(lnum);
                    171:        col = 0;
                    172:        vcol = 0;
                    173:        did_undo = FALSE;
                    174:        for (;;)
                    175:        {
                    176:            if (vim_iswhite(ptr[col]))
                    177:            {
                    178:                if (!got_tab && num_spaces == 0)
                    179:                {
                    180:                    /* First consecutive white-space */
                    181:                    start_vcol = vcol;
                    182:                    start_col = col;
                    183:                }
                    184:                if (ptr[col] == ' ')
                    185:                    num_spaces++;
                    186:                else
                    187:                    got_tab = TRUE;
                    188:            }
                    189:            else
                    190:            {
1.2       downsj    191:                if (got_tab || (forceit && num_spaces > 1))
1.1       downsj    192:                {
                    193:                    /* Retabulate this string of white-space */
                    194:
                    195:                    /* len is virtual length of white string */
                    196:                    len = num_spaces = vcol - start_vcol;
                    197:                    num_tabs = 0;
                    198:                    if (!curbuf->b_p_et)
                    199:                    {
                    200:                        temp = new_ts - (start_vcol % new_ts);
                    201:                        if (num_spaces >= temp)
                    202:                        {
                    203:                            num_spaces -= temp;
                    204:                            num_tabs++;
                    205:                        }
                    206:                        num_tabs += num_spaces / new_ts;
                    207:                        num_spaces -= (num_spaces / new_ts) * new_ts;
                    208:                    }
                    209:                    if (curbuf->b_p_et || got_tab ||
                    210:                                        (num_spaces + num_tabs < len))
                    211:                    {
                    212:                        if (did_undo == FALSE)
                    213:                        {
                    214:                            did_undo = TRUE;
                    215:                            if (u_save((linenr_t)(lnum - 1),
                    216:                                                (linenr_t)(lnum + 1)) == FAIL)
                    217:                            {
                    218:                                new_line = NULL;        /* flag out-of-memory */
                    219:                                break;
                    220:                            }
                    221:                        }
                    222:
                    223:                        /* len is actual number of white characters used */
                    224:                        len = num_spaces + num_tabs;
                    225:                        old_len = STRLEN(ptr);
                    226:                        new_line = lalloc(old_len - col + start_col + len + 1,
                    227:                                                                        TRUE);
                    228:                        if (new_line == NULL)
                    229:                            break;
                    230:                        if (start_col > 0)
                    231:                            vim_memmove(new_line, ptr, (size_t)start_col);
                    232:                        vim_memmove(new_line + start_col + len,
                    233:                                      ptr + col, (size_t)(old_len - col + 1));
                    234:                        ptr = new_line + start_col;
                    235:                        for (col = 0; col < len; col++)
                    236:                            ptr[col] = (col < num_tabs) ? '\t' : ' ';
                    237:                        ml_replace(lnum, new_line, FALSE);
                    238:                        did_something = TRUE;
                    239:                        ptr = new_line;
                    240:                        col = start_col + len;
                    241:                    }
                    242:                }
                    243:                got_tab = FALSE;
                    244:                num_spaces = 0;
                    245:            }
                    246:            if (ptr[col] == NUL)
                    247:                break;
                    248:            vcol += chartabsize(ptr[col++], (colnr_t)vcol);
                    249:        }
                    250:        if (new_line == NULL)               /* out of memory */
                    251:            break;
                    252:        line_breakcheck();
                    253:    }
                    254:    if (got_int)
                    255:        emsg(e_interr);
                    256:    if (did_something)
                    257:        CHANGED;
                    258:    curbuf->b_p_ts = new_ts;
                    259:    coladvance(curwin->w_curswant);
                    260: }
                    261:
                    262: /*
                    263:  * :move command - move lines line1-line2 to line n
                    264:  *
                    265:  * return FAIL for failure, OK otherwise
                    266:  */
                    267:    int
                    268: do_move(line1, line2, n)
                    269:    linenr_t    line1;
                    270:    linenr_t    line2;
                    271:    linenr_t    n;
                    272: {
                    273:    char_u      *str;
                    274:    linenr_t    l;
                    275:    linenr_t    extra;      /* Num lines added before line1 */
                    276:    linenr_t    num_lines;  /* Num lines moved */
                    277:    linenr_t    last_line;  /* Last line in file after adding new text */
                    278:    int         has_mark;
                    279:
                    280:    if (n >= line1 && n < line2)
                    281:    {
                    282:        EMSG("Move lines into themselves");
                    283:        return FAIL;
                    284:    }
                    285:
                    286:    num_lines = line2 - line1 + 1;
                    287:
                    288:    /*
                    289:     * First we copy the old text to its new location -- webb
                    290:     */
                    291:    if (u_save(n, n + 1) == FAIL)
                    292:        return FAIL;
                    293:    for (extra = 0, l = line1; l <= line2; l++)
                    294:    {
                    295:        str = strsave(ml_get(l + extra));
                    296:        if (str != NULL)
                    297:        {
                    298:            has_mark = ml_has_mark(l + extra);
                    299:            ml_append(n + l - line1, str, (colnr_t)0, FALSE);
                    300:            vim_free(str);
                    301:            if (has_mark)
                    302:                ml_setmarked(n + l - line1 + 1);
                    303:            if (n < line1)
                    304:                extra++;
                    305:        }
                    306:    }
                    307:
                    308:    /*
                    309:     * Now we must be careful adjusting our marks so that we don't overlap our
                    310:     * mark_adjust() calls.
                    311:     *
                    312:     * We adjust the marks within the old text so that they refer to the
                    313:     * last lines of the file (temporarily), because we know no other marks
                    314:     * will be set there since these line numbers did not exist until we added
                    315:     * our new lines.
                    316:     *
                    317:     * Then we adjust the marks on lines between the old and new text positions
                    318:     * (either forwards or backwards).
                    319:     *
                    320:     * And Finally we adjust the marks we put at the end of the file back to
                    321:     * their final destination at the new text position -- webb
                    322:     */
                    323:    last_line = curbuf->b_ml.ml_line_count;
                    324:    mark_adjust(line1, line2, last_line - line2, 0L);
                    325:    if (n >= line2)
                    326:        mark_adjust(line2 + 1, n, -num_lines, 0L);
                    327:    else
                    328:        mark_adjust(n + 1, line1 - 1, num_lines, 0L);
                    329:    mark_adjust(last_line - num_lines + 1, last_line,
                    330:                                                -(last_line - n - extra), 0L);
                    331:
                    332:    /*
                    333:     * Now we delete the original text -- webb
                    334:     */
                    335:    if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
                    336:        return FAIL;
                    337:
                    338:    for (l = line1; l <= line2; l++)
                    339:        ml_delete(line1 + extra, TRUE);
                    340:
                    341:    CHANGED;
                    342:    if (!global_busy && num_lines > p_report)
                    343:        smsg((char_u *)"%ld line%s moved", num_lines, plural(num_lines));
1.4     ! downsj    344:
        !           345:    /*
        !           346:     * Leave the cursor on the last of the moved lines.
        !           347:     */
        !           348:    if (n >= line1)
        !           349:        curwin->w_cursor.lnum = n;
        !           350:    else
        !           351:        curwin->w_cursor.lnum = n + (line2 - line1) + 1;
        !           352:
1.1       downsj    353:    return OK;
                    354: }
                    355:
                    356: /*
                    357:  * :copy command - copy lines line1-line2 to line n
                    358:  */
                    359:    void
                    360: do_copy(line1, line2, n)
                    361:    linenr_t    line1;
                    362:    linenr_t    line2;
                    363:    linenr_t    n;
                    364: {
                    365:    linenr_t        lnum;
                    366:    char_u          *p;
                    367:
                    368:    mark_adjust(n + 1, MAXLNUM, line2 - line1 + 1, 0L);
                    369:
                    370:    /*
                    371:     * there are three situations:
                    372:     * 1. destination is above line1
                    373:     * 2. destination is between line1 and line2
                    374:     * 3. destination is below line2
                    375:     *
                    376:     * n = destination (when starting)
                    377:     * curwin->w_cursor.lnum = destination (while copying)
                    378:     * line1 = start of source (while copying)
                    379:     * line2 = end of source (while copying)
                    380:     */
                    381:    if (u_save(n, n + 1) == FAIL)
                    382:        return;
                    383:    curwin->w_cursor.lnum = n;
                    384:    lnum = line2 - line1 + 1;
                    385:    while (line1 <= line2)
                    386:    {
                    387:        /* need to use strsave() because the line will be unlocked
                    388:            within ml_append */
                    389:        p = strsave(ml_get(line1));
                    390:        if (p != NULL)
                    391:        {
                    392:            ml_append(curwin->w_cursor.lnum, p, (colnr_t)0, FALSE);
                    393:            vim_free(p);
                    394:        }
                    395:                /* situation 2: skip already copied lines */
                    396:        if (line1 == n)
                    397:            line1 = curwin->w_cursor.lnum;
                    398:        ++line1;
                    399:        if (curwin->w_cursor.lnum < line1)
                    400:            ++line1;
                    401:        if (curwin->w_cursor.lnum < line2)
                    402:            ++line2;
                    403:        ++curwin->w_cursor.lnum;
                    404:    }
                    405:    CHANGED;
                    406:    msgmore((long)lnum);
                    407: }
                    408:
                    409: /*
                    410:  * Handle the ":!cmd" command.  Also for ":r !cmd" and ":w !cmd"
                    411:  * Bangs in the argument are replaced with the previously entered command.
                    412:  * Remember the argument.
                    413:  */
                    414:    void
                    415: do_bang(addr_count, line1, line2, forceit, arg, do_in, do_out)
                    416:    int         addr_count;
                    417:    linenr_t    line1, line2;
                    418:    int         forceit;
                    419:    char_u      *arg;
                    420:    int         do_in, do_out;
                    421: {
                    422:    static  char_u  *prevcmd = NULL;        /* the previous command */
                    423:    char_u          *newcmd = NULL;         /* the new command */
                    424:    int             ins_prevcmd;
                    425:    char_u          *t;
                    426:    char_u          *p;
                    427:    char_u          *trailarg;
                    428:    int             len;
                    429:    int             scroll_save = msg_scroll;
                    430:
                    431:    /*
                    432:     * Disallow shell commands from .exrc and .vimrc in current directory for
                    433:     * security reasons.
                    434:     */
                    435:    if (secure)
                    436:    {
                    437:        secure = 2;
                    438:        emsg(e_curdir);
                    439:        return;
                    440:    }
                    441:
                    442:    if (addr_count == 0)                /* :! */
                    443:    {
                    444:        msg_scroll = FALSE;         /* don't scroll here */
                    445:        autowrite_all();
                    446:        msg_scroll = scroll_save;
                    447:    }
                    448:
                    449:    /*
                    450:     * Try to find an embedded bang, like in :!<cmd> ! [args]
                    451:     * (:!! is indicated by the 'forceit' variable)
                    452:     */
                    453:    ins_prevcmd = forceit;
                    454:    trailarg = arg;
                    455:    do
                    456:    {
                    457:        len = STRLEN(trailarg) + 1;
                    458:        if (newcmd != NULL)
                    459:            len += STRLEN(newcmd);
                    460:        if (ins_prevcmd)
                    461:        {
                    462:            if (prevcmd == NULL)
                    463:            {
                    464:                emsg(e_noprev);
                    465:                vim_free(newcmd);
                    466:                return;
                    467:            }
                    468:            len += STRLEN(prevcmd);
                    469:        }
                    470:        if ((t = alloc(len)) == NULL)
                    471:        {
                    472:            vim_free(newcmd);
                    473:            return;
                    474:        }
                    475:        *t = NUL;
                    476:        if (newcmd != NULL)
                    477:            STRCAT(t, newcmd);
                    478:        if (ins_prevcmd)
                    479:            STRCAT(t, prevcmd);
                    480:        p = t + STRLEN(t);
                    481:        STRCAT(t, trailarg);
                    482:        vim_free(newcmd);
                    483:        newcmd = t;
                    484:
                    485:        /*
                    486:         * Scan the rest of the argument for '!', which is replaced by the
                    487:         * previous command.  "\!" is replaced by "!" (this is vi compatible).
                    488:         */
                    489:        trailarg = NULL;
                    490:        while (*p)
                    491:        {
                    492:            if (*p == '!')
                    493:            {
                    494:                if (p > newcmd && p[-1] == '\\')
                    495:                    vim_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
                    496:                else
                    497:                {
                    498:                    trailarg = p;
                    499:                    *trailarg++ = NUL;
                    500:                    ins_prevcmd = TRUE;
                    501:                    break;
                    502:                }
                    503:            }
                    504:            ++p;
                    505:        }
                    506:    } while (trailarg != NULL);
                    507:
                    508:    vim_free(prevcmd);
                    509:    prevcmd = newcmd;
                    510:
                    511:    if (bangredo)           /* put cmd in redo buffer for ! command */
                    512:    {
                    513:        AppendToRedobuff(prevcmd);
                    514:        AppendToRedobuff((char_u *)"\n");
                    515:        bangredo = FALSE;
                    516:    }
1.2       downsj    517:    /*
                    518:     * Add quotes around the command, for shells that need them.
                    519:     */
                    520:    if (*p_shq != NUL)
                    521:    {
                    522:        newcmd = alloc((unsigned)(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1));
                    523:        if (newcmd == NULL)
                    524:            return;
                    525:        STRCPY(newcmd, p_shq);
                    526:        STRCAT(newcmd, prevcmd);
                    527:        STRCAT(newcmd, p_shq);
                    528:    }
1.1       downsj    529:    if (addr_count == 0)                /* :! */
                    530:    {
                    531:            /* echo the command */
                    532:        msg_start();
                    533:        msg_outchar(':');
                    534:        msg_outchar('!');
1.2       downsj    535:        msg_outtrans(newcmd);
1.1       downsj    536:        msg_clr_eos();
                    537:        windgoto(msg_row, msg_col);
                    538:
1.2       downsj    539:        do_shell(newcmd);
1.1       downsj    540:    }
                    541:    else                                /* :range! */
1.2       downsj    542:        do_filter(line1, line2, newcmd, do_in, do_out);
                    543:    if (newcmd != prevcmd)
                    544:        vim_free(newcmd);
1.1       downsj    545: }
                    546:
                    547: /*
                    548:  * call a shell to execute a command
                    549:  */
                    550:    void
                    551: do_shell(cmd)
                    552:    char_u  *cmd;
                    553: {
                    554:    BUF     *buf;
                    555:    int     save_nwr;
                    556:
                    557:    /*
                    558:     * Disallow shell commands from .exrc and .vimrc in current directory for
                    559:     * security reasons.
                    560:     */
                    561:    if (secure)
                    562:    {
                    563:        secure = 2;
                    564:        emsg(e_curdir);
                    565:        msg_end();
                    566:        return;
                    567:    }
                    568:
                    569: #ifdef WIN32
                    570:    /*
                    571:     * Check if external commands are allowed now.
                    572:     */
                    573:    if (can_end_termcap_mode(TRUE) == FALSE)
                    574:        return;
                    575: #endif
                    576:
                    577:    /*
                    578:     * For autocommands we want to get the output on the current screen, to
                    579:     * avoid having to type return below.
                    580:     */
                    581:    msg_outchar('\r');                  /* put cursor at start of line */
                    582: #ifdef AUTOCMD
                    583:    if (!autocmd_busy)
                    584: #endif
                    585:        stoptermcap();
                    586:    msg_outchar('\n');                  /* may shift screen one line up */
                    587:
                    588:        /* warning message before calling the shell */
                    589:    if (p_warn
                    590: #ifdef AUTOCMD
                    591:                && !autocmd_busy
                    592: #endif
                    593:                                   )
                    594:        for (buf = firstbuf; buf; buf = buf->b_next)
                    595:            if (buf->b_changed)
                    596:            {
                    597:                MSG_OUTSTR("[No write since last change]\n");
                    598:                break;
                    599:            }
                    600:
                    601: /* This windgoto is required for when the '\n' resulted in a "delete line 1"
                    602:  * command to the terminal. */
                    603:
                    604:    windgoto(msg_row, msg_col);
                    605:    cursor_on();
                    606:    (void)call_shell(cmd, SHELL_COOKED);
                    607:    need_check_timestamps = TRUE;
                    608:
                    609: /*
                    610:  * put the message cursor at the end of the screen, avoids wait_return() to
                    611:  * overwrite the text that the external command showed
                    612:  */
                    613:    msg_pos((int)Rows - 1, 0);
                    614:
                    615: #ifdef AUTOCMD
1.2       downsj    616:    if (autocmd_busy)
                    617:        must_redraw = CLEAR;
                    618:    else
1.1       downsj    619: #endif
                    620:    {
                    621:        /*
                    622:         * If K_TI is defined, we assume that we switch screens when
                    623:         * starttermcap() is called. In that case we really want to wait for
                    624:         * "hit return to continue".
                    625:         */
                    626:        save_nwr = no_wait_return;
                    627:        if (*T_TI != NUL)
                    628:            no_wait_return = FALSE;
                    629: #ifdef AMIGA
                    630:        wait_return(term_console ? -1 : TRUE);      /* see below */
                    631: #else
                    632:        wait_return(TRUE);
                    633: #endif
                    634:        no_wait_return = save_nwr;
                    635:        starttermcap();     /* start termcap if not done by wait_return() */
                    636:
                    637:        /*
                    638:         * In an Amiga window redrawing is caused by asking the window size.
                    639:         * If we got an interrupt this will not work. The chance that the
                    640:         * window size is wrong is very small, but we need to redraw the
                    641:         * screen.  Don't do this if ':' hit in wait_return().  THIS IS UGLY
                    642:         * but it saves an extra redraw.
                    643:         */
                    644: #ifdef AMIGA
                    645:        if (skip_redraw)                /* ':' hit in wait_return() */
                    646:            must_redraw = CLEAR;
                    647:        else if (term_console)
                    648:        {
                    649:            OUTSTR("\033[0 q");         /* get window size */
                    650:            if (got_int)
                    651:                must_redraw = CLEAR;    /* if got_int is TRUE, redraw needed */
                    652:            else
                    653:                must_redraw = 0;        /* no extra redraw needed */
                    654:        }
                    655: #endif /* AMIGA */
                    656:    }
                    657: }
                    658:
                    659: /*
                    660:  * do_filter: filter lines through a command given by the user
                    661:  *
                    662:  * We use temp files and the call_shell() routine here. This would normally
                    663:  * be done using pipes on a UNIX machine, but this is more portable to
                    664:  * non-unix machines. The call_shell() routine needs to be able
                    665:  * to deal with redirection somehow, and should handle things like looking
                    666:  * at the PATH env. variable, and adding reasonable extensions to the
                    667:  * command name given by the user. All reasonable versions of call_shell()
                    668:  * do this.
                    669:  * We use input redirection if do_in is TRUE.
                    670:  * We use output redirection if do_out is TRUE.
                    671:  */
1.2       downsj    672:    static void
1.1       downsj    673: do_filter(line1, line2, buff, do_in, do_out)
                    674:    linenr_t    line1, line2;
                    675:    char_u      *buff;
                    676:    int         do_in, do_out;
                    677: {
1.2       downsj    678:    char_u      *itmp = NULL;
                    679:    char_u      *otmp = NULL;
1.1       downsj    680:    linenr_t    linecount;
                    681:    FPOS        cursor_save;
1.2       downsj    682: #ifdef AUTOCMD
                    683:    BUF         *old_curbuf = curbuf;
                    684: #endif
1.1       downsj    685:
                    686:    /*
                    687:     * Disallow shell commands from .exrc and .vimrc in current directory for
                    688:     * security reasons.
                    689:     */
                    690:    if (secure)
                    691:    {
                    692:        secure = 2;
                    693:        emsg(e_curdir);
                    694:        return;
                    695:    }
                    696:    if (*buff == NUL)       /* no filter command */
                    697:        return;
                    698:
                    699: #ifdef WIN32
                    700:    /*
                    701:     * Check if external commands are allowed now.
                    702:     */
                    703:    if (can_end_termcap_mode(TRUE) == FALSE)
                    704:        return;
                    705: #endif
                    706:
                    707:    cursor_save = curwin->w_cursor;
                    708:    linecount = line2 - line1 + 1;
                    709:    curwin->w_cursor.lnum = line1;
                    710:    curwin->w_cursor.col = 0;
                    711:
                    712:    /*
                    713:     * 1. Form temp file names
                    714:     * 2. Write the lines to a temp file
                    715:     * 3. Run the filter command on the temp file
                    716:     * 4. Read the output of the command into the buffer
                    717:     * 5. Delete the original lines to be filtered
                    718:     * 6. Remove the temp files
                    719:     */
                    720:
1.2       downsj    721:    if ((do_in && (itmp = vim_tempname('i')) == NULL) ||
                    722:                               (do_out && (otmp = vim_tempname('o')) == NULL))
1.1       downsj    723:    {
                    724:        emsg(e_notmp);
1.2       downsj    725:        goto filterend;
1.1       downsj    726:    }
                    727:
                    728: /*
                    729:  * The writing and reading of temp files will not be shown.
                    730:  * Vi also doesn't do this and the messages are not very informative.
                    731:  */
                    732:    ++no_wait_return;           /* don't call wait_return() while busy */
                    733:    if (do_in && buf_write(curbuf, itmp, NULL, line1, line2,
1.2       downsj    734:                                           FALSE, FALSE, FALSE, TRUE) == FAIL)
1.1       downsj    735:    {
                    736:        msg_outchar('\n');                  /* keep message from buf_write() */
                    737:        --no_wait_return;
                    738:        (void)emsg2(e_notcreate, itmp);     /* will call wait_return */
                    739:        goto filterend;
                    740:    }
1.2       downsj    741: #ifdef AUTOCMD
                    742:    if (curbuf != old_curbuf)
                    743:        goto filterend;
                    744: #endif
                    745:
1.1       downsj    746:    if (!do_out)
                    747:        msg_outchar('\n');
                    748:
                    749: #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
                    750: /*
                    751:  * put braces around the command (for concatenated commands)
                    752:  */
                    753:    sprintf((char *)IObuff, "(%s)", (char *)buff);
                    754:    if (do_in)
                    755:    {
                    756:        STRCAT(IObuff, " < ");
                    757:        STRCAT(IObuff, itmp);
                    758:    }
                    759: #else
                    760: /*
                    761:  * for shells that don't understand braces around commands, at least allow
                    762:  * the use of commands in a pipe.
                    763:  */
                    764:    STRCPY(IObuff, buff);
                    765:    if (do_in)
                    766:    {
                    767:        char_u      *p;
                    768:    /*
1.2       downsj    769:     * If there is a pipe, we have to put the '<' in front of it.
                    770:     * Don't do this when 'shellquote' is not empty, otherwise the redirection
                    771:     * would be inside the quotes.
1.1       downsj    772:     */
                    773:        p = vim_strchr(IObuff, '|');
1.2       downsj    774:        if (p && *p_shq == NUL)
1.1       downsj    775:            *p = NUL;
                    776:        STRCAT(IObuff, " < ");
                    777:        STRCAT(IObuff, itmp);
                    778:        p = vim_strchr(buff, '|');
1.2       downsj    779:        if (p && *p_shq == NUL)
1.1       downsj    780:            STRCAT(IObuff, p);
                    781:    }
                    782: #endif
                    783:    if (do_out)
                    784:    {
                    785:        char_u *p;
                    786:
                    787:        if ((p = vim_strchr(p_srr, '%')) != NULL && p[1] == 's')
                    788:        {
                    789:            p = IObuff + STRLEN(IObuff);
                    790:            *p++ = ' '; /* not really needed? Not with sh, ksh or bash */
                    791:            sprintf((char *)p, (char *)p_srr, (char *)otmp);
                    792:        }
                    793:        else
                    794:            sprintf((char *)IObuff + STRLEN(IObuff), " %s %s",
                    795:                                                 (char *)p_srr, (char *)otmp);
                    796:    }
                    797:
                    798:    windgoto((int)Rows - 1, 0);
                    799:    cursor_on();
                    800:
                    801:    /*
                    802:     * When not redirecting the output the command can write anything to the
                    803:     * screen. If 'shellredir' is equal to ">", screen may be messed up by
                    804:     * stderr output of external command. Clear the screen later.
                    805:     * If do_in is FALSE, this could be something like ":r !cat", which may
                    806:     * also mess up the screen, clear it later.
                    807:     */
                    808:    if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
                    809:        must_redraw = CLEAR;
                    810:    else
                    811:        redraw_later(NOT_VALID);
                    812:
                    813:    /*
                    814:     * When call_shell() fails wait_return() is called to give the user a
                    815:     * chance to read the error messages. Otherwise errors are ignored, so you
                    816:     * can see the error messages from the command that appear on stdout; use
                    817:     * 'u' to fix the text
                    818:     * Switch to cooked mode when not redirecting stdin, avoids that something
                    819:     * like ":r !cat" hangs.
                    820:     */
                    821:    if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED) == FAIL)
                    822:    {
                    823:        must_redraw = CLEAR;
                    824:        wait_return(FALSE);
                    825:    }
                    826:    need_check_timestamps = TRUE;
                    827:
                    828:    if (do_out)
                    829:    {
                    830:        if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
                    831:        {
                    832:            goto error;
                    833:        }
                    834:        if (readfile(otmp, NULL, line2, FALSE, (linenr_t)0, MAXLNUM, TRUE)
                    835:                                                                      == FAIL)
                    836:        {
                    837:            msg_outchar('\n');
                    838:            emsg2(e_notread, otmp);
                    839:            goto error;
                    840:        }
1.2       downsj    841: #ifdef AUTOCMD
                    842:        if (curbuf != old_curbuf)
                    843:            goto filterend;
                    844: #endif
1.1       downsj    845:
                    846:        if (do_in)
                    847:        {
                    848:            /* put cursor on first filtered line for ":range!cmd" */
                    849:            curwin->w_cursor.lnum = line1;
                    850:            dellines(linecount, TRUE, TRUE);
                    851:            curbuf->b_op_start.lnum -= linecount;       /* adjust '[ */
                    852:            curbuf->b_op_end.lnum -= linecount;         /* adjust '] */
1.2       downsj    853:            write_lnum_adjust(-linecount);              /* adjust last line
                    854:                                                           for next write */
1.1       downsj    855:        }
                    856:        else
                    857:        {
                    858:            /* put cursor on last new line for ":r !cmd" */
                    859:            curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
                    860:            linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
                    861:        }
                    862:        beginline(TRUE);                /* cursor on first non-blank */
                    863:        --no_wait_return;
                    864:
                    865:        if (linecount > p_report)
                    866:        {
                    867:            if (do_in)
                    868:            {
                    869:                sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
                    870:                if (msg(msg_buf) && !msg_scroll)
                    871:                    keep_msg = msg_buf;     /* display message after redraw */
                    872:            }
                    873:            else
                    874:                msgmore((long)linecount);
                    875:        }
                    876:    }
                    877:    else
                    878:    {
                    879: error:
                    880:        /* put cursor back in same position for ":w !cmd" */
                    881:        curwin->w_cursor = cursor_save;
                    882:        --no_wait_return;
                    883:        wait_return(FALSE);
                    884:    }
                    885:
                    886: filterend:
                    887:
1.2       downsj    888: #ifdef AUTOCMD
                    889:    if (curbuf != old_curbuf)
1.1       downsj    890:    {
1.2       downsj    891:        --no_wait_return;
                    892:        EMSG("*Filter* Autocommands must not change current buffer");
1.1       downsj    893:    }
1.2       downsj    894: #endif
                    895:    if (itmp != NULL)
                    896:        vim_remove(itmp);
                    897:    if (otmp != NULL)
                    898:        vim_remove(otmp);
                    899:    vim_free(itmp);
                    900:    vim_free(otmp);
1.1       downsj    901: }
                    902:
                    903: #ifdef VIMINFO
                    904:
                    905: static int no_viminfo __ARGS((void));
1.2       downsj    906: static int viminfo_errcnt;
1.1       downsj    907:
                    908:    static int
                    909: no_viminfo()
                    910: {
                    911:    /* "vim -i NONE" does not read or write a viminfo file */
                    912:    return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
                    913: }
                    914:
                    915: /*
1.2       downsj    916:  * Report an error for reading a viminfo file.
                    917:  * Count the number of errors.  When there are more than 10, return TRUE.
                    918:  */
                    919:    int
                    920: viminfo_error(message, line)
                    921:    char    *message;
                    922:    char_u  *line;
                    923: {
                    924:    sprintf((char *)IObuff, "viminfo: %s in line: ", message);
                    925:    STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
                    926:    emsg(IObuff);
                    927:    if (++viminfo_errcnt >= 10)
                    928:    {
                    929:        EMSG("viminfo: Too many errors, skipping rest of file");
                    930:        return TRUE;
                    931:    }
                    932:    return FALSE;
                    933: }
                    934:
                    935: /*
1.1       downsj    936:  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
                    937:  * set are not over-written unless force is TRUE. -- webb
                    938:  */
                    939:    int
1.2       downsj    940: read_viminfo(file, want_info, want_marks, forceit)
1.1       downsj    941:    char_u  *file;
                    942:    int     want_info;
                    943:    int     want_marks;
1.2       downsj    944:    int     forceit;
1.1       downsj    945: {
                    946:    FILE    *fp;
                    947:
                    948:    if (no_viminfo())
                    949:        return FAIL;
                    950:
                    951:    file = viminfo_filename(file);          /* may set to default if NULL */
                    952:    if ((fp = fopen((char *)file, READBIN)) == NULL)
                    953:        return FAIL;
                    954:
1.2       downsj    955:    viminfo_errcnt = 0;
                    956:    do_viminfo(fp, NULL, want_info, want_marks, forceit);
1.1       downsj    957:
                    958:    fclose(fp);
                    959:
                    960:    return OK;
                    961: }
                    962:
                    963: /*
                    964:  * write_viminfo() -- Write the viminfo file.  The old one is read in first so
                    965:  * that effectively a merge of current info and old info is done.  This allows
                    966:  * multiple vims to run simultaneously, without losing any marks etc.  If
1.2       downsj    967:  * forceit is TRUE, then the old file is not read in, and only internal info is
1.1       downsj    968:  * written to the file. -- webb
                    969:  */
                    970:    void
1.2       downsj    971: write_viminfo(file, forceit)
1.1       downsj    972:    char_u  *file;
1.2       downsj    973:    int     forceit;
1.1       downsj    974: {
                    975:    FILE    *fp_in = NULL;
                    976:    FILE    *fp_out = NULL;
1.2       downsj    977:    char_u  *tempname = NULL;
1.1       downsj    978:
                    979:    if (no_viminfo())
                    980:        return;
                    981:
                    982:    file = viminfo_filename(file);      /* may set to default if NULL */
                    983:    file = strsave(file);               /* make a copy, don't want NameBuff */
                    984:    if (file != NULL)
                    985:    {
                    986:        fp_in = fopen((char *)file, READBIN);
                    987:        if (fp_in == NULL)
                    988:            fp_out = fopen((char *)file, WRITEBIN);
1.2       downsj    989:        else if ((tempname = vim_tempname('o')) != NULL)
                    990:            fp_out = fopen((char *)tempname, WRITEBIN);
1.1       downsj    991:    }
                    992:    if (file == NULL || fp_out == NULL)
                    993:    {
                    994:        EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
1.2       downsj    995:                                              fp_in == NULL ? file : tempname);
1.1       downsj    996:        if (fp_in != NULL)
                    997:            fclose(fp_in);
1.2       downsj    998:        goto end;
1.1       downsj    999:    }
                   1000:
1.2       downsj   1001:    viminfo_errcnt = 0;
                   1002:    do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
1.1       downsj   1003:
                   1004:    fclose(fp_out);         /* errors are ignored !? */
                   1005:    if (fp_in != NULL)
                   1006:    {
                   1007:        fclose(fp_in);
1.2       downsj   1008:        /*
                   1009:         * In case of an error, don't overwrite the original viminfo file.
                   1010:         */
                   1011:        if (viminfo_errcnt || vim_rename(tempname, file) == -1)
                   1012:            vim_remove(tempname);
1.1       downsj   1013:    }
1.2       downsj   1014: end:
1.1       downsj   1015:    vim_free(file);
1.2       downsj   1016:    vim_free(tempname);
1.1       downsj   1017: }
                   1018:
                   1019:    static char_u *
                   1020: viminfo_filename(file)
                   1021:    char_u      *file;
                   1022: {
                   1023:    if (file == NULL || *file == NUL)
                   1024:    {
                   1025:        expand_env(use_viminfo == NULL ? (char_u *)VIMINFO_FILE : use_viminfo,
                   1026:                                                          NameBuff, MAXPATHL);
                   1027:        return NameBuff;
                   1028:    }
                   1029:    return file;
                   1030: }
                   1031:
                   1032: /*
                   1033:  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
                   1034:  */
                   1035:    static void
                   1036: do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
                   1037:    FILE    *fp_in;
                   1038:    FILE    *fp_out;
                   1039:    int     want_info;
                   1040:    int     want_marks;
                   1041:    int     force_read;
                   1042: {
                   1043:    int     count = 0;
                   1044:    int     eof = FALSE;
                   1045:    char_u  *line;
                   1046:
                   1047:    if ((line = alloc(LSIZE)) == NULL)
                   1048:        return;
                   1049:
                   1050:    if (fp_in != NULL)
                   1051:    {
                   1052:        if (want_info)
                   1053:            eof = read_viminfo_up_to_marks(line, fp_in, force_read);
                   1054:        else
                   1055:            /* Skip info, find start of marks */
                   1056:            while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
                   1057:                ;
                   1058:    }
                   1059:    if (fp_out != NULL)
                   1060:    {
                   1061:        /* Write the info: */
                   1062:        fprintf(fp_out, "# This viminfo file was generated by vim\n");
                   1063:        fprintf(fp_out, "# You may edit it if you're careful!\n\n");
                   1064:        write_viminfo_search_pattern(fp_out);
                   1065:        write_viminfo_sub_string(fp_out);
                   1066:        write_viminfo_history(fp_out);
                   1067:        write_viminfo_registers(fp_out);
                   1068:        write_viminfo_filemarks(fp_out);
                   1069:        count = write_viminfo_marks(fp_out);
                   1070:    }
                   1071:    if (fp_in != NULL && want_marks)
                   1072:        copy_viminfo_marks(line, fp_in, fp_out, count, eof);
                   1073:    vim_free(line);
                   1074: }
                   1075:
                   1076: /*
                   1077:  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
                   1078:  * first part of the viminfo file which contains everything but the marks that
                   1079:  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
                   1080:  */
                   1081:    static int
1.2       downsj   1082: read_viminfo_up_to_marks(line, fp, forceit)
1.1       downsj   1083:    char_u  *line;
                   1084:    FILE    *fp;
1.2       downsj   1085:    int     forceit;
1.1       downsj   1086: {
                   1087:    int     eof;
                   1088:
1.2       downsj   1089:    prepare_viminfo_history(forceit ? 9999 : 0);
1.1       downsj   1090:    eof = vim_fgets(line, LSIZE, fp);
                   1091:    while (!eof && line[0] != '>')
                   1092:    {
                   1093:        switch (line[0])
                   1094:        {
                   1095:            case NUL:
                   1096:            case '\r':
                   1097:            case '\n':
                   1098:            case '#':       /* A comment */
                   1099:                eof = vim_fgets(line, LSIZE, fp);
                   1100:                break;
                   1101:            case '"':
1.2       downsj   1102:                eof = read_viminfo_register(line, fp, forceit);
1.1       downsj   1103:                break;
                   1104:            case '/':       /* Search string */
                   1105:            case '&':       /* Substitute search string */
                   1106:            case '~':       /* Last search string, followed by '/' or '&' */
1.2       downsj   1107:                eof = read_viminfo_search_pattern(line, fp, forceit);
1.1       downsj   1108:                break;
                   1109:            case '$':
1.2       downsj   1110:                eof = read_viminfo_sub_string(line, fp, forceit);
1.1       downsj   1111:                break;
                   1112:            case ':':
                   1113:            case '?':
                   1114:                eof = read_viminfo_history(line, fp);
                   1115:                break;
                   1116:            case '\'':
                   1117:                /* How do we have a file mark when the file is not in the
                   1118:                 * buffer list?
                   1119:                 */
1.2       downsj   1120:                eof = read_viminfo_filemark(line, fp, forceit);
1.1       downsj   1121:                break;
                   1122: #if 0
                   1123:            case '+':
                   1124:                /* eg: "+40 /path/dir file", for running vim with no args */
                   1125:                eof = vim_fgets(line, LSIZE, fp);
                   1126:                break;
                   1127: #endif
                   1128:            default:
1.2       downsj   1129:                if (viminfo_error("Illegal starting char", line))
                   1130:                    eof = TRUE;
                   1131:                else
                   1132:                    eof = vim_fgets(line, LSIZE, fp);
1.1       downsj   1133:                break;
                   1134:        }
                   1135:    }
                   1136:    finish_viminfo_history();
                   1137:    return eof;
                   1138: }
                   1139:
                   1140: /*
                   1141:  * check string read from viminfo file
                   1142:  * remove '\n' at the end of the line
                   1143:  * - replace CTRL-V CTRL-V with CTRL-V
                   1144:  * - replace CTRL-V 'n'    with '\n'
                   1145:  */
                   1146:    void
                   1147: viminfo_readstring(p)
                   1148:    char_u      *p;
                   1149: {
                   1150:    while (*p != NUL && *p != '\n')
                   1151:    {
                   1152:        if (*p == Ctrl('V'))
                   1153:        {
                   1154:            if (p[1] == 'n')
                   1155:                p[0] = '\n';
                   1156:            vim_memmove(p + 1, p + 2, STRLEN(p));
                   1157:        }
                   1158:        ++p;
                   1159:    }
                   1160:    *p = NUL;
                   1161: }
                   1162:
                   1163: /*
                   1164:  * write string to viminfo file
                   1165:  * - replace CTRL-V with CTRL-V CTRL-V
                   1166:  * - replace '\n'   with CTRL-V 'n'
                   1167:  * - add a '\n' at the end
                   1168:  */
                   1169:    void
                   1170: viminfo_writestring(fd, p)
                   1171:    FILE    *fd;
                   1172:    char_u  *p;
                   1173: {
                   1174:    register int    c;
                   1175:
                   1176:    while ((c = *p++) != NUL)
                   1177:    {
                   1178:        if (c == Ctrl('V') || c == '\n')
                   1179:        {
                   1180:            putc(Ctrl('V'), fd);
                   1181:            if (c == '\n')
                   1182:                c = 'n';
                   1183:        }
                   1184:        putc(c, fd);
                   1185:    }
                   1186:    putc('\n', fd);
                   1187: }
                   1188: #endif /* VIMINFO */
                   1189:
                   1190: /*
                   1191:  * Implementation of ":fixdel", also used by get_stty().
                   1192:  *  <BS>    resulting <Del>
                   1193:  *   ^?        ^H
                   1194:  * not ^?      ^?
                   1195:  */
                   1196:    void
                   1197: do_fixdel()
                   1198: {
                   1199:    char_u  *p;
                   1200:
                   1201:    p = find_termcode((char_u *)"kb");
                   1202:    add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ?
                   1203:                                         (char_u *)"\010" : (char_u *)"\177");
                   1204: }
                   1205:
1.3       downsj   1206:    static void
                   1207: print_line_no_prefix(lnum, use_number)
1.1       downsj   1208:    linenr_t    lnum;
                   1209:    int         use_number;
                   1210: {
                   1211:    char_u      numbuf[20];
                   1212:
                   1213:    if (curwin->w_p_nu || use_number)
                   1214:    {
                   1215:        sprintf((char *)numbuf, "%7ld ", (long)lnum);
                   1216:        set_highlight('n');     /* Highlight line numbers */
                   1217:        start_highlight();
                   1218:        msg_outstr(numbuf);
                   1219:        stop_highlight();
                   1220:    }
                   1221:    msg_prt_line(ml_get(lnum));
                   1222: }
                   1223:
1.3       downsj   1224:     void
                   1225: print_line(lnum, use_number)
                   1226:    linenr_t    lnum;
                   1227:    int         use_number;
                   1228: {
                   1229:    msg_outchar('\n');
                   1230:    print_line_no_prefix (lnum, use_number);
                   1231: }
                   1232:
                   1233:     void
                   1234: print_line_cr(lnum, use_number)
                   1235:    linenr_t    lnum;
                   1236:    int         use_number;
                   1237: {
                   1238:    msg_outchar('\r');
                   1239:    print_line_no_prefix (lnum, use_number);
                   1240: }
                   1241:
1.1       downsj   1242: /*
1.2       downsj   1243:  * Implementation of ":file[!] [fname]".
1.1       downsj   1244:  */
                   1245:    void
                   1246: do_file(arg, forceit)
                   1247:    char_u  *arg;
                   1248:    int     forceit;
                   1249: {
                   1250:    char_u      *fname, *sfname;
                   1251:    BUF         *buf;
                   1252:
                   1253:    if (*arg != NUL)
                   1254:    {
                   1255:        /*
                   1256:         * The name of the current buffer will be changed.
                   1257:         * A new buffer entry needs to be made to hold the old
                   1258:         * file name, which will become the alternate file name.
                   1259:         */
                   1260:        fname = curbuf->b_filename;
                   1261:        sfname = curbuf->b_sfilename;
                   1262:        curbuf->b_filename = NULL;
                   1263:        curbuf->b_sfilename = NULL;
                   1264:        if (setfname(arg, NULL, TRUE) == FAIL)
                   1265:        {
                   1266:            curbuf->b_filename = fname;
                   1267:            curbuf->b_sfilename = sfname;
                   1268:            return;
                   1269:        }
                   1270:        curbuf->b_notedited = TRUE;
                   1271:        buf = buflist_new(fname, sfname, curwin->w_cursor.lnum, FALSE);
                   1272:        if (buf != NULL)
                   1273:            curwin->w_alt_fnum = buf->b_fnum;
                   1274:        vim_free(fname);
                   1275:        vim_free(sfname);
                   1276:    }
                   1277:    /* print full filename if :cd used */
                   1278:    fileinfo(did_cd, FALSE, forceit);
1.3       downsj   1279: }
                   1280:
                   1281: /*
                   1282:  * do the Ex mode :insert and :append commands
                   1283:  */
                   1284:
                   1285: void
                   1286: ex_insert (int before, linenr_t whatline)
                   1287: {
                   1288:    /* put the cursor somewhere sane if we insert nothing */
                   1289:
                   1290:    if (whatline > curbuf->b_ml.ml_line_count) {
                   1291:        curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
                   1292:    } else {
                   1293:        curwin->w_cursor.lnum = whatline;
                   1294:    }
                   1295:
                   1296:    while (1) {
                   1297:        char_u *theline;
                   1298:
                   1299:        if (((theline = getcmdline (' ', 1L)) == 0) ||
                   1300:            ((theline[0] == '.') && (theline[1] == 0))) {
                   1301:            break;
                   1302:        }
                   1303:
                   1304:        if (before) {
                   1305:            mark_adjust (whatline, MAXLNUM, 1, 0L);
                   1306:            ml_append (whatline - 1, theline, (colnr_t) 0, FALSE);
                   1307:            curwin->w_cursor.lnum = whatline;
                   1308:        } else {
                   1309:            mark_adjust (whatline + 1, MAXLNUM, 1, 0L);
                   1310:            ml_append (whatline, theline, (colnr_t) 0, FALSE);
                   1311:            curwin->w_cursor.lnum = whatline + 1;
                   1312:        }
                   1313:
                   1314:        vim_free (theline);
                   1315:        whatline++;
                   1316:    }
                   1317:
                   1318:    CHANGED;
                   1319:    beginline (MAYBE);
                   1320:    updateScreen (NOT_VALID);
                   1321: }
                   1322:
                   1323: /*
                   1324:  * do the Ex mode :change command
                   1325:  */
                   1326:
                   1327: void
                   1328: ex_change (linenr_t start, linenr_t end)
                   1329: {
                   1330:    while (end >= start) {
                   1331:        ml_delete (start, FALSE);
                   1332:        end--;
                   1333:    }
                   1334:
                   1335:    ex_insert (TRUE, start);
                   1336: }
                   1337:
                   1338: void
                   1339: ex_z (linenr_t line, char_u *arg)
                   1340: {
                   1341:    char_u *x;
                   1342:    int bigness = curwin->w_height - 3;
                   1343:    char_u kind;
                   1344:    int minus = 0;
                   1345:    linenr_t start, end, curs, i;
                   1346:
                   1347:    if (arg == 0) { /* is this possible?  I don't remember */
                   1348:        arg = "";
                   1349:    }
                   1350:
                   1351:    if (bigness < 1) {
                   1352:        bigness = 1;
                   1353:    }
                   1354:
                   1355:    x = arg;
                   1356:    if (*x == '-' || *x == '+' || *x == '=' || *x == '^' || *x == '.') x++;
                   1357:
                   1358:    if (*x != 0) {
                   1359:        if (!isdigit (*x)) {
                   1360:            EMSG ("non-numeric argument to :z");
                   1361:            return;
                   1362:        } else {
                   1363:            bigness = atoi (x);
                   1364:        }
                   1365:    }
                   1366:
                   1367:    kind = *arg;
                   1368:
                   1369:    switch (kind) {
                   1370:        case '-':
                   1371:            start = line - bigness;
                   1372:            end = line;
                   1373:            curs = line;
                   1374:            break;
                   1375:
                   1376:        case '=':
                   1377:            start = line - bigness / 2 + 1;
                   1378:            end = line + bigness / 2 - 1;
                   1379:            curs = line;
                   1380:            minus = 1;
                   1381:            break;
                   1382:
                   1383:        case '^':
                   1384:            start = line - bigness * 2;
                   1385:            end = line - bigness;
                   1386:            curs = line - bigness;
                   1387:            break;
                   1388:
                   1389:        case '.':
                   1390:            start = line - bigness / 2;
                   1391:            end = line + bigness / 2;
                   1392:            curs = end;
                   1393:            break;
                   1394:
                   1395:        default:  /* '+' */
                   1396:            start = line;
                   1397:            end = line + bigness;
                   1398:            curs = end;
                   1399:            break;
                   1400:    }
                   1401:
                   1402:    if (start < 1) {
                   1403:        start = 1;
                   1404:    }
                   1405:
                   1406:    if (end > curbuf->b_ml.ml_line_count) {
                   1407:        end = curbuf->b_ml.ml_line_count;
                   1408:    }
                   1409:
                   1410:    if (curs > curbuf->b_ml.ml_line_count) {
                   1411:        curs = curbuf->b_ml.ml_line_count;
                   1412:    }
                   1413:
                   1414:    for (i = start; i <= end; i++) {
                   1415:        int j;
                   1416:
                   1417:        if (minus && (i == line)) {
                   1418:            msg_outchar ('\n');
                   1419:
                   1420:            for (j = 1; j < Columns; j++) {
                   1421:                msg_outchar ('-');
                   1422:            }
                   1423:        }
                   1424:
                   1425:        print_line (i, FALSE);
                   1426:
                   1427:        if (minus && (i == line)) {
                   1428:            msg_outchar ('\n');
                   1429:
                   1430:            for (j = 1; j < Columns; j++) {
                   1431:                msg_outchar ('-');
                   1432:            }
                   1433:        }
                   1434:    }
                   1435:
                   1436:    curwin->w_cursor.lnum = curs;
1.1       downsj   1437: }