|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_put.c 6.3 11/3/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: ! 1104: #ifdef SIGTSTP ! 1105: /* ! 1106: * We have just gotten a susp. Suspend and prepare to resume. ! 1107: */ ! 1108: onsusp() ! 1109: { ! 1110: ttymode f; ! 1111: ! 1112: f = setty(normf); ! 1113: vnfl(); ! 1114: putpad(TE); ! 1115: flush(); ! 1116: ! 1117: signal(SIGTSTP, SIG_DFL); ! 1118: kill(0, SIGTSTP); ! 1119: ! 1120: /* the pc stops here */ ! 1121: ! 1122: signal(SIGTSTP, onsusp); ! 1123: vcontin(0); ! 1124: setty(f); ! 1125: if (!inopen) ! 1126: error(0); ! 1127: else { ! 1128: if (vcnt < 0) { ! 1129: vcnt = -vcnt; ! 1130: if (state == VISUAL) ! 1131: vclear(); ! 1132: else if (state == CRTOPEN) ! 1133: vcnt = 0; ! 1134: } ! 1135: vdirty(0, LINES); ! 1136: vrepaint(cursor); ! 1137: } ! 1138: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.