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