Annotation of 43BSD/ucb/ex/ex_vput.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_vput.c   7.4 (Berkeley) 6/7/85";
                      9: #endif not lint
                     10: 
                     11: #include "ex.h"
                     12: #include "ex_tty.h"
                     13: #include "ex_vis.h"
                     14: 
                     15: /*
                     16:  * 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 - 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:                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 (Peekkey == 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 = 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.