=================================================================== RCS file: /cvs/mandoc/html.c,v retrieving revision 1.130 retrieving revision 1.148 diff -u -p -r1.130 -r1.148 --- mandoc/html.c 2011/03/22 10:13:01 1.130 +++ mandoc/html.c 2011/07/04 09:42:38 1.148 @@ -1,4 +1,4 @@ -/* $Id: html.c,v 1.130 2011/03/22 10:13:01 kristaps Exp $ */ +/* $Id: html.c,v 1.148 2011/07/04 09:42:38 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -31,6 +31,7 @@ #include #include "mandoc.h" +#include "libmandoc.h" #include "out.h" #include "html.h" #include "main.h" @@ -93,19 +94,25 @@ static const char *const htmlattrs[ATTR_MAX] = { "colspan", /* ATTR_COLSPAN */ }; -static void print_num(struct html *, const char *, size_t); -static void print_spec(struct html *, enum roffdeco, - const char *, size_t); -static void print_res(struct html *, const char *, size_t); -static void print_ctag(struct html *, enum htmltag); -static void print_doctype(struct html *); -static void print_xmltype(struct html *); -static int print_encode(struct html *, const char *, int); -static void print_metaf(struct html *, enum roffdeco); -static void print_attr(struct html *, - const char *, const char *); -static void *ml_alloc(char *, enum htmltype); +static const char *const roffscales[SCALE_MAX] = { + "cm", /* SCALE_CM */ + "in", /* SCALE_IN */ + "pc", /* SCALE_PC */ + "pt", /* SCALE_PT */ + "em", /* SCALE_EM */ + "em", /* SCALE_MM */ + "ex", /* SCALE_EN */ + "ex", /* SCALE_BU */ + "em", /* SCALE_VS */ + "ex", /* SCALE_FS */ +}; +static void bufncat(struct html *, const char *, size_t); +static void print_ctag(struct html *, enum htmltag); +static int print_encode(struct html *, const char *, int); +static void print_metaf(struct html *, enum mandoc_esc); +static void print_attr(struct html *, const char *, const char *); +static void *ml_alloc(char *, enum htmltype); static void * ml_alloc(char *outopts, enum htmltype type) @@ -123,7 +130,7 @@ ml_alloc(char *outopts, enum htmltype type) h->type = type; h->tags.head = NULL; - h->symtab = chars_init(CHARS_HTML); + h->symtab = mchars_alloc(); while (outopts && *outopts) switch (getsubopt(&outopts, UNCONST(toks), &v)) { @@ -173,7 +180,7 @@ html_free(void *p) } if (h->symtab) - chars_free(h->symtab); + mchars_free(h->symtab); free(h); } @@ -209,72 +216,24 @@ print_gen_head(struct html *h) } } -/* ARGSUSED */ static void -print_num(struct html *h, const char *p, size_t len) +print_metaf(struct html *h, enum mandoc_esc deco) { - const char *rhs; - - rhs = chars_num2char(p, len); - if (rhs) - putchar((int)*rhs); -} - -static void -print_spec(struct html *h, enum roffdeco d, const char *p, size_t len) -{ - int cp; - const char *rhs; - size_t sz; - - if ((cp = chars_spec2cp(h->symtab, p, len)) > 0) { - printf("&#%d;", cp); - return; - } else if (-1 == cp && DECO_SSPECIAL == d) { - fwrite(p, 1, len, stdout); - return; - } else if (-1 == cp) - return; - - if (NULL != (rhs = chars_spec2str(h->symtab, p, len, &sz))) - fwrite(rhs, 1, sz, stdout); -} - - -static void -print_res(struct html *h, const char *p, size_t len) -{ - int cp; - const char *rhs; - size_t sz; - - if ((cp = chars_res2cp(h->symtab, p, len)) > 0) { - printf("&#%d;", cp); - return; - } else if (-1 == cp) - return; - - if (NULL != (rhs = chars_res2str(h->symtab, p, len, &sz))) - fwrite(rhs, 1, sz, stdout); -} - - -static void -print_metaf(struct html *h, enum roffdeco deco) -{ enum htmlfont font; switch (deco) { - case (DECO_PREVIOUS): + case (ESCAPE_FONTPREV): font = h->metal; break; - case (DECO_ITALIC): + case (ESCAPE_FONTITALIC): font = HTMLFONT_ITALIC; break; - case (DECO_BOLD): + case (ESCAPE_FONTBOLD): font = HTMLFONT_BOLD; break; - case (DECO_ROMAN): + case (ESCAPE_FONT): + /* FALLTHROUGH */ + case (ESCAPE_FONTROMAN): font = HTMLFONT_NONE; break; default: @@ -296,80 +255,123 @@ print_metaf(struct html *h, enum roffdeco deco) print_otag(h, TAG_I, 0, NULL); } +int +html_strlen(const char *cp) +{ + int ssz, sz; + const char *seq, *p; + /* + * Account for escaped sequences within string length + * calculations. This follows the logic in term_strlen() as we + * must calculate the width of produced strings. + * Assume that characters are always width of "1". This is + * hacky, but it gets the job done for approximation of widths. + */ + + sz = 0; + while (NULL != (p = strchr(cp, '\\'))) { + sz += (int)(p - cp); + ++cp; + switch (mandoc_escape(&cp, &seq, &ssz)) { + case (ESCAPE_ERROR): + return(sz); + case (ESCAPE_UNICODE): + /* FALLTHROUGH */ + case (ESCAPE_NUMBERED): + /* FALLTHROUGH */ + case (ESCAPE_SPECIAL): + sz++; + break; + default: + break; + } + } + + assert(sz >= 0); + return(sz + strlen(cp)); +} + static int print_encode(struct html *h, const char *p, int norecurse) { size_t sz; - int len, nospace; + int c, len, nospace; const char *seq; - enum roffdeco deco; + enum mandoc_esc esc; static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' }; nospace = 0; - for (; *p; p++) { + while ('\0' != *p) { sz = strcspn(p, rejs); fwrite(p, 1, sz, stdout); - p += /* LINTED */ - sz; + p += (int)sz; - if ('<' == *p) { + if ('\0' == *p) + break; + + switch (*p++) { + case ('<'): printf("<"); continue; - } else if ('>' == *p) { + case ('>'): printf(">"); continue; - } else if ('&' == *p) { + case ('&'): printf("&"); continue; - } else if (ASCII_HYPH == *p) { - /* - * Note: "soft hyphens" aren't graphically - * displayed when not breaking the text; we want - * them to be displayed. - */ - /*printf("­");*/ + case (ASCII_HYPH): putchar('-'); continue; - } else if ('\0' == *p) + default: break; + } - seq = ++p; - len = a2roffdeco(&deco, &seq, &sz); + esc = mandoc_escape(&p, &seq, &len); + if (ESCAPE_ERROR == esc) + break; - switch (deco) { - case (DECO_NUMBERED): - print_num(h, seq, sz); + switch (esc) { + case (ESCAPE_UNICODE): + /* Skip passed "u" header. */ + c = mchars_num2uc(seq + 1, len - 1); + if ('\0' != c) + printf("&#x%x;", c); break; - case (DECO_RESERVED): - print_res(h, seq, sz); + case (ESCAPE_NUMBERED): + c = mchars_num2char(seq, len); + if ('\0' != c) + putchar(c); break; - case (DECO_SSPECIAL): - /* FALLTHROUGH */ - case (DECO_SPECIAL): - print_spec(h, deco, seq, sz); + case (ESCAPE_SPECIAL): + c = mchars_spec2cp(h->symtab, seq, len); + if (c > 0) + printf("&#%d;", c); + else if (-1 == c && 1 == len) + putchar((int)*seq); break; - case (DECO_PREVIOUS): + case (ESCAPE_FONT): /* FALLTHROUGH */ - case (DECO_BOLD): + case (ESCAPE_FONTPREV): /* FALLTHROUGH */ - case (DECO_ITALIC): + case (ESCAPE_FONTBOLD): /* FALLTHROUGH */ - case (DECO_ROMAN): + case (ESCAPE_FONTITALIC): + /* FALLTHROUGH */ + case (ESCAPE_FONTROMAN): if (norecurse) break; - print_metaf(h, deco); + print_metaf(h, esc); break; + case (ESCAPE_NOSPACE): + if ('\0' == *p) + nospace = 1; + break; default: break; } - - p += len - 1; - - if (DECO_NOSPACE == deco && '\0' == *(p + 1)) - nospace = 1; } return(nospace); @@ -432,7 +434,7 @@ print_otag(struct html *h, enum htmltag tag, print_attr(h, "lang", "en"); } - /* Accomodate for XML "well-formed" singleton escaping. */ + /* Accommodate for XML "well-formed" singleton escaping. */ if (HTML_AUTOCLOSE & htmltags[tag].flags) switch (h->type) { @@ -465,28 +467,9 @@ print_ctag(struct html *h, enum htmltag tag) } } - void print_gen_decls(struct html *h) { - - print_xmltype(h); - print_doctype(h); -} - - -static void -print_xmltype(struct html *h) -{ - - if (HTML_XHTML_1_0_STRICT == h->type) - puts(""); -} - - -static void -print_doctype(struct html *h) -{ const char *doctype; const char *dtd; const char *name; @@ -498,6 +481,7 @@ print_doctype(struct html *h) dtd = "http://www.w3.org/TR/html4/strict.dtd"; break; default: + puts(""); name = "html"; doctype = "-//W3C//DTD XHTML 1.0 Strict//EN"; dtd = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; @@ -508,15 +492,10 @@ print_doctype(struct html *h) name, doctype, dtd); } - void print_text(struct html *h, const char *word) { - if (DELIM_CLOSE == mandoc_isdelim(word)) - if ( ! (HTML_IGNDELIM & h->flags)) - h->flags |= HTML_NOSPACE; - if ( ! (HTML_NOSPACE & h->flags)) { /* Manage keeps! */ if ( ! (HTML_KEEP & h->flags)) { @@ -544,9 +523,6 @@ print_text(struct html *h, const char *word) } h->flags &= ~HTML_IGNDELIM; - - if (DELIM_OPEN == mandoc_isdelim(word)) - h->flags |= HTML_NOSPACE; } @@ -595,7 +571,6 @@ print_stagq(struct html *h, const struct tag *suntil) } } - void bufinit(struct html *h) { @@ -604,28 +579,26 @@ bufinit(struct html *h) h->buflen = 0; } - void bufcat_style(struct html *h, const char *key, const char *val) { bufcat(h, key); - bufncat(h, ":", 1); + bufcat(h, ":"); bufcat(h, val); - bufncat(h, ";", 1); + bufcat(h, ";"); } - void bufcat(struct html *h, const char *p) { - bufncat(h, p, strlen(p)); + h->buflen = strlcat(h->buf, p, BUFSIZ); + assert(h->buflen < BUFSIZ); } - void -buffmt(struct html *h, const char *fmt, ...) +bufcat_fmt(struct html *h, const char *fmt, ...) { va_list ap; @@ -636,19 +609,15 @@ buffmt(struct html *h, const char *fmt, ...) h->buflen = strlen(h->buf); } - -void +static void bufncat(struct html *h, const char *p, size_t sz) { - if (h->buflen + sz > BUFSIZ - 1) - sz = BUFSIZ - 1 - h->buflen; - - (void)strncat(h->buf, p, sz); + assert(h->buflen + sz + 1 < BUFSIZ); + strncat(h->buf, p, sz); h->buflen += sz; } - void buffmt_includes(struct html *h, const char *name) { @@ -656,6 +625,7 @@ buffmt_includes(struct html *h, const char *name) pp = h->base_includes; + bufinit(h); while (NULL != (p = strchr(pp, '%'))) { bufncat(h, pp, (size_t)(p - pp)); switch (*(p + 1)) { @@ -672,7 +642,6 @@ buffmt_includes(struct html *h, const char *name) bufcat(h, pp); } - void buffmt_man(struct html *h, const char *name, const char *sec) @@ -681,7 +650,7 @@ buffmt_man(struct html *h, pp = h->base_man; - /* LINTED */ + bufinit(h); while (NULL != (p = strchr(pp, '%'))) { bufncat(h, pp, (size_t)(p - pp)); switch (*(p + 1)) { @@ -689,7 +658,7 @@ buffmt_man(struct html *h, bufcat(h, sec ? sec : "1"); break; case('N'): - buffmt(h, name); + bufcat_fmt(h, name); break; default: bufncat(h, p, 2); @@ -701,85 +670,24 @@ buffmt_man(struct html *h, bufcat(h, pp); } - void bufcat_su(struct html *h, const char *p, const struct roffsu *su) { double v; - const char *u; v = su->scale; + if (SCALE_MM == su->unit && 0.0 == (v /= 100.0)) + v = 1.0; - switch (su->unit) { - case (SCALE_CM): - u = "cm"; - break; - case (SCALE_IN): - u = "in"; - break; - case (SCALE_PC): - u = "pc"; - break; - case (SCALE_PT): - u = "pt"; - break; - case (SCALE_EM): - u = "em"; - break; - case (SCALE_MM): - if (0 == (v /= 100)) - v = 1; - u = "em"; - break; - case (SCALE_EN): - u = "ex"; - break; - case (SCALE_BU): - u = "ex"; - break; - case (SCALE_VS): - u = "em"; - break; - default: - u = "ex"; - break; - } - - /* - * XXX: the CSS spec isn't clear as to which types accept - * integer or real numbers, so we just make them all decimals. - */ - buffmt(h, "%s: %.2f%s;", p, v, u); + bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]); } - void -html_idcat(char *dst, const char *src, int sz) +bufcat_id(struct html *h, const char *src) { - int ssz; - assert(sz > 2); - /* Cf. . */ - /* We can't start with a number (bah). */ - - if ('#' == *dst) { - dst++; - sz--; - } - if ('\0' == *dst) { - *dst++ = 'x'; - *dst = '\0'; - sz--; - } - - for ( ; *dst != '\0' && sz; dst++, sz--) - /* Jump to end. */ ; - - for ( ; *src != '\0' && sz > 1; src++) { - ssz = snprintf(dst, (size_t)sz, "%.2x", *src); - sz -= ssz; - dst += ssz; - } + while ('\0' != *src) + bufcat_fmt(h, "%.2x", *src++); }