]>
git.cameronkatri.com Git - mandoc.git/blob - tbl.c
1 /* $Id: tbl.c,v 1.19 2011/01/02 20:34:05 kristaps Exp $ */
3 * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
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.
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.
25 #include "libmandoc.h"
28 static void tbl_calc(struct tbl_node
*);
29 static void tbl_calc_data(struct tbl_node
*, struct tbl_dat
*);
30 static void tbl_calc_data_literal(struct tbl_dat
*);
31 static void tbl_calc_data_number(struct tbl_node
*, struct tbl_dat
*);
32 static void tbl_calc_data_spanner(struct tbl_dat
*);
35 tbl_read(struct tbl_node
*tbl
, int ln
, const char *p
, int offs
)
41 len
= (int)strlen(cp
);
44 * If we're in the options section and we don't have a
45 * terminating semicolon, assume we've moved directly into the
46 * layout section. No need to report a warning: this is,
47 * apparently, standard behaviour.
50 if (TBL_PART_OPTS
== tbl
->part
&& len
)
51 if (';' != cp
[len
- 1])
52 tbl
->part
= TBL_PART_LAYOUT
;
54 /* Now process each logical section of the table. */
58 return(tbl_option(tbl
, ln
, p
) ? ROFF_IGN
: ROFF_ERR
);
59 case (TBL_PART_LAYOUT
):
60 return(tbl_layout(tbl
, ln
, p
) ? ROFF_IGN
: ROFF_ERR
);
66 * This only returns zero if the line is empty, so we ignore it
69 return(tbl_data(tbl
, ln
, p
) ? ROFF_TBL
: ROFF_IGN
);
73 tbl_alloc(int pos
, int line
, void *data
, const mandocmsg msg
)
77 p
= mandoc_calloc(1, sizeof(struct tbl_node
));
82 p
->part
= TBL_PART_OPTS
;
84 p
->opts
.linesize
= 12;
85 p
->opts
.decimal
= '.';
90 tbl_free(struct tbl_node
*p
)
98 while (NULL
!= (rp
= p
->first_row
)) {
99 p
->first_row
= rp
->next
;
102 rp
->first
= cp
->next
;
108 while (NULL
!= (sp
= p
->first_span
)) {
109 p
->first_span
= sp
->next
;
112 sp
->first
= dp
->next
;
120 while (NULL
!= (hp
= p
->first_head
)) {
121 p
->first_head
= hp
->next
;
129 tbl_restart(int line
, int pos
, struct tbl_node
*tbl
)
132 tbl
->part
= TBL_PART_LAYOUT
;
136 if (NULL
== tbl
->first_span
|| NULL
== tbl
->first_span
->first
)
137 TBL_MSG(tbl
, MANDOCERR_TBLNODATA
, tbl
->line
, tbl
->pos
);
140 const struct tbl_span
*
141 tbl_span(const struct tbl_node
*tbl
)
145 return(tbl
->last_span
);
149 tbl_end(struct tbl_node
*tbl
)
152 if (NULL
== tbl
->first_span
|| NULL
== tbl
->first_span
->first
)
153 TBL_MSG(tbl
, MANDOCERR_TBLNODATA
, tbl
->line
, tbl
->pos
);
158 tbl
->last_span
->flags
|= TBL_SPAN_LAST
;
162 tbl_calc(struct tbl_node
*tbl
)
168 /* Calculate width as the max of column cells' widths. */
170 for (sp
= tbl
->first_span
; sp
; sp
= sp
->next
) {
172 case (TBL_DATA_HORIZ
):
174 case (TBL_DATA_DHORIZ
):
179 for (dp
= sp
->first
; dp
; dp
= dp
->next
)
180 tbl_calc_data(tbl
, dp
);
183 /* Calculate width as the simple spanner value. */
185 for (hp
= tbl
->first_head
; hp
; hp
= hp
->next
)
187 case (TBL_HEAD_VERT
):
190 case (TBL_HEAD_DVERT
):
199 tbl_calc_data(struct tbl_node
*tbl
, struct tbl_dat
*data
)
202 if (NULL
== data
->layout
)
205 /* Branch down into data sub-types. */
207 switch (data
->layout
->pos
) {
208 case (TBL_CELL_HORIZ
):
210 case (TBL_CELL_DHORIZ
):
211 tbl_calc_data_spanner(data
);
213 case (TBL_CELL_LONG
):
215 case (TBL_CELL_CENTRE
):
217 case (TBL_CELL_LEFT
):
219 case (TBL_CELL_RIGHT
):
220 tbl_calc_data_literal(data
);
222 case (TBL_CELL_NUMBER
):
223 tbl_calc_data_number(tbl
, data
);
232 tbl_calc_data_spanner(struct tbl_dat
*data
)
235 /* N.B., these are horiz spanners (not vert) so always 1. */
236 data
->layout
->head
->width
= 1;
240 tbl_calc_data_number(struct tbl_node
*tbl
, struct tbl_dat
*data
)
246 * First calculate number width and decimal place (last + 1 for
247 * no-decimal numbers). If the stored decimal is subsequent
248 * ours, make our size longer by that difference
249 * (right-"shifting"); similarly, if ours is subsequent the
250 * stored, then extend the stored size by the difference.
251 * Finally, re-assign the stored values.
254 /* TODO: use spacing modifier. */
256 assert(data
->string
);
257 sz
= (int)strlen(data
->string
);
258 pnt
= tbl
->opts
.decimal
;
260 if (NULL
== (dp
= strchr(data
->string
, pnt
)))
263 d
= (int)(dp
- data
->string
) + 1;
267 if (data
->layout
->head
->decimal
> d
) {
268 sz
+= data
->layout
->head
->decimal
- d
;
269 d
= data
->layout
->head
->decimal
;
271 data
->layout
->head
->width
+=
272 d
- data
->layout
->head
->decimal
;
274 if (sz
> data
->layout
->head
->width
)
275 data
->layout
->head
->width
= sz
;
276 if (d
> data
->layout
->head
->decimal
)
277 data
->layout
->head
->decimal
= d
;
281 tbl_calc_data_literal(struct tbl_dat
*data
)
286 * Calculate our width and use the spacing, with a minimum
287 * spacing dictated by position (centre, e.g,. gets a space on
288 * either side, while right/left get a single adjacent space).
291 assert(data
->string
);
292 sz
= (int)strlen(data
->string
);
294 switch (data
->layout
->pos
) {
295 case (TBL_CELL_LONG
):
297 case (TBL_CELL_CENTRE
):
305 if (data
->layout
->spacing
)
306 bufsz
= bufsz
> data
->layout
->spacing
?
307 bufsz
: data
->layout
->spacing
;
310 if (data
->layout
->head
->width
< sz
)
311 data
->layout
->head
->width
= sz
;