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

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

unix.superglobalmegacorp.com

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