xref: /freebsd/contrib/mandoc/roff_term.c (revision 7295610f)
1*7295610fSBaptiste Daroussin /*	$Id: roff_term.c,v 1.19 2019/01/04 03:24:33 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
3*7295610fSBaptiste Daroussin  * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  *
561d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
661d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
761d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
861d06d6bSBaptiste Daroussin  *
961d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d06d6bSBaptiste Daroussin  */
1761d06d6bSBaptiste Daroussin #include <sys/types.h>
1861d06d6bSBaptiste Daroussin 
1961d06d6bSBaptiste Daroussin #include <assert.h>
20*7295610fSBaptiste Daroussin #include <stdio.h>
21*7295610fSBaptiste Daroussin #include <string.h>
2261d06d6bSBaptiste Daroussin 
2361d06d6bSBaptiste Daroussin #include "mandoc.h"
2461d06d6bSBaptiste Daroussin #include "roff.h"
2561d06d6bSBaptiste Daroussin #include "out.h"
2661d06d6bSBaptiste Daroussin #include "term.h"
2761d06d6bSBaptiste Daroussin 
2861d06d6bSBaptiste Daroussin #define	ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
2961d06d6bSBaptiste Daroussin 
3061d06d6bSBaptiste Daroussin typedef	void	(*roff_term_pre_fp)(ROFF_TERM_ARGS);
3161d06d6bSBaptiste Daroussin 
3261d06d6bSBaptiste Daroussin static	void	  roff_term_pre_br(ROFF_TERM_ARGS);
3361d06d6bSBaptiste Daroussin static	void	  roff_term_pre_ce(ROFF_TERM_ARGS);
3461d06d6bSBaptiste Daroussin static	void	  roff_term_pre_ft(ROFF_TERM_ARGS);
3561d06d6bSBaptiste Daroussin static	void	  roff_term_pre_ll(ROFF_TERM_ARGS);
3661d06d6bSBaptiste Daroussin static	void	  roff_term_pre_mc(ROFF_TERM_ARGS);
3761d06d6bSBaptiste Daroussin static	void	  roff_term_pre_po(ROFF_TERM_ARGS);
3861d06d6bSBaptiste Daroussin static	void	  roff_term_pre_sp(ROFF_TERM_ARGS);
3961d06d6bSBaptiste Daroussin static	void	  roff_term_pre_ta(ROFF_TERM_ARGS);
4061d06d6bSBaptiste Daroussin static	void	  roff_term_pre_ti(ROFF_TERM_ARGS);
4161d06d6bSBaptiste Daroussin 
4261d06d6bSBaptiste Daroussin static	const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
4361d06d6bSBaptiste Daroussin 	roff_term_pre_br,  /* br */
4461d06d6bSBaptiste Daroussin 	roff_term_pre_ce,  /* ce */
45*7295610fSBaptiste Daroussin 	roff_term_pre_br,  /* fi */
4661d06d6bSBaptiste Daroussin 	roff_term_pre_ft,  /* ft */
4761d06d6bSBaptiste Daroussin 	roff_term_pre_ll,  /* ll */
4861d06d6bSBaptiste Daroussin 	roff_term_pre_mc,  /* mc */
49*7295610fSBaptiste Daroussin 	roff_term_pre_br,  /* nf */
5061d06d6bSBaptiste Daroussin 	roff_term_pre_po,  /* po */
5161d06d6bSBaptiste Daroussin 	roff_term_pre_ce,  /* rj */
5261d06d6bSBaptiste Daroussin 	roff_term_pre_sp,  /* sp */
5361d06d6bSBaptiste Daroussin 	roff_term_pre_ta,  /* ta */
5461d06d6bSBaptiste Daroussin 	roff_term_pre_ti,  /* ti */
5561d06d6bSBaptiste Daroussin };
5661d06d6bSBaptiste Daroussin 
5761d06d6bSBaptiste Daroussin 
5861d06d6bSBaptiste Daroussin void
5961d06d6bSBaptiste Daroussin roff_term_pre(struct termp *p, const struct roff_node *n)
6061d06d6bSBaptiste Daroussin {
6161d06d6bSBaptiste Daroussin 	assert(n->tok < ROFF_MAX);
6261d06d6bSBaptiste Daroussin 	(*roff_term_pre_acts[n->tok])(p, n);
6361d06d6bSBaptiste Daroussin }
6461d06d6bSBaptiste Daroussin 
6561d06d6bSBaptiste Daroussin static void
6661d06d6bSBaptiste Daroussin roff_term_pre_br(ROFF_TERM_ARGS)
6761d06d6bSBaptiste Daroussin {
6861d06d6bSBaptiste Daroussin 	term_newln(p);
6961d06d6bSBaptiste Daroussin 	if (p->flags & TERMP_BRIND) {
7061d06d6bSBaptiste Daroussin 		p->tcol->offset = p->tcol->rmargin;
7161d06d6bSBaptiste Daroussin 		p->tcol->rmargin = p->maxrmargin;
72*7295610fSBaptiste Daroussin 		p->trailspace = 0;
7361d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
74*7295610fSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
7561d06d6bSBaptiste Daroussin 	}
7661d06d6bSBaptiste Daroussin }
7761d06d6bSBaptiste Daroussin 
7861d06d6bSBaptiste Daroussin static void
7961d06d6bSBaptiste Daroussin roff_term_pre_ce(ROFF_TERM_ARGS)
8061d06d6bSBaptiste Daroussin {
8161d06d6bSBaptiste Daroussin 	const struct roff_node	*nc1, *nc2;
8261d06d6bSBaptiste Daroussin 
8361d06d6bSBaptiste Daroussin 	roff_term_pre_br(p, n);
84*7295610fSBaptiste Daroussin 	p->flags |= n->tok == ROFF_ce ? TERMP_CENTER : TERMP_RIGHT;
8561d06d6bSBaptiste Daroussin 	nc1 = n->child->next;
8661d06d6bSBaptiste Daroussin 	while (nc1 != NULL) {
8761d06d6bSBaptiste Daroussin 		nc2 = nc1;
8861d06d6bSBaptiste Daroussin 		do {
8961d06d6bSBaptiste Daroussin 			nc2 = nc2->next;
9061d06d6bSBaptiste Daroussin 		} while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
9161d06d6bSBaptiste Daroussin 		    (nc2->flags & NODE_LINE) == 0));
9261d06d6bSBaptiste Daroussin 		while (nc1 != nc2) {
9361d06d6bSBaptiste Daroussin 			if (nc1->type == ROFFT_TEXT)
9461d06d6bSBaptiste Daroussin 				term_word(p, nc1->string);
9561d06d6bSBaptiste Daroussin 			else
9661d06d6bSBaptiste Daroussin 				roff_term_pre(p, nc1);
9761d06d6bSBaptiste Daroussin 			nc1 = nc1->next;
9861d06d6bSBaptiste Daroussin 		}
9961d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
10061d06d6bSBaptiste Daroussin 		term_flushln(p);
10161d06d6bSBaptiste Daroussin 	}
102*7295610fSBaptiste Daroussin 	p->flags &= ~(TERMP_CENTER | TERMP_RIGHT);
10361d06d6bSBaptiste Daroussin }
10461d06d6bSBaptiste Daroussin 
10561d06d6bSBaptiste Daroussin static void
10661d06d6bSBaptiste Daroussin roff_term_pre_ft(ROFF_TERM_ARGS)
10761d06d6bSBaptiste Daroussin {
108*7295610fSBaptiste Daroussin 	const char	*cp;
109*7295610fSBaptiste Daroussin 
110*7295610fSBaptiste Daroussin 	cp = n->child->string;
111*7295610fSBaptiste Daroussin 	switch (mandoc_font(cp, (int)strlen(cp))) {
112*7295610fSBaptiste Daroussin 	case ESCAPE_FONTBOLD:
11361d06d6bSBaptiste Daroussin 		term_fontrepl(p, TERMFONT_BOLD);
11461d06d6bSBaptiste Daroussin 		break;
115*7295610fSBaptiste Daroussin 	case ESCAPE_FONTITALIC:
11661d06d6bSBaptiste Daroussin 		term_fontrepl(p, TERMFONT_UNDER);
11761d06d6bSBaptiste Daroussin 		break;
118*7295610fSBaptiste Daroussin 	case ESCAPE_FONTBI:
119*7295610fSBaptiste Daroussin 		term_fontrepl(p, TERMFONT_BI);
120*7295610fSBaptiste Daroussin 		break;
121*7295610fSBaptiste Daroussin 	case ESCAPE_FONTPREV:
12261d06d6bSBaptiste Daroussin 		term_fontlast(p);
12361d06d6bSBaptiste Daroussin 		break;
124*7295610fSBaptiste Daroussin 	case ESCAPE_FONTROMAN:
125*7295610fSBaptiste Daroussin 	case ESCAPE_FONTCW:
12661d06d6bSBaptiste Daroussin 		term_fontrepl(p, TERMFONT_NONE);
12761d06d6bSBaptiste Daroussin 		break;
12861d06d6bSBaptiste Daroussin 	default:
12961d06d6bSBaptiste Daroussin 		break;
13061d06d6bSBaptiste Daroussin 	}
13161d06d6bSBaptiste Daroussin }
13261d06d6bSBaptiste Daroussin 
13361d06d6bSBaptiste Daroussin static void
13461d06d6bSBaptiste Daroussin roff_term_pre_ll(ROFF_TERM_ARGS)
13561d06d6bSBaptiste Daroussin {
13661d06d6bSBaptiste Daroussin 	term_setwidth(p, n->child != NULL ? n->child->string : NULL);
13761d06d6bSBaptiste Daroussin }
13861d06d6bSBaptiste Daroussin 
13961d06d6bSBaptiste Daroussin static void
14061d06d6bSBaptiste Daroussin roff_term_pre_mc(ROFF_TERM_ARGS)
14161d06d6bSBaptiste Daroussin {
14261d06d6bSBaptiste Daroussin 	if (p->col) {
14361d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOBREAK;
14461d06d6bSBaptiste Daroussin 		term_flushln(p);
14561d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
14661d06d6bSBaptiste Daroussin 	}
14761d06d6bSBaptiste Daroussin 	if (n->child != NULL) {
14861d06d6bSBaptiste Daroussin 		p->mc = n->child->string;
14961d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NEWMC;
15061d06d6bSBaptiste Daroussin 	} else
15161d06d6bSBaptiste Daroussin 		p->flags |= TERMP_ENDMC;
15261d06d6bSBaptiste Daroussin }
15361d06d6bSBaptiste Daroussin 
15461d06d6bSBaptiste Daroussin static void
15561d06d6bSBaptiste Daroussin roff_term_pre_po(ROFF_TERM_ARGS)
15661d06d6bSBaptiste Daroussin {
15761d06d6bSBaptiste Daroussin 	struct roffsu	 su;
15861d06d6bSBaptiste Daroussin 	static int	 po, polast;
15961d06d6bSBaptiste Daroussin 	int		 ponew;
16061d06d6bSBaptiste Daroussin 
16161d06d6bSBaptiste Daroussin 	if (n->child != NULL &&
16261d06d6bSBaptiste Daroussin 	    a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
16361d06d6bSBaptiste Daroussin 		ponew = term_hen(p, &su);
16461d06d6bSBaptiste Daroussin 		if (*n->child->string == '+' ||
16561d06d6bSBaptiste Daroussin 		    *n->child->string == '-')
16661d06d6bSBaptiste Daroussin 			ponew += po;
16761d06d6bSBaptiste Daroussin 	} else
16861d06d6bSBaptiste Daroussin 		ponew = polast;
16961d06d6bSBaptiste Daroussin 	polast = po;
17061d06d6bSBaptiste Daroussin 	po = ponew;
17161d06d6bSBaptiste Daroussin 
17261d06d6bSBaptiste Daroussin 	ponew = po - polast + (int)p->tcol->offset;
17361d06d6bSBaptiste Daroussin 	p->tcol->offset = ponew > 0 ? ponew : 0;
17461d06d6bSBaptiste Daroussin }
17561d06d6bSBaptiste Daroussin 
17661d06d6bSBaptiste Daroussin static void
17761d06d6bSBaptiste Daroussin roff_term_pre_sp(ROFF_TERM_ARGS)
17861d06d6bSBaptiste Daroussin {
17961d06d6bSBaptiste Daroussin 	struct roffsu	 su;
18061d06d6bSBaptiste Daroussin 	int		 len;
18161d06d6bSBaptiste Daroussin 
18261d06d6bSBaptiste Daroussin 	if (n->child != NULL) {
18361d06d6bSBaptiste Daroussin 		if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
18461d06d6bSBaptiste Daroussin 			su.scale = 1.0;
18561d06d6bSBaptiste Daroussin 		len = term_vspan(p, &su);
18661d06d6bSBaptiste Daroussin 	} else
18761d06d6bSBaptiste Daroussin 		len = 1;
18861d06d6bSBaptiste Daroussin 
18961d06d6bSBaptiste Daroussin 	if (len < 0)
19061d06d6bSBaptiste Daroussin 		p->skipvsp -= len;
19161d06d6bSBaptiste Daroussin 	else
19261d06d6bSBaptiste Daroussin 		while (len--)
19361d06d6bSBaptiste Daroussin 			term_vspace(p);
19461d06d6bSBaptiste Daroussin 
19561d06d6bSBaptiste Daroussin 	roff_term_pre_br(p, n);
19661d06d6bSBaptiste Daroussin }
19761d06d6bSBaptiste Daroussin 
19861d06d6bSBaptiste Daroussin static void
19961d06d6bSBaptiste Daroussin roff_term_pre_ta(ROFF_TERM_ARGS)
20061d06d6bSBaptiste Daroussin {
20161d06d6bSBaptiste Daroussin 	term_tab_set(p, NULL);
20261d06d6bSBaptiste Daroussin 	for (n = n->child; n != NULL; n = n->next)
20361d06d6bSBaptiste Daroussin 		term_tab_set(p, n->string);
20461d06d6bSBaptiste Daroussin }
20561d06d6bSBaptiste Daroussin 
20661d06d6bSBaptiste Daroussin static void
20761d06d6bSBaptiste Daroussin roff_term_pre_ti(ROFF_TERM_ARGS)
20861d06d6bSBaptiste Daroussin {
20961d06d6bSBaptiste Daroussin 	struct roffsu	 su;
21061d06d6bSBaptiste Daroussin 	const char	*cp;
21161d06d6bSBaptiste Daroussin 	int		 len, sign;
21261d06d6bSBaptiste Daroussin 
21361d06d6bSBaptiste Daroussin 	roff_term_pre_br(p, n);
21461d06d6bSBaptiste Daroussin 
21561d06d6bSBaptiste Daroussin 	if (n->child == NULL)
21661d06d6bSBaptiste Daroussin 		return;
21761d06d6bSBaptiste Daroussin 	cp = n->child->string;
21861d06d6bSBaptiste Daroussin 	if (*cp == '+') {
21961d06d6bSBaptiste Daroussin 		sign = 1;
22061d06d6bSBaptiste Daroussin 		cp++;
22161d06d6bSBaptiste Daroussin 	} else if (*cp == '-') {
22261d06d6bSBaptiste Daroussin 		sign = -1;
22361d06d6bSBaptiste Daroussin 		cp++;
22461d06d6bSBaptiste Daroussin 	} else
22561d06d6bSBaptiste Daroussin 		sign = 0;
22661d06d6bSBaptiste Daroussin 
22761d06d6bSBaptiste Daroussin 	if (a2roffsu(cp, &su, SCALE_EM) == NULL)
22861d06d6bSBaptiste Daroussin 		return;
22961d06d6bSBaptiste Daroussin 	len = term_hen(p, &su);
23061d06d6bSBaptiste Daroussin 
23161d06d6bSBaptiste Daroussin 	if (sign == 0) {
23261d06d6bSBaptiste Daroussin 		p->ti = len - p->tcol->offset;
23361d06d6bSBaptiste Daroussin 		p->tcol->offset = len;
23461d06d6bSBaptiste Daroussin 	} else if (sign == 1) {
23561d06d6bSBaptiste Daroussin 		p->ti = len;
23661d06d6bSBaptiste Daroussin 		p->tcol->offset += len;
23761d06d6bSBaptiste Daroussin 	} else if ((size_t)len < p->tcol->offset) {
23861d06d6bSBaptiste Daroussin 		p->ti = -len;
23961d06d6bSBaptiste Daroussin 		p->tcol->offset -= len;
24061d06d6bSBaptiste Daroussin 	} else {
24161d06d6bSBaptiste Daroussin 		p->ti = -p->tcol->offset;
24261d06d6bSBaptiste Daroussin 		p->tcol->offset = 0;
24361d06d6bSBaptiste Daroussin 	}
24461d06d6bSBaptiste Daroussin }
245