Annotation of 42BSD/ucb/ex/ex_vops.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1981 Regents of the University of California */
                      2: static char *sccsid = "@(#)ex_vops.c   7.2     10/31/81";
                      3: #include "ex.h"
                      4: #include "ex_tty.h"
                      5: #include "ex_vis.h"
                      6: 
                      7: /*
                      8:  * This file defines the operation sequences which interface the
                      9:  * logical changes to the file buffer with the internal and external
                     10:  * display representations.
                     11:  */
                     12: 
                     13: /*
                     14:  * Undo.
                     15:  *
                     16:  * Undo is accomplished in two ways.  We often for small changes in the
                     17:  * current line know how (in terms of a change operator) how the change
                     18:  * occurred.  Thus on an intelligent terminal we can undo the operation
                     19:  * by another such operation, using insert and delete character
                     20:  * stuff.  The pointers vU[AD][12] index the buffer vutmp when this
                     21:  * is possible and provide the necessary information.
                     22:  *
                     23:  * The other case is that the change involved multiple lines or that
                     24:  * we have moved away from the line or forgotten how the change was
                     25:  * accomplished.  In this case we do a redisplay and hope that the
                     26:  * low level optimization routines (which don't look for winning
                     27:  * via insert/delete character) will not lose too badly.
                     28:  */
                     29: char   *vUA1, *vUA2;
                     30: char   *vUD1, *vUD2;
                     31: 
                     32: vUndo()
                     33: {
                     34: 
                     35:        /*
                     36:         * Avoid UU which clobbers ability to do u.
                     37:         */
                     38:        if (vundkind == VCAPU || vUNDdot != dot) {
                     39:                beep();
                     40:                return;
                     41:        }
                     42:        CP(vutmp, linebuf);
                     43:        vUD1 = linebuf; vUD2 = strend(linebuf);
                     44:        putmk1(dot, vUNDsav);
                     45:        getDOT();
                     46:        vUA1 = linebuf; vUA2 = strend(linebuf);
                     47:        vundkind = VCAPU;
                     48:        if (state == ONEOPEN || state == HARDOPEN) {
                     49:                vjumpto(dot, vUNDcurs, 0);
                     50:                return;
                     51:        }
                     52:        vdirty(vcline, 1);
                     53:        vsyncCL();
                     54:        cursor = linebuf;
                     55:        vfixcurs();
                     56: }
                     57: 
                     58: vundo(show)
                     59: bool show;     /* if true update the screen */
                     60: {
                     61:        register int cnt;
                     62:        register line *addr;
                     63:        register char *cp;
                     64:        char temp[LBSIZE];
                     65:        bool savenote;
                     66:        int (*OO)();
                     67:        short oldhold = hold;
                     68: 
                     69:        switch (vundkind) {
                     70: 
                     71:        case VMANYINS:
                     72:                wcursor = 0;
                     73:                addr1 = undap1;
                     74:                addr2 = undap2 - 1;
                     75:                vsave();
                     76:                YANKreg('1');
                     77:                notecnt = 0;
                     78:                /* fall into ... */
                     79: 
                     80:        case VMANY:
                     81:        case VMCHNG:
                     82:                vsave();
                     83:                addr = dot - vcline;
                     84:                notecnt = 1;
                     85:                if (undkind == UNDPUT && undap1 == undap2) {
                     86:                        beep();
                     87:                        break;
                     88:                }
                     89:                /*
                     90:                 * Undo() call below basically replaces undap1 to undap2-1
                     91:                 * with dol through unddol-1.  Hack screen image to
                     92:                 * reflect this replacement.
                     93:                 */
                     94:                if (show)
                     95:                        if (undkind == UNDMOVE)
                     96:                                vdirty(0, LINES);
                     97:                        else
                     98:                                vreplace(undap1 - addr, undap2 - undap1,
                     99:                                    undkind == UNDPUT ? 0 : unddol - dol);
                    100:                savenote = notecnt;
                    101:                undo(1);
                    102:                if (show && (vundkind != VMCHNG || addr != dot))
                    103:                        killU();
                    104:                vundkind = VMANY;
                    105:                cnt = dot - addr;
                    106:                if (cnt < 0 || cnt > vcnt || state != VISUAL) {
                    107:                        if (show)
                    108:                                vjumpto(dot, NOSTR, '.');
                    109:                        break;
                    110:                }
                    111:                if (!savenote)
                    112:                        notecnt = 0;
                    113:                if (show) {
                    114:                        vcline = cnt;
                    115:                        vrepaint(vmcurs);
                    116:                }
                    117:                vmcurs = 0;
                    118:                break;
                    119: 
                    120:        case VCHNG:
                    121:        case VCAPU:
                    122:                vundkind = VCHNG;
                    123:                strcpy(temp, vutmp);
                    124:                strcpy(vutmp, linebuf);
                    125:                doomed = column(vUA2 - 1) - column(vUA1 - 1);
                    126:                strcLIN(temp);
                    127:                cp = vUA1; vUA1 = vUD1; vUD1 = cp;
                    128:                cp = vUA2; vUA2 = vUD2; vUD2 = cp;
                    129:                if (!show)
                    130:                        break;
                    131:                cursor = vUD1;
                    132:                if (state == HARDOPEN) {
                    133:                        doomed = 0;
                    134:                        vsave();
                    135:                        vopen(dot, WBOT);
                    136:                        vnline(cursor);
                    137:                        break;
                    138:                }
                    139:                /*
                    140:                 * Pseudo insert command.
                    141:                 */
                    142:                vcursat(cursor);
                    143:                OO = Outchar; Outchar = vinschar; hold |= HOLDQIK;
                    144:                vprepins();
                    145:                temp[vUA2 - linebuf] = 0;
                    146:                for (cp = &temp[vUA1 - linebuf]; *cp;)
                    147:                        putchar(*cp++);
                    148:                Outchar = OO; hold = oldhold;
                    149:                endim();
                    150:                physdc(cindent(), cindent() + doomed);
                    151:                doomed = 0;
                    152:                vdirty(vcline, 1);
                    153:                vsyncCL();
                    154:                if (cursor > linebuf && cursor >= strend(linebuf))
                    155:                        cursor--;
                    156:                vfixcurs();
                    157:                break;
                    158: 
                    159:        case VNONE:
                    160:                beep();
                    161:                break;
                    162:        }
                    163: }
                    164: 
                    165: /*
                    166:  * Routine to handle a change inside a macro.
                    167:  * Fromvis is true if we were called from a visual command (as
                    168:  * opposed to an ex command).  This has nothing to do with being
                    169:  * in open/visual mode as :s/foo/bar is not fromvis.
                    170:  */
                    171: vmacchng(fromvis)
                    172: bool fromvis;
                    173: {
                    174:        line *savedot, *savedol;
                    175:        char *savecursor;
                    176:        char savelb[LBSIZE];
                    177:        int nlines, more;
                    178:        register line *a1, *a2;
                    179:        char ch;        /* DEBUG */
                    180:        int copyw(), copywR();
                    181: 
                    182:        if (!inopen)
                    183:                return;
                    184:        if (!vmacp)
                    185:                vch_mac = VC_NOTINMAC;
                    186: #ifdef TRACE
                    187:        if (trace)
                    188:                fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
                    189: #endif
                    190:        if (vmacp && fromvis)
                    191:                vsave();
                    192: #ifdef TRACE
                    193:        if (trace)
                    194:                fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
                    195: #endif
                    196:        switch(vch_mac) {
                    197:        case VC_NOCHANGE:
                    198:                vch_mac = VC_ONECHANGE;
                    199:                break;
                    200:        case VC_ONECHANGE:
                    201:                /* Save current state somewhere */
                    202: #ifdef TRACE
                    203:                vudump("before vmacchng hairy case");
                    204: #endif
                    205:                savedot = dot; savedol = dol; savecursor = cursor;
                    206:                CP(savelb, linebuf);
                    207:                nlines = dol - zero;
                    208:                while ((line *) endcore - truedol < nlines)
                    209:                        morelines();
                    210:                copyw(truedol+1, zero+1, nlines);
                    211:                truedol += nlines;
                    212: 
                    213: #ifdef TRACE
                    214:                visdump("before vundo");
                    215: #endif
                    216:                /* Restore state as it was at beginning of macro */
                    217:                vundo(0);
                    218: #ifdef TRACE
                    219:                visdump("after vundo");
                    220:                vudump("after vundo");
                    221: #endif
                    222: 
                    223:                /* Do the saveall we should have done then */
                    224:                saveall();
                    225: #ifdef TRACE
                    226:                vudump("after saveall");
                    227: #endif
                    228: 
                    229:                /* Restore current state from where saved */
                    230:                more = savedol - dol; /* amount we shift everything by */
                    231:                if (more)
                    232:                        (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
                    233:                unddol += more; truedol += more; undap2 += more;
                    234: 
                    235:                truedol -= nlines;
                    236:                copyw(zero+1, truedol+1, nlines);
                    237:                dot = savedot; dol = savedol ; cursor = savecursor;
                    238:                CP(linebuf, savelb);
                    239:                vch_mac = VC_MANYCHANGE;
                    240: 
                    241:                /* Arrange that no further undo saving happens within macro */
                    242:                otchng = tchng; /* Copied this line blindly - bug? */
                    243:                inopen = -1;    /* no need to save since it had to be 1 or -1 before */
                    244:                vundkind = VMANY;
                    245: #ifdef TRACE
                    246:                vudump("after vmacchng");
                    247: #endif
                    248:                break;
                    249:        case VC_NOTINMAC:
                    250:        case VC_MANYCHANGE:
                    251:                /* Nothing to do for various reasons. */
                    252:                break;
                    253:        }
                    254: }
                    255: 
                    256: /*
                    257:  * Initialize undo information before an append.
                    258:  */
                    259: vnoapp()
                    260: {
                    261: 
                    262:        vUD1 = vUD2 = cursor;
                    263: }
                    264: 
                    265: /*
                    266:  * All the rest of the motion sequences have one or more
                    267:  * cases to deal with.  In the case wdot == 0, operation
                    268:  * is totally within current line, from cursor to wcursor.
                    269:  * If wdot is given, but wcursor is 0, then operation affects
                    270:  * the inclusive line range.  The hardest case is when both wdot
                    271:  * and wcursor are given, then operation affects from line dot at
                    272:  * cursor to line wdot at wcursor.
                    273:  */
                    274: 
                    275: /*
                    276:  * Move is simple, except for moving onto new lines in hardcopy open mode.
                    277:  */
                    278: vmove()
                    279: {
                    280:        register int cnt;
                    281: 
                    282:        if (wdot) {
                    283:                if (wdot < one || wdot > dol) {
                    284:                        beep();
                    285:                        return;
                    286:                }
                    287:                cnt = wdot - dot;
                    288:                wdot = NOLINE;
                    289:                if (cnt)
                    290:                        killU();
                    291:                vupdown(cnt, wcursor);
                    292:                return;
                    293:        }
                    294: 
                    295:        /*
                    296:         * When we move onto a new line, save information for U undo.
                    297:         */
                    298:        if (vUNDdot != dot) {
                    299:                vUNDsav = *dot;
                    300:                vUNDcurs = wcursor;
                    301:                vUNDdot = dot;
                    302:        }
                    303: 
                    304:        /*
                    305:         * In hardcopy open, type characters to left of cursor
                    306:         * on new line, or back cursor up if its to left of where we are.
                    307:         * In any case if the current line is ``rubbled'' i.e. has trashy
                    308:         * looking overstrikes on it or \'s from deletes, we reprint
                    309:         * so it is more comprehensible (and also because we can't work
                    310:         * if we let it get more out of sync since column() won't work right.
                    311:         */
                    312:        if (state == HARDOPEN) {
                    313:                register char *cp;
                    314:                if (rubble) {
                    315:                        register int c;
                    316:                        int oldhold = hold;
                    317: 
                    318:                        sethard();
                    319:                        cp = wcursor;
                    320:                        c = *cp;
                    321:                        *cp = 0;
                    322:                        hold |= HOLDDOL;
                    323:                        vreopen(WTOP, lineDOT(), vcline);
                    324:                        hold = oldhold;
                    325:                        *cp = c;
                    326:                } else if (wcursor > cursor) {
                    327:                        vfixcurs();
                    328:                        for (cp = cursor; *cp && cp < wcursor;) {
                    329:                                register int c = *cp++ & TRIM;
                    330: 
                    331:                                putchar(c ? c : ' ');
                    332:                        }
                    333:                }
                    334:        }
                    335:        vsetcurs(wcursor);
                    336: }
                    337: 
                    338: /*
                    339:  * Delete operator.
                    340:  *
                    341:  * Hard case of deleting a range where both wcursor and wdot
                    342:  * are specified is treated as a special case of change and handled
                    343:  * by vchange (although vchange may pass it back if it degenerates
                    344:  * to a full line range delete.)
                    345:  */
                    346: vdelete(c)
                    347:        char c;
                    348: {
                    349:        register char *cp;
                    350:        register int i;
                    351: 
                    352:        if (wdot) {
                    353:                if (wcursor) {
                    354:                        vchange('d');
                    355:                        return;
                    356:                }
                    357:                if ((i = xdw()) < 0)
                    358:                        return;
                    359:                if (state != VISUAL) {
                    360:                        vgoto(LINE(0), 0);
                    361:                        vputchar('@');
                    362:                }
                    363:                wdot = dot;
                    364:                vremote(i, delete, 0);
                    365:                notenam = "delete";
                    366:                DEL[0] = 0;
                    367:                killU();
                    368:                vreplace(vcline, i, 0);
                    369:                if (wdot > dol)
                    370:                        vcline--;
                    371:                vrepaint(NOSTR);
                    372:                return;
                    373:        }
                    374:        if (wcursor < linebuf)
                    375:                wcursor = linebuf;
                    376:        if (cursor == wcursor) {
                    377:                beep();
                    378:                return;
                    379:        }
                    380:        i = vdcMID();
                    381:        cp = cursor;
                    382:        setDEL();
                    383:        CP(cp, wcursor);
                    384:        if (cp > linebuf && (cp[0] == 0 || c == '#'))
                    385:                cp--;
                    386:        if (state == HARDOPEN) {
                    387:                bleep(i, cp);
                    388:                cursor = cp;
                    389:                return;
                    390:        }
                    391:        physdc(column(cursor - 1), i);
                    392:        DEPTH(vcline) = 0;
                    393:        vreopen(LINE(vcline), lineDOT(), vcline);
                    394:        vsyncCL();
                    395:        vsetcurs(cp);
                    396: }
                    397: 
                    398: /*
                    399:  * Change operator.
                    400:  *
                    401:  * In a single line we mark the end of the changed area with '$'.
                    402:  * On multiple whole lines, we clear the lines first.
                    403:  * Across lines with both wcursor and wdot given, we delete
                    404:  * and sync then append (but one operation for undo).
                    405:  */
                    406: vchange(c)
                    407:        char c;
                    408: {
                    409:        register char *cp;
                    410:        register int i, ind, cnt;
                    411:        line *addr;
                    412: 
                    413:        if (wdot) {
                    414:                /*
                    415:                 * Change/delete of lines or across line boundaries.
                    416:                 */
                    417:                if ((cnt = xdw()) < 0)
                    418:                        return;
                    419:                getDOT();
                    420:                if (wcursor && cnt == 1) {
                    421:                        /*
                    422:                         * Not really.
                    423:                         */
                    424:                        wdot = 0;
                    425:                        if (c == 'd') {
                    426:                                vdelete(c);
                    427:                                return;
                    428:                        }
                    429:                        goto smallchange;
                    430:                }
                    431:                if (cursor && wcursor) {
                    432:                        /*
                    433:                         * Across line boundaries, but not
                    434:                         * necessarily whole lines.
                    435:                         * Construct what will be left.
                    436:                         */
                    437:                        *cursor = 0;
                    438:                        strcpy(genbuf, linebuf);
                    439:                        getline(*wdot);
                    440:                        if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) {
                    441:                                getDOT();
                    442:                                beep();
                    443:                                return;
                    444:                        }
                    445:                        strcat(genbuf, wcursor);
                    446:                        if (c == 'd' && *vpastwh(genbuf) == 0) {
                    447:                                /*
                    448:                                 * Although this is a delete
                    449:                                 * spanning line boundaries, what
                    450:                                 * would be left is all white space,
                    451:                                 * so take it all away.
                    452:                                 */
                    453:                                wcursor = 0;
                    454:                                getDOT();
                    455:                                op = 0;
                    456:                                notpart(lastreg);
                    457:                                notpart('1');
                    458:                                vdelete(c);
                    459:                                return;
                    460:                        }
                    461:                        ind = -1;
                    462:                } else if (c == 'd' && wcursor == 0) {
                    463:                        vdelete(c);
                    464:                        return;
                    465:                } else
                    466: #ifdef LISPCODE
                    467:                        /*
                    468:                         * We are just substituting text for whole lines,
                    469:                         * so determine the first autoindent.
                    470:                         */
                    471:                        if (value(LISP) && value(AUTOINDENT))
                    472:                                ind = lindent(dot);
                    473:                        else
                    474: #endif
                    475:                                ind = whitecnt(linebuf);
                    476:                i = vcline >= 0 ? LINE(vcline) : WTOP;
                    477: 
                    478:                /*
                    479:                 * Delete the lines from the buffer,
                    480:                 * and remember how the partial stuff came about in
                    481:                 * case we are told to put.
                    482:                 */
                    483:                addr = dot;
                    484:                vremote(cnt, delete, 0);
                    485:                setpk();
                    486:                notenam = "delete";
                    487:                if (c != 'd')
                    488:                        notenam = "change";
                    489:                /*
                    490:                 * If DEL[0] were nonzero, put would put it back
                    491:                 * rather than the deleted lines.
                    492:                 */
                    493:                DEL[0] = 0;
                    494:                if (cnt > 1)
                    495:                        killU();
                    496: 
                    497:                /*
                    498:                 * Now hack the screen image coordination.
                    499:                 */
                    500:                vreplace(vcline, cnt, 0);
                    501:                wdot = NOLINE;
                    502:                noteit(0);
                    503:                vcline--;
                    504:                if (addr <= dol)
                    505:                        dot--;
                    506: 
                    507:                /*
                    508:                 * If this is a across line delete/change,
                    509:                 * cursor stays where it is; just splice together the pieces
                    510:                 * of the new line.  Otherwise generate a autoindent
                    511:                 * after a S command.
                    512:                 */
                    513:                if (ind >= 0) {
                    514:                        *genindent(ind) = 0;
                    515:                        vdoappend(genbuf);
                    516:                } else {
                    517:                        vmcurs = cursor;
                    518:                        strcLIN(genbuf);
                    519:                        vdoappend(linebuf);
                    520:                }
                    521: 
                    522:                /*
                    523:                 * Indicate a change on hardcopies by
                    524:                 * erasing the current line.
                    525:                 */
                    526:                if (c != 'd' && state != VISUAL && state != HARDOPEN) {
                    527:                        int oldhold = hold;
                    528: 
                    529:                        hold |= HOLDAT, vclrlin(i, dot), hold = oldhold;
                    530:                }
                    531: 
                    532:                /*
                    533:                 * Open the line (logically) on the screen, and 
                    534:                 * update the screen tail.  Unless we are really a delete
                    535:                 * go off and gather up inserted characters.
                    536:                 */
                    537:                vcline++;
                    538:                if (vcline < 0)
                    539:                        vcline = 0;
                    540:                vopen(dot, i);
                    541:                vsyncCL();
                    542:                noteit(1);
                    543:                if (c != 'd') {
                    544:                        if (ind >= 0) {
                    545:                                cursor = linebuf;
                    546:                                linebuf[0] = 0;
                    547:                                vfixcurs();
                    548:                        } else {
                    549:                                ind = 0;
                    550:                                vcursat(cursor);
                    551:                        }
                    552:                        vappend('x', 1, ind);
                    553:                        return;
                    554:                }
                    555:                if (*cursor == 0 && cursor > linebuf)
                    556:                        cursor--;
                    557:                vrepaint(cursor);
                    558:                return;
                    559:        }
                    560: 
                    561: smallchange:
                    562:        /*
                    563:         * The rest of this is just low level hacking on changes
                    564:         * of small numbers of characters.
                    565:         */
                    566:        if (wcursor < linebuf)
                    567:                wcursor = linebuf;
                    568:        if (cursor == wcursor) {
                    569:                beep();
                    570:                return;
                    571:        }
                    572:        i = vdcMID();
                    573:        cp = cursor;
                    574:        if (state != HARDOPEN)
                    575:                vfixcurs();
                    576: 
                    577:        /*
                    578:         * Put out the \\'s indicating changed text in hardcopy,
                    579:         * or mark the end of the change with $ if not hardcopy.
                    580:         */
                    581:        if (state == HARDOPEN) 
                    582:                bleep(i, cp);
                    583:        else {
                    584:                vcursbef(wcursor);
                    585:                putchar('$');
                    586:                i = cindent();
                    587:        }
                    588: 
                    589:        /*
                    590:         * Remember the deleted text for possible put,
                    591:         * and then prepare and execute the input portion of the change.
                    592:         */
                    593:        cursor = cp;
                    594:        setDEL();
                    595:        CP(cursor, wcursor);
                    596:        if (state != HARDOPEN) {
                    597:                vcursaft(cursor - 1);
                    598:                doomed = i - cindent();
                    599:        } else {
                    600: /*
                    601:                sethard();
                    602:                wcursor = cursor;
                    603:                cursor = linebuf;
                    604:                vgoto(outline, value(NUMBER) << 3);
                    605:                vmove();
                    606: */
                    607:                doomed = 0;
                    608:        }
                    609:        prepapp();
                    610:        vappend('c', 1, 0);
                    611: }
                    612: 
                    613: /*
                    614:  * Open new lines.
                    615:  *
                    616:  * Tricky thing here is slowopen.  This causes display updating
                    617:  * to be held off so that 300 baud dumb terminals don't lose badly.
                    618:  * This also suppressed counts, which otherwise say how many blank
                    619:  * space to open up.  Counts are also suppressed on intelligent terminals.
                    620:  * Actually counts are obsoleted, since if your terminal is slow
                    621:  * you are better off with slowopen.
                    622:  */
                    623: voOpen(c, cnt)
                    624:        int c;  /* mjm: char --> int */
                    625:        register int cnt;
                    626: {
                    627:        register int ind = 0, i;
                    628:        short oldhold = hold;
                    629: 
                    630:        if (value(SLOWOPEN) || value(REDRAW) && AL && DL)
                    631:                cnt = 1;
                    632:        vsave();
                    633:        setLAST();
                    634:        if (value(AUTOINDENT))
                    635:                ind = whitecnt(linebuf);
                    636:        if (c == 'O') {
                    637:                vcline--;
                    638:                dot--;
                    639:                if (dot > zero)
                    640:                        getDOT();
                    641:        }
                    642:        if (value(AUTOINDENT)) {
                    643: #ifdef LISPCODE
                    644:                if (value(LISP))
                    645:                        ind = lindent(dot + 1);
                    646: #endif
                    647:        }
                    648:        killU();
                    649:        prepapp();
                    650:        if (FIXUNDO)
                    651:                vundkind = VMANY;
                    652:        if (state != VISUAL)
                    653:                c = WBOT + 1;
                    654:        else {
                    655:                c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
                    656:                if (c < ZERO)
                    657:                        c = ZERO;
                    658:                i = LINE(vcline + 1) - c;
                    659:                if (i < cnt && c <= WBOT && (!AL || !DL))
                    660:                        vinslin(c, cnt - i, vcline);
                    661:        }
                    662:        *genindent(ind) = 0;
                    663:        vdoappend(genbuf);
                    664:        vcline++;
                    665:        oldhold = hold;
                    666:        hold |= HOLDROL;
                    667:        vopen(dot, c);
                    668:        hold = oldhold;
                    669:        if (value(SLOWOPEN))
                    670:                /*
                    671:                 * Oh, so lazy!
                    672:                 */
                    673:                vscrap();
                    674:        else
                    675:                vsync1(LINE(vcline));
                    676:        cursor = linebuf;
                    677:        linebuf[0] = 0;
                    678:        vappend('o', 1, ind);
                    679: }
                    680: 
                    681: /*
                    682:  * > < and = shift operators.
                    683:  *
                    684:  * Note that =, which aligns lisp, is just a ragged sort of shift,
                    685:  * since it never distributes text between lines.
                    686:  */
                    687: char   vshnam[2] = { 'x', 0 };
                    688: 
                    689: vshftop()
                    690: {
                    691:        register line *addr;
                    692:        register int cnt;
                    693: 
                    694:        if ((cnt = xdw()) < 0)
                    695:                return;
                    696:        addr = dot;
                    697:        vremote(cnt, vshift, 0);
                    698:        vshnam[0] = op;
                    699:        notenam = vshnam;
                    700:        dot = addr;
                    701:        vreplace(vcline, cnt, cnt);
                    702:        if (state == HARDOPEN)
                    703:                vcnt = 0;
                    704:        vrepaint(NOSTR);
                    705: }
                    706: 
                    707: /*
                    708:  * !.
                    709:  *
                    710:  * Filter portions of the buffer through unix commands.
                    711:  */
                    712: vfilter()
                    713: {
                    714:        register line *addr;
                    715:        register int cnt;
                    716:        char *oglobp;
                    717:        short d;
                    718: 
                    719:        if ((cnt = xdw()) < 0)
                    720:                return;
                    721:        if (vglobp)
                    722:                vglobp = uxb;
                    723:        if (readecho('!'))
                    724:                return;
                    725:        oglobp = globp; globp = genbuf + 1;
                    726:        d = peekc; ungetchar(0);
                    727:        CATCH
                    728:                fixech();
                    729:                unix0(0);
                    730:        ONERR
                    731:                splitw = 0;
                    732:                ungetchar(d);
                    733:                vrepaint(cursor);
                    734:                globp = oglobp;
                    735:                return;
                    736:        ENDCATCH
                    737:        ungetchar(d); globp = oglobp;
                    738:        addr = dot;
                    739:        CATCH
                    740:                vgoto(WECHO, 0); flusho();
                    741:                vremote(cnt, filter, 2);
                    742:        ONERR
                    743:                vdirty(0, LINES);
                    744:        ENDCATCH
                    745:        if (dot == zero && dol > zero)
                    746:                dot = one;
                    747:        splitw = 0;
                    748:        notenam = "";
                    749:        /*
                    750:         * BUG: we shouldn't be depending on what undap2 and undap1 are,
                    751:         * since we may be inside a macro.  What's really wanted is the
                    752:         * number of lines we read from the filter.  However, the mistake
                    753:         * will be an overestimate so it only results in extra work,
                    754:         * it shouldn't cause any real screwups.
                    755:         */
                    756:        vreplace(vcline, cnt, undap2 - undap1);
                    757:        dot = addr;
                    758:        if (dot > dol) {
                    759:                dot--;
                    760:                vcline--;
                    761:        }
                    762:        vrepaint(NOSTR);
                    763: }
                    764: 
                    765: /*
                    766:  * Xdw exchanges dot and wdot if appropriate and also checks
                    767:  * that wdot is reasonable.  Its name comes from
                    768:  *     xchange dotand wdot
                    769:  */
                    770: xdw()
                    771: {
                    772:        register char *cp;
                    773:        register int cnt;
                    774: /*
                    775:        register int notp = 0;
                    776:  */
                    777: 
                    778:        if (wdot == NOLINE || wdot < one || wdot > dol) {
                    779:                beep();
                    780:                return (-1);
                    781:        }
                    782:        vsave();
                    783:        setLAST();
                    784:        if (dot > wdot) {
                    785:                register line *addr;
                    786: 
                    787:                vcline -= dot - wdot;
                    788:                addr = dot; dot = wdot; wdot = addr;
                    789:                cp = cursor; cursor = wcursor; wcursor = cp;
                    790:        }
                    791:        /*
                    792:         * If a region is specified but wcursor is at the begining
                    793:         * of the last line, then we move it to be the end of the
                    794:         * previous line (actually off the end).
                    795:         */
                    796:        if (cursor && wcursor == linebuf && wdot > dot) {
                    797:                wdot--;
                    798:                getDOT();
                    799:                if (vpastwh(linebuf) >= cursor)
                    800:                        wcursor = 0;
                    801:                else {
                    802:                        getline(*wdot);
                    803:                        wcursor = strend(linebuf);
                    804:                        getDOT();
                    805:                }
                    806:                /*
                    807:                 * Should prepare in caller for possible dot == wdot.
                    808:                 */
                    809:        }
                    810:        cnt = wdot - dot + 1;
                    811:        if (vreg) {
                    812:                vremote(cnt, YANKreg, vreg);
                    813: /*
                    814:                if (notp)
                    815:                        notpart(vreg);
                    816:  */
                    817:        }
                    818: 
                    819:        /*
                    820:         * Kill buffer code.  If delete operator is c or d, then save
                    821:         * the region in numbered buffers.
                    822:         *
                    823:         * BUG:                 This may be somewhat inefficient due
                    824:         *                      to the way named buffer are implemented,
                    825:         *                      necessitating some optimization.
                    826:         */
                    827:        vreg = 0;
                    828:        if (any(op, "cd")) {
                    829:                vremote(cnt, YANKreg, '1');
                    830: /*
                    831:                if (notp)
                    832:                        notpart('1');
                    833:  */
                    834:        }
                    835:        return (cnt);
                    836: }
                    837: 
                    838: /*
                    839:  * Routine for vremote to call to implement shifts.
                    840:  */
                    841: vshift()
                    842: {
                    843: 
                    844:        shift(op, 1);
                    845: }
                    846: 
                    847: /*
                    848:  * Replace a single character with the next input character.
                    849:  * A funny kind of insert.
                    850:  */
                    851: vrep(cnt)
                    852:        register int cnt;
                    853: {
                    854:        register int i, c;
                    855: 
                    856:        if (cnt > strlen(cursor)) {
                    857:                beep();
                    858:                return;
                    859:        }
                    860:        i = column(cursor + cnt - 1);
                    861:        vcursat(cursor);
                    862:        doomed = i - cindent();
                    863:        if (!vglobp) {
                    864:                c = getesc();
                    865:                if (c == 0) {
                    866:                        vfixcurs();
                    867:                        return;
                    868:                }
                    869:                ungetkey(c);
                    870:        }
                    871:        CP(vutmp, linebuf);
                    872:        if (FIXUNDO)
                    873:                vundkind = VCHNG;
                    874:        wcursor = cursor + cnt;
                    875:        vUD1 = cursor; vUD2 = wcursor;
                    876:        CP(cursor, wcursor);
                    877:        prepapp();
                    878:        vappend('r', cnt, 0);
                    879:        *lastcp++ = INS[0];
                    880:        setLAST();
                    881: }
                    882: 
                    883: /*
                    884:  * Yank.
                    885:  *
                    886:  * Yanking to string registers occurs for free (essentially)
                    887:  * in the routine xdw().
                    888:  */
                    889: vyankit()
                    890: {
                    891:        register int cnt;
                    892: 
                    893:        if (wdot) {
                    894:                if ((cnt = xdw()) < 0)
                    895:                        return;
                    896:                vremote(cnt, yank, 0);
                    897:                setpk();
                    898:                notenam = "yank";
                    899:                if (FIXUNDO)
                    900:                        vundkind = VNONE;
                    901:                DEL[0] = 0;
                    902:                wdot = NOLINE;
                    903:                if (notecnt <= vcnt - vcline && notecnt < value(REPORT))
                    904:                        notecnt = 0;
                    905:                vrepaint(cursor);
                    906:                return;
                    907:        }
                    908:        takeout(DEL);
                    909: }
                    910: 
                    911: /*
                    912:  * Set pkill variables so a put can
                    913:  * know how to put back partial text.
                    914:  * This is necessary because undo needs the complete
                    915:  * line images to be saved, while a put wants to trim
                    916:  * the first and last lines.  The compromise
                    917:  * is for put to be more clever.
                    918:  */
                    919: setpk()
                    920: {
                    921: 
                    922:        if (wcursor) {
                    923:                pkill[0] = cursor;
                    924:                pkill[1] = wcursor;
                    925:        }
                    926: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.