]> git.cameronkatri.com Git - mandoc.git/blob - roff_term.c
Do not allocate a column for decimal points if all numbers are integers.
[mandoc.git] / roff_term.c
1 /* $Id: roff_term.c,v 1.15 2018/08/10 20:40:45 schwarze Exp $ */
2 /*
3 * Copyright (c) 2010,2014,2015,2017,2018 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 assert(n->tok < ROFF_MAX);
59 (*roff_term_pre_acts[n->tok])(p, n);
60 }
61
62 static void
63 roff_term_pre_br(ROFF_TERM_ARGS)
64 {
65 term_newln(p);
66 if (p->flags & TERMP_BRIND) {
67 p->tcol->offset = p->tcol->rmargin;
68 p->tcol->rmargin = p->maxrmargin;
69 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
70 }
71 }
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 const char *cp;
115
116 if (*(cp = n->child->string) == 'C')
117 cp++;
118
119 switch (*cp) {
120 case '4':
121 case '3':
122 case 'B':
123 term_fontrepl(p, TERMFONT_BOLD);
124 break;
125 case '2':
126 case 'I':
127 term_fontrepl(p, TERMFONT_UNDER);
128 break;
129 case 'P':
130 term_fontlast(p);
131 break;
132 case '1':
133 case 'C':
134 case 'R':
135 term_fontrepl(p, TERMFONT_NONE);
136 break;
137 default:
138 break;
139 }
140 }
141
142 static void
143 roff_term_pre_ll(ROFF_TERM_ARGS)
144 {
145 term_setwidth(p, n->child != NULL ? n->child->string : NULL);
146 }
147
148 static void
149 roff_term_pre_mc(ROFF_TERM_ARGS)
150 {
151 if (p->col) {
152 p->flags |= TERMP_NOBREAK;
153 term_flushln(p);
154 p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
155 }
156 if (n->child != NULL) {
157 p->mc = n->child->string;
158 p->flags |= TERMP_NEWMC;
159 } else
160 p->flags |= TERMP_ENDMC;
161 }
162
163 static void
164 roff_term_pre_po(ROFF_TERM_ARGS)
165 {
166 struct roffsu su;
167 static int po, polast;
168 int ponew;
169
170 if (n->child != NULL &&
171 a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
172 ponew = term_hen(p, &su);
173 if (*n->child->string == '+' ||
174 *n->child->string == '-')
175 ponew += po;
176 } else
177 ponew = polast;
178 polast = po;
179 po = ponew;
180
181 ponew = po - polast + (int)p->tcol->offset;
182 p->tcol->offset = ponew > 0 ? ponew : 0;
183 }
184
185 static void
186 roff_term_pre_sp(ROFF_TERM_ARGS)
187 {
188 struct roffsu su;
189 int len;
190
191 if (n->child != NULL) {
192 if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
193 su.scale = 1.0;
194 len = term_vspan(p, &su);
195 } else
196 len = 1;
197
198 if (len < 0)
199 p->skipvsp -= len;
200 else
201 while (len--)
202 term_vspace(p);
203
204 roff_term_pre_br(p, n);
205 }
206
207 static void
208 roff_term_pre_ta(ROFF_TERM_ARGS)
209 {
210 term_tab_set(p, NULL);
211 for (n = n->child; n != NULL; n = n->next)
212 term_tab_set(p, n->string);
213 }
214
215 static void
216 roff_term_pre_ti(ROFF_TERM_ARGS)
217 {
218 struct roffsu su;
219 const char *cp;
220 int len, sign;
221
222 roff_term_pre_br(p, n);
223
224 if (n->child == NULL)
225 return;
226 cp = n->child->string;
227 if (*cp == '+') {
228 sign = 1;
229 cp++;
230 } else if (*cp == '-') {
231 sign = -1;
232 cp++;
233 } else
234 sign = 0;
235
236 if (a2roffsu(cp, &su, SCALE_EM) == NULL)
237 return;
238 len = term_hen(p, &su);
239
240 if (sign == 0) {
241 p->ti = len - p->tcol->offset;
242 p->tcol->offset = len;
243 } else if (sign == 1) {
244 p->ti = len;
245 p->tcol->offset += len;
246 } else if ((size_t)len < p->tcol->offset) {
247 p->ti = -len;
248 p->tcol->offset -= len;
249 } else {
250 p->ti = -p->tcol->offset;
251 p->tcol->offset = 0;
252 }
253 }