GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/roff_term.c Lines: 73 108 67.6 %
Date: 2017-11-07 Branches: 38 74 51.4 %

Line Branch Exec Source
1
/*	$OpenBSD: roff_term.c,v 1.14 2017/06/24 14:38:28 schwarze Exp $ */
2
/*
3
 * Copyright (c) 2010, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
#include <sys/types.h>
18
19
#include <assert.h>
20
#include <stddef.h>
21
22
#include "mandoc.h"
23
#include "roff.h"
24
#include "out.h"
25
#include "term.h"
26
27
#define	ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
28
29
typedef	void	(*roff_term_pre_fp)(ROFF_TERM_ARGS);
30
31
static	void	  roff_term_pre_br(ROFF_TERM_ARGS);
32
static	void	  roff_term_pre_ce(ROFF_TERM_ARGS);
33
static	void	  roff_term_pre_ft(ROFF_TERM_ARGS);
34
static	void	  roff_term_pre_ll(ROFF_TERM_ARGS);
35
static	void	  roff_term_pre_mc(ROFF_TERM_ARGS);
36
static	void	  roff_term_pre_po(ROFF_TERM_ARGS);
37
static	void	  roff_term_pre_sp(ROFF_TERM_ARGS);
38
static	void	  roff_term_pre_ta(ROFF_TERM_ARGS);
39
static	void	  roff_term_pre_ti(ROFF_TERM_ARGS);
40
41
static	const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
42
	roff_term_pre_br,  /* br */
43
	roff_term_pre_ce,  /* ce */
44
	roff_term_pre_ft,  /* ft */
45
	roff_term_pre_ll,  /* ll */
46
	roff_term_pre_mc,  /* mc */
47
	roff_term_pre_po,  /* po */
48
	roff_term_pre_ce,  /* rj */
49
	roff_term_pre_sp,  /* sp */
50
	roff_term_pre_ta,  /* ta */
51
	roff_term_pre_ti,  /* ti */
52
};
53
54
55
void
56
roff_term_pre(struct termp *p, const struct roff_node *n)
57
{
58
24444
	assert(n->tok < ROFF_MAX);
59
12222
	(*roff_term_pre_acts[n->tok])(p, n);
60
12222
}
61
62
static void
63
roff_term_pre_br(ROFF_TERM_ARGS)
64
{
65
23814
	term_newln(p);
66
11907
	if (p->flags & TERMP_BRIND) {
67
117
		p->tcol->offset = p->tcol->rmargin;
68
117
		p->tcol->rmargin = p->maxrmargin;
69
117
		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
70
117
	}
71
11907
}
72
73
static void
74
roff_term_pre_ce(ROFF_TERM_ARGS)
75
{
76
	const struct roff_node	*nc1, *nc2;
77
	size_t			 len, lm;
78
79
	roff_term_pre_br(p, n);
80
	lm = p->tcol->offset;
81
	nc1 = n->child->next;
82
	while (nc1 != NULL) {
83
		nc2 = nc1;
84
		len = 0;
85
		do {
86
			if (nc2->type == ROFFT_TEXT) {
87
				if (len)
88
					len++;
89
				len += term_strlen(p, nc2->string);
90
			}
91
			nc2 = nc2->next;
92
		} while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
93
		    (nc2->flags & NODE_LINE) == 0));
94
		p->tcol->offset = len >= p->tcol->rmargin ? 0 :
95
		    lm + len >= p->tcol->rmargin ? p->tcol->rmargin - len :
96
		    n->tok == ROFF_rj ? p->tcol->rmargin - len :
97
		    (lm + p->tcol->rmargin - len) / 2;
98
		while (nc1 != nc2) {
99
			if (nc1->type == ROFFT_TEXT)
100
				term_word(p, nc1->string);
101
			else
102
				roff_term_pre(p, nc1);
103
			nc1 = nc1->next;
104
		}
105
		p->flags |= TERMP_NOSPACE;
106
		term_flushln(p);
107
	}
108
	p->tcol->offset = lm;
109
}
110
111
static void
112
roff_term_pre_ft(ROFF_TERM_ARGS)
113
{
114


324
	switch (*n->child->string) {
115
	case '4':
116
	case '3':
117
	case 'B':
118
27
		term_fontrepl(p, TERMFONT_BOLD);
119
27
		break;
120
	case '2':
121
	case 'I':
122
27
		term_fontrepl(p, TERMFONT_UNDER);
123
27
		break;
124
	case 'P':
125
54
		term_fontlast(p);
126
54
		break;
127
	case '1':
128
	case 'C':
129
	case 'R':
130
		term_fontrepl(p, TERMFONT_NONE);
131
		break;
132
	default:
133
		break;
134
	}
135
108
}
136
137
static void
138
roff_term_pre_ll(ROFF_TERM_ARGS)
139
{
140
342
	term_setwidth(p, n->child != NULL ? n->child->string : NULL);
141
90
}
142
143
static void
144
roff_term_pre_mc(ROFF_TERM_ARGS)
145
{
146
	if (p->col) {
147
		p->flags |= TERMP_NOBREAK;
148
		term_flushln(p);
149
		p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
150
	}
151
	if (n->child != NULL) {
152
		p->mc = n->child->string;
153
		p->flags |= TERMP_NEWMC;
154
	} else
155
		p->flags |= TERMP_ENDMC;
156
}
157
158
static void
159
roff_term_pre_po(ROFF_TERM_ARGS)
160
{
161
72
	struct roffsu	 su;
162
	static int	 po, polast;
163
	int		 ponew;
164
165

72
	if (n->child != NULL &&
166
36
	    a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
167
27
		ponew = term_hen(p, &su);
168

45
		if (*n->child->string == '+' ||
169
18
		    *n->child->string == '-')
170
18
			ponew += po;
171
	} else
172
9
		ponew = polast;
173
36
	polast = po;
174
36
	po = ponew;
175
176
36
	ponew = po - polast + (int)p->tcol->offset;
177
36
	p->tcol->offset = ponew > 0 ? ponew : 0;
178
36
}
179
180
static void
181
roff_term_pre_sp(ROFF_TERM_ARGS)
182
{
183
14328
	struct roffsu	 su;
184
	int		 len;
185
186
7164
	if (n->child != NULL) {
187
2628
		if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
188
18
			su.scale = 1.0;
189
2628
		len = term_vspan(p, &su);
190
2628
	} else
191
		len = 1;
192
193
7164
	if (len < 0)
194
9
		p->skipvsp -= len;
195
	else
196
26145
		while (len--)
197
9495
			term_vspace(p);
198
199
7164
	roff_term_pre_br(p, n);
200
7164
}
201
202
static void
203
roff_term_pre_ta(ROFF_TERM_ARGS)
204
{
205
162
	term_tab_set(p, NULL);
206
540
	for (n = n->child; n != NULL; n = n->next)
207
189
		term_tab_set(p, n->string);
208
81
}
209
210
static void
211
roff_term_pre_ti(ROFF_TERM_ARGS)
212
{
213
144
	struct roffsu	 su;
214
	const char	*cp;
215
	int		 len, sign;
216
217
72
	roff_term_pre_br(p, n);
218
219
72
	if (n->child == NULL)
220
		return;
221
72
	cp = n->child->string;
222
72
	if (*cp == '+') {
223
		sign = 1;
224
18
		cp++;
225
72
	} else if (*cp == '-') {
226
		sign = -1;
227
36
		cp++;
228
36
	} else
229
		sign = 0;
230
231
72
	if (a2roffsu(cp, &su, SCALE_EM) == NULL)
232
		return;
233
72
	len = term_hen(p, &su);
234
235
72
	if (sign == 0) {
236
18
		p->ti = len - p->tcol->offset;
237
18
		p->tcol->offset = len;
238
72
	} else if (sign == 1) {
239
18
		p->ti = len;
240
18
		p->tcol->offset += len;
241
54
	} else if ((size_t)len < p->tcol->offset) {
242
18
		p->ti = -len;
243
18
		p->tcol->offset -= len;
244
18
	} else {
245
18
		p->ti = -p->tcol->offset;
246
18
		p->tcol->offset = 0;
247
	}
248
144
}