xref: /titanic_52/usr/src/cmd/ul/ul.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
2*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
3*7c478bd9Sstevel@tonic-gate 
4*7c478bd9Sstevel@tonic-gate 
5*7c478bd9Sstevel@tonic-gate /*
6*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
7*7c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
8*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
9*7c478bd9Sstevel@tonic-gate  */
10*7c478bd9Sstevel@tonic-gate 
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, 2000 Sun Microsystems, Inc.
13*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
14*7c478bd9Sstevel@tonic-gate  */
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.1	*/
17*7c478bd9Sstevel@tonic-gate 
18*7c478bd9Sstevel@tonic-gate #include <stdio.h>
19*7c478bd9Sstevel@tonic-gate #include <locale.h>
20*7c478bd9Sstevel@tonic-gate #include <wctype.h>
21*7c478bd9Sstevel@tonic-gate #include <widec.h>
22*7c478bd9Sstevel@tonic-gate #include <euc.h>
23*7c478bd9Sstevel@tonic-gate #include <limits.h>
24*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #define	IESC	L'\033'
27*7c478bd9Sstevel@tonic-gate #define	SO	L'\016'
28*7c478bd9Sstevel@tonic-gate #define	SI	L'\017'
29*7c478bd9Sstevel@tonic-gate #define	HFWD	L'9'
30*7c478bd9Sstevel@tonic-gate #define	HREV	L'8'
31*7c478bd9Sstevel@tonic-gate #define	FREV	L'7'
32*7c478bd9Sstevel@tonic-gate #define	CDUMMY	-1
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #define	NORMAL	000
35*7c478bd9Sstevel@tonic-gate #define	ALTSET	001	/* Reverse */
36*7c478bd9Sstevel@tonic-gate #define	SUPERSC	002	/* Dim */
37*7c478bd9Sstevel@tonic-gate #define	SUBSC	004	/* Dim | Ul */
38*7c478bd9Sstevel@tonic-gate #define	UNDERL	010	/* Ul */
39*7c478bd9Sstevel@tonic-gate #define	BOLD	020	/* Bold */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #define	MEMFCT	16
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * MEMFCT is a number that is likely to be large enough as a factor for
44*7c478bd9Sstevel@tonic-gate  * allocating more memory and to be small enough so as not wasting memory
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate int	must_use_uc, must_overstrike;
48*7c478bd9Sstevel@tonic-gate char	*CURS_UP, *CURS_RIGHT, *CURS_LEFT,
49*7c478bd9Sstevel@tonic-gate 	*ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
50*7c478bd9Sstevel@tonic-gate 	*ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate struct	CHAR	{
53*7c478bd9Sstevel@tonic-gate 	char	c_mode;
54*7c478bd9Sstevel@tonic-gate 	wchar_t	c_char;
55*7c478bd9Sstevel@tonic-gate };
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate struct	CHAR	obuf[LINE_MAX];
58*7c478bd9Sstevel@tonic-gate int	col, maxcol;
59*7c478bd9Sstevel@tonic-gate int	mode;
60*7c478bd9Sstevel@tonic-gate int	halfpos;
61*7c478bd9Sstevel@tonic-gate int	upln;
62*7c478bd9Sstevel@tonic-gate int	iflag;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate eucwidth_t wp;
65*7c478bd9Sstevel@tonic-gate int scrw[4];
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate main(argc, argv)
68*7c478bd9Sstevel@tonic-gate 	int argc;
69*7c478bd9Sstevel@tonic-gate 	char **argv;
70*7c478bd9Sstevel@tonic-gate {
71*7c478bd9Sstevel@tonic-gate 	int c;
72*7c478bd9Sstevel@tonic-gate 	char *cp, *termtype;
73*7c478bd9Sstevel@tonic-gate 	FILE *f;
74*7c478bd9Sstevel@tonic-gate 	char termcap[1024];
75*7c478bd9Sstevel@tonic-gate 	char *getenv();
76*7c478bd9Sstevel@tonic-gate 	extern int optind;
77*7c478bd9Sstevel@tonic-gate 	extern char *optarg;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
80*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
81*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
82*7c478bd9Sstevel@tonic-gate #endif
83*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 	getwidth(&wp);
86*7c478bd9Sstevel@tonic-gate 	scrw[0] = 1;
87*7c478bd9Sstevel@tonic-gate 	scrw[1] = wp._scrw1;
88*7c478bd9Sstevel@tonic-gate 	scrw[2] = wp._scrw2;
89*7c478bd9Sstevel@tonic-gate 	scrw[3] = wp._scrw3;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 	termtype = getenv("TERM");
92*7c478bd9Sstevel@tonic-gate 	if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
93*7c478bd9Sstevel@tonic-gate 		termtype = "lpr";
94*7c478bd9Sstevel@tonic-gate 	while ((c=getopt(argc, argv, "it:T:")) != EOF)
95*7c478bd9Sstevel@tonic-gate 		switch (c) {
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 		case 't':
98*7c478bd9Sstevel@tonic-gate 		case 'T': /* for nroff compatibility */
99*7c478bd9Sstevel@tonic-gate 				termtype = optarg;
100*7c478bd9Sstevel@tonic-gate 			break;
101*7c478bd9Sstevel@tonic-gate 		case 'i':
102*7c478bd9Sstevel@tonic-gate 			iflag = 1;
103*7c478bd9Sstevel@tonic-gate 			break;
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		default:
106*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
107*7c478bd9Sstevel@tonic-gate 			gettext("\
108*7c478bd9Sstevel@tonic-gate Usage: %s [ -i ] [ -t terminal ] [ filename...]\n"),
109*7c478bd9Sstevel@tonic-gate 				argv[0]);
110*7c478bd9Sstevel@tonic-gate 			exit(1);
111*7c478bd9Sstevel@tonic-gate 		}
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	switch (tgetent(termcap, termtype)) {
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	case 1:
116*7c478bd9Sstevel@tonic-gate 		break;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	default:
119*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("trouble reading termcap"));
120*7c478bd9Sstevel@tonic-gate 		/* fall through to ... */
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 	case 0:
123*7c478bd9Sstevel@tonic-gate 		/* No such terminal type - assume dumb */
124*7c478bd9Sstevel@tonic-gate 		strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
125*7c478bd9Sstevel@tonic-gate 		break;
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	initcap();
128*7c478bd9Sstevel@tonic-gate 	if ((tgetflag("os") && ENTER_BOLD==NULL) ||
129*7c478bd9Sstevel@tonic-gate 		(tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
130*7c478bd9Sstevel@tonic-gate 			must_overstrike = 1;
131*7c478bd9Sstevel@tonic-gate 	initbuf();
132*7c478bd9Sstevel@tonic-gate 	if (optind == argc)
133*7c478bd9Sstevel@tonic-gate 		filter(stdin);
134*7c478bd9Sstevel@tonic-gate 	else for (; optind<argc; optind++) {
135*7c478bd9Sstevel@tonic-gate 		f = fopen(argv[optind], "r");
136*7c478bd9Sstevel@tonic-gate 		if (f == NULL) {
137*7c478bd9Sstevel@tonic-gate 			perror(argv[optind]);
138*7c478bd9Sstevel@tonic-gate 			exit(1);
139*7c478bd9Sstevel@tonic-gate 		} else
140*7c478bd9Sstevel@tonic-gate 			filter(f);
141*7c478bd9Sstevel@tonic-gate 	}
142*7c478bd9Sstevel@tonic-gate 	exit(0);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate filter(f)
146*7c478bd9Sstevel@tonic-gate FILE *f;
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	register wchar_t c;
149*7c478bd9Sstevel@tonic-gate 	register i;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	while ((c = getwc(f)) != EOF) {
152*7c478bd9Sstevel@tonic-gate 		if (maxcol >= LINE_MAX)
153*7c478bd9Sstevel@tonic-gate 		{
154*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
155*7c478bd9Sstevel@tonic-gate 	gettext("Input line longer than %d characters\n"), LINE_MAX);
156*7c478bd9Sstevel@tonic-gate 			exit(1);
157*7c478bd9Sstevel@tonic-gate 		}
158*7c478bd9Sstevel@tonic-gate 		switch (c) {
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 		case L'\b':
161*7c478bd9Sstevel@tonic-gate 			if (col > 0)
162*7c478bd9Sstevel@tonic-gate 				col--;
163*7c478bd9Sstevel@tonic-gate 			continue;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 		case L'\t':
166*7c478bd9Sstevel@tonic-gate 			col = (col+8) & ~07;
167*7c478bd9Sstevel@tonic-gate 			if (col > maxcol)
168*7c478bd9Sstevel@tonic-gate 				maxcol = col;
169*7c478bd9Sstevel@tonic-gate 			continue;
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		case L'\r':
172*7c478bd9Sstevel@tonic-gate 			col = 0;
173*7c478bd9Sstevel@tonic-gate 			continue;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 		case SO:
176*7c478bd9Sstevel@tonic-gate 			mode |= ALTSET;
177*7c478bd9Sstevel@tonic-gate 			continue;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 		case SI:
180*7c478bd9Sstevel@tonic-gate 			mode &= ~ALTSET;
181*7c478bd9Sstevel@tonic-gate 			continue;
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 		case IESC:
184*7c478bd9Sstevel@tonic-gate 			switch (c = getwc(f)) {
185*7c478bd9Sstevel@tonic-gate 			case HREV:
186*7c478bd9Sstevel@tonic-gate 				if (halfpos == 0) {
187*7c478bd9Sstevel@tonic-gate 					mode |= SUPERSC;
188*7c478bd9Sstevel@tonic-gate 					halfpos--;
189*7c478bd9Sstevel@tonic-gate 				} else if (halfpos > 0) {
190*7c478bd9Sstevel@tonic-gate 					mode &= ~SUBSC;
191*7c478bd9Sstevel@tonic-gate 					halfpos--;
192*7c478bd9Sstevel@tonic-gate 				} else {
193*7c478bd9Sstevel@tonic-gate 					halfpos = 0;
194*7c478bd9Sstevel@tonic-gate 					reverse();
195*7c478bd9Sstevel@tonic-gate 				}
196*7c478bd9Sstevel@tonic-gate 				continue;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 			case HFWD:
199*7c478bd9Sstevel@tonic-gate 				if (halfpos == 0) {
200*7c478bd9Sstevel@tonic-gate 					mode |= SUBSC;
201*7c478bd9Sstevel@tonic-gate 					halfpos++;
202*7c478bd9Sstevel@tonic-gate 				} else if (halfpos < 0) {
203*7c478bd9Sstevel@tonic-gate 					mode &= ~SUPERSC;
204*7c478bd9Sstevel@tonic-gate 					halfpos++;
205*7c478bd9Sstevel@tonic-gate 				} else {
206*7c478bd9Sstevel@tonic-gate 					halfpos = 0;
207*7c478bd9Sstevel@tonic-gate 					fwd();
208*7c478bd9Sstevel@tonic-gate 				}
209*7c478bd9Sstevel@tonic-gate 				continue;
210*7c478bd9Sstevel@tonic-gate 			case FREV:
211*7c478bd9Sstevel@tonic-gate 				reverse();
212*7c478bd9Sstevel@tonic-gate 				continue;
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 			default:
215*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
216*7c478bd9Sstevel@tonic-gate 			gettext("Unknown escape sequence in input: %o, %o\n"),
217*7c478bd9Sstevel@tonic-gate 					IESC, c);
218*7c478bd9Sstevel@tonic-gate 				exit(1);
219*7c478bd9Sstevel@tonic-gate 			}
220*7c478bd9Sstevel@tonic-gate 			continue;
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 		case L'_':
223*7c478bd9Sstevel@tonic-gate 			if (obuf[col].c_char)
224*7c478bd9Sstevel@tonic-gate 				obuf[col].c_mode |= UNDERL | mode;
225*7c478bd9Sstevel@tonic-gate 			else
226*7c478bd9Sstevel@tonic-gate 				obuf[col].c_char = '_';
227*7c478bd9Sstevel@tonic-gate 		case L' ':
228*7c478bd9Sstevel@tonic-gate 			col++;
229*7c478bd9Sstevel@tonic-gate 			if (col > maxcol)
230*7c478bd9Sstevel@tonic-gate 				maxcol = col;
231*7c478bd9Sstevel@tonic-gate 			continue;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 		case L'\n':
234*7c478bd9Sstevel@tonic-gate 			flushln();
235*7c478bd9Sstevel@tonic-gate 			continue;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		default:
238*7c478bd9Sstevel@tonic-gate 			if (c < L' ')	/* non printing */
239*7c478bd9Sstevel@tonic-gate 				continue;
240*7c478bd9Sstevel@tonic-gate 			if (obuf[col].c_char == L'\0') {
241*7c478bd9Sstevel@tonic-gate 				obuf[col].c_char = c;
242*7c478bd9Sstevel@tonic-gate 				obuf[col].c_mode = mode;
243*7c478bd9Sstevel@tonic-gate 				i = scrw[wcsetno(c)];
244*7c478bd9Sstevel@tonic-gate 				while (--i > 0)
245*7c478bd9Sstevel@tonic-gate 					obuf[++col].c_char = CDUMMY;
246*7c478bd9Sstevel@tonic-gate 			} else if (obuf[col].c_char == L'_') {
247*7c478bd9Sstevel@tonic-gate 				obuf[col].c_char = c;
248*7c478bd9Sstevel@tonic-gate 				obuf[col].c_mode |= UNDERL|mode;
249*7c478bd9Sstevel@tonic-gate 				i = scrw[wcsetno(c)];
250*7c478bd9Sstevel@tonic-gate 				while (--i > 0)
251*7c478bd9Sstevel@tonic-gate 					obuf[++col].c_char = CDUMMY;
252*7c478bd9Sstevel@tonic-gate 			} else if (obuf[col].c_char == c)
253*7c478bd9Sstevel@tonic-gate 				obuf[col].c_mode |= BOLD|mode;
254*7c478bd9Sstevel@tonic-gate 			else {
255*7c478bd9Sstevel@tonic-gate 				obuf[col].c_char = c;
256*7c478bd9Sstevel@tonic-gate 				obuf[col].c_mode = mode;
257*7c478bd9Sstevel@tonic-gate 			}
258*7c478bd9Sstevel@tonic-gate 			col++;
259*7c478bd9Sstevel@tonic-gate 			if (col > maxcol)
260*7c478bd9Sstevel@tonic-gate 				maxcol = col;
261*7c478bd9Sstevel@tonic-gate 			continue;
262*7c478bd9Sstevel@tonic-gate 		}
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 	if (maxcol)
265*7c478bd9Sstevel@tonic-gate 		flushln();
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate flushln()
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate 	register lastmode;
271*7c478bd9Sstevel@tonic-gate 	register i;
272*7c478bd9Sstevel@tonic-gate 	int hadmodes = 0;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	lastmode = NORMAL;
275*7c478bd9Sstevel@tonic-gate 	for (i=0; i<maxcol; i++) {
276*7c478bd9Sstevel@tonic-gate 		if (obuf[i].c_mode != lastmode) {
277*7c478bd9Sstevel@tonic-gate 			hadmodes++;
278*7c478bd9Sstevel@tonic-gate 			setmode(obuf[i].c_mode);
279*7c478bd9Sstevel@tonic-gate 			lastmode = obuf[i].c_mode;
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 		if (obuf[i].c_char == L'\0') {
282*7c478bd9Sstevel@tonic-gate 			if (upln) {
283*7c478bd9Sstevel@tonic-gate 				puts(CURS_RIGHT);
284*7c478bd9Sstevel@tonic-gate 			} else
285*7c478bd9Sstevel@tonic-gate 				outc(L' ');
286*7c478bd9Sstevel@tonic-gate 		} else
287*7c478bd9Sstevel@tonic-gate 			outc(obuf[i].c_char);
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 	if (lastmode != NORMAL) {
290*7c478bd9Sstevel@tonic-gate 		setmode(0);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 	if (must_overstrike && hadmodes)
293*7c478bd9Sstevel@tonic-gate 		overstrike();
294*7c478bd9Sstevel@tonic-gate 	putwchar(L'\n');
295*7c478bd9Sstevel@tonic-gate 	if (iflag && hadmodes)
296*7c478bd9Sstevel@tonic-gate 		iattr();
297*7c478bd9Sstevel@tonic-gate 	if (upln)
298*7c478bd9Sstevel@tonic-gate 		upln--;
299*7c478bd9Sstevel@tonic-gate 	initbuf();
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate /*
303*7c478bd9Sstevel@tonic-gate  * For terminals that can overstrike, overstrike underlines and bolds.
304*7c478bd9Sstevel@tonic-gate  * We don't do anything with halfline ups and downs, or Greek.
305*7c478bd9Sstevel@tonic-gate  */
306*7c478bd9Sstevel@tonic-gate overstrike()
307*7c478bd9Sstevel@tonic-gate {
308*7c478bd9Sstevel@tonic-gate 	register int i, n;
309*7c478bd9Sstevel@tonic-gate 	wchar_t *cp, *scp;
310*7c478bd9Sstevel@tonic-gate 	size_t  szbf = 256, tszbf;
311*7c478bd9Sstevel@tonic-gate 	int hadbold=0;
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf);
314*7c478bd9Sstevel@tonic-gate 	if (!scp) {
315*7c478bd9Sstevel@tonic-gate 	/* this kind of message need not to be gettext'ed */
316*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "malloc failed\n");
317*7c478bd9Sstevel@tonic-gate 		exit(1);
318*7c478bd9Sstevel@tonic-gate 	}
319*7c478bd9Sstevel@tonic-gate 	cp = scp;
320*7c478bd9Sstevel@tonic-gate 	tszbf = szbf;
321*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
322*7c478bd9Sstevel@tonic-gate 	/*
323*7c478bd9Sstevel@tonic-gate 	 * to allocate a memory after the chunk of the current scp
324*7c478bd9Sstevel@tonic-gate 	 * and to make sure the following realloc() allocates
325*7c478bd9Sstevel@tonic-gate 	 * memory from different chunks.
326*7c478bd9Sstevel@tonic-gate 	 */
327*7c478bd9Sstevel@tonic-gate 	(void) malloc(1024 * 1024);
328*7c478bd9Sstevel@tonic-gate #endif
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	/* Set up overstrike buffer */
331*7c478bd9Sstevel@tonic-gate 	for (i=0; i<maxcol; i++) {
332*7c478bd9Sstevel@tonic-gate 		n = scrw[wcsetno(obuf[i].c_char)];
333*7c478bd9Sstevel@tonic-gate 		if (tszbf <= n) {
334*7c478bd9Sstevel@tonic-gate 		/* may not enough buffer for this char */
335*7c478bd9Sstevel@tonic-gate 			size_t  pos;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 			/* obtain the offset of cp */
338*7c478bd9Sstevel@tonic-gate 			pos = cp - scp;
339*7c478bd9Sstevel@tonic-gate 			/* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
340*7c478bd9Sstevel@tonic-gate 			scp = (wchar_t *)realloc(scp,
341*7c478bd9Sstevel@tonic-gate 				sizeof (wchar_t) * (szbf + (n * MEMFCT)));
342*7c478bd9Sstevel@tonic-gate 			if (!scp) {
343*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "malloc failed\n");
344*7c478bd9Sstevel@tonic-gate 				exit(1);
345*7c478bd9Sstevel@tonic-gate 			}
346*7c478bd9Sstevel@tonic-gate 			/* get the new address of cp */
347*7c478bd9Sstevel@tonic-gate 			cp = scp + pos;
348*7c478bd9Sstevel@tonic-gate 			szbf += n * MEMFCT;
349*7c478bd9Sstevel@tonic-gate 			tszbf += n * MEMFCT;
350*7c478bd9Sstevel@tonic-gate 		}
351*7c478bd9Sstevel@tonic-gate 		switch (obuf[i].c_mode) {
352*7c478bd9Sstevel@tonic-gate 		case NORMAL:
353*7c478bd9Sstevel@tonic-gate 		default:
354*7c478bd9Sstevel@tonic-gate 			tszbf -= n;
355*7c478bd9Sstevel@tonic-gate 			*cp++ = L' ';
356*7c478bd9Sstevel@tonic-gate 			while (--n > 0) {
357*7c478bd9Sstevel@tonic-gate 				*cp++ = L' ';
358*7c478bd9Sstevel@tonic-gate 				i++;
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 			break;
361*7c478bd9Sstevel@tonic-gate 		case UNDERL:
362*7c478bd9Sstevel@tonic-gate 			tszbf -= n;
363*7c478bd9Sstevel@tonic-gate 			*cp++ = L'_';
364*7c478bd9Sstevel@tonic-gate 			while (--n > 0) {
365*7c478bd9Sstevel@tonic-gate 				*cp++ = L'_';
366*7c478bd9Sstevel@tonic-gate 				i++;
367*7c478bd9Sstevel@tonic-gate 			}
368*7c478bd9Sstevel@tonic-gate 			break;
369*7c478bd9Sstevel@tonic-gate 		case BOLD:
370*7c478bd9Sstevel@tonic-gate 			tszbf--;
371*7c478bd9Sstevel@tonic-gate 			*cp++ = obuf[i].c_char;
372*7c478bd9Sstevel@tonic-gate 			hadbold=1;
373*7c478bd9Sstevel@tonic-gate 			break;
374*7c478bd9Sstevel@tonic-gate 		}
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 	putwchar(L'\r');
377*7c478bd9Sstevel@tonic-gate 	for (*cp=L' '; *cp==L' '; cp--)
378*7c478bd9Sstevel@tonic-gate 		*cp = L'\0';
379*7c478bd9Sstevel@tonic-gate 	for (cp=scp; *cp; cp++)
380*7c478bd9Sstevel@tonic-gate 		putwchar(*cp);
381*7c478bd9Sstevel@tonic-gate 	if (hadbold) {
382*7c478bd9Sstevel@tonic-gate 		putwchar(L'\r');
383*7c478bd9Sstevel@tonic-gate 		for (cp=scp; *cp; cp++)
384*7c478bd9Sstevel@tonic-gate 			putwchar(*cp==L'_' ? L' ' : *cp);
385*7c478bd9Sstevel@tonic-gate 		putwchar(L'\r');
386*7c478bd9Sstevel@tonic-gate 		for (cp=scp; *cp; cp++)
387*7c478bd9Sstevel@tonic-gate 			putwchar(*cp==L'_' ? L' ' : *cp);
388*7c478bd9Sstevel@tonic-gate 	}
389*7c478bd9Sstevel@tonic-gate 	free(scp);
390*7c478bd9Sstevel@tonic-gate }
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate iattr()
393*7c478bd9Sstevel@tonic-gate {
394*7c478bd9Sstevel@tonic-gate 	register int i, n;
395*7c478bd9Sstevel@tonic-gate 	wchar_t *cp, *scp;
396*7c478bd9Sstevel@tonic-gate 	register wchar_t cx;
397*7c478bd9Sstevel@tonic-gate 	size_t  szbf = 256, tszbf;
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf);
400*7c478bd9Sstevel@tonic-gate 	if (!scp) {
401*7c478bd9Sstevel@tonic-gate 		/* this kind of message need not to be gettext'ed */
402*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "malloc failed\n");
403*7c478bd9Sstevel@tonic-gate 		exit(1);
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 	cp = scp;
406*7c478bd9Sstevel@tonic-gate 	tszbf = szbf;
407*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
408*7c478bd9Sstevel@tonic-gate 	/*
409*7c478bd9Sstevel@tonic-gate 	 * to allocate a memory after the chunk of the current scp
410*7c478bd9Sstevel@tonic-gate 	 * and to make sure the following realloc() allocates
411*7c478bd9Sstevel@tonic-gate 	 * memory from different chunks.
412*7c478bd9Sstevel@tonic-gate 	 */
413*7c478bd9Sstevel@tonic-gate 	(void) malloc(1024 * 1024);
414*7c478bd9Sstevel@tonic-gate #endif
415*7c478bd9Sstevel@tonic-gate 	for (i=0; i<maxcol; i++) {
416*7c478bd9Sstevel@tonic-gate 		switch (obuf[i].c_mode) {
417*7c478bd9Sstevel@tonic-gate 		case NORMAL:	cx = ' '; break;
418*7c478bd9Sstevel@tonic-gate 		case ALTSET:	cx = 'g'; break;
419*7c478bd9Sstevel@tonic-gate 		case SUPERSC:	cx = '^'; break;
420*7c478bd9Sstevel@tonic-gate 		case SUBSC:	cx = 'v'; break;
421*7c478bd9Sstevel@tonic-gate 		case UNDERL:	cx = '_'; break;
422*7c478bd9Sstevel@tonic-gate 		case BOLD:	cx = '!'; break;
423*7c478bd9Sstevel@tonic-gate 		default:	cx = 'X'; break;
424*7c478bd9Sstevel@tonic-gate 		}
425*7c478bd9Sstevel@tonic-gate 		n = scrw[wcsetno(obuf[i].c_char)];
426*7c478bd9Sstevel@tonic-gate 		if (tszbf <= n) {
427*7c478bd9Sstevel@tonic-gate 			/* may not enough buffer for this char */
428*7c478bd9Sstevel@tonic-gate 			size_t  pos;
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 			/* obtain the offset of cp */
431*7c478bd9Sstevel@tonic-gate 			pos = cp - scp;
432*7c478bd9Sstevel@tonic-gate 			/* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
433*7c478bd9Sstevel@tonic-gate 			scp = (wchar_t *)realloc(scp,
434*7c478bd9Sstevel@tonic-gate 				sizeof (wchar_t) * (szbf + (n * MEMFCT)));
435*7c478bd9Sstevel@tonic-gate 			if (!scp) {
436*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "malloc failed\n");
437*7c478bd9Sstevel@tonic-gate 				exit(1);
438*7c478bd9Sstevel@tonic-gate 			}
439*7c478bd9Sstevel@tonic-gate 			/* get the new address of cp */
440*7c478bd9Sstevel@tonic-gate 			cp = scp + pos;
441*7c478bd9Sstevel@tonic-gate 			szbf += n * MEMFCT;
442*7c478bd9Sstevel@tonic-gate 			tszbf += n * MEMFCT;
443*7c478bd9Sstevel@tonic-gate 		}
444*7c478bd9Sstevel@tonic-gate 		tszbf -= n;
445*7c478bd9Sstevel@tonic-gate 		 *cp++ = cx;
446*7c478bd9Sstevel@tonic-gate 		while (--n > 0) {
447*7c478bd9Sstevel@tonic-gate 			*cp++ = cx;
448*7c478bd9Sstevel@tonic-gate 			i++;
449*7c478bd9Sstevel@tonic-gate 		}
450*7c478bd9Sstevel@tonic-gate 	}
451*7c478bd9Sstevel@tonic-gate 	for (*cp=L' '; *cp==L' '; cp--)
452*7c478bd9Sstevel@tonic-gate 		*cp = L'\0';
453*7c478bd9Sstevel@tonic-gate 	for (cp=scp; *cp; cp++)
454*7c478bd9Sstevel@tonic-gate 		putwchar(*cp);
455*7c478bd9Sstevel@tonic-gate 	putwchar(L'\n');
456*7c478bd9Sstevel@tonic-gate 	free(scp);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate initbuf()
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate 	register i;
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	/* following depends on NORMAL == 000 */
464*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LINE_MAX; i++)
465*7c478bd9Sstevel@tonic-gate 		obuf[i].c_char = obuf[i].c_mode = 0;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	col = 0;
468*7c478bd9Sstevel@tonic-gate 	maxcol = 0;
469*7c478bd9Sstevel@tonic-gate 	mode &= ALTSET;
470*7c478bd9Sstevel@tonic-gate }
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate fwd()
473*7c478bd9Sstevel@tonic-gate {
474*7c478bd9Sstevel@tonic-gate 	register oldcol, oldmax;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	oldcol = col;
477*7c478bd9Sstevel@tonic-gate 	oldmax = maxcol;
478*7c478bd9Sstevel@tonic-gate 	flushln();
479*7c478bd9Sstevel@tonic-gate 	col = oldcol;
480*7c478bd9Sstevel@tonic-gate 	maxcol = oldmax;
481*7c478bd9Sstevel@tonic-gate }
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate reverse()
484*7c478bd9Sstevel@tonic-gate {
485*7c478bd9Sstevel@tonic-gate 	upln++;
486*7c478bd9Sstevel@tonic-gate 	fwd();
487*7c478bd9Sstevel@tonic-gate 	puts(CURS_UP);
488*7c478bd9Sstevel@tonic-gate 	puts(CURS_UP);
489*7c478bd9Sstevel@tonic-gate 	upln++;
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate initcap()
493*7c478bd9Sstevel@tonic-gate {
494*7c478bd9Sstevel@tonic-gate 	static char tcapbuf[512];
495*7c478bd9Sstevel@tonic-gate 	char *termtype;
496*7c478bd9Sstevel@tonic-gate 	char *bp = tcapbuf;
497*7c478bd9Sstevel@tonic-gate 	char *getenv(), *tgetstr();
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	/* This nonsense attempts to work with both old and new termcap */
500*7c478bd9Sstevel@tonic-gate 	CURS_UP =		tgetstr("up", &bp);
501*7c478bd9Sstevel@tonic-gate 	CURS_RIGHT =		tgetstr("ri", &bp);
502*7c478bd9Sstevel@tonic-gate 	if (CURS_RIGHT == NULL)
503*7c478bd9Sstevel@tonic-gate 		CURS_RIGHT =	tgetstr("nd", &bp);
504*7c478bd9Sstevel@tonic-gate 	CURS_LEFT =		tgetstr("le", &bp);
505*7c478bd9Sstevel@tonic-gate 	if (CURS_LEFT == NULL)
506*7c478bd9Sstevel@tonic-gate 		CURS_LEFT =	tgetstr("bc", &bp);
507*7c478bd9Sstevel@tonic-gate 	if (CURS_LEFT == NULL && tgetflag("bs"))
508*7c478bd9Sstevel@tonic-gate 		CURS_LEFT =	"\b";
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	ENTER_STANDOUT =	tgetstr("so", &bp);
511*7c478bd9Sstevel@tonic-gate 	EXIT_STANDOUT =		tgetstr("se", &bp);
512*7c478bd9Sstevel@tonic-gate 	ENTER_UNDERLINE =	tgetstr("us", &bp);
513*7c478bd9Sstevel@tonic-gate 	EXIT_UNDERLINE =	tgetstr("ue", &bp);
514*7c478bd9Sstevel@tonic-gate 	ENTER_DIM =		tgetstr("mh", &bp);
515*7c478bd9Sstevel@tonic-gate 	ENTER_BOLD =		tgetstr("md", &bp);
516*7c478bd9Sstevel@tonic-gate 	ENTER_REVERSE =		tgetstr("mr", &bp);
517*7c478bd9Sstevel@tonic-gate 	EXIT_ATTRIBUTES =	tgetstr("me", &bp);
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	if (!ENTER_BOLD && ENTER_REVERSE)
520*7c478bd9Sstevel@tonic-gate 		ENTER_BOLD = ENTER_REVERSE;
521*7c478bd9Sstevel@tonic-gate 	if (!ENTER_BOLD && ENTER_STANDOUT)
522*7c478bd9Sstevel@tonic-gate 		ENTER_BOLD = ENTER_STANDOUT;
523*7c478bd9Sstevel@tonic-gate 	if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
524*7c478bd9Sstevel@tonic-gate 		ENTER_UNDERLINE = ENTER_STANDOUT;
525*7c478bd9Sstevel@tonic-gate 		EXIT_UNDERLINE = EXIT_STANDOUT;
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate 	if (!ENTER_DIM && ENTER_STANDOUT)
528*7c478bd9Sstevel@tonic-gate 		ENTER_DIM = ENTER_STANDOUT;
529*7c478bd9Sstevel@tonic-gate 	if (!ENTER_REVERSE && ENTER_STANDOUT)
530*7c478bd9Sstevel@tonic-gate 		ENTER_REVERSE = ENTER_STANDOUT;
531*7c478bd9Sstevel@tonic-gate 	if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
532*7c478bd9Sstevel@tonic-gate 		EXIT_ATTRIBUTES = EXIT_STANDOUT;
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	/*
535*7c478bd9Sstevel@tonic-gate 	 * Note that we use REVERSE for the alternate character set,
536*7c478bd9Sstevel@tonic-gate 	 * not the as/ae capabilities.  This is because we are modelling
537*7c478bd9Sstevel@tonic-gate 	 * the model 37 teletype (since that's what nroff outputs) and
538*7c478bd9Sstevel@tonic-gate 	 * the typical as/ae is more of a graphics set, not the greek
539*7c478bd9Sstevel@tonic-gate 	 * letters the 37 has.
540*7c478bd9Sstevel@tonic-gate 	 */
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate #ifdef notdef
543*7c478bd9Sstevel@tonic-gate printf("so %s se %s us %s ue %s me %s\n",
544*7c478bd9Sstevel@tonic-gate 	ENTER_STANDOUT, EXIT_STANDOUT, ENTER_UNDERLINE,
545*7c478bd9Sstevel@tonic-gate 	EXIT_UNDERLINE, EXIT_ATTRIBUTES);
546*7c478bd9Sstevel@tonic-gate #endif
547*7c478bd9Sstevel@tonic-gate 	UNDER_CHAR =		tgetstr("uc", &bp);
548*7c478bd9Sstevel@tonic-gate 	must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
549*7c478bd9Sstevel@tonic-gate }
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate outchar(c)
552*7c478bd9Sstevel@tonic-gate char c;
553*7c478bd9Sstevel@tonic-gate {
554*7c478bd9Sstevel@tonic-gate 	putchar(c&0177);
555*7c478bd9Sstevel@tonic-gate }
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate puts(str)
558*7c478bd9Sstevel@tonic-gate const char *str;
559*7c478bd9Sstevel@tonic-gate {
560*7c478bd9Sstevel@tonic-gate 	if (str)
561*7c478bd9Sstevel@tonic-gate 		tputs(str, 1, outchar);
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate static curmode = 0;
565*7c478bd9Sstevel@tonic-gate outc(c)
566*7c478bd9Sstevel@tonic-gate wchar_t c;
567*7c478bd9Sstevel@tonic-gate {
568*7c478bd9Sstevel@tonic-gate 	register int m, n;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	if (c == CDUMMY)
571*7c478bd9Sstevel@tonic-gate 		return;
572*7c478bd9Sstevel@tonic-gate 	putwchar(c);
573*7c478bd9Sstevel@tonic-gate 	if (must_use_uc && (curmode & UNDERL)) {
574*7c478bd9Sstevel@tonic-gate 		m = n = scrw[wcsetno(c)];
575*7c478bd9Sstevel@tonic-gate 		puts(CURS_LEFT);
576*7c478bd9Sstevel@tonic-gate 		while (--m > 0)
577*7c478bd9Sstevel@tonic-gate 			puts(CURS_LEFT);
578*7c478bd9Sstevel@tonic-gate 		puts(UNDER_CHAR);
579*7c478bd9Sstevel@tonic-gate 		while (--n > 0)
580*7c478bd9Sstevel@tonic-gate 			puts(UNDER_CHAR);
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate }
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate setmode(newmode)
585*7c478bd9Sstevel@tonic-gate int newmode;
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	if (!iflag)
588*7c478bd9Sstevel@tonic-gate 	{
589*7c478bd9Sstevel@tonic-gate 		if (curmode != NORMAL && newmode != NORMAL)
590*7c478bd9Sstevel@tonic-gate 			setmode(NORMAL);
591*7c478bd9Sstevel@tonic-gate 		switch (newmode) {
592*7c478bd9Sstevel@tonic-gate 		case NORMAL:
593*7c478bd9Sstevel@tonic-gate 			switch (curmode) {
594*7c478bd9Sstevel@tonic-gate 			case NORMAL:
595*7c478bd9Sstevel@tonic-gate 				break;
596*7c478bd9Sstevel@tonic-gate 			case UNDERL:
597*7c478bd9Sstevel@tonic-gate 				puts(EXIT_UNDERLINE);
598*7c478bd9Sstevel@tonic-gate 				break;
599*7c478bd9Sstevel@tonic-gate 			default:
600*7c478bd9Sstevel@tonic-gate 				/* This includes standout */
601*7c478bd9Sstevel@tonic-gate 				puts(EXIT_ATTRIBUTES);
602*7c478bd9Sstevel@tonic-gate 				break;
603*7c478bd9Sstevel@tonic-gate 			}
604*7c478bd9Sstevel@tonic-gate 			break;
605*7c478bd9Sstevel@tonic-gate 		case ALTSET:
606*7c478bd9Sstevel@tonic-gate 			puts(ENTER_REVERSE);
607*7c478bd9Sstevel@tonic-gate 			break;
608*7c478bd9Sstevel@tonic-gate 		case SUPERSC:
609*7c478bd9Sstevel@tonic-gate 			/*
610*7c478bd9Sstevel@tonic-gate 			 * This only works on a few terminals.
611*7c478bd9Sstevel@tonic-gate 			 * It should be fixed.
612*7c478bd9Sstevel@tonic-gate 			 */
613*7c478bd9Sstevel@tonic-gate 			puts(ENTER_UNDERLINE);
614*7c478bd9Sstevel@tonic-gate 			puts(ENTER_DIM);
615*7c478bd9Sstevel@tonic-gate 			break;
616*7c478bd9Sstevel@tonic-gate 		case SUBSC:
617*7c478bd9Sstevel@tonic-gate 			puts(ENTER_DIM);
618*7c478bd9Sstevel@tonic-gate 			break;
619*7c478bd9Sstevel@tonic-gate 		case UNDERL:
620*7c478bd9Sstevel@tonic-gate 			puts(ENTER_UNDERLINE);
621*7c478bd9Sstevel@tonic-gate 			break;
622*7c478bd9Sstevel@tonic-gate 		case BOLD:
623*7c478bd9Sstevel@tonic-gate 			puts(ENTER_BOLD);
624*7c478bd9Sstevel@tonic-gate 			break;
625*7c478bd9Sstevel@tonic-gate 		default:
626*7c478bd9Sstevel@tonic-gate 			/*
627*7c478bd9Sstevel@tonic-gate 			 * We should have some provision here for multiple modes
628*7c478bd9Sstevel@tonic-gate 			 * on at once.  This will have to come later.
629*7c478bd9Sstevel@tonic-gate 			 */
630*7c478bd9Sstevel@tonic-gate 			puts(ENTER_STANDOUT);
631*7c478bd9Sstevel@tonic-gate 			break;
632*7c478bd9Sstevel@tonic-gate 		}
633*7c478bd9Sstevel@tonic-gate 	}
634*7c478bd9Sstevel@tonic-gate 	curmode = newmode;
635*7c478bd9Sstevel@tonic-gate }
636