]> git.cameronkatri.com Git - mandoc.git/blob - out.c
Implement the roff(7) .rr (remove register) request.
[mandoc.git] / out.c
1 /* $Id: out.c,v 1.47 2014/03/23 11:25:26 schwarze Exp $ */
2 /*
3 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <sys/types.h>
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "mandoc_aux.h"
32 #include "mandoc.h"
33 #include "out.h"
34
35 static void tblcalc_data(struct rofftbl *, struct roffcol *,
36 const struct tbl_opts *, const struct tbl_dat *);
37 static void tblcalc_literal(struct rofftbl *, struct roffcol *,
38 const struct tbl_dat *);
39 static void tblcalc_number(struct rofftbl *, struct roffcol *,
40 const struct tbl_opts *, const struct tbl_dat *);
41
42 /*
43 * Convert a `scaling unit' to a consistent form, or fail. Scaling
44 * units are documented in groff.7, mdoc.7, man.7.
45 */
46 int
47 a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
48 {
49 char buf[BUFSIZ], hasd;
50 int i;
51 enum roffscale unit;
52
53 if ('\0' == *src)
54 return(0);
55
56 i = hasd = 0;
57
58 switch (*src) {
59 case ('+'):
60 src++;
61 break;
62 case ('-'):
63 buf[i++] = *src++;
64 break;
65 default:
66 break;
67 }
68
69 if ('\0' == *src)
70 return(0);
71
72 while (i < BUFSIZ) {
73 if ( ! isdigit((unsigned char)*src)) {
74 if ('.' != *src)
75 break;
76 else if (hasd)
77 break;
78 else
79 hasd = 1;
80 }
81 buf[i++] = *src++;
82 }
83
84 if (BUFSIZ == i || (*src && *(src + 1)))
85 return(0);
86
87 buf[i] = '\0';
88
89 switch (*src) {
90 case ('c'):
91 unit = SCALE_CM;
92 break;
93 case ('i'):
94 unit = SCALE_IN;
95 break;
96 case ('P'):
97 unit = SCALE_PC;
98 break;
99 case ('p'):
100 unit = SCALE_PT;
101 break;
102 case ('f'):
103 unit = SCALE_FS;
104 break;
105 case ('v'):
106 unit = SCALE_VS;
107 break;
108 case ('m'):
109 unit = SCALE_EM;
110 break;
111 case ('\0'):
112 if (SCALE_MAX == def)
113 return(0);
114 unit = SCALE_BU;
115 break;
116 case ('u'):
117 unit = SCALE_BU;
118 break;
119 case ('M'):
120 unit = SCALE_MM;
121 break;
122 case ('n'):
123 unit = SCALE_EN;
124 break;
125 default:
126 return(0);
127 }
128
129 /* FIXME: do this in the caller. */
130 if ((dst->scale = atof(buf)) < 0)
131 dst->scale = 0;
132 dst->unit = unit;
133 return(1);
134 }
135
136 /*
137 * Calculate the abstract widths and decimal positions of columns in a
138 * table. This routine allocates the columns structures then runs over
139 * all rows and cells in the table. The function pointers in "tbl" are
140 * used for the actual width calculations.
141 */
142 void
143 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
144 {
145 const struct tbl_dat *dp;
146 struct roffcol *col;
147 int spans;
148
149 /*
150 * Allocate the master column specifiers. These will hold the
151 * widths and decimal positions for all cells in the column. It
152 * must be freed and nullified by the caller.
153 */
154
155 assert(NULL == tbl->cols);
156 tbl->cols = mandoc_calloc
157 ((size_t)sp->opts->cols, sizeof(struct roffcol));
158
159 for ( ; sp; sp = sp->next) {
160 if (TBL_SPAN_DATA != sp->pos)
161 continue;
162 spans = 1;
163 /*
164 * Account for the data cells in the layout, matching it
165 * to data cells in the data section.
166 */
167 for (dp = sp->first; dp; dp = dp->next) {
168 /* Do not used spanned cells in the calculation. */
169 if (0 < --spans)
170 continue;
171 spans = dp->spans;
172 if (1 < spans)
173 continue;
174 assert(dp->layout);
175 col = &tbl->cols[dp->layout->head->ident];
176 tblcalc_data(tbl, col, sp->opts, dp);
177 }
178 }
179 }
180
181 static void
182 tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
183 const struct tbl_opts *opts, const struct tbl_dat *dp)
184 {
185 size_t sz;
186
187 /* Branch down into data sub-types. */
188
189 switch (dp->layout->pos) {
190 case (TBL_CELL_HORIZ):
191 /* FALLTHROUGH */
192 case (TBL_CELL_DHORIZ):
193 sz = (*tbl->len)(1, tbl->arg);
194 if (col->width < sz)
195 col->width = sz;
196 break;
197 case (TBL_CELL_LONG):
198 /* FALLTHROUGH */
199 case (TBL_CELL_CENTRE):
200 /* FALLTHROUGH */
201 case (TBL_CELL_LEFT):
202 /* FALLTHROUGH */
203 case (TBL_CELL_RIGHT):
204 tblcalc_literal(tbl, col, dp);
205 break;
206 case (TBL_CELL_NUMBER):
207 tblcalc_number(tbl, col, opts, dp);
208 break;
209 case (TBL_CELL_DOWN):
210 break;
211 default:
212 abort();
213 /* NOTREACHED */
214 }
215 }
216
217 static void
218 tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
219 const struct tbl_dat *dp)
220 {
221 size_t sz;
222 const char *str;
223
224 str = dp->string ? dp->string : "";
225 sz = (*tbl->slen)(str, tbl->arg);
226
227 if (col->width < sz)
228 col->width = sz;
229 }
230
231 static void
232 tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
233 const struct tbl_opts *opts, const struct tbl_dat *dp)
234 {
235 int i;
236 size_t sz, psz, ssz, d;
237 const char *str;
238 char *cp;
239 char buf[2];
240
241 /*
242 * First calculate number width and decimal place (last + 1 for
243 * non-decimal numbers). If the stored decimal is subsequent to
244 * ours, make our size longer by that difference
245 * (right-"shifting"); similarly, if ours is subsequent the
246 * stored, then extend the stored size by the difference.
247 * Finally, re-assign the stored values.
248 */
249
250 str = dp->string ? dp->string : "";
251 sz = (*tbl->slen)(str, tbl->arg);
252
253 /* FIXME: TBL_DATA_HORIZ et al.? */
254
255 buf[0] = opts->decimal;
256 buf[1] = '\0';
257
258 psz = (*tbl->slen)(buf, tbl->arg);
259
260 if (NULL != (cp = strrchr(str, opts->decimal))) {
261 buf[1] = '\0';
262 for (ssz = 0, i = 0; cp != &str[i]; i++) {
263 buf[0] = str[i];
264 ssz += (*tbl->slen)(buf, tbl->arg);
265 }
266 d = ssz + psz;
267 } else
268 d = sz + psz;
269
270 /* Adjust the settings for this column. */
271
272 if (col->decimal > d) {
273 sz += col->decimal - d;
274 d = col->decimal;
275 } else
276 col->width += d - col->decimal;
277
278 if (sz > col->width)
279 col->width = sz;
280 if (d > col->decimal)
281 col->decimal = d;
282 }