xref: /netbsd-src/external/bsd/mdocml/dist/roff_term.c (revision 544c191c349c1704c9d5e679d12ec15cff579663)
1*544c191cSchristos /*	Id: roff_term.c,v 1.19 2019/01/04 03:24:33 schwarze Exp  */
2c9bcef03Schristos /*
3*544c191cSchristos  * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
4c9bcef03Schristos  *
5c9bcef03Schristos  * Permission to use, copy, modify, and distribute this software for any
6c9bcef03Schristos  * purpose with or without fee is hereby granted, provided that the above
7c9bcef03Schristos  * copyright notice and this permission notice appear in all copies.
8c9bcef03Schristos  *
9c9bcef03Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10c9bcef03Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11c9bcef03Schristos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12c9bcef03Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13c9bcef03Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14c9bcef03Schristos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15c9bcef03Schristos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16c9bcef03Schristos  */
17c9bcef03Schristos #include <sys/types.h>
18c9bcef03Schristos 
19c9bcef03Schristos #include <assert.h>
20*544c191cSchristos #include <stdio.h>
21*544c191cSchristos #include <string.h>
22c9bcef03Schristos 
23c9bcef03Schristos #include "mandoc.h"
24c9bcef03Schristos #include "roff.h"
25c9bcef03Schristos #include "out.h"
26c9bcef03Schristos #include "term.h"
27c9bcef03Schristos 
28c9bcef03Schristos #define	ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
29c9bcef03Schristos 
30c9bcef03Schristos typedef	void	(*roff_term_pre_fp)(ROFF_TERM_ARGS);
31c9bcef03Schristos 
32c9bcef03Schristos static	void	  roff_term_pre_br(ROFF_TERM_ARGS);
33c9bcef03Schristos static	void	  roff_term_pre_ce(ROFF_TERM_ARGS);
34c9bcef03Schristos static	void	  roff_term_pre_ft(ROFF_TERM_ARGS);
35c9bcef03Schristos static	void	  roff_term_pre_ll(ROFF_TERM_ARGS);
36c9bcef03Schristos static	void	  roff_term_pre_mc(ROFF_TERM_ARGS);
37c9bcef03Schristos static	void	  roff_term_pre_po(ROFF_TERM_ARGS);
38c9bcef03Schristos static	void	  roff_term_pre_sp(ROFF_TERM_ARGS);
39c9bcef03Schristos static	void	  roff_term_pre_ta(ROFF_TERM_ARGS);
40c9bcef03Schristos static	void	  roff_term_pre_ti(ROFF_TERM_ARGS);
41c9bcef03Schristos 
42c9bcef03Schristos static	const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
43c9bcef03Schristos 	roff_term_pre_br,  /* br */
44c9bcef03Schristos 	roff_term_pre_ce,  /* ce */
45*544c191cSchristos 	roff_term_pre_br,  /* fi */
46c9bcef03Schristos 	roff_term_pre_ft,  /* ft */
47c9bcef03Schristos 	roff_term_pre_ll,  /* ll */
48c9bcef03Schristos 	roff_term_pre_mc,  /* mc */
49*544c191cSchristos 	roff_term_pre_br,  /* nf */
50c9bcef03Schristos 	roff_term_pre_po,  /* po */
51c9bcef03Schristos 	roff_term_pre_ce,  /* rj */
52c9bcef03Schristos 	roff_term_pre_sp,  /* sp */
53c9bcef03Schristos 	roff_term_pre_ta,  /* ta */
54c9bcef03Schristos 	roff_term_pre_ti,  /* ti */
55c9bcef03Schristos };
56c9bcef03Schristos 
57c9bcef03Schristos 
58c9bcef03Schristos void
roff_term_pre(struct termp * p,const struct roff_node * n)59c9bcef03Schristos roff_term_pre(struct termp *p, const struct roff_node *n)
60c9bcef03Schristos {
61c9bcef03Schristos 	assert(n->tok < ROFF_MAX);
62c9bcef03Schristos 	(*roff_term_pre_acts[n->tok])(p, n);
63c9bcef03Schristos }
64c9bcef03Schristos 
65c9bcef03Schristos static void
roff_term_pre_br(ROFF_TERM_ARGS)66c9bcef03Schristos roff_term_pre_br(ROFF_TERM_ARGS)
67c9bcef03Schristos {
68c9bcef03Schristos 	term_newln(p);
69c9bcef03Schristos 	if (p->flags & TERMP_BRIND) {
70c9bcef03Schristos 		p->tcol->offset = p->tcol->rmargin;
71c9bcef03Schristos 		p->tcol->rmargin = p->maxrmargin;
72*544c191cSchristos 		p->trailspace = 0;
73c9bcef03Schristos 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
74*544c191cSchristos 		p->flags |= TERMP_NOSPACE;
75c9bcef03Schristos 	}
76c9bcef03Schristos }
77c9bcef03Schristos 
78c9bcef03Schristos static void
roff_term_pre_ce(ROFF_TERM_ARGS)79c9bcef03Schristos roff_term_pre_ce(ROFF_TERM_ARGS)
80c9bcef03Schristos {
81c9bcef03Schristos 	const struct roff_node	*nc1, *nc2;
82c9bcef03Schristos 
83c9bcef03Schristos 	roff_term_pre_br(p, n);
84*544c191cSchristos 	p->flags |= n->tok == ROFF_ce ? TERMP_CENTER : TERMP_RIGHT;
85c9bcef03Schristos 	nc1 = n->child->next;
86c9bcef03Schristos 	while (nc1 != NULL) {
87c9bcef03Schristos 		nc2 = nc1;
88c9bcef03Schristos 		do {
89c9bcef03Schristos 			nc2 = nc2->next;
90c9bcef03Schristos 		} while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
91c9bcef03Schristos 		    (nc2->flags & NODE_LINE) == 0));
92c9bcef03Schristos 		while (nc1 != nc2) {
93c9bcef03Schristos 			if (nc1->type == ROFFT_TEXT)
94c9bcef03Schristos 				term_word(p, nc1->string);
95c9bcef03Schristos 			else
96c9bcef03Schristos 				roff_term_pre(p, nc1);
97c9bcef03Schristos 			nc1 = nc1->next;
98c9bcef03Schristos 		}
99c9bcef03Schristos 		p->flags |= TERMP_NOSPACE;
100c9bcef03Schristos 		term_flushln(p);
101c9bcef03Schristos 	}
102*544c191cSchristos 	p->flags &= ~(TERMP_CENTER | TERMP_RIGHT);
103c9bcef03Schristos }
104c9bcef03Schristos 
105c9bcef03Schristos static void
roff_term_pre_ft(ROFF_TERM_ARGS)106c9bcef03Schristos roff_term_pre_ft(ROFF_TERM_ARGS)
107c9bcef03Schristos {
108*544c191cSchristos 	const char	*cp;
109*544c191cSchristos 
110*544c191cSchristos 	cp = n->child->string;
111*544c191cSchristos 	switch (mandoc_font(cp, (int)strlen(cp))) {
112*544c191cSchristos 	case ESCAPE_FONTBOLD:
113c9bcef03Schristos 		term_fontrepl(p, TERMFONT_BOLD);
114c9bcef03Schristos 		break;
115*544c191cSchristos 	case ESCAPE_FONTITALIC:
116c9bcef03Schristos 		term_fontrepl(p, TERMFONT_UNDER);
117c9bcef03Schristos 		break;
118*544c191cSchristos 	case ESCAPE_FONTBI:
119*544c191cSchristos 		term_fontrepl(p, TERMFONT_BI);
120*544c191cSchristos 		break;
121*544c191cSchristos 	case ESCAPE_FONTPREV:
122c9bcef03Schristos 		term_fontlast(p);
123c9bcef03Schristos 		break;
124*544c191cSchristos 	case ESCAPE_FONTROMAN:
125*544c191cSchristos 	case ESCAPE_FONTCW:
126c9bcef03Schristos 		term_fontrepl(p, TERMFONT_NONE);
127c9bcef03Schristos 		break;
128c9bcef03Schristos 	default:
129c9bcef03Schristos 		break;
130c9bcef03Schristos 	}
131c9bcef03Schristos }
132c9bcef03Schristos 
133c9bcef03Schristos static void
roff_term_pre_ll(ROFF_TERM_ARGS)134c9bcef03Schristos roff_term_pre_ll(ROFF_TERM_ARGS)
135c9bcef03Schristos {
136c9bcef03Schristos 	term_setwidth(p, n->child != NULL ? n->child->string : NULL);
137c9bcef03Schristos }
138c9bcef03Schristos 
139c9bcef03Schristos static void
roff_term_pre_mc(ROFF_TERM_ARGS)140c9bcef03Schristos roff_term_pre_mc(ROFF_TERM_ARGS)
141c9bcef03Schristos {
142c9bcef03Schristos 	if (p->col) {
143c9bcef03Schristos 		p->flags |= TERMP_NOBREAK;
144c9bcef03Schristos 		term_flushln(p);
145c9bcef03Schristos 		p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
146c9bcef03Schristos 	}
147c9bcef03Schristos 	if (n->child != NULL) {
148c9bcef03Schristos 		p->mc = n->child->string;
149c9bcef03Schristos 		p->flags |= TERMP_NEWMC;
150c9bcef03Schristos 	} else
151c9bcef03Schristos 		p->flags |= TERMP_ENDMC;
152c9bcef03Schristos }
153c9bcef03Schristos 
154c9bcef03Schristos static void
roff_term_pre_po(ROFF_TERM_ARGS)155c9bcef03Schristos roff_term_pre_po(ROFF_TERM_ARGS)
156c9bcef03Schristos {
157c9bcef03Schristos 	struct roffsu	 su;
158c9bcef03Schristos 	static int	 po, polast;
159c9bcef03Schristos 	int		 ponew;
160c9bcef03Schristos 
161c9bcef03Schristos 	if (n->child != NULL &&
162c9bcef03Schristos 	    a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
163c9bcef03Schristos 		ponew = term_hen(p, &su);
164c9bcef03Schristos 		if (*n->child->string == '+' ||
165c9bcef03Schristos 		    *n->child->string == '-')
166c9bcef03Schristos 			ponew += po;
167c9bcef03Schristos 	} else
168c9bcef03Schristos 		ponew = polast;
169c9bcef03Schristos 	polast = po;
170c9bcef03Schristos 	po = ponew;
171c9bcef03Schristos 
172c9bcef03Schristos 	ponew = po - polast + (int)p->tcol->offset;
173c9bcef03Schristos 	p->tcol->offset = ponew > 0 ? ponew : 0;
174c9bcef03Schristos }
175c9bcef03Schristos 
176c9bcef03Schristos static void
roff_term_pre_sp(ROFF_TERM_ARGS)177c9bcef03Schristos roff_term_pre_sp(ROFF_TERM_ARGS)
178c9bcef03Schristos {
179c9bcef03Schristos 	struct roffsu	 su;
180c9bcef03Schristos 	int		 len;
181c9bcef03Schristos 
182c9bcef03Schristos 	if (n->child != NULL) {
183c9bcef03Schristos 		if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
184c9bcef03Schristos 			su.scale = 1.0;
185c9bcef03Schristos 		len = term_vspan(p, &su);
186c9bcef03Schristos 	} else
187c9bcef03Schristos 		len = 1;
188c9bcef03Schristos 
189c9bcef03Schristos 	if (len < 0)
190c9bcef03Schristos 		p->skipvsp -= len;
191c9bcef03Schristos 	else
192c9bcef03Schristos 		while (len--)
193c9bcef03Schristos 			term_vspace(p);
194c9bcef03Schristos 
195c9bcef03Schristos 	roff_term_pre_br(p, n);
196c9bcef03Schristos }
197c9bcef03Schristos 
198c9bcef03Schristos static void
roff_term_pre_ta(ROFF_TERM_ARGS)199c9bcef03Schristos roff_term_pre_ta(ROFF_TERM_ARGS)
200c9bcef03Schristos {
201c9bcef03Schristos 	term_tab_set(p, NULL);
202c9bcef03Schristos 	for (n = n->child; n != NULL; n = n->next)
203c9bcef03Schristos 		term_tab_set(p, n->string);
204c9bcef03Schristos }
205c9bcef03Schristos 
206c9bcef03Schristos static void
roff_term_pre_ti(ROFF_TERM_ARGS)207c9bcef03Schristos roff_term_pre_ti(ROFF_TERM_ARGS)
208c9bcef03Schristos {
209c9bcef03Schristos 	struct roffsu	 su;
210c9bcef03Schristos 	const char	*cp;
211c9bcef03Schristos 	int		 len, sign;
212c9bcef03Schristos 
213c9bcef03Schristos 	roff_term_pre_br(p, n);
214c9bcef03Schristos 
215c9bcef03Schristos 	if (n->child == NULL)
216c9bcef03Schristos 		return;
217c9bcef03Schristos 	cp = n->child->string;
218c9bcef03Schristos 	if (*cp == '+') {
219c9bcef03Schristos 		sign = 1;
220c9bcef03Schristos 		cp++;
221c9bcef03Schristos 	} else if (*cp == '-') {
222c9bcef03Schristos 		sign = -1;
223c9bcef03Schristos 		cp++;
224c9bcef03Schristos 	} else
225c9bcef03Schristos 		sign = 0;
226c9bcef03Schristos 
227c9bcef03Schristos 	if (a2roffsu(cp, &su, SCALE_EM) == NULL)
228c9bcef03Schristos 		return;
229c9bcef03Schristos 	len = term_hen(p, &su);
230c9bcef03Schristos 
231c9bcef03Schristos 	if (sign == 0) {
232c9bcef03Schristos 		p->ti = len - p->tcol->offset;
233c9bcef03Schristos 		p->tcol->offset = len;
234c9bcef03Schristos 	} else if (sign == 1) {
235c9bcef03Schristos 		p->ti = len;
236c9bcef03Schristos 		p->tcol->offset += len;
237c9bcef03Schristos 	} else if ((size_t)len < p->tcol->offset) {
238c9bcef03Schristos 		p->ti = -len;
239c9bcef03Schristos 		p->tcol->offset -= len;
240c9bcef03Schristos 	} else {
241c9bcef03Schristos 		p->ti = -p->tcol->offset;
242c9bcef03Schristos 		p->tcol->offset = 0;
243c9bcef03Schristos 	}
244c9bcef03Schristos }
245