- tbl->last_span = tbl->first_span = dp;
-
- if ( ! strcmp(p, "_")) {
- dp->flags |= TBL_SPAN_HORIZ;
- return(1);
- } else if ( ! strcmp(p, "=")) {
- dp->flags |= TBL_SPAN_DHORIZ;
- return(1);
+ dp->prev->next = dp;
+ tbl->last_span = dp;
+
+ return dp;
+}
+
+void
+tbl_data(struct tbl_node *tbl, int ln, const char *p, int pos)
+{
+ struct tbl_row *rp;
+ struct tbl_cell *cp;
+ struct tbl_span *sp;
+
+ rp = (sp = tbl->last_span) == NULL ? tbl->first_row :
+ sp->pos == TBL_SPAN_DATA && sp->layout->next != NULL ?
+ sp->layout->next : sp->layout;
+
+ assert(rp != NULL);
+
+ if (p[1] == '\0') {
+ switch (p[0]) {
+ case '.':
+ /*
+ * Empty request lines must be handled here
+ * and cannot be discarded in roff_parseln()
+ * because in the layout section, they
+ * are significant and end the layout.
+ */
+ return;
+ case '_':
+ sp = newspan(tbl, ln, rp);
+ sp->pos = TBL_SPAN_HORIZ;
+ return;
+ case '=':
+ sp = newspan(tbl, ln, rp);
+ sp->pos = TBL_SPAN_DHORIZ;
+ return;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * If the layout row contains nothing but horizontal lines,
+ * allocate an empty span for it and assign the current span
+ * to the next layout row accepting data.
+ */
+
+ while (rp->next != NULL) {
+ if (rp->last->col + 1 < tbl->opts.cols)
+ break;
+ for (cp = rp->first; cp != NULL; cp = cp->next)
+ if (cp->pos != TBL_CELL_HORIZ &&
+ cp->pos != TBL_CELL_DHORIZ)
+ break;
+ if (cp != NULL)
+ break;
+ sp = newspan(tbl, ln, rp);
+ sp->pos = TBL_SPAN_DATA;
+ rp = rp->next;