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