=================================================================== RCS file: /cvs/mandoc/tbl_term.c,v retrieving revision 1.17 retrieving revision 1.22 diff -u -p -r1.17 -r1.22 --- mandoc/tbl_term.c 2011/01/10 14:56:06 1.17 +++ mandoc/tbl_term.c 2012/05/27 17:54:54 1.22 @@ -1,6 +1,7 @@ -/* $Id: tbl_term.c,v 1.17 2011/01/10 14:56:06 kristaps Exp $ */ +/* $Id: tbl_term.c,v 1.22 2012/05/27 17:54:54 schwarze Exp $ */ /* - * Copyright (c) 2009 Kristaps Dzonsons + * Copyright (c) 2009, 2011 Kristaps Dzonsons + * Copyright (c) 2011 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -33,14 +34,14 @@ static void tbl_char(struct termp *, char, size_t); static void tbl_data(struct termp *, const struct tbl *, const struct tbl_dat *, const struct roffcol *); -static void tbl_hframe(struct termp *, const struct tbl_span *); +static size_t tbl_rulewidth(struct termp *, const struct tbl_head *); +static void tbl_hframe(struct termp *, const struct tbl_span *, int); static void tbl_literal(struct termp *, const struct tbl_dat *, const struct roffcol *); static void tbl_number(struct termp *, const struct tbl *, const struct tbl_dat *, const struct roffcol *); static void tbl_hrule(struct termp *, const struct tbl_span *); -static void tbl_vframe(struct termp *, const struct tbl *); static void tbl_vrule(struct termp *, const struct tbl_head *); @@ -94,12 +95,19 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) /* Horizontal frame at the start of boxed tables. */ - if (TBL_SPAN_FIRST & sp->flags) - tbl_hframe(tp, sp); + if (TBL_SPAN_FIRST & sp->flags) { + if (TBL_OPT_DBOX & sp->tbl->opts) + tbl_hframe(tp, sp, 1); + if (TBL_OPT_DBOX & sp->tbl->opts || + TBL_OPT_BOX & sp->tbl->opts) + tbl_hframe(tp, sp, 0); + } /* Vertical frame at the start of each row. */ - tbl_vframe(tp, sp->tbl); + if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts) + term_word(tp, TBL_SPAN_HORIZ == sp->pos || + TBL_SPAN_DHORIZ == sp->pos ? "+" : "|"); /* * Now print the actual data itself depending on the span type. @@ -118,25 +126,21 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) dp = sp->first; spans = 0; for (hp = sp->head; hp; hp = hp->next) { + /* * If the current data header is invoked during * a spanner ("spans" > 0), don't emit anything * at all. */ - switch (hp->pos) { - case (TBL_HEAD_VERT): - /* FALLTHROUGH */ - case (TBL_HEAD_DVERT): - if (spans <= 0) - tbl_vrule(tp, hp); - continue; - case (TBL_HEAD_DATA): - break; - } if (--spans >= 0) continue; + /* Separate columns. */ + + if (NULL != hp->prev) + tbl_vrule(tp, hp); + col = &tp->tbl.cols[hp->ident]; tbl_data(tp, sp->tbl, dp, col); @@ -153,7 +157,11 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) break; } - tbl_vframe(tp, sp->tbl); + /* Vertical frame at the end of each row. */ + + if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts) + term_word(tp, TBL_SPAN_HORIZ == sp->pos || + TBL_SPAN_DHORIZ == sp->pos ? "+" : " |"); term_flushln(tp); /* @@ -162,7 +170,11 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) */ if (TBL_SPAN_LAST & sp->flags) { - tbl_hframe(tp, sp); + if (TBL_OPT_DBOX & sp->tbl->opts || + TBL_OPT_BOX & sp->tbl->opts) + tbl_hframe(tp, sp, 0); + if (TBL_OPT_DBOX & sp->tbl->opts) + tbl_hframe(tp, sp, 1); assert(tp->tbl.cols); free(tp->tbl.cols); tp->tbl.cols = NULL; @@ -174,83 +186,64 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) } +/* + * Horizontal rules extend across the entire table. + * Calculate the width by iterating over columns. + */ +static size_t +tbl_rulewidth(struct termp *tp, const struct tbl_head *hp) +{ + size_t width; + + width = tp->tbl.cols[hp->ident].width; + + /* Account for leading blanks. */ + if (hp->prev) + width += 2 - hp->vert; + + /* Account for trailing blank. */ + width++; + + return(width); +} + +/* + * Rules inside the table can be single or double + * and have crossings with vertical rules marked with pluses. + */ static void tbl_hrule(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; char c; - size_t width; - /* - * An hrule extends across the entire table and is demarked by a - * standalone `_' or whatnot in lieu of a table row. Spanning - * headers are marked by a `+', as are table boundaries. - */ - c = '-'; if (TBL_SPAN_DHORIZ == sp->pos) c = '='; - /* FIXME: don't use `+' between data and a spanner! */ - for (hp = sp->head; hp; hp = hp->next) { - width = tp->tbl.cols[hp->ident].width; - switch (hp->pos) { - case (TBL_HEAD_DATA): - tbl_char(tp, c, width); - break; - case (TBL_HEAD_DVERT): - tbl_char(tp, '+', width); - /* FALLTHROUGH */ - case (TBL_HEAD_VERT): - tbl_char(tp, '+', width); - break; - default: - abort(); - /* NOTREACHED */ - } + if (hp->prev && hp->vert) + tbl_char(tp, '+', hp->vert); + tbl_char(tp, c, tbl_rulewidth(tp, hp)); } } +/* + * Rules above and below the table are always single + * and have an additional plus at the beginning and end. + * For double frames, this function is called twice, + * and the outer one does not have crossings. + */ static void -tbl_hframe(struct termp *tp, const struct tbl_span *sp) +tbl_hframe(struct termp *tp, const struct tbl_span *sp, int outer) { const struct tbl_head *hp; - size_t width; - if ( ! (TBL_OPT_BOX & sp->tbl->opts || - TBL_OPT_DBOX & sp->tbl->opts)) - return; - - /* - * Print out the horizontal part of a frame or double frame. A - * double frame has an unbroken `-' outer line the width of the - * table, bordered by `+'. The frame (or inner frame, in the - * case of the double frame) is a `-' bordered by `+' and broken - * by `+' whenever a span is encountered. - */ - - if (TBL_OPT_DBOX & sp->tbl->opts) { - term_word(tp, "+"); - for (hp = sp->head; hp; hp = hp->next) { - width = tp->tbl.cols[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.cols[hp->ident].width; - switch (hp->pos) { - case (TBL_HEAD_DATA): - tbl_char(tp, '-', width); - break; - default: - tbl_char(tp, '+', width); - break; - } + if (hp->prev && hp->vert) + tbl_char(tp, (outer ? '-' : '+'), hp->vert); + tbl_char(tp, '-', tbl_rulewidth(tp, hp)); } term_word(tp, "+"); term_flushln(tp); @@ -305,6 +298,9 @@ tbl_data(struct termp *tp, const struct tbl *tbl, case (TBL_CELL_NUMBER): tbl_number(tp, tbl, dp, col); break; + case (TBL_CELL_DOWN): + tbl_char(tp, ASCII_NBRSP, col->width); + break; default: abort(); /* NOTREACHED */ @@ -315,27 +311,14 @@ static void tbl_vrule(struct termp *tp, const struct tbl_head *hp) { - switch (hp->pos) { - case (TBL_HEAD_VERT): - term_word(tp, "|"); - break; - case (TBL_HEAD_DVERT): - term_word(tp, "||"); - break; - default: - break; - } + tbl_char(tp, ASCII_NBRSP, 1); + if (0 < hp->vert) + tbl_char(tp, '|', hp->vert); + if (2 > hp->vert) + tbl_char(tp, ASCII_NBRSP, 2 - hp->vert); } static void -tbl_vframe(struct termp *tp, const struct tbl *tbl) -{ - - if (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts) - term_word(tp, "|"); -} - -static void tbl_char(struct termp *tp, char c, size_t len) { size_t i, sz; @@ -354,31 +337,29 @@ static void tbl_literal(struct termp *tp, const struct tbl_dat *dp, const struct roffcol *col) { - size_t padl, padr, ssz; + size_t len, padl, padr; - padl = padr = 0; - assert(dp->string); + len = term_strlen(tp, dp->string); + padr = col->width > len ? col->width - len : 0; + padl = 0; - ssz = term_len(tp, 1); - switch (dp->layout->pos) { case (TBL_CELL_LONG): - padl = ssz; - padr = col->width - term_strlen(tp, dp->string) - ssz; + padl = term_len(tp, 1); + padr = padr > padl ? padr - padl : 0; break; case (TBL_CELL_CENTRE): - padl = col->width - term_strlen(tp, dp->string); - if (padl % 2) - padr++; - padl /= 2; - padr += padl; + if (2 > padr) + break; + padl = padr / 2; + padr -= padl; break; case (TBL_CELL_RIGHT): - padl = col->width - term_strlen(tp, dp->string); + padl = padr; + padr = 0; break; default: - padr = col->width - term_strlen(tp, dp->string); break; } @@ -421,13 +402,11 @@ tbl_number(struct termp *tp, const struct tbl *tbl, } else d = sz + psz; - sz += term_len(tp, 2); - d += term_len(tp, 1); - padl = col->decimal - d; tbl_char(tp, ASCII_NBRSP, padl); term_word(tp, dp->string); - tbl_char(tp, ASCII_NBRSP, col->width - sz - padl); + if (col->width > sz + padl) + tbl_char(tp, ASCII_NBRSP, col->width - sz - padl); }