=================================================================== RCS file: /cvs/mandoc/html.c,v retrieving revision 1.95 retrieving revision 1.109 diff -u -p -r1.95 -r1.109 --- mandoc/html.c 2010/01/30 08:42:20 1.95 +++ mandoc/html.c 2010/07/23 00:08:57 1.109 @@ -1,6 +1,6 @@ -/* $Id: html.c,v 1.95 2010/01/30 08:42:20 kristaps Exp $ */ +/* $Id: html.c,v 1.109 2010/07/23 00:08:57 kristaps Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,13 +29,12 @@ #include #include +#include "mandoc.h" #include "out.h" #include "chars.h" #include "html.h" #include "main.h" -#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a)) - struct htmldata { const char *name; int flags; @@ -54,7 +53,7 @@ static const struct htmldata htmltags[TAG_MAX] = { {"h1", 0}, /* TAG_H1 */ {"h2", 0}, /* TAG_H2 */ {"span", 0}, /* TAG_SPAN */ - {"link", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */ + {"link", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_LINK */ {"br", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_BR */ {"a", 0}, /* TAG_A */ {"table", HTML_CLRLINE}, /* TAG_TABLE */ @@ -89,7 +88,8 @@ static const char *const htmlattrs[ATTR_MAX] = { "summary", }; -static void print_spec(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 *); @@ -216,30 +216,41 @@ print_gen_head(struct html *h) static void -print_spec(struct html *h, const char *p, size_t len) +print_spec(struct html *h, enum roffdeco d, const char *p, size_t len) { + int cp; const char *rhs; size_t sz; - rhs = chars_a2ascii(h->symtab, p, len, &sz); - - if (NULL == rhs) + if ((cp = chars_spec2cp(h->symtab, p, len)) > 0) { + printf("&#%d;", cp); return; - fwrite(rhs, 1, sz, stdout); + } 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; - rhs = chars_a2res(h->symtab, p, len, &sz); - - if (NULL == rhs) + if ((cp = chars_res2cp(h->symtab, p, len)) > 0) { + printf("&#%d;", cp); return; - fwrite(rhs, 1, sz, stdout); + } else if (-1 == cp) + return; + + if (NULL != (rhs = chars_res2str(h->symtab, p, len, &sz))) + fwrite(rhs, 1, sz, stdout); } @@ -296,11 +307,12 @@ print_encode(struct html *h, const char *p, int norecu 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, "\\<>&"); + sz = strcspn(p, rejs); fwrite(p, 1, sz, stdout); p += /* LINTED */ @@ -315,6 +327,15 @@ print_encode(struct html *h, const char *p, int norecu } 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; @@ -325,8 +346,10 @@ print_encode(struct html *h, const char *p, int norecu case (DECO_RESERVED): print_res(h, seq, sz); break; + case (DECO_SSPECIAL): + /* FALLTHROUGH */ case (DECO_SPECIAL): - print_spec(h, seq, sz); + print_spec(h, deco, seq, sz); break; case (DECO_PREVIOUS): /* FALLTHROUGH */ @@ -384,9 +407,19 @@ print_otag(struct html *h, enum htmltag tag, t = NULL; if ( ! (HTML_NOSPACE & h->flags)) - if ( ! (HTML_CLRLINE & htmltags[tag].flags)) - putchar(' '); + if ( ! (HTML_CLRLINE & htmltags[tag].flags)) { + /* Manage keeps! */ + if ( ! (HTML_KEEP & h->flags)) { + if (HTML_PREKEEP & h->flags) + h->flags |= HTML_KEEP; + putchar(' '); + } else + printf(" "); + } + if ( ! (h->flags & HTML_NONOSPACE)) + h->flags &= ~HTML_NOSPACE; + /* Print out the tag name and attributes. */ printf("<%s", htmltags[tag].name); @@ -443,21 +476,9 @@ print_gen_decls(struct html *h) static void print_xmltype(struct html *h) { - const char *decl; - switch (h->type) { - case (HTML_XHTML_1_0_STRICT): - decl = ""; - break; - default: - decl = NULL; - break; - } - - if (NULL == decl) - return; - - printf("%s\n", decl); + if (HTML_XHTML_1_0_STRICT == h->type) + printf(""); } @@ -466,28 +487,32 @@ print_doctype(struct html *h) { const char *doctype; const char *dtd; + const char *name; switch (h->type) { case (HTML_HTML_4_01_STRICT): + name = "HTML"; doctype = "-//W3C//DTD HTML 4.01//EN"; dtd = "http://www.w3.org/TR/html4/strict.dtd"; break; default: + name = "html"; doctype = "-//W3C//DTD XHTML 1.0 Strict//EN"; dtd = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; break; } - printf("\n", doctype, dtd); + printf("\n", + name, doctype, dtd); } void -print_text(struct html *h, const char *p) +print_text(struct html *h, const char *word) { - if (*p && 0 == *(p + 1)) - switch (*p) { + if (word[0] && '\0' == word[1]) + switch (word[0]) { case('.'): /* FALLTHROUGH */ case(','): @@ -503,8 +528,6 @@ print_text(struct html *h, const char *p) case(')'): /* FALLTHROUGH */ case(']'): - /* FALLTHROUGH */ - case('}'): if ( ! (HTML_IGNDELIM & h->flags)) h->flags |= HTML_NOSPACE; break; @@ -512,20 +535,30 @@ print_text(struct html *h, const char *p) break; } - if ( ! (h->flags & HTML_NOSPACE)) - putchar(' '); + if ( ! (HTML_NOSPACE & h->flags)) { + /* Manage keeps! */ + if ( ! (HTML_KEEP & h->flags)) { + if (HTML_PREKEEP & h->flags) + h->flags |= HTML_KEEP; + putchar(' '); + } else + printf(" "); + } - assert(p); - if ( ! print_encode(h, p, 0)) - h->flags &= ~HTML_NOSPACE; + assert(word); + if ( ! print_encode(h, word, 0)) + if ( ! (h->flags & HTML_NONOSPACE)) + h->flags &= ~HTML_NOSPACE; - if (*p && 0 == *(p + 1)) - switch (*p) { + /* + * Note that we don't process the pipe: the parser sees it as + * punctuation, but we don't in terms of typography. + */ + if (word[0] && '\0' == word[1]) + switch (word[0]) { case('('): /* FALLTHROUGH */ case('['): - /* FALLTHROUGH */ - case('{'): h->flags |= HTML_NOSPACE; break; default: @@ -717,11 +750,11 @@ bufcat_su(struct html *h, const char *p, const struct break; } - if (su->pt) - buffmt(h, "%s: %f%s;", p, v, u); - else - /* LINTED */ - buffmt(h, "%s: %d%s;", p, (int)v, u); + /* + * 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); }