Annotation of 41BSD/cmd/ex/ex_put.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1980 Regents of the University of California */
                      2: static char *sccsid = "@(#)ex_put.c    6.3 11/3/80";
                      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: static 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('\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:        while (outline < destline) {
                    566:                outline++;
                    567:                if (xNL && pfast)
                    568:                        tputs(xNL, 0, plodput);
                    569:                else
                    570:                        plodput('\n');
                    571:                if (plodcnt < 0)
                    572:                        goto out;
                    573:                if (NONL || pfast == 0)
                    574:                        outcol = 0;
                    575:        }
                    576:        if (BT)
                    577:                k = strlen(BT);
                    578:        while (outcol > destcol) {
                    579:                if (plodcnt < 0)
                    580:                        goto out;
                    581: /*
                    582:                if (BT && !insmode && outcol - destcol > 4+k) {
                    583:                        tputs(BT, 0, plodput);
                    584:                        outcol--;
                    585:                        outcol &= ~7;
                    586:                        continue;
                    587:                }
                    588: */
                    589:                outcol--;
                    590:                if (BC)
                    591:                        tputs(BC, 0, plodput);
                    592:                else
                    593:                        plodput('\b');
                    594:        }
                    595:        while (outline > destline) {
                    596:                outline--;
                    597:                tputs(UP, 0, plodput);
                    598:                if (plodcnt < 0)
                    599:                        goto out;
                    600:        }
                    601:        if (GT && !insmode && destcol - outcol > 1) {
                    602:        for (;;) {
                    603:                i = tabcol(outcol, value(HARDTABS));
                    604:                if (i > destcol)
                    605:                        break;
                    606:                        if (TA)
                    607:                                tputs(TA, 0, plodput);
                    608:                        else
                    609:                                plodput('\t');
                    610:                        outcol = i;
                    611:                }
                    612:                if (destcol - outcol > 4 && i < COLUMNS && (BC || BS)) {
                    613:                        if (TA)
                    614:                                tputs(TA, 0, plodput);
                    615:                        else
                    616:                                plodput('\t');
                    617:                        outcol = i;
                    618:                        while (outcol > destcol) {
                    619:                                outcol--;
                    620:                                if (BC)
                    621:                                        tputs(BC, 0, plodput);
                    622:                                else
                    623:                                        plodput('\b');
                    624:                        }
                    625:                }
                    626:        }
                    627:        while (outcol < destcol) {
                    628:                /*
                    629:                 * move one char to the right.  We don't use ND space
                    630:                 * because it's better to just print the char we are
                    631:                 * moving over.  There are various exceptions, however.
                    632:                 * If !inopen, vtube contains garbage.  If the char is
                    633:                 * a null or a tab we want to print a space.  Other random
                    634:                 * chars we use space for instead, too.
                    635:                 */
                    636:                if (!inopen || vtube[outline]==NULL ||
                    637:                        (i=vtube[outline][outcol]) < ' ')
                    638:                        i = ' ';
                    639:                if (insmode && ND)
                    640:                        tputs(ND, 0, plodput);
                    641:                else
                    642:                        plodput(i);
                    643:                outcol++;
                    644:                if (plodcnt < 0)
                    645:                        goto out;
                    646:        }
                    647: out:
                    648:        if (plodflg) {
                    649:                outcol = soutcol;
                    650:                outline = soutline;
                    651:        }
                    652:        return(plodcnt);
                    653: }
                    654: 
                    655: /*
                    656:  * An input line arrived.
                    657:  * Calculate new (approximate) screen line position.
                    658:  * Approximate because kill character echoes newline with
                    659:  * no feedback and also because of long input lines.
                    660:  */
                    661: noteinp()
                    662: {
                    663: 
                    664:        outline++;
                    665:        if (outline > LINES - 1)
                    666:                outline = LINES - 1;
                    667:        destline = outline;
                    668:        destcol = outcol = 0;
                    669: }
                    670: 
                    671: /*
                    672:  * Something weird just happened and we
                    673:  * lost track of whats happening out there.
                    674:  * Since we cant, in general, read where we are
                    675:  * we just reset to some known state.
                    676:  * On cursor addressible terminals setting to unknown
                    677:  * will force a cursor address soon.
                    678:  */
                    679: termreset()
                    680: {
                    681: 
                    682:        endim();
                    683:        if (TI) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */
                    684:                putpad(TI);      /*adb change -- emit terminal initial sequence */
                    685:        destcol = 0;
                    686:        destline = LINES - 1;
                    687:        if (CA) {
                    688:                outcol = UKCOL;
                    689:                outline = UKCOL;
                    690:        } else {
                    691:                outcol = destcol;
                    692:                outline = destline;
                    693:        }
                    694: }
                    695: 
                    696: /*
                    697:  * Low level buffering, with the ability to drain
                    698:  * buffered output without printing it.
                    699:  */
                    700: char   *obp = obuf;
                    701: 
                    702: draino()
                    703: {
                    704: 
                    705:        obp = obuf;
                    706: }
                    707: 
                    708: flusho()
                    709: {
                    710: 
                    711:        if (obp != obuf) {
                    712:                write(1, obuf, obp - obuf);
                    713:                obp = obuf;
                    714:        }
                    715: }
                    716: 
                    717: putnl()
                    718: {
                    719: 
                    720:        putchar('\n');
                    721: }
                    722: 
                    723: putS(cp)
                    724:        char *cp;
                    725: {
                    726: 
                    727:        if (cp == NULL)
                    728:                return;
                    729:        while (*cp)
                    730:                putch(*cp++);
                    731: }
                    732: 
                    733: 
                    734: putch(c)
                    735:        int c;
                    736: {
                    737: 
                    738:        *obp++ = c & 0177;
                    739:        if (obp >= &obuf[sizeof obuf])
                    740:                flusho();
                    741: }
                    742: 
                    743: /*
                    744:  * Miscellaneous routines related to output.
                    745:  */
                    746: 
                    747: /*
                    748:  * Put with padding
                    749:  */
                    750: putpad(cp)
                    751:        char *cp;
                    752: {
                    753: 
                    754:        flush();
                    755:        tputs(cp, 0, putch);
                    756: }
                    757: 
                    758: /*
                    759:  * Set output through normal command mode routine.
                    760:  */
                    761: setoutt()
                    762: {
                    763: 
                    764:        Outchar = termchar;
                    765: }
                    766: 
                    767: /*
                    768:  * Printf (temporarily) in list mode.
                    769:  */
                    770: /*VARARGS2*/
                    771: lprintf(cp, dp)
                    772:        char *cp, *dp;
                    773: {
                    774:        register int (*P)();
                    775: 
                    776:        P = setlist(1);
                    777:        printf(cp, dp);
                    778:        Putchar = P;
                    779: }
                    780: 
                    781: /*
                    782:  * Newline + flush.
                    783:  */
                    784: putNFL()
                    785: {
                    786: 
                    787:        putnl();
                    788:        flush();
                    789: }
                    790: 
                    791: /*
                    792:  * Try to start -nl mode.
                    793:  */
                    794: pstart()
                    795: {
                    796: 
                    797:        if (NONL)
                    798:                return;
                    799:        if (!value(OPTIMIZE))
                    800:                return;
                    801:        if (ruptible == 0 || pfast)
                    802:                return;
                    803:        fgoto();
                    804:        flusho();
                    805:        pfast = 1;
                    806:        normtty++;
                    807: #ifndef USG3TTY
                    808:        tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
                    809: #else
                    810:        tty = normf;
                    811:        tty.c_oflag &= ~(ONLCR|TAB3);
                    812:        tty.c_lflag &= ~ECHO;
                    813: #endif
                    814:        sTTY(1);
                    815: }
                    816: 
                    817: /*
                    818:  * Stop -nl mode.
                    819:  */
                    820: pstop()
                    821: {
                    822: 
                    823:        if (inopen)
                    824:                return;
                    825:        phadnl = 0;
                    826:        linp = linb;
                    827:        draino();
                    828:        normal(normf);
                    829:        pfast &= ~1;
                    830: }
                    831: 
                    832: /*
                    833:  * Prep tty for open mode.
                    834:  */
                    835: ttymode
                    836: ostart()
                    837: {
                    838:        ttymode f;
                    839: 
                    840:        if (!intty)
                    841:                error("Open and visual must be used interactively");
                    842:        gTTY(1);
                    843:        normtty++;
                    844: #ifndef USG3TTY
                    845:        f = tty.sg_flags;
                    846:        tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
                    847: # ifdef CBREAK
                    848:                                                        CBREAK;
                    849: # else
                    850:                                                        RAW;
                    851: # endif
                    852: # ifdef TIOCGETC
                    853:        ttcharoff();
                    854: # endif
                    855: #else
                    856:        f = tty;
                    857:        tty = normf;
                    858:        tty.c_iflag &= ~ICRNL;
                    859:        tty.c_lflag &= ~(ECHO|ICANON);
                    860:        tty.c_oflag &= ~TAB3;
                    861:        tty.c_cc[VMIN] = 1;
                    862:        tty.c_cc[VTIME] = 1;
                    863:        ttcharoff();
                    864: #endif
                    865:        sTTY(1);
                    866:        tostart();
                    867:        pfast |= 2;
                    868:        return (f);
                    869: }
                    870: 
                    871: /* actions associated with putting the terminal in open mode */
                    872: tostart()
                    873: {
                    874:        putpad(VS);
                    875:        putpad(KS);
                    876:        if (!value(MESG)) {
                    877:                if (ttynbuf[0] == 0) {
                    878:                        register char *tn;
                    879:                        if ((tn=ttyname(2)) == NULL &&
                    880:                            (tn=ttyname(1)) == NULL &&
                    881:                            (tn=ttyname(0)) == NULL)
                    882:                                ttynbuf[0] = 1;
                    883:                        else
                    884:                                strcpy(ttynbuf, tn);
                    885:                }
                    886:                if (ttynbuf[0] != 1) {
                    887:                        struct stat sbuf;
                    888:                        stat(ttynbuf, &sbuf);
                    889:                        ttymesg = sbuf.st_mode & 0777;
                    890:                        chmod(ttynbuf,
                    891: #ifdef UCBV7
                    892:        /*
                    893:         * This applies to the UCB V7 Pdp-11 system with the
                    894:         * -u write option only.
                    895:         */
                    896:                                        0611    /* 11 = urgent only allowed */
                    897: #else
                    898:                                        0600
                    899: #endif
                    900:                                                );
                    901:                }
                    902:        }
                    903: }
                    904: 
                    905: /*
                    906:  * Turn off start/stop chars if they aren't the default ^S/^Q.
                    907:  * This is so idiots who make esc their start/stop don't lose.
                    908:  * We always turn off quit since datamedias send ^\ for their
                    909:  * right arrow key.
                    910:  */
                    911: #ifdef TIOCGETC
                    912: ttcharoff()
                    913: {
                    914:        nttyc.t_quitc = '\377';
                    915:        if (nttyc.t_startc != CTRL(q))
                    916:                nttyc.t_startc = '\377';
                    917:        if (nttyc.t_stopc != CTRL(s))
                    918:                nttyc.t_stopc = '\377';
                    919: # ifdef TIOCLGET
                    920:        nlttyc.t_suspc = '\377';        /* ^Z */
                    921:        nlttyc.t_dsuspc = '\377';       /* ^Y */
                    922:        nlttyc.t_flushc = '\377';       /* ^O */
                    923:        nlttyc.t_lnextc = '\377';       /* ^V */
                    924: # endif
                    925: }
                    926: #endif
                    927: 
                    928: #ifdef USG3TTY
                    929: ttcharoff()
                    930: {
                    931:        tty.c_cc[VQUIT] = '\377';
                    932: # ifdef VSTART
                    933:        /*
                    934:         * The following is sample code if USG ever lets people change
                    935:         * their start/stop chars.  As long as they can't we can't get
                    936:         * into trouble so we just leave them alone.
                    937:         */
                    938:        if (tty.c_cc[VSTART] != CTRL(q))
                    939:                tty.c_cc[VSTART] = '\377';
                    940:        if (tty.c_cc[VSTOP] != CTRL(s))
                    941:                tty.c_cc[VSTOP] = '\377';
                    942: # endif
                    943: }
                    944: #endif
                    945: 
                    946: /*
                    947:  * Stop open, restoring tty modes.
                    948:  */
                    949: ostop(f)
                    950:        ttymode f;
                    951: {
                    952: 
                    953: #ifndef USG3TTY
                    954:        pfast = (f & CRMOD) == 0;
                    955: #else
                    956:        pfast = (f.c_oflag & OCRNL) == 0;
                    957: #endif
                    958:        termreset(), fgoto(), flusho();
                    959:        normal(f);
                    960:        tostop();
                    961: }
                    962: 
                    963: /* Actions associated with putting the terminal in the right mode. */
                    964: tostop()
                    965: {
                    966:        putpad(VE);
                    967:        putpad(KE);
                    968:        if (!value(MESG))
                    969:                chmod(ttynbuf, ttymesg);
                    970: }
                    971: 
                    972: #ifndef CBREAK
                    973: /*
                    974:  * Into cooked mode for interruptibility.
                    975:  */
                    976: vcook()
                    977: {
                    978: 
                    979:        tty.sg_flags &= ~RAW;
                    980:        sTTY(1);
                    981: }
                    982: 
                    983: /*
                    984:  * Back into raw mode.
                    985:  */
                    986: vraw()
                    987: {
                    988: 
                    989:        tty.sg_flags |= RAW;
                    990:        sTTY(1);
                    991: }
                    992: #endif
                    993: 
                    994: /*
                    995:  * Restore flags to normal state f.
                    996:  */
                    997: normal(f)
                    998:        ttymode f;
                    999: {
                   1000: 
                   1001:        if (normtty > 0) {
                   1002:                setty(f);
                   1003:                normtty--;
                   1004:        }
                   1005: }
                   1006: 
                   1007: /*
                   1008:  * Straight set of flags to state f.
                   1009:  */
                   1010: ttymode
                   1011: setty(f)
                   1012:        ttymode f;
                   1013: {
                   1014: #ifndef USG3TTY
                   1015:        register int ot = tty.sg_flags;
                   1016: #else
                   1017:        ttymode ot;
                   1018:        ot = tty;
                   1019: #endif
                   1020: 
                   1021: #ifndef USG3TTY
                   1022:        if (f == normf) {
                   1023:                nttyc = ottyc;
                   1024: # ifdef TIOCLGET
                   1025:                nlttyc = olttyc;
                   1026: # endif
                   1027:        } else
                   1028:                ttcharoff();
                   1029:        tty.sg_flags = f;
                   1030: #else
                   1031:        if (tty.c_lflag & ICANON)
                   1032:                ttcharoff();
                   1033:        tty = f;
                   1034: #endif
                   1035:        sTTY(1);
                   1036:        return (ot);
                   1037: }
                   1038: 
                   1039: gTTY(i)
                   1040:        int i;
                   1041: {
                   1042: 
                   1043: #ifndef USG3TTY
                   1044:        ignore(gtty(i, &tty));
                   1045: # ifdef TIOCGETC
                   1046:        ioctl(i, TIOCGETC, &ottyc);
                   1047:        nttyc = ottyc;
                   1048: # endif
                   1049: # ifdef TIOCGLTC
                   1050:        ioctl(i, TIOCGLTC, &olttyc);
                   1051:        nlttyc = olttyc;
                   1052: # endif
                   1053: #else
                   1054:        ioctl(i, TCGETA, &tty);
                   1055: #endif
                   1056: }
                   1057: 
                   1058: /*
                   1059:  * sTTY: set the tty modes on file descriptor i to be what's
                   1060:  * currently in global "tty".  (Also use nttyc if needed.)
                   1061:  */
                   1062: sTTY(i)
                   1063:        int i;
                   1064: {
                   1065: 
                   1066: #ifndef USG3TTY
                   1067: # ifdef USG
                   1068:        /* Bug in USG tty driver, put out a DEL as a patch. */
                   1069:        if (tty.sg_ospeed >= B1200)
                   1070:                write(1, "\377", 1);
                   1071: # endif
                   1072: 
                   1073: # ifdef TIOCSETN
                   1074:        /* Don't flush typeahead if we don't have to */
                   1075:        ioctl(i, TIOCSETN, &tty);
                   1076: # else
                   1077:        /* We have to.  Too bad. */
                   1078:        stty(i, &tty);
                   1079: # endif
                   1080: 
                   1081: # ifdef TIOCGETC
                   1082:        /* Update the other random chars while we're at it. */
                   1083:        ioctl(i, TIOCSETC, &nttyc);
                   1084: # endif
                   1085: # ifdef TIOCSLTC
                   1086:        ioctl(i, TIOCSLTC, &nlttyc);
                   1087: # endif
                   1088: 
                   1089: #else
                   1090:        /* USG 3 very simple: just set everything */
                   1091:        ioctl(i, TCSETAW, &tty);
                   1092: #endif
                   1093: }
                   1094: 
                   1095: /*
                   1096:  * Print newline, or blank if in open/visual
                   1097:  */
                   1098: noonl()
                   1099: {
                   1100: 
                   1101:        putchar(Outchar != termchar ? ' ' : '\n');
                   1102: }
                   1103: 
                   1104: #ifdef SIGTSTP
                   1105: /*
                   1106:  * We have just gotten a susp.  Suspend and prepare to resume.
                   1107:  */
                   1108: onsusp()
                   1109: {
                   1110:        ttymode f;
                   1111: 
                   1112:        f = setty(normf);
                   1113:        vnfl();
                   1114:        putpad(TE);
                   1115:        flush();
                   1116: 
                   1117:        signal(SIGTSTP, SIG_DFL);
                   1118:        kill(0, SIGTSTP);
                   1119: 
                   1120:        /* the pc stops here */
                   1121: 
                   1122:        signal(SIGTSTP, onsusp);
                   1123:        vcontin(0);
                   1124:        setty(f);
                   1125:        if (!inopen)
                   1126:                error(0);
                   1127:        else {
                   1128:                if (vcnt < 0) {
                   1129:                        vcnt = -vcnt;
                   1130:                        if (state == VISUAL)
                   1131:                                vclear();
                   1132:                        else if (state == CRTOPEN)
                   1133:                                vcnt = 0;
                   1134:                }
                   1135:                vdirty(0, LINES);
                   1136:                vrepaint(cursor);
                   1137:        }
                   1138: }

unix.superglobalmegacorp.com

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