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

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