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