=================================================================== RCS file: /cvs/mandoc/html.c,v retrieving revision 1.242 retrieving revision 1.253 diff -u -p -r1.242 -r1.253 --- mandoc/html.c 2018/10/25 01:32:40 1.242 +++ mandoc/html.c 2019/03/01 10:57:17 1.253 @@ -1,7 +1,7 @@ -/* $Id: html.c,v 1.242 2018/10/25 01:32:40 schwarze Exp $ */ +/* $Id: html.c,v 1.253 2019/03/01 10:57:17 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons - * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze + * Copyright (c) 2011-2015, 2017-2019 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -63,6 +63,7 @@ static const struct htmldata htmltags[TAG_MAX] = { {"title", HTML_NLAROUND}, {"div", HTML_NLAROUND}, {"div", 0}, + {"section", HTML_NLALL}, {"h1", HTML_NLAROUND}, {"h2", HTML_NLAROUND}, {"span", 0}, @@ -78,6 +79,7 @@ static const struct htmldata htmltags[TAG_MAX] = { {"dl", HTML_NLALL | HTML_INDENT}, {"dt", HTML_NLAROUND}, {"dd", HTML_NLAROUND | HTML_INDENT}, + {"p", HTML_NLAROUND | HTML_INDENT}, {"pre", HTML_NLALL | HTML_NOINDENT}, {"var", 0}, {"cite", 0}, @@ -117,7 +119,6 @@ static void print_ctag(struct html *, struct tag *); static int print_escape(struct html *, char); static int print_encode(struct html *, const char *, const char *, int); static void print_href(struct html *, const char *, const char *, int); -static void print_metaf(struct html *, enum mandoc_esc); void * @@ -210,7 +211,7 @@ print_gen_head(struct html *h) print_tagq(h, t); } -static void +void print_metaf(struct html *h, enum mandoc_esc deco) { enum htmlfont font; @@ -236,7 +237,7 @@ print_metaf(struct html *h, enum mandoc_esc deco) font = HTMLFONT_NONE; break; default: - abort(); + return; } if (h->metaf) { @@ -266,6 +267,61 @@ print_metaf(struct html *h, enum mandoc_esc deco) } } +void +html_close_paragraph(struct html *h) +{ + struct tag *t; + + for (t = h->tag; t != NULL && t->closed == 0; t = t->next) { + switch(t->tag) { + case TAG_P: + case TAG_PRE: + print_tagq(h, t); + break; + case TAG_A: + print_tagq(h, t); + continue; + default: + continue; + } + break; + } +} + +/* + * ROFF_nf switches to no-fill mode, ROFF_fi to fill mode. + * TOKEN_NONE does not switch. The old mode is returned. + */ +enum roff_tok +html_fillmode(struct html *h, enum roff_tok want) +{ + struct tag *t; + enum roff_tok had; + + for (t = h->tag; t != NULL; t = t->next) + if (t->tag == TAG_PRE) + break; + + had = t == NULL ? ROFF_fi : ROFF_nf; + + if (want != had) { + switch (want) { + case ROFF_fi: + print_tagq(h, t); + break; + case ROFF_nf: + html_close_paragraph(h); + print_otag(h, TAG_PRE, ""); + break; + case TOKEN_NONE: + break; + default: + abort(); + } + } + return had; +} + char * html_make_id(const struct roff_node *n, int unique) { @@ -357,7 +413,6 @@ static int print_encode(struct html *h, const char *p, const char *pend, int norecurse) { char numbuf[16]; - struct tag *t; const char *seq; size_t sz; int c, len, breakline, nospace; @@ -383,9 +438,7 @@ print_encode(struct html *h, const char *p, const char if (breakline && (p >= pend || *p == ' ' || *p == ASCII_NBRSP)) { - t = print_otag(h, TAG_DIV, ""); - print_text(h, "\\~"); - print_tagq(h, t); + print_otag(h, TAG_BR, ""); breakline = 0; while (p < pend && (*p == ' ' || *p == ASCII_NBRSP)) p++; @@ -405,9 +458,6 @@ print_encode(struct html *h, const char *p, const char continue; esc = mandoc_escape(&p, &seq, &len); - if (ESCAPE_ERROR == esc) - break; - switch (esc) { case ESCAPE_FONT: case ESCAPE_FONTPREV: @@ -416,12 +466,17 @@ print_encode(struct html *h, const char *p, const char case ESCAPE_FONTBI: case ESCAPE_FONTCW: case ESCAPE_FONTROMAN: - if (0 == norecurse) + if (0 == norecurse) { + h->flags |= HTML_NOSPACE; print_metaf(h, esc); + h->flags &= ~HTML_NOSPACE; + } continue; case ESCAPE_SKIPCHAR: h->flags |= HTML_SKIPCHAR; continue; + case ESCAPE_ERROR: + continue; default: break; } @@ -446,6 +501,9 @@ print_encode(struct html *h, const char *p, const char if (c <= 0) continue; break; + case ESCAPE_UNDEF: + c = *seq; + break; case ESCAPE_DEVICE: print_word(h, "html"); continue; @@ -520,7 +578,7 @@ print_otag(struct html *h, enum htmltag tag, const cha struct tag *t; const char *attr; char *arg1, *arg2; - int tflags; + int style_written, tflags; tflags = htmltags[tag].flags; @@ -530,6 +588,8 @@ print_otag(struct html *h, enum htmltag tag, const cha t = mandoc_malloc(sizeof(struct tag)); t->tag = tag; t->next = h->tag; + t->refcnt = 0; + t->closed = 0; h->tag = t; } else t = NULL; @@ -560,7 +620,7 @@ print_otag(struct html *h, enum htmltag tag, const cha va_start(ap, fmt); - while (*fmt != '\0') { + while (*fmt != '\0' && *fmt != 's') { /* Parse attributes and arguments. */ @@ -576,10 +636,6 @@ print_otag(struct html *h, enum htmltag tag, const cha case 'i': attr = "id"; break; - case 's': - attr = "style"; - arg2 = va_arg(ap, char *); - break; case '?': attr = arg1; arg1 = va_arg(ap, char *); @@ -612,26 +668,33 @@ print_otag(struct html *h, enum htmltag tag, const cha print_encode(h, arg1, NULL, 1); fmt++; break; - case 'T': + default: print_encode(h, arg1, NULL, 1); - print_word(h, "\" title=\""); - print_encode(h, arg1, NULL, 1); - fmt++; break; - default: - if (arg2 == NULL) - print_encode(h, arg1, NULL, 1); - else { - print_word(h, arg1); - print_byte(h, ':'); - print_byte(h, ' '); - print_word(h, arg2); - print_byte(h, ';'); - } - break; } print_byte(h, '"'); } + + style_written = 0; + while (*fmt++ == 's') { + arg1 = va_arg(ap, char *); + arg2 = va_arg(ap, char *); + if (arg2 == NULL) + continue; + print_byte(h, ' '); + if (style_written == 0) { + print_word(h, "style=\""); + style_written = 1; + } + print_word(h, arg1); + print_byte(h, ':'); + print_byte(h, ' '); + print_word(h, arg2); + print_byte(h, ';'); + } + if (style_written) + print_byte(h, '"'); + va_end(ap); /* Accommodate for "well-formed" singleton escaping. */ @@ -659,33 +722,32 @@ print_ctag(struct html *h, struct tag *tag) { int tflags; - /* - * Remember to close out and nullify the current - * meta-font and table, if applicable. - */ - if (tag == h->metaf) - h->metaf = NULL; - if (tag == h->tblt) - h->tblt = NULL; + if (tag->closed == 0) { + tag->closed = 1; + if (tag == h->metaf) + h->metaf = NULL; + if (tag == h->tblt) + h->tblt = NULL; - tflags = htmltags[tag->tag].flags; - - if (tflags & HTML_INDENT) - h->indent--; - if (tflags & HTML_NOINDENT) - h->noindent--; - if (tflags & HTML_NLEND) - print_endline(h); - print_indent(h); - print_byte(h, '<'); - print_byte(h, '/'); - print_word(h, htmltags[tag->tag].name); - print_byte(h, '>'); - if (tflags & HTML_NLAFTER) - print_endline(h); - - h->tag = tag->next; - free(tag); + tflags = htmltags[tag->tag].flags; + if (tflags & HTML_INDENT) + h->indent--; + if (tflags & HTML_NOINDENT) + h->noindent--; + if (tflags & HTML_NLEND) + print_endline(h); + print_indent(h); + print_byte(h, '<'); + print_byte(h, '/'); + print_word(h, htmltags[tag->tag].name); + print_byte(h, '>'); + if (tflags & HTML_NLAFTER) + print_endline(h); + } + if (tag->refcnt == 0) { + h->tag = tag->next; + free(tag); + } } void @@ -772,34 +834,31 @@ print_text(struct html *h, const char *word) void print_tagq(struct html *h, const struct tag *until) { - struct tag *tag; + struct tag *this, *next; - while ((tag = h->tag) != NULL) { - print_ctag(h, tag); - if (until && tag == until) - return; + for (this = h->tag; this != NULL; this = next) { + next = this == until ? NULL : this->next; + print_ctag(h, this); } } +/* + * Close out all open elements up to but excluding suntil. + * Note that a paragraph just inside stays open together with it + * because paragraphs include subsequent phrasing content. + */ void print_stagq(struct html *h, const struct tag *suntil) { - struct tag *tag; + struct tag *this, *next; - while ((tag = h->tag) != NULL) { - if (suntil && tag == suntil) - return; - print_ctag(h, tag); + for (this = h->tag; this != NULL; this = next) { + next = this->next; + if (this == suntil || (next == suntil && + (this->tag == TAG_P || this->tag == TAG_PRE))) + break; + print_ctag(h, this); } -} - -void -print_paragraph(struct html *h) -{ - struct tag *t; - - t = print_otag(h, TAG_DIV, "c", "Pp"); - print_tagq(h, t); }