Simplify handling of no-fill mode in man(7) by inspecting NODE_NOFILL
authorschwarze <schwarze@openbsd.org>
Mon, 15 Aug 2022 18:44:24 +0000 (18:44 +0000)
committerschwarze <schwarze@openbsd.org>
Mon, 15 Aug 2022 18:44:24 +0000 (18:44 +0000)
at the beginning of the node handler, in the same way as it is done
in the mdoc(7) node handler.

As a side effect, this also fixes a bug: if an input line contained
nothing but an escape sequence producing no output whatsoever (for
example, \fR), the old code incorrectly emitted a blank line anyway,
whereas the new code only emits such a blank link if the input line
actually produces output (even invisible zero-width output). To make
the distinction, the ASCII_NBRZW -> lastcol -> term_newln() mechanism
established in term.c rev. 1.149 is used.

usr.bin/mandoc/man_term.c

index 2433abc..2ca2533 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: man_term.c,v 1.191 2022/08/15 13:01:40 schwarze Exp $ */
+/* $OpenBSD: man_term.c,v 1.192 2022/08/15 18:44:24 schwarze Exp $ */
 /*
  * Copyright (c) 2010-2015,2017-2020,2022 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -515,7 +515,7 @@ pre_IP(DECL_ARGS)
                p->trailspace = 1;
                break;
        case ROFFT_BODY:
-               p->flags |= TERMP_NOSPACE;
+               p->flags |= TERMP_NOSPACE | TERMP_NONEWLINE;
                break;
        default:
                abort();
@@ -589,7 +589,7 @@ pre_TP(DECL_ARGS)
                p->trailspace = 1;
                break;
        case ROFFT_BODY:
-               p->flags |= TERMP_NOSPACE;
+               p->flags |= TERMP_NOSPACE | TERMP_NONEWLINE;
                break;
        default:
                abort();
@@ -898,6 +898,19 @@ print_man_node(DECL_ARGS)
        const struct man_term_act *act;
        int c;
 
+       /*
+        * In no-fill mode, break the output line at the beginning
+        * of new input lines except after \c, and nowhere else.
+        */
+
+       if (n->flags & NODE_NOFILL) {
+               if (n->flags & NODE_LINE &&
+                   (p->flags & TERMP_NONEWLINE) == 0)
+                       term_newln(p);
+               p->flags |= TERMP_BRNEVER;
+       } else
+               p->flags &= ~TERMP_BRNEVER;
+
        if (n->flags & NODE_ID)
                term_tag_write(n, p->line);
 
@@ -962,28 +975,11 @@ print_man_node(DECL_ARGS)
                term_fontrepl(p, TERMFONT_NONE);
 
 out:
-       /*
-        * If we're in a literal context, make sure that words
-        * together on the same line stay together.  This is a
-        * POST-printing call, so we check the NEXT word.  Since
-        * -man doesn't have nested macros, we don't need to be
-        * more specific than this.
-        */
-       if (n->flags & NODE_NOFILL &&
-           ! (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
-                       term_newln(p);
-               p->flags &= ~TERMP_BRNEVER;
-               if (p->tcol->rmargin < p->maxrmargin &&
-                   n->parent->tok == MAN_HP) {
-                       p->tcol->offset = p->tcol->rmargin;
-                       p->tcol->rmargin = p->maxrmargin;
-               }
+       if (n->parent->tok == MAN_HP && n->parent->type == ROFFT_BODY &&
+           n->prev == NULL && n->flags & NODE_NOFILL) {
+               term_newln(p);
+               p->tcol->offset = p->tcol->rmargin;
+               p->tcol->rmargin = p->maxrmargin;
        }
        if (n->flags & NODE_EOS)
                p->flags |= TERMP_SENTENCE;