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: }