1 /* Copyright (c) 1981 Regents of the University of California */ 2 static char *sccsid = "@(#)ex_put.c 7.1 07/08/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 static 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 while (outline < destline) { 566 outline++; 567 if (xNL && pfast) 568 tputs(xNL, 0, plodput); 569 else 570 plodput('\n'); 571 if (plodcnt < 0) 572 goto out; 573 if (NONL || pfast == 0) 574 outcol = 0; 575 } 576 if (BT) 577 k = strlen(BT); 578 while (outcol > destcol) { 579 if (plodcnt < 0) 580 goto out; 581 /* 582 if (BT && !insmode && outcol - destcol > 4+k) { 583 tputs(BT, 0, plodput); 584 outcol--; 585 outcol &= ~7; 586 continue; 587 } 588 */ 589 outcol--; 590 if (BC) 591 tputs(BC, 0, plodput); 592 else 593 plodput('\b'); 594 } 595 while (outline > destline) { 596 outline--; 597 tputs(UP, 0, plodput); 598 if (plodcnt < 0) 599 goto out; 600 } 601 if (GT && !insmode && destcol - outcol > 1) { 602 for (;;) { 603 i = tabcol(outcol, value(HARDTABS)); 604 if (i > destcol) 605 break; 606 if (TA) 607 tputs(TA, 0, plodput); 608 else 609 plodput('\t'); 610 outcol = i; 611 } 612 if (destcol - outcol > 4 && i < COLUMNS && (BC || BS)) { 613 if (TA) 614 tputs(TA, 0, plodput); 615 else 616 plodput('\t'); 617 outcol = i; 618 while (outcol > destcol) { 619 outcol--; 620 if (BC) 621 tputs(BC, 0, plodput); 622 else 623 plodput('\b'); 624 } 625 } 626 } 627 while (outcol < destcol) { 628 /* 629 * move one char to the right. We don't use ND space 630 * because it's better to just print the char we are 631 * moving over. There are various exceptions, however. 632 * If !inopen, vtube contains garbage. If the char is 633 * a null or a tab we want to print a space. Other random 634 * chars we use space for instead, too. 635 */ 636 if (!inopen || vtube[outline]==NULL || 637 (i=vtube[outline][outcol]) < ' ') 638 i = ' '; 639 if(i & QUOTE) /* mjm: no sign extension on 3B */ 640 i = ' '; 641 if (insmode && ND) 642 tputs(ND, 0, plodput); 643 else 644 plodput(i); 645 outcol++; 646 if (plodcnt < 0) 647 goto out; 648 } 649 out: 650 if (plodflg) { 651 outcol = soutcol; 652 outline = soutline; 653 } 654 return(plodcnt); 655 } 656 657 /* 658 * An input line arrived. 659 * Calculate new (approximate) screen line position. 660 * Approximate because kill character echoes newline with 661 * no feedback and also because of long input lines. 662 */ 663 noteinp() 664 { 665 666 outline++; 667 if (outline > LINES - 1) 668 outline = LINES - 1; 669 destline = outline; 670 destcol = outcol = 0; 671 } 672 673 /* 674 * Something weird just happened and we 675 * lost track of whats happening out there. 676 * Since we cant, in general, read where we are 677 * we just reset to some known state. 678 * On cursor addressible terminals setting to unknown 679 * will force a cursor address soon. 680 */ 681 termreset() 682 { 683 684 endim(); 685 if (TI) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */ 686 putpad(TI); /*adb change -- emit terminal initial sequence */ 687 destcol = 0; 688 destline = LINES - 1; 689 if (CA) { 690 outcol = UKCOL; 691 outline = UKCOL; 692 } else { 693 outcol = destcol; 694 outline = destline; 695 } 696 } 697 698 /* 699 * Low level buffering, with the ability to drain 700 * buffered output without printing it. 701 */ 702 char *obp = obuf; 703 704 draino() 705 { 706 707 obp = obuf; 708 } 709 710 flusho() 711 { 712 713 if (obp != obuf) { 714 write(1, obuf, obp - obuf); 715 obp = obuf; 716 } 717 } 718 719 putnl() 720 { 721 722 putchar('\n'); 723 } 724 725 putS(cp) 726 char *cp; 727 { 728 729 if (cp == NULL) 730 return; 731 while (*cp) 732 putch(*cp++); 733 } 734 735 736 putch(c) 737 int c; 738 { 739 740 #ifdef OLD3BTTY /* mjm */ 741 if(c == '\n') /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */ 742 putch('\r'); /* mjm: vi does "stty -icanon" => -onlcr !! */ 743 #endif 744 *obp++ = c & 0177; 745 if (obp >= &obuf[sizeof obuf]) 746 flusho(); 747 } 748 749 /* 750 * Miscellaneous routines related to output. 751 */ 752 753 /* 754 * Put with padding 755 */ 756 putpad(cp) 757 char *cp; 758 { 759 760 flush(); 761 tputs(cp, 0, putch); 762 } 763 764 /* 765 * Set output through normal command mode routine. 766 */ 767 setoutt() 768 { 769 770 Outchar = termchar; 771 } 772 773 /* 774 * Printf (temporarily) in list mode. 775 */ 776 /*VARARGS2*/ 777 lprintf(cp, dp) 778 char *cp, *dp; 779 { 780 register int (*P)(); 781 782 P = setlist(1); 783 printf(cp, dp); 784 Putchar = P; 785 } 786 787 /* 788 * Newline + flush. 789 */ 790 putNFL() 791 { 792 793 putnl(); 794 flush(); 795 } 796 797 /* 798 * Try to start -nl mode. 799 */ 800 pstart() 801 { 802 803 if (NONL) 804 return; 805 if (!value(OPTIMIZE)) 806 return; 807 if (ruptible == 0 || pfast) 808 return; 809 fgoto(); 810 flusho(); 811 pfast = 1; 812 normtty++; 813 #ifndef USG3TTY 814 tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD); 815 #else 816 tty = normf; 817 tty.c_oflag &= ~(ONLCR|TAB3); 818 tty.c_lflag &= ~ECHO; 819 #endif 820 sTTY(1); 821 } 822 823 /* 824 * Stop -nl mode. 825 */ 826 pstop() 827 { 828 829 if (inopen) 830 return; 831 phadnl = 0; 832 linp = linb; 833 draino(); 834 normal(normf); 835 pfast &= ~1; 836 } 837 838 /* 839 * Prep tty for open mode. 840 */ 841 ttymode 842 ostart() 843 { 844 ttymode f; 845 846 if (!intty) 847 error("Open and visual must be used interactively"); 848 gTTY(1); 849 normtty++; 850 #ifndef USG3TTY 851 f = tty.sg_flags; 852 tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | 853 # ifdef CBREAK 854 CBREAK; 855 # else 856 RAW; 857 # endif 858 # ifdef TIOCGETC 859 ttcharoff(); 860 # endif 861 #else 862 f = tty; 863 tty = normf; 864 tty.c_iflag &= ~ICRNL; 865 tty.c_lflag &= ~(ECHO|ICANON); 866 tty.c_oflag &= ~TAB3; 867 tty.c_cc[VMIN] = 1; 868 tty.c_cc[VTIME] = 1; 869 ttcharoff(); 870 #endif 871 sTTY(1); 872 tostart(); 873 pfast |= 2; 874 return (f); 875 } 876 877 /* actions associated with putting the terminal in open mode */ 878 tostart() 879 { 880 putpad(VS); 881 putpad(KS); 882 if (!value(MESG)) { 883 if (ttynbuf[0] == 0) { 884 register char *tn; 885 if ((tn=ttyname(2)) == NULL && 886 (tn=ttyname(1)) == NULL && 887 (tn=ttyname(0)) == NULL) 888 ttynbuf[0] = 1; 889 else 890 strcpy(ttynbuf, tn); 891 } 892 if (ttynbuf[0] != 1) { 893 struct stat sbuf; 894 stat(ttynbuf, &sbuf); 895 ttymesg = sbuf.st_mode & 0777; 896 chmod(ttynbuf, 897 #ifdef UCBV7 898 /* 899 * This applies to the UCB V7 Pdp-11 system with the 900 * -u write option only. 901 */ 902 0611 /* 11 = urgent only allowed */ 903 #else 904 0600 905 #endif 906 ); 907 } 908 } 909 } 910 911 /* 912 * Turn off start/stop chars if they aren't the default ^S/^Q. 913 * This is so idiots who make esc their start/stop don't lose. 914 * We always turn off quit since datamedias send ^\ for their 915 * right arrow key. 916 */ 917 #ifdef TIOCGETC 918 ttcharoff() 919 { 920 nttyc.t_quitc = '\377'; 921 if (nttyc.t_startc != CTRL(q)) 922 nttyc.t_startc = '\377'; 923 if (nttyc.t_stopc != CTRL(s)) 924 nttyc.t_stopc = '\377'; 925 # ifdef TIOCLGET 926 nlttyc.t_suspc = '\377'; /* ^Z */ 927 nlttyc.t_dsuspc = '\377'; /* ^Y */ 928 nlttyc.t_flushc = '\377'; /* ^O */ 929 nlttyc.t_lnextc = '\377'; /* ^V */ 930 # endif 931 } 932 #endif 933 934 #ifdef USG3TTY 935 ttcharoff() 936 { 937 tty.c_cc[VQUIT] = '\377'; 938 # ifdef VSTART 939 /* 940 * The following is sample code if USG ever lets people change 941 * their start/stop chars. As long as they can't we can't get 942 * into trouble so we just leave them alone. 943 */ 944 if (tty.c_cc[VSTART] != CTRL(q)) 945 tty.c_cc[VSTART] = '\377'; 946 if (tty.c_cc[VSTOP] != CTRL(s)) 947 tty.c_cc[VSTOP] = '\377'; 948 # endif 949 } 950 #endif 951 952 /* 953 * Stop open, restoring tty modes. 954 */ 955 ostop(f) 956 ttymode f; 957 { 958 959 #ifndef USG3TTY 960 pfast = (f & CRMOD) == 0; 961 #else 962 pfast = (f.c_oflag & OCRNL) == 0; 963 #endif 964 termreset(), fgoto(), flusho(); 965 normal(f); 966 tostop(); 967 } 968 969 /* Actions associated with putting the terminal in the right mode. */ 970 tostop() 971 { 972 putpad(VE); 973 putpad(KE); 974 if (!value(MESG)) 975 chmod(ttynbuf, ttymesg); 976 } 977 978 #ifndef CBREAK 979 /* 980 * Into cooked mode for interruptibility. 981 */ 982 vcook() 983 { 984 985 tty.sg_flags &= ~RAW; 986 sTTY(1); 987 } 988 989 /* 990 * Back into raw mode. 991 */ 992 vraw() 993 { 994 995 tty.sg_flags |= RAW; 996 sTTY(1); 997 } 998 #endif 999 1000 /* 1001 * Restore flags to normal state f. 1002 */ 1003 normal(f) 1004 ttymode f; 1005 { 1006 1007 if (normtty > 0) { 1008 setty(f); 1009 normtty--; 1010 } 1011 } 1012 1013 /* 1014 * Straight set of flags to state f. 1015 */ 1016 ttymode 1017 setty(f) 1018 ttymode f; 1019 { 1020 #ifndef USG3TTY 1021 register int ot = tty.sg_flags; 1022 #else 1023 ttymode ot; 1024 ot = tty; 1025 #endif 1026 1027 #ifndef USG3TTY 1028 if (f == normf) { 1029 nttyc = ottyc; 1030 # ifdef TIOCLGET 1031 nlttyc = olttyc; 1032 # endif 1033 } else 1034 ttcharoff(); 1035 tty.sg_flags = f; 1036 #else 1037 if (tty.c_lflag & ICANON) 1038 ttcharoff(); 1039 tty = f; 1040 #endif 1041 sTTY(1); 1042 return (ot); 1043 } 1044 1045 gTTY(i) 1046 int i; 1047 { 1048 1049 #ifndef USG3TTY 1050 ignore(gtty(i, &tty)); 1051 # ifdef TIOCGETC 1052 ioctl(i, TIOCGETC, &ottyc); 1053 nttyc = ottyc; 1054 # endif 1055 # ifdef TIOCGLTC 1056 ioctl(i, TIOCGLTC, &olttyc); 1057 nlttyc = olttyc; 1058 # endif 1059 #else 1060 ioctl(i, TCGETA, &tty); 1061 #endif 1062 } 1063 1064 /* 1065 * sTTY: set the tty modes on file descriptor i to be what's 1066 * currently in global "tty". (Also use nttyc if needed.) 1067 */ 1068 sTTY(i) 1069 int i; 1070 { 1071 1072 #ifndef USG3TTY 1073 # ifdef USG 1074 /* Bug in USG tty driver, put out a DEL as a patch. */ 1075 if (tty.sg_ospeed >= B1200) 1076 write(1, "\377", 1); 1077 # endif 1078 1079 # ifdef TIOCSETN 1080 /* Don't flush typeahead if we don't have to */ 1081 ioctl(i, TIOCSETN, &tty); 1082 # else 1083 /* We have to. Too bad. */ 1084 stty(i, &tty); 1085 # endif 1086 1087 # ifdef TIOCGETC 1088 /* Update the other random chars while we're at it. */ 1089 ioctl(i, TIOCSETC, &nttyc); 1090 # endif 1091 # ifdef TIOCSLTC 1092 ioctl(i, TIOCSLTC, &nlttyc); 1093 # endif 1094 1095 #else 1096 /* USG 3 very simple: just set everything */ 1097 ioctl(i, TCSETAW, &tty); 1098 #endif 1099 } 1100 1101 /* 1102 * Print newline, or blank if in open/visual 1103 */ 1104 noonl() 1105 { 1106 1107 putchar(Outchar != termchar ? ' ' : '\n'); 1108 } 1109