Annotation of 43BSDReno/usr.bin/ex/ex_vput.c, revision 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_vput.c   7.5 (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:  * Deal with the screen, clearing, cursor positioning, putting characters
        !            17:  * into the screen image, and deleting characters.
        !            18:  * Really hard stuff here is utilizing insert character operations
        !            19:  * on intelligent terminals which differs widely from terminal to terminal.
        !            20:  */
        !            21: vclear()
        !            22: {
        !            23: 
        !            24: #ifdef ADEBUG
        !            25:        if (trace)
        !            26:                tfixnl(), fprintf(trace, "------\nvclear\n");
        !            27: #endif
        !            28:        tputs(CL, LINES, putch);
        !            29:        destcol = 0;
        !            30:        outcol = 0;
        !            31:        destline = 0;
        !            32:        outline = 0;
        !            33:        if (inopen)
        !            34:                vclrbyte(vtube0, WCOLS * (WECHO - ex_ZERO + 1));
        !            35: }
        !            36: 
        !            37: /*
        !            38:  * Clear memory.
        !            39:  */
        !            40: vclrbyte(cp, i)
        !            41:        register char *cp;
        !            42:        register int i;
        !            43: {
        !            44: 
        !            45:        if (i > 0)
        !            46:                do
        !            47:                        *cp++ = 0;
        !            48:                while (--i != 0);
        !            49: }
        !            50: 
        !            51: /*
        !            52:  * Clear a physical display line, high level.
        !            53:  */
        !            54: vclrlin(l, tp)
        !            55:        int l;
        !            56:        line *tp;
        !            57: {
        !            58: 
        !            59:        vigoto(l, 0);
        !            60:        if ((hold & HOLDAT) == 0)
        !            61:                ex_putchar(tp > dol ? ((UPPERCASE || HZ) ? '^' : '~') : '@');
        !            62:        if (state == HARDOPEN)
        !            63:                sethard();
        !            64:        vclreol();
        !            65: }
        !            66: 
        !            67: /*
        !            68:  * Clear to the end of the current physical line
        !            69:  */
        !            70: vclreol()
        !            71: {
        !            72:        register int i, j;
        !            73:        register char *tp;
        !            74: 
        !            75:        if (destcol == WCOLS)
        !            76:                return;
        !            77:        destline += destcol / WCOLS;
        !            78:        destcol %= WCOLS;
        !            79:        if (destline < 0 || destline > WECHO)
        !            80:                error("Internal error: vclreol");
        !            81:        i = WCOLS - destcol;
        !            82:        tp = vtube[destline] + destcol;
        !            83:        if (CE) {
        !            84:                if (IN && *tp || !ateopr()) {
        !            85:                        vcsync();
        !            86:                        vputp(CE, 1);
        !            87:                }
        !            88:                vclrbyte(tp, i);
        !            89:                return;
        !            90:        }
        !            91:        if (*tp == 0)
        !            92:                return;
        !            93:        while (i > 0 && (j = *tp & (QUOTE|TRIM))) {
        !            94:                if (j != ' ' && (j & QUOTE) == 0) {
        !            95:                        destcol = WCOLS - i;
        !            96:                        vputchar(' ');
        !            97:                }
        !            98:                --i, *tp++ = 0;
        !            99:        }
        !           100: }
        !           101: 
        !           102: /*
        !           103:  * Clear the echo line.
        !           104:  * If didphys then its been cleared physically (as
        !           105:  * a side effect of a clear to end of display, e.g.)
        !           106:  * so just do it logically.
        !           107:  * If work here is being held off, just remember, in
        !           108:  * heldech, if work needs to be done, don't do anything.
        !           109:  */
        !           110: vclrech(didphys)
        !           111:        bool didphys;
        !           112: {
        !           113: 
        !           114:        if (Peek_key == ATTN)
        !           115:                return;
        !           116:        if (hold & HOLDECH) {
        !           117:                heldech = !didphys;
        !           118:                return;
        !           119:        }
        !           120:        if (!didphys && (CD || CE)) {
        !           121:                splitw++;
        !           122:                /*
        !           123:                 * If display is retained below, then MUST use CD or CE
        !           124:                 * since we don't really know whats out there.
        !           125:                 * Vigoto might decide (incorrectly) to do nothing.
        !           126:                 */
        !           127:                if (DB) {
        !           128:                        vgoto(WECHO, 0);
        !           129:                        vputp(CD ? CD : CE, 1);
        !           130:                } else {
        !           131:                        if (XT) {
        !           132:                                /*
        !           133:                                 * This code basically handles the t1061
        !           134:                                 * where positioning at (0, 0) won't work
        !           135:                                 * because the terminal won't let you put
        !           136:                                 * the cursor on it's magic cookie.
        !           137:                                 *
        !           138:                                 * Should probably be XS above, or even a
        !           139:                                 * new X? glitch, but right now t1061 is the
        !           140:                                 * only terminal with XT.
        !           141:                                 */
        !           142:                                vgoto(WECHO, 0);
        !           143:                                vputp(DL, 1);
        !           144:                        } else {
        !           145:                                vigoto(WECHO, 0);
        !           146:                                vclreol();
        !           147:                        }
        !           148:                }
        !           149:                splitw = 0;
        !           150:                didphys = 1;
        !           151:        }
        !           152:        if (didphys)
        !           153:                vclrbyte(vtube[WECHO], WCOLS);
        !           154:        heldech = 0;
        !           155: }
        !           156: 
        !           157: /*
        !           158:  * Fix the echo area for use, setting
        !           159:  * the state variable splitw so we wont rollup
        !           160:  * when we move the cursor there.
        !           161:  */
        !           162: fixech()
        !           163: {
        !           164: 
        !           165:        splitw++;
        !           166:        if (state != VISUAL && state != CRTOPEN) {
        !           167:                vclean();
        !           168:                vcnt = 0;
        !           169:        }
        !           170:        vgoto(WECHO, 0); flusho();
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * Put the cursor ``before'' cp.
        !           175:  */
        !           176: vcursbef(cp)
        !           177:        register char *cp;
        !           178: {
        !           179: 
        !           180:        if (cp <= linebuf)
        !           181:                vgotoCL(value(NUMBER) << 3);
        !           182:        else
        !           183:                vgotoCL(column(cp - 1) - 1);
        !           184: }
        !           185: 
        !           186: /*
        !           187:  * Put the cursor ``at'' cp.
        !           188:  */
        !           189: vcursat(cp)
        !           190:        register char *cp;
        !           191: {
        !           192: 
        !           193:        if (cp <= linebuf && linebuf[0] == 0)
        !           194:                vgotoCL(value(NUMBER) << 3);
        !           195:        else
        !           196:                vgotoCL(column(cp - 1));
        !           197: }
        !           198: 
        !           199: /*
        !           200:  * Put the cursor ``after'' cp.
        !           201:  */
        !           202: vcursaft(cp)
        !           203:        register char *cp;
        !           204: {
        !           205: 
        !           206:        vgotoCL(column(cp));
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * Fix the cursor to be positioned in the correct place
        !           211:  * to accept a command.
        !           212:  */
        !           213: vfixcurs()
        !           214: {
        !           215: 
        !           216:        vsetcurs(cursor);
        !           217: }
        !           218: 
        !           219: /*
        !           220:  * Compute the column position implied by the cursor at ``nc'',
        !           221:  * and move the cursor there.
        !           222:  */
        !           223: vsetcurs(nc)
        !           224:        register char *nc;
        !           225: {
        !           226:        register int col;
        !           227: 
        !           228:        col = column(nc);
        !           229:        if (linebuf[0])
        !           230:                col--;
        !           231:        vgotoCL(col);
        !           232:        cursor = nc;
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Move the cursor invisibly, i.e. only remember to do it.
        !           237:  */
        !           238: vigoto(y, x)
        !           239:        int y, x;
        !           240: {
        !           241: 
        !           242:        destline = y;
        !           243:        destcol = x;
        !           244: }
        !           245: 
        !           246: /*
        !           247:  * Move the cursor to the position implied by any previous
        !           248:  * vigoto (or low level hacking with destcol/destline as in readecho).
        !           249:  */
        !           250: vcsync()
        !           251: {
        !           252: 
        !           253:        vgoto(destline, destcol);
        !           254: }
        !           255: 
        !           256: /*
        !           257:  * Goto column x of the current line.
        !           258:  */
        !           259: vgotoCL(x)
        !           260:        register int x;
        !           261: {
        !           262: 
        !           263:        if (splitw)
        !           264:                vgoto(WECHO, x);
        !           265:        else
        !           266:                vgoto(LINE(vcline), x);
        !           267: }
        !           268: 
        !           269: /*
        !           270:  * Invisible goto column x of current line.
        !           271:  */
        !           272: vigotoCL(x)
        !           273:        register int x;
        !           274: {
        !           275: 
        !           276:        if (splitw)
        !           277:                vigoto(WECHO, x);
        !           278:        else
        !           279:                vigoto(LINE(vcline), x);
        !           280: }
        !           281: 
        !           282: /*
        !           283:  * Move cursor to line y, column x, handling wraparound and scrolling.
        !           284:  */
        !           285: vgoto(y, x)
        !           286:        register int y, x;
        !           287: {
        !           288:        register char *tp;
        !           289:        register int c;
        !           290: 
        !           291:        /*
        !           292:         * Fold the possibly too large value of x.
        !           293:         */
        !           294:        if (x >= WCOLS) {
        !           295:                y += x / WCOLS;
        !           296:                x %= WCOLS;
        !           297:        }
        !           298:        if (y < 0)
        !           299:                error("Internal error: vgoto");
        !           300:        if (outcol >= WCOLS) {
        !           301:                if (AM) {
        !           302:                        outline += outcol / WCOLS;
        !           303:                        outcol %= WCOLS;
        !           304:                } else
        !           305:                        outcol = WCOLS - 1;
        !           306:        }
        !           307: 
        !           308:        /*
        !           309:         * In a hardcopy or glass crt open, print the stuff
        !           310:         * implied by a motion, or backspace.
        !           311:         */
        !           312:        if (state == HARDOPEN || state == ONEOPEN) {
        !           313:                if (y != outline)
        !           314:                        error("Line too long for open");
        !           315:                if (x + 1 < outcol - x || (outcol > x && !BS))
        !           316:                        destcol = 0, fgoto();
        !           317:                tp = vtube[WBOT] + outcol;
        !           318:                while (outcol != x)
        !           319:                        if (outcol < x) {
        !           320:                                if (*tp == 0)
        !           321:                                        *tp = ' ';
        !           322:                                c = *tp++ & TRIM;
        !           323:                                vputc(c && (!OS || EO) ? c : ' '), outcol++;
        !           324:                        } else {
        !           325:                                if (BC)
        !           326:                                        vputp(BC, 0);
        !           327:                                else
        !           328:                                        vputc('\b');
        !           329:                                outcol--;
        !           330:                        }
        !           331:                destcol = outcol = x;
        !           332:                destline = outline;
        !           333:                return;
        !           334:        }
        !           335: 
        !           336:        /*
        !           337:         * If the destination position implies a scroll, do it.
        !           338:         */
        !           339:        destline = y;
        !           340:        if (destline > WBOT && (!splitw || destline > WECHO)) {
        !           341:                endim();
        !           342:                vrollup(destline);
        !           343:        }
        !           344: 
        !           345:        /*
        !           346:         * If there really is a motion involved, do it.
        !           347:         * The check here is an optimization based on profiling.
        !           348:         */
        !           349:        destcol = x;
        !           350:        if ((destline - outline) * WCOLS != destcol - outcol) {
        !           351:                if (!MI)
        !           352:                        endim();
        !           353:                fgoto();
        !           354:        }
        !           355: }
        !           356: 
        !           357: /*
        !           358:  * This is the hardest code in the editor, and deals with insert modes
        !           359:  * on different kinds of intelligent terminals.  The complexity is due
        !           360:  * to the cross product of three factors:
        !           361:  *
        !           362:  *     1. Lines may display as more than one segment on the screen.
        !           363:  *     2. There are 2 kinds of intelligent terminal insert modes.
        !           364:  *     3. Tabs squash when you insert characters in front of them,
        !           365:  *        in a way in which current intelligent terminals don't handle.
        !           366:  *
        !           367:  * The two kinds of terminals are typified by the DM2500 or HP2645 for
        !           368:  * one and the CONCEPT-100 or the FOX for the other.
        !           369:  *
        !           370:  * The first (HP2645) kind has an insert mode where the characters
        !           371:  * fall off the end of the line and the screen is shifted rigidly
        !           372:  * no matter how the display came about.
        !           373:  *
        !           374:  * The second (CONCEPT-100) kind comes from terminals which are designed
        !           375:  * for forms editing and which distinguish between blanks and ``spaces''
        !           376:  * on the screen, spaces being like blank, but never having had
        !           377:  * and data typed into that screen position (since, e.g. a clear operation
        !           378:  * like clear screen).  On these terminals, when you insert a character,
        !           379:  * the characters from where you are to the end of the screen shift
        !           380:  * over till a ``space'' is found, and the null character there gets
        !           381:  * eaten up.
        !           382:  *
        !           383:  *
        !           384:  * The code here considers the line as consisting of several parts
        !           385:  * the first part is the ``doomed'' part, i.e. a part of the line
        !           386:  * which is being typed over.  Next comes some text up to the first
        !           387:  * following tab.  The tab is the next segment of the line, and finally
        !           388:  * text after the tab.
        !           389:  *
        !           390:  * We have to consider each of these segments and the effect of the
        !           391:  * insertion of a character on them.  On terminals like HP2645's we
        !           392:  * must simulate a multi-line insert mode using the primitive one
        !           393:  * line insert mode.  If we are inserting in front of a tab, we have
        !           394:  * to either delete characters from the tab or insert white space
        !           395:  * (when the tab reaches a new spot where it gets larger) before we
        !           396:  * insert the new character.
        !           397:  *
        !           398:  * On a terminal like a CONCEPT our strategy is to make all
        !           399:  * blanks be displayed, while trying to keep the screen having ``spaces''
        !           400:  * for portions of tabs.  In this way the terminal hardward does some
        !           401:  * of the hacking for compression of tabs, although this tends to
        !           402:  * disappear as you work on the line and spaces change into blanks.
        !           403:  *
        !           404:  * There are a number of boundary conditions (like typing just before
        !           405:  * the first following tab) where we can avoid a lot of work.  Most
        !           406:  * of them have to be dealt with explicitly because performance is
        !           407:  * much, much worse if we don't.
        !           408:  *
        !           409:  * A final thing which is hacked here is two flavors of insert mode.
        !           410:  * Datamedia's do this by an insert mode which you enter and leave
        !           411:  * and by having normal motion character operate differently in this
        !           412:  * mode, notably by having a newline insert a line on the screen in
        !           413:  * this mode.  This generally means it is unsafe to move around
        !           414:  * the screen ignoring the fact that we are in this mode.
        !           415:  * This is possible on some terminals, and wins big (e.g. HP), so
        !           416:  * we encode this as a ``can move in insert capability'' mi,
        !           417:  * and terminals which have it can do insert mode with much less
        !           418:  * work when tabs are present following the cursor on the current line.
        !           419:  */
        !           420: 
        !           421: /*
        !           422:  * Routine to expand a tab, calling the normal Outchar routine
        !           423:  * to put out each implied character.  Note that we call outchar
        !           424:  * with a QUOTE.  We use QUOTE internally to represent a position
        !           425:  * which is part of the expansion of a tab.
        !           426:  */
        !           427: vgotab()
        !           428: {
        !           429:        register int i = tabcol(destcol, value(TABSTOP)) - destcol;
        !           430: 
        !           431:        do
        !           432:                (*Outchar)(QUOTE);
        !           433:        while (--i);
        !           434: }
        !           435: 
        !           436: /*
        !           437:  * Variables for insert mode.
        !           438:  */
        !           439: int    linend;                 /* The column position of end of line */
        !           440: int    tabstart;               /* Column of start of first following tab */
        !           441: int    tabend;                 /* Column of end of following tabs */
        !           442: int    tabsize;                /* Size of the following tabs */
        !           443: int    tabslack;               /* Number of ``spaces'' in following tabs */
        !           444: int    inssiz;                 /* Number of characters to be inserted */
        !           445: int    inscol;                 /* Column where insertion is taking place */
        !           446: int    shft;                   /* Amount tab expansion shifted rest of line */
        !           447: int    slakused;               /* This much of tabslack will be used up */
        !           448: 
        !           449: /*
        !           450:  * This routine MUST be called before insert mode is run,
        !           451:  * and brings all segments of the current line to the top
        !           452:  * of the screen image buffer so it is easier for us to
        !           453:  * maniuplate them.
        !           454:  */
        !           455: vprepins()
        !           456: {
        !           457:        register int i;
        !           458:        register char *cp = vtube0;
        !           459: 
        !           460:        for (i = 0; i < DEPTH(vcline); i++) {
        !           461:                vmaktop(LINE(vcline) + i, cp);
        !           462:                cp += WCOLS;
        !           463:        }
        !           464: }
        !           465: 
        !           466: vmaktop(p, cp)
        !           467:        register int p;
        !           468:        char *cp;
        !           469: {
        !           470:        register int i;
        !           471:        char temp[TUBECOLS];
        !           472: 
        !           473:        if (p < 0 || vtube[p] == cp)
        !           474:                return;
        !           475:        for (i = ex_ZERO; i <= WECHO; i++)
        !           476:                if (vtube[i] == cp) {
        !           477:                        copy(temp, vtube[i], WCOLS);
        !           478:                        copy(vtube[i], vtube[p], WCOLS);
        !           479:                        copy(vtube[p], temp, WCOLS);
        !           480:                        vtube[i] = vtube[p];
        !           481:                        vtube[p] = cp;
        !           482:                        return;
        !           483:                }
        !           484:        error("Line too long");
        !           485: }
        !           486: 
        !           487: /*
        !           488:  * Insert character c at current cursor position.
        !           489:  * Multi-character inserts occur only as a result
        !           490:  * of expansion of tabs (i.e. inssize == 1 except
        !           491:  * for tabs) and code assumes this in several place
        !           492:  * to make life simpler.
        !           493:  */
        !           494: vinschar(c)
        !           495:        int c;          /* mjm: char --> int */
        !           496: {
        !           497:        register int i;
        !           498:        register char *tp;
        !           499: 
        !           500:        if ((!IM || !EI) && ((hold & HOLDQIK) || !value(REDRAW) || value(SLOWOPEN))) {
        !           501:                /*
        !           502:                 * Don't want to try to use terminal
        !           503:                 * insert mode, or to try to fake it.
        !           504:                 * Just put the character out; the screen
        !           505:                 * will probably be wrong but we will fix it later.
        !           506:                 */
        !           507:                if (c == '\t') {
        !           508:                        vgotab();
        !           509:                        return;
        !           510:                }
        !           511:                vputchar(c);
        !           512:                if (DEPTH(vcline) * WCOLS + !value(REDRAW) >
        !           513:                    (destline - LINE(vcline)) * WCOLS + destcol)
        !           514:                        return;
        !           515:                /*
        !           516:                 * The next line is about to be clobbered
        !           517:                 * make space for another segment of this line
        !           518:                 * (on an intelligent terminal) or just remember
        !           519:                 * that next line was clobbered (on a dumb one
        !           520:                 * if we don't care to redraw the tail.
        !           521:                 */
        !           522:                if (AL) {
        !           523:                        vnpins(0);
        !           524:                } else {
        !           525:                        c = LINE(vcline) + DEPTH(vcline);
        !           526:                        if (c < LINE(vcline + 1) || c > WBOT)
        !           527:                                return;
        !           528:                        i = destcol;
        !           529:                        vinslin(c, 1, vcline);
        !           530:                        DEPTH(vcline)++;
        !           531:                        vigoto(c, i);
        !           532:                        vprepins();
        !           533:                }
        !           534:                return;
        !           535:        }
        !           536:        /*
        !           537:         * Compute the number of positions in the line image of the
        !           538:         * current line.  This is done from the physical image
        !           539:         * since that is faster.  Note that we have no memory
        !           540:         * from insertion to insertion so that routines which use
        !           541:         * us don't have to worry about moving the cursor around.
        !           542:         */
        !           543:        if (*vtube0 == 0)
        !           544:                linend = 0;
        !           545:        else {
        !           546:                /*
        !           547:                 * Search backwards for a non-null character
        !           548:                 * from the end of the displayed line.
        !           549:                 */
        !           550:                i = WCOLS * DEPTH(vcline);
        !           551:                if (i == 0)
        !           552:                        i = WCOLS;
        !           553:                tp = vtube0 + i;
        !           554:                while (*--tp == 0)
        !           555:                        if (--i == 0)
        !           556:                                break;
        !           557:                linend = i;
        !           558:        }
        !           559: 
        !           560:        /*
        !           561:         * We insert at a position based on the physical location
        !           562:         * of the output cursor.
        !           563:         */
        !           564:        inscol = destcol + (destline - LINE(vcline)) * WCOLS;
        !           565:        if (c == '\t') {
        !           566:                /*
        !           567:                 * Characters inserted from a tab must be
        !           568:                 * remembered as being part of a tab, but we can't
        !           569:                 * use QUOTE here since we really need to print blanks.
        !           570:                 * QUOTE|' ' is the representation of this.
        !           571:                 */
        !           572:                inssiz = tabcol(inscol, value(TABSTOP)) - inscol;
        !           573:                c = ' ' | QUOTE;
        !           574:        } else
        !           575:                inssiz = 1;
        !           576: 
        !           577:        /*
        !           578:         * If the text to be inserted is less than the number
        !           579:         * of doomed positions, then we don't need insert mode,
        !           580:         * rather we can just typeover.
        !           581:         */
        !           582:        if (inssiz <= doomed) {
        !           583:                endim();
        !           584:                if (inscol != linend)
        !           585:                        doomed -= inssiz;
        !           586:                do
        !           587:                        vputchar(c);
        !           588:                while (--inssiz);
        !           589:                return;
        !           590:        }
        !           591: 
        !           592:        /*
        !           593:         * Have to really do some insertion, thus
        !           594:         * stake out the bounds of the first following
        !           595:         * group of tabs, computing starting position,
        !           596:         * ending position, and the number of ``spaces'' therein
        !           597:         * so we can tell how much it will squish.
        !           598:         */
        !           599:        tp = vtube0 + inscol;
        !           600:        for (i = inscol; i < linend; i++)
        !           601:                if (*tp++ & QUOTE) {
        !           602:                        --tp;
        !           603:                        break;
        !           604:                }
        !           605:        tabstart = tabend = i;
        !           606:        tabslack = 0;
        !           607:        while (tabend < linend) {
        !           608:                i = *tp++;
        !           609:                if ((i & QUOTE) == 0)
        !           610:                        break;
        !           611:                if ((i & TRIM) == 0)
        !           612:                        tabslack++;
        !           613:                tabsize++;
        !           614:                tabend++;
        !           615:        }
        !           616:        tabsize = tabend - tabstart;
        !           617: 
        !           618:        /*
        !           619:         * For HP's and DM's, e.g. tabslack has no meaning.
        !           620:         */
        !           621:        if (!IN)
        !           622:                tabslack = 0;
        !           623: #ifdef IDEBUG
        !           624:        if (trace) {
        !           625:                fprintf(trace, "inscol %d, inssiz %d, tabstart %d, ",
        !           626:                        inscol, inssiz, tabstart);
        !           627:                fprintf(trace, "tabend %d, tabslack %d, linend %d\n",
        !           628:                        tabend, tabslack, linend);
        !           629:        }
        !           630: #endif
        !           631: 
        !           632:        /*
        !           633:         * The real work begins.
        !           634:         */
        !           635:        slakused = 0;
        !           636:        shft = 0;
        !           637:        if (tabsize) {
        !           638:                /*
        !           639:                 * There are tabs on this line.
        !           640:                 * If they need to expand, then the rest of the line
        !           641:                 * will have to be shifted over.  In this case,
        !           642:                 * we will need to make sure there are no ``spaces''
        !           643:                 * in the rest of the line (on e.g. CONCEPT-100)
        !           644:                 * and then grab another segment on the screen if this
        !           645:                 * line is now deeper.  We then do the shift
        !           646:                 * implied by the insertion.
        !           647:                 */
        !           648:                if (inssiz >= doomed + tabcol(tabstart, value(TABSTOP)) - tabstart) {
        !           649:                        if (IN)
        !           650:                                vrigid();
        !           651:                        vneedpos(value(TABSTOP));
        !           652:                        vishft();
        !           653:                }
        !           654:        } else if (inssiz > doomed)
        !           655:                /*
        !           656:                 * No tabs, but line may still get deeper.
        !           657:                 */
        !           658:                vneedpos(inssiz - doomed);
        !           659:        /*
        !           660:         * Now put in the inserted characters.
        !           661:         */
        !           662:        viin(c);
        !           663: 
        !           664:        /*
        !           665:         * Now put the cursor in its final resting place.
        !           666:         */
        !           667:        destline = LINE(vcline);
        !           668:        destcol = inscol + inssiz;
        !           669:        vcsync();
        !           670: }
        !           671: 
        !           672: /*
        !           673:  * Rigidify the rest of the line after the first
        !           674:  * group of following tabs, typing blanks over ``spaces''.
        !           675:  */
        !           676: vrigid()
        !           677: {
        !           678:        register int col;
        !           679:        register char *tp = vtube0 + tabend;
        !           680: 
        !           681:        for (col = tabend; col < linend; col++)
        !           682:                if ((*tp++ & TRIM) == 0) {
        !           683:                        endim();
        !           684:                        vgotoCL(col);
        !           685:                        vputchar(' ' | QUOTE);
        !           686:                }
        !           687: }
        !           688: 
        !           689: /*
        !           690:  * We need cnt more positions on this line.
        !           691:  * Open up new space on the screen (this may in fact be a
        !           692:  * screen rollup).
        !           693:  *
        !           694:  * On a dumb terminal we may infact redisplay the rest of the
        !           695:  * screen here brute force to keep it pretty.
        !           696:  */
        !           697: vneedpos(cnt)
        !           698:        int cnt;
        !           699: {
        !           700:        register int d = DEPTH(vcline);
        !           701:        register int rmdr = d * WCOLS - linend;
        !           702: 
        !           703:        if (cnt <= rmdr - IN)
        !           704:                return;
        !           705:        endim();
        !           706:        vnpins(1);
        !           707: }
        !           708: 
        !           709: vnpins(dosync)
        !           710:        int dosync;
        !           711: {
        !           712:        register int d = DEPTH(vcline);
        !           713:        register int e;
        !           714: 
        !           715:        e = LINE(vcline) + DEPTH(vcline);
        !           716:        if (e < LINE(vcline + 1)) {
        !           717:                vigoto(e, 0);
        !           718:                vclreol();
        !           719:                return;
        !           720:        }
        !           721:        DEPTH(vcline)++;
        !           722:        if (e < WECHO) {
        !           723:                e = vglitchup(vcline, d);
        !           724:                vigoto(e, 0); vclreol();
        !           725:                if (dosync) {
        !           726:                        int (*Ooutchar)() = Outchar;
        !           727:                        Outchar = vputchar;
        !           728:                        vsync(e + 1);
        !           729:                        Outchar = Ooutchar;
        !           730:                }
        !           731:        } else {
        !           732:                vup1();
        !           733:                vigoto(WBOT, 0);
        !           734:                vclreol();
        !           735:        }
        !           736:        vprepins();
        !           737: }
        !           738: 
        !           739: /*
        !           740:  * Do the shift of the next tabstop implied by
        !           741:  * insertion so it expands.
        !           742:  */
        !           743: vishft()
        !           744: {
        !           745:        int tshft = 0;
        !           746:        int j;
        !           747:        register int i;
        !           748:        register char *tp = vtube0;
        !           749:        register char *up;
        !           750:        short oldhold = hold;
        !           751: 
        !           752:        shft = value(TABSTOP);
        !           753:        hold |= HOLDPUPD;
        !           754:        if (!IM && !EI) {
        !           755:                /*
        !           756:                 * Dumb terminals are easy, we just have
        !           757:                 * to retype the text.
        !           758:                 */
        !           759:                vigotoCL(tabend + shft);
        !           760:                up = tp + tabend;
        !           761:                for (i = tabend; i < linend; i++)
        !           762:                        vputchar(*up++);
        !           763:        } else if (IN) {
        !           764:                /*
        !           765:                 * CONCEPT-like terminals do most of the work for us,
        !           766:                 * we don't have to muck with simulation of multi-line
        !           767:                 * insert mode.  Some of the shifting may come for free
        !           768:                 * also if the tabs don't have enough slack to take up
        !           769:                 * all the inserted characters.
        !           770:                 */
        !           771:                i = shft;
        !           772:                slakused = inssiz - doomed;
        !           773:                if (slakused > tabslack) {
        !           774:                        i -= slakused - tabslack;
        !           775:                        slakused -= tabslack;
        !           776:                }
        !           777:                if (i > 0 && tabend != linend) {
        !           778:                        tshft = i;
        !           779:                        vgotoCL(tabend);
        !           780:                        goim();
        !           781:                        do
        !           782:                                vputchar(' ' | QUOTE);
        !           783:                        while (--i);
        !           784:                }
        !           785:        } else {
        !           786:                /*
        !           787:                 * HP and Datamedia type terminals have to have multi-line
        !           788:                 * insert faked.  Hack each segment after where we are
        !           789:                 * (going backwards to where we are.)  We then can
        !           790:                 * hack the segment where the end of the first following
        !           791:                 * tab group is.
        !           792:                 */
        !           793:                for (j = DEPTH(vcline) - 1; j > (tabend + shft) / WCOLS; j--) {
        !           794:                        vgotoCL(j * WCOLS);
        !           795:                        goim();
        !           796:                        up = tp + j * WCOLS - shft;
        !           797:                        i = shft;
        !           798:                        do {
        !           799:                                if (*up)
        !           800:                                        vputchar(*up++);
        !           801:                                else
        !           802:                                        break;
        !           803:                        } while (--i);
        !           804:                }
        !           805:                vigotoCL(tabstart);
        !           806:                i = shft - (inssiz - doomed);
        !           807:                if (i > 0) {
        !           808:                        tabslack = inssiz - doomed;
        !           809:                        vcsync();
        !           810:                        goim();
        !           811:                        do
        !           812:                                vputchar(' ');
        !           813:                        while (--i);
        !           814:                }
        !           815:        }
        !           816:        /*
        !           817:         * Now do the data moving in the internal screen
        !           818:         * image which is common to all three cases.
        !           819:         */
        !           820:        tp += linend;
        !           821:        up = tp + shft;
        !           822:        i = linend - tabend;
        !           823:        if (i > 0)
        !           824:                do
        !           825:                        *--up = *--tp;
        !           826:                while (--i);
        !           827:        if (IN && tshft) {
        !           828:                i = tshft;
        !           829:                do
        !           830:                        *--up = ' ' | QUOTE;
        !           831:                while (--i);
        !           832:        }
        !           833:        hold = oldhold;
        !           834: }
        !           835: 
        !           836: /*
        !           837:  * Now do the insert of the characters (finally).
        !           838:  */
        !           839: viin(c)
        !           840:        int c;          /* mjm: char --> int */
        !           841: {
        !           842:        register char *tp, *up;
        !           843:        register int i, j;
        !           844:        register bool noim = 0;
        !           845:        int remdoom;
        !           846:        short oldhold = hold;
        !           847: 
        !           848:        hold |= HOLDPUPD;
        !           849:        if (tabsize && (IM && EI) && inssiz - doomed > tabslack)
        !           850:                /*
        !           851:                 * There is a tab out there which will be affected
        !           852:                 * by the insertion since there aren't enough doomed
        !           853:                 * characters to take up all the insertion and we do
        !           854:                 * have insert mode capability.
        !           855:                 */
        !           856:                if (inscol + doomed == tabstart) {
        !           857:                        /*
        !           858:                         * The end of the doomed characters sits right at the
        !           859:                         * start of the tabs, then we don't need to use insert
        !           860:                         * mode; unless the tab has already been expanded
        !           861:                         * in which case we MUST use insert mode.
        !           862:                         */
        !           863:                        slakused = 0;
        !           864:                        noim = !shft;
        !           865:                } else {
        !           866:                        /*
        !           867:                         * The last really special case to handle is case
        !           868:                         * where the tab is just sitting there and doesn't
        !           869:                         * have enough slack to let the insertion take
        !           870:                         * place without shifting the rest of the line
        !           871:                         * over.  In this case we have to go out and
        !           872:                         * delete some characters of the tab before we start
        !           873:                         * or the answer will be wrong, as the rest of the
        !           874:                         * line will have been shifted.  This code means
        !           875:                         * that terminals with only insert chracter (no
        !           876:                         * delete character) won't work correctly.
        !           877:                         */
        !           878:                        i = inssiz - doomed - tabslack - slakused;
        !           879:                        i %= value(TABSTOP);
        !           880:                        if (i > 0) {
        !           881:                                vgotoCL(tabstart);
        !           882:                                godm();
        !           883:                                for (i = inssiz - doomed - tabslack; i > 0; i--)
        !           884:                                        vputp(DC, DEPTH(vcline));
        !           885:                                enddm();
        !           886:                        }
        !           887:                }
        !           888: 
        !           889:        /* 
        !           890:         * Now put out the characters of the actual insertion.
        !           891:         */
        !           892:        vigotoCL(inscol);
        !           893:        remdoom = doomed;
        !           894:        for (i = inssiz; i > 0; i--) {
        !           895:                if (remdoom > 0) {
        !           896:                        remdoom--;
        !           897:                        endim();
        !           898:                } else if (noim)
        !           899:                        endim();
        !           900:                else if (IM && EI) {
        !           901:                        vcsync();
        !           902:                        goim();
        !           903:                }
        !           904:                vputchar(c);
        !           905:        }
        !           906: 
        !           907:        if (!IM || !EI) {
        !           908:                /*
        !           909:                 * We are a dumb terminal; brute force update
        !           910:                 * the rest of the line; this is very much an n^^2 process,
        !           911:                 * and totally unreasonable at low speed.
        !           912:                 *
        !           913:                 * You asked for it, you get it.
        !           914:                 */
        !           915:                tp = vtube0 + inscol + doomed;
        !           916:                for (i = inscol + doomed; i < tabstart; i++)
        !           917:                        vputchar(*tp++);
        !           918:                hold = oldhold;
        !           919:                vigotoCL(tabstart + inssiz - doomed);
        !           920:                for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
        !           921:                        vputchar(' ' | QUOTE);
        !           922:        } else {
        !           923:                if (!IN) {
        !           924:                        /*
        !           925:                         * On terminals without multi-line
        !           926:                         * insert in the hardware, we must go fix the segments
        !           927:                         * between the inserted text and the following
        !           928:                         * tabs, if they are on different lines.
        !           929:                         *
        !           930:                         * Aaargh.
        !           931:                         */
        !           932:                        tp = vtube0;
        !           933:                        for (j = (inscol + inssiz - 1) / WCOLS + 1;
        !           934:                            j <= (tabstart + inssiz - doomed - 1) / WCOLS; j++) {
        !           935:                                vgotoCL(j * WCOLS);
        !           936:                                i = inssiz - doomed;
        !           937:                                up = tp + j * WCOLS - i;
        !           938:                                goim();
        !           939:                                do
        !           940:                                        vputchar(*up++);
        !           941:                                while (--i && *up);
        !           942:                        }
        !           943:                } else {
        !           944:                        /*
        !           945:                         * On terminals with multi line inserts,
        !           946:                         * life is simpler, just reflect eating of
        !           947:                         * the slack.
        !           948:                         */
        !           949:                        tp = vtube0 + tabend;
        !           950:                        for (i = tabsize - (inssiz - doomed); i >= 0; i--) {
        !           951:                                if ((*--tp & (QUOTE|TRIM)) == QUOTE) {
        !           952:                                        --tabslack;
        !           953:                                        if (tabslack >= slakused)
        !           954:                                                continue;
        !           955:                                }
        !           956:                                *tp = ' ' | QUOTE;
        !           957:                        }
        !           958:                }
        !           959:                /*
        !           960:                 * Blank out the shifted positions to be tab positions.
        !           961:                 */
        !           962:                if (shft) {
        !           963:                        tp = vtube0 + tabend + shft;
        !           964:                        for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
        !           965:                                if ((*--tp & QUOTE) == 0)
        !           966:                                        *tp = ' ' | QUOTE;
        !           967:                }
        !           968:        }
        !           969: 
        !           970:        /*
        !           971:         * Finally, complete the screen image update
        !           972:         * to reflect the insertion.
        !           973:         */
        !           974:        hold = oldhold;
        !           975:        tp = vtube0 + tabstart; up = tp + inssiz - doomed;
        !           976:        for (i = tabstart; i > inscol + doomed; i--)
        !           977:                *--up = *--tp;
        !           978:        for (i = inssiz; i > 0; i--)
        !           979:                *--up = c;
        !           980:        doomed = 0;
        !           981: }
        !           982: 
        !           983: /*
        !           984:  * Go into ``delete mode''.  If the
        !           985:  * sequence which goes into delete mode
        !           986:  * is the same as that which goes into insert
        !           987:  * mode, then we are in delete mode already.
        !           988:  */
        !           989: godm()
        !           990: {
        !           991: 
        !           992:        if (insmode) {
        !           993:                if (eq(DM, IM))
        !           994:                        return;
        !           995:                endim();
        !           996:        }
        !           997:        vputp(DM, 0);
        !           998: }
        !           999: 
        !          1000: /*
        !          1001:  * If we are coming out of delete mode, but
        !          1002:  * delete and insert mode end with the same sequence,
        !          1003:  * it wins to pretend we are now in insert mode,
        !          1004:  * since we will likely want to be there again soon
        !          1005:  * if we just moved over to delete space from part of
        !          1006:  * a tab (above).
        !          1007:  */
        !          1008: enddm()
        !          1009: {
        !          1010: 
        !          1011:        if (eq(DM, IM)) {
        !          1012:                insmode = 1;
        !          1013:                return;
        !          1014:        }
        !          1015:        vputp(ED, 0);
        !          1016: }
        !          1017: 
        !          1018: /*
        !          1019:  * In and out of insert mode.
        !          1020:  * Note that the code here demands that there be
        !          1021:  * a string for insert mode (the null string) even
        !          1022:  * if the terminal does all insertions a single character
        !          1023:  * at a time, since it branches based on whether IM is null.
        !          1024:  */
        !          1025: goim()
        !          1026: {
        !          1027: 
        !          1028:        if (!insmode)
        !          1029:                vputp(IM, 0);
        !          1030:        insmode = 1;
        !          1031: }
        !          1032: 
        !          1033: endim()
        !          1034: {
        !          1035: 
        !          1036:        if (insmode) {
        !          1037:                vputp(EI, 0);
        !          1038:                insmode = 0;
        !          1039:        }
        !          1040: }
        !          1041: 
        !          1042: /*
        !          1043:  * Put the character c on the screen at the current cursor position.
        !          1044:  * This routine handles wraparound and scrolling and understands not
        !          1045:  * to roll when splitw is set, i.e. we are working in the echo area.
        !          1046:  * There is a bunch of hacking here dealing with the difference between
        !          1047:  * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
        !          1048:  * code to deal with terminals which overstrike, including CRT's where
        !          1049:  * you can erase overstrikes with some work.  CRT's which do underlining
        !          1050:  * implicitly which has to be erased (like CONCEPTS) are also handled.
        !          1051:  */
        !          1052: vputchar(c)
        !          1053:        register int c;
        !          1054: {
        !          1055:        register char *tp;
        !          1056:        register int d;
        !          1057: 
        !          1058:        c &= (QUOTE|TRIM);
        !          1059: #ifdef TRACE
        !          1060:        if (trace)
        !          1061:                tracec(c);
        !          1062: #endif
        !          1063:        /* Fix problem of >79 chars on echo line. */
        !          1064:        if (destcol >= WCOLS-1 && splitw && destline == WECHO)
        !          1065:                pofix();
        !          1066:        if (destcol >= WCOLS) {
        !          1067:                destline += destcol / WCOLS;
        !          1068:                destcol %= WCOLS;
        !          1069:        }
        !          1070:        if (destline > WBOT && (!splitw || destline > WECHO))
        !          1071:                vrollup(destline);
        !          1072:        tp = vtube[destline] + destcol;
        !          1073:        switch (c) {
        !          1074: 
        !          1075:        case '\t':
        !          1076:                vgotab();
        !          1077:                return;
        !          1078: 
        !          1079:        case ' ':
        !          1080:                /*
        !          1081:                 * We can get away without printing a space in a number
        !          1082:                 * of cases, but not always.  We get away with doing nothing
        !          1083:                 * if we are not in insert mode, and not on a CONCEPT-100
        !          1084:                 * like terminal, and either not in hardcopy open or in hardcopy
        !          1085:                 * open on a terminal with no overstriking, provided,
        !          1086:                 * in all cases, that nothing has ever been displayed
        !          1087:                 * at this position.  Ugh.
        !          1088:                 */
        !          1089:                if (!insmode && !IN && (state != HARDOPEN || OS) && (*tp&TRIM) == 0) {
        !          1090:                        *tp = ' ';
        !          1091:                        destcol++;
        !          1092:                        return;
        !          1093:                }
        !          1094:                goto def;
        !          1095: 
        !          1096:        case QUOTE:
        !          1097:                if (insmode) {
        !          1098:                        /*
        !          1099:                         * When in insert mode, tabs have to expand
        !          1100:                         * to real, printed blanks.
        !          1101:                         */
        !          1102:                        c = ' ' | QUOTE;
        !          1103:                        goto def;
        !          1104:                }
        !          1105:                if (*tp == 0) {
        !          1106:                        /*
        !          1107:                         * A ``space''.
        !          1108:                         */
        !          1109:                        if ((hold & HOLDPUPD) == 0)
        !          1110:                                *tp = QUOTE;
        !          1111:                        destcol++;
        !          1112:                        return;
        !          1113:                }
        !          1114:                /*
        !          1115:                 * A ``space'' ontop of a part of a tab.
        !          1116:                 */
        !          1117:                if (*tp & QUOTE) {
        !          1118:                        destcol++;
        !          1119:                        return;
        !          1120:                }
        !          1121:                c = ' ' | QUOTE;
        !          1122:                /* fall into ... */
        !          1123: 
        !          1124: def:
        !          1125:        default:
        !          1126:                d = *tp & TRIM;
        !          1127:                /*
        !          1128:                 * Now get away with doing nothing if the characters
        !          1129:                 * are the same, provided we are not in insert mode
        !          1130:                 * and if we are in hardopen, that the terminal has overstrike.
        !          1131:                 */
        !          1132:                if (d == (c & TRIM) && !insmode && (state != HARDOPEN || OS)) {
        !          1133:                        if ((hold & HOLDPUPD) == 0)
        !          1134:                                *tp = c;
        !          1135:                        destcol++;
        !          1136:                        return;
        !          1137:                }
        !          1138:                /*
        !          1139:                 * Backwards looking optimization.
        !          1140:                 * The low level cursor motion routines will use
        !          1141:                 * a cursor motion right sequence to step 1 character
        !          1142:                 * right.  On, e.g., a DM3025A this is 2 characters
        !          1143:                 * and printing is noticeably slower at 300 baud.
        !          1144:                 * Since the low level routines are not allowed to use
        !          1145:                 * spaces for positioning, we discover the common
        !          1146:                 * case of a single space here and force a space
        !          1147:                 * to be printed.
        !          1148:                 */
        !          1149:                if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) {
        !          1150:                        vputc(' ');
        !          1151:                        outcol++;
        !          1152:                }
        !          1153: 
        !          1154:                /*
        !          1155:                 * This is an inline expansion a call to vcsync() dictated
        !          1156:                 * by high frequency in a profile.
        !          1157:                 */
        !          1158:                if (outcol != destcol || outline != destline)
        !          1159:                        vgoto(destline, destcol);
        !          1160: 
        !          1161:                /*
        !          1162:                 * Deal with terminals which have overstrike.
        !          1163:                 * We handle erasing general overstrikes, erasing
        !          1164:                 * underlines on terminals (such as CONCEPTS) which
        !          1165:                 * do underlining correctly automatically (e.g. on nroff
        !          1166:                 * output), and remembering, in hardcopy mode,
        !          1167:                 * that we have overstruct something.
        !          1168:                 */
        !          1169:                if (!insmode && d && d != ' ' && d != (c & TRIM)) {
        !          1170:                        if (EO && (OS || UL && (c == '_' || d == '_'))) {
        !          1171:                                vputc(' ');
        !          1172:                                outcol++, destcol++;
        !          1173:                                back1();
        !          1174:                        } else
        !          1175:                                rubble = 1;
        !          1176:                }
        !          1177: 
        !          1178:                /*
        !          1179:                 * Unless we are just bashing characters around for
        !          1180:                 * inner working of insert mode, update the display.
        !          1181:                 */
        !          1182:                if ((hold & HOLDPUPD) == 0)
        !          1183:                        *tp = c;
        !          1184: 
        !          1185:                /*
        !          1186:                 * In insert mode, put out the IC sequence, padded
        !          1187:                 * based on the depth of the current line.
        !          1188:                 * A terminal which had no real insert mode, rather
        !          1189:                 * opening a character position at a time could do this.
        !          1190:                 * Actually should use depth to end of current line
        !          1191:                 * but this rarely matters.
        !          1192:                 */
        !          1193:                if (insmode)
        !          1194:                        vputp(IC, DEPTH(vcline));
        !          1195:                vputc(c & TRIM);
        !          1196: 
        !          1197:                /*
        !          1198:                 * In insert mode, IP is a post insert pad.
        !          1199:                 */
        !          1200:                if (insmode)
        !          1201:                        vputp(IP, DEPTH(vcline));
        !          1202:                destcol++, outcol++;
        !          1203: 
        !          1204:                /*
        !          1205:                 * CONCEPT braindamage in early models:  after a wraparound
        !          1206:                 * the next newline is eaten.  It's hungry so we just
        !          1207:                 * feed it now rather than worrying about it.
        !          1208:                 * Fixed to use return linefeed to work right
        !          1209:                 * on vt100/tab132 as well as concept.
        !          1210:                 */
        !          1211:                if (XN && outcol % WCOLS == 0) {
        !          1212:                        vputc('\r');
        !          1213:                        vputc('\n');
        !          1214:                }
        !          1215:        }
        !          1216: }
        !          1217: 
        !          1218: /*
        !          1219:  * Delete display positions stcol through endcol.
        !          1220:  * Amount of use of special terminal features here is limited.
        !          1221:  */
        !          1222: physdc(stcol, endcol)
        !          1223:        int stcol, endcol;
        !          1224: {
        !          1225:        register char *tp, *up;
        !          1226:        char *tpe;
        !          1227:        register int i;
        !          1228:        register int nc = endcol - stcol;
        !          1229: 
        !          1230: #ifdef IDEBUG
        !          1231:        if (trace)
        !          1232:                tfixnl(), fprintf(trace, "physdc(%d, %d)\n", stcol, endcol);
        !          1233: #endif
        !          1234:        if (!DC || nc <= 0)
        !          1235:                return;
        !          1236:        if (IN) {
        !          1237:                /*
        !          1238:                 * CONCEPT-100 like terminal.
        !          1239:                 * If there are any ``spaces'' in the material to be
        !          1240:                 * deleted, then this is too hard, just retype.
        !          1241:                 */
        !          1242:                vprepins();
        !          1243:                up = vtube0 + stcol;
        !          1244:                i = nc;
        !          1245:                do
        !          1246:                        if ((*up++ & (QUOTE|TRIM)) == QUOTE)
        !          1247:                                return;
        !          1248:                while (--i);
        !          1249:                i = 2 * nc;
        !          1250:                do
        !          1251:                        if (*up == 0 || (*up++ & QUOTE) == QUOTE)
        !          1252:                                return;
        !          1253:                while (--i);
        !          1254:                vgotoCL(stcol);
        !          1255:        } else {
        !          1256:                /*
        !          1257:                 * HP like delete mode.
        !          1258:                 * Compute how much text we are moving over by deleting.
        !          1259:                 * If it appears to be faster to just retype
        !          1260:                 * the line, do nothing and that will be done later.
        !          1261:                 * We are assuming 2 output characters per deleted
        !          1262:                 * characters and that clear to end of line is available.
        !          1263:                 */
        !          1264:                i = stcol / WCOLS;
        !          1265:                if (i != endcol / WCOLS)
        !          1266:                        return;
        !          1267:                i += LINE(vcline);
        !          1268:                stcol %= WCOLS;
        !          1269:                endcol %= WCOLS;
        !          1270:                up = vtube[i]; tp = up + endcol; tpe = up + WCOLS;
        !          1271:                while (tp < tpe && *tp)
        !          1272:                        tp++;
        !          1273:                if (tp - (up + stcol) < 2 * nc)
        !          1274:                        return;
        !          1275:                vgoto(i, stcol);
        !          1276:        }
        !          1277: 
        !          1278:        /*
        !          1279:         * Go into delete mode and do the actual delete.
        !          1280:         * Padding is on DC itself.
        !          1281:         */
        !          1282:        godm();
        !          1283:        for (i = nc; i > 0; i--)
        !          1284:                vputp(DC, DEPTH(vcline));
        !          1285:        vputp(ED, 0);
        !          1286: 
        !          1287:        /*
        !          1288:         * Straighten up.
        !          1289:         * With CONCEPT like terminals, characters are pulled left
        !          1290:         * from first following null.  HP like terminals shift rest of
        !          1291:         * this (single physical) line rigidly.
        !          1292:         */
        !          1293:        if (IN) {
        !          1294:                up = vtube0 + stcol;
        !          1295:                tp = vtube0 + endcol;
        !          1296:                while (i = *tp++) {
        !          1297:                        if ((i & (QUOTE|TRIM)) == QUOTE)
        !          1298:                                break;
        !          1299:                        *up++ = i;
        !          1300:                }
        !          1301:                do
        !          1302:                        *up++ = i;
        !          1303:                while (--nc);
        !          1304:        } else {
        !          1305:                copy(up + stcol, up + endcol, WCOLS - endcol);
        !          1306:                vclrbyte(tpe - nc, nc);
        !          1307:        }
        !          1308: }
        !          1309: 
        !          1310: #ifdef TRACE
        !          1311: tfixnl()
        !          1312: {
        !          1313: 
        !          1314:        if (trubble || techoin)
        !          1315:                fprintf(trace, "\n");
        !          1316:        trubble = 0, techoin = 0;
        !          1317: }
        !          1318: 
        !          1319: tvliny()
        !          1320: {
        !          1321:        register int i;
        !          1322: 
        !          1323:        if (!trace)
        !          1324:                return;
        !          1325:        tfixnl();
        !          1326:        fprintf(trace, "vcnt = %d, vcline = %d, vliny = ", vcnt, vcline);
        !          1327:        for (i = 0; i <= vcnt; i++) {
        !          1328:                fprintf(trace, "%d", LINE(i));
        !          1329:                if (FLAGS(i) & VDIRT)
        !          1330:                        fprintf(trace, "*");
        !          1331:                if (DEPTH(i) != 1)
        !          1332:                        fprintf(trace, "<%d>", DEPTH(i));
        !          1333:                if (i < vcnt)
        !          1334:                        fprintf(trace, " ");
        !          1335:        }
        !          1336:        fprintf(trace, "\n");
        !          1337: }
        !          1338: 
        !          1339: tracec(c)
        !          1340:        int c;          /* mjm: char --> int */
        !          1341: {
        !          1342: 
        !          1343:        if (!techoin)
        !          1344:                trubble = 1;
        !          1345:        if (c == ESCAPE)
        !          1346:                fprintf(trace, "$");
        !          1347:        else if (c & QUOTE)     /* mjm: for 3B (no sign extension) */
        !          1348:                fprintf(trace, "~%c", ctlof(c&TRIM));
        !          1349:        else if (c < ' ' || c == DELETE)
        !          1350:                fprintf(trace, "^%c", ctlof(c));
        !          1351:        else
        !          1352:                fprintf(trace, "%c", c);
        !          1353: }
        !          1354: #endif
        !          1355: 
        !          1356: /*
        !          1357:  * Put a character with possible tracing.
        !          1358:  */
        !          1359: vputch(c)
        !          1360:        int c;
        !          1361: {
        !          1362: 
        !          1363: #ifdef TRACE
        !          1364:        if (trace)
        !          1365:                tracec(c);
        !          1366: #endif
        !          1367:        vputc(c);
        !          1368: }

unix.superglobalmegacorp.com

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