]>
git.cameronkatri.com Git - mandoc.git/blob - out.c
1 /* $Id: out.c,v 1.56 2014/12/23 09:31:46 schwarze Exp $ */
3 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org>
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.
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.
20 #include <sys/types.h>
27 #include "mandoc_aux.h"
31 static void tblcalc_data(struct rofftbl
*, struct roffcol
*,
32 const struct tbl_opts
*, const struct tbl_dat
*);
33 static void tblcalc_literal(struct rofftbl
*, struct roffcol
*,
34 const struct tbl_dat
*);
35 static void tblcalc_number(struct rofftbl
*, struct roffcol
*,
36 const struct tbl_opts
*, const struct tbl_dat
*);
40 * Parse the *src string and store a scaling unit into *dst.
41 * If the string doesn't specify the unit, use the default.
42 * If no default is specified, fail.
43 * Return 2 on complete success, 1 when a conversion was done,
44 * but there was trailing garbage, and 0 on total failure.
47 a2roffsu(const char *src
, struct roffsu
*dst
, enum roffscale def
)
51 dst
->unit
= def
== SCALE_MAX
? SCALE_BU
: def
;
52 dst
->scale
= strtod(src
, &endptr
);
97 /* FIXME: do this in the caller. */
100 return(*endptr
== '\0' ? 2 : 1);
104 * Calculate the abstract widths and decimal positions of columns in a
105 * table. This routine allocates the columns structures then runs over
106 * all rows and cells in the table. The function pointers in "tbl" are
107 * used for the actual width calculations.
110 tblcalc(struct rofftbl
*tbl
, const struct tbl_span
*sp
,
113 const struct tbl_dat
*dp
;
115 size_t ewidth
, xwidth
;
117 int icol
, maxcol
, necol
, nxcol
;
120 * Allocate the master column specifiers. These will hold the
121 * widths and decimal positions for all cells in the column. It
122 * must be freed and nullified by the caller.
125 assert(NULL
== tbl
->cols
);
126 tbl
->cols
= mandoc_calloc((size_t)sp
->opts
->cols
,
127 sizeof(struct roffcol
));
129 for (maxcol
= -1; sp
; sp
= sp
->next
) {
130 if (TBL_SPAN_DATA
!= sp
->pos
)
134 * Account for the data cells in the layout, matching it
135 * to data cells in the data section.
137 for (dp
= sp
->first
; dp
; dp
= dp
->next
) {
138 /* Do not used spanned cells in the calculation. */
144 icol
= dp
->layout
->head
->ident
;
147 col
= tbl
->cols
+ icol
;
148 col
->flags
|= dp
->layout
->flags
;
149 if (dp
->layout
->flags
& TBL_CELL_WIGN
)
151 tblcalc_data(tbl
, col
, sp
->opts
, dp
);
156 * Count columns to equalize and columns to maximize.
157 * Find maximum width of the columns to equalize.
158 * Find total width of the columns *not* to maximize.
163 for (icol
= 0; icol
<= maxcol
; icol
++) {
164 col
= tbl
->cols
+ icol
;
165 if (col
->flags
& TBL_CELL_EQUAL
) {
167 if (ewidth
< col
->width
)
170 if (col
->flags
& TBL_CELL_WMAX
)
173 xwidth
+= col
->width
;
177 * Equalize columns, if requested for any of them.
178 * Update total width of the columns not to maximize.
182 for (icol
= 0; icol
<= maxcol
; icol
++) {
183 col
= tbl
->cols
+ icol
;
184 if ( ! (col
->flags
& TBL_CELL_EQUAL
))
186 if (col
->width
== ewidth
)
188 if (nxcol
&& totalwidth
)
189 xwidth
+= ewidth
- col
->width
;
195 * If there are any columns to maximize, find the total
196 * available width, deducting 3n margins between columns.
197 * Distribute the available width evenly.
200 if (nxcol
&& totalwidth
) {
201 xwidth
= totalwidth
- 3*maxcol
- xwidth
;
202 for (icol
= 0; icol
<= maxcol
; icol
++) {
203 col
= tbl
->cols
+ icol
;
204 if ( ! (col
->flags
& TBL_CELL_WMAX
))
206 col
->width
= xwidth
/ nxcol
--;
207 xwidth
-= col
->width
;
213 tblcalc_data(struct rofftbl
*tbl
, struct roffcol
*col
,
214 const struct tbl_opts
*opts
, const struct tbl_dat
*dp
)
218 /* Branch down into data sub-types. */
220 switch (dp
->layout
->pos
) {
223 case TBL_CELL_DHORIZ
:
224 sz
= (*tbl
->len
)(1, tbl
->arg
);
230 case TBL_CELL_CENTRE
:
235 tblcalc_literal(tbl
, col
, dp
);
237 case TBL_CELL_NUMBER
:
238 tblcalc_number(tbl
, col
, opts
, dp
);
249 tblcalc_literal(struct rofftbl
*tbl
, struct roffcol
*col
,
250 const struct tbl_dat
*dp
)
255 str
= dp
->string
? dp
->string
: "";
256 sz
= (*tbl
->slen
)(str
, tbl
->arg
);
263 tblcalc_number(struct rofftbl
*tbl
, struct roffcol
*col
,
264 const struct tbl_opts
*opts
, const struct tbl_dat
*dp
)
267 size_t sz
, psz
, ssz
, d
;
273 * First calculate number width and decimal place (last + 1 for
274 * non-decimal numbers). If the stored decimal is subsequent to
275 * ours, make our size longer by that difference
276 * (right-"shifting"); similarly, if ours is subsequent the
277 * stored, then extend the stored size by the difference.
278 * Finally, re-assign the stored values.
281 str
= dp
->string
? dp
->string
: "";
282 sz
= (*tbl
->slen
)(str
, tbl
->arg
);
284 /* FIXME: TBL_DATA_HORIZ et al.? */
286 buf
[0] = opts
->decimal
;
289 psz
= (*tbl
->slen
)(buf
, tbl
->arg
);
291 if (NULL
!= (cp
= strrchr(str
, opts
->decimal
))) {
293 for (ssz
= 0, i
= 0; cp
!= &str
[i
]; i
++) {
295 ssz
+= (*tbl
->slen
)(buf
, tbl
->arg
);
301 /* Adjust the settings for this column. */
303 if (col
->decimal
> d
) {
304 sz
+= col
->decimal
- d
;
307 col
->width
+= d
- col
->decimal
;
311 if (d
> col
->decimal
)