xref: /titanic_51/usr/src/cmd/troff/n5.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * University Copyright- Copyright (c) 1982, 1986, 1988
35  * The Regents of the University of California
36  * All Rights Reserved
37  *
38  * University Acknowledgment- Portions of this document are derived from
39  * software developed by the University of California, Berkeley, and its
40  * contributors.
41  */
42 
43 #ifdef 	EUC
44 #ifdef	NROFF
45 #include <stddef.h>
46 #include <stdlib.h>
47 #include <widec.h>
48 #endif	/* NROFF */
49 #endif	/* EUC */
50 #include <string.h>
51 #include "tdef.h"
52 #include "ext.h"
53 
54 /*
55  * troff5.c
56  *
57  * misc processing requests
58  */
59 
60 int	iflist[NIF];
61 int	ifx;
62 
63 casead()
64 {
65 	register i;
66 
67 	ad = 1;
68 	/*leave admod alone*/
69 	if (skip())
70 		return;
71 	switch (i = cbits(getch())) {
72 	case 'r':	/*right adj, left ragged*/
73 		admod = 2;
74 		break;
75 	case 'l':	/*left adj, right ragged*/
76 		admod = ad = 0;	/*same as casena*/
77 		break;
78 	case 'c':	/*centered adj*/
79 		admod = 1;
80 		break;
81 	case 'b':
82 	case 'n':
83 		admod = 0;
84 		break;
85 	case '0':
86 	case '2':
87 	case '4':
88 		ad = 0;
89 	case '1':
90 	case '3':
91 	case '5':
92 		admod = (i - '0') / 2;
93 	}
94 }
95 
96 
97 casena()
98 {
99 	ad = 0;
100 }
101 
102 
103 casefi()
104 {
105 	tbreak();
106 	fi++;
107 	pendnf = 0;
108 	lnsize = LNSIZE;
109 }
110 
111 
112 casenf()
113 {
114 	tbreak();
115 	fi = 0;
116 }
117 
118 
119 casers()
120 {
121 	dip->nls = 0;
122 }
123 
124 
125 casens()
126 {
127 	dip->nls++;
128 }
129 
130 
131 chget(c)
132 int	c;
133 {
134 	tchar i;
135 
136 	if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') {
137 		ch = i;
138 		return(c);
139 	} else
140 		return(i & BYTEMASK);
141 }
142 
143 
144 casecc()
145 {
146 	cc = chget('.');
147 }
148 
149 
150 casec2()
151 {
152 	c2 = chget('\'');
153 }
154 
155 
156 casehc()
157 {
158 	ohc = chget(OHC);
159 }
160 
161 
162 casetc()
163 {
164 	tabc = chget(0);
165 }
166 
167 
168 caselc()
169 {
170 	dotc = chget(0);
171 }
172 
173 
174 casehy()
175 {
176 	register i;
177 
178 	hyf = 1;
179 	if (skip())
180 		return;
181 	noscale++;
182 	i = atoi();
183 	noscale = 0;
184 	if (nonumb)
185 		return;
186 	hyf = max(i, 0);
187 }
188 
189 
190 casenh()
191 {
192 	hyf = 0;
193 }
194 
195 
196 max(aa, bb)
197 int	aa, bb;
198 {
199 	if (aa > bb)
200 		return(aa);
201 	else
202 		return(bb);
203 }
204 
205 
206 casece()
207 {
208 	register i;
209 
210 	noscale++;
211 	skip();
212 	i = max(atoi(), 0);
213 	if (nonumb)
214 		i = 1;
215 	tbreak();
216 	ce = i;
217 	noscale = 0;
218 }
219 
220 
221 casein()
222 {
223 	register i;
224 
225 	if (skip())
226 		i = in1;
227 	else
228 		i = max(hnumb(&in), 0);
229 	tbreak();
230 	in1 = in;
231 	in = i;
232 	if (!nc) {
233 		un = in;
234 		setnel();
235 	}
236 }
237 
238 
239 casell()
240 {
241 	register i;
242 
243 	if (skip())
244 		i = ll1;
245 	else
246 		i = max(hnumb(&ll), INCH / 10);
247 	ll1 = ll;
248 	ll = i;
249 	setnel();
250 }
251 
252 
253 caselt()
254 {
255 	register i;
256 
257 	if (skip())
258 		i = lt1;
259 	else
260 		i = max(hnumb(&lt), 0);
261 	lt1 = lt;
262 	lt = i;
263 }
264 
265 
266 caseti()
267 {
268 	register i;
269 
270 	if (skip())
271 		return;
272 	i = max(hnumb(&in), 0);
273 	tbreak();
274 	un1 = i;
275 	setnel();
276 }
277 
278 
279 casels()
280 {
281 	register i;
282 
283 	noscale++;
284 	if (skip())
285 		i = ls1;
286 	else
287 		i = max(inumb(&ls), 1);
288 	ls1 = ls;
289 	ls = i;
290 	noscale = 0;
291 }
292 
293 
294 casepo()
295 {
296 	register i;
297 
298 	if (skip())
299 		i = po1;
300 	else
301 		i = max(hnumb(&po), 0);
302 	po1 = po;
303 	po = i;
304 #ifndef NROFF
305 	if (!ascii)
306 		esc += po - po1;
307 #endif
308 }
309 
310 
311 casepl()
312 {
313 	register i;
314 
315 	skip();
316 	if ((i = vnumb(&pl)) == 0)
317 		pl = 11 * INCH; /*11in*/
318 	else
319 		pl = i;
320 	if (numtab[NL].val > pl)
321 		numtab[NL].val = pl;
322 }
323 
324 
325 casewh()
326 {
327 	register i, j, k;
328 
329 	lgf++;
330 	skip();
331 	i = vnumb((int *)0);
332 	if (nonumb)
333 		return;
334 	skip();
335 	j = getrq();
336 	if ((k = findn(i)) != NTRAP) {
337 		mlist[k] = j;
338 		return;
339 	}
340 	for (k = 0; k < NTRAP; k++)
341 		if (mlist[k] == 0)
342 			break;
343 	if (k == NTRAP) {
344 		flusho();
345 		errprint(gettext("cannot plant trap."));
346 		return;
347 	}
348 	mlist[k] = j;
349 	nlist[k] = i;
350 }
351 
352 
353 casech()
354 {
355 	register i, j, k;
356 
357 	lgf++;
358 	skip();
359 	if (!(j = getrq()))
360 		return;
361 	else
362 		for (k = 0; k < NTRAP; k++)
363 			if (mlist[k] == j)
364 				break;
365 	if (k == NTRAP)
366 		return;
367 	skip();
368 	i = vnumb((int *)0);
369 	if (nonumb)
370 		mlist[k] = 0;
371 	nlist[k] = i;
372 }
373 
374 
375 findn(i)
376 int	i;
377 {
378 	register k;
379 
380 	for (k = 0; k < NTRAP; k++)
381 		if ((nlist[k] == i) && (mlist[k] != 0))
382 			break;
383 	return(k);
384 }
385 
386 
387 casepn()
388 {
389 	register i;
390 
391 	skip();
392 	noscale++;
393 	i = max(inumb(&numtab[PN].val), 0);
394 	noscale = 0;
395 	if (!nonumb) {
396 		npn = i;
397 		npnflg++;
398 	}
399 }
400 
401 
402 casebp()
403 {
404 	register i;
405 	register struct s *savframe;
406 
407 	if (dip != d)
408 		return;
409 	savframe = frame;
410 	skip();
411 	if ((i = inumb(&numtab[PN].val)) < 0)
412 		i = 0;
413 	tbreak();
414 	if (!nonumb) {
415 		npn = i;
416 		npnflg++;
417 	} else if (dip->nls)
418 		return;
419 	eject(savframe);
420 }
421 
422 
423 casetm(ab)
424 	int ab;
425 {
426 	register i;
427 	char	tmbuf[NTM];
428 
429 	lgf++;
430 	copyf++;
431 	if (skip() && ab)
432 		errprint(gettext("User Abort"));
433 	for (i = 0; i < NTM - 2; )
434 		if ((tmbuf[i++] = getch()) == '\n')
435 			break;
436 	if (i == NTM - 2)
437 		tmbuf[i++] = '\n';
438 	tmbuf[i] = 0;
439 	if (ab)	/* truncate output */
440 		obufp = obuf;	/* should be a function in n2.c */
441 	flusho();
442 	fdprintf(stderr, "%s", tmbuf);
443 	copyf--;
444 	lgf--;
445 }
446 
447 
448 casesp(a)
449 int	a;
450 {
451 	register i, j, savlss;
452 
453 	tbreak();
454 	if (dip->nls || trap)
455 		return;
456 	i = findt1();
457 	if (!a) {
458 		skip();
459 		j = vnumb((int *)0);
460 		if (nonumb)
461 			j = lss;
462 	} else
463 		j = a;
464 	if (j == 0)
465 		return;
466 	if (i < j)
467 		j = i;
468 	savlss = lss;
469 	if (dip != d)
470 		i = dip->dnl;
471 	else
472 		i = numtab[NL].val;
473 	if ((i + j) < 0)
474 		j = -i;
475 	lss = j;
476 	newline(0);
477 	lss = savlss;
478 }
479 
480 
481 casert()
482 {
483 	register a, *p;
484 
485 	skip();
486 	if (dip != d)
487 		p = &dip->dnl;
488 	else
489 		p = &numtab[NL].val;
490 	a = vnumb(p);
491 	if (nonumb)
492 		a = dip->mkline;
493 	if ((a < 0) || (a >= *p))
494 		return;
495 	nb++;
496 	casesp(a - *p);
497 }
498 
499 
500 caseem()
501 {
502 	lgf++;
503 	skip();
504 	em = getrq();
505 }
506 
507 
508 casefl()
509 {
510 	tbreak();
511 	flusho();
512 }
513 
514 
515 caseev()
516 {
517 	register nxev;
518 
519 	if (skip()) {
520 e0:
521 		if (evi == 0)
522 			return;
523 		nxev =  evlist[--evi];
524 		goto e1;
525 	}
526 	noscale++;
527 	nxev = atoi();
528 	noscale = 0;
529 	if (nonumb)
530 		goto e0;
531 	flushi();
532 	if ((nxev >= NEV) || (nxev < 0) || (evi >= EVLSZ)) {
533 		flusho();
534 		errprint(gettext("cannot do ev."));
535 		if (error)
536 			done2(040);
537 		else
538 			edone(040);
539 		return;
540 	}
541 	evlist[evi++] = ev;
542 e1:
543 	if (ev == nxev)
544 		return;
545 #ifdef INCORE
546 	{
547 		extern tchar corebuf[];
548 		*(struct env *)&corebuf[ev * sizeof(env)/sizeof(tchar)] = env;
549 		env = *(struct env *)&corebuf[nxev * sizeof(env)/sizeof(tchar)];
550 	}
551 #else
552 	lseek(ibf, ev * (long)sizeof(env), 0);
553 	write(ibf, (char *) & env, sizeof(env));
554 	lseek(ibf, nxev * (long)sizeof(env), 0);
555 	read(ibf, (char *) & env, sizeof(env));
556 #endif
557 	ev = nxev;
558 }
559 
560 caseel()
561 {
562 	if (--ifx < 0) {
563 		ifx = 0;
564 		iflist[0] = 0;
565 	}
566 	caseif(2);
567 }
568 
569 
570 caseie()
571 {
572 	if (ifx >= NIF) {
573 		errprint(gettext("if-else overflow."));
574 		ifx = 0;
575 		edone(040);
576 	}
577 	caseif(1);
578 	ifx++;
579 }
580 
581 
582 caseif(x)
583 int	x;
584 {
585 	extern int falsef;
586 	register notflag, true;
587 	tchar i;
588 
589 	if (x == 2) {
590 		notflag = 0;
591 		true = iflist[ifx];
592 		goto i1;
593 	}
594 	true = 0;
595 	skip();
596 	if ((cbits(i = getch())) == '!') {
597 		notflag = 1;
598 	} else {
599 		notflag = 0;
600 		ch = i;
601 	}
602 	i = atoi();
603 	if (!nonumb) {
604 		if (i > 0)
605 			true++;
606 		goto i1;
607 	}
608 	i = getch();
609 	switch (cbits(i)) {
610 	case 'e':
611 		if (!(numtab[PN].val & 01))
612 			true++;
613 		break;
614 	case 'o':
615 		if (numtab[PN].val & 01)
616 			true++;
617 		break;
618 #ifdef NROFF
619 	case 'n':
620 		true++;
621 	case 't':
622 #endif
623 #ifndef NROFF
624 	case 't':
625 		true++;
626 	case 'n':
627 #endif
628 	case ' ':
629 		break;
630 	default:
631 		true = cmpstr(i);
632 	}
633 i1:
634 	true ^= notflag;
635 	if (x == 1)
636 		iflist[ifx] = !true;
637 	if (true) {
638 i2:
639 		while ((cbits(i = getch())) == ' ')
640 			;
641 		if (cbits(i) == LEFT)
642 			goto i2;
643 		ch = i;
644 		nflush++;
645 	} else {
646 		copyf++;
647 		falsef++;
648 		eatblk(0);
649 		copyf--;
650 		falsef--;
651 	}
652 }
653 
654 eatblk(inblk)
655 int inblk;
656 {	register int cnt, i;
657 
658 	cnt = 0;
659 	do {
660 		if (ch)	{
661 			i = cbits(ch);
662 			ch = 0;
663 		} else
664 			i = cbits(getch0());
665 		if (i == ESC)
666 			cnt++;
667 		else {
668 			if (cnt == 1)
669 				switch (i) {
670 				case '{':  i = LEFT; break;
671 				case '}':  i = RIGHT; break;
672 				case '\n': i = 'x'; break;
673 				}
674 			cnt = 0;
675 		}
676 		if (i == LEFT) eatblk(1);
677 	} while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT)));
678 	if (i == '\n')
679 		nlflg++;
680 }
681 
682 
683 cmpstr(c)
684 tchar c;
685 {
686 	register j, delim;
687 	register tchar i;
688 	register val;
689 	int savapts, savapts1, savfont, savfont1, savpts, savpts1;
690 	tchar string[1280];
691 	register tchar *sp;
692 
693 	if (ismot(c))
694 		return(0);
695 	delim = cbits(c);
696 	savapts = apts;
697 	savapts1 = apts1;
698 	savfont = font;
699 	savfont1 = font1;
700 	savpts = pts;
701 	savpts1 = pts1;
702 	sp = string;
703 	while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1])
704 		*sp++ = i;
705 	if (sp >= string + 1280) {
706 		errprint(gettext("too-long string compare."));
707 		edone(0100);
708 	}
709 	if (nlflg) {
710 		val = sp==string;
711 		goto rtn;
712 	}
713 	*sp++ = 0;
714 	apts = savapts;
715 	apts1 = savapts1;
716 	font = savfont;
717 	font1 = savfont1;
718 	pts = savpts;
719 	pts1 = savpts1;
720 	mchbits();
721 	val = 1;
722 	sp = string;
723 	while ((j = cbits(i = getch())) != delim && j != '\n') {
724 		if (*sp != i) {
725 			eat(delim);
726 			val = 0;
727 			goto rtn;
728 		}
729 		sp++;
730 	}
731 	if (*sp)
732 		val = 0;
733 rtn:
734 	apts = savapts;
735 	apts1 = savapts1;
736 	font = savfont;
737 	font1 = savfont1;
738 	pts = savpts;
739 	pts1 = savpts1;
740 	mchbits();
741 	return(val);
742 }
743 
744 
745 caserd()
746 {
747 
748 	lgf++;
749 	skip();
750 	getname();
751 	if (!iflg) {
752 		if (quiet) {
753 #ifdef	NROFF
754 			echo_off();
755 			flusho();
756 #endif	NROFF
757 			fdprintf(stderr, "\007"); /*bell*/
758 		} else {
759 			if (nextf[0]) {
760 				fdprintf(stderr, "%s:", nextf);
761 			} else {
762 				fdprintf(stderr, "\007"); /*bell*/
763 			}
764 		}
765 	}
766 	collect();
767 	tty++;
768 	pushi(NBLIST*BLK, PAIR('r','d'));
769 }
770 
771 
772 rdtty()
773 {
774 	char	onechar;
775 #ifdef EUC
776 #ifdef NROFF
777 	int	i, n, col_index;
778 #endif /* NROFF */
779 #endif /* EUC */
780 
781 	onechar = 0;
782 	if (read(0, &onechar, 1) == 1) {
783 		if (onechar == '\n')
784 			tty++;
785 		else
786 			tty = 1;
787 #ifndef EUC
788 		if (tty != 3)
789 			return(onechar);
790 #else
791 #ifndef NROFF
792 		if (tty != 3)
793 			return(onechar);
794 #else
795 		if (tty != 3) {
796 			if (!multi_locale)
797 				return(onechar);
798 			i = onechar & 0377;
799 			*mbbuf1p++ = i;
800 			*mbbuf1p = 0;
801 			if ((n = mbtowc(&twc, mbbuf1, MB_CUR_MAX)) <= 0) {
802 				if (mbbuf1p >= mbbuf1 + MB_CUR_MAX) {
803 					i &= ~(MBMASK | CSMASK);
804 					twc = 0;
805 					mbbuf1p = mbbuf1;
806 					*mbbuf1p = 0;
807 				} else {
808 					i |= (MIDDLEOFMB);
809 				}
810 			} else {
811 				if (n > 1)
812 					i |= (LASTOFMB);
813 				else
814 					i |= (BYTE_CHR);
815 				if (isascii(twc)) {
816 					col_index = 0;
817 				} else {
818 					if ((col_index = wcwidth(twc)) < 0)
819 						col_index = 0;
820 				}
821 				setcsbits(i, col_index);
822 				twc = 0;
823 				mbbuf1p = mbbuf1;
824 			}
825 			return(i);
826 		}
827 #endif /* NROFF */
828 #endif /* EUC */
829 	}
830 	popi();
831 	tty = 0;
832 #ifdef	NROFF
833 	if (quiet)
834 		echo_on();
835 #endif	NROFF
836 	return(0);
837 }
838 
839 
840 caseec()
841 {
842 	eschar = chget('\\');
843 }
844 
845 
846 caseeo()
847 {
848 	eschar = 0;
849 }
850 
851 
852 caseta()
853 {
854 	register i;
855 
856 	tabtab[0] = nonumb = 0;
857 	for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) {
858 		if (skip())
859 			break;
860 		tabtab[i] = max(hnumb(&tabtab[max(i-1,0)]), 0) & TABMASK;
861 		if (!nonumb)
862 			switch (cbits(ch)) {
863 			case 'C':
864 				tabtab[i] |= CTAB;
865 				break;
866 			case 'R':
867 				tabtab[i] |= RTAB;
868 				break;
869 			default: /*includes L*/
870 				break;
871 			}
872 		nonumb = ch = 0;
873 	}
874 	tabtab[i] = 0;
875 }
876 
877 
878 casene()
879 {
880 	register i, j;
881 
882 	skip();
883 	i = vnumb((int *)0);
884 	if (nonumb)
885 		i = lss;
886 	if (i > (j = findt1())) {
887 		i = lss;
888 		lss = j;
889 		dip->nls = 0;
890 		newline(0);
891 		lss = i;
892 	}
893 }
894 
895 
896 casetr()
897 {
898 	register i, j;
899 	tchar k;
900 
901 	lgf++;
902 	skip();
903 	while ((i = cbits(k=getch())) != '\n') {
904 		if (ismot(k))
905 			return;
906 		if (ismot(k = getch()))
907 			return;
908 		if ((j = cbits(k)) == '\n')
909 			j = ' ';
910 		trtab[i] = j;
911 	}
912 }
913 
914 
915 casecu()
916 {
917 	cu++;
918 	caseul();
919 }
920 
921 
922 caseul()
923 {
924 	register i;
925 
926 	noscale++;
927 	if (skip())
928 		i = 1;
929 	else
930 		i = atoi();
931 	if (ul && (i == 0)) {
932 		font = sfont;
933 		ul = cu = 0;
934 	}
935 	if (i) {
936 		if (!ul) {
937 			sfont = font;
938 			font = ulfont;
939 		}
940 		ul = i;
941 	}
942 	noscale = 0;
943 	mchbits();
944 }
945 
946 
947 caseuf()
948 {
949 	register i, j;
950 
951 	if (skip() || !(i = getrq()) || i == 'S' ||  (j = findft(i))  == -1)
952 		ulfont = ULFONT; /*default underline position*/
953 	else
954 		ulfont = j;
955 #ifdef NROFF
956 	if (ulfont == FT)
957 		ulfont = ULFONT;
958 #endif
959 }
960 
961 
962 caseit()
963 {
964 	register i;
965 
966 	lgf++;
967 	it = itmac = 0;
968 	noscale++;
969 	skip();
970 	i = atoi();
971 	skip();
972 	if (!nonumb && (itmac = getrq()))
973 		it = i;
974 	noscale = 0;
975 }
976 
977 
978 casemc()
979 {
980 	register i;
981 
982 	if (icf > 1)
983 		ic = 0;
984 	icf = 0;
985 	if (skip())
986 		return;
987 	ic = getch();
988 	icf = 1;
989 	skip();
990 	i = max(hnumb((int *)0), 0);
991 	if (!nonumb)
992 		ics = i;
993 }
994 
995 
996 casemk()
997 {
998 	register i, j;
999 
1000 	if (dip != d)
1001 		j = dip->dnl;
1002 	else
1003 		j = numtab[NL].val;
1004 	if (skip()) {
1005 		dip->mkline = j;
1006 		return;
1007 	}
1008 	if ((i = getrq()) == 0)
1009 		return;
1010 	numtab[findr(i)].val = j;
1011 }
1012 
1013 
1014 casesv()
1015 {
1016 	register i;
1017 
1018 	skip();
1019 	if ((i = vnumb((int *)0)) < 0)
1020 		return;
1021 	if (nonumb)
1022 		i = 1;
1023 	sv += i;
1024 	caseos();
1025 }
1026 
1027 
1028 caseos()
1029 {
1030 	register savlss;
1031 
1032 	if (sv <= findt1()) {
1033 		savlss = lss;
1034 		lss = sv;
1035 		newline(0);
1036 		lss = savlss;
1037 		sv = 0;
1038 	}
1039 }
1040 
1041 
1042 casenm()
1043 {
1044 	register i;
1045 
1046 	lnmod = nn = 0;
1047 	if (skip())
1048 		return;
1049 	lnmod++;
1050 	noscale++;
1051 	i = inumb(&numtab[LN].val);
1052 	if (!nonumb)
1053 		numtab[LN].val = max(i, 0);
1054 	getnm(&ndf, 1);
1055 	getnm(&nms, 0);
1056 	getnm(&ni, 0);
1057 	noscale = 0;
1058 	nmbits = chbits;
1059 }
1060 
1061 
1062 getnm(p, min)
1063 int	*p, min;
1064 {
1065 	register i;
1066 
1067 	eat(' ');
1068 	if (skip())
1069 		return;
1070 	i = atoi();
1071 	if (nonumb)
1072 		return;
1073 	*p = max(i, min);
1074 }
1075 
1076 
1077 casenn()
1078 {
1079 	noscale++;
1080 	skip();
1081 	nn = max(atoi(), 1);
1082 	noscale = 0;
1083 }
1084 
1085 
1086 caseab()
1087 {
1088 	casetm(1);
1089 	done3(0);
1090 }
1091 
1092 
1093 #ifdef	NROFF
1094 /*
1095  * The following routines are concerned with setting terminal options.
1096  *	The manner of doing this differs between research/Berkeley systems
1097  *	and UNIX System V systems (i.e. DOCUMENTER'S WORKBENCH)
1098  *	The distinction is controlled by the #define'd variable USG,
1099  *	which must be set by System V users.
1100  */
1101 
1102 
1103 #ifdef	USG
1104 #include <termio.h>
1105 #define	ECHO_USG (ECHO | ECHOE | ECHOK | ECHONL)
1106 struct termio	ttys;
1107 #else
1108 #include <sgtty.h>
1109 struct	sgttyb	ttys[2];
1110 #endif	USG
1111 
1112 int	ttysave[2] = {-1, -1};
1113 
1114 save_tty()			/*save any tty settings that may be changed*/
1115 {
1116 
1117 #ifdef	USG
1118 	if (ioctl(0, TCGETA, &ttys) >= 0)
1119 		ttysave[0] = ttys.c_lflag;
1120 #else
1121 	if (gtty(0, &ttys[0]) >= 0)
1122 		ttysave[0] = ttys[0].sg_flags;
1123 	if (gtty(1, &ttys[1]) >= 0)
1124 		ttysave[1] = ttys[1].sg_flags;
1125 #endif	USG
1126 
1127 }
1128 
1129 
1130 restore_tty()			/*restore tty settings from beginning*/
1131 {
1132 
1133 	if (ttysave[0] != -1) {
1134 #ifdef	USG
1135 		ttys.c_lflag = ttysave[0];
1136 		ioctl(0, TCSETAW, &ttys);
1137 #else
1138 		ttys[0].sg_flags = ttysave[0];
1139 		stty(0, &ttys[0]);
1140 	}
1141 	if (ttysave[1] != -1) {
1142 		ttys[1].sg_flags = ttysave[1];
1143 		stty(1, &ttys[1]);
1144 #endif	USG
1145 	}
1146 }
1147 
1148 
1149 set_tty()			/*this replaces the use of bset and breset*/
1150 {
1151 
1152 #ifndef	USG			/*for research/BSD only, reset CRMOD*/
1153 	if (ttysave[1] == -1)
1154 		save_tty();
1155 	if (ttysave[1] != -1) {
1156 		ttys[1].sg_flags &= ~CRMOD;
1157 		stty(1, &ttys[1]);
1158 	}
1159 #endif	USG
1160 
1161 }
1162 
1163 
1164 echo_off()			/*turn off ECHO for .rd in "-q" mode*/
1165 {
1166 	if (ttysave[0] == -1)
1167 		return;
1168 
1169 #ifdef	USG
1170 	ttys.c_lflag &= ~ECHO_USG;
1171 	ioctl(0, TCSETAW, &ttys);
1172 #else
1173 	ttys[0].sg_flags &= ~ECHO;
1174 	stty(0, &ttys[0]);
1175 #endif	USG
1176 
1177 }
1178 
1179 
1180 echo_on()			/*restore ECHO after .rd in "-q" mode*/
1181 {
1182 	if (ttysave[0] == -1)
1183 		return;
1184 
1185 #ifdef	USG
1186 	ttys.c_lflag |= ECHO_USG;
1187 	ioctl(0, TCSETAW, &ttys);
1188 #else
1189 	ttys[0].sg_flags |= ECHO;
1190 	stty(0, &ttys[0]);
1191 #endif	USG
1192 
1193 }
1194 #endif	NROFF
1195