Annotation of 43BSDReno/usr.bin/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.12 (Berkeley) 5/19/89";
                      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    (*Put_char)() = 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 = Put_char;
                     43:        Put_char = 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:                ex_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:        ex_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:                ex_putchar(*cp++);
                    164:        if (!inopen)
                    165:                ex_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 (Put_char == 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: ex_putchar(c)
                    221:        int c;
                    222: {
                    223: 
                    224:        (*Put_char)(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: #ifndef vms
                    775:                write(1, obuf, obp - obuf);
                    776: #else
                    777:                vms_write(1, obuf, obp - obuf);
                    778: #endif
                    779:                obp = obuf;
                    780:        }
                    781: }
                    782: 
                    783: putnl()
                    784: {
                    785: 
                    786:        ex_putchar('\n');
                    787: }
                    788: 
                    789: ex_putS(cp)
                    790:        char *cp;
                    791: {
                    792: 
                    793:        if (cp == NULL)
                    794:                return;
                    795:        while (*cp)
                    796:                putch(*cp++);
                    797: }
                    798: 
                    799: 
                    800: putch(c)
                    801:        int c;
                    802: {
                    803: 
                    804: #ifdef OLD3BTTY                /* mjm */
                    805:        if(c == '\n')   /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */
                    806:                putch('\r');    /* mjm: vi does "stty -icanon" => -onlcr !! */
                    807: #endif
                    808:        *obp++ = c & 0177;
                    809:        if (obp >= &obuf[sizeof obuf])
                    810:                flusho();
                    811: }
                    812: 
                    813: /*
                    814:  * Miscellaneous routines related to output.
                    815:  */
                    816: 
                    817: /*
                    818:  * Put with padding
                    819:  */
                    820: putpad(cp)
                    821:        char *cp;
                    822: {
                    823: 
                    824:        flush();
                    825:        tputs(cp, 0, putch);
                    826: }
                    827: 
                    828: /*
                    829:  * Set output through normal command mode routine.
                    830:  */
                    831: setoutt()
                    832: {
                    833: 
                    834:        Outchar = termchar;
                    835: }
                    836: 
                    837: /*
                    838:  * Printf (temporarily) in list mode.
                    839:  */
                    840: /*VARARGS1*/
                    841: lprintf(cp, dp)
                    842:        char *cp, *dp;
                    843: {
                    844:        register int (*P)();
                    845: 
                    846:        P = setlist(1);
                    847:        ex_printf(cp, dp);
                    848:        Put_char = P;
                    849: }
                    850: 
                    851: /*
                    852:  * Newline + flush.
                    853:  */
                    854: putNFL()
                    855: {
                    856: 
                    857:        putnl();
                    858:        flush();
                    859: }
                    860: 
                    861: /*
                    862:  * Try to start -nl mode.
                    863:  */
                    864: pstart()
                    865: {
                    866: 
                    867:        if (NONL)
                    868:                return;
                    869:        if (!value(OPTIMIZE))
                    870:                return;
                    871:        if (ruptible == 0 || pfast)
                    872:                return;
                    873:        fgoto();
                    874:        flusho();
                    875:        pfast = 1;
                    876:        normtty++;
                    877: #ifndef USG3TTY
                    878:        tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
                    879: #else
                    880:        tty = normf;
                    881:        tty.c_oflag &= ~(ONLCR|TAB3);
                    882:        tty.c_lflag &= ~ECHO;
                    883: #endif
                    884:        ex_sTTY(1);
                    885: }
                    886: 
                    887: /*
                    888:  * Stop -nl mode.
                    889:  */
                    890: pstop()
                    891: {
                    892: 
                    893:        if (inopen)
                    894:                return;
                    895:        phadnl = 0;
                    896:        linp = linb;
                    897:        draino();
                    898:        normal(normf);
                    899:        pfast &= ~1;
                    900: }
                    901: 
                    902: /*
                    903:  * Prep tty for open mode.
                    904:  */
                    905: ttymode
                    906: ostart()
                    907: {
                    908:        ttymode f;
                    909: 
                    910:        if (!intty)
                    911:                error("Open and visual must be used interactively");
                    912:        ex_gTTY(1);
                    913:        normtty++;
                    914: #ifndef USG3TTY
                    915:        f = tty.sg_flags;
                    916:        tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
                    917: # ifdef CBREAK
                    918:                                                        CBREAK;
                    919: # else
                    920:                                                        RAW;
                    921: # endif
                    922: # ifdef TIOCGETC
                    923:        ttcharoff();
                    924: # endif
                    925: #else
                    926:        f = tty;
                    927:        tty = normf;
                    928:        tty.c_iflag &= ~ICRNL;
                    929:        tty.c_lflag &= ~(ECHO|ICANON);
                    930:        tty.c_oflag &= ~(TAB3|ONLCR);
                    931:        tty.c_cc[VMIN] = 1;
                    932:        tty.c_cc[VTIME] = 1;
                    933:        ttcharoff();
                    934: #endif
                    935:        ex_sTTY(1);
                    936:        tostart();
                    937:        pfast |= 2;
                    938:        return (f);
                    939: }
                    940: 
                    941: /* actions associated with putting the terminal in open mode */
                    942: tostart()
                    943: {
                    944:        putpad(VS);
                    945:        putpad(KS);
                    946:        if (!value(MESG)) {
                    947:                if (ttynbuf[0] == 0) {
                    948:                        register char *tn;
                    949:                        if ((tn=ttyname(2)) == NULL &&
                    950:                            (tn=ttyname(1)) == NULL &&
                    951:                            (tn=ttyname(0)) == NULL)
                    952:                                ttynbuf[0] = 1;
                    953:                        else
                    954:                                strcpy(ttynbuf, tn);
                    955:                }
                    956:                if (ttynbuf[0] != 1) {
                    957:                        struct stat sbuf;
                    958:                        stat(ttynbuf, &sbuf);
                    959:                        ttymesg = sbuf.st_mode & 0777;
                    960:                        chmod(ttynbuf,
                    961: #ifdef UCBV7
                    962:        /*
                    963:         * This applies to the UCB V7 Pdp-11 system with the
                    964:         * -u write option only.
                    965:         */
                    966:                                        0611    /* 11 = urgent only allowed */
                    967: #else
                    968:                                        0600
                    969: #endif
                    970:                                                );
                    971:                }
                    972:        }
                    973: }
                    974: 
                    975: /*
                    976:  * Turn off start/stop chars if they aren't the default ^S/^Q.
                    977:  * This is so idiots who make esc their start/stop don't lose.
                    978:  * We always turn off quit since datamedias send ^\ for their
                    979:  * right arrow key.
                    980:  */
                    981: #ifdef TIOCGETC
                    982: ttcharoff()
                    983: {
                    984:        nttyc.t_quitc = '\377';
                    985:        if (nttyc.t_startc != CTRL('q'))
                    986:                nttyc.t_startc = '\377';
                    987:        if (nttyc.t_stopc != CTRL('s'))
                    988:                nttyc.t_stopc = '\377';
                    989: # ifdef TIOCLGET
                    990:        nlttyc.t_suspc = '\377';        /* ^Z */
                    991:        nlttyc.t_dsuspc = '\377';       /* ^Y */
                    992:        nlttyc.t_flushc = '\377';       /* ^O */
                    993:        nlttyc.t_lnextc = '\377';       /* ^V */
                    994: # endif
                    995: }
                    996: #endif
                    997: 
                    998: #ifdef USG3TTY
                    999: ttcharoff()
                   1000: {
                   1001:        tty.c_cc[VQUIT] = '\377';
                   1002: # ifdef VSTART
                   1003:        /*
                   1004:         * The following is sample code if USG ever lets people change
                   1005:         * their start/stop chars.  As long as they can't we can't get
                   1006:         * into trouble so we just leave them alone.
                   1007:         */
                   1008:        if (tty.c_cc[VSTART] != CTRL('q'))
                   1009:                tty.c_cc[VSTART] = '\377';
                   1010:        if (tty.c_cc[VSTOP] != CTRL('s'))
                   1011:                tty.c_cc[VSTOP] = '\377';
                   1012: # endif
                   1013: }
                   1014: #endif
                   1015: 
                   1016: /*
                   1017:  * Stop open, restoring tty modes.
                   1018:  */
                   1019: ostop(f)
                   1020:        ttymode f;
                   1021: {
                   1022: 
                   1023: #ifndef USG3TTY
                   1024:        pfast = (f & CRMOD) == 0;
                   1025: #else
                   1026:        pfast = (f.c_oflag & ONLCR) == 0;
                   1027: #endif
                   1028:        termreset(), fgoto(), flusho();
                   1029:        normal(f);
                   1030:        tostop();
                   1031: }
                   1032: 
                   1033: /* Actions associated with putting the terminal in the right mode. */
                   1034: tostop()
                   1035: {
                   1036:        putpad(VE);
                   1037:        putpad(KE);
                   1038:        if (!value(MESG) && ttynbuf[0]>1)
                   1039:                chmod(ttynbuf, ttymesg);
                   1040: }
                   1041: 
                   1042: #ifndef CBREAK
                   1043: /*
                   1044:  * Into cooked mode for interruptibility.
                   1045:  */
                   1046: vcook()
                   1047: {
                   1048: 
                   1049:        tty.sg_flags &= ~RAW;
                   1050:        ex_sTTY(1);
                   1051: }
                   1052: 
                   1053: /*
                   1054:  * Back into raw mode.
                   1055:  */
                   1056: vraw()
                   1057: {
                   1058: 
                   1059:        tty.sg_flags |= RAW;
                   1060:        ex_sTTY(1);
                   1061: }
                   1062: #endif
                   1063: 
                   1064: /*
                   1065:  * Restore flags to normal state f.
                   1066:  */
                   1067: normal(f)
                   1068:        ttymode f;
                   1069: {
                   1070: 
                   1071:        if (normtty > 0) {
                   1072:                ignore(setty(f));
                   1073:                normtty--;
                   1074:        }
                   1075: }
                   1076: 
                   1077: /*
                   1078:  * Straight set of flags to state f.
                   1079:  */
                   1080: ttymode
                   1081: setty(f)
                   1082:        ttymode f;
                   1083: {
                   1084: #ifndef USG3TTY
                   1085:        register int ot = tty.sg_flags;
                   1086: #else
                   1087:        ttymode ot;
                   1088:        ot = tty;
                   1089: #endif
                   1090: 
                   1091: #ifndef USG3TTY
                   1092: # ifdef TIOCGETC
                   1093:        if (f == normf) {
                   1094:                nttyc = ottyc;
                   1095: # ifdef TIOCLGET
                   1096:                nlttyc = olttyc;
                   1097: # endif
                   1098:        } else
                   1099:                ttcharoff();
                   1100: # endif
                   1101:        tty.sg_flags = f;
                   1102: #else
                   1103:        if (tty.c_lflag & ICANON)
                   1104:                ttcharoff();
                   1105:        tty = f;
                   1106: #endif
                   1107:        ex_sTTY(1);
                   1108:        return (ot);
                   1109: }
                   1110: 
                   1111: ex_gTTY(i)
                   1112:        int i;
                   1113: {
                   1114: 
                   1115: #ifndef USG3TTY
                   1116:        ignore(ioctl(i, TIOCGETP, &tty));
                   1117: # ifdef TIOCGETC
                   1118:        ioctl(i, TIOCGETC, (char *) &ottyc);
                   1119:        nttyc = ottyc;
                   1120: # endif
                   1121: # ifdef TIOCGLTC
                   1122:        ioctl(i, TIOCGLTC, (char *) &olttyc);
                   1123:        nlttyc = olttyc;
                   1124: # endif
                   1125: #else
                   1126:        ioctl(i, TCGETA, (char *) &tty);
                   1127: #endif
                   1128: }
                   1129: 
                   1130: /*
                   1131:  * ex_sTTY: set the tty modes on file descriptor i to be what's
                   1132:  * currently in global "tty".  (Also use nttyc if needed.)
                   1133:  */
                   1134: ex_sTTY(i)
                   1135:        int i;
                   1136: {
                   1137: 
                   1138: #ifndef USG3TTY
                   1139: # ifdef USG
                   1140:        /* Bug in USG tty driver, put out a DEL as a patch. */
                   1141:        if (tty.sg_ospeed >= B1200)
                   1142:                write(1, "\377", 1);
                   1143: # endif
                   1144: 
                   1145: # ifdef TIOCSETN
                   1146:        /* Don't flush typeahead if we don't have to */
                   1147:        ioctl(i, TIOCSETN, (char *) &tty);
                   1148: # else
                   1149:        /* We have to.  Too bad. */
                   1150:        stty(i, &tty);
                   1151: # endif
                   1152: 
                   1153: # ifdef TIOCGETC
                   1154:        /* Update the other random chars while we're at it. */
                   1155:        ioctl(i, TIOCSETC, (char *) &nttyc);
                   1156: # endif
                   1157: # ifdef TIOCSLTC
                   1158:        ioctl(i, TIOCSLTC, (char *) &nlttyc);
                   1159: # endif
                   1160: 
                   1161: #else
                   1162:        /* USG 3 very simple: just set everything */
                   1163:        ioctl(i, TCSETAW, (char *) &tty);
                   1164: #endif
                   1165: }
                   1166: 
                   1167: /*
                   1168:  * Print newline, or blank if in open/visual
                   1169:  */
                   1170: noonl()
                   1171: {
                   1172: 
                   1173:        ex_putchar(Outchar != termchar ? ' ' : '\n');
                   1174: }

unix.superglobalmegacorp.com

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