=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/html.c,v retrieving revision 1.25 retrieving revision 1.26 diff -c -r1.25 -r1.26 *** src/usr.bin/mandoc/html.c 2011/04/24 16:22:02 1.25 --- src/usr.bin/mandoc/html.c 2011/05/29 21:22:18 1.26 *************** *** 1,4 **** ! /* $Id: html.c,v 1.25 2011/04/24 16:22:02 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze --- 1,4 ---- ! /* $Id: html.c,v 1.26 2011/05/29 21:22:18 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze *************** *** 27,32 **** --- 27,33 ---- #include #include "mandoc.h" + #include "libmandoc.h" #include "out.h" #include "html.h" #include "main.h" *************** *** 89,107 **** "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 void * ml_alloc(char *outopts, enum htmltype type) --- 90,114 ---- "colspan", /* ATTR_COLSPAN */ }; ! 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) *************** *** 119,125 **** h->type = type; h->tags.head = NULL; ! h->symtab = chars_init(CHARS_HTML); while (outopts && *outopts) switch (getsubopt(&outopts, UNCONST(toks), &v)) { --- 126,132 ---- h->type = type; h->tags.head = NULL; ! h->symtab = mchars_alloc(); while (outopts && *outopts) switch (getsubopt(&outopts, UNCONST(toks), &v)) { *************** *** 169,175 **** } if (h->symtab) ! chars_free(h->symtab); free(h); } --- 176,182 ---- } if (h->symtab) ! mchars_free(h->symtab); free(h); } *************** *** 205,276 **** } } - /* ARGSUSED */ static void ! print_num(struct html *h, const char *p, size_t len) { - 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): font = h->metal; break; ! case (DECO_ITALIC): font = HTMLFONT_ITALIC; break; ! case (DECO_BOLD): font = HTMLFONT_BOLD; break; ! case (DECO_ROMAN): font = HTMLFONT_NONE; break; default: --- 212,235 ---- } } static void ! print_metaf(struct html *h, enum mandoc_esc deco) { enum htmlfont font; switch (deco) { ! case (ESCAPE_FONTPREV): font = h->metal; break; ! case (ESCAPE_FONTITALIC): font = HTMLFONT_ITALIC; break; ! case (ESCAPE_FONTBOLD): font = HTMLFONT_BOLD; break; ! case (ESCAPE_FONT): ! /* FALLTHROUGH */ ! case (ESCAPE_FONTROMAN): font = HTMLFONT_NONE; break; default: *************** *** 292,371 **** print_otag(h, TAG_I, 0, NULL); } static int print_encode(struct html *h, const char *p, int norecurse) { size_t sz; ! int len, nospace; const char *seq; ! enum roffdeco deco; static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' }; nospace = 0; ! for (; *p; p++) { sz = strcspn(p, rejs); fwrite(p, 1, sz, stdout); ! p += /* LINTED */ ! sz; ! if ('<' == *p) { printf("<"); continue; ! } else if ('>' == *p) { printf(">"); continue; ! } else if ('&' == *p) { 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("­");*/ putchar('-'); continue; ! } else if ('\0' == *p) break; ! seq = ++p; ! len = a2roffdeco(&deco, &seq, &sz); ! switch (deco) { ! case (DECO_NUMBERED): ! print_num(h, seq, sz); break; ! case (DECO_RESERVED): ! print_res(h, seq, sz); break; ! case (DECO_SSPECIAL): ! /* FALLTHROUGH */ ! case (DECO_SPECIAL): ! print_spec(h, deco, seq, sz); break; ! case (DECO_PREVIOUS): /* FALLTHROUGH */ ! case (DECO_BOLD): /* FALLTHROUGH */ ! case (DECO_ITALIC): /* FALLTHROUGH */ ! case (DECO_ROMAN): if (norecurse) break; ! print_metaf(h, deco); break; default: break; } - - p += len - 1; - - if (DECO_NOSPACE == deco && '\0' == *(p + 1)) - nospace = 1; } return(nospace); --- 251,373 ---- 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 c, len, nospace; const char *seq; ! enum mandoc_esc esc; static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' }; nospace = 0; ! while ('\0' != *p) { sz = strcspn(p, rejs); fwrite(p, 1, sz, stdout); ! p += (int)sz; ! if ('\0' == *p) ! break; ! ! switch (*p++) { ! case ('<'): printf("<"); continue; ! case ('>'): printf(">"); continue; ! case ('&'): printf("&"); continue; ! case (ASCII_HYPH): putchar('-'); continue; ! default: break; + } ! esc = mandoc_escape(&p, &seq, &len); ! if (ESCAPE_ERROR == esc) ! break; ! 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 (ESCAPE_NUMBERED): ! c = mchars_num2char(seq, len); ! if ('\0' != c) ! putchar(c); break; ! 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 (ESCAPE_FONT): /* FALLTHROUGH */ ! case (ESCAPE_FONTPREV): /* FALLTHROUGH */ ! case (ESCAPE_FONTBOLD): /* FALLTHROUGH */ ! case (ESCAPE_FONTITALIC): ! /* FALLTHROUGH */ ! case (ESCAPE_FONTROMAN): if (norecurse) break; ! print_metaf(h, esc); break; + case (ESCAPE_NOSPACE): + if ('\0' == *p) + nospace = 1; + break; default: break; } } return(nospace); *************** *** 428,434 **** print_attr(h, "lang", "en"); } ! /* Accomodate for XML "well-formed" singleton escaping. */ if (HTML_AUTOCLOSE & htmltags[tag].flags) switch (h->type) { --- 430,436 ---- print_attr(h, "lang", "en"); } ! /* Accommodate for XML "well-formed" singleton escaping. */ if (HTML_AUTOCLOSE & htmltags[tag].flags) switch (h->type) { *************** *** 461,488 **** } } - 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; --- 463,471 ---- *************** *** 494,499 **** --- 477,483 ---- 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"; *************** *** 583,589 **** } } - void bufinit(struct html *h) { --- 567,572 ---- *************** *** 592,619 **** h->buflen = 0; } - void bufcat_style(struct html *h, const char *key, const char *val) { bufcat(h, key); ! bufncat(h, ":", 1); bufcat(h, val); ! bufncat(h, ";", 1); } - void bufcat(struct html *h, const char *p) { ! bufncat(h, p, strlen(p)); } - void ! buffmt(struct html *h, const char *fmt, ...) { va_list ap; --- 575,601 ---- h->buflen = 0; } void bufcat_style(struct html *h, const char *key, const char *val) { bufcat(h, key); ! bufcat(h, ":"); bufcat(h, val); ! bufcat(h, ";"); } void bufcat(struct html *h, const char *p) { ! h->buflen = strlcat(h->buf, p, BUFSIZ); ! assert(h->buflen < BUFSIZ); ! h->buflen--; } void ! bufcat_fmt(struct html *h, const char *fmt, ...) { va_list ap; *************** *** 624,642 **** h->buflen = strlen(h->buf); } ! ! 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); h->buflen += sz; } - void buffmt_includes(struct html *h, const char *name) { --- 606,620 ---- h->buflen = strlen(h->buf); } ! static void bufncat(struct html *h, const char *p, size_t sz) { ! assert(h->buflen + sz + 1 < BUFSIZ); ! strncat(h->buf, p, sz); h->buflen += sz; } void buffmt_includes(struct html *h, const char *name) { *************** *** 644,649 **** --- 622,628 ---- pp = h->base_includes; + bufinit(h); while (NULL != (p = strchr(pp, '%'))) { bufncat(h, pp, (size_t)(p - pp)); switch (*(p + 1)) { *************** *** 660,666 **** bufcat(h, pp); } - void buffmt_man(struct html *h, const char *name, const char *sec) --- 639,644 ---- *************** *** 669,675 **** pp = h->base_man; ! /* LINTED */ while (NULL != (p = strchr(pp, '%'))) { bufncat(h, pp, (size_t)(p - pp)); switch (*(p + 1)) { --- 647,653 ---- pp = h->base_man; ! bufinit(h); while (NULL != (p = strchr(pp, '%'))) { bufncat(h, pp, (size_t)(p - pp)); switch (*(p + 1)) { *************** *** 677,683 **** bufcat(h, sec ? sec : "1"); break; case('N'): ! buffmt(h, name); break; default: bufncat(h, p, 2); --- 655,661 ---- bufcat(h, sec ? sec : "1"); break; case('N'): ! bufcat_fmt(h, name); break; default: bufncat(h, p, 2); *************** *** 689,773 **** bufcat(h, pp); } - void bufcat_su(struct html *h, const char *p, const struct roffsu *su) { double v; - const char *u; v = su->scale; ! 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); } - void ! html_idcat(char *dst, const char *src, int sz) { - 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; ! } } --- 667,690 ---- bufcat(h, pp); } void bufcat_su(struct html *h, const char *p, const struct roffsu *su) { double v; v = su->scale; + if (SCALE_MM == su->unit && 0.0 == (v /= 100.0)) + v = 1.0; ! bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]); } void ! bufcat_id(struct html *h, const char *src) { /* Cf. . */ ! while ('\0' != *src) ! bufcat_fmt(h, "%.2x", *src++); }