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