void term_tbl(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; const struct tbl_dat *dp; struct roffcol *col; int spans; size_t rmargin, maxrmargin; rmargin = tp->rmargin; maxrmargin = tp->maxrmargin; tp->rmargin = tp->maxrmargin = TERM_MAXMARGIN; /* 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, * calculate the table widths and decimal positions. */ if (TBL_SPAN_FIRST & sp->flags) { term_flushln(tp); tp->tbl.len = term_tbl_len; tp->tbl.slen = term_tbl_strlen; tp->tbl.arg = tp; tblcalc(&tp->tbl, sp); } /* Horizontal frame at the start of boxed tables. */ if (TBL_SPAN_FIRST & sp->flags) { if (TBL_OPT_DBOX & sp->opts->opts) tbl_hframe(tp, sp, 1); if (TBL_OPT_DBOX & sp->opts->opts || TBL_OPT_BOX & sp->opts->opts) tbl_hframe(tp, sp, 0); } /* Vertical frame at the start of each row. */ if ((TBL_OPT_BOX | TBL_OPT_DBOX) & sp->opts->opts || sp->head->vert) term_word(tp, TBL_SPAN_HORIZ == sp->pos || TBL_SPAN_DHORIZ == sp->pos ? "+" : "|"); /* * 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); break; case TBL_SPAN_DATA: /* Iterate over template headers. */ 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. */ if (--spans >= 0) continue; /* Separate columns. */ if (NULL != hp->prev) tbl_vrule(tp, hp); col = &tp->tbl.cols[hp->ident]; tbl_data(tp, sp->opts, dp, col); /* * Go to the next data cell and assign the * number of subsequent spans, if applicable. */ if (dp) { spans = dp->spans; dp = dp->next; } } break; } /* Vertical frame at the end of each row. */ if ((TBL_OPT_BOX | TBL_OPT_DBOX) & sp->opts->opts || sp->layout->vert) term_word(tp, TBL_SPAN_HORIZ == sp->pos || TBL_SPAN_DHORIZ == sp->pos ? "+" : " |"); term_flushln(tp); /* * 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) { if (TBL_OPT_DBOX & sp->opts->opts || TBL_OPT_BOX & sp->opts->opts) { tbl_hframe(tp, sp, 0); tp->skipvsp = 1; } if (TBL_OPT_DBOX & sp->opts->opts) { tbl_hframe(tp, sp, 1); tp->skipvsp = 2; } assert(tp->tbl.cols); free(tp->tbl.cols); tp->tbl.cols = NULL; } tp->flags &= ~TERMP_NONOSPACE; tp->rmargin = rmargin; tp->maxrmargin = maxrmargin; }
void term_tbl(struct termp *tp, const struct tbl_span *sp) { const struct tbl_head *hp; const struct tbl_dat *dp; struct roffcol *col; size_t rmargin, maxrmargin; rmargin = tp->rmargin; maxrmargin = tp->maxrmargin; tp->rmargin = tp->maxrmargin = TERM_MAXMARGIN; /* 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, * calculate the table widths and decimal positions. */ if (TBL_SPAN_FIRST & sp->flags) { term_flushln(tp); tp->tbl.len = term_tbl_len; tp->tbl.slen = term_tbl_strlen; tp->tbl.arg = tp; tblcalc(&tp->tbl, sp); } /* Horizontal frame at the start of boxed tables. */ if (TBL_SPAN_FIRST & sp->flags) tbl_hframe(tp, sp); /* 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); 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_vrule(tp, hp); continue; case (TBL_HEAD_DATA): break; } col = &tp->tbl.cols[hp->ident]; tbl_data(tp, sp->tbl, dp, col); /* Go to the next data cell. */ if (dp) dp = dp->next; } break; } tbl_vframe(tp, sp->tbl); term_flushln(tp); /* * 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.cols); free(tp->tbl.cols); tp->tbl.cols = NULL; } tp->flags &= ~TERMP_NONOSPACE; tp->rmargin = rmargin; tp->maxrmargin = maxrmargin; }