xref: /netbsd-src/usr.bin/ul/ul.c (revision fbffadb9f864c0324fb295860ab0faeb187269cc)
1*fbffadb9Smrg /*	$NetBSD: ul.c,v 1.20 2019/02/03 03:19:30 mrg Exp $	*/
27a51c221Sjtc 
361f28255Scgd /*
47a51c221Sjtc  * Copyright (c) 1980, 1993
57a51c221Sjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
322122942cSlukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
3598e5374cSlukem  The Regents of the University of California.  All rights reserved.");
3661f28255Scgd #endif /* not lint */
3761f28255Scgd 
3861f28255Scgd #ifndef lint
397a51c221Sjtc #if 0
407a51c221Sjtc static char sccsid[] = "@(#)ul.c	8.1 (Berkeley) 6/6/93";
417a51c221Sjtc #endif
42*fbffadb9Smrg __RCSID("$NetBSD: ul.c,v 1.20 2019/02/03 03:19:30 mrg Exp $");
4361f28255Scgd #endif /* not lint */
4461f28255Scgd 
4589e18818Sabhinav #include <err.h>
4661f28255Scgd #include <stdio.h>
47db5284edSjtc #include <stdlib.h>
48db5284edSjtc #include <string.h>
4998eb8895Sroy #include <term.h>
502122942cSlukem #include <unistd.h>
5189e18818Sabhinav #include <util.h>
5261f28255Scgd 
5361f28255Scgd #define	IESC	'\033'
5461f28255Scgd #define	SO	'\016'
5561f28255Scgd #define	SI	'\017'
5661f28255Scgd #define	HFWD	'9'
5761f28255Scgd #define	HREV	'8'
5861f28255Scgd #define	FREV	'7'
5961f28255Scgd #define	MAXBUF	512
6061f28255Scgd 
6161f28255Scgd #define	NORMAL	000
6261f28255Scgd #define	ALTSET	001	/* Reverse */
6361f28255Scgd #define	SUPERSC	002	/* Dim */
6461f28255Scgd #define	SUBSC	004	/* Dim | Ul */
6561f28255Scgd #define	UNDERL	010	/* Ul */
6661f28255Scgd #define	BOLD	020	/* Bold */
6761f28255Scgd 
688dc887f7Sabhinav static int	must_overstrike;
6961f28255Scgd 
7061f28255Scgd struct	CHAR	{
7161f28255Scgd 	char	c_mode;
7261f28255Scgd 	char	c_char;
7361f28255Scgd } ;
7461f28255Scgd 
758dc887f7Sabhinav static size_t col, maxcol;
768dc887f7Sabhinav static int	mode;
778dc887f7Sabhinav static int	halfpos;
788dc887f7Sabhinav static int	upln;
798dc887f7Sabhinav static int	iflag;
8061f28255Scgd 
818dc887f7Sabhinav static void filter(FILE *);
828dc887f7Sabhinav static void flushln(struct CHAR *, size_t);
838dc887f7Sabhinav static void fwd(struct CHAR *, size_t);
848dc887f7Sabhinav static void iattr(struct CHAR *);
858dc887f7Sabhinav static void initbuf(struct CHAR *, size_t);
868dc887f7Sabhinav static void outc(int);
878dc887f7Sabhinav static int outchar(int);
888dc887f7Sabhinav static void overstrike(struct CHAR *);
898dc887f7Sabhinav static void reverse(struct CHAR *, size_t);
908dc887f7Sabhinav static void setulmode(int);
9189e18818Sabhinav static void alloc_buf(struct CHAR **, size_t *);
9289e18818Sabhinav static void set_mode(void);
932122942cSlukem 
942122942cSlukem 
9561f28255Scgd #define	PRINT(s)	if (s == NULL) /* void */; else tputs(s, 1, outchar)
9661f28255Scgd 
972122942cSlukem int
main(int argc,char ** argv)98d34c2845Smatt main(int argc, char **argv)
9961f28255Scgd {
10061f28255Scgd 	int c;
101f76ec3edSlukem 	const char *termtype;
10261f28255Scgd 	FILE *f;
10361f28255Scgd 
10461f28255Scgd 	termtype = getenv("TERM");
10561f28255Scgd 	if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
10661f28255Scgd 		termtype = "lpr";
10769ac758aSlukem 	while ((c=getopt(argc, argv, "it:T:")) != -1)
10861f28255Scgd 		switch(c) {
10961f28255Scgd 
11061f28255Scgd 		case 't':
11161f28255Scgd 		case 'T': /* for nroff compatibility */
11261f28255Scgd 				termtype = optarg;
11361f28255Scgd 			break;
11461f28255Scgd 		case 'i':
11561f28255Scgd 			iflag = 1;
11661f28255Scgd 			break;
11761f28255Scgd 
11861f28255Scgd 		default:
11961f28255Scgd 			fprintf(stderr,
12061f28255Scgd 				"usage: %s [ -i ] [ -tTerm ] file...\n",
12161f28255Scgd 				argv[0]);
12261f28255Scgd 			exit(1);
12361f28255Scgd 		}
12461f28255Scgd 
12598eb8895Sroy 	setupterm(termtype, 0, NULL);
12698eb8895Sroy 	if ((over_strike && enter_bold_mode == NULL) ||
12798eb8895Sroy 	    (transparent_underline && enter_underline_mode == NULL &&
12889e18818Sabhinav 		underline_char == NULL)) {
12989e18818Sabhinav 		set_mode();
13089e18818Sabhinav 	}
13161f28255Scgd 	if (optind == argc)
13261f28255Scgd 		filter(stdin);
13389e18818Sabhinav 	else {
13489e18818Sabhinav 		for (; optind < argc; optind++) {
13561f28255Scgd 			f = fopen(argv[optind], "r");
13689e18818Sabhinav 			if (f == NULL)
13789e18818Sabhinav 				err(EXIT_FAILURE, "Failed to open `%s'", argv[optind]);
13861f28255Scgd 			filter(f);
139db5284edSjtc 			fclose(f);
14061f28255Scgd 		}
14189e18818Sabhinav 	}
14261f28255Scgd 	exit(0);
14361f28255Scgd }
14461f28255Scgd 
1458dc887f7Sabhinav static void
filter(FILE * f)146d34c2845Smatt filter(FILE *f)
14761f28255Scgd {
1482122942cSlukem 	int c;
14989e18818Sabhinav 	struct	CHAR *obuf = NULL;
15089e18818Sabhinav 	size_t obuf_size = 0;
15189e18818Sabhinav 	alloc_buf(&obuf, &obuf_size);
15261f28255Scgd 
15361f28255Scgd 	while ((c = getc(f)) != EOF) switch(c) {
15461f28255Scgd 
15561f28255Scgd 	case '\b':
15661f28255Scgd 		if (col > 0)
15761f28255Scgd 			col--;
15861f28255Scgd 		continue;
15961f28255Scgd 
16061f28255Scgd 	case '\t':
16161f28255Scgd 		col = (col+8) & ~07;
16261f28255Scgd 		if (col > maxcol)
16361f28255Scgd 			maxcol = col;
16489e18818Sabhinav 		if (col >= obuf_size)
16589e18818Sabhinav 			alloc_buf(&obuf, &obuf_size);
16661f28255Scgd 		continue;
16761f28255Scgd 
16861f28255Scgd 	case '\r':
16961f28255Scgd 		col = 0;
17061f28255Scgd 		continue;
17161f28255Scgd 
17261f28255Scgd 	case SO:
17361f28255Scgd 		mode |= ALTSET;
17461f28255Scgd 		continue;
17561f28255Scgd 
17661f28255Scgd 	case SI:
17761f28255Scgd 		mode &= ~ALTSET;
17861f28255Scgd 		continue;
17961f28255Scgd 
18061f28255Scgd 	case IESC:
18161f28255Scgd 		switch (c = getc(f)) {
18261f28255Scgd 
18361f28255Scgd 		case HREV:
18461f28255Scgd 			if (halfpos == 0) {
18561f28255Scgd 				mode |= SUPERSC;
18661f28255Scgd 				halfpos--;
18761f28255Scgd 			} else if (halfpos > 0) {
18861f28255Scgd 				mode &= ~SUBSC;
18961f28255Scgd 				halfpos--;
19061f28255Scgd 			} else {
19161f28255Scgd 				halfpos = 0;
19289e18818Sabhinav 				reverse(obuf, obuf_size);
19361f28255Scgd 			}
19461f28255Scgd 			continue;
19561f28255Scgd 
19661f28255Scgd 		case HFWD:
19761f28255Scgd 			if (halfpos == 0) {
19861f28255Scgd 				mode |= SUBSC;
19961f28255Scgd 				halfpos++;
20061f28255Scgd 			} else if (halfpos < 0) {
20161f28255Scgd 				mode &= ~SUPERSC;
20261f28255Scgd 				halfpos++;
20361f28255Scgd 			} else {
20461f28255Scgd 				halfpos = 0;
20589e18818Sabhinav 				fwd(obuf, obuf_size);
20661f28255Scgd 			}
20761f28255Scgd 			continue;
20861f28255Scgd 
20961f28255Scgd 		case FREV:
21089e18818Sabhinav 			reverse(obuf, obuf_size);
21161f28255Scgd 			continue;
21261f28255Scgd 
21361f28255Scgd 		default:
21461f28255Scgd 			fprintf(stderr,
21561f28255Scgd 				"Unknown escape sequence in input: %o, %o\n",
21661f28255Scgd 				IESC, c);
21761f28255Scgd 			exit(1);
21861f28255Scgd 		}
21961f28255Scgd 
22061f28255Scgd 	case '_':
22161f28255Scgd 		if (obuf[col].c_char)
22261f28255Scgd 			obuf[col].c_mode |= UNDERL | mode;
22361f28255Scgd 		else
22461f28255Scgd 			obuf[col].c_char = '_';
225*fbffadb9Smrg 		/* FALLTHROUGH */
22661f28255Scgd 	case ' ':
22761f28255Scgd 		col++;
22861f28255Scgd 		if (col > maxcol)
22961f28255Scgd 			maxcol = col;
23089e18818Sabhinav 		if (col >= obuf_size)
23189e18818Sabhinav 			alloc_buf(&obuf, &obuf_size);
23261f28255Scgd 		continue;
23361f28255Scgd 
23461f28255Scgd 	case '\n':
23589e18818Sabhinav 		flushln(obuf, obuf_size);
23661f28255Scgd 		continue;
23761f28255Scgd 
23861f28255Scgd 	case '\f':
23989e18818Sabhinav 		flushln(obuf, obuf_size);
24061f28255Scgd 		putchar('\f');
24161f28255Scgd 		continue;
24261f28255Scgd 
24361f28255Scgd 	default:
24461f28255Scgd 		if (c < ' ')	/* non printing */
24561f28255Scgd 			continue;
24661f28255Scgd 		if (obuf[col].c_char == '\0') {
24761f28255Scgd 			obuf[col].c_char = c;
24861f28255Scgd 			obuf[col].c_mode = mode;
24961f28255Scgd 		} else if (obuf[col].c_char == '_') {
25061f28255Scgd 			obuf[col].c_char = c;
25161f28255Scgd 			obuf[col].c_mode |= UNDERL|mode;
25261f28255Scgd 		} else if (obuf[col].c_char == c)
25361f28255Scgd 			obuf[col].c_mode |= BOLD|mode;
25461f28255Scgd 		else
25561f28255Scgd 			obuf[col].c_mode = mode;
25661f28255Scgd 		col++;
25761f28255Scgd 		if (col > maxcol)
25861f28255Scgd 			maxcol = col;
25989e18818Sabhinav 		if (col >= obuf_size)
26089e18818Sabhinav 			alloc_buf(&obuf, &obuf_size);
26161f28255Scgd 		continue;
26261f28255Scgd 	}
26361f28255Scgd 	if (maxcol)
26489e18818Sabhinav 		flushln(obuf, obuf_size);
26589e18818Sabhinav 
26689e18818Sabhinav 	free(obuf);
26761f28255Scgd }
26861f28255Scgd 
2698dc887f7Sabhinav static void
flushln(struct CHAR * obuf,size_t obuf_size)27089e18818Sabhinav flushln(struct CHAR *obuf, size_t obuf_size)
27161f28255Scgd {
2722122942cSlukem 	int lastmode;
27389e18818Sabhinav 	size_t i;
27461f28255Scgd 	int hadmodes = 0;
27561f28255Scgd 
27661f28255Scgd 	lastmode = NORMAL;
27761f28255Scgd 	for (i=0; i<maxcol; i++) {
27861f28255Scgd 		if (obuf[i].c_mode != lastmode) {
27961f28255Scgd 			hadmodes++;
2802122942cSlukem 			setulmode(obuf[i].c_mode);
28161f28255Scgd 			lastmode = obuf[i].c_mode;
28261f28255Scgd 		}
28361f28255Scgd 		if (obuf[i].c_char == '\0') {
28423933685Schristos 			if (upln) {
28598eb8895Sroy 				PRINT(cursor_right);
28623933685Schristos 			}
28723933685Schristos 			else {
28861f28255Scgd 				outc(' ');
28923933685Schristos 			}
29061f28255Scgd 		} else
29161f28255Scgd 			outc(obuf[i].c_char);
29261f28255Scgd 	}
29361f28255Scgd 	if (lastmode != NORMAL) {
2942122942cSlukem 		setulmode(0);
29561f28255Scgd 	}
29661f28255Scgd 	if (must_overstrike && hadmodes)
29789e18818Sabhinav 		overstrike(obuf);
29861f28255Scgd 	putchar('\n');
29961f28255Scgd 	if (iflag && hadmodes)
30089e18818Sabhinav 		iattr(obuf);
30161f28255Scgd 	(void)fflush(stdout);
30261f28255Scgd 	if (upln)
30361f28255Scgd 		upln--;
30489e18818Sabhinav 	initbuf(obuf, obuf_size);
30561f28255Scgd }
30661f28255Scgd 
30761f28255Scgd /*
30861f28255Scgd  * For terminals that can overstrike, overstrike underlines and bolds.
30961f28255Scgd  * We don't do anything with halfline ups and downs, or Greek.
31061f28255Scgd  */
3118dc887f7Sabhinav static void
overstrike(struct CHAR * obuf)31289e18818Sabhinav overstrike(struct CHAR *obuf)
31361f28255Scgd {
31489e18818Sabhinav 	size_t i;
31561f28255Scgd 	char lbuf[256];
3162122942cSlukem 	char *cp = lbuf;
31761f28255Scgd 	int hadbold=0;
31861f28255Scgd 
31961f28255Scgd 	/* Set up overstrike buffer */
32061f28255Scgd 	for (i=0; i<maxcol; i++)
32161f28255Scgd 		switch (obuf[i].c_mode) {
32261f28255Scgd 		case NORMAL:
32361f28255Scgd 		default:
32461f28255Scgd 			*cp++ = ' ';
32561f28255Scgd 			break;
32661f28255Scgd 		case UNDERL:
32761f28255Scgd 			*cp++ = '_';
32861f28255Scgd 			break;
32961f28255Scgd 		case BOLD:
33061f28255Scgd 			*cp++ = obuf[i].c_char;
33161f28255Scgd 			hadbold=1;
33261f28255Scgd 			break;
33361f28255Scgd 		}
33461f28255Scgd 	putchar('\r');
33561f28255Scgd 	for (*cp=' '; *cp==' '; cp--)
33661f28255Scgd 		*cp = 0;
33761f28255Scgd 	for (cp=lbuf; *cp; cp++)
33861f28255Scgd 		putchar(*cp);
33961f28255Scgd 	if (hadbold) {
34061f28255Scgd 		putchar('\r');
34161f28255Scgd 		for (cp=lbuf; *cp; cp++)
34261f28255Scgd 			putchar(*cp=='_' ? ' ' : *cp);
34361f28255Scgd 		putchar('\r');
34461f28255Scgd 		for (cp=lbuf; *cp; cp++)
34561f28255Scgd 			putchar(*cp=='_' ? ' ' : *cp);
34661f28255Scgd 	}
34761f28255Scgd }
34861f28255Scgd 
3498dc887f7Sabhinav static void
iattr(struct CHAR * obuf)35089e18818Sabhinav iattr(struct CHAR *obuf)
35161f28255Scgd {
35289e18818Sabhinav 	size_t i;
35361f28255Scgd 	char lbuf[256];
3542122942cSlukem 	char *cp = lbuf;
35561f28255Scgd 
35661f28255Scgd 	for (i=0; i<maxcol; i++)
35761f28255Scgd 		switch (obuf[i].c_mode) {
35861f28255Scgd 		case NORMAL:	*cp++ = ' '; break;
35961f28255Scgd 		case ALTSET:	*cp++ = 'g'; break;
36061f28255Scgd 		case SUPERSC:	*cp++ = '^'; break;
36161f28255Scgd 		case SUBSC:	*cp++ = 'v'; break;
36261f28255Scgd 		case UNDERL:	*cp++ = '_'; break;
36361f28255Scgd 		case BOLD:	*cp++ = '!'; break;
36461f28255Scgd 		default:	*cp++ = 'X'; break;
36561f28255Scgd 		}
36661f28255Scgd 	for (*cp=' '; *cp==' '; cp--)
36761f28255Scgd 		*cp = 0;
36861f28255Scgd 	for (cp=lbuf; *cp; cp++)
36961f28255Scgd 		putchar(*cp);
37061f28255Scgd 	putchar('\n');
37161f28255Scgd }
37261f28255Scgd 
3738dc887f7Sabhinav static void
initbuf(struct CHAR * obuf,size_t obuf_size)37489e18818Sabhinav initbuf(struct CHAR *obuf, size_t obuf_size)
37561f28255Scgd {
37661f28255Scgd 
37789e18818Sabhinav 	memset(obuf, 0, obuf_size * sizeof(*obuf));	/* depends on NORMAL == 0 */
37861f28255Scgd 	col = 0;
37961f28255Scgd 	maxcol = 0;
38089e18818Sabhinav 	set_mode();
38189e18818Sabhinav }
38289e18818Sabhinav 
38389e18818Sabhinav static void
set_mode(void)38489e18818Sabhinav set_mode(void)
38589e18818Sabhinav {
38661f28255Scgd 	mode &= ALTSET;
38761f28255Scgd }
38861f28255Scgd 
3898dc887f7Sabhinav static void
fwd(struct CHAR * obuf,size_t obuf_size)39089e18818Sabhinav fwd(struct CHAR *obuf, size_t obuf_size)
39161f28255Scgd {
3922122942cSlukem 	int oldcol, oldmax;
39361f28255Scgd 
39461f28255Scgd 	oldcol = col;
39561f28255Scgd 	oldmax = maxcol;
39689e18818Sabhinav 	flushln(obuf, obuf_size);
39761f28255Scgd 	col = oldcol;
39861f28255Scgd 	maxcol = oldmax;
39961f28255Scgd }
40061f28255Scgd 
4018dc887f7Sabhinav static void
reverse(struct CHAR * obuf,size_t obuf_size)40289e18818Sabhinav reverse(struct CHAR *obuf, size_t obuf_size)
40361f28255Scgd {
40461f28255Scgd 	upln++;
40589e18818Sabhinav 	fwd(obuf, obuf_size);
40698eb8895Sroy 	PRINT(cursor_up);
40798eb8895Sroy 	PRINT(cursor_up);
40861f28255Scgd 	upln++;
40961f28255Scgd }
41061f28255Scgd 
4118dc887f7Sabhinav static int
outchar(int c)412d34c2845Smatt outchar(int c)
41361f28255Scgd {
41488d3d7c5Slukem 	return (putchar(c & 0177));
41561f28255Scgd }
41661f28255Scgd 
41761f28255Scgd static int curmode = 0;
41861f28255Scgd 
4198dc887f7Sabhinav static void
outc(int c)420d34c2845Smatt outc(int c)
42161f28255Scgd {
42261f28255Scgd 	putchar(c);
42398eb8895Sroy 	if (underline_char && !enter_underline_mode && (curmode & UNDERL)) {
42498eb8895Sroy 		if (cursor_left)
42598eb8895Sroy 			PRINT(cursor_left);
42698eb8895Sroy 		else
42798eb8895Sroy 			putchar('\b');
42898eb8895Sroy 		PRINT(underline_char);
42961f28255Scgd 	}
43061f28255Scgd }
43161f28255Scgd 
4328dc887f7Sabhinav static void
setulmode(int newmode)433d34c2845Smatt setulmode(int newmode)
43461f28255Scgd {
43561f28255Scgd 	if (!iflag) {
43661f28255Scgd 		if (curmode != NORMAL && newmode != NORMAL)
4372122942cSlukem 			setulmode(NORMAL);
43861f28255Scgd 		switch (newmode) {
43961f28255Scgd 		case NORMAL:
44061f28255Scgd 			switch(curmode) {
44161f28255Scgd 			case NORMAL:
44261f28255Scgd 				break;
44361f28255Scgd 			case UNDERL:
44498eb8895Sroy 				if (enter_underline_mode)
44598eb8895Sroy 					PRINT(exit_underline_mode);
44698eb8895Sroy 				else
44798eb8895Sroy 					PRINT(exit_standout_mode);
44861f28255Scgd 				break;
44961f28255Scgd 			default:
45061f28255Scgd 				/* This includes standout */
45198eb8895Sroy 				if (exit_attribute_mode)
45298eb8895Sroy 					PRINT(exit_attribute_mode);
45398eb8895Sroy 				else
45498eb8895Sroy 					PRINT(exit_standout_mode);
45561f28255Scgd 				break;
45661f28255Scgd 			}
45761f28255Scgd 			break;
45861f28255Scgd 		case ALTSET:
45998eb8895Sroy 			if (enter_reverse_mode)
46098eb8895Sroy 				PRINT(enter_reverse_mode);
46198eb8895Sroy 			else
46298eb8895Sroy 				PRINT(enter_standout_mode);
46361f28255Scgd 			break;
46461f28255Scgd 		case SUPERSC:
46561f28255Scgd 			/*
46661f28255Scgd 			 * This only works on a few terminals.
46761f28255Scgd 			 * It should be fixed.
46861f28255Scgd 			 */
46998eb8895Sroy 			PRINT(enter_underline_mode);
47098eb8895Sroy 			PRINT(enter_dim_mode);
47161f28255Scgd 			break;
47261f28255Scgd 		case SUBSC:
47398eb8895Sroy 			if (enter_dim_mode)
47498eb8895Sroy 				PRINT(enter_dim_mode);
47598eb8895Sroy 			else
47698eb8895Sroy 				PRINT(enter_standout_mode);
47761f28255Scgd 			break;
47861f28255Scgd 		case UNDERL:
47998eb8895Sroy 			if (enter_underline_mode)
48098eb8895Sroy 				PRINT(enter_underline_mode);
48198eb8895Sroy 			else
48298eb8895Sroy 				PRINT(enter_standout_mode);
48361f28255Scgd 			break;
48461f28255Scgd 		case BOLD:
48598eb8895Sroy 			if (enter_bold_mode)
48698eb8895Sroy 				PRINT(enter_bold_mode);
48798eb8895Sroy 			else
48898eb8895Sroy 				PRINT(enter_reverse_mode);
48961f28255Scgd 			break;
49061f28255Scgd 		default:
49161f28255Scgd 			/*
49261f28255Scgd 			 * We should have some provision here for multiple modes
49361f28255Scgd 			 * on at once.  This will have to come later.
49461f28255Scgd 			 */
49598eb8895Sroy 			PRINT(enter_standout_mode);
49661f28255Scgd 			break;
49761f28255Scgd 		}
49861f28255Scgd 	}
49961f28255Scgd 	curmode = newmode;
50061f28255Scgd }
50189e18818Sabhinav 
50289e18818Sabhinav /*
50389e18818Sabhinav  * Reallocates the buffer pointed to by *buf and sets
50489e18818Sabhinav  * the newly allocated set of bytes to 0.
50589e18818Sabhinav  */
506762c2184Sabhinav static void
alloc_buf(struct CHAR ** buf,size_t * size)50789e18818Sabhinav alloc_buf(struct CHAR **buf, size_t *size)
50889e18818Sabhinav {
50989e18818Sabhinav         size_t osize = *size;
51089e18818Sabhinav         *size += MAXBUF;
51189e18818Sabhinav         ereallocarr(buf, *size, sizeof(**buf));
51289e18818Sabhinav         memset(*buf + osize, 0, (*size - osize) * sizeof(**buf));
51389e18818Sabhinav }
514