=================================================================== RCS file: /cvs/mandoc/man_html.c,v retrieving revision 1.165 retrieving revision 1.172 diff -u -p -r1.165 -r1.172 --- mandoc/man_html.c 2019/01/05 21:55:11 1.165 +++ mandoc/man_html.c 2019/03/01 10:57:18 1.172 @@ -1,4 +1,4 @@ -/* $Id: man_html.c,v 1.165 2019/01/05 21:55:11 schwarze Exp $ */ +/* $Id: man_html.c,v 1.172 2019/03/01 10:57:18 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze @@ -42,14 +42,11 @@ struct man_html_act { int (*post)(MAN_ARGS); }; -static void print_bvspace(struct html *, - const struct roff_node *); static void print_man_head(const struct roff_meta *, struct html *); static void print_man_nodelist(MAN_ARGS); static void print_man_node(MAN_ARGS); static int man_B_pre(MAN_ARGS); -static int man_HP_pre(MAN_ARGS); static int man_IP_pre(MAN_ARGS); static int man_I_pre(MAN_ARGS); static int man_OP_pre(MAN_ARGS); @@ -57,7 +54,6 @@ static int man_PP_pre(MAN_ARGS); static int man_RS_pre(MAN_ARGS); static int man_SH_pre(MAN_ARGS); static int man_SM_pre(MAN_ARGS); -static int man_SS_pre(MAN_ARGS); static int man_SY_pre(MAN_ARGS); static int man_UR_pre(MAN_ARGS); static int man_abort_pre(MAN_ARGS); @@ -72,14 +68,14 @@ static void man_root_pre(const struct roff_meta *, static const struct man_html_act man_html_acts[MAN_MAX - MAN_TH] = { { NULL, NULL }, /* TH */ { man_SH_pre, NULL }, /* SH */ - { man_SS_pre, NULL }, /* SS */ + { man_SH_pre, NULL }, /* SS */ { man_IP_pre, NULL }, /* TP */ { man_IP_pre, NULL }, /* TQ */ { man_abort_pre, NULL }, /* LP */ { man_PP_pre, NULL }, /* PP */ { man_abort_pre, NULL }, /* P */ { man_IP_pre, NULL }, /* IP */ - { man_HP_pre, NULL }, /* HP */ + { man_PP_pre, NULL }, /* HP */ { man_SM_pre, NULL }, /* SM */ { man_SM_pre, NULL }, /* SB */ { man_alt_pre, NULL }, /* BI */ @@ -110,27 +106,6 @@ static const struct man_html_act man_html_acts[MAN_MAX }; -/* - * Printing leading vertical space before a block. - * This is used for the paragraph macros. - * The rules are pretty simple, since there's very little nesting going - * on here. Basically, if we're the first within another block (SS/SH), - * then don't emit vertical space. If we are (RS), then do. If not the - * first, print it. - */ -static void -print_bvspace(struct html *h, const struct roff_node *n) -{ - if (n->body != NULL && n->body->child != NULL && - n->body->child->type == ROFFT_TBL) - return; - - if (n->prev == NULL && n->parent->tok != MAN_RS) - return; - - print_paragraph(h); -} - void html_man(void *arg, const struct roff_meta *man) { @@ -144,7 +119,7 @@ html_man(void *arg, const struct roff_meta *man) if ((h->oflags & HTML_FRAGMENT) == 0) { print_gen_decls(h); print_otag(h, TAG_HTML, ""); - if (n->type == ROFFT_COMMENT) + if (n != NULL && n->type == ROFFT_COMMENT) print_gen_comment(h, n); t = print_otag(h, TAG_HEAD, ""); print_man_head(man, h); @@ -187,6 +162,9 @@ print_man_node(MAN_ARGS) struct tag *t; int child; + if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT) + return; + html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi); child = 1; @@ -196,18 +174,18 @@ print_man_node(MAN_ARGS) print_endline(h); return; } - t = h->tag; if (*n->string == ' ' && n->flags & NODE_LINE && (h->flags & HTML_NONEWLINE) == 0) print_endline(h); else if (n->flags & NODE_DELIMC) h->flags |= HTML_NOSPACE; + t = h->tag; + t->refcnt++; print_text(h, n->string); break; - case ROFFT_COMMENT: - return; case ROFFT_EQN: t = h->tag; + t->refcnt++; print_eqn(h, n->eqn); break; case ROFFT_TBL: @@ -235,14 +213,14 @@ print_man_node(MAN_ARGS) */ if (h->tblt != NULL) print_tblclose(h); - t = h->tag; + t->refcnt++; if (n->tok < ROFF_MAX) { roff_html_pre(h, n); + t->refcnt--; print_stagq(h, t); return; } - assert(n->tok >= MAN_TH && n->tok < MAN_MAX); if (man_html_acts[n->tok - MAN_TH].pre != NULL) child = (*man_html_acts[n->tok - MAN_TH].pre)(man, @@ -254,7 +232,26 @@ print_man_node(MAN_ARGS) print_man_nodelist(man, n->child, h); /* This will automatically close out any font scope. */ - print_stagq(h, t); + t->refcnt--; + if (n->type == ROFFT_BLOCK && + (n->tok == MAN_IP || n->tok == MAN_TP || n->tok == MAN_TQ)) { + t = h->tag; + while (t->tag != TAG_DL) + t = t->next; + /* + * Close the list if no further item of the same type + * follows; otherwise, close the item only. + */ + if (n->next == NULL || + (n->tok == MAN_IP && n->next->tok != MAN_IP) || + (n->tok != MAN_IP && + n->next->tok != MAN_TP && n->next->tok != MAN_TQ)) { + print_tagq(h, t); + t = NULL; + } + } + if (t != NULL) + print_stagq(h, t); if (n->flags & NODE_NOFILL && n->tok != MAN_YS && (n->next != NULL && n->next->flags & NODE_LINE)) { @@ -313,13 +310,32 @@ man_root_post(const struct roff_meta *man, struct html static int man_SH_pre(MAN_ARGS) { - char *id; + const char *class; + char *id; + enum htmltag tag; - if (n->type == ROFFT_HEAD) { + if (n->tok == MAN_SH) { + tag = TAG_H1; + class = "Sh"; + } else { + tag = TAG_H2; + class = "Ss"; + } + switch (n->type) { + case ROFFT_BLOCK: + html_close_paragraph(h); + print_otag(h, TAG_SECTION, "c", class); + break; + case ROFFT_HEAD: id = html_make_id(n, 1); - print_otag(h, TAG_H1, "cTi", "Sh", id); + print_otag(h, tag, "ci", class, id); if (id != NULL) print_otag(h, TAG_A, "chR", "permalink", id); + break; + case ROFFT_BODY: + break; + default: + abort(); } return 1; } @@ -380,27 +396,23 @@ man_SM_pre(MAN_ARGS) } static int -man_SS_pre(MAN_ARGS) -{ - char *id; - - if (n->type == ROFFT_HEAD) { - id = html_make_id(n, 1); - print_otag(h, TAG_H2, "cTi", "Ss", id); - if (id != NULL) - print_otag(h, TAG_A, "chR", "permalink", id); - } - return 1; -} - -static int man_PP_pre(MAN_ARGS) { - if (n->type == ROFFT_HEAD) + switch (n->type) { + case ROFFT_BLOCK: + html_close_paragraph(h); + break; + case ROFFT_HEAD: return 0; - else if (n->type == ROFFT_BLOCK) - print_bvspace(h, n); - + case ROFFT_BODY: + if (n->child != NULL && + (n->child->flags & NODE_NOFILL) == 0) + print_otag(h, TAG_P, "c", + n->tok == MAN_PP ? "Pp" : "Pp HP"); + break; + default: + abort(); + } return 1; } @@ -409,16 +421,29 @@ man_IP_pre(MAN_ARGS) { const struct roff_node *nn; - if (n->type == ROFFT_BODY) { + switch (n->type) { + case ROFFT_BLOCK: + html_close_paragraph(h); + /* + * Open a new list unless there is an immediately + * preceding item of the same type. + */ + if (n->prev == NULL || + (n->tok == MAN_IP && n->prev->tok != MAN_IP) || + (n->tok != MAN_IP && + n->prev->tok != MAN_TP && n->prev->tok != MAN_TQ)) + print_otag(h, TAG_DL, "c", "Bl-tag"); + return 1; + case ROFFT_HEAD: + print_otag(h, TAG_DT, ""); + break; + case ROFFT_BODY: print_otag(h, TAG_DD, ""); return 1; - } else if (n->type != ROFFT_HEAD) { - print_otag(h, TAG_DL, "c", "Bl-tag"); - return 1; + default: + abort(); } - print_otag(h, TAG_DT, ""); - switch(n->tok) { case MAN_IP: /* Only print the first header element. */ if (n->child != NULL) @@ -441,19 +466,6 @@ man_IP_pre(MAN_ARGS) } static int -man_HP_pre(MAN_ARGS) -{ - if (n->type == ROFFT_HEAD) - return 0; - - if (n->type == ROFFT_BLOCK) { - print_bvspace(h, n); - print_otag(h, TAG_DIV, "c", "HP"); - } - return 1; -} - -static int man_OP_pre(MAN_ARGS) { struct tag *tt; @@ -510,10 +522,18 @@ man_ign_pre(MAN_ARGS) static int man_RS_pre(MAN_ARGS) { - if (n->type == ROFFT_HEAD) + switch (n->type) { + case ROFFT_BLOCK: + html_close_paragraph(h); + break; + case ROFFT_HEAD: return 0; - if (n->type == ROFFT_BLOCK) + case ROFFT_BODY: print_otag(h, TAG_DIV, "c", "Bd-indent"); + break; + default: + abort(); + } return 1; } @@ -522,12 +542,13 @@ man_SY_pre(MAN_ARGS) { switch (n->type) { case ROFFT_BLOCK: + html_close_paragraph(h); print_otag(h, TAG_TABLE, "c", "Nm"); print_otag(h, TAG_TR, ""); break; case ROFFT_HEAD: print_otag(h, TAG_TD, ""); - print_otag(h, TAG_CODE, "cT", "Nm"); + print_otag(h, TAG_CODE, "c", "Nm"); break; case ROFFT_BODY: print_otag(h, TAG_TD, ""); @@ -549,10 +570,10 @@ man_UR_pre(MAN_ARGS) assert(n->child->type == ROFFT_TEXT); if (n->tok == MAN_MT) { mandoc_asprintf(&cp, "mailto:%s", n->child->string); - print_otag(h, TAG_A, "cTh", "Mt", cp); + print_otag(h, TAG_A, "ch", "Mt", cp); free(cp); } else - print_otag(h, TAG_A, "cTh", "Lk", n->child->string); + print_otag(h, TAG_A, "ch", "Lk", n->child->string); } assert(n->next->type == ROFFT_BODY);