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