moved signal catching routines to ex_subr.c so they'll be in root ovly
[unix-history] / usr / src / usr.bin / ex / ex_put.c
CommitLineData
7c4625ef 1/* Copyright (c) 1980 Regents of the University of California */
16fb7022 2static char *sccsid = "@(#)ex_put.c 6.4 %G%";
e45f2c96
MH
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 */
23int (*Outchar)() = termchar;
24int (*Putchar)() = normchar;
25int (*Pline)() = normline;
26
27int (*
28setlist(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
39int (*
40setnumb(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 */
55listchar(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 */
89normchar(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 */
133numbline(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 */
146normline()
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 */
165slobber(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 */
d266c416
MH
198static char linb[66];
199static char *linp = linb;
e45f2c96
MH
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 */
207static bool phadnl;
208
209/*
210 * Indirect to current definition of putchar.
211 */
212putchar(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 */
225termchar(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
242flush()
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 */
254flush1()
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
315flush2()
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 */
329fgoto()
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)
d266c416
MH
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');
e45f2c96
MH
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) {
d266c416
MH
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');
e45f2c96
MH
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 */
416tab(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
431static int plodcnt, plodflg;
432
433plodput(c)
434{
435
436 if (plodflg)
437 plodcnt--;
438 else
439 putch(c);
440}
441
442plod(cnt)
443{
444 register int i, j, k;
445 register int soutcol, soutline;
446
447 plodcnt = plodflg = cnt;
448 soutcol = outcol;
449 soutline = outline;
d266c416
MH
450 /*
451 * Consider homing and moving down/right from there, vs moving
452 * directly with local motions to the right spot.
453 */
e45f2c96 454 if (HO) {
d266c416
MH
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 */
e45f2c96 460 if (GT)
d266c416 461 i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS));
e45f2c96
MH
462 else
463 i = destcol;
d266c416
MH
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);
e45f2c96
MH
471 else
472 j = destcol - outcol;
d266c416
MH
473 } else
474 /* leftward motion only works if we can backspace. */
e45f2c96 475 if (outcol - destcol <= i && (BS || BC))
d266c416 476 i = j = outcol - destcol; /* cheaper to backspace */
e45f2c96 477 else
d266c416
MH
478 j = i + 1; /* impossibly expensive */
479
480 /* k is the absolute value of vertical distance */
e45f2c96
MH
481 k = outline - destline;
482 if (k < 0)
483 k = -k;
484 j += k;
d266c416
MH
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 */
e45f2c96
MH
494 tputs(HO, 0, plodput);
495 outcol = outline = 0;
496 } else if (LL) {
d266c416
MH
497 /*
498 * Quickly consider homing down and moving from there.
499 * Assume cost of LL is 2.
500 */
e45f2c96 501 k = (LINES - 1) - destline;
d266c416 502 if (i + k + 2 < j && (k<=0 || UP)) {
e45f2c96
MH
503 tputs(LL, 0, plodput);
504 outcol = 0;
505 outline = LINES - 1;
506 }
507 }
d266c416
MH
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);
e45f2c96 515 if (GT)
d266c416
MH
516 i = destcol % value(HARDTABS)
517 + destcol / value(HARDTABS);
e45f2c96
MH
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) {
d266c416
MH
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');
e45f2c96 555 if (NC) {
d266c416
MH
556 if (xNL)
557 tputs(xNL, 0, plodput);
558 else
559 plodput('\n');
e45f2c96
MH
560 outline++;
561 }
562 outcol = 0;
563 }
564dontcr:
565 while (outline < destline) {
566 outline++;
d266c416
MH
567 if (xNL && pfast)
568 tputs(xNL, 0, plodput);
569 else
570 plodput('\n');
e45f2c96
MH
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 (;;) {
d266c416 603 i = tabcol(outcol, value(HARDTABS));
e45f2c96
MH
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) {
887e3e0d
MH
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 */
887e3e0d
MH
636 if (!inopen || vtube[outline]==NULL ||
637 (i=vtube[outline][outcol]) < ' ')
638 i = ' ';
639 if (insmode && ND)
e45f2c96
MH
640 tputs(ND, 0, plodput);
641 else
887e3e0d 642 plodput(i);
e45f2c96
MH
643 outcol++;
644 if (plodcnt < 0)
645 goto out;
646 }
647out:
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 */
661noteinp()
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 */
679termreset()
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 */
700char *obp = obuf;
701
702draino()
703{
704
705 obp = obuf;
706}
707
708flusho()
709{
710
711 if (obp != obuf) {
712 write(1, obuf, obp - obuf);
713 obp = obuf;
714 }
715}
716
717putnl()
718{
719
720 putchar('\n');
721}
722
723putS(cp)
724 char *cp;
725{
726
727 if (cp == NULL)
728 return;
729 while (*cp)
730 putch(*cp++);
731}
732
733
734putch(c)
735 int c;
736{
737
d266c416 738 *obp++ = c & 0177;
e45f2c96
MH
739 if (obp >= &obuf[sizeof obuf])
740 flusho();
741}
742
743/*
744 * Miscellaneous routines related to output.
745 */
746
e45f2c96
MH
747/*
748 * Put with padding
749 */
750putpad(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 */
761setoutt()
762{
763
764 Outchar = termchar;
765}
766
767/*
768 * Printf (temporarily) in list mode.
769 */
770/*VARARGS2*/
771lprintf(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 */
784putNFL()
785{
786
787 putnl();
788 flush();
789}
790
791/*
792 * Try to start -nl mode.
793 */
794pstart()
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++;
d266c416 807#ifndef USG3TTY
e45f2c96 808 tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
d266c416
MH
809#else
810 tty = normf;
811 tty.c_oflag &= ~(ONLCR|TAB3);
812 tty.c_lflag &= ~ECHO;
813#endif
e45f2c96
MH
814 sTTY(1);
815}
816
817/*
818 * Stop -nl mode.
819 */
820pstop()
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 */
d266c416 835ttymode
e45f2c96
MH
836ostart()
837{
d266c416 838 ttymode f;
e45f2c96
MH
839
840 if (!intty)
841 error("Open and visual must be used interactively");
842 gTTY(1);
843 normtty++;
d266c416 844#ifndef USG3TTY
e45f2c96 845 f = tty.sg_flags;
d266c416
MH
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
e45f2c96 855#else
d266c416
MH
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();
e45f2c96
MH
864#endif
865 sTTY(1);
d266c416 866 tostart();
e45f2c96
MH
867 pfast |= 2;
868 return (f);
869}
870
d266c416
MH
871/* actions associated with putting the terminal in open mode */
872tostart()
873{
874 putpad(VS);
875 putpad(KS);
9cc49269
MH
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 }
d266c416
MH
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
912ttcharoff()
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
929ttcharoff()
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
e45f2c96
MH
946/*
947 * Stop open, restoring tty modes.
948 */
949ostop(f)
d266c416 950 ttymode f;
e45f2c96
MH
951{
952
d266c416 953#ifndef USG3TTY
e45f2c96 954 pfast = (f & CRMOD) == 0;
d266c416
MH
955#else
956 pfast = (f.c_oflag & OCRNL) == 0;
957#endif
e45f2c96
MH
958 termreset(), fgoto(), flusho();
959 normal(f);
d266c416
MH
960 tostop();
961}
962
963/* Actions associated with putting the terminal in the right mode. */
964tostop()
965{
e45f2c96
MH
966 putpad(VE);
967 putpad(KE);
d266c416
MH
968 if (!value(MESG))
969 chmod(ttynbuf, ttymesg);
e45f2c96
MH
970}
971
972#ifndef CBREAK
973/*
974 * Into cooked mode for interruptibility.
975 */
976vcook()
977{
978
979 tty.sg_flags &= ~RAW;
980 sTTY(1);
981}
982
983/*
984 * Back into raw mode.
985 */
986vraw()
987{
988
989 tty.sg_flags |= RAW;
990 sTTY(1);
991}
992#endif
993
994/*
995 * Restore flags to normal state f.
996 */
997normal(f)
d266c416 998 ttymode f;
e45f2c96
MH
999{
1000
1001 if (normtty > 0) {
1002 setty(f);
1003 normtty--;
1004 }
1005}
1006
1007/*
1008 * Straight set of flags to state f.
1009 */
d266c416 1010ttymode
e45f2c96 1011setty(f)
d266c416 1012 ttymode f;
e45f2c96 1013{
d266c416 1014#ifndef USG3TTY
e45f2c96 1015 register int ot = tty.sg_flags;
d266c416
MH
1016#else
1017 ttymode ot;
1018 ot = tty;
1019#endif
e45f2c96 1020
d266c416
MH
1021#ifndef USG3TTY
1022 if (f == normf) {
e45f2c96 1023 nttyc = ottyc;
d266c416
MH
1024# ifdef TIOCLGET
1025 nlttyc = olttyc;
1026# endif
1027 } else
1028 ttcharoff();
e45f2c96 1029 tty.sg_flags = f;
d266c416
MH
1030#else
1031 if (tty.c_lflag & ICANON)
1032 ttcharoff();
1033 tty = f;
1034#endif
e45f2c96
MH
1035 sTTY(1);
1036 return (ot);
1037}
1038
1039gTTY(i)
1040 int i;
1041{
1042
d266c416 1043#ifndef USG3TTY
e45f2c96 1044 ignore(gtty(i, &tty));
d266c416 1045# ifdef TIOCGETC
e45f2c96
MH
1046 ioctl(i, TIOCGETC, &ottyc);
1047 nttyc = ottyc;
d266c416 1048# endif
bdbbb330 1049# ifdef TIOCGLTC
d266c416
MH
1050 ioctl(i, TIOCGLTC, &olttyc);
1051 nlttyc = olttyc;
1052# endif
1053#else
1054 ioctl(i, TCGETA, &tty);
e45f2c96
MH
1055#endif
1056}
1057
d266c416
MH
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 */
e45f2c96
MH
1062sTTY(i)
1063 int i;
1064{
1065
d266c416
MH
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 */
e45f2c96 1075 ioctl(i, TIOCSETN, &tty);
d266c416
MH
1076# else
1077 /* We have to. Too bad. */
e45f2c96 1078 stty(i, &tty);
d266c416
MH
1079# endif
1080
1081# ifdef TIOCGETC
1082 /* Update the other random chars while we're at it. */
e45f2c96 1083 ioctl(i, TIOCSETC, &nttyc);
d266c416 1084# endif
bdbbb330 1085# ifdef TIOCSLTC
d266c416
MH
1086 ioctl(i, TIOCSLTC, &nlttyc);
1087# endif
1088
1089#else
1090 /* USG 3 very simple: just set everything */
1091 ioctl(i, TCSETAW, &tty);
e45f2c96
MH
1092#endif
1093}
1094
1095/*
1096 * Print newline, or blank if in open/visual
1097 */
1098noonl()
1099{
1100
1101 putchar(Outchar != termchar ? ' ' : '\n');
1102}