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