From dd2df837b0207b8180c9ec795b7e9dced6131bee Mon Sep 17 00:00:00 2001 From: schwarze Date: Mon, 15 Aug 2022 13:01:40 +0000 Subject: [PATCH] In GNU, Heirloom, and Plan 9 roff, tab positions apply to *input* lines, not to *output* lines. In particular, if an input line gets broken in fill mode and a tab occurs in the second output line, it advances to a position of at least (width of the first output line) + (width of a space character even though this is never printed) + (width of the part of the second output line that precedes the tab). Implement the same logic in mandoc. Again, do not use tabs in filled text: they have surprising effects, including this one. --- usr.bin/mandoc/man_term.c | 3 ++- usr.bin/mandoc/term.c | 19 +++++++++++-------- usr.bin/mandoc/term.h | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c index 2152cdea691..2433abcdbae 100644 --- a/usr.bin/mandoc/man_term.c +++ b/usr.bin/mandoc/man_term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: man_term.c,v 1.190 2022/04/27 17:04:15 schwarze Exp $ */ +/* $OpenBSD: man_term.c,v 1.191 2022/08/15 13:01:40 schwarze Exp $ */ /* * Copyright (c) 2010-2015,2017-2020,2022 Ingo Schwarze * Copyright (c) 2008-2012 Kristaps Dzonsons @@ -973,6 +973,7 @@ out: ! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) && (n->next == NULL || n->next->flags & NODE_LINE)) { p->flags |= TERMP_BRNEVER | TERMP_NOSPACE; + p->tcol->taboff = 0; if (n->string != NULL && *n->string != '\0') term_flushln(p); else diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index b57296c45ce..fe098f76c0b 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: term.c,v 1.147 2022/08/15 10:21:01 schwarze Exp $ */ +/* $OpenBSD: term.c,v 1.148 2022/08/15 13:01:40 schwarze Exp $ */ /* * Copyright (c) 2010-2022 Ingo Schwarze * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons @@ -155,6 +155,7 @@ term_flushln(struct termp *p) /* Finally, print the field content. */ term_field(p, vbl, nbr); + p->tcol->taboff += vbr + (*p->width)(p, ' '); /* * If there is no text left in the field, exit the loop. @@ -307,7 +308,9 @@ term_fill(struct termp *p, size_t *nbr, size_t *vbr, size_t vtarget) default: switch (p->tcol->buf[ic]) { case '\t': + vis += p->tcol->taboff; vis = term_tab_next(vis); + vis -= p->tcol->taboff; break; case ASCII_NBRSP: /* Non-breakable space. */ p->tcol->buf[ic] = ' '; @@ -346,8 +349,8 @@ term_field(struct termp *p, size_t vbl, size_t nbr) { size_t ic; /* Character position in the input buffer. */ size_t vis; /* Visual position of the current character. */ + size_t vt; /* Visual position including tab offset. */ size_t dv; /* Visual width of the current character. */ - size_t vn; /* Visual position of the next character. */ vis = 0; for (ic = p->tcol->col; ic < nbr; ic++) { @@ -362,13 +365,13 @@ term_field(struct termp *p, size_t vbl, size_t nbr) case ASCII_BREAK: continue; case '\t': - vn = term_tab_next(vis); - vbl += vn - vis; - vis = vn; - continue; case ' ': case ASCII_NBRSP: - dv = (*p->width)(p, ' '); + if (p->tcol->buf[ic] == '\t') { + vt = p->tcol->taboff + vis; + dv = term_tab_next(vt) - vt; + } else + dv = (*p->width)(p, ' '); vbl += dv; vis += dv; continue; @@ -430,7 +433,7 @@ endline(struct termp *p) void term_newln(struct termp *p) { - + p->tcol->taboff = 0; p->flags |= TERMP_NOSPACE; if (p->tcol->lastcol || p->viscol) term_flushln(p); diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index deba9352979..afdc5591f57 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -1,4 +1,4 @@ -/* $OpenBSD: term.h,v 1.76 2021/10/04 18:56:24 schwarze Exp $ */ +/* $OpenBSD: term.h,v 1.77 2022/08/15 13:01:40 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2011-2015, 2017, 2019 Ingo Schwarze @@ -56,6 +56,7 @@ struct termp_col { size_t col; /* Byte in buf to be written. */ size_t rmargin; /* Current right margin. */ size_t offset; /* Current left margin. */ + size_t taboff; /* Offset for literal tabs. */ }; struct termp { -- 2.20.1