]>
git.cameronkatri.com Git - mandoc.git/blob - tbl_term.c
1 /* $Id: tbl_term.c,v 1.17 2011/01/10 14:56:06 kristaps Exp $ */
3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
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.
30 static size_t term_tbl_len(size_t, void *);
31 static size_t term_tbl_strlen(const char *, void *);
32 static void tbl_char(struct termp
*, char, size_t);
33 static void tbl_data(struct termp
*, const struct tbl
*,
34 const struct tbl_dat
*,
35 const struct roffcol
*);
36 static void tbl_hframe(struct termp
*, const struct tbl_span
*);
37 static void tbl_literal(struct termp
*, const struct tbl_dat
*,
38 const struct roffcol
*);
39 static void tbl_number(struct termp
*, const struct tbl
*,
40 const struct tbl_dat
*,
41 const struct roffcol
*);
42 static void tbl_hrule(struct termp
*, const struct tbl_span
*);
43 static void tbl_vframe(struct termp
*, const struct tbl
*);
44 static void tbl_vrule(struct termp
*, const struct tbl_head
*);
48 term_tbl_strlen(const char *p
, void *arg
)
51 return(term_strlen((const struct termp
*)arg
, p
));
55 term_tbl_len(size_t sz
, void *arg
)
58 return(term_len((const struct termp
*)arg
, sz
));
62 term_tbl(struct termp
*tp
, const struct tbl_span
*sp
)
64 const struct tbl_head
*hp
;
65 const struct tbl_dat
*dp
;
68 size_t rmargin
, maxrmargin
;
70 rmargin
= tp
->rmargin
;
71 maxrmargin
= tp
->maxrmargin
;
73 tp
->rmargin
= tp
->maxrmargin
= TERM_MAXMARGIN
;
75 /* Inhibit printing of spaces: we do padding ourselves. */
77 tp
->flags
|= TERMP_NONOSPACE
;
78 tp
->flags
|= TERMP_NOSPACE
;
81 * The first time we're invoked for a given table block,
82 * calculate the table widths and decimal positions.
85 if (TBL_SPAN_FIRST
& sp
->flags
) {
88 tp
->tbl
.len
= term_tbl_len
;
89 tp
->tbl
.slen
= term_tbl_strlen
;
92 tblcalc(&tp
->tbl
, sp
);
95 /* Horizontal frame at the start of boxed tables. */
97 if (TBL_SPAN_FIRST
& sp
->flags
)
100 /* Vertical frame at the start of each row. */
102 tbl_vframe(tp
, sp
->tbl
);
105 * Now print the actual data itself depending on the span type.
106 * Spanner spans get a horizontal rule; data spanners have their
107 * data printed by matching data to header.
111 case (TBL_SPAN_HORIZ
):
113 case (TBL_SPAN_DHORIZ
):
116 case (TBL_SPAN_DATA
):
117 /* Iterate over template headers. */
120 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
122 * If the current data header is invoked during
123 * a spanner ("spans" > 0), don't emit anything
127 case (TBL_HEAD_VERT
):
129 case (TBL_HEAD_DVERT
):
133 case (TBL_HEAD_DATA
):
140 col
= &tp
->tbl
.cols
[hp
->ident
];
141 tbl_data(tp
, sp
->tbl
, dp
, col
);
144 * Go to the next data cell and assign the
145 * number of subsequent spans, if applicable.
156 tbl_vframe(tp
, sp
->tbl
);
160 * If we're the last row, clean up after ourselves: clear the
161 * existing table configuration and set it to NULL.
164 if (TBL_SPAN_LAST
& sp
->flags
) {
166 assert(tp
->tbl
.cols
);
171 tp
->flags
&= ~TERMP_NONOSPACE
;
172 tp
->rmargin
= rmargin
;
173 tp
->maxrmargin
= maxrmargin
;
178 tbl_hrule(struct termp
*tp
, const struct tbl_span
*sp
)
180 const struct tbl_head
*hp
;
185 * An hrule extends across the entire table and is demarked by a
186 * standalone `_' or whatnot in lieu of a table row. Spanning
187 * headers are marked by a `+', as are table boundaries.
191 if (TBL_SPAN_DHORIZ
== sp
->pos
)
194 /* FIXME: don't use `+' between data and a spanner! */
196 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
197 width
= tp
->tbl
.cols
[hp
->ident
].width
;
199 case (TBL_HEAD_DATA
):
200 tbl_char(tp
, c
, width
);
202 case (TBL_HEAD_DVERT
):
203 tbl_char(tp
, '+', width
);
205 case (TBL_HEAD_VERT
):
206 tbl_char(tp
, '+', width
);
216 tbl_hframe(struct termp
*tp
, const struct tbl_span
*sp
)
218 const struct tbl_head
*hp
;
221 if ( ! (TBL_OPT_BOX
& sp
->tbl
->opts
||
222 TBL_OPT_DBOX
& sp
->tbl
->opts
))
226 * Print out the horizontal part of a frame or double frame. A
227 * double frame has an unbroken `-' outer line the width of the
228 * table, bordered by `+'. The frame (or inner frame, in the
229 * case of the double frame) is a `-' bordered by `+' and broken
230 * by `+' whenever a span is encountered.
233 if (TBL_OPT_DBOX
& sp
->tbl
->opts
) {
235 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
236 width
= tp
->tbl
.cols
[hp
->ident
].width
;
237 tbl_char(tp
, '-', width
);
244 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
245 width
= tp
->tbl
.cols
[hp
->ident
].width
;
247 case (TBL_HEAD_DATA
):
248 tbl_char(tp
, '-', width
);
251 tbl_char(tp
, '+', width
);
260 tbl_data(struct termp
*tp
, const struct tbl
*tbl
,
261 const struct tbl_dat
*dp
,
262 const struct roffcol
*col
)
266 tbl_char(tp
, ASCII_NBRSP
, col
->width
);
272 case (TBL_DATA_NONE
):
273 tbl_char(tp
, ASCII_NBRSP
, col
->width
);
275 case (TBL_DATA_HORIZ
):
277 case (TBL_DATA_NHORIZ
):
278 tbl_char(tp
, '-', col
->width
);
280 case (TBL_DATA_NDHORIZ
):
282 case (TBL_DATA_DHORIZ
):
283 tbl_char(tp
, '=', col
->width
);
289 switch (dp
->layout
->pos
) {
290 case (TBL_CELL_HORIZ
):
291 tbl_char(tp
, '-', col
->width
);
293 case (TBL_CELL_DHORIZ
):
294 tbl_char(tp
, '=', col
->width
);
296 case (TBL_CELL_LONG
):
298 case (TBL_CELL_CENTRE
):
300 case (TBL_CELL_LEFT
):
302 case (TBL_CELL_RIGHT
):
303 tbl_literal(tp
, dp
, col
);
305 case (TBL_CELL_NUMBER
):
306 tbl_number(tp
, tbl
, dp
, col
);
315 tbl_vrule(struct termp
*tp
, const struct tbl_head
*hp
)
319 case (TBL_HEAD_VERT
):
322 case (TBL_HEAD_DVERT
):
331 tbl_vframe(struct termp
*tp
, const struct tbl
*tbl
)
334 if (TBL_OPT_BOX
& tbl
->opts
|| TBL_OPT_DBOX
& tbl
->opts
)
339 tbl_char(struct termp
*tp
, char c
, size_t len
)
347 sz
= term_strlen(tp
, cp
);
349 for (i
= 0; i
< len
; i
+= sz
)
354 tbl_literal(struct termp
*tp
, const struct tbl_dat
*dp
,
355 const struct roffcol
*col
)
357 size_t padl
, padr
, ssz
;
363 ssz
= term_len(tp
, 1);
365 switch (dp
->layout
->pos
) {
366 case (TBL_CELL_LONG
):
368 padr
= col
->width
- term_strlen(tp
, dp
->string
) - ssz
;
370 case (TBL_CELL_CENTRE
):
371 padl
= col
->width
- term_strlen(tp
, dp
->string
);
377 case (TBL_CELL_RIGHT
):
378 padl
= col
->width
- term_strlen(tp
, dp
->string
);
381 padr
= col
->width
- term_strlen(tp
, dp
->string
);
385 tbl_char(tp
, ASCII_NBRSP
, padl
);
386 term_word(tp
, dp
->string
);
387 tbl_char(tp
, ASCII_NBRSP
, padr
);
391 tbl_number(struct termp
*tp
, const struct tbl
*tbl
,
392 const struct tbl_dat
*dp
,
393 const struct roffcol
*col
)
397 size_t sz
, psz
, ssz
, d
, padl
;
401 * See calc_data_number(). Left-pad by taking the offset of our
402 * and the maximum decimal; right-pad by the remaining amount.
407 sz
= term_strlen(tp
, dp
->string
);
409 buf
[0] = tbl
->decimal
;
412 psz
= term_strlen(tp
, buf
);
414 if (NULL
!= (cp
= strrchr(dp
->string
, tbl
->decimal
))) {
416 for (ssz
= 0, i
= 0; cp
!= &dp
->string
[i
]; i
++) {
417 buf
[0] = dp
->string
[i
];
418 ssz
+= term_strlen(tp
, buf
);
424 sz
+= term_len(tp
, 2);
425 d
+= term_len(tp
, 1);
427 padl
= col
->decimal
- d
;
429 tbl_char(tp
, ASCII_NBRSP
, padl
);
430 term_word(tp
, dp
->string
);
431 tbl_char(tp
, ASCII_NBRSP
, col
->width
- sz
- padl
);