|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid = "@(#)ex_put.c 7.11 (Berkeley) 1/2/88"; ! 9: #endif not lint ! 10: ! 11: #include "ex.h" ! 12: #include "ex_tty.h" ! 13: #include "ex_vis.h" ! 14: ! 15: /* ! 16: * Terminal driving and line formatting routines. ! 17: * Basic motion optimizations are done here as well ! 18: * as formatting of lines (printing of control characters, ! 19: * line numbering and the like). ! 20: */ ! 21: ! 22: /* ! 23: * The routines outchar, putchar and pline are actually ! 24: * variables, and these variables point at the current definitions ! 25: * of the routines. See the routine setflav. ! 26: * We sometimes make outchar be routines which catch the characters ! 27: * to be printed, e.g. if we want to see how long a line is. ! 28: * During open/visual, outchar and putchar will be set to ! 29: * routines in the file ex_vput.c (vputchar, vinschar, etc.). ! 30: */ ! 31: int (*Outchar)() = termchar; ! 32: int (*Put_char)() = normchar; ! 33: int (*Pline)() = normline; ! 34: ! 35: int (* ! 36: setlist(t))() ! 37: bool t; ! 38: { ! 39: register int (*P)(); ! 40: ! 41: listf = t; ! 42: P = Put_char; ! 43: Put_char = t ? listchar : normchar; ! 44: return (P); ! 45: } ! 46: ! 47: int (* ! 48: setnumb(t))() ! 49: bool t; ! 50: { ! 51: register int (*P)(); ! 52: ! 53: numberf = t; ! 54: P = Pline; ! 55: Pline = t ? numbline : normline; ! 56: return (P); ! 57: } ! 58: ! 59: /* ! 60: * Format c for list mode; leave things in common ! 61: * with normal print mode to be done by normchar. ! 62: */ ! 63: listchar(c) ! 64: register short c; ! 65: { ! 66: ! 67: c &= (TRIM|QUOTE); ! 68: switch (c) { ! 69: ! 70: case '\t': ! 71: case '\b': ! 72: outchar('^'); ! 73: c = ctlof(c); ! 74: break; ! 75: ! 76: case '\n': ! 77: break; ! 78: ! 79: case '\n' | QUOTE: ! 80: outchar('$'); ! 81: break; ! 82: ! 83: default: ! 84: if (c & QUOTE) ! 85: break; ! 86: if (c < ' ' && c != '\n' || c == DELETE) ! 87: outchar('^'), c = ctlof(c); ! 88: break; ! 89: } ! 90: normchar(c); ! 91: } ! 92: ! 93: /* ! 94: * Format c for printing. Handle funnies of upper case terminals ! 95: * and crocky hazeltines which don't have ~. ! 96: */ ! 97: normchar(c) ! 98: register short c; ! 99: { ! 100: register char *colp; ! 101: ! 102: c &= (TRIM|QUOTE); ! 103: if (c == '~' && HZ) { ! 104: normchar('\\'); ! 105: c = '^'; ! 106: } ! 107: if (c & QUOTE) ! 108: switch (c) { ! 109: ! 110: case ' ' | QUOTE: ! 111: case '\b' | QUOTE: ! 112: break; ! 113: ! 114: case QUOTE: ! 115: return; ! 116: ! 117: default: ! 118: c &= TRIM; ! 119: } ! 120: else if (c < ' ' && (c != '\b' || !OS) && c != '\n' && c != '\t' || c == DELETE) ! 121: ex_putchar('^'), c = ctlof(c); ! 122: else if (UPPERCASE) ! 123: if (isupper(c)) { ! 124: outchar('\\'); ! 125: c = tolower(c); ! 126: } else { ! 127: colp = "({)}!|^~'`"; ! 128: while (*colp++) ! 129: if (c == *colp++) { ! 130: outchar('\\'); ! 131: c = colp[-2]; ! 132: break; ! 133: } ! 134: } ! 135: outchar(c); ! 136: } ! 137: ! 138: /* ! 139: * Print a line with a number. ! 140: */ ! 141: numbline(i) ! 142: int i; ! 143: { ! 144: ! 145: if (shudclob) ! 146: slobber(' '); ! 147: ex_printf("%6d ", i); ! 148: normline(); ! 149: } ! 150: ! 151: /* ! 152: * Normal line output, no numbering. ! 153: */ ! 154: normline() ! 155: { ! 156: register char *cp; ! 157: ! 158: if (shudclob) ! 159: slobber(linebuf[0]); ! 160: /* pdp-11 doprnt is not reentrant so can't use "printf" here ! 161: in case we are tracing */ ! 162: for (cp = linebuf; *cp;) ! 163: ex_putchar(*cp++); ! 164: if (!inopen) ! 165: ex_putchar('\n' | QUOTE); ! 166: } ! 167: ! 168: /* ! 169: * Given c at the beginning of a line, determine whether ! 170: * the printing of the line will erase or otherwise obliterate ! 171: * the prompt which was printed before. If it won't, do it now. ! 172: */ ! 173: slobber(c) ! 174: int c; ! 175: { ! 176: ! 177: shudclob = 0; ! 178: switch (c) { ! 179: ! 180: case '\t': ! 181: if (Put_char == listchar) ! 182: return; ! 183: break; ! 184: ! 185: default: ! 186: return; ! 187: ! 188: case ' ': ! 189: case 0: ! 190: break; ! 191: } ! 192: if (OS) ! 193: return; ! 194: flush(); ! 195: putch(' '); ! 196: if (BC) ! 197: tputs(BC, 0, putch); ! 198: else ! 199: putch('\b'); ! 200: } ! 201: ! 202: /* ! 203: * The output buffer is initialized with a useful error ! 204: * message so we don't have to keep it in data space. ! 205: */ ! 206: static char linb[66]; ! 207: char *linp = linb; ! 208: ! 209: /* ! 210: * Phadnl records when we have already had a complete line ending with \n. ! 211: * If another line starts without a flush, and the terminal suggests it, ! 212: * we switch into -nl mode so that we can send lineffeeds to avoid ! 213: * a lot of spacing. ! 214: */ ! 215: static bool phadnl; ! 216: ! 217: /* ! 218: * Indirect to current definition of putchar. ! 219: */ ! 220: ex_putchar(c) ! 221: int c; ! 222: { ! 223: ! 224: (*Put_char)(c); ! 225: } ! 226: ! 227: /* ! 228: * Termchar routine for command mode. ! 229: * Watch for possible switching to -nl mode. ! 230: * Otherwise flush into next level of buffering when ! 231: * small buffer fills or at a newline. ! 232: */ ! 233: termchar(c) ! 234: int c; ! 235: { ! 236: ! 237: if (pfast == 0 && phadnl) ! 238: pstart(); ! 239: if (c == '\n') ! 240: phadnl = 1; ! 241: else if (linp >= &linb[63]) ! 242: flush1(); ! 243: *linp++ = c; ! 244: if (linp >= &linb[63]) { ! 245: fgoto(); ! 246: flush1(); ! 247: } ! 248: } ! 249: ! 250: flush() ! 251: { ! 252: ! 253: flush1(); ! 254: flush2(); ! 255: } ! 256: ! 257: /* ! 258: * Flush from small line buffer into output buffer. ! 259: * Work here is destroying motion into positions, and then ! 260: * letting fgoto do the optimized motion. ! 261: */ ! 262: flush1() ! 263: { ! 264: register char *lp; ! 265: register short c; ! 266: ! 267: *linp = 0; ! 268: lp = linb; ! 269: while (*lp) ! 270: switch (c = *lp++) { ! 271: ! 272: case '\r': ! 273: destline += destcol / COLUMNS; ! 274: destcol = 0; ! 275: continue; ! 276: ! 277: case '\b': ! 278: if (destcol) ! 279: destcol--; ! 280: continue; ! 281: ! 282: case ' ': ! 283: destcol++; ! 284: continue; ! 285: ! 286: case '\t': ! 287: destcol += value(TABSTOP) - destcol % value(TABSTOP); ! 288: continue; ! 289: ! 290: case '\n': ! 291: destline += destcol / COLUMNS + 1; ! 292: if (destcol != 0 && destcol % COLUMNS == 0) ! 293: destline--; ! 294: destcol = 0; ! 295: continue; ! 296: ! 297: default: ! 298: fgoto(); ! 299: for (;;) { ! 300: if (AM == 0 && outcol == COLUMNS) ! 301: fgoto(); ! 302: c &= TRIM; ! 303: putch(c); ! 304: if (c == '\b') { ! 305: outcol--; ! 306: destcol--; ! 307: } else if (c >= ' ' && c != DELETE) { ! 308: outcol++; ! 309: destcol++; ! 310: if (XN && outcol % COLUMNS == 0) ! 311: putch('\r'), putch('\n'); ! 312: } ! 313: c = *lp++; ! 314: if (c <= ' ') ! 315: break; ! 316: } ! 317: --lp; ! 318: continue; ! 319: } ! 320: linp = linb; ! 321: } ! 322: ! 323: flush2() ! 324: { ! 325: ! 326: fgoto(); ! 327: flusho(); ! 328: pstop(); ! 329: } ! 330: ! 331: /* ! 332: * Sync the position of the output cursor. ! 333: * Most work here is rounding for terminal boundaries getting the ! 334: * column position implied by wraparound or the lack thereof and ! 335: * rolling up the screen to get destline on the screen. ! 336: */ ! 337: fgoto() ! 338: { ! 339: register int l, c; ! 340: ! 341: if (destcol > COLUMNS - 1) { ! 342: destline += destcol / COLUMNS; ! 343: destcol %= COLUMNS; ! 344: } ! 345: if (outcol > COLUMNS - 1) { ! 346: l = (outcol + 1) / COLUMNS; ! 347: outline += l; ! 348: outcol %= COLUMNS; ! 349: if (AM == 0) { ! 350: while (l > 0) { ! 351: if (pfast) ! 352: if (xCR) ! 353: tputs(xCR, 0, putch); ! 354: else ! 355: putch('\r'); ! 356: if (xNL) ! 357: tputs(xNL, 0, putch); ! 358: else ! 359: putch('\n'); ! 360: l--; ! 361: } ! 362: outcol = 0; ! 363: } ! 364: if (outline > LINES - 1) { ! 365: destline -= outline - (LINES - 1); ! 366: outline = LINES - 1; ! 367: } ! 368: } ! 369: if (destline > LINES - 1) { ! 370: l = destline; ! 371: destline = LINES - 1; ! 372: if (outline < LINES - 1) { ! 373: c = destcol; ! 374: if (pfast == 0 && (!CA || holdcm)) ! 375: destcol = 0; ! 376: fgoto(); ! 377: destcol = c; ! 378: } ! 379: while (l > LINES - 1) { ! 380: /* ! 381: * The following linefeed (or simulation thereof) ! 382: * is supposed to scroll up the screen, since we ! 383: * are on the bottom line. We make the assumption ! 384: * that linefeed will scroll. If ns is in the ! 385: * capability list this won't work. We should ! 386: * probably have an sc capability but sf will ! 387: * generally take the place if it works. ! 388: * ! 389: * Superbee glitch: in the middle of the screen we ! 390: * have to use esc B (down) because linefeed screws up ! 391: * in "Efficient Paging" (what a joke) mode (which is ! 392: * essential in some SB's because CRLF mode puts garbage ! 393: * in at end of memory), but you must use linefeed to ! 394: * scroll since down arrow won't go past memory end. ! 395: * I turned this off after recieving Paul Eggert's ! 396: * Superbee description which wins better. ! 397: */ ! 398: if (xNL /* && !XB */ && pfast) ! 399: tputs(xNL, 0, putch); ! 400: else ! 401: putch('\n'); ! 402: l--; ! 403: if (pfast == 0) ! 404: outcol = 0; ! 405: } ! 406: } ! 407: if (destline < outline && !(CA && !holdcm || UP != NOSTR)) ! 408: destline = outline; ! 409: if (CA && !holdcm) ! 410: if (plod(costCM) > 0) ! 411: plod(0); ! 412: else ! 413: tputs(tgoto(CM, destcol, destline), 0, putch); ! 414: else ! 415: plod(0); ! 416: outline = destline; ! 417: outcol = destcol; ! 418: } ! 419: ! 420: /* ! 421: * Tab to column col by flushing and then setting destcol. ! 422: * Used by "set all". ! 423: */ ! 424: tab(col) ! 425: int col; ! 426: { ! 427: ! 428: flush1(); ! 429: destcol = col; ! 430: } ! 431: ! 432: /* ! 433: * Move (slowly) to destination. ! 434: * Hard thing here is using home cursor on really deficient terminals. ! 435: * Otherwise just use cursor motions, hacking use of tabs and overtabbing ! 436: * and backspace. ! 437: */ ! 438: ! 439: static int plodcnt, plodflg; ! 440: ! 441: plodput(c) ! 442: { ! 443: ! 444: if (plodflg) ! 445: plodcnt--; ! 446: else ! 447: putch(c); ! 448: } ! 449: ! 450: plod(cnt) ! 451: { ! 452: register int i, j, k; ! 453: register int soutcol, soutline; ! 454: ! 455: plodcnt = plodflg = cnt; ! 456: soutcol = outcol; ! 457: soutline = outline; ! 458: /* ! 459: * Consider homing and moving down/right from there, vs moving ! 460: * directly with local motions to the right spot. ! 461: */ ! 462: if (HO) { ! 463: /* ! 464: * i is the cost to home and tab/space to the right to ! 465: * get to the proper column. This assumes ND space costs ! 466: * 1 char. So i+destcol is cost of motion with home. ! 467: */ ! 468: if (GT) ! 469: i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS)); ! 470: else ! 471: i = destcol; ! 472: /* ! 473: * j is cost to move locally without homing ! 474: */ ! 475: if (destcol >= outcol) { /* if motion is to the right */ ! 476: j = destcol / value(HARDTABS) - outcol / value(HARDTABS); ! 477: if (GT && j) ! 478: j += destcol % value(HARDTABS); ! 479: else ! 480: j = destcol - outcol; ! 481: } else ! 482: /* leftward motion only works if we can backspace. */ ! 483: if (outcol - destcol <= i && (BS || BC)) ! 484: i = j = outcol - destcol; /* cheaper to backspace */ ! 485: else ! 486: j = i + 1; /* impossibly expensive */ ! 487: ! 488: /* k is the absolute value of vertical distance */ ! 489: k = outline - destline; ! 490: if (k < 0) ! 491: k = -k; ! 492: j += k; ! 493: ! 494: /* ! 495: * Decision. We may not have a choice if no UP. ! 496: */ ! 497: if (i + destline < j || (!UP && destline < outline)) { ! 498: /* ! 499: * Cheaper to home. Do it now and pretend it's a ! 500: * regular local motion. ! 501: */ ! 502: tputs(HO, 0, plodput); ! 503: outcol = outline = 0; ! 504: } else if (LL) { ! 505: /* ! 506: * Quickly consider homing down and moving from there. ! 507: * Assume cost of LL is 2. ! 508: */ ! 509: k = (LINES - 1) - destline; ! 510: if (i + k + 2 < j && (k<=0 || UP)) { ! 511: tputs(LL, 0, plodput); ! 512: outcol = 0; ! 513: outline = LINES - 1; ! 514: } ! 515: } ! 516: } else ! 517: /* ! 518: * No home and no up means it's impossible, so we return an ! 519: * incredibly big number to make cursor motion win out. ! 520: */ ! 521: if (!UP && destline < outline) ! 522: return (500); ! 523: if (GT) ! 524: i = destcol % value(HARDTABS) ! 525: + destcol / value(HARDTABS); ! 526: else ! 527: i = destcol; ! 528: /* ! 529: if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) { ! 530: j *= (k = strlen(BT)); ! 531: if ((k += (destcol&7)) > 4) ! 532: j += 8 - (destcol&7); ! 533: else ! 534: j += k; ! 535: } else ! 536: */ ! 537: j = outcol - destcol; ! 538: /* ! 539: * If we will later need a \n which will turn into a \r\n by ! 540: * the system or the terminal, then don't bother to try to \r. ! 541: */ ! 542: if ((NONL || !pfast) && outline < destline) ! 543: goto dontcr; ! 544: /* ! 545: * If the terminal will do a \r\n and there isn't room for it, ! 546: * then we can't afford a \r. ! 547: */ ! 548: if (NC && outline >= destline) ! 549: goto dontcr; ! 550: /* ! 551: * If it will be cheaper, or if we can't back up, then send ! 552: * a return preliminarily. ! 553: */ ! 554: if (j > i + 1 || outcol > destcol && !BS && !BC) { ! 555: /* ! 556: * BUG: this doesn't take the (possibly long) length ! 557: * of xCR into account. ! 558: */ ! 559: if (xCR) ! 560: tputs(xCR, 0, plodput); ! 561: else ! 562: plodput('\r'); ! 563: if (NC) { ! 564: if (xNL) ! 565: tputs(xNL, 0, plodput); ! 566: else ! 567: plodput('\n'); ! 568: outline++; ! 569: } ! 570: outcol = 0; ! 571: } ! 572: dontcr: ! 573: /* Move down, if necessary, until we are at the desired line */ ! 574: while (outline < destline) { ! 575: j = destline - outline; ! 576: if (j > costDP && DOWN_PARM) { ! 577: /* Win big on Tek 4025 */ ! 578: tputs(tgoto(DOWN_PARM, 0, j), j, plodput); ! 579: outline += j; ! 580: } ! 581: else { ! 582: outline++; ! 583: if (xNL && pfast) ! 584: tputs(xNL, 0, plodput); ! 585: else ! 586: plodput('\n'); ! 587: } ! 588: if (plodcnt < 0) ! 589: goto out; ! 590: if (NONL || pfast == 0) ! 591: outcol = 0; ! 592: } ! 593: if (BT) ! 594: k = strlen(BT); /* should probably be cost(BT) and moved out */ ! 595: /* Move left, if necessary, to desired column */ ! 596: while (outcol > destcol) { ! 597: if (plodcnt < 0) ! 598: goto out; ! 599: if (BT && !insmode && outcol - destcol > 4+k) { ! 600: tputs(BT, 0, plodput); ! 601: outcol--; ! 602: outcol -= outcol % value(HARDTABS); /* outcol &= ~7; */ ! 603: continue; ! 604: } ! 605: j = outcol - destcol; ! 606: if (j > costLP && LEFT_PARM) { ! 607: tputs(tgoto(LEFT_PARM, 0, j), j, plodput); ! 608: outcol -= j; ! 609: } ! 610: else { ! 611: outcol--; ! 612: if (BC) ! 613: tputs(BC, 0, plodput); ! 614: else ! 615: plodput('\b'); ! 616: } ! 617: } ! 618: /* Move up, if necessary, to desired row */ ! 619: while (outline > destline) { ! 620: j = outline - destline; ! 621: if (UP_PARM && j > 1) { ! 622: /* Win big on Tek 4025 */ ! 623: tputs(tgoto(UP_PARM, 0, j), j, plodput); ! 624: outline -= j; ! 625: } ! 626: else { ! 627: outline--; ! 628: tputs(UP, 0, plodput); ! 629: } ! 630: if (plodcnt < 0) ! 631: goto out; ! 632: } ! 633: /* ! 634: * Now move to the right, if necessary. We first tab to ! 635: * as close as we can get. ! 636: */ ! 637: if (GT && !insmode && destcol - outcol > 1) { ! 638: /* tab to right as far as possible without passing col */ ! 639: for (;;) { ! 640: i = tabcol(outcol, value(HARDTABS)); ! 641: if (i > destcol) ! 642: break; ! 643: if (TA) ! 644: tputs(TA, 0, plodput); ! 645: else ! 646: plodput('\t'); ! 647: outcol = i; ! 648: } ! 649: /* consider another tab and then some backspaces */ ! 650: if (destcol - outcol > 4 && i < COLUMNS && (BC || BS)) { ! 651: if (TA) ! 652: tputs(TA, 0, plodput); ! 653: else ! 654: plodput('\t'); ! 655: outcol = i; ! 656: /* ! 657: * Back up. Don't worry about LEFT_PARM because ! 658: * it's never more than 4 spaces anyway. ! 659: */ ! 660: while (outcol > destcol) { ! 661: outcol--; ! 662: if (BC) ! 663: tputs(BC, 0, plodput); ! 664: else ! 665: plodput('\b'); ! 666: } ! 667: } ! 668: } ! 669: /* ! 670: * We've tabbed as much as possible. If we still need to go ! 671: * further (not exact or can't tab) space over. This is a ! 672: * very common case when moving to the right with space. ! 673: */ ! 674: while (outcol < destcol) { ! 675: j = destcol - outcol; ! 676: if (j > costRP && RIGHT_PARM) { ! 677: /* ! 678: * This probably happens rarely, if at all. ! 679: * It seems mainly useful for ANSI terminals ! 680: * with no hardware tabs, and I don't know ! 681: * of any such terminal at the moment. ! 682: */ ! 683: tputs(tgoto(RIGHT_PARM, 0, j), j, plodput); ! 684: outcol += j; ! 685: } ! 686: else { ! 687: /* ! 688: * move one char to the right. We don't use ND space ! 689: * because it's better to just print the char we are ! 690: * moving over. There are various exceptions, however. ! 691: * If !inopen, vtube contains garbage. If the char is ! 692: * a null or a tab we want to print a space. Other ! 693: * random chars we use space for instead, too. ! 694: */ ! 695: if (!inopen || vtube[outline]==NULL || ! 696: (i=vtube[outline][outcol]) < ' ') ! 697: i = ' '; ! 698: if(i & QUOTE) /* mjm: no sign extension on 3B */ ! 699: i = ' '; ! 700: if (insmode && ND) ! 701: tputs(ND, 0, plodput); ! 702: else ! 703: plodput(i); ! 704: outcol++; ! 705: } ! 706: if (plodcnt < 0) ! 707: goto out; ! 708: } ! 709: out: ! 710: if (plodflg) { ! 711: outcol = soutcol; ! 712: outline = soutline; ! 713: } ! 714: return(plodcnt); ! 715: } ! 716: ! 717: /* ! 718: * An input line arrived. ! 719: * Calculate new (approximate) screen line position. ! 720: * Approximate because kill character echoes newline with ! 721: * no feedback and also because of long input lines. ! 722: */ ! 723: noteinp() ! 724: { ! 725: ! 726: outline++; ! 727: if (outline > LINES - 1) ! 728: outline = LINES - 1; ! 729: destline = outline; ! 730: destcol = outcol = 0; ! 731: } ! 732: ! 733: /* ! 734: * Something weird just happened and we ! 735: * lost track of whats happening out there. ! 736: * Since we cant, in general, read where we are ! 737: * we just reset to some known state. ! 738: * On cursor addressible terminals setting to unknown ! 739: * will force a cursor address soon. ! 740: */ ! 741: termreset() ! 742: { ! 743: ! 744: endim(); ! 745: if (TI) /* otherwise it flushes anyway, and 'set tty=dumb' vomits */ ! 746: putpad(TI); /*adb change -- emit terminal initial sequence */ ! 747: destcol = 0; ! 748: destline = LINES - 1; ! 749: if (CA) { ! 750: outcol = UKCOL; ! 751: outline = UKCOL; ! 752: } else { ! 753: outcol = destcol; ! 754: outline = destline; ! 755: } ! 756: } ! 757: ! 758: /* ! 759: * Low level buffering, with the ability to drain ! 760: * buffered output without printing it. ! 761: */ ! 762: char *obp = obuf; ! 763: ! 764: draino() ! 765: { ! 766: ! 767: obp = obuf; ! 768: } ! 769: ! 770: flusho() ! 771: { ! 772: ! 773: if (obp != obuf) { ! 774: #ifndef vms ! 775: write(1, obuf, obp - obuf); ! 776: #else ! 777: vms_write(1, obuf, obp - obuf); ! 778: #endif ! 779: obp = obuf; ! 780: } ! 781: } ! 782: ! 783: putnl() ! 784: { ! 785: ! 786: ex_putchar('\n'); ! 787: } ! 788: ! 789: ex_putS(cp) ! 790: char *cp; ! 791: { ! 792: ! 793: if (cp == NULL) ! 794: return; ! 795: while (*cp) ! 796: putch(*cp++); ! 797: } ! 798: ! 799: ! 800: putch(c) ! 801: int c; ! 802: { ! 803: ! 804: #ifdef OLD3BTTY /* mjm */ ! 805: if(c == '\n') /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */ ! 806: putch('\r'); /* mjm: vi does "stty -icanon" => -onlcr !! */ ! 807: #endif ! 808: *obp++ = c & 0177; ! 809: if (obp >= &obuf[sizeof obuf]) ! 810: flusho(); ! 811: } ! 812: ! 813: /* ! 814: * Miscellaneous routines related to output. ! 815: */ ! 816: ! 817: /* ! 818: * Put with padding ! 819: */ ! 820: putpad(cp) ! 821: char *cp; ! 822: { ! 823: ! 824: flush(); ! 825: tputs(cp, 0, putch); ! 826: } ! 827: ! 828: /* ! 829: * Set output through normal command mode routine. ! 830: */ ! 831: setoutt() ! 832: { ! 833: ! 834: Outchar = termchar; ! 835: } ! 836: ! 837: /* ! 838: * Printf (temporarily) in list mode. ! 839: */ ! 840: /*VARARGS1*/ ! 841: lprintf(cp, dp) ! 842: char *cp, *dp; ! 843: { ! 844: register int (*P)(); ! 845: ! 846: P = setlist(1); ! 847: ex_printf(cp, dp); ! 848: Put_char = P; ! 849: } ! 850: ! 851: /* ! 852: * Newline + flush. ! 853: */ ! 854: putNFL() ! 855: { ! 856: ! 857: putnl(); ! 858: flush(); ! 859: } ! 860: ! 861: /* ! 862: * Try to start -nl mode. ! 863: */ ! 864: pstart() ! 865: { ! 866: ! 867: if (NONL) ! 868: return; ! 869: if (!value(OPTIMIZE)) ! 870: return; ! 871: if (ruptible == 0 || pfast) ! 872: return; ! 873: fgoto(); ! 874: flusho(); ! 875: pfast = 1; ! 876: normtty++; ! 877: #ifndef USG3TTY ! 878: tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD); ! 879: #else ! 880: tty = normf; ! 881: tty.c_oflag &= ~(ONLCR|TAB3); ! 882: tty.c_lflag &= ~ECHO; ! 883: #endif ! 884: ex_sTTY(1); ! 885: } ! 886: ! 887: /* ! 888: * Stop -nl mode. ! 889: */ ! 890: pstop() ! 891: { ! 892: ! 893: if (inopen) ! 894: return; ! 895: phadnl = 0; ! 896: linp = linb; ! 897: draino(); ! 898: normal(normf); ! 899: pfast &= ~1; ! 900: } ! 901: ! 902: /* ! 903: * Prep tty for open mode. ! 904: */ ! 905: ttymode ! 906: ostart() ! 907: { ! 908: ttymode f; ! 909: ! 910: if (!intty) ! 911: error("Open and visual must be used interactively"); ! 912: ex_gTTY(1); ! 913: normtty++; ! 914: #ifndef USG3TTY ! 915: f = tty.sg_flags; ! 916: tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | ! 917: # ifdef CBREAK ! 918: CBREAK; ! 919: # else ! 920: RAW; ! 921: # endif ! 922: # ifdef TIOCGETC ! 923: ttcharoff(); ! 924: # endif ! 925: #else ! 926: f = tty; ! 927: tty = normf; ! 928: tty.c_iflag &= ~ICRNL; ! 929: tty.c_lflag &= ~(ECHO|ICANON); ! 930: tty.c_oflag &= ~(TAB3|ONLCR); ! 931: tty.c_cc[VMIN] = 1; ! 932: tty.c_cc[VTIME] = 1; ! 933: ttcharoff(); ! 934: #endif ! 935: ex_sTTY(1); ! 936: tostart(); ! 937: pfast |= 2; ! 938: return (f); ! 939: } ! 940: ! 941: /* actions associated with putting the terminal in open mode */ ! 942: tostart() ! 943: { ! 944: putpad(VS); ! 945: putpad(KS); ! 946: if (!value(MESG)) { ! 947: if (ttynbuf[0] == 0) { ! 948: register char *tn; ! 949: if ((tn=ttyname(2)) == NULL && ! 950: (tn=ttyname(1)) == NULL && ! 951: (tn=ttyname(0)) == NULL) ! 952: ttynbuf[0] = 1; ! 953: else ! 954: strcpy(ttynbuf, tn); ! 955: } ! 956: if (ttynbuf[0] != 1) { ! 957: struct stat sbuf; ! 958: stat(ttynbuf, &sbuf); ! 959: ttymesg = sbuf.st_mode & 0777; ! 960: chmod(ttynbuf, ! 961: #ifdef UCBV7 ! 962: /* ! 963: * This applies to the UCB V7 Pdp-11 system with the ! 964: * -u write option only. ! 965: */ ! 966: 0611 /* 11 = urgent only allowed */ ! 967: #else ! 968: 0600 ! 969: #endif ! 970: ); ! 971: } ! 972: } ! 973: } ! 974: ! 975: /* ! 976: * Turn off start/stop chars if they aren't the default ^S/^Q. ! 977: * This is so idiots who make esc their start/stop don't lose. ! 978: * We always turn off quit since datamedias send ^\ for their ! 979: * right arrow key. ! 980: */ ! 981: #ifdef TIOCGETC ! 982: ttcharoff() ! 983: { ! 984: nttyc.t_quitc = '\377'; ! 985: if (nttyc.t_startc != CTRL('q')) ! 986: nttyc.t_startc = '\377'; ! 987: if (nttyc.t_stopc != CTRL('s')) ! 988: nttyc.t_stopc = '\377'; ! 989: # ifdef TIOCLGET ! 990: nlttyc.t_suspc = '\377'; /* ^Z */ ! 991: nlttyc.t_dsuspc = '\377'; /* ^Y */ ! 992: nlttyc.t_flushc = '\377'; /* ^O */ ! 993: nlttyc.t_lnextc = '\377'; /* ^V */ ! 994: # endif ! 995: } ! 996: #endif ! 997: ! 998: #ifdef USG3TTY ! 999: ttcharoff() ! 1000: { ! 1001: tty.c_cc[VQUIT] = '\377'; ! 1002: # ifdef VSTART ! 1003: /* ! 1004: * The following is sample code if USG ever lets people change ! 1005: * their start/stop chars. As long as they can't we can't get ! 1006: * into trouble so we just leave them alone. ! 1007: */ ! 1008: if (tty.c_cc[VSTART] != CTRL('q')) ! 1009: tty.c_cc[VSTART] = '\377'; ! 1010: if (tty.c_cc[VSTOP] != CTRL('s')) ! 1011: tty.c_cc[VSTOP] = '\377'; ! 1012: # endif ! 1013: } ! 1014: #endif ! 1015: ! 1016: /* ! 1017: * Stop open, restoring tty modes. ! 1018: */ ! 1019: ostop(f) ! 1020: ttymode f; ! 1021: { ! 1022: ! 1023: #ifndef USG3TTY ! 1024: pfast = (f & CRMOD) == 0; ! 1025: #else ! 1026: pfast = (f.c_oflag & ONLCR) == 0; ! 1027: #endif ! 1028: termreset(), fgoto(), flusho(); ! 1029: normal(f); ! 1030: tostop(); ! 1031: } ! 1032: ! 1033: /* Actions associated with putting the terminal in the right mode. */ ! 1034: tostop() ! 1035: { ! 1036: putpad(VE); ! 1037: putpad(KE); ! 1038: if (!value(MESG) && ttynbuf[0]>1) ! 1039: chmod(ttynbuf, ttymesg); ! 1040: } ! 1041: ! 1042: #ifndef CBREAK ! 1043: /* ! 1044: * Into cooked mode for interruptibility. ! 1045: */ ! 1046: vcook() ! 1047: { ! 1048: ! 1049: tty.sg_flags &= ~RAW; ! 1050: ex_sTTY(1); ! 1051: } ! 1052: ! 1053: /* ! 1054: * Back into raw mode. ! 1055: */ ! 1056: vraw() ! 1057: { ! 1058: ! 1059: tty.sg_flags |= RAW; ! 1060: ex_sTTY(1); ! 1061: } ! 1062: #endif ! 1063: ! 1064: /* ! 1065: * Restore flags to normal state f. ! 1066: */ ! 1067: normal(f) ! 1068: ttymode f; ! 1069: { ! 1070: ! 1071: if (normtty > 0) { ! 1072: ignore(setty(f)); ! 1073: normtty--; ! 1074: } ! 1075: } ! 1076: ! 1077: /* ! 1078: * Straight set of flags to state f. ! 1079: */ ! 1080: ttymode ! 1081: setty(f) ! 1082: ttymode f; ! 1083: { ! 1084: #ifndef USG3TTY ! 1085: register int ot = tty.sg_flags; ! 1086: #else ! 1087: ttymode ot; ! 1088: ot = tty; ! 1089: #endif ! 1090: ! 1091: #ifndef USG3TTY ! 1092: # ifdef TIOCGETC ! 1093: if (f == normf) { ! 1094: nttyc = ottyc; ! 1095: # ifdef TIOCLGET ! 1096: nlttyc = olttyc; ! 1097: # endif ! 1098: } else ! 1099: ttcharoff(); ! 1100: # endif ! 1101: tty.sg_flags = f; ! 1102: #else ! 1103: if (tty.c_lflag & ICANON) ! 1104: ttcharoff(); ! 1105: tty = f; ! 1106: #endif ! 1107: ex_sTTY(1); ! 1108: return (ot); ! 1109: } ! 1110: ! 1111: ex_gTTY(i) ! 1112: int i; ! 1113: { ! 1114: ! 1115: #ifndef USG3TTY ! 1116: ignore(gtty(i, &tty)); ! 1117: # ifdef TIOCGETC ! 1118: ioctl(i, TIOCGETC, (char *) &ottyc); ! 1119: nttyc = ottyc; ! 1120: # endif ! 1121: # ifdef TIOCGLTC ! 1122: ioctl(i, TIOCGLTC, (char *) &olttyc); ! 1123: nlttyc = olttyc; ! 1124: # endif ! 1125: #else ! 1126: ioctl(i, TCGETA, (char *) &tty); ! 1127: #endif ! 1128: } ! 1129: ! 1130: /* ! 1131: * ex_sTTY: set the tty modes on file descriptor i to be what's ! 1132: * currently in global "tty". (Also use nttyc if needed.) ! 1133: */ ! 1134: ex_sTTY(i) ! 1135: int i; ! 1136: { ! 1137: ! 1138: #ifndef USG3TTY ! 1139: # ifdef USG ! 1140: /* Bug in USG tty driver, put out a DEL as a patch. */ ! 1141: if (tty.sg_ospeed >= B1200) ! 1142: write(1, "\377", 1); ! 1143: # endif ! 1144: ! 1145: # ifdef TIOCSETN ! 1146: /* Don't flush typeahead if we don't have to */ ! 1147: ioctl(i, TIOCSETN, (char *) &tty); ! 1148: # else ! 1149: /* We have to. Too bad. */ ! 1150: stty(i, &tty); ! 1151: # endif ! 1152: ! 1153: # ifdef TIOCGETC ! 1154: /* Update the other random chars while we're at it. */ ! 1155: ioctl(i, TIOCSETC, (char *) &nttyc); ! 1156: # endif ! 1157: # ifdef TIOCSLTC ! 1158: ioctl(i, TIOCSLTC, (char *) &nlttyc); ! 1159: # endif ! 1160: ! 1161: #else ! 1162: /* USG 3 very simple: just set everything */ ! 1163: ioctl(i, TCSETAW, (char *) &tty); ! 1164: #endif ! 1165: } ! 1166: ! 1167: /* ! 1168: * Print newline, or blank if in open/visual ! 1169: */ ! 1170: noonl() ! 1171: { ! 1172: ! 1173: ex_putchar(Outchar != termchar ? ' ' : '\n'); ! 1174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.