enum rofferr tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs) { int len; const char *cp; cp = &p[offs]; len = (int)strlen(cp); /* * If we're in the options section and we don't have a * terminating semicolon, assume we've moved directly into the * layout section. No need to report a warning: this is, * apparently, standard behaviour. */ if (TBL_PART_OPTS == tbl->part && len) if (';' != cp[len - 1]) tbl->part = TBL_PART_LAYOUT; /* Now process each logical section of the table. */ switch (tbl->part) { case (TBL_PART_OPTS): return(tbl_option(tbl, ln, p) ? ROFF_IGN : ROFF_ERR); case (TBL_PART_LAYOUT): return(tbl_layout(tbl, ln, p) ? ROFF_IGN : ROFF_ERR); case (TBL_PART_CDATA): return(tbl_cdata(tbl, ln, p) ? ROFF_TBL : ROFF_IGN); default: break; } /* * This only returns zero if the line is empty, so we ignore it * and continue on. */ return(tbl_data(tbl, ln, p) ? ROFF_TBL : ROFF_IGN); }
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; }