=/^G show total bytes now; document may not always work
[unix-history] / usr / src / usr.bin / ex / ex_put.c
CommitLineData
19d73a0e
DF
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
65bacefd 8static char *sccsid = "@(#)ex_put.c 7.11 (Berkeley) %G%";
19d73a0e
DF
9#endif not lint
10
e45f2c96
MH
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 */
31int (*Outchar)() = termchar;
5a6c967e 32int (*Put_char)() = normchar;
e45f2c96
MH
33int (*Pline)() = normline;
34
35int (*
36setlist(t))()
37 bool t;
38{
39 register int (*P)();
40
41 listf = t;
5a6c967e
CH
42 P = Put_char;
43 Put_char = t ? listchar : normchar;
e45f2c96
MH
44 return (P);
45}
46
47int (*
48setnumb(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 */
63listchar(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 */
97normchar(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)
5a6c967e 121 ex_putchar('^'), c = ctlof(c);
e45f2c96
MH
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 */
141numbline(i)
142 int i;
143{
144
145 if (shudclob)
146 slobber(' ');
5a6c967e 147 ex_printf("%6d ", i);
e45f2c96
MH
148 normline();
149}
150
151/*
152 * Normal line output, no numbering.
153 */
154normline()
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;)
5a6c967e 163 ex_putchar(*cp++);
e45f2c96 164 if (!inopen)
5a6c967e 165 ex_putchar('\n' | QUOTE);
e45f2c96
MH
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 */
173slobber(c)
174 int c;
175{
176
177 shudclob = 0;
178 switch (c) {
179
180 case '\t':
5a6c967e 181 if (Put_char == listchar)
e45f2c96
MH
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 */
d266c416 206static char linb[66];
3c7b865a 207char *linp = linb;
e45f2c96
MH
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 */
215static bool phadnl;
216
217/*
218 * Indirect to current definition of putchar.
219 */
5a6c967e 220ex_putchar(c)
e45f2c96
MH
221 int c;
222{
223
5a6c967e 224 (*Put_char)(c);
e45f2c96
MH
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 */
233termchar(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
250flush()
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 */
262flush1()
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)
299f2784 311 putch('\r'), putch('\n');
e45f2c96
MH
312 }
313 c = *lp++;
314 if (c <= ' ')
315 break;
316 }
317 --lp;
318 continue;
319 }
320 linp = linb;
321}
322
323flush2()
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 */
337fgoto()
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)
d266c416
MH
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');
e45f2c96
MH
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) {
d266c416
MH
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');
e45f2c96
MH
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 */
424tab(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
439static int plodcnt, plodflg;
440
441plodput(c)
442{
443
444 if (plodflg)
445 plodcnt--;
446 else
447 putch(c);
448}
449
450plod(cnt)
451{
452 register int i, j, k;
453 register int soutcol, soutline;
454
455 plodcnt = plodflg = cnt;
456 soutcol = outcol;
457 soutline = outline;
d266c416
MH
458 /*
459 * Consider homing and moving down/right from there, vs moving
460 * directly with local motions to the right spot.
461 */
e45f2c96 462 if (HO) {
d266c416
MH
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 */
e45f2c96 468 if (GT)
d266c416 469 i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS));
e45f2c96
MH
470 else
471 i = destcol;
d266c416
MH
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);
e45f2c96
MH
479 else
480 j = destcol - outcol;
d266c416
MH
481 } else
482 /* leftward motion only works if we can backspace. */
e45f2c96 483 if (outcol - destcol <= i && (BS || BC))
d266c416 484 i = j = outcol - destcol; /* cheaper to backspace */
e45f2c96 485 else
d266c416
MH
486 j = i + 1; /* impossibly expensive */
487
488 /* k is the absolute value of vertical distance */
e45f2c96
MH
489 k = outline - destline;
490 if (k < 0)
491 k = -k;
492 j += k;
d266c416
MH
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 */
e45f2c96
MH
502 tputs(HO, 0, plodput);
503 outcol = outline = 0;
504 } else if (LL) {
d266c416
MH
505 /*
506 * Quickly consider homing down and moving from there.
507 * Assume cost of LL is 2.
508 */
e45f2c96 509 k = (LINES - 1) - destline;
d266c416 510 if (i + k + 2 < j && (k<=0 || UP)) {
e45f2c96
MH
511 tputs(LL, 0, plodput);
512 outcol = 0;
513 outline = LINES - 1;
514 }
515 }
d266c416
MH
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);
e45f2c96 523 if (GT)
d266c416
MH
524 i = destcol % value(HARDTABS)
525 + destcol / value(HARDTABS);
e45f2c96
MH
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) {
d266c416
MH
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');
e45f2c96 563 if (NC) {
d266c416
MH
564 if (xNL)
565 tputs(xNL, 0, plodput);
566 else
567 plodput('\n');
e45f2c96
MH
568 outline++;
569 }
570 outcol = 0;
571 }
572dontcr:
17687128 573 /* Move down, if necessary, until we are at the desired line */
e45f2c96 574 while (outline < destline) {
17687128 575 j = destline - outline;
d68a9fd3 576 if (j > costDP && DOWN_PARM) {
17687128
MH
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 }
e45f2c96
MH
588 if (plodcnt < 0)
589 goto out;
590 if (NONL || pfast == 0)
591 outcol = 0;
592 }
593 if (BT)
17687128
MH
594 k = strlen(BT); /* should probably be cost(BT) and moved out */
595 /* Move left, if necessary, to desired column */
e45f2c96
MH
596 while (outcol > destcol) {
597 if (plodcnt < 0)
598 goto out;
e45f2c96
MH
599 if (BT && !insmode && outcol - destcol > 4+k) {
600 tputs(BT, 0, plodput);
601 outcol--;
17687128 602 outcol -= outcol % value(HARDTABS); /* outcol &= ~7; */
e45f2c96
MH
603 continue;
604 }
17687128 605 j = outcol - destcol;
d68a9fd3 606 if (j > costLP && LEFT_PARM) {
17687128
MH
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 }
e45f2c96 617 }
17687128 618 /* Move up, if necessary, to desired row */
e45f2c96 619 while (outline > destline) {
17687128 620 j = outline - destline;
090a8083 621 if (UP_PARM && j > 1) {
17687128
MH
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 }
e45f2c96
MH
630 if (plodcnt < 0)
631 goto out;
632 }
17687128
MH
633 /*
634 * Now move to the right, if necessary. We first tab to
635 * as close as we can get.
636 */
e45f2c96 637 if (GT && !insmode && destcol - outcol > 1) {
17687128
MH
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;
e45f2c96
MH
643 if (TA)
644 tputs(TA, 0, plodput);
645 else
646 plodput('\t');
647 outcol = i;
648 }
17687128 649 /* consider another tab and then some backspaces */
e45f2c96
MH
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;
17687128
MH
656 /*
657 * Back up. Don't worry about LEFT_PARM because
658 * it's never more than 4 spaces anyway.
659 */
e45f2c96
MH
660 while (outcol > destcol) {
661 outcol--;
662 if (BC)
663 tputs(BC, 0, plodput);
664 else
665 plodput('\b');
666 }
667 }
668 }
17687128
MH
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 */
e45f2c96 674 while (outcol < destcol) {
17687128 675 j = destcol - outcol;
d68a9fd3 676 if (j > costRP && RIGHT_PARM) {
17687128
MH
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 }
e45f2c96
MH
706 if (plodcnt < 0)
707 goto out;
708 }
709out:
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 */
723noteinp()
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 */
741termreset()
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 */
762char *obp = obuf;
763
764draino()
765{
766
767 obp = obuf;
768}
769
770flusho()
771{
772
773 if (obp != obuf) {
5a6c967e 774#ifndef vms
e45f2c96 775 write(1, obuf, obp - obuf);
5a6c967e
CH
776#else
777 vms_write(1, obuf, obp - obuf);
778#endif
e45f2c96
MH
779 obp = obuf;
780 }
781}
782
783putnl()
784{
785
5a6c967e 786 ex_putchar('\n');
e45f2c96
MH
787}
788
5a6c967e 789ex_putS(cp)
e45f2c96
MH
790 char *cp;
791{
792
793 if (cp == NULL)
794 return;
795 while (*cp)
796 putch(*cp++);
797}
798
799
800putch(c)
801 int c;
802{
803
299f2784
MH
804#ifdef OLD3BTTY /* mjm */
805 if(c == '\n') /* mjm: Fake "\n\r" for '\n' til fix in 3B firmware */
806 putch('\r'); /* mjm: vi does "stty -icanon" => -onlcr !! */
807#endif
d266c416 808 *obp++ = c & 0177;
e45f2c96
MH
809 if (obp >= &obuf[sizeof obuf])
810 flusho();
811}
812
813/*
814 * Miscellaneous routines related to output.
815 */
816
e45f2c96
MH
817/*
818 * Put with padding
819 */
820putpad(cp)
821 char *cp;
822{
823
824 flush();
825 tputs(cp, 0, putch);
826}
827
828/*
829 * Set output through normal command mode routine.
830 */
831setoutt()
832{
833
834 Outchar = termchar;
835}
836
837/*
838 * Printf (temporarily) in list mode.
839 */
5a6c967e 840/*VARARGS1*/
e45f2c96
MH
841lprintf(cp, dp)
842 char *cp, *dp;
843{
844 register int (*P)();
845
846 P = setlist(1);
5a6c967e
CH
847 ex_printf(cp, dp);
848 Put_char = P;
e45f2c96
MH
849}
850
851/*
852 * Newline + flush.
853 */
854putNFL()
855{
856
857 putnl();
858 flush();
859}
860
861/*
862 * Try to start -nl mode.
863 */
864pstart()
865{
866
867 if (NONL)
868 return;
869 if (!value(OPTIMIZE))
870 return;
871 if (ruptible == 0 || pfast)
872 return;
873 fgoto();
874 flusho();
875 pfast = 1;
876 normtty++;
d266c416 877#ifndef USG3TTY
e45f2c96 878 tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD);
d266c416
MH
879#else
880 tty = normf;
881 tty.c_oflag &= ~(ONLCR|TAB3);
882 tty.c_lflag &= ~ECHO;
883#endif
5a6c967e 884 ex_sTTY(1);
e45f2c96
MH
885}
886
887/*
888 * Stop -nl mode.
889 */
890pstop()
891{
892
893 if (inopen)
894 return;
895 phadnl = 0;
896 linp = linb;
897 draino();
898 normal(normf);
899 pfast &= ~1;
900}
901
902/*
903 * Prep tty for open mode.
904 */
d266c416 905ttymode
e45f2c96
MH
906ostart()
907{
d266c416 908 ttymode f;
e45f2c96
MH
909
910 if (!intty)
911 error("Open and visual must be used interactively");
5a6c967e 912 ex_gTTY(1);
e45f2c96 913 normtty++;
d266c416 914#ifndef USG3TTY
e45f2c96 915 f = tty.sg_flags;
d266c416
MH
916 tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) |
917# ifdef CBREAK
918 CBREAK;
919# else
920 RAW;
921# endif
922# ifdef TIOCGETC
923 ttcharoff();
924# endif
e45f2c96 925#else
d266c416
MH
926 f = tty;
927 tty = normf;
928 tty.c_iflag &= ~ICRNL;
929 tty.c_lflag &= ~(ECHO|ICANON);
14382c50 930 tty.c_oflag &= ~(TAB3|ONLCR);
d266c416
MH
931 tty.c_cc[VMIN] = 1;
932 tty.c_cc[VTIME] = 1;
933 ttcharoff();
e45f2c96 934#endif
5a6c967e 935 ex_sTTY(1);
d266c416 936 tostart();
e45f2c96
MH
937 pfast |= 2;
938 return (f);
939}
940
d266c416
MH
941/* actions associated with putting the terminal in open mode */
942tostart()
943{
944 putpad(VS);
945 putpad(KS);
9cc49269
MH
946 if (!value(MESG)) {
947 if (ttynbuf[0] == 0) {
948 register char *tn;
949 if ((tn=ttyname(2)) == NULL &&
950 (tn=ttyname(1)) == NULL &&
951 (tn=ttyname(0)) == NULL)
952 ttynbuf[0] = 1;
953 else
954 strcpy(ttynbuf, tn);
955 }
956 if (ttynbuf[0] != 1) {
957 struct stat sbuf;
958 stat(ttynbuf, &sbuf);
959 ttymesg = sbuf.st_mode & 0777;
960 chmod(ttynbuf,
961#ifdef UCBV7
962 /*
963 * This applies to the UCB V7 Pdp-11 system with the
964 * -u write option only.
965 */
966 0611 /* 11 = urgent only allowed */
967#else
968 0600
969#endif
970 );
971 }
972 }
d266c416
MH
973}
974
975/*
976 * Turn off start/stop chars if they aren't the default ^S/^Q.
977 * This is so idiots who make esc their start/stop don't lose.
978 * We always turn off quit since datamedias send ^\ for their
979 * right arrow key.
980 */
981#ifdef TIOCGETC
982ttcharoff()
983{
984 nttyc.t_quitc = '\377';
65bacefd 985 if (nttyc.t_startc != CTRL('q'))
d266c416 986 nttyc.t_startc = '\377';
65bacefd 987 if (nttyc.t_stopc != CTRL('s'))
d266c416
MH
988 nttyc.t_stopc = '\377';
989# ifdef TIOCLGET
990 nlttyc.t_suspc = '\377'; /* ^Z */
991 nlttyc.t_dsuspc = '\377'; /* ^Y */
992 nlttyc.t_flushc = '\377'; /* ^O */
993 nlttyc.t_lnextc = '\377'; /* ^V */
994# endif
995}
996#endif
997
998#ifdef USG3TTY
999ttcharoff()
1000{
1001 tty.c_cc[VQUIT] = '\377';
1002# ifdef VSTART
1003 /*
1004 * The following is sample code if USG ever lets people change
1005 * their start/stop chars. As long as they can't we can't get
1006 * into trouble so we just leave them alone.
1007 */
65bacefd 1008 if (tty.c_cc[VSTART] != CTRL('q'))
d266c416 1009 tty.c_cc[VSTART] = '\377';
65bacefd 1010 if (tty.c_cc[VSTOP] != CTRL('s'))
d266c416
MH
1011 tty.c_cc[VSTOP] = '\377';
1012# endif
1013}
1014#endif
1015
e45f2c96
MH
1016/*
1017 * Stop open, restoring tty modes.
1018 */
1019ostop(f)
d266c416 1020 ttymode f;
e45f2c96
MH
1021{
1022
d266c416 1023#ifndef USG3TTY
e45f2c96 1024 pfast = (f & CRMOD) == 0;
d266c416 1025#else
3c7b865a 1026 pfast = (f.c_oflag & ONLCR) == 0;
d266c416 1027#endif
e45f2c96
MH
1028 termreset(), fgoto(), flusho();
1029 normal(f);
d266c416
MH
1030 tostop();
1031}
1032
1033/* Actions associated with putting the terminal in the right mode. */
1034tostop()
1035{
e45f2c96
MH
1036 putpad(VE);
1037 putpad(KE);
c2480b3f 1038 if (!value(MESG) && ttynbuf[0]>1)
d266c416 1039 chmod(ttynbuf, ttymesg);
e45f2c96
MH
1040}
1041
1042#ifndef CBREAK
1043/*
1044 * Into cooked mode for interruptibility.
1045 */
1046vcook()
1047{
1048
1049 tty.sg_flags &= ~RAW;
5a6c967e 1050 ex_sTTY(1);
e45f2c96
MH
1051}
1052
1053/*
1054 * Back into raw mode.
1055 */
1056vraw()
1057{
1058
1059 tty.sg_flags |= RAW;
5a6c967e 1060 ex_sTTY(1);
e45f2c96
MH
1061}
1062#endif
1063
1064/*
1065 * Restore flags to normal state f.
1066 */
1067normal(f)
d266c416 1068 ttymode f;
e45f2c96
MH
1069{
1070
1071 if (normtty > 0) {
5a6c967e 1072 ignore(setty(f));
e45f2c96
MH
1073 normtty--;
1074 }
1075}
1076
1077/*
1078 * Straight set of flags to state f.
1079 */
d266c416 1080ttymode
e45f2c96 1081setty(f)
d266c416 1082 ttymode f;
e45f2c96 1083{
d266c416 1084#ifndef USG3TTY
e45f2c96 1085 register int ot = tty.sg_flags;
d266c416
MH
1086#else
1087 ttymode ot;
1088 ot = tty;
1089#endif
e45f2c96 1090
d266c416 1091#ifndef USG3TTY
5a6c967e 1092# ifdef TIOCGETC
d266c416 1093 if (f == normf) {
e45f2c96 1094 nttyc = ottyc;
d266c416
MH
1095# ifdef TIOCLGET
1096 nlttyc = olttyc;
1097# endif
1098 } else
1099 ttcharoff();
5a6c967e 1100# endif
e45f2c96 1101 tty.sg_flags = f;
d266c416
MH
1102#else
1103 if (tty.c_lflag & ICANON)
1104 ttcharoff();
1105 tty = f;
1106#endif
5a6c967e 1107 ex_sTTY(1);
e45f2c96
MH
1108 return (ot);
1109}
1110
5a6c967e 1111ex_gTTY(i)
e45f2c96
MH
1112 int i;
1113{
1114
d266c416 1115#ifndef USG3TTY
e45f2c96 1116 ignore(gtty(i, &tty));
d266c416 1117# ifdef TIOCGETC
5a6c967e 1118 ioctl(i, TIOCGETC, (char *) &ottyc);
e45f2c96 1119 nttyc = ottyc;
d266c416 1120# endif
bdbbb330 1121# ifdef TIOCGLTC
5a6c967e 1122 ioctl(i, TIOCGLTC, (char *) &olttyc);
d266c416
MH
1123 nlttyc = olttyc;
1124# endif
1125#else
5a6c967e 1126 ioctl(i, TCGETA, (char *) &tty);
e45f2c96
MH
1127#endif
1128}
1129
d266c416 1130/*
5a6c967e 1131 * ex_sTTY: set the tty modes on file descriptor i to be what's
d266c416
MH
1132 * currently in global "tty". (Also use nttyc if needed.)
1133 */
5a6c967e 1134ex_sTTY(i)
e45f2c96
MH
1135 int i;
1136{
1137
d266c416
MH
1138#ifndef USG3TTY
1139# ifdef USG
1140 /* Bug in USG tty driver, put out a DEL as a patch. */
1141 if (tty.sg_ospeed >= B1200)
1142 write(1, "\377", 1);
1143# endif
1144
1145# ifdef TIOCSETN
1146 /* Don't flush typeahead if we don't have to */
5a6c967e 1147 ioctl(i, TIOCSETN, (char *) &tty);
d266c416
MH
1148# else
1149 /* We have to. Too bad. */
e45f2c96 1150 stty(i, &tty);
d266c416
MH
1151# endif
1152
1153# ifdef TIOCGETC
1154 /* Update the other random chars while we're at it. */
5a6c967e 1155 ioctl(i, TIOCSETC, (char *) &nttyc);
d266c416 1156# endif
bdbbb330 1157# ifdef TIOCSLTC
5a6c967e 1158 ioctl(i, TIOCSLTC, (char *) &nlttyc);
d266c416
MH
1159# endif
1160
1161#else
1162 /* USG 3 very simple: just set everything */
5a6c967e 1163 ioctl(i, TCSETAW, (char *) &tty);
e45f2c96
MH
1164#endif
1165}
1166
1167/*
1168 * Print newline, or blank if in open/visual
1169 */
1170noonl()
1171{
1172
5a6c967e 1173 ex_putchar(Outchar != termchar ? ' ' : '\n');
e45f2c96 1174}