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