aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tbl_term.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-06-12 19:05:47 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-06-12 19:05:47 +0000
commite0177b9bff2cd6141e183411fe5a31f6ba8fe1a9 (patch)
tree6bd3def11ff1053a38ced25716cddbf6378e26c9 /tbl_term.c
parent603cf4a99d61372bf702e449ab0aba998312b923 (diff)
downloadmandoc-e0177b9bff2cd6141e183411fe5a31f6ba8fe1a9.tar.gz
mandoc-e0177b9bff2cd6141e183411fe5a31f6ba8fe1a9.tar.zst
mandoc-e0177b9bff2cd6141e183411fe5a31f6ba8fe1a9.zip
Implement automatic line breaking
inside individual table cells that contain text blocks. This cures overlong lines in various Xenocara manuals.
Diffstat (limited to 'tbl_term.c')
-rw-r--r--tbl_term.c214
1 files changed, 157 insertions, 57 deletions
diff --git a/tbl_term.c b/tbl_term.c
index 52c41a21..36fa2b70 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_term.c,v 1.46 2017/06/08 18:11:22 schwarze Exp $ */
+/* $Id: tbl_term.c,v 1.47 2017/06/12 19:05:47 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011,2012,2014,2015,2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -68,12 +68,13 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
const struct tbl_cell *cp;
const struct tbl_dat *dp;
static size_t offset;
- size_t tsz;
- int ic, horiz, spans, vert;
+ size_t coloff, tsz;
+ int ic, horiz, spans, vert, more;
+ char fc;
/* Inhibit printing of spaces: we do padding ourselves. */
- tp->flags |= TERMP_NOSPACE | TERMP_NONOSPACE | TERMP_BRNEVER;
+ tp->flags |= TERMP_NOSPACE | TERMP_NONOSPACE;
/*
* The first time we're invoked for a given table block,
@@ -111,82 +112,181 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
tbl_hrule(tp, sp, 1);
}
- /* Vertical frame at the start of each row. */
+ /* Set up the columns. */
- horiz = sp->pos == TBL_SPAN_HORIZ || sp->pos == TBL_SPAN_DHORIZ;
+ tp->flags |= TERMP_MULTICOL;
+ horiz = 0;
+ switch (sp->pos) {
+ case TBL_SPAN_HORIZ:
+ case TBL_SPAN_DHORIZ:
+ horiz = 1;
+ term_setcol(tp, 1);
+ break;
+ case TBL_SPAN_DATA:
+ term_setcol(tp, sp->opts->cols + 2);
+ coloff = tp->tcol->offset;
- if (sp->layout->vert ||
- (sp->prev != NULL && sp->prev->layout->vert) ||
- sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))
- term_word(tp, horiz ? "+" : "|");
- else if (sp->opts->lvert)
- tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
+ /* Set up a column for a left vertical frame. */
- /*
- * Now print the actual data itself depending on the span type.
- * Match data cells to column numbers.
- */
+ if (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ||
+ sp->opts->lvert)
+ coloff++;
+ tp->tcol->rmargin = coloff;
+
+ /* Set up the data columns. */
- if (sp->pos == TBL_SPAN_DATA) {
- cp = sp->layout->first;
dp = sp->first;
spans = 0;
for (ic = 0; ic < sp->opts->cols; ic++) {
+ if (spans == 0) {
+ tp->tcol++;
+ tp->tcol->offset = coloff;
+ }
+ coloff += tp->tbl.cols[ic].width;
+ tp->tcol->rmargin = coloff;
+ coloff++;
+ if (ic + 1 < sp->opts->cols)
+ coloff += 2;
+ if (spans) {
+ spans--;
+ continue;
+ }
+ if (dp == NULL)
+ continue;
+ spans = dp->spans;
+ dp = dp->next;
+ }
- /*
- * Remeber whether we need a vertical bar
- * after this cell.
- */
+ /* Set up a column for a right vertical frame. */
- vert = cp == NULL ? 0 : cp->vert;
+ tp->tcol++;
+ tp->tcol->offset = coloff;
+ if (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ||
+ sp->opts->rvert)
+ coloff++;
+ tp->tcol->rmargin = coloff;
- /*
- * Print the data and advance to the next cell.
- */
+ /* Spans may have reduced the number of columns. */
- if (spans == 0) {
- tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic);
- if (dp != NULL) {
- spans = dp->spans;
- dp = dp->next;
- }
- } else
- spans--;
- if (cp != NULL)
- cp = cp->next;
+ tp->lasttcol = tp->tcol - tp->tcols;
- /*
- * Separate columns, except in the middle
- * of spans and after the last cell.
- */
+ /* Fill the buffers for all data columns. */
- if (ic + 1 == sp->opts->cols || spans)
+ tp->tcol = tp->tcols;
+ dp = sp->first;
+ spans = 0;
+ for (ic = 0; ic < sp->opts->cols; ic++) {
+ if (spans) {
+ spans--;
+ continue;
+ }
+ tp->tcol++;
+ tp->col = 0;
+ tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic);
+ if (dp == NULL)
continue;
+ spans = dp->spans;
+ dp = dp->next;
+ }
+ break;
+ }
- tbl_char(tp, ASCII_NBRSP, 1);
- if (vert > 0)
- tbl_char(tp, '|', vert);
- if (vert < 2)
- tbl_char(tp, ASCII_NBRSP, 2 - vert);
+ do {
+ /* Print the vertical frame at the start of each row. */
+
+ tp->tcol = tp->tcols;
+ fc = '\0';
+ if (sp->layout->vert ||
+ (sp->prev != NULL && sp->prev->layout->vert) ||
+ sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))
+ fc = horiz ? '+' : '|';
+ else if (horiz && sp->opts->lvert)
+ fc = '-';
+ if (fc != '\0') {
+ (*tp->advance)(tp, tp->tcols->offset);
+ (*tp->letter)(tp, fc);
+ tp->viscol = tp->tcol->offset + 1;
}
- } else if (horiz)
- tbl_hrule(tp, sp, 0);
- /* Vertical frame at the end of each row. */
+ /* Print the data cells. */
+
+ more = 0;
+ if (horiz) {
+ tbl_hrule(tp, sp, 0);
+ term_flushln(tp);
+ } else {
+ cp = sp->layout->first;
+ dp = sp->first;
+ spans = 0;
+ for (ic = 0; ic < sp->opts->cols; ic++) {
+ if (spans == 0) {
+ tp->tcol++;
+ if (dp != NULL) {
+ spans = dp->spans;
+ dp = dp->next;
+ }
+ if (tp->tcol->col < tp->tcol->lastcol)
+ term_flushln(tp);
+ if (tp->tcol->col < tp->tcol->lastcol)
+ more = 1;
+ if (tp->tcol + 1 ==
+ tp->tcols + tp->lasttcol)
+ continue;
+ } else
+ spans--;
+
+ /* Vertical frames between data cells. */
+
+ if (cp != NULL) {
+ vert = cp->vert;
+ cp = cp->next;
+ } else
+ vert = 0;
+ if (vert == 0)
+ continue;
+
+ if (tp->tcol->rmargin + 1 > tp->viscol) {
+ (*tp->advance)(tp, tp->tcol->rmargin
+ + 1 - tp->viscol);
+ tp->viscol = tp->tcol->rmargin + 1;
+ }
+ while (vert--) {
+ (*tp->letter)(tp, '|');
+ tp->viscol++;
+ }
+ }
+ }
- if (sp->layout->last->vert ||
- (sp->prev != NULL && sp->prev->layout->last->vert) ||
- (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))
- term_word(tp, horiz ? "+" : " |");
- else if (sp->opts->rvert)
- tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
- term_flushln(tp);
+ /* Print the vertical frame at the end of each row. */
+
+ fc = '\0';
+ if (sp->layout->last->vert ||
+ (sp->prev != NULL && sp->prev->layout->last->vert) ||
+ (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))
+ fc = horiz ? '+' : '|';
+ else if (horiz && sp->opts->rvert)
+ fc = '-';
+ if (fc != '\0') {
+ if (horiz == 0) {
+ tp->tcol++;
+ (*tp->advance)(tp,
+ tp->tcol->offset > tp->viscol ?
+ tp->tcol->offset - tp->viscol : 1);
+ }
+ (*tp->letter)(tp, fc);
+ }
+ (*tp->endline)(tp);
+ tp->viscol = 0;
+ } while (more);
/*
* If we're the last row, clean up after ourselves: clear the
* existing table configuration and set it to NULL.
*/
+ term_setcol(tp, 1);
+ tp->flags &= ~TERMP_MULTICOL;
+ tp->tcol->rmargin = tp->maxrmargin;
if (sp->next == NULL) {
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
tbl_hrule(tp, sp, 1);
@@ -201,7 +301,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
tp->tbl.cols = NULL;
tp->tcol->offset = offset;
}
- tp->flags &= ~(TERMP_NONOSPACE | TERMP_BRNEVER);
+ tp->flags &= ~TERMP_NONOSPACE;
}
/*