Annotation of 43BSD/ucb/ex/ex_put.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_put.c    7.9 (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:  * Terminal driving and line formatting routines.
                     17:  * Basic motion optimizations are done here as well
                     18:  * as formatting of lines (printing of control characters,
                     19:  * line numbering and the like).
                     20:  */
                     21: 
                     22: /*
                     23:  * The routines outchar, putchar and pline are actually
                     24:  * variables, and these variables point at the current definitions
                     25:  * of the routines.  See the routine setflav.
                     26:  * We sometimes make outchar be routines which catch the characters
                     27:  * to be printed, e.g. if we want to see how long a line is.
                     28:  * During open/visual, outchar and putchar will be set to
                     29:  * routines in the file ex_vput.c (vputchar, vinschar, etc.).
                     30:  */
                     31: int    (*Outchar)() = termchar;
                     32: int    (*Putchar)() = normchar;
                     33: int    (*Pline)() = normline;
                     34: 
                     35: int (*
                     36: setlist(t))()
                     37:        bool t;
                     38: {
                     39:        register int (*P)();
                     40: 
                     41:        listf = t;
                     42:        P = Putchar;
                     43:        Putchar = t ? listchar : normchar;
                     44:        return (P);
                     45: }
                     46: 
                     47: int (*
                     48: setnumb(t))()
                     49:        bool t;
                     50: {
                     51:        register int (*P)();
                     52: 
                     53:        numberf = t;
                     54:        P = Pline;
                     55:        Pline = t ? numbline : normline;
                     56:        return (P);
                     57: }
                     58: 
                     59: /*
                     60:  * Format c for list mode; leave things in common
                     61:  * with normal print mode to be done by normchar.
                     62:  */
                     63: listchar(c)
                     64:        register short c;
                     65: {
                     66: 
                     67:        c &= (TRIM|QUOTE);
                     68:        switch (c) {
                     69: 
                     70:        case '\t':
                     71:        case '\b':
                     72:                outchar('^');
                     73:                c = ctlof(c);
                     74:                break;
                     75: 
                     76:        case '\n':
                     77:                break;
                     78: 
                     79:        case '\n' | QUOTE:
                     80:                outchar('$');
                     81:                break;
                     82: 
                     83:        default:
                     84:                if (c & QUOTE)
                     85:                        break;
                     86:                if (c < ' ' && c != '\n' || c == DELETE)
                     87:                        outchar('^'), c = ctlof(c);
                     88:                break;
                     89:        }
                     90:        normchar(c);
                     91: }
                     92: 
                     93: /*
                     94:  * Format c for printing.  Handle funnies of upper case terminals
                     95:  * and crocky hazeltines which don't have ~.
                     96:  */
                     97: normchar(c)
                     98:        register short c;
                     99: {
                    100:        register char *colp;
                    101: 
                    102:        c &= (TRIM|QUOTE);
                    103:        if (c == '~' && HZ) {
                    104:                normchar('\\');
                    105:                c = '^';
                    106:        }
                    107:        if (c & QUOTE)
                    108:                switch (c) {
                    109: 
                    110:                case ' ' | QUOTE:
                    111:                case '\b' | QUOTE:
                    112:                        break;
                    113: 
                    114:                case QUOTE:
                    115:                        return;
                    116: 
                    117:                default:
                    118:                        c &= TRIM;
                    119:                }
                    120:        else if (c < ' ' && (c != '\b' || !OS) && c != '\n' && c != '\t' || c == DELETE)
                    121:                putchar('^'), c = ctlof(c);
                    122:        else if (UPPERCASE)
                    123:                if (isupper(c)) {
                    124:                        outchar('\\');
                    125:                        c = tolower(c);
                    126:                } else {
                    127:                        colp = "({)}!|^~'`";
                    128:                        while (*colp++)
                    129:                                if (c == *colp++) {
                    130:                                        outchar('\\');
                    131:                                        c = colp[-2];
                    132:                                        break;
                    133:                                }
                    134:                }
                    135:        outchar(c);
                    136: }
                    137: 
                    138: /*
                    139:  * Print a line with a number.
                    140:  */
                    141: numbline(i)
                    142:        int i;
                    143: {
                    144: 
                    145:        if (shudclob)
                    146:                slobber(' ');
                    147:        printf("%6d  ", i);
                    148:        normline();
                    149: }
                    150: 
                    151: /*
                    152:  * Normal line output, no numbering.
                    153:  */
                    154: normline()
                    155: {
                    156:        register char *cp;
                    157: 
                    158:        if (shudclob)
                    159:                slobber(linebuf[0]);
                    160:        /* pdp-11 doprnt is not reentrant so can't use "printf" here
                    161:           in case we are tracing */
                    162:        for (cp = linebuf; *cp;)
                    163:                putchar(*cp++);
                    164:        if (!inopen)
                    165:                putchar('\n' | QUOTE);
                    166: }
                    167: 
                    168: /*
                    169:  * Given c at the beginning of a line, determine whether
                    170:  * the printing of the line will erase or otherwise obliterate
                    171:  * the prompt which was printed before.  If it won't, do it now.
                    172:  */
                    173: slobber(c)
                    174:        int c;
                    175: {
                    176: 
                    177:        shudclob = 0;
                    178:        switch (c) {
                    179: 
                    180:        case '\t':
                    181:                if (Putchar == listchar)
                    182:                        return;
                    183:                break;
                    184: 
                    185:        default:
                    186:                return;
                    187: 
                    188:        case ' ':
                    189:        case 0:
                    190:                break;
                    191:        }
                    192:        if (OS)
                    193:                return;
                    194:        flush();
                    195:        putch(' ');
                    196:        if (BC)
                    197:                tputs(BC, 0, putch);
                    198:        else
                    199:                putch('\b');
                    200: }
                    201: 
                    202: /*
                    203:  * The output buffer is initialized with a useful error
                    204:  * message so we don't have to keep it in data space.
                    205:  */
                    206: static char linb[66];
                    207: char *linp = linb;
                    208: 
                    209: /*
                    210:  * Phadnl records when we have already had a complete line ending with \n.
                    211:  * If another line starts without a flush, and the terminal suggests it,
                    212:  * we switch into -nl mode so that we can send lineffeeds to avoid
                    213:  * a lot of spacing.
                    214:  */
                    215: static bool phadnl;
                    216: 
                    217: /*
                    218:  * Indirect to current definition of putchar.
                    219:  */
                    220: putchar(c)
                    221:        int c;
                    222: {
                    223: 
                    224:        (*Putchar)(c);
                    225: }
                    226: 
                    227: /*
                    228:  * Termchar routine for command mode.
                    229:  * Watch for possible switching to -nl mode.
                    230:  * Otherwise flush into next level of buffering when
                    231:  * small buffer fills or at a newline.
                    232:  */
                    233: termchar(c)
                    234:        int c;
                    235: {
                    236: 
                    237:        if (pfast == 0 && phadnl)
                    238:                pstart();
                    239:        if (c == '\n')
                    240:                phadnl = 1;
                    241:        else if (linp >= &linb[63])
                    242:                flush1();
                    243:        *linp++ = c;
                    244:        if (linp >= &linb[63]) {
                    245:                fgoto();
                    246:                flush1();
                    247:        }
                    248: }
                    249: 
                    250: flush()
                    251: {
                    252: 
                    253:        flush1();
                    254:        flush2();
                    255: }
                    256: 
                    257: /*
                    258:  * Flush from small line buffer into output buffer.
                    259:  * Work here is destroying motion into positions, and then
                    260:  * letting fgoto do the optimized motion.
                    261:  */
                    262: flush1()
                    263: {
                    264:        register char *lp;
                    265:        register short c;
                    266: 
                    267:        *linp = 0;
                    268:        lp = linb;
                    269:        while (*lp)
                    270:                switch (c = *lp++) {
                    271: 
                    272:                case '\r':
                    273:                        destline += destcol / COLUMNS;
                    274:                        destcol = 0;
                    275:                        continue;
                    276: 
                    277:                case '\b':
                    278:                        if (destcol)
                    279:                                destcol--;
                    280:                        continue;
                    281: 
                    282:                case ' ':
                    283:                        destcol++;
                    284:                        continue;
                    285: 
                    286:                case '\t':
                    287:                        destcol += value(TABSTOP) - destcol % value(TABSTOP);
                    288:                        continue;
                    289: 
                    290:                case '\n':
                    291:                        destline += destcol / COLUMNS + 1;
                    292:                        if (destcol != 0 && destcol % COLUMNS == 0)
                    293:                                destline--;
                    294:                        destcol = 0;
                    295:                        continue;
                    296: 
                    297:                default:
                    298:                        fgoto();
                    299:                        for (;;) {
                    300:                                if (AM == 0 && outcol == COLUMNS)
                    301:                                        fgoto();
                    302:                                c &= TRIM;
                    303:                                putch(c);
                    304:                                if (c == '\b') {
                    305:                                        outcol--;
                    306:                                        destcol--;
                    307:                                } else if (c >= ' ' && c != DELETE) {
                    308:                                        outcol++;
                    309:                                        destcol++;
                    310:                                        if (XN && outcol % COLUMNS == 0)
                    311:                                                putch('\r'), putch('\n');
                    312:                                }
                    313:                                c = *lp++;
                    314:                                if (c <= ' ')
                    315:                                        break;
                    316:                        }
                    317:                        --lp;
                    318:                        continue;
                    319:                }
                    320:        linp = linb;
                    321: }
                    322: 
                    323: flush2()
                    324: {
                    325: 
                    326:        fgoto();
                    327:        flusho();
                    328:        pstop();
                    329: }
                    330: 
                    331: /*
                    332:  * Sync the position of the output cursor.
                    333:  * Most work here is rounding for terminal boundaries getting the
                    334:  * column position implied by wraparound or the lack thereof and
                    335:  * rolling up the screen to get destline on the screen.
                    336:  */
                    337: fgoto()
                    338: {
                    339:        register int l, c;
                    340: 
                    341:        if (destcol > COLUMNS - 1) {
                    342:                destline += destcol / COLUMNS;
                    343:                destcol %= COLUMNS;
                    344:        }
                    345:        if (outcol > COLUMNS - 1) {
                    346:                l = (outcol + 1) / COLUMNS;
                    347:                outline += l;
                    348:                outcol %= COLUMNS;
                    349:                if (AM == 0) {
                    350:                        while (l > 0) {
                    351:                                if (pfast)
                    352:                                        if (xCR)
                    353:                                                tputs(xCR, 0, putch);
                    354:                                        else
                    355:                                                putch('\r');
                    356:                                if (xNL)
                    357:                                        tputs(xNL, 0, putch);
                    358:                                else
                    359:                                        putch('\n');
                    360:                                l--;
                    361:                        }
                    362:                        outcol = 0;
                    363:                }
                    364:                if (outline > LINES - 1) {
                    365:                        destline -= outline - (LINES - 1);
                    366:                        outline = LINES - 1;
                    367:                }
                    368:        }
                    369:        if (destline > LINES - 1) {
                    370:                l = destline;
                    371:                destline = LINES - 1;
                    372:                if (outline < LINES - 1) {
                    373:                        c = destcol;
                    374:                        if (pfast == 0 && (!CA || holdcm))
                    375:                                destcol = 0;
                    376:                        fgoto();
                    377:                        destcol = c;
                    378:                }
                    379:                while (l > LINES - 1) {
                    380:                        /*
                    381:                         * The following linefeed (or simulation thereof)
                    382:                         * is supposed to scroll up the screen, since we
                    383:                         * are on the bottom line.  We make the assumption
                    384:                         * that linefeed will scroll.  If ns is in the
                    385:                         * capability list this won't work.  We should
                    386:                         * probably have an sc capability but sf will
                    387:                         * generally take the place if it works.
                    388:                         *
                    389:                         * Superbee glitch:  in the middle of the screen we
                    390:                         * have to use esc B (down) because linefeed screws up
                    391:                         * in "Efficient Paging" (what a joke) mode (which is
                    392:                         * essential in some SB's because CRLF mode puts garbage
                    393:                         * in at end of memory), but you must use linefeed to
                    394:                         * scroll since down arrow won't go past memory end.
                    395:                         * I turned this off after recieving Paul Eggert's
                    396:                         * Superbee description which wins better.
                    397:                         */
                    398:                        if (xNL /* && !XB */ && pfast)
                    399:                                tputs(xNL, 0, putch);
                    400:                        else
                    401:                                putch('\n');
                    402:                        l--;
                    403:                        if (pfast == 0)
                    404:                                outcol = 0;
                    405:                }
                    406:        }
                    407:        if (destline < outline && !(CA && !holdcm || UP != NOSTR))
                    408:                destline = outline;
                    409:        if (CA && !holdcm)
                    410:                if (plod(costCM) > 0)
                    411:                        plod(0);
                    412:                else
                    413:                        tputs(tgoto(CM, destcol, destline), 0, putch);
                    414:        else
                    415:                plod(0);
                    416:        outline = destline;
                    417:        outcol = destcol;
                    418: }
                    419: 
                    420: /*
                    421:  * Tab to column col by flushing and then setting destcol.
                    422:  * Used by "set all".
                    423:  */
                    424: tab(col)
                    425:        int col;
                    426: {
                    427: 
                    428:        flush1();
                    429:        destcol = col;
                    430: }
                    431: 
                    432: /*
                    433:  * Move (slowly) to destination.
                    434:  * Hard thing here is using home cursor on really deficient terminals.
                    435:  * Otherwise just use cursor motions, hacking use of tabs and overtabbing
                    436:  * and backspace.
                    437:  */
                    438: 
                    439: static int plodcnt, plodflg;
                    440: 
                    441: plodput(c)
                    442: {
                    443: 
                    444:        if (plodflg)
                    445:                plodcnt--;
                    446:        else
                    447:                putch(c);
                    448: }
                    449: 
                    450: plod(cnt)
                    451: {
                    452:        register int i, j, k;
                    453:        register int soutcol, soutline;
                    454: 
                    455:        plodcnt = plodflg = cnt;
                    456:        soutcol = outcol;
                    457:        soutline = outline;
                    458:        /*
                    459:         * Consider homing and moving down/right from there, vs moving
                    460:         * directly with local motions to the right spot.
                    461:         */
                    462:        if (HO) {
                    463:                /*
                    464:                 * i is the cost to home and tab/space to the right to
                    465:                 * get to the proper column.  This assumes ND space costs
                    466:                 * 1 char.  So i+destcol is cost of motion with home.
                    467:                 */
                    468:                if (GT)
                    469:                        i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS));
                    470:                else
                    471:                        i = destcol;
                    472:                /*
                    473:                 * j is cost to move locally without homing
                    474:                 */
                    475:                if (destcol >= outcol) {        /* if motion is to the right */
                    476:                        j = destcol / value(HARDTABS) - outcol / value(HARDTABS);
                    477:                        if (GT && j)
                    478:                                j += destcol % value(HARDTABS);
                    479:                        else
                    480:                                j = destcol - outcol;
                    481:                } else
                    482:                        /* leftward motion only works if we can backspace. */
                    483:                        if (outcol - destcol <= i && (BS || BC))
                    484:                                i = j = outcol - destcol; /* cheaper to backspace */
                    485:                        else
                    486:                                j = i + 1; /* impossibly expensive */
                    487: 
                    488:                /* k is the absolute value of vertical distance */
                    489:                k = outline - destline;
                    490:                if (k < 0)
                    491:                        k = -k;
                    492:                j += k;
                    493: 
                    494:                /*
                    495:                 * Decision.  We may not have a choice if no UP.
                    496:                 */
                    497:                if (i + destline < j || (!UP && destline < outline)) {
                    498:                        /*
                    499:                         * Cheaper to home.  Do it now and pretend it's a
                    500:                         * regular local motion.
                    501:                         */
                    502:                        tputs(HO, 0, plodput);
                    503:                        outcol = outline = 0;
                    504:                } else if (LL) {
                    505:                        /*
                    506:                         * Quickly consider homing down and moving from there.
                    507:                         * Assume cost of LL is 2.
                    508:                         */
                    509:                        k = (LINES - 1) - destline;
                    510:                        if (i + k + 2 < j && (k<=0 || UP)) {
                    511:                                tputs(LL, 0, plodput);
                    512:                                outcol = 0;
                    513:                                outline = LINES - 1;
                    514:                        }
                    515:                }
                    516:        } else
                    517:        /*
                    518:         * No home and no up means it's impossible, so we return an
                    519:         * incredibly big number to make cursor motion win out.
                    520:         */
                    521:                if (!UP && destline < outline)
                    522:                        return (500);
                    523:        if (GT)
                    524:                i = destcol % value(HARDTABS)
                    525:                    + destcol / value(HARDTABS);
                    526:        else
                    527:                i = destcol;
                    528: /*
                    529:        if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
                    530:                j *= (k = strlen(BT));
                    531:                if ((k += (destcol&7)) > 4)
                    532:                        j += 8 - (destcol&7);
                    533:                else
                    534:                        j += k;
                    535:        } else
                    536: */
                    537:                j = outcol - destcol;
                    538:        /*
                    539:         * If we will later need a \n which will turn into a \r\n by
                    540:         * the system or the terminal, then don't bother to try to \r.
                    541:         */
                    542:        if ((NONL || !pfast) && outline < destline)
                    543:                goto dontcr;
                    544:        /*
                    545:         * If the terminal will do a \r\n and there isn't room for it,
                    546:         * then we can't afford a \r.
                    547:         */
                    548:        if (NC && outline >= destline)
                    549:                goto dontcr;
                    550:        /*
                    551:         * If it will be cheaper, or if we can't back up, then send
                    552:         * a return preliminarily.
                    553:         */
                    554:        if (j > i + 1 || outcol > destcol && !BS && !BC) {
                    555:                /*
                    556:                 * BUG: this doesn't take the (possibly long) length
                    557:                 * of xCR into account.
                    558:                 */
                    559:                if (xCR)
                    560:                        tputs(xCR, 0, plodput);
                    561:                else
                    562:                        plodput('\r');
                    563:                if (NC) {
                    564:                        if (xNL)
                    565:                                tputs(xNL, 0, plodput);
                    566:                        else
                    567:                                plodput('\n');
                    568:                        outline++;
                    569:                }
                    570:                outcol = 0;
                    571:        }
                    572: dontcr:
                    573:        /* Move down, if necessary, until we are at the desired line */
                    574:        while (outline < destline) {
                    575:                j = destline - outline;
                    576:                if (j > costDP && DOWN_PARM) {
                    577:                        /* Win big on Tek 4025 */
                    578:                        tputs(tgoto(DOWN_PARM, 0, j), j, plodput);
                    579:                        outline += j;
                    580:                }
                    581:                else {
                    582:                        outline++;
                    583:                        if (xNL && pfast)
                    584:                                tputs(xNL, 0, plodput);
                    585:                        else
                    586:                                plodput('\n');
                    587:                }
                    588:                if (plodcnt < 0)
                    589:                        goto out;
                    590:                if (NONL || pfast == 0)
                    591:                        outcol = 0;
                    592:        }
                    593:        if (BT)
                    594:                k = strlen(BT); /* should probably be cost(BT) and moved out */
                    595:        /* Move left, if necessary, to desired column */
                    596:        while (outcol > destcol) {
                    597:                if (plodcnt < 0)
                    598:                        goto out;
                    599:                if (BT && !insmode && outcol - destcol > 4+k) {
                    600:                        tputs(BT, 0, plodput);
                    601:                        outcol--;
                    602:                        outcol -= outcol % value(HARDTABS); /* outcol &= ~7; */
                    603:                        continue;
                    604:                }
                    605:                j = outcol - destcol;
                    606:                if (j > costLP && LEFT_PARM) {
                    607:                        tputs(tgoto(LEFT_PARM, 0, j), j, plodput);
                    608:                        outcol -= j;
                    609:                }
                    610:                else {
                    611:                        outcol--;
                    612:                        if (BC)
                    613:                                tputs(BC, 0, plodput);
                    614:                        else
                    615:                                plodput('\b');
                    616:                }
                    617:        }
                    618:        /* Move up, if necessary, to desired row */
                    619:        while (outline > destline) {
                    620:                j = outline - destline;
                    621:                if (UP_PARM && j > 1) {
                    622:                        /* Win big on Tek 4025 */
                    623:                        tputs(tgoto(UP_PARM, 0, j), j, plodput);
                    624:                        outline -= j;
                    625:                }
                    626:                else {
                    627:                        outline--;
                    628:                        tputs(UP, 0, plodput);
                    629:                }
                    630:                if (plodcnt < 0)
                    631:                        goto out;
                    632:        }
                    633:        /*
                    634:         * Now move to the right, if necessary.  We first tab to
                    635:         * as close as we can get.
                    636:         */
                    637:        if (GT && !insmode && destcol - outcol > 1) {
                    638:                /* tab to right as far as possible without passing col */
                    639:                for (;;) {
                    640:                        i = tabcol(outcol, value(HARDTABS));
                    641:                        if (i > destcol)
                    642:                                break;
                    643:                        if (TA)
                    644:                                tputs(TA, 0, plodput);
                    645:                        else
                    646:                                plodput('\t');
                    647:                        outcol = i;
                    648:                }
                    649:                /* consider another tab and then some backspaces */
                    650:                if (destcol - outcol > 4 && i < COLUMNS && (BC || BS)) {
                    651:                        if (TA)
                    652:                                tputs(TA, 0, plodput);
                    653:                        else
                    654:                                plodput('\t');
                    655:                        outcol = i;
                    656:                        /*
                    657:                         * Back up.  Don't worry about LEFT_PARM because
                    658:                         * it's never more than 4 spaces anyway.
                    659:                         */
                    660:                        while (outcol > destcol) {
                    661:                                outcol--;
                    662:                                if (BC)
                    663:                                        tputs(BC, 0, plodput);
                    664:                                else
                    665:                                        plodput('\b');
                    666:                        }
                    667:                }
                    668:        }
                    669:        /*
                    670:         * We've tabbed as much as possible.  If we still need to go
                    671:         * further (not exact or can't tab) space over.  This is a
                    672:         * very common case when moving to the right with space.
                    673:         */
                    674:        while (outcol < destcol) {
                    675:                j = destcol - outcol;
                    676:                if (j > costRP && RIGHT_PARM) {
                    677:                        /*
                    678:                         * This probably happens rarely, if at all.
                    679:                         * It seems mainly useful for ANSI terminals
                    680:                         * with no hardware tabs, and I don't know
                    681:                         * of any such terminal at the moment.
                    682:                         */
                    683:                        tputs(tgoto(RIGHT_PARM, 0, j), j, plodput);
                    684:                        outcol += j;
                    685:                }
                    686:                else {
                    687:                        /*
                    688:                         * move one char to the right.  We don't use ND space
                    689:                         * because it's better to just print the char we are
                    690:                         * moving over.  There are various exceptions, however.
                    691:                         * If !inopen, vtube contains garbage.  If the char is
                    692:                         * a null or a tab we want to print a space.  Other
                    693:                         * random chars we use space for instead, too.
                    694:                         */
                    695:                        if (!inopen || vtube[outline]==NULL ||
                    696:                                (i=vtube[outline][outcol]) < ' ')
                    697:                                i = ' ';
                    698:                        if(i & QUOTE)   /* mjm: no sign extension on 3B */
                    699:                                i = ' ';
                    700:                        if (insmode && ND)
                    701:                                tputs(ND, 0, plodput);
                    702:                        else
                    703:                                plodput(i);
                    704:                        outcol++;
                    705:                }
                    706:                if (plodcnt < 0)
                    707:                        goto out;
                    708:        }
                    709: out:
                    710:        if (plodflg) {
                    711:                outcol = soutcol;
                    712:                outline = soutline;
                    713:        }
                    714:        return(plodcnt);
                    715: }
                    716: 
                    717: /*
                    718:  * An input line arrived.
                    719:  * Calculate new (approximate) screen line position.
                    720:  * Approximate because kill character echoes newline with
                    721:  * no feedback and also because of long input lines.
                    722:  */
                    723: noteinp()
                    724: {
                    725: 
                    726:        outline++;
                    727:        if (outline > LINES - 1)
                    728:                outline = LINES - 1;
                    729:        destline = outline;
                    730:        destcol = outcol = 0;
                    731: }
                    732: 
                    733: /*
                    734:  * Something weird just happened and we
                    735:  * lost track of whats happening out there.
                    736:  * Since we cant, in general, read where we are
                    737:  * we just reset to some known state.
                    738:  * On cursor addressible terminals setting to unknown
                    739:  * will force a cursor address soon.
                    740:  */
                    741: termreset()
                    742: {
                    743: 
                    744:        endim();
                    745:        if (TI) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */
                    746:                putpad(TI);      /*adb change -- emit terminal initial sequence */
                    747:        destcol = 0;
                    748:        destline = LINES - 1;
                    749:        if (CA) {
                    750:                outcol = UKCOL;
                    751:                outline = UKCOL;
                    752:        } else {
                    753:                outcol = destcol;
                    754:                outline = destline;
                    755:        }
                    756: }
                    757: 
                    758: /*
                    759:  * Low level buffering, with the ability to drain
                    760:  * buffered output without printing it.
                    761:  */
                    762: char   *obp = obuf;
                    763: 
                    764: draino()
                    765: {
                    766: 
                    767:        obp = obuf;
                    768: }
                    769: 
                    770: flusho()
                    771: {
                    772: 
                    773:        if (obp != obuf) {
                    774:                write(1, obuf, obp - obuf);
                    775:                obp = obuf;
                    776:        }
                    777: }
                    778: 
                    779: putnl()
                    780: {
                    781: 
                    782:        putchar('\n');
                    783: }
                    784: 
                    785: putS(cp)
                    786:        char *cp;
                    787: {
                    788: 
                    789:        if (cp == NULL)
                    790:                return;
                    791:        while (*cp)
                    792:                putch(*cp++);
                    793: }
                    794: 
                    795: 
                    796: putch(c)
                    797:        int c;
                    798: {
                    799: 
                    800: #ifdef OLD3BTTY                /* mjm */
                    801:        if(c == '\n')   /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */
                    802:                putch('\r');    /* mjm: vi does "stty -icanon" => -onlcr !! */
                    803: #endif
                    804:        *obp++ = c & 0177;
                    805:        if (obp >= &obuf[sizeof obuf])
                    806:                flusho();
                    807: }
                    808: 
                    809: /*
                    810:  * Miscellaneous routines related to output.
                    811:  */
                    812: 
                    813: /*
                    814:  * Put with padding
                    815:  */
                    816: putpad(cp)
                    817:        char *cp;
                    818: {
                    819: 
                    820:        flush();
                    821:        tputs(cp, 0, putch);
                    822: }
                    823: 
                    824: /*
                    825:  * Set output through normal command mode routine.
                    826:  */
                    827: setoutt()
                    828: {
                    829: 
                    830:        Outchar = termchar;
                    831: }
                    832: 
                    833: /*
                    834:  * Printf (temporarily) in list mode.
                    835:  */
                    836: /*VARARGS2*/
                    837: lprintf(cp, dp)
                    838:        char *cp, *dp;
                    839: {
                    840:        register int (*P)();
                    841: 
                    842:        P = setlist(1);
                    843:        printf(cp, dp);
                    844:        Putchar = P;
                    845: }
                    846: 
                    847: /*
                    848:  * Newline + flush.
                    849:  */
                    850: putNFL()
                    851: {
                    852: 
                    853:        putnl();
                    854:        flush();
                    855: }
                    856: 
                    857: /*
                    858:  * Try to start -nl mode.
                    859:  */
                    860: pstart()
                    861: {
                    862: 
                    863:        if (NONL)
                    864:                return;
                    865:        if (!value(OPTIMIZE))
                    866:                return;
                    867:        if (ruptible == 0 || pfast)
                    868:                return;
                    869:        fgoto();
                    870:        flusho();
                    871:        pfast = 1;
                    872:        normtty++;
                    873: #ifndef USG3TTY
                    874:        tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
                    875: #else
                    876:        tty = normf;
                    877:        tty.c_oflag &= ~(ONLCR|TAB3);
                    878:        tty.c_lflag &= ~ECHO;
                    879: #endif
                    880:        sTTY(1);
                    881: }
                    882: 
                    883: /*
                    884:  * Stop -nl mode.
                    885:  */
                    886: pstop()
                    887: {
                    888: 
                    889:        if (inopen)
                    890:                return;
                    891:        phadnl = 0;
                    892:        linp = linb;
                    893:        draino();
                    894:        normal(normf);
                    895:        pfast &= ~1;
                    896: }
                    897: 
                    898: /*
                    899:  * Prep tty for open mode.
                    900:  */
                    901: ttymode
                    902: ostart()
                    903: {
                    904:        ttymode f;
                    905: 
                    906:        if (!intty)
                    907:                error("Open and visual must be used interactively");
                    908:        gTTY(1);
                    909:        normtty++;
                    910: #ifndef USG3TTY
                    911:        f = tty.sg_flags;
                    912:        tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
                    913: # ifdef CBREAK
                    914:                                                        CBREAK;
                    915: # else
                    916:                                                        RAW;
                    917: # endif
                    918: # ifdef TIOCGETC
                    919:        ttcharoff();
                    920: # endif
                    921: #else
                    922:        f = tty;
                    923:        tty = normf;
                    924:        tty.c_iflag &= ~ICRNL;
                    925:        tty.c_lflag &= ~(ECHO|ICANON);
                    926:        tty.c_oflag &= ~(TAB3|ONLCR);
                    927:        tty.c_cc[VMIN] = 1;
                    928:        tty.c_cc[VTIME] = 1;
                    929:        ttcharoff();
                    930: #endif
                    931:        sTTY(1);
                    932:        tostart();
                    933:        pfast |= 2;
                    934:        return (f);
                    935: }
                    936: 
                    937: /* actions associated with putting the terminal in open mode */
                    938: tostart()
                    939: {
                    940:        putpad(VS);
                    941:        putpad(KS);
                    942:        if (!value(MESG)) {
                    943:                if (ttynbuf[0] == 0) {
                    944:                        register char *tn;
                    945:                        if ((tn=ttyname(2)) == NULL &&
                    946:                            (tn=ttyname(1)) == NULL &&
                    947:                            (tn=ttyname(0)) == NULL)
                    948:                                ttynbuf[0] = 1;
                    949:                        else
                    950:                                strcpy(ttynbuf, tn);
                    951:                }
                    952:                if (ttynbuf[0] != 1) {
                    953:                        struct stat sbuf;
                    954:                        stat(ttynbuf, &sbuf);
                    955:                        ttymesg = sbuf.st_mode & 0777;
                    956:                        chmod(ttynbuf,
                    957: #ifdef UCBV7
                    958:        /*
                    959:         * This applies to the UCB V7 Pdp-11 system with the
                    960:         * -u write option only.
                    961:         */
                    962:                                        0611    /* 11 = urgent only allowed */
                    963: #else
                    964:                                        0600
                    965: #endif
                    966:                                                );
                    967:                }
                    968:        }
                    969: }
                    970: 
                    971: /*
                    972:  * Turn off start/stop chars if they aren't the default ^S/^Q.
                    973:  * This is so idiots who make esc their start/stop don't lose.
                    974:  * We always turn off quit since datamedias send ^\ for their
                    975:  * right arrow key.
                    976:  */
                    977: #ifdef TIOCGETC
                    978: ttcharoff()
                    979: {
                    980:        nttyc.t_quitc = '\377';
                    981:        if (nttyc.t_startc != CTRL(q))
                    982:                nttyc.t_startc = '\377';
                    983:        if (nttyc.t_stopc != CTRL(s))
                    984:                nttyc.t_stopc = '\377';
                    985: # ifdef TIOCLGET
                    986:        nlttyc.t_suspc = '\377';        /* ^Z */
                    987:        nlttyc.t_dsuspc = '\377';       /* ^Y */
                    988:        nlttyc.t_flushc = '\377';       /* ^O */
                    989:        nlttyc.t_lnextc = '\377';       /* ^V */
                    990: # endif
                    991: }
                    992: #endif
                    993: 
                    994: #ifdef USG3TTY
                    995: ttcharoff()
                    996: {
                    997:        tty.c_cc[VQUIT] = '\377';
                    998: # ifdef VSTART
                    999:        /*
                   1000:         * The following is sample code if USG ever lets people change
                   1001:         * their start/stop chars.  As long as they can't we can't get
                   1002:         * into trouble so we just leave them alone.
                   1003:         */
                   1004:        if (tty.c_cc[VSTART] != CTRL(q))
                   1005:                tty.c_cc[VSTART] = '\377';
                   1006:        if (tty.c_cc[VSTOP] != CTRL(s))
                   1007:                tty.c_cc[VSTOP] = '\377';
                   1008: # endif
                   1009: }
                   1010: #endif
                   1011: 
                   1012: /*
                   1013:  * Stop open, restoring tty modes.
                   1014:  */
                   1015: ostop(f)
                   1016:        ttymode f;
                   1017: {
                   1018: 
                   1019: #ifndef USG3TTY
                   1020:        pfast = (f & CRMOD) == 0;
                   1021: #else
                   1022:        pfast = (f.c_oflag & ONLCR) == 0;
                   1023: #endif
                   1024:        termreset(), fgoto(), flusho();
                   1025:        normal(f);
                   1026:        tostop();
                   1027: }
                   1028: 
                   1029: /* Actions associated with putting the terminal in the right mode. */
                   1030: tostop()
                   1031: {
                   1032:        putpad(VE);
                   1033:        putpad(KE);
                   1034:        if (!value(MESG) && ttynbuf[0]>1)
                   1035:                chmod(ttynbuf, ttymesg);
                   1036: }
                   1037: 
                   1038: #ifndef CBREAK
                   1039: /*
                   1040:  * Into cooked mode for interruptibility.
                   1041:  */
                   1042: vcook()
                   1043: {
                   1044: 
                   1045:        tty.sg_flags &= ~RAW;
                   1046:        sTTY(1);
                   1047: }
                   1048: 
                   1049: /*
                   1050:  * Back into raw mode.
                   1051:  */
                   1052: vraw()
                   1053: {
                   1054: 
                   1055:        tty.sg_flags |= RAW;
                   1056:        sTTY(1);
                   1057: }
                   1058: #endif
                   1059: 
                   1060: /*
                   1061:  * Restore flags to normal state f.
                   1062:  */
                   1063: normal(f)
                   1064:        ttymode f;
                   1065: {
                   1066: 
                   1067:        if (normtty > 0) {
                   1068:                setty(f);
                   1069:                normtty--;
                   1070:        }
                   1071: }
                   1072: 
                   1073: /*
                   1074:  * Straight set of flags to state f.
                   1075:  */
                   1076: ttymode
                   1077: setty(f)
                   1078:        ttymode f;
                   1079: {
                   1080: #ifndef USG3TTY
                   1081:        register int ot = tty.sg_flags;
                   1082: #else
                   1083:        ttymode ot;
                   1084:        ot = tty;
                   1085: #endif
                   1086: 
                   1087: #ifndef USG3TTY
                   1088:        if (f == normf) {
                   1089:                nttyc = ottyc;
                   1090: # ifdef TIOCLGET
                   1091:                nlttyc = olttyc;
                   1092: # endif
                   1093:        } else
                   1094:                ttcharoff();
                   1095:        tty.sg_flags = f;
                   1096: #else
                   1097:        if (tty.c_lflag & ICANON)
                   1098:                ttcharoff();
                   1099:        tty = f;
                   1100: #endif
                   1101:        sTTY(1);
                   1102:        return (ot);
                   1103: }
                   1104: 
                   1105: gTTY(i)
                   1106:        int i;
                   1107: {
                   1108: 
                   1109: #ifndef USG3TTY
                   1110:        ignore(gtty(i, &tty));
                   1111: # ifdef TIOCGETC
                   1112:        ioctl(i, TIOCGETC, &ottyc);
                   1113:        nttyc = ottyc;
                   1114: # endif
                   1115: # ifdef TIOCGLTC
                   1116:        ioctl(i, TIOCGLTC, &olttyc);
                   1117:        nlttyc = olttyc;
                   1118: # endif
                   1119: #else
                   1120:        ioctl(i, TCGETA, &tty);
                   1121: #endif
                   1122: }
                   1123: 
                   1124: /*
                   1125:  * sTTY: set the tty modes on file descriptor i to be what's
                   1126:  * currently in global "tty".  (Also use nttyc if needed.)
                   1127:  */
                   1128: sTTY(i)
                   1129:        int i;
                   1130: {
                   1131: 
                   1132: #ifndef USG3TTY
                   1133: # ifdef USG
                   1134:        /* Bug in USG tty driver, put out a DEL as a patch. */
                   1135:        if (tty.sg_ospeed >= B1200)
                   1136:                write(1, "\377", 1);
                   1137: # endif
                   1138: 
                   1139: # ifdef TIOCSETN
                   1140:        /* Don't flush typeahead if we don't have to */
                   1141:        ioctl(i, TIOCSETN, &tty);
                   1142: # else
                   1143:        /* We have to.  Too bad. */
                   1144:        stty(i, &tty);
                   1145: # endif
                   1146: 
                   1147: # ifdef TIOCGETC
                   1148:        /* Update the other random chars while we're at it. */
                   1149:        ioctl(i, TIOCSETC, &nttyc);
                   1150: # endif
                   1151: # ifdef TIOCSLTC
                   1152:        ioctl(i, TIOCSLTC, &nlttyc);
                   1153: # endif
                   1154: 
                   1155: #else
                   1156:        /* USG 3 very simple: just set everything */
                   1157:        ioctl(i, TCSETAW, &tty);
                   1158: #endif
                   1159: }
                   1160: 
                   1161: /*
                   1162:  * Print newline, or blank if in open/visual
                   1163:  */
                   1164: noonl()
                   1165: {
                   1166: 
                   1167:        putchar(Outchar != termchar ? ' ' : '\n');
                   1168: }

unix.superglobalmegacorp.com

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