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) 06/07/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 } 1169