]>
git.cameronkatri.com Git - mandoc.git/blob - tbl_term.c
1 /* $Id: tbl_term.c,v 1.13 2011/01/07 14:59:52 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 /* FIXME: `n' modifier doesn't always do the right thing. */
31 /* FIXME: `n' modifier doesn't use the cell-spacing buffer. */
33 static size_t term_tbl_len(size_t, void *);
34 static size_t term_tbl_strlen(const char *, void *);
35 static void tbl_char(struct termp
*, char, size_t);
36 static void tbl_data(struct termp
*, const struct tbl
*,
37 const struct tbl_dat
*,
38 const struct roffcol
*);
39 static void tbl_hframe(struct termp
*, const struct tbl_span
*);
40 static void tbl_literal(struct termp
*, const struct tbl_dat
*,
41 const struct roffcol
*);
42 static void tbl_number(struct termp
*, const struct tbl
*,
43 const struct tbl_dat
*,
44 const struct roffcol
*);
45 static void tbl_hrule(struct termp
*, const struct tbl_span
*);
46 static void tbl_vframe(struct termp
*, const struct tbl
*);
47 static void tbl_vrule(struct termp
*, const struct tbl_head
*);
51 term_tbl_strlen(const char *p
, void *arg
)
54 return(term_strlen((const struct termp
*)arg
, p
));
58 term_tbl_len(size_t sz
, void *arg
)
61 return(term_len((const struct termp
*)arg
, sz
));
65 term_tbl(struct termp
*tp
, const struct tbl_span
*sp
)
67 const struct tbl_head
*hp
;
68 const struct tbl_dat
*dp
;
70 size_t rmargin
, maxrmargin
;
72 rmargin
= tp
->rmargin
;
73 maxrmargin
= tp
->maxrmargin
;
75 tp
->rmargin
= tp
->maxrmargin
= TERM_MAXMARGIN
;
77 /* Inhibit printing of spaces: we do padding ourselves. */
79 tp
->flags
|= TERMP_NONOSPACE
;
80 tp
->flags
|= TERMP_NOSPACE
;
83 * The first time we're invoked for a given table block,
84 * calculate the table widths and decimal positions.
87 if (TBL_SPAN_FIRST
& sp
->flags
) {
90 tp
->tbl
.len
= term_tbl_len
;
91 tp
->tbl
.slen
= term_tbl_strlen
;
94 tblcalc(&tp
->tbl
, sp
);
97 /* Horizontal frame at the start of boxed tables. */
99 if (TBL_SPAN_FIRST
& sp
->flags
)
102 /* Vertical frame at the start of each row. */
104 tbl_vframe(tp
, sp
->tbl
);
107 * Now print the actual data itself depending on the span type.
108 * Spanner spans get a horizontal rule; data spanners have their
109 * data printed by matching data to header.
113 case (TBL_SPAN_HORIZ
):
115 case (TBL_SPAN_DHORIZ
):
118 case (TBL_SPAN_DATA
):
119 /* Iterate over template headers. */
121 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
123 case (TBL_HEAD_VERT
):
125 case (TBL_HEAD_DVERT
):
128 case (TBL_HEAD_DATA
):
132 col
= &tp
->tbl
.cols
[hp
->ident
];
133 tbl_data(tp
, sp
->tbl
, dp
, col
);
135 /* Go to the next data cell. */
142 tbl_vframe(tp
, sp
->tbl
);
146 * If we're the last row, clean up after ourselves: clear the
147 * existing table configuration and set it to NULL.
150 if (TBL_SPAN_LAST
& sp
->flags
) {
152 assert(tp
->tbl
.cols
);
157 tp
->flags
&= ~TERMP_NONOSPACE
;
158 tp
->rmargin
= rmargin
;
159 tp
->maxrmargin
= maxrmargin
;
164 tbl_hrule(struct termp
*tp
, const struct tbl_span
*sp
)
166 const struct tbl_head
*hp
;
171 * An hrule extends across the entire table and is demarked by a
172 * standalone `_' or whatnot in lieu of a table row. Spanning
173 * headers are marked by a `+', as are table boundaries.
177 if (TBL_SPAN_DHORIZ
== sp
->pos
)
180 /* FIXME: don't use `+' between data and a spanner! */
182 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
183 width
= tp
->tbl
.cols
[hp
->ident
].width
;
185 case (TBL_HEAD_DATA
):
186 tbl_char(tp
, c
, width
);
188 case (TBL_HEAD_DVERT
):
189 tbl_char(tp
, '+', width
);
191 case (TBL_HEAD_VERT
):
192 tbl_char(tp
, '+', width
);
202 tbl_hframe(struct termp
*tp
, const struct tbl_span
*sp
)
204 const struct tbl_head
*hp
;
207 if ( ! (TBL_OPT_BOX
& sp
->tbl
->opts
||
208 TBL_OPT_DBOX
& sp
->tbl
->opts
))
212 * Print out the horizontal part of a frame or double frame. A
213 * double frame has an unbroken `-' outer line the width of the
214 * table, bordered by `+'. The frame (or inner frame, in the
215 * case of the double frame) is a `-' bordered by `+' and broken
216 * by `+' whenever a span is encountered.
219 if (TBL_OPT_DBOX
& sp
->tbl
->opts
) {
221 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
222 width
= tp
->tbl
.cols
[hp
->ident
].width
;
223 tbl_char(tp
, '-', width
);
230 for (hp
= sp
->head
; hp
; hp
= hp
->next
) {
231 width
= tp
->tbl
.cols
[hp
->ident
].width
;
233 case (TBL_HEAD_DATA
):
234 tbl_char(tp
, '-', width
);
237 tbl_char(tp
, '+', width
);
246 tbl_data(struct termp
*tp
, const struct tbl
*tbl
,
247 const struct tbl_dat
*dp
,
248 const struct roffcol
*col
)
253 tbl_char(tp
, ASCII_NBRSP
, col
->width
);
258 case (TBL_DATA_NONE
):
259 tbl_char(tp
, ASCII_NBRSP
, col
->width
);
261 case (TBL_DATA_HORIZ
):
263 case (TBL_DATA_NHORIZ
):
264 tbl_char(tp
, '-', col
->width
);
266 case (TBL_DATA_NDHORIZ
):
268 case (TBL_DATA_DHORIZ
):
269 tbl_char(tp
, '=', col
->width
);
275 pos
= dp
&& dp
->layout
? dp
->layout
->pos
: TBL_CELL_LEFT
;
278 case (TBL_CELL_HORIZ
):
279 tbl_char(tp
, '-', col
->width
);
281 case (TBL_CELL_DHORIZ
):
282 tbl_char(tp
, '=', col
->width
);
284 case (TBL_CELL_LONG
):
286 case (TBL_CELL_CENTRE
):
288 case (TBL_CELL_LEFT
):
290 case (TBL_CELL_RIGHT
):
291 tbl_literal(tp
, dp
, col
);
293 case (TBL_CELL_NUMBER
):
294 tbl_number(tp
, tbl
, dp
, col
);
303 tbl_vrule(struct termp
*tp
, const struct tbl_head
*hp
)
307 case (TBL_HEAD_VERT
):
310 case (TBL_HEAD_DVERT
):
319 tbl_vframe(struct termp
*tp
, const struct tbl
*tbl
)
322 if (TBL_OPT_BOX
& tbl
->opts
|| TBL_OPT_DBOX
& tbl
->opts
)
327 tbl_char(struct termp
*tp
, char c
, size_t len
)
335 sz
= term_strlen(tp
, cp
);
337 for (i
= 0; i
< len
; i
+= sz
)
342 tbl_literal(struct termp
*tp
, const struct tbl_dat
*dp
,
343 const struct roffcol
*col
)
345 size_t padl
, padr
, ssz
;
351 pos
= dp
&& dp
->layout
? dp
->layout
->pos
: TBL_CELL_LEFT
;
352 str
= dp
&& dp
->string
? dp
->string
: "";
354 ssz
= term_len(tp
, 1);
357 case (TBL_CELL_LONG
):
359 padr
= col
->width
- term_strlen(tp
, str
) - ssz
;
361 case (TBL_CELL_CENTRE
):
362 padl
= col
->width
- term_strlen(tp
, str
);
368 case (TBL_CELL_RIGHT
):
369 padl
= col
->width
- term_strlen(tp
, str
);
372 padr
= col
->width
- term_strlen(tp
, str
);
376 tbl_char(tp
, ASCII_NBRSP
, padl
);
378 tbl_char(tp
, ASCII_NBRSP
, padr
);
382 tbl_number(struct termp
*tp
, const struct tbl
*tbl
,
383 const struct tbl_dat
*dp
,
384 const struct roffcol
*col
)
389 size_t sz
, psz
, ssz
, d
, padl
;
393 * See calc_data_number(). Left-pad by taking the offset of our
394 * and the maximum decimal; right-pad by the remaining amount.
397 str
= dp
&& dp
->string
? dp
->string
: "";
399 sz
= term_strlen(tp
, str
);
401 buf
[0] = tbl
->decimal
;
404 psz
= term_strlen(tp
, buf
);
406 if (NULL
!= (cp
= strchr(str
, tbl
->decimal
))) {
408 for (ssz
= 0, i
= 0; cp
!= &str
[i
]; i
++) {
410 ssz
+= term_strlen(tp
, buf
);
416 sz
+= term_len(tp
, 2);
417 d
+= term_len(tp
, 1);
419 padl
= col
->decimal
- d
;
421 tbl_char(tp
, ASCII_NBRSP
, padl
);
423 tbl_char(tp
, ASCII_NBRSP
, col
->width
- sz
- padl
);