diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2017-01-26 18:28:18 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2017-01-26 18:28:18 +0000 |
commit | 235ae1a6a0c472285b2c9310fe2e27c03a80393d (patch) | |
tree | b17150962d8d551f194058cfd460dfe4b358985b /man_html.c | |
parent | 596fca22f9c5c89fa592c0edf80c10f94529b3a6 (diff) | |
download | mandoc-235ae1a6a0c472285b2c9310fe2e27c03a80393d.tar.gz |
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 'man_html.c')
-rw-r--r-- | man_html.c | 103 |
1 files changed, 46 insertions, 57 deletions
@@ -32,7 +32,6 @@ #include "html.h" #include "main.h" -/* TODO: preserve ident widths. */ /* FIXME: have PD set the default vspace width. */ #define INDENT 5 @@ -43,8 +42,7 @@ struct html *h struct mhtml { - int fl; -#define MANH_LITERAL (1 << 0) /* literal context */ + struct tag *nofill; }; struct htmlman { @@ -72,9 +70,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); @@ -101,8 +99,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 */ @@ -112,8 +110,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 */ @@ -150,7 +148,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) { @@ -200,6 +198,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: @@ -207,12 +207,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; @@ -252,16 +251,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 @@ -349,13 +347,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; } @@ -363,17 +359,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; @@ -400,18 +390,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; } @@ -427,13 +413,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; } @@ -552,15 +536,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; } |