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

unix.superglobalmegacorp.com

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