]>
git.cameronkatri.com Git - mandoc.git/blob - out.c
b13d783f7989306eafbb995b63ae2fd0763e1062
1 /* $Id: out.c,v 1.33 2011/01/10 14:40:30 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.
21 #include <sys/types.h>
33 static void tblcalc_data(struct rofftbl
*, struct roffcol
*,
34 const struct tbl
*, const struct tbl_dat
*);
35 static void tblcalc_literal(struct rofftbl
*, struct roffcol
*,
36 const struct tbl_dat
*);
37 static void tblcalc_number(struct rofftbl
*, struct roffcol
*,
38 const struct tbl
*, const struct tbl_dat
*);
41 * Convert a `scaling unit' to a consistent form, or fail. Scaling
42 * units are documented in groff.7, mdoc.7, man.7.
45 a2roffsu(const char *src
, struct roffsu
*dst
, enum roffscale def
)
47 char buf
[BUFSIZ
], hasd
;
71 if ( ! isdigit((u_char
)*src
)) {
82 if (BUFSIZ
== i
|| (*src
&& *(src
+ 1)))
110 if (SCALE_MAX
== def
)
127 /* FIXME: do this in the caller. */
128 if ((dst
->scale
= atof(buf
)) < 0)
136 * Correctly writes the time in nroff form, which differs from standard
137 * form in that a space isn't printed in lieu of the extra %e field for
138 * single-digit dates.
141 time2a(time_t t
, char *dst
, size_t sz
)
149 localtime_r(&t
, &tm
);
156 if (0 == (nsz
= strftime(p
, sz
, "%B ", &tm
)))
162 if (0 == strftime(buf
, sizeof(buf
), "%e, ", &tm
))
165 nsz
= strlcat(p
, buf
+ (' ' == buf
[0] ? 1 : 0), sz
);
173 (void)strftime(p
, sz
, "%Y", &tm
);
178 a2roffdeco(enum roffdeco
*d
, const char **word
, size_t *sz
)
190 switch ((c
= wp
[i
++])) {
198 *d
= 'F' == c
? DECO_FFONT
: DECO_FONT
;
260 if ('+' == wp
[i
] || '-' == wp
[i
]) {
284 if ('+' == wp
[i
] || '-' == wp
[i
]) {
290 /* Handle embedded numerical subexp or escape. */
293 while (wp
[i
] && ')' != wp
[i
])
294 if ('\\' == wp
[i
++]) {
295 /* Handle embedded escape. */
297 i
+= a2roffdeco(&dd
, word
, sz
);
305 } else if ('\\' == wp
[i
]) {
307 i
+= a2roffdeco(&dd
, word
, sz
);
322 return(i
+ a2roffdeco(&dd
, word
, sz
));
329 if ('\'' == wp
[i
++]) {
346 while (wp
[i
] && wp
[i
] != term
)
354 *sz
= (size_t)(i
- j
);
362 for (j
= 0; wp
[i
] && j
< lim
; j
++)
371 * Calculate the abstract widths and decimal positions of columns in a
372 * table. This routine allocates the columns structures then runs over
373 * all rows and cells in the table. The function pointers in "tbl" are
374 * used for the actual width calculations.
377 tblcalc(struct rofftbl
*tbl
, const struct tbl_span
*sp
)
379 const struct tbl_dat
*dp
;
380 const struct tbl_head
*hp
;
384 * Allocate the master column specifiers. These will hold the
385 * widths and decimal positions for all cells in the column. It
386 * must be freed and nullified by the caller.
389 assert(NULL
== tbl
->cols
);
390 tbl
->cols
= calloc(sp
->tbl
->cols
, sizeof(struct roffcol
));
394 for ( ; sp
; sp
= sp
->next
) {
395 if (TBL_SPAN_DATA
!= sp
->pos
)
398 * Account for the data cells in the layout, matching it
399 * to data cells in the data section.
401 for (dp
= sp
->first
; dp
; dp
= dp
->next
) {
403 col
= &tbl
->cols
[dp
->layout
->head
->ident
];
404 tblcalc_data(tbl
, col
, sp
->tbl
, dp
);
409 * Calculate width of the spanners. These get one space for a
410 * vertical line, two for a double-vertical line.
413 for ( ; hp
; hp
= hp
->next
) {
414 col
= &tbl
->cols
[hp
->ident
];
416 case (TBL_HEAD_VERT
):
417 col
->width
= (*tbl
->len
)(1, tbl
->arg
);
419 case (TBL_HEAD_DVERT
):
420 col
->width
= (*tbl
->len
)(2, tbl
->arg
);
429 tblcalc_data(struct rofftbl
*tbl
, struct roffcol
*col
,
430 const struct tbl
*tp
, const struct tbl_dat
*dp
)
434 /* Branch down into data sub-types. */
436 switch (dp
->layout
->pos
) {
437 case (TBL_CELL_HORIZ
):
439 case (TBL_CELL_DHORIZ
):
440 sz
= (*tbl
->len
)(1, tbl
->arg
);
444 case (TBL_CELL_LONG
):
446 case (TBL_CELL_CENTRE
):
448 case (TBL_CELL_LEFT
):
450 case (TBL_CELL_RIGHT
):
451 tblcalc_literal(tbl
, col
, dp
);
453 case (TBL_CELL_NUMBER
):
454 tblcalc_number(tbl
, col
, tp
, dp
);
463 tblcalc_literal(struct rofftbl
*tbl
, struct roffcol
*col
,
464 const struct tbl_dat
*dp
)
466 size_t sz
, bufsz
, spsz
;
469 * Calculate our width and use the spacing, with a minimum
470 * spacing dictated by position (centre, e.g,. gets a space on
471 * either side, while right/left get a single adjacent space).
474 sz
= bufsz
= spsz
= 0;
476 sz
= (*tbl
->slen
)(dp
->string
, tbl
->arg
);
479 switch (dp
->layout
->pos
) {
480 case (TBL_CELL_LONG
):
482 case (TBL_CELL_CENTRE
):
483 bufsz
= (*tbl
->len
)(2, tbl
->arg
);
486 bufsz
= (*tbl
->len
)(1, tbl
->arg
);
490 if (dp
->layout
->spacing
) {
491 spsz
= (*tbl
->len
)(dp
->layout
->spacing
, tbl
->arg
);
492 bufsz
= bufsz
> spsz
? bufsz
: spsz
;
501 tblcalc_number(struct rofftbl
*tbl
, struct roffcol
*col
,
502 const struct tbl
*tp
, const struct tbl_dat
*dp
)
505 size_t sz
, psz
, ssz
, d
, max
;
511 * First calculate number width and decimal place (last + 1 for
512 * no-decimal numbers). If the stored decimal is subsequent
513 * ours, make our size longer by that difference
514 * (right-"shifting"); similarly, if ours is subsequent the
515 * stored, then extend the stored size by the difference.
516 * Finally, re-assign the stored values.
519 str
= dp
&& dp
->string
? dp
->string
: "";
520 max
= dp
&& dp
->layout
? dp
->layout
->spacing
: 0;
522 sz
= (*tbl
->slen
)(str
, tbl
->arg
);
524 buf
[0] = tp
->decimal
;
527 psz
= (*tbl
->slen
)(buf
, tbl
->arg
);
529 if (NULL
!= (cp
= strrchr(str
, tp
->decimal
))) {
531 for (ssz
= 0, i
= 0; cp
!= &str
[i
]; i
++) {
533 ssz
+= (*tbl
->slen
)(buf
, tbl
->arg
);
541 sz
+= (*tbl
->len
)(2, tbl
->arg
);
542 d
+= (*tbl
->len
)(1, tbl
->arg
);
544 /* Adjust the settings for this column. */
546 if (col
->decimal
> d
) {
547 sz
+= col
->decimal
- d
;
550 col
->width
+= d
- col
->decimal
;
554 if (d
> col
->decimal
)
557 /* Adjust for stipulated width. */
559 if (col
->width
< max
)