diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2011-01-03 13:59:21 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2011-01-03 13:59:21 +0000 |
commit | 37cc2001c18336b17ab1db0fd5b493e86de5619a (patch) | |
tree | b39a648728b8aeb8b18a965cbdb9f87f773bdfd2 | |
parent | 014a5fb27cb61fd91481514f5e11ab50aefdbfdb (diff) | |
download | mandoc-37cc2001c18336b17ab1db0fd5b493e86de5619a.tar.gz |
Make width calculations occur within tbl_term.c, not tbl.c. This allows
for front-ends to make decisions about widths, not the back-end.
To pull this off, first make each tbl_head contain a unique index value
(0 <= index < total tbl_head elements) and remove the tbl_calc() routine
from the back-end.
Then, when encountering the first tbl_span in the front-end, dynamically
create an array of configurations (termp_tbl) keyed on each tbl_head's
unique index value. Construct the decimals and widths at this time,
then continue parsing as before.
The termp_tbl and indexes are required because we pass a const tbl AST
into the front-end.
-rw-r--r-- | mandoc.h | 6 | ||||
-rw-r--r-- | tbl.c | 160 | ||||
-rw-r--r-- | tbl_layout.c | 2 | ||||
-rw-r--r-- | tbl_term.c | 265 | ||||
-rw-r--r-- | term.h | 8 | ||||
-rw-r--r-- | tree.c | 13 |
6 files changed, 239 insertions, 215 deletions
@@ -149,7 +149,7 @@ struct tbl { char tab; /* cell-separator */ char decimal; /* decimal point */ int linesize; - char delims[2]; + char delims[2]; /* FIXME: deprecate */ int opts; #define TBL_OPT_CENTRE (1 << 0) #define TBL_OPT_EXPAND (1 << 1) @@ -158,6 +158,7 @@ struct tbl { #define TBL_OPT_ALLBOX (1 << 4) #define TBL_OPT_NOKEEP (1 << 5) #define TBL_OPT_NOSPACE (1 << 6) + int cols; /* number of columns */ }; enum tbl_headt { @@ -173,8 +174,7 @@ enum tbl_headt { */ struct tbl_head { enum tbl_headt pos; - int width; /* width of cell in fixed chars */ - int decimal; /* decimal point position */ + int ident; /* 0 <= unique id < cols */ struct tbl_head *next; struct tbl_head *prev; }; @@ -25,12 +25,6 @@ #include "libmandoc.h" #include "libroff.h" -static void tbl_calc(struct tbl_node *); -static void tbl_calc_data(struct tbl_node *, struct tbl_dat *); -static void tbl_calc_data_literal(struct tbl_dat *); -static void tbl_calc_data_number(struct tbl_node *, struct tbl_dat *); -static void tbl_calc_data_spanner(struct tbl_dat *); - enum rofferr tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs) { @@ -151,162 +145,8 @@ tbl_end(struct tbl_node *tbl) if (NULL == tbl->first_span || NULL == tbl->first_span->first) TBL_MSG(tbl, MANDOCERR_TBLNODATA, tbl->line, tbl->pos); - else - tbl_calc(tbl); if (tbl->last_span) tbl->last_span->flags |= TBL_SPAN_LAST; } -static void -tbl_calc(struct tbl_node *tbl) -{ - struct tbl_span *sp; - struct tbl_dat *dp; - struct tbl_head *hp; - - /* Calculate width as the max of column cells' widths. */ - - for (sp = tbl->first_span; sp; sp = sp->next) { - switch (sp->pos) { - case (TBL_DATA_HORIZ): - /* FALLTHROUGH */ - case (TBL_DATA_DHORIZ): - continue; - default: - break; - } - for (dp = sp->first; dp; dp = dp->next) - tbl_calc_data(tbl, dp); - } - - /* Calculate width as the simple spanner value. */ - - for (hp = tbl->first_head; hp; hp = hp->next) - switch (hp->pos) { - case (TBL_HEAD_VERT): - hp->width = 1; - break; - case (TBL_HEAD_DVERT): - hp->width = 2; - break; - default: - break; - } -} - -static void -tbl_calc_data(struct tbl_node *tbl, struct tbl_dat *data) -{ - - if (NULL == data->layout) - return; - - /* Branch down into data sub-types. */ - - switch (data->layout->pos) { - case (TBL_CELL_HORIZ): - /* FALLTHROUGH */ - case (TBL_CELL_DHORIZ): - tbl_calc_data_spanner(data); - break; - case (TBL_CELL_LONG): - /* FALLTHROUGH */ - case (TBL_CELL_CENTRE): - /* FALLTHROUGH */ - case (TBL_CELL_LEFT): - /* FALLTHROUGH */ - case (TBL_CELL_RIGHT): - tbl_calc_data_literal(data); - break; - case (TBL_CELL_NUMBER): - tbl_calc_data_number(tbl, data); - break; - default: - abort(); - /* NOTREACHED */ - } -} - -static void -tbl_calc_data_spanner(struct tbl_dat *data) -{ - - /* N.B., these are horiz spanners (not vert) so always 1. */ - data->layout->head->width = 1; -} - -static void -tbl_calc_data_number(struct tbl_node *tbl, struct tbl_dat *data) -{ - int sz, d; - char *dp, pnt; - - /* - * First calculate number width and decimal place (last + 1 for - * no-decimal numbers). If the stored decimal is subsequent - * ours, make our size longer by that difference - * (right-"shifting"); similarly, if ours is subsequent the - * stored, then extend the stored size by the difference. - * Finally, re-assign the stored values. - */ - - /* TODO: use spacing modifier. */ - - assert(data->string); - sz = (int)strlen(data->string); - pnt = tbl->opts.decimal; - - if (NULL == (dp = strchr(data->string, pnt))) - d = sz + 1; - else - d = (int)(dp - data->string) + 1; - - sz += 2; - - if (data->layout->head->decimal > d) { - sz += data->layout->head->decimal - d; - d = data->layout->head->decimal; - } else - data->layout->head->width += - d - data->layout->head->decimal; - - if (sz > data->layout->head->width) - data->layout->head->width = sz; - if (d > data->layout->head->decimal) - data->layout->head->decimal = d; -} - -static void -tbl_calc_data_literal(struct tbl_dat *data) -{ - int sz, bufsz; - - /* - * Calculate our width and use the spacing, with a minimum - * spacing dictated by position (centre, e.g,. gets a space on - * either side, while right/left get a single adjacent space). - */ - - assert(data->string); - sz = (int)strlen(data->string); - - switch (data->layout->pos) { - case (TBL_CELL_LONG): - /* FALLTHROUGH */ - case (TBL_CELL_CENTRE): - bufsz = 2; - break; - default: - bufsz = 1; - break; - } - - if (data->layout->spacing) - bufsz = bufsz > data->layout->spacing ? - bufsz : data->layout->spacing; - - sz += bufsz; - if (data->layout->head->width < sz) - data->layout->head->width = sz; -} diff --git a/tbl_layout.c b/tbl_layout.c index 3e3695cd..c630e3a8 100644 --- a/tbl_layout.c +++ b/tbl_layout.c @@ -319,6 +319,7 @@ cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos) (TBL_CELL_VERT == p->pos || TBL_CELL_DVERT == p->pos)) { hp = mandoc_calloc(1, sizeof(struct tbl_head)); + hp->ident = tbl->opts.cols++; hp->prev = h->prev; if (h->prev) h->prev->next = hp; @@ -341,6 +342,7 @@ cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos) } hp = mandoc_calloc(1, sizeof(struct tbl_head)); + hp->ident = tbl->opts.cols++; if (tbl->last_head) { hp->prev = tbl->last_head; @@ -35,18 +35,33 @@ static void tbl_hframe(struct termp *, const struct tbl_span *); static void tbl_data_number(struct termp *, const struct tbl *, - const struct tbl_dat *, int); + const struct tbl_dat *, + const struct termp_tbl *); static void tbl_data_literal(struct termp *, - const struct tbl_dat *, int); + const struct tbl_dat *, + const struct termp_tbl *); static void tbl_data_spanner(struct termp *, - const struct tbl_dat *, int); + const struct tbl_dat *, + const struct termp_tbl *); static void tbl_data(struct termp *, const struct tbl *, - const struct tbl_dat *, int); + const struct tbl_dat *, + const struct termp_tbl *); static void tbl_spanner(struct termp *, const struct tbl_head *); static void tbl_hrule(struct termp *, const struct tbl_span *); -static void tbl_vframe(struct termp *, const struct tbl *); +static void tbl_vframe(struct termp *, + const struct tbl *); +static void tbl_calc(const struct tbl_span *, + struct termp_tbl *); +static void tbl_calc_data(const struct tbl *, + const struct tbl_dat *, + struct termp_tbl *); +static void tbl_calc_data_literal(const struct tbl_dat *, + struct termp_tbl *); +static void tbl_calc_data_number(const struct tbl *, + const struct tbl_dat *, + struct termp_tbl *); void term_tbl(struct termp *tp, const struct tbl_span *sp) @@ -54,8 +69,17 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) const struct tbl_head *hp; const struct tbl_dat *dp; - if (TBL_SPAN_FIRST & sp->flags) + if (TBL_SPAN_FIRST & sp->flags) { + assert(NULL == tp->tbl); + tp->tbl = calloc + (sp->tbl->cols, sizeof(struct termp_tbl)); + if (NULL == tp->tbl) { + perror(NULL); + exit(EXIT_FAILURE); + } + tbl_calc(sp, tp->tbl); term_flushln(tp); + } if (TBL_SPAN_FIRST & sp->flags) tbl_hframe(tp, sp); @@ -72,8 +96,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tbl_hrule(tp, sp); tbl_vframe(tp, sp->tbl); term_newln(tp); - tp->flags &= ~TERMP_NONOSPACE; - return; + goto end; default: break; } @@ -87,7 +110,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tbl_spanner(tp, hp); break; case (TBL_HEAD_DATA): - tbl_data(tp, sp->tbl, dp, hp->width); + tbl_data(tp, sp->tbl, dp, &tp->tbl[hp->ident]); if (dp) dp = dp->next; break; @@ -100,8 +123,13 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tbl_vframe(tp, sp->tbl); term_flushln(tp); - if (TBL_SPAN_LAST & sp->flags) +end: + if (TBL_SPAN_LAST & sp->flags) { tbl_hframe(tp, sp); + assert(tp->tbl); + free(tp->tbl); + tp->tbl = NULL; + } tp->flags &= ~TERMP_NONOSPACE; @@ -112,6 +140,7 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; char c; + int width; /* * An hrule extends across the entire table and is demarked by a @@ -126,15 +155,16 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp) /* FIXME: don't use `+' between data and a spanner! */ for (hp = sp->head; hp; hp = hp->next) { + width = tp->tbl[hp->ident].width; switch (hp->pos) { case (TBL_HEAD_DATA): - tbl_char(tp, c, hp->width); + tbl_char(tp, c, width); break; case (TBL_HEAD_DVERT): - tbl_char(tp, '+', hp->width); + tbl_char(tp, '+', width); /* FALLTHROUGH */ case (TBL_HEAD_VERT): - tbl_char(tp, '+', hp->width); + tbl_char(tp, '+', width); break; default: abort(); @@ -147,6 +177,7 @@ static void tbl_hframe(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; + int width; if ( ! (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)) @@ -165,20 +196,23 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp) if (TBL_OPT_DBOX & sp->tbl->opts) { term_word(tp, "+"); - for (hp = sp->head; hp; hp = hp->next) - tbl_char(tp, '-', hp->width); + for (hp = sp->head; hp; hp = hp->next) { + width = tp->tbl[hp->ident].width; + tbl_char(tp, '-', width); + } term_word(tp, "+"); term_flushln(tp); } term_word(tp, "+"); for (hp = sp->head; hp; hp = hp->next) { + width = tp->tbl[hp->ident].width; switch (hp->pos) { case (TBL_HEAD_DATA): - tbl_char(tp, '-', hp->width); + tbl_char(tp, '-', width); break; default: - tbl_char(tp, '+', hp->width); + tbl_char(tp, '+', width); break; } } @@ -188,12 +222,13 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp) static void tbl_data(struct termp *tp, const struct tbl *tbl, - const struct tbl_dat *dp, int width) + const struct tbl_dat *dp, + const struct termp_tbl *tbp) { enum tbl_cellt pos; if (NULL == dp) { - tbl_char(tp, ASCII_NBRSP, width); + tbl_char(tp, ASCII_NBRSP, tbp->width); return; } @@ -201,7 +236,7 @@ tbl_data(struct termp *tp, const struct tbl *tbl, case (TBL_DATA_HORIZ): /* FALLTHROUGH */ case (TBL_DATA_DHORIZ): - tbl_data_spanner(tp, dp, width); + tbl_data_spanner(tp, dp, tbp); return; default: break; @@ -213,7 +248,7 @@ tbl_data(struct termp *tp, const struct tbl *tbl, case (TBL_CELL_HORIZ): /* FALLTHROUGH */ case (TBL_CELL_DHORIZ): - tbl_data_spanner(tp, dp, width); + tbl_data_spanner(tp, dp, tbp); break; case (TBL_CELL_LONG): /* FALLTHROUGH */ @@ -222,10 +257,10 @@ tbl_data(struct termp *tp, const struct tbl *tbl, case (TBL_CELL_LEFT): /* FALLTHROUGH */ case (TBL_CELL_RIGHT): - tbl_data_literal(tp, dp, width); + tbl_data_literal(tp, dp, tbp); break; case (TBL_CELL_NUMBER): - tbl_data_number(tp, tbl, dp, width); + tbl_data_number(tp, tbl, dp, tbp); break; default: abort(); @@ -272,17 +307,19 @@ tbl_char(struct termp *tp, char c, int len) } static void -tbl_data_spanner(struct termp *tp, const struct tbl_dat *dp, int width) +tbl_data_spanner(struct termp *tp, + const struct tbl_dat *dp, + const struct termp_tbl *tblp) { switch (dp->pos) { case (TBL_DATA_HORIZ): case (TBL_DATA_NHORIZ): - tbl_char(tp, '-', width); + tbl_char(tp, '-', tblp->width); break; case (TBL_DATA_DHORIZ): case (TBL_DATA_NDHORIZ): - tbl_char(tp, '=', width); + tbl_char(tp, '=', tblp->width); break; default: break; @@ -290,7 +327,9 @@ tbl_data_spanner(struct termp *tp, const struct tbl_dat *dp, int width) } static void -tbl_data_literal(struct termp *tp, const struct tbl_dat *dp, int width) +tbl_data_literal(struct termp *tp, + const struct tbl_dat *dp, + const struct termp_tbl *tblp) { int padl, padr; enum tbl_cellt pos; @@ -302,20 +341,20 @@ tbl_data_literal(struct termp *tp, const struct tbl_dat *dp, int width) switch (pos) { case (TBL_CELL_LONG): padl = 1; - padr = width - (int)strlen(dp->string) - 1; + padr = tblp->width - (int)strlen(dp->string) - 1; break; case (TBL_CELL_CENTRE): - padl = width - (int)strlen(dp->string); + padl = tblp->width - (int)strlen(dp->string); if (padl % 2) padr++; padl /= 2; padr += padl; break; case (TBL_CELL_RIGHT): - padl = width - (int)strlen(dp->string); + padl = tblp->width - (int)strlen(dp->string); break; default: - padr = width - (int)strlen(dp->string); + padr = tblp->width - (int)strlen(dp->string); break; } @@ -326,7 +365,8 @@ tbl_data_literal(struct termp *tp, const struct tbl_dat *dp, int width) static void tbl_data_number(struct termp *tp, const struct tbl *tbl, - const struct tbl_dat *dp, int width) + const struct tbl_dat *dp, + const struct termp_tbl *tblp) { char *decp, pnt; int d, padl, sz; @@ -345,14 +385,163 @@ tbl_data_number(struct termp *tp, const struct tbl *tbl, d = (int)(decp - dp->string) + 1; } - assert(d <= dp->layout->head->decimal); - assert(sz - d <= dp->layout->head->width - - dp->layout->head->decimal); + assert(d <= tblp->decimal); + assert(sz - d <= tblp->width - tblp->decimal); - padl = dp->layout->head->decimal - d + 1; - assert(width - sz - padl); + padl = tblp->decimal - d + 1; + assert(tblp->width - sz - padl); tbl_char(tp, ASCII_NBRSP, padl); term_word(tp, dp->string); - tbl_char(tp, ASCII_NBRSP, width - sz - padl); + tbl_char(tp, ASCII_NBRSP, tblp->width - sz - padl); +} + +static void +tbl_calc(const struct tbl_span *sp, struct termp_tbl *tblp) +{ + const struct tbl_dat *dp; + const struct tbl_head *hp; + struct termp_tbl *p; + + /* Calculate width as the max of column cells' widths. */ + + hp = sp->head; + + for ( ; sp; sp = sp->next) { + switch (sp->pos) { + case (TBL_DATA_HORIZ): + /* FALLTHROUGH */ + case (TBL_DATA_DHORIZ): + continue; + default: + break; + } + for (dp = sp->first; dp; dp = dp->next) { + if (NULL == dp->layout) + continue; + p = &tblp[dp->layout->head->ident]; + tbl_calc_data(sp->tbl, dp, p); + } + } + + /* Calculate width as the simple spanner value. */ + + for ( ; hp; hp = hp->next) + switch (hp->pos) { + case (TBL_HEAD_VERT): + tblp[hp->ident].width = 1; + break; + case (TBL_HEAD_DVERT): + tblp[hp->ident].width = 2; + break; + default: + break; + } +} + +static void +tbl_calc_data(const struct tbl *tbl, + const struct tbl_dat *dp, + struct termp_tbl *tblp) +{ + + /* Branch down into data sub-types. */ + + switch (dp->layout->pos) { + case (TBL_CELL_HORIZ): + /* FALLTHROUGH */ + case (TBL_CELL_DHORIZ): + tblp->width = 1; + break; + case (TBL_CELL_LONG): + /* FALLTHROUGH */ + case (TBL_CELL_CENTRE): + /* FALLTHROUGH */ + case (TBL_CELL_LEFT): + /* FALLTHROUGH */ + case (TBL_CELL_RIGHT): + tbl_calc_data_literal(dp, tblp); + break; + case (TBL_CELL_NUMBER): + tbl_calc_data_number(tbl, dp, tblp); + break; + default: + abort(); + /* NOTREACHED */ + } +} + +static void +tbl_calc_data_number(const struct tbl *tbl, + const struct tbl_dat *dp, struct termp_tbl *tblp) +{ + int sz, d; + char *cp, pnt; + + /* + * First calculate number width and decimal place (last + 1 for + * no-decimal numbers). If the stored decimal is subsequent + * ours, make our size longer by that difference + * (right-"shifting"); similarly, if ours is subsequent the + * stored, then extend the stored size by the difference. + * Finally, re-assign the stored values. + */ + + /* TODO: use spacing modifier. */ + + assert(dp->string); + sz = (int)strlen(dp->string); + pnt = tbl->decimal; + + if (NULL == (cp = strchr(dp->string, pnt))) + d = sz + 1; + else + d = (int)(cp - dp->string) + 1; + + sz += 2; + + if (tblp->decimal > d) { + sz += tblp->decimal - d; + d = tblp->decimal; + } else + tblp->width += d - tblp->decimal; + + if (sz > tblp->width) + tblp->width = sz; + if (d > tblp->decimal) + tblp->decimal = d; +} + +static void +tbl_calc_data_literal(const struct tbl_dat *dp, struct termp_tbl *tblp) +{ + int sz, bufsz; + + /* + * Calculate our width and use the spacing, with a minimum + * spacing dictated by position (centre, e.g,. gets a space on + * either side, while right/left get a single adjacent space). + */ + + assert(dp->string); + sz = (int)strlen(dp->string); + + switch (dp->layout->pos) { + case (TBL_CELL_LONG): + /* FALLTHROUGH */ + case (TBL_CELL_CENTRE): + bufsz = 2; + break; + default: + bufsz = 1; + break; + } + + if (dp->layout->spacing) + bufsz = bufsz > dp->layout->spacing ? + bufsz : dp->layout->spacing; + + sz += bufsz; + if (tblp->width < sz) + tblp->width = sz; } @@ -71,9 +71,15 @@ struct termp_ps { size_t pdfobjsz; /* size of pdfobjs */ }; +struct termp_tbl { + int width; /* width in fixed chars */ + int decimal; /* decimal point position */ +}; + struct termp { enum termtype type; - size_t defrmargin; /* Right margin of the device.. */ + struct termp_tbl *tbl; /* table configuration */ + size_t defrmargin; /* Right margin of the device. */ size_t rmargin; /* Current right margin. */ size_t maxrmargin; /* Max right margin. */ size_t maxcols; /* Max size of buf. */ @@ -249,21 +249,8 @@ static void print_span(const struct tbl_span *sp, int indent) { const struct tbl_dat *dp; - const struct tbl_head *hp; int i; - if (TBL_SPAN_FIRST & sp->flags) { - for (i = 0; i < indent; i++) - putchar('\t'); - printf("tbl-head: "); - for (hp = sp->head; hp; hp = hp->next) { - printf("[%d]", hp->width); - if (hp->next) - putchar(' '); - } - putchar('\n'); - } - for (i = 0; i < indent; i++) putchar('\t'); |