=================================================================== RCS file: /cvs/mandoc/tbl_term.c,v retrieving revision 1.2 retrieving revision 1.8 diff -u -p -r1.2 -r1.8 --- mandoc/tbl_term.c 2011/01/03 13:59:21 1.2 +++ mandoc/tbl_term.c 2011/01/04 13:14:26 1.8 @@ -1,4 +1,4 @@ -/* $Id: tbl_term.c,v 1.2 2011/01/03 13:59:21 kristaps Exp $ */ +/* $Id: tbl_term.c,v 1.8 2011/01/04 13:14:26 kristaps Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons * @@ -40,9 +40,6 @@ static void tbl_data_number(struct termp *, static void tbl_data_literal(struct termp *, const struct tbl_dat *, const struct termp_tbl *); -static void tbl_data_spanner(struct termp *, - const struct tbl_dat *, - const struct termp_tbl *); static void tbl_data(struct termp *, const struct tbl *, const struct tbl_dat *, const struct termp_tbl *); @@ -52,14 +49,17 @@ static void tbl_hrule(struct termp *, const struct tbl_span *); static void tbl_vframe(struct termp *, const struct tbl *); -static void tbl_calc(const struct tbl_span *, +static void tbl_calc(struct termp *, + const struct tbl_span *); +static void tbl_calc_data(struct termp *, + const struct tbl *, + const struct tbl_dat *, struct termp_tbl *); -static void tbl_calc_data(const struct tbl *, +static void tbl_calc_data_literal(struct termp *, 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 *, +static void tbl_calc_data_number(struct termp *, + const struct tbl *, const struct tbl_dat *, struct termp_tbl *); @@ -69,6 +69,18 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) const struct tbl_head *hp; const struct tbl_dat *dp; + /* Inhibit printing of spaces: we do padding ourselves. */ + + tp->flags |= TERMP_NONOSPACE; + tp->flags |= TERMP_NOSPACE; + + /* + * The first time we're invoked for a given table block, create + * the termp_tbl structure. This contains the column + * configuration for the entire table, e.g., table-wide column + * width, decimal point, etc. + */ + if (TBL_SPAN_FIRST & sp->flags) { assert(NULL == tp->tbl); tp->tbl = calloc @@ -77,53 +89,64 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) perror(NULL); exit(EXIT_FAILURE); } - tbl_calc(sp, tp->tbl); + tbl_calc(tp, sp); + + /* Flush out any preceding data. */ term_flushln(tp); } + /* Horizontal frame at the start of boxed tables. */ + if (TBL_SPAN_FIRST & sp->flags) tbl_hframe(tp, sp); - tp->flags |= TERMP_NONOSPACE; - tp->flags |= TERMP_NOSPACE; + /* Vertical frame at the start of each row. */ tbl_vframe(tp, sp->tbl); + /* + * Now print the actual data itself depending on the span type. + * Spanner spans get a horizontal rule; data spanners have their + * data printed by matching data to header. + */ + switch (sp->pos) { case (TBL_SPAN_HORIZ): /* FALLTHROUGH */ case (TBL_SPAN_DHORIZ): tbl_hrule(tp, sp); - tbl_vframe(tp, sp->tbl); - term_newln(tp); - goto end; - default: break; - } + case (TBL_SPAN_DATA): + /* Iterate over template headers. */ + dp = sp->first; + for (hp = sp->head; hp; hp = hp->next) { + switch (hp->pos) { + case (TBL_HEAD_VERT): + /* FALLTHROUGH */ + case (TBL_HEAD_DVERT): + tbl_spanner(tp, hp); + continue; + case (TBL_HEAD_DATA): + break; + } + tbl_data(tp, sp->tbl, dp, + &tp->tbl[hp->ident]); - dp = sp->first; - for (hp = sp->head; hp; hp = hp->next) { - switch (hp->pos) { - case (TBL_HEAD_VERT): - /* FALLTHROUGH */ - case (TBL_HEAD_DVERT): - tbl_spanner(tp, hp); - break; - case (TBL_HEAD_DATA): - tbl_data(tp, sp->tbl, dp, &tp->tbl[hp->ident]); + /* Go to the next data cell. */ if (dp) dp = dp->next; - break; - default: - abort(); - /* NOTREACHED */ } + break; } tbl_vframe(tp, sp->tbl); term_flushln(tp); -end: + /* + * If we're the last row, clean up after ourselves: clear the + * existing table configuration and set it to NULL. + */ + if (TBL_SPAN_LAST & sp->flags) { tbl_hframe(tp, sp); assert(tp->tbl); @@ -183,9 +206,6 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp TBL_OPT_DBOX & sp->tbl->opts)) return; - tp->flags |= TERMP_NONOSPACE; - tp->flags |= TERMP_NOSPACE; - /* * Print out the horizontal part of a frame or double frame. A * double frame has an unbroken `-' outer line the width of the @@ -235,8 +255,13 @@ tbl_data(struct termp *tp, const struct tbl *tbl, switch (dp->pos) { case (TBL_DATA_HORIZ): /* FALLTHROUGH */ + case (TBL_DATA_NHORIZ): + tbl_char(tp, '-', tbp->width); + return; + case (TBL_DATA_NDHORIZ): + /* FALLTHROUGH */ case (TBL_DATA_DHORIZ): - tbl_data_spanner(tp, dp, tbp); + tbl_char(tp, '=', tbp->width); return; default: break; @@ -246,9 +271,10 @@ tbl_data(struct termp *tp, const struct tbl *tbl, switch (pos) { case (TBL_CELL_HORIZ): - /* FALLTHROUGH */ + tbl_char(tp, '-', tbp->width); + break; case (TBL_CELL_DHORIZ): - tbl_data_spanner(tp, dp, tbp); + tbl_char(tp, '=', tbp->width); break; case (TBL_CELL_LONG): /* FALLTHROUGH */ @@ -292,69 +318,51 @@ tbl_vframe(struct termp *tp, const struct tbl *tbl) term_word(tp, "|"); } - static inline void tbl_char(struct termp *tp, char c, int len) { - int i; + int i, sz; char cp[2]; cp[0] = c; cp[1] = '\0'; - for (i = 0; i < len; i++) + sz = term_strlen(tp, cp); + + for (i = 0; i < len; i += sz) term_word(tp, cp); } static void -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, '-', tblp->width); - break; - case (TBL_DATA_DHORIZ): - case (TBL_DATA_NDHORIZ): - tbl_char(tp, '=', tblp->width); - break; - default: - break; - } -} - -static void tbl_data_literal(struct termp *tp, const struct tbl_dat *dp, const struct termp_tbl *tblp) { - int padl, padr; + int padl, padr, ssz; enum tbl_cellt pos; padl = padr = 0; pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT; + ssz = term_len(tp, 1); switch (pos) { case (TBL_CELL_LONG): - padl = 1; - padr = tblp->width - (int)strlen(dp->string) - 1; + padl = ssz; + padr = tblp->width - term_strlen(tp, dp->string) - ssz; break; case (TBL_CELL_CENTRE): - padl = tblp->width - (int)strlen(dp->string); + padl = tblp->width - term_strlen(tp, dp->string); if (padl % 2) padr++; padl /= 2; padr += padl; break; case (TBL_CELL_RIGHT): - padl = tblp->width - (int)strlen(dp->string); + padl = tblp->width - term_strlen(tp, dp->string); break; default: - padr = tblp->width - (int)strlen(dp->string); + padr = tblp->width - term_strlen(tp, dp->string); break; } @@ -368,27 +376,31 @@ tbl_data_number(struct termp *tp, const struct tbl *tb const struct tbl_dat *dp, const struct termp_tbl *tblp) { - char *decp, pnt; - int d, padl, sz; + char *decp, buf[2]; + int d, padl, sz, psz, ssz, i; /* * See calc_data_number(). Left-pad by taking the offset of our * and the maximum decimal; right-pad by the remaining amount. */ - sz = (int)strlen(dp->string); - pnt = tbl->decimal; + sz = term_strlen(tp, dp->string); + psz = term_strlen(tp, "."); - if (NULL == (decp = strchr(dp->string, pnt))) { - d = sz + 1; - } else { - d = (int)(decp - dp->string) + 1; - } + if (NULL != (decp = strchr(dp->string, tbl->decimal))) { + buf[1] = '\0'; + for (ssz = i = 0; decp != &dp->string[i]; i++) { + buf[0] = dp->string[i]; + ssz += term_strlen(tp, buf); + } + d = ssz + psz; + } else + d = sz + psz; assert(d <= tblp->decimal); assert(sz - d <= tblp->width - tblp->decimal); - padl = tblp->decimal - d + 1; + padl = tblp->decimal - d + term_len(tp, 1); assert(tblp->width - sz - padl); tbl_char(tp, ASCII_NBRSP, padl); @@ -397,7 +409,7 @@ tbl_data_number(struct termp *tp, const struct tbl *tb } static void -tbl_calc(const struct tbl_span *sp, struct termp_tbl *tblp) +tbl_calc(struct termp *tp, const struct tbl_span *sp) { const struct tbl_dat *dp; const struct tbl_head *hp; @@ -419,8 +431,8 @@ tbl_calc(const struct tbl_span *sp, struct termp_tbl * 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); + p = &tp->tbl[dp->layout->head->ident]; + tbl_calc_data(tp, sp->tbl, dp, p); } } @@ -429,10 +441,10 @@ tbl_calc(const struct tbl_span *sp, struct termp_tbl * for ( ; hp; hp = hp->next) switch (hp->pos) { case (TBL_HEAD_VERT): - tblp[hp->ident].width = 1; + tp->tbl[hp->ident].width = term_len(tp, 1); break; case (TBL_HEAD_DVERT): - tblp[hp->ident].width = 2; + tp->tbl[hp->ident].width = term_len(tp, 2); break; default: break; @@ -440,9 +452,8 @@ tbl_calc(const struct tbl_span *sp, struct termp_tbl * } static void -tbl_calc_data(const struct tbl *tbl, - const struct tbl_dat *dp, - struct termp_tbl *tblp) +tbl_calc_data(struct termp *tp, const struct tbl *tbl, + const struct tbl_dat *dp, struct termp_tbl *tblp) { /* Branch down into data sub-types. */ @@ -451,7 +462,7 @@ tbl_calc_data(const struct tbl *tbl, case (TBL_CELL_HORIZ): /* FALLTHROUGH */ case (TBL_CELL_DHORIZ): - tblp->width = 1; + tblp->width = term_len(tp, 1); break; case (TBL_CELL_LONG): /* FALLTHROUGH */ @@ -460,10 +471,10 @@ tbl_calc_data(const struct tbl *tbl, case (TBL_CELL_LEFT): /* FALLTHROUGH */ case (TBL_CELL_RIGHT): - tbl_calc_data_literal(dp, tblp); + tbl_calc_data_literal(tp, dp, tblp); break; case (TBL_CELL_NUMBER): - tbl_calc_data_number(tbl, dp, tblp); + tbl_calc_data_number(tp, tbl, dp, tblp); break; default: abort(); @@ -472,11 +483,11 @@ tbl_calc_data(const struct tbl *tbl, } static void -tbl_calc_data_number(const struct tbl *tbl, +tbl_calc_data_number(struct termp *tp, const struct tbl *tbl, const struct tbl_dat *dp, struct termp_tbl *tblp) { - int sz, d; - char *cp, pnt; + int sz, d, psz, i, ssz; + char *cp, buf[2]; /* * First calculate number width and decimal place (last + 1 for @@ -490,15 +501,20 @@ tbl_calc_data_number(const struct tbl *tbl, /* TODO: use spacing modifier. */ assert(dp->string); - sz = (int)strlen(dp->string); - pnt = tbl->decimal; + sz = term_strlen(tp, dp->string); + psz = term_strlen(tp, "."); - if (NULL == (cp = strchr(dp->string, pnt))) - d = sz + 1; - else - d = (int)(cp - dp->string) + 1; + if (NULL != (cp = strchr(dp->string, tbl->decimal))) { + buf[1] = '\0'; + for (ssz = i = 0; cp != &dp->string[i]; i++) { + buf[0] = dp->string[i]; + ssz += term_strlen(tp, buf); + } + d = ssz + psz; + } else + d = sz + psz; - sz += 2; + sz += term_len(tp, 2); if (tblp->decimal > d) { sz += tblp->decimal - d; @@ -513,9 +529,11 @@ tbl_calc_data_number(const struct tbl *tbl, } static void -tbl_calc_data_literal(const struct tbl_dat *dp, struct termp_tbl *tblp) +tbl_calc_data_literal(struct termp *tp, + const struct tbl_dat *dp, + struct termp_tbl *tblp) { - int sz, bufsz; + int sz, bufsz, spsz; /* * Calculate our width and use the spacing, with a minimum @@ -524,22 +542,25 @@ tbl_calc_data_literal(const struct tbl_dat *dp, struct */ assert(dp->string); - sz = (int)strlen(dp->string); + sz = term_strlen(tp, dp->string); switch (dp->layout->pos) { case (TBL_CELL_LONG): /* FALLTHROUGH */ case (TBL_CELL_CENTRE): - bufsz = 2; + bufsz = term_len(tp, 2); break; default: - bufsz = 1; + bufsz = term_len(tp, 1); break; } + spsz = 0; if (dp->layout->spacing) - bufsz = bufsz > dp->layout->spacing ? - bufsz : dp->layout->spacing; + spsz = term_len(tp, dp->layout->spacing); + + if (spsz) + bufsz = bufsz > spsz ? bufsz : spsz; sz += bufsz; if (tblp->width < sz)