Annotation of 42BSD/ucb/ex/ex_put.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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