summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc/man_html.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2017-01-26 18:28:06 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2017-01-26 18:28:06 +0000
commit93331e17aeecbfb33ec9c48521ade7aed914e609 (patch)
tree7f0e0c0163bdf88a25f6a7d19e60ad656b60acc5 /usr.bin/mandoc/man_html.c
parented8098d9ded7c0223cd86a93edde73daf3d18c5c (diff)
Fix -man -Thtml formatting after .nf (which has nothing to do
with "literal", by the way, it means "no fill"): * Use <pre> such that whitespace is preserved. * Preserve lines breaks. * For font alternating macros, avoid node recursion which required scary juggling with the fill state. Instead, simply print the text children directly. Missing feature first noticed by kristaps@ in 2011, the again reported by afresh1@ in 2016, and finally reported here: https://github.com/Debian/debiman/issues/21 , which i only found because of Shane Kerr's comment here: https://plus.google.com/110314300533310775053/posts/H1eaw9Yskoc
Diffstat (limited to 'usr.bin/mandoc/man_html.c')
-rw-r--r--usr.bin/mandoc/man_html.c105
1 files changed, 47 insertions, 58 deletions
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 180bb96a382..7693cbf7b4d 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: man_html.c,v 1.82 2017/01/21 01:20:29 schwarze Exp $ */
+/* $OpenBSD: man_html.c,v 1.83 2017/01/26 18:28:04 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -30,7 +30,6 @@
#include "html.h"
#include "main.h"
-/* TODO: preserve ident widths. */
/* FIXME: have PD set the default vspace width. */
#define INDENT 5
@@ -41,8 +40,7 @@
struct html *h
struct mhtml {
- int fl;
-#define MANH_LITERAL (1 << 0) /* literal context */
+ struct tag *nofill;
};
struct htmlman {
@@ -70,9 +68,9 @@ static int man_SS_pre(MAN_ARGS);
static int man_UR_pre(MAN_ARGS);
static int man_alt_pre(MAN_ARGS);
static int man_br_pre(MAN_ARGS);
+static int man_fill_pre(MAN_ARGS);
static int man_ign_pre(MAN_ARGS);
static int man_in_pre(MAN_ARGS);
-static int man_literal_pre(MAN_ARGS);
static void man_root_post(MAN_ARGS);
static void man_root_pre(MAN_ARGS);
@@ -99,8 +97,8 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_alt_pre, NULL }, /* IR */
{ man_alt_pre, NULL }, /* RI */
{ man_br_pre, NULL }, /* sp */
- { man_literal_pre, NULL }, /* nf */
- { man_literal_pre, NULL }, /* fi */
+ { man_fill_pre, NULL }, /* nf */
+ { man_fill_pre, NULL }, /* fi */
{ NULL, NULL }, /* RE */
{ man_RS_pre, NULL }, /* RS */
{ man_ign_pre, NULL }, /* DT */
@@ -110,8 +108,8 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_in_pre, NULL }, /* in */
{ man_ign_pre, NULL }, /* ft */
{ man_OP_pre, NULL }, /* OP */
- { man_literal_pre, NULL }, /* EX */
- { man_literal_pre, NULL }, /* EE */
+ { man_fill_pre, NULL }, /* EX */
+ { man_fill_pre, NULL }, /* EE */
{ man_UR_pre, NULL }, /* UR */
{ NULL, NULL }, /* UE */
{ man_ign_pre, NULL }, /* ll */
@@ -148,7 +146,7 @@ html_man(void *arg, const struct roff_man *man)
struct html *h;
struct tag *t;
- memset(&mh, 0, sizeof(mh));
+ mh.nofill = NULL;
h = (struct html *)arg;
if ((h->oflags & HTML_FRAGMENT) == 0) {
@@ -198,6 +196,8 @@ print_man_node(MAN_ARGS)
child = 1;
t = h->tags.head;
+ if (t == mh->nofill)
+ t = t->next;
switch (n->type) {
case ROFFT_TEXT:
@@ -205,12 +205,11 @@ print_man_node(MAN_ARGS)
print_paragraph(h);
return;
}
- if (n->flags & NODE_LINE && (*n->string == ' ' ||
- (n->prev != NULL && mh->fl & MANH_LITERAL &&
- ! (h->flags & HTML_NONEWLINE))))
+ if (mh->nofill == NULL &&
+ n->flags & NODE_LINE && *n->string == ' ')
print_otag(h, TAG_BR, "");
print_text(h, n->string);
- return;
+ break;
case ROFFT_EQN:
print_eqn(h, n->eqn);
break;
@@ -250,16 +249,15 @@ print_man_node(MAN_ARGS)
print_man_nodelist(man, n->child, mh, h);
/* This will automatically close out any font scope. */
- print_stagq(h, t);
+ print_stagq(h, mh->nofill == NULL ? t : mh->nofill);
- switch (n->type) {
- case ROFFT_EQN:
- break;
- default:
- if (mans[n->tok].post)
- (*mans[n->tok].post)(man, n, mh, h);
- break;
- }
+ if (n->type != ROFFT_TEXT && n->type != ROFFT_EQN &&
+ mans[n->tok].post != NULL)
+ (*mans[n->tok].post)(man, n, mh, h);
+
+ if (mh->nofill != NULL &&
+ (n->next == NULL || n->next->flags & NODE_LINE))
+ print_endline(h);
}
static int
@@ -347,13 +345,11 @@ man_br_pre(MAN_ARGS)
static int
man_SH_pre(MAN_ARGS)
{
- if (n->type == ROFFT_BLOCK) {
- mh->fl &= ~MANH_LITERAL;
- return 1;
- } else if (n->type == ROFFT_BODY)
- return 1;
-
- print_otag(h, TAG_H1, "c", "Sh");
+ if (n->type == ROFFT_BLOCK && mh->nofill != NULL) {
+ print_tagq(h, mh->nofill);
+ mh->nofill = NULL;
+ } else if (n->type == ROFFT_HEAD)
+ print_otag(h, TAG_H1, "c", "Sh");
return 1;
}
@@ -361,17 +357,11 @@ static int
man_alt_pre(MAN_ARGS)
{
const struct roff_node *nn;
- int i, savelit;
+ int i;
enum htmltag fp;
struct tag *t;
- if ((savelit = mh->fl & MANH_LITERAL))
- print_otag(h, TAG_BR, "");
-
- mh->fl &= ~MANH_LITERAL;
-
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
- t = NULL;
switch (n->tok) {
case MAN_BI:
fp = i % 2 ? TAG_I : TAG_B;
@@ -398,18 +388,14 @@ man_alt_pre(MAN_ARGS)
if (i)
h->flags |= HTML_NOSPACE;
- if (TAG_MAX != fp)
+ if (fp != TAG_MAX)
t = print_otag(h, fp, "");
- print_man_node(man, nn, mh, h);
+ print_text(h, nn->string);
- if (t)
+ if (fp != TAG_MAX)
print_tagq(h, t);
}
-
- if (savelit)
- mh->fl |= MANH_LITERAL;
-
return 0;
}
@@ -425,13 +411,11 @@ man_SM_pre(MAN_ARGS)
static int
man_SS_pre(MAN_ARGS)
{
- if (n->type == ROFFT_BLOCK) {
- mh->fl &= ~MANH_LITERAL;
- return 1;
- } else if (n->type == ROFFT_BODY)
- return 1;
-
- print_otag(h, TAG_H2, "c", "Ss");
+ if (n->type == ROFFT_BLOCK && mh->nofill != NULL) {
+ print_tagq(h, mh->nofill);
+ mh->nofill = NULL;
+ } else if (n->type == ROFFT_HEAD)
+ print_otag(h, TAG_H2, "c", "Ss");
return 1;
}
@@ -550,15 +534,20 @@ man_I_pre(MAN_ARGS)
}
static int
-man_literal_pre(MAN_ARGS)
+man_fill_pre(MAN_ARGS)
{
-
if (MAN_fi == n->tok || MAN_EE == n->tok) {
- print_otag(h, TAG_BR, "");
- mh->fl &= ~MANH_LITERAL;
- } else
- mh->fl |= MANH_LITERAL;
-
+ if (mh->nofill != NULL) {
+ print_tagq(h, mh->nofill);
+ mh->nofill = NULL;
+ } else
+ print_otag(h, TAG_BR, "");
+ } else {
+ if (mh->nofill == NULL)
+ mh->nofill = print_otag(h, TAG_PRE, "");
+ else
+ print_otag(h, TAG_BR, "");
+ }
return 0;
}