|
|
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.9 (Berkeley) 6/7/85";
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 (*Putchar)() = 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 = Putchar;
43: Putchar = 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: 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: 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: putchar(*cp++);
164: if (!inopen)
165: 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 (Putchar == 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: putchar(c)
221: int c;
222: {
223:
224: (*Putchar)(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: write(1, obuf, obp - obuf);
775: obp = obuf;
776: }
777: }
778:
779: putnl()
780: {
781:
782: putchar('\n');
783: }
784:
785: putS(cp)
786: char *cp;
787: {
788:
789: if (cp == NULL)
790: return;
791: while (*cp)
792: putch(*cp++);
793: }
794:
795:
796: putch(c)
797: int c;
798: {
799:
800: #ifdef OLD3BTTY /* mjm */
801: if(c == '\n') /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */
802: putch('\r'); /* mjm: vi does "stty -icanon" => -onlcr !! */
803: #endif
804: *obp++ = c & 0177;
805: if (obp >= &obuf[sizeof obuf])
806: flusho();
807: }
808:
809: /*
810: * Miscellaneous routines related to output.
811: */
812:
813: /*
814: * Put with padding
815: */
816: putpad(cp)
817: char *cp;
818: {
819:
820: flush();
821: tputs(cp, 0, putch);
822: }
823:
824: /*
825: * Set output through normal command mode routine.
826: */
827: setoutt()
828: {
829:
830: Outchar = termchar;
831: }
832:
833: /*
834: * Printf (temporarily) in list mode.
835: */
836: /*VARARGS2*/
837: lprintf(cp, dp)
838: char *cp, *dp;
839: {
840: register int (*P)();
841:
842: P = setlist(1);
843: printf(cp, dp);
844: Putchar = P;
845: }
846:
847: /*
848: * Newline + flush.
849: */
850: putNFL()
851: {
852:
853: putnl();
854: flush();
855: }
856:
857: /*
858: * Try to start -nl mode.
859: */
860: pstart()
861: {
862:
863: if (NONL)
864: return;
865: if (!value(OPTIMIZE))
866: return;
867: if (ruptible == 0 || pfast)
868: return;
869: fgoto();
870: flusho();
871: pfast = 1;
872: normtty++;
873: #ifndef USG3TTY
874: tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
875: #else
876: tty = normf;
877: tty.c_oflag &= ~(ONLCR|TAB3);
878: tty.c_lflag &= ~ECHO;
879: #endif
880: sTTY(1);
881: }
882:
883: /*
884: * Stop -nl mode.
885: */
886: pstop()
887: {
888:
889: if (inopen)
890: return;
891: phadnl = 0;
892: linp = linb;
893: draino();
894: normal(normf);
895: pfast &= ~1;
896: }
897:
898: /*
899: * Prep tty for open mode.
900: */
901: ttymode
902: ostart()
903: {
904: ttymode f;
905:
906: if (!intty)
907: error("Open and visual must be used interactively");
908: gTTY(1);
909: normtty++;
910: #ifndef USG3TTY
911: f = tty.sg_flags;
912: tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
913: # ifdef CBREAK
914: CBREAK;
915: # else
916: RAW;
917: # endif
918: # ifdef TIOCGETC
919: ttcharoff();
920: # endif
921: #else
922: f = tty;
923: tty = normf;
924: tty.c_iflag &= ~ICRNL;
925: tty.c_lflag &= ~(ECHO|ICANON);
926: tty.c_oflag &= ~(TAB3|ONLCR);
927: tty.c_cc[VMIN] = 1;
928: tty.c_cc[VTIME] = 1;
929: ttcharoff();
930: #endif
931: sTTY(1);
932: tostart();
933: pfast |= 2;
934: return (f);
935: }
936:
937: /* actions associated with putting the terminal in open mode */
938: tostart()
939: {
940: putpad(VS);
941: putpad(KS);
942: if (!value(MESG)) {
943: if (ttynbuf[0] == 0) {
944: register char *tn;
945: if ((tn=ttyname(2)) == NULL &&
946: (tn=ttyname(1)) == NULL &&
947: (tn=ttyname(0)) == NULL)
948: ttynbuf[0] = 1;
949: else
950: strcpy(ttynbuf, tn);
951: }
952: if (ttynbuf[0] != 1) {
953: struct stat sbuf;
954: stat(ttynbuf, &sbuf);
955: ttymesg = sbuf.st_mode & 0777;
956: chmod(ttynbuf,
957: #ifdef UCBV7
958: /*
959: * This applies to the UCB V7 Pdp-11 system with the
960: * -u write option only.
961: */
962: 0611 /* 11 = urgent only allowed */
963: #else
964: 0600
965: #endif
966: );
967: }
968: }
969: }
970:
971: /*
972: * Turn off start/stop chars if they aren't the default ^S/^Q.
973: * This is so idiots who make esc their start/stop don't lose.
974: * We always turn off quit since datamedias send ^\ for their
975: * right arrow key.
976: */
977: #ifdef TIOCGETC
978: ttcharoff()
979: {
980: nttyc.t_quitc = '\377';
981: if (nttyc.t_startc != CTRL(q))
982: nttyc.t_startc = '\377';
983: if (nttyc.t_stopc != CTRL(s))
984: nttyc.t_stopc = '\377';
985: # ifdef TIOCLGET
986: nlttyc.t_suspc = '\377'; /* ^Z */
987: nlttyc.t_dsuspc = '\377'; /* ^Y */
988: nlttyc.t_flushc = '\377'; /* ^O */
989: nlttyc.t_lnextc = '\377'; /* ^V */
990: # endif
991: }
992: #endif
993:
994: #ifdef USG3TTY
995: ttcharoff()
996: {
997: tty.c_cc[VQUIT] = '\377';
998: # ifdef VSTART
999: /*
1000: * The following is sample code if USG ever lets people change
1001: * their start/stop chars. As long as they can't we can't get
1002: * into trouble so we just leave them alone.
1003: */
1004: if (tty.c_cc[VSTART] != CTRL(q))
1005: tty.c_cc[VSTART] = '\377';
1006: if (tty.c_cc[VSTOP] != CTRL(s))
1007: tty.c_cc[VSTOP] = '\377';
1008: # endif
1009: }
1010: #endif
1011:
1012: /*
1013: * Stop open, restoring tty modes.
1014: */
1015: ostop(f)
1016: ttymode f;
1017: {
1018:
1019: #ifndef USG3TTY
1020: pfast = (f & CRMOD) == 0;
1021: #else
1022: pfast = (f.c_oflag & ONLCR) == 0;
1023: #endif
1024: termreset(), fgoto(), flusho();
1025: normal(f);
1026: tostop();
1027: }
1028:
1029: /* Actions associated with putting the terminal in the right mode. */
1030: tostop()
1031: {
1032: putpad(VE);
1033: putpad(KE);
1034: if (!value(MESG) && ttynbuf[0]>1)
1035: chmod(ttynbuf, ttymesg);
1036: }
1037:
1038: #ifndef CBREAK
1039: /*
1040: * Into cooked mode for interruptibility.
1041: */
1042: vcook()
1043: {
1044:
1045: tty.sg_flags &= ~RAW;
1046: sTTY(1);
1047: }
1048:
1049: /*
1050: * Back into raw mode.
1051: */
1052: vraw()
1053: {
1054:
1055: tty.sg_flags |= RAW;
1056: sTTY(1);
1057: }
1058: #endif
1059:
1060: /*
1061: * Restore flags to normal state f.
1062: */
1063: normal(f)
1064: ttymode f;
1065: {
1066:
1067: if (normtty > 0) {
1068: setty(f);
1069: normtty--;
1070: }
1071: }
1072:
1073: /*
1074: * Straight set of flags to state f.
1075: */
1076: ttymode
1077: setty(f)
1078: ttymode f;
1079: {
1080: #ifndef USG3TTY
1081: register int ot = tty.sg_flags;
1082: #else
1083: ttymode ot;
1084: ot = tty;
1085: #endif
1086:
1087: #ifndef USG3TTY
1088: if (f == normf) {
1089: nttyc = ottyc;
1090: # ifdef TIOCLGET
1091: nlttyc = olttyc;
1092: # endif
1093: } else
1094: ttcharoff();
1095: tty.sg_flags = f;
1096: #else
1097: if (tty.c_lflag & ICANON)
1098: ttcharoff();
1099: tty = f;
1100: #endif
1101: sTTY(1);
1102: return (ot);
1103: }
1104:
1105: gTTY(i)
1106: int i;
1107: {
1108:
1109: #ifndef USG3TTY
1110: ignore(gtty(i, &tty));
1111: # ifdef TIOCGETC
1112: ioctl(i, TIOCGETC, &ottyc);
1113: nttyc = ottyc;
1114: # endif
1115: # ifdef TIOCGLTC
1116: ioctl(i, TIOCGLTC, &olttyc);
1117: nlttyc = olttyc;
1118: # endif
1119: #else
1120: ioctl(i, TCGETA, &tty);
1121: #endif
1122: }
1123:
1124: /*
1125: * sTTY: set the tty modes on file descriptor i to be what's
1126: * currently in global "tty". (Also use nttyc if needed.)
1127: */
1128: sTTY(i)
1129: int i;
1130: {
1131:
1132: #ifndef USG3TTY
1133: # ifdef USG
1134: /* Bug in USG tty driver, put out a DEL as a patch. */
1135: if (tty.sg_ospeed >= B1200)
1136: write(1, "\377", 1);
1137: # endif
1138:
1139: # ifdef TIOCSETN
1140: /* Don't flush typeahead if we don't have to */
1141: ioctl(i, TIOCSETN, &tty);
1142: # else
1143: /* We have to. Too bad. */
1144: stty(i, &tty);
1145: # endif
1146:
1147: # ifdef TIOCGETC
1148: /* Update the other random chars while we're at it. */
1149: ioctl(i, TIOCSETC, &nttyc);
1150: # endif
1151: # ifdef TIOCSLTC
1152: ioctl(i, TIOCSLTC, &nlttyc);
1153: # endif
1154:
1155: #else
1156: /* USG 3 very simple: just set everything */
1157: ioctl(i, TCSETAW, &tty);
1158: #endif
1159: }
1160:
1161: /*
1162: * Print newline, or blank if in open/visual
1163: */
1164: noonl()
1165: {
1166:
1167: putchar(Outchar != termchar ? ' ' : '\n');
1168: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.