inside individual table cells that contain text blocks.
This cures overlong lines in various Xenocara manuals.
U+007f 0xc1bf ?? highest obfuscated ASCII
0xc278 ?x ASCII continuation
U+0080 0xc280 <80><80> lowest two-byte
- 0xc2c380 ?`\bA high continuation
+ 0xc2c380 ?`\bA high continuation
U+07FF 0xdfbf <?><?> highest two-byte
T\bTh\bhr\bre\bee\be-\b-b\bby\byt\bte\be r\bra\ban\bng\bge\be
-/* $OpenBSD: mandoc_aux.c,v 1.7 2015/10/12 21:09:08 schwarze Exp $ */
+/* $OpenBSD: mandoc_aux.c,v 1.8 2017/06/12 18:55:42 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
void *
mandoc_realloc(void *ptr, size_t size)
{
-
ptr = realloc(ptr, size);
if (ptr == NULL)
err((int)MANDOCLEVEL_SYSERR, NULL);
void *
mandoc_reallocarray(void *ptr, size_t num, size_t size)
{
-
ptr = reallocarray(ptr, num, size);
if (ptr == NULL)
err((int)MANDOCLEVEL_SYSERR, NULL);
return ptr;
}
+void *
+mandoc_recallocarray(void *ptr, size_t oldnum, size_t num, size_t size)
+{
+ ptr = recallocarray(ptr, oldnum, num, size);
+ if (ptr == NULL)
+ err((int)MANDOCLEVEL_SYSERR, NULL);
+ return ptr;
+}
+
char *
mandoc_strdup(const char *ptr)
{
-/* $OpenBSD: mandoc_aux.h,v 1.8 2017/02/09 17:19:07 schwarze Exp $ */
+/* $OpenBSD: mandoc_aux.h,v 1.9 2017/06/12 18:55:42 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);
void *mandoc_reallocarray(void *, size_t, size_t);
+void *mandoc_recallocarray(void *, size_t, size_t, size_t);
char *mandoc_strdup(const char *);
char *mandoc_strndup(const char *, size_t);
-/* $OpenBSD: tbl_term.c,v 1.34 2017/06/08 18:11:15 schwarze Exp $ */
+/* $OpenBSD: tbl_term.c,v 1.35 2017/06/12 18:55:42 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011,2012,2014,2015,2017 Ingo Schwarze <schwarze@openbsd.org>
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,
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);
tp->tbl.cols = NULL;
tp->tcol->offset = offset;
}
- tp->flags &= ~(TERMP_NONOSPACE | TERMP_BRNEVER);
+ tp->flags &= ~TERMP_NONOSPACE;
}
/*
-/* $OpenBSD: term.c,v 1.128 2017/06/08 12:54:40 schwarze Exp $ */
+/* $OpenBSD: term.c,v 1.129 2017/06/12 18:55:42 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
static void endline(struct termp *);
+void
+term_setcol(struct termp *p, size_t maxtcol)
+{
+ if (maxtcol > p->maxtcol) {
+ p->tcols = mandoc_recallocarray(p->tcols,
+ p->maxtcol, maxtcol, sizeof(*p->tcols));
+ p->maxtcol = maxtcol;
+ }
+ p->lasttcol = maxtcol - 1;
+ p->tcol = p->tcols;
+}
+
void
term_free(struct termp *p)
{
p->maxrmargin - p->viscol - vbl : 0;
vis = vend = 0;
- if (p->lasttcol == 0)
+ if ((p->flags && TERMP_MULTICOL) == 0)
p->tcol->col = 0;
- while (p->tcol->col < p->lastcol) {
+ while (p->tcol->col < p->tcol->lastcol) {
/*
* Handle literal tab characters: collapse all
*/
ntab = 0;
- while (p->tcol->col < p->lastcol &&
+ while (p->tcol->col < p->tcol->lastcol &&
p->tcol->buf[p->tcol->col] == '\t') {
vend = term_tab_next(vis);
vbl += vend - vis;
*/
jhy = 0;
- for (j = p->tcol->col; j < p->lastcol; j++) {
+ for (j = p->tcol->col; j < p->tcol->lastcol; j++) {
if (p->tcol->buf[j] == ' ' || p->tcol->buf[j] == '\t')
break;
if (vend > bp && jhy == 0 && vis > 0 &&
(p->flags & TERMP_BRNEVER) == 0) {
- if (p->lasttcol)
+ if (p->flags & TERMP_MULTICOL)
return;
endline(p);
* Write out the rest of the word.
*/
- for ( ; p->tcol->col < p->lastcol; p->tcol->col++) {
+ for ( ; p->tcol->col < p->tcol->lastcol; p->tcol->col++) {
if (vend > bp && jhy > 0 && p->tcol->col > jhy)
break;
if (p->tcol->buf[p->tcol->col] == '\t')
break;
if (p->tcol->buf[p->tcol->col] == ' ') {
j = p->tcol->col;
- while (p->tcol->col < p->lastcol &&
+ while (p->tcol->col < p->tcol->lastcol &&
p->tcol->buf[p->tcol->col] == ' ')
p->tcol->col++;
dv = (p->tcol->col - j) * (*p->width)(p, ' ');
else
vis = 0;
- p->col = p->lastcol = 0;
+ p->col = p->tcol->col = p->tcol->lastcol = 0;
p->minbl = p->trailspace;
p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE | TERMP_NOPAD);
+ if (p->flags & TERMP_MULTICOL)
+ return;
+
/* Trailing whitespace is significant in some columns. */
if (vis && vbl && (TERMP_BRTRSP & p->flags))
{
p->flags |= TERMP_NOSPACE;
- if (p->lastcol || p->viscol)
+ if (p->tcol->lastcol || p->viscol)
term_flushln(p);
}
}
}
/* Trim trailing backspace/blank pair. */
- if (p->lastcol > 2 &&
- (p->tcol->buf[p->lastcol - 1] == ' ' ||
- p->tcol->buf[p->lastcol - 1] == '\t'))
- p->lastcol -= 2;
- if (p->col > p->lastcol)
- p->col = p->lastcol;
+ if (p->tcol->lastcol > 2 &&
+ (p->tcol->buf[p->tcol->lastcol - 1] == ' ' ||
+ p->tcol->buf[p->tcol->lastcol - 1] == '\t'))
+ p->tcol->lastcol -= 2;
+ if (p->col > p->tcol->lastcol)
+ p->col = p->tcol->lastcol;
continue;
default:
continue;
}
if (p->col + 1 >= p->tcol->maxcols)
adjbuf(p->tcol, p->col + 1);
- if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
+ if (p->tcol->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
p->tcol->buf[p->col] = c;
- if (p->lastcol < ++p->col)
- p->lastcol = p->col;
+ if (p->tcol->lastcol < ++p->col)
+ p->tcol->lastcol = p->col;
}
/*
p->tcol->buf[p->col++] = c;
p->tcol->buf[p->col++] = '\b';
}
- if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
+ if (p->tcol->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
p->tcol->buf[p->col] = c;
- if (p->lastcol < ++p->col)
- p->lastcol = p->col;
+ if (p->tcol->lastcol < ++p->col)
+ p->tcol->lastcol = p->col;
if (p->flags & TERMP_BACKAFTER) {
p->flags |= TERMP_BACKBEFORE;
p->flags &= ~TERMP_BACKAFTER;
isgraph((unsigned char)word[i]))
encode1(p, word[i]);
else {
- if (p->lastcol <= p->col ||
+ if (p->tcol->lastcol <= p->col ||
(word[i] != ' ' && word[i] != ASCII_NBRSP))
p->tcol->buf[p->col] = word[i];
p->col++;
}
}
}
- if (p->lastcol < p->col)
- p->lastcol = p->col;
+ if (p->tcol->lastcol < p->col)
+ p->tcol->lastcol = p->col;
}
void
-/* $OpenBSD: term.h,v 1.70 2017/06/07 20:01:07 schwarze Exp $ */
+/* $OpenBSD: term.h,v 1.71 2017/06/12 18:55:42 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
struct termp_col {
int *buf; /* Output buffer. */
size_t maxcols; /* Allocated bytes in buf. */
+ size_t lastcol; /* Last byte in buf. */
size_t col; /* Byte in buf to be written. */
size_t rmargin; /* Current right margin. */
size_t offset; /* Current left margin. */
size_t lastrmargin; /* Right margin before the last ll. */
size_t maxrmargin; /* Max right margin. */
size_t col; /* Byte position in buf. */
- size_t lastcol; /* Bytes in buf. */
size_t viscol; /* Chars on current line. */
size_t trailspace; /* See term_flushln(). */
size_t minbl; /* Minimum blanks before next field. */
#define TERMP_NOBUF (1 << 17) /* Bypass output buffer. */
#define TERMP_NEWMC (1 << 18) /* No .mc printed yet. */
#define TERMP_ENDMC (1 << 19) /* Next break ends .mc mode. */
+#define TERMP_MULTICOL (1 << 20) /* Multiple column mode. */
enum termtype type; /* Terminal, PS, or PDF. */
enum termenc enc; /* Type of encoding. */
enum termfont fontl; /* Last font set. */
void term_eqn(struct termp *, const struct eqn *);
void term_tbl(struct termp *, const struct tbl_span *);
void term_free(struct termp *);
+void term_setcol(struct termp *, size_t);
void term_newln(struct termp *);
void term_vspace(struct termp *);
void term_word(struct termp *, const char *);