|
|
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.