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