=================================================================== RCS file: /cvs/mandoc/html.c,v retrieving revision 1.35 retrieving revision 1.48 diff -u -p -r1.35 -r1.48 --- mandoc/html.c 2009/09/20 11:05:22 1.35 +++ mandoc/html.c 2009/09/21 14:07:07 1.48 @@ -1,4 +1,4 @@ -/* $Id: html.c,v 1.35 2009/09/20 11:05:22 kristaps Exp $ */ +/* $Id: html.c,v 1.48 2009/09/21 14:07:07 kristaps Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -14,6 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include "chars.h" #include "mdoc.h" @@ -32,7 +34,6 @@ #define INDENT 5 #define HALFINDENT 3 -#define PX_MULT 8 enum htmltag { TAG_HTML, @@ -55,6 +56,7 @@ enum htmltag { TAG_LI, TAG_UL, TAG_OL, + TAG_BASE, TAG_MAX }; @@ -101,6 +103,7 @@ static const struct htmldata htmltags[TAG_MAX] = { {"li", HTML_CLRLINE}, /* TAG_LI */ {"ul", HTML_CLRLINE}, /* TAG_UL */ {"ol", HTML_CLRLINE}, /* TAG_OL */ + {"base", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_BASE */ }; static const char *const htmlattrs[ATTR_MAX] = { @@ -127,14 +130,24 @@ struct tag { SLIST_ENTRY(tag) entry; }; +struct ord { + int pos; + const void *cookie; + SLIST_ENTRY(ord) entry; +}; + SLIST_HEAD(tagq, tag); +SLIST_HEAD(ordq, ord); struct html { int flags; #define HTML_NOSPACE (1 << 0) #define HTML_NEWLINE (1 << 1) - struct tagq stack; + struct tagq tags; + struct ordq ords; void *symtab; + char *base; + char *style; }; #define MDOC_ARGS const struct mdoc_meta *m, \ @@ -152,11 +165,10 @@ static void print_gen_doctype(struct html *); static void print_gen_head(struct html *); static void print_mdoc(MDOC_ARGS); static void print_mdoc_head(MDOC_ARGS); -static void print_mdoc_title(MDOC_ARGS); static void print_mdoc_node(MDOC_ARGS); +static void print_mdoc_nodelist(MDOC_ARGS); static void print_man(MAN_ARGS); static void print_man_head(MAN_ARGS); -static void print_man_body(MAN_ARGS); static struct tag *print_otag(struct html *, enum htmltag, int, const struct htmlpair *); static void print_tagq(struct html *, const struct tag *); @@ -170,22 +182,36 @@ static void print_spec(struct html *, const char *, static int a2width(const char *); static int a2offs(const char *); +static int a2list(const struct mdoc_node *); -static int mdoc_list_pre(MDOC_ARGS, int); -static int mdoc_listitem_pre(MDOC_ARGS); +static void mdoc_root_post(MDOC_ARGS); static int mdoc_root_pre(MDOC_ARGS); static int mdoc_tbl_pre(MDOC_ARGS, int); -static int mdoc_tbl_block_pre(MDOC_ARGS, int, int, int); +static int mdoc_tbl_block_pre(MDOC_ARGS, int, int, int, int); static int mdoc_tbl_body_pre(MDOC_ARGS, int, int); static int mdoc_tbl_head_pre(MDOC_ARGS, int, int); +static int mdoc_ad_pre(MDOC_ARGS); +static int mdoc_an_pre(MDOC_ARGS); +static void mdoc_aq_post(MDOC_ARGS); +static int mdoc_aq_pre(MDOC_ARGS); static int mdoc_ar_pre(MDOC_ARGS); +static int mdoc_bd_pre(MDOC_ARGS); +static void mdoc_bl_post(MDOC_ARGS); static int mdoc_bl_pre(MDOC_ARGS); +static int mdoc_cd_pre(MDOC_ARGS); static int mdoc_d1_pre(MDOC_ARGS); static void mdoc_dq_post(MDOC_ARGS); static int mdoc_dq_pre(MDOC_ARGS); +static int mdoc_dv_pre(MDOC_ARGS); +static int mdoc_fa_pre(MDOC_ARGS); +static int mdoc_fd_pre(MDOC_ARGS); static int mdoc_fl_pre(MDOC_ARGS); +static int mdoc_fn_pre(MDOC_ARGS); +static int mdoc_ft_pre(MDOC_ARGS); static int mdoc_em_pre(MDOC_ARGS); +static int mdoc_er_pre(MDOC_ARGS); +static int mdoc_ev_pre(MDOC_ARGS); static int mdoc_ex_pre(MDOC_ARGS); static int mdoc_it_pre(MDOC_ARGS); static int mdoc_nd_pre(MDOC_ARGS); @@ -193,18 +219,23 @@ static int mdoc_nm_pre(MDOC_ARGS); static int mdoc_ns_pre(MDOC_ARGS); static void mdoc_op_post(MDOC_ARGS); static int mdoc_op_pre(MDOC_ARGS); -static int mdoc_pp_pre(MDOC_ARGS); +static int mdoc_pa_pre(MDOC_ARGS); static void mdoc_pq_post(MDOC_ARGS); static int mdoc_pq_pre(MDOC_ARGS); +static void mdoc_qq_post(MDOC_ARGS); +static int mdoc_qq_pre(MDOC_ARGS); static int mdoc_sh_pre(MDOC_ARGS); +static int mdoc_sp_pre(MDOC_ARGS); static void mdoc_sq_post(MDOC_ARGS); static int mdoc_sq_pre(MDOC_ARGS); static int mdoc_ss_pre(MDOC_ARGS); static int mdoc_sx_pre(MDOC_ARGS); +static int mdoc_vt_pre(MDOC_ARGS); static int mdoc_xr_pre(MDOC_ARGS); static int mdoc_xx_pre(MDOC_ARGS); #ifdef __linux__ +extern int getsubopt(char **, char * const *, char **); extern size_t strlcpy(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); #endif @@ -216,28 +247,28 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {NULL, NULL}, /* Os */ {mdoc_sh_pre, NULL }, /* Sh */ {mdoc_ss_pre, NULL }, /* Ss */ - {mdoc_pp_pre, NULL}, /* Pp */ + {mdoc_sp_pre, NULL}, /* Pp */ {mdoc_d1_pre, NULL}, /* D1 */ {mdoc_d1_pre, NULL}, /* Dl */ - {NULL, NULL}, /* Bd */ + {mdoc_bd_pre, NULL}, /* Bd */ {NULL, NULL}, /* Ed */ - {mdoc_bl_pre, NULL}, /* Bl */ + {mdoc_bl_pre, mdoc_bl_post}, /* Bl */ {NULL, NULL}, /* El */ {mdoc_it_pre, NULL}, /* It */ - {NULL, NULL}, /* Ad */ - {NULL, NULL}, /* An */ + {mdoc_ad_pre, NULL}, /* Ad */ + {mdoc_an_pre, NULL}, /* An */ {mdoc_ar_pre, NULL}, /* Ar */ - {NULL, NULL}, /* Cd */ - {NULL, NULL}, /* Cm */ - {NULL, NULL}, /* Dv */ - {NULL, NULL}, /* Er */ - {NULL, NULL}, /* Ev */ + {mdoc_cd_pre, NULL}, /* Cd */ + {mdoc_fl_pre, NULL}, /* Cm */ + {mdoc_dv_pre, NULL}, /* Dv */ + {mdoc_er_pre, NULL}, /* Er */ + {mdoc_ev_pre, NULL}, /* Ev */ {mdoc_ex_pre, NULL}, /* Ex */ - {NULL, NULL}, /* Fa */ - {NULL, NULL}, /* Fd */ + {mdoc_fa_pre, NULL}, /* Fa */ + {mdoc_fd_pre, NULL}, /* Fd */ {mdoc_fl_pre, NULL}, /* Fl */ - {NULL, NULL}, /* Fn */ - {NULL, NULL}, /* Ft */ + {mdoc_fn_pre, NULL}, /* Fn */ + {mdoc_ft_pre, NULL}, /* Ft */ {NULL, NULL}, /* Ic */ {NULL, NULL}, /* In */ {NULL, NULL}, /* Li */ @@ -245,11 +276,11 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {mdoc_nm_pre, NULL}, /* Nm */ {mdoc_op_pre, mdoc_op_post}, /* Op */ {NULL, NULL}, /* Ot */ - {NULL, NULL}, /* Pa */ + {mdoc_pa_pre, NULL}, /* Pa */ {NULL, NULL}, /* Rv */ {NULL, NULL}, /* St */ {NULL, NULL}, /* Va */ - {NULL, NULL}, /* Vt */ + {mdoc_vt_pre, NULL}, /* Vt */ {mdoc_xr_pre, NULL}, /* Xr */ {NULL, NULL}, /* %A */ {NULL, NULL}, /* %B */ @@ -263,8 +294,8 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {NULL, NULL}, /* %T */ {NULL, NULL}, /* %V */ {NULL, NULL}, /* Ac */ - {NULL, NULL}, /* Ao */ - {NULL, NULL}, /* Aq */ + {mdoc_aq_pre, mdoc_aq_post}, /* Ao */ + {mdoc_aq_pre, mdoc_aq_post}, /* Aq */ {NULL, NULL}, /* At */ {NULL, NULL}, /* Bc */ {NULL, NULL}, /* Bf */ @@ -292,8 +323,8 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {mdoc_pq_pre, mdoc_pq_post}, /* Pq */ {NULL, NULL}, /* Qc */ {NULL, NULL}, /* Ql */ - {NULL, NULL}, /* Qo */ - {NULL, NULL}, /* Qq */ + {mdoc_qq_pre, mdoc_qq_post}, /* Qo */ + {mdoc_qq_pre, mdoc_qq_post}, /* Qq */ {NULL, NULL}, /* Re */ {NULL, NULL}, /* Rs */ {NULL, NULL}, /* Sc */ @@ -317,7 +348,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {NULL, NULL}, /* Fr */ {NULL, NULL}, /* Ud */ {NULL, NULL}, /* Lb */ - {NULL, NULL}, /* Lp */ + {mdoc_sp_pre, NULL}, /* Lp */ {NULL, NULL}, /* Lk */ {NULL, NULL}, /* Mt */ {NULL, NULL}, /* Brq */ @@ -328,8 +359,8 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = { {NULL, NULL}, /* En */ {mdoc_xx_pre, NULL}, /* Dx */ {NULL, NULL}, /* %Q */ - {NULL, NULL}, /* br */ - {NULL, NULL}, /* sp */ + {mdoc_sp_pre, NULL}, /* br */ + {mdoc_sp_pre, NULL}, /* sp */ }; static char buf[BUFSIZ]; /* XXX */ @@ -373,18 +404,38 @@ html_man(void *arg, const struct man *m) void * -html_alloc(void) +html_alloc(char *outopts) { struct html *h; + char *toks[3], *v; + toks[0] = "style"; + toks[1] = "base"; + toks[2] = NULL; + if (NULL == (h = calloc(1, sizeof(struct html)))) return(NULL); - SLIST_INIT(&h->stack); + SLIST_INIT(&h->tags); + SLIST_INIT(&h->ords); + if (NULL == (h->symtab = chars_init(CHARS_HTML))) { free(h); return(NULL); } + + while (outopts && *outopts) + switch (getsubopt(&outopts, toks, &v)) { + case (0): + h->style = v; + break; + case (1): + h->base = v; + break; + default: + break; + } + return(h); } @@ -393,31 +444,133 @@ void html_free(void *p) { struct tag *tag; + struct ord *ord; struct html *h; h = (struct html *)p; - while ( ! SLIST_EMPTY(&h->stack)) { - tag = SLIST_FIRST(&h->stack); - SLIST_REMOVE_HEAD(&h->stack, entry); + while ( ! SLIST_EMPTY(&h->ords)) { + ord = SLIST_FIRST(&h->ords); + SLIST_REMOVE_HEAD(&h->ords, entry); + free(ord); + } + + while ( ! SLIST_EMPTY(&h->tags)) { + tag = SLIST_FIRST(&h->tags); + SLIST_REMOVE_HEAD(&h->tags, entry); free(tag); } + + if (h->symtab) + chars_free(h->symtab); free(h); } +static int +a2list(const struct mdoc_node *n) +{ + int i; + + assert(MDOC_BLOCK == n->type && MDOC_Bl == n->tok); + assert(n->args); + + for (i = 0; i < (int)n->args->argc; i++) + switch (n->args->argv[i].arg) { + case (MDOC_Enum): + /* FALLTHROUGH */ + case (MDOC_Dash): + /* FALLTHROUGH */ + case (MDOC_Hyphen): + /* FALLTHROUGH */ + case (MDOC_Bullet): + /* FALLTHROUGH */ + case (MDOC_Tag): + /* FALLTHROUGH */ + case (MDOC_Hang): + /* FALLTHROUGH */ + case (MDOC_Inset): + /* FALLTHROUGH */ + case (MDOC_Diag): + /* FALLTHROUGH */ + case (MDOC_Item): + /* FALLTHROUGH */ + case (MDOC_Column): + /* FALLTHROUGH */ + case (MDOC_Ohang): + return(n->args->argv[i].arg); + default: + break; + } + + abort(); + /* NOTREACHED */ +} + + +static int +a2width(const char *p) +{ + int i, len; + + if (0 == (len = (int)strlen(p))) + return(0); + for (i = 0; i < len - 1; i++) + if ( ! isdigit((u_char)p[i])) + break; + + if (i == len - 1) + if ('n' == p[len - 1] || 'm' == p[len - 1]) + return(atoi(p) + 2); + + return(len + 2); +} + + +static int +a2offs(const char *p) +{ + int len, i; + + if (0 == strcmp(p, "left")) + return(0); + if (0 == strcmp(p, "indent")) + return(INDENT + 1); + if (0 == strcmp(p, "indent-two")) + return((INDENT + 1) * 2); + + if (0 == (len = (int)strlen(p))) + return(0); + + for (i = 0; i < len - 1; i++) + if ( ! isdigit((u_char)p[i])) + break; + + if (i == len - 1) + if ('n' == p[len - 1] || 'm' == p[len - 1]) + return(atoi(p)); + + return(len); +} + + static void print_mdoc(MDOC_ARGS) { struct tag *t; + struct htmlpair tag; t = print_otag(h, TAG_HEAD, 0, NULL); print_mdoc_head(m, n, h); print_tagq(h, t); t = print_otag(h, TAG_BODY, 0, NULL); - print_mdoc_title(m, n, h); - print_mdoc_node(m, n, h); + + tag.key = ATTR_CLASS; + tag.val = "body"; + print_otag(h, TAG_DIV, 1, &tag); + + print_mdoc_nodelist(m, n, h); print_tagq(h, t); } @@ -425,32 +578,37 @@ print_mdoc(MDOC_ARGS) static void print_gen_head(struct html *h) { - struct htmlpair meta0[2]; - struct htmlpair meta1[2]; - struct htmlpair link[4]; + struct htmlpair tag[4]; - meta0[0].key = ATTR_HTTPEQUIV; - meta0[0].val = "Content-Type"; - meta0[1].key = ATTR_CONTENT; - meta0[1].val = "text/html; charset=utf-8"; + tag[0].key = ATTR_HTTPEQUIV; + tag[0].val = "Content-Type"; + tag[1].key = ATTR_CONTENT; + tag[1].val = "text/html; charset=utf-8"; + print_otag(h, TAG_META, 2, tag); - meta1[0].key = ATTR_NAME; - meta1[0].val = "resource-type"; - meta1[1].key = ATTR_CONTENT; - meta1[1].val = "document"; + tag[0].key = ATTR_NAME; + tag[0].val = "resource-type"; + tag[1].key = ATTR_CONTENT; + tag[1].val = "document"; + print_otag(h, TAG_META, 2, tag); - link[0].key = ATTR_REL; - link[0].val = "stylesheet"; - link[1].key = ATTR_HREF; - link[1].val = "style.css"; /* XXX */ - link[2].key = ATTR_TYPE; - link[2].val = "text/css"; - link[3].key = ATTR_MEDIA; - link[3].val = "all"; + if (h->style) { + tag[0].key = ATTR_REL; + tag[0].val = "stylesheet"; + tag[1].key = ATTR_HREF; + tag[1].val = h->style; + tag[2].key = ATTR_TYPE; + tag[2].val = "text/css"; + tag[3].key = ATTR_MEDIA; + tag[3].val = "all"; + print_otag(h, TAG_LINK, 4, tag); + } - print_otag(h, TAG_META, 2, meta0); - print_otag(h, TAG_META, 2, meta1); - print_otag(h, TAG_LINK, 4, link); + if (h->base) { + tag[0].key = ATTR_HREF; + tag[1].val = h->base; + print_otag(h, TAG_BASE, 1, tag); + } } @@ -461,16 +619,17 @@ print_mdoc_head(MDOC_ARGS) print_gen_head(h); print_otag(h, TAG_TITLE, 0, NULL); - print_encode(h, m->title); + print_text(h, m->title); } -/* ARGSUSED */ static void -print_mdoc_title(MDOC_ARGS) +print_mdoc_nodelist(MDOC_ARGS) { - /* TODO */ + print_mdoc_node(m, n, h); + if (n->next) + print_mdoc_nodelist(m, n->next, h); } @@ -481,7 +640,7 @@ print_mdoc_node(MDOC_ARGS) struct tag *t; child = 1; - t = SLIST_FIRST(&h->stack); + t = SLIST_FIRST(&h->tags); bufinit(); @@ -499,7 +658,7 @@ print_mdoc_node(MDOC_ARGS) } if (child && n->child) - print_mdoc_node(m, n->child, h); + print_mdoc_nodelist(m, n->child, h); print_stagq(h, t); @@ -507,6 +666,7 @@ print_mdoc_node(MDOC_ARGS) switch (n->type) { case (MDOC_ROOT): + mdoc_root_post(m, n, h); break; case (MDOC_TEXT): break; @@ -515,9 +675,6 @@ print_mdoc_node(MDOC_ARGS) (*mdocs[n->tok].post)(m, n, h); break; } - - if (n->next) - print_mdoc_node(m, n->next, h); } @@ -531,7 +688,7 @@ print_man(MAN_ARGS) print_tagq(h, t); t = print_otag(h, TAG_BODY, 0, NULL); - print_man_body(m, n, h); + /*print_man_body(m, n, h);*/ print_tagq(h, t); } @@ -543,20 +700,11 @@ print_man_head(MAN_ARGS) print_gen_head(h); print_otag(h, TAG_TITLE, 0, NULL); - print_encode(h, m->title); + print_text(h, m->title); } -/* ARGSUSED */ static void -print_man_body(MAN_ARGS) -{ - - /* TODO */ -} - - -static void print_spec(struct html *h, const char *p, int len) { const char *rhs; @@ -726,7 +874,7 @@ print_otag(struct html *h, enum htmltag tag, if (NULL == (t = malloc(sizeof(struct tag)))) err(EXIT_FAILURE, "malloc"); t->tag = tag; - SLIST_INSERT_HEAD(&h->stack, t, entry); + SLIST_INSERT_HEAD(&h->tags, t, entry); } else t = NULL; @@ -773,7 +921,7 @@ static void print_gen_doctype(struct html *h) { - printf("\n", DOCTYPE, DTD); + printf("", DOCTYPE, DTD); } @@ -835,10 +983,10 @@ print_tagq(struct html *h, const struct tag *until) { struct tag *tag; - while ( ! SLIST_EMPTY(&h->stack)) { - tag = SLIST_FIRST(&h->stack); + while ( ! SLIST_EMPTY(&h->tags)) { + tag = SLIST_FIRST(&h->tags); print_ctag(h, tag->tag); - SLIST_REMOVE_HEAD(&h->stack, entry); + SLIST_REMOVE_HEAD(&h->tags, entry); free(tag); if (until && tag == until) return; @@ -851,77 +999,96 @@ print_stagq(struct html *h, const struct tag *suntil) { struct tag *tag; - while ( ! SLIST_EMPTY(&h->stack)) { - tag = SLIST_FIRST(&h->stack); + while ( ! SLIST_EMPTY(&h->tags)) { + tag = SLIST_FIRST(&h->tags); if (suntil && tag == suntil) return; print_ctag(h, tag->tag); - SLIST_REMOVE_HEAD(&h->stack, entry); + SLIST_REMOVE_HEAD(&h->tags, entry); free(tag); } } -/* FIXME: put in utility file for front-ends. */ -static int -a2offs(const char *p) +/* ARGSUSED */ +static void +mdoc_root_post(MDOC_ARGS) { - int len, i; + struct tm tm; + struct htmlpair tag[2]; + struct tag *t, *tt; + char b[BUFSIZ]; - if (0 == strcmp(p, "left")) - return(0); - if (0 == strcmp(p, "indent")) - return(INDENT + 1); - if (0 == strcmp(p, "indent-two")) - return((INDENT + 1) * 2); + (void)localtime_r(&m->date, &tm); - if (0 == (len = (int)strlen(p))) - return(0); + if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm)) + err(EXIT_FAILURE, "strftime"); - for (i = 0; i < len - 1; i++) - if ( ! isdigit((u_char)p[i])) - break; + tag[0].key = ATTR_CLASS; + tag[0].val = "footer"; + tag[1].key = ATTR_STYLE; + tag[1].val = "width: 100%;"; + t = print_otag(h, TAG_TABLE, 2, tag); + tt = print_otag(h, TAG_TR, 0, NULL); - if (i == len - 1) - if ('n' == p[len - 1] || 'm' == p[len - 1]) - return(atoi(p)); + tag[0].key = ATTR_STYLE; + tag[0].val = "width: 50%;"; + print_otag(h, TAG_TD, 1, tag); + print_text(h, b); + print_stagq(h, tt); - return(len); + tag[0].key = ATTR_STYLE; + tag[0].val = "width: 50%; text-align: right;"; + print_otag(h, TAG_TD, 1, tag); + print_text(h, m->os); + print_tagq(h, t); } -/* FIXME: put in utility file for front-ends. */ +/* ARGSUSED */ static int -a2width(const char *p) +mdoc_root_pre(MDOC_ARGS) { - int i, len; + struct htmlpair tag[2]; + struct tag *t, *tt; + char b[BUFSIZ], title[BUFSIZ]; - if (0 == (len = (int)strlen(p))) - return(0); - for (i = 0; i < len - 1; i++) - if ( ! isdigit((u_char)p[i])) - break; + (void)strlcpy(b, m->vol, BUFSIZ); - if (i == len - 1) - if ('n' == p[len - 1] || 'm' == p[len - 1]) - return(atoi(p) + 2); + if (m->arch) { + (void)strlcat(b, " (", BUFSIZ); + (void)strlcat(b, m->arch, BUFSIZ); + (void)strlcat(b, ")", BUFSIZ); + } - return(len + 2); -} + (void)snprintf(title, BUFSIZ - 1, + "%s(%d)", m->title, m->msec); + tag[0].key = ATTR_CLASS; + tag[0].val = "header"; + tag[1].key = ATTR_STYLE; + tag[1].val = "width: 100%;"; + t = print_otag(h, TAG_TABLE, 2, tag); + tt = print_otag(h, TAG_TR, 0, NULL); + tag[0].key = ATTR_STYLE; + tag[0].val = "width: 33%;"; + print_otag(h, TAG_TD, 1, tag); + print_text(h, b); + print_stagq(h, tt); + tag[0].key = ATTR_STYLE; + tag[0].val = "width: 33%; text-align: center;"; + print_otag(h, TAG_TD, 1, tag); + print_text(h, title); + print_stagq(h, tt); -/* ARGSUSED */ -static int -mdoc_root_pre(MDOC_ARGS) -{ - struct htmlpair tag; + tag[0].key = ATTR_STYLE; + tag[0].val = "width: 33%; text-align: right;"; + print_otag(h, TAG_TD, 1, tag); + print_text(h, b); + print_tagq(h, t); - tag.key = ATTR_CLASS; - tag.val = "body"; - - print_otag(h, TAG_DIV, 1, &tag); return(1); } @@ -930,26 +1097,46 @@ mdoc_root_pre(MDOC_ARGS) static int mdoc_sh_pre(MDOC_ARGS) { - struct htmlpair tag[2]; + struct htmlpair tag[2]; + const struct mdoc_node *nn; if (MDOC_HEAD == n->type) { tag[0].key = ATTR_CLASS; tag[0].val = "sec-head"; print_otag(h, TAG_DIV, 1, tag); print_otag(h, TAG_SPAN, 1, tag); + + for (nn = n->child; nn; nn = nn->next) { + bufcat(nn->string); + if (nn->next) + bufcat(" "); + } + tag[0].key = ATTR_NAME; + tag[0].val = buf; + print_otag(h, TAG_A, 1, tag); return(1); } else if (MDOC_BLOCK == n->type) { tag[0].key = ATTR_CLASS; tag[0].val = "sec-block"; - print_otag(h, TAG_DIV, 1, tag); + + if (n->prev && NULL == n->prev->body->child) { + print_otag(h, TAG_DIV, 1, tag); + return(1); + } + + bufcat("margin-top: 1em;"); + if (NULL == n->next) + bufcat("margin-bottom: 1em;"); + + tag[1].key = ATTR_STYLE; + tag[1].val = buf; + + print_otag(h, TAG_DIV, 2, tag); return(1); } buffmt("margin-left: %dem;", INDENT); - if (n->parent->next && n->child) - bufcat("margin-bottom: 1em;"); - tag[0].key = ATTR_CLASS; tag[0].val = "sec-body"; tag[1].key = ATTR_STYLE; @@ -964,8 +1151,9 @@ mdoc_sh_pre(MDOC_ARGS) static int mdoc_ss_pre(MDOC_ARGS) { - struct htmlpair tag[2]; - int i; + struct htmlpair tag[2]; + int i; + const struct mdoc_node *nn; i = 0; @@ -1000,6 +1188,17 @@ mdoc_ss_pre(MDOC_ARGS) print_otag(h, TAG_DIV, 2, tag); print_otag(h, TAG_SPAN, 1, tag); + + bufinit(); + for (nn = n->child; nn; nn = nn->next) { + bufcat(nn->string); + if (nn->next) + bufcat(" "); + } + tag[0].key = ATTR_NAME; + tag[0].val = buf; + print_otag(h, TAG_A, 1, tag); + return(1); } @@ -1014,31 +1213,16 @@ mdoc_fl_pre(MDOC_ARGS) tag.val = "flag"; print_otag(h, TAG_SPAN, 1, &tag); - print_text(h, "\\-"); - h->flags |= HTML_NOSPACE; + if (MDOC_Fl == n->tok) { + print_text(h, "\\-"); + h->flags |= HTML_NOSPACE; + } return(1); } /* ARGSUSED */ static int -mdoc_pp_pre(MDOC_ARGS) -{ - struct htmlpair tag; - - bufcat("clear: both;"); - bufcat("height: 1em;"); - - tag.key = ATTR_STYLE; - tag.val = buf; - - print_otag(h, TAG_DIV, 1, &tag); - return(0); -} - - -/* ARGSUSED */ -static int mdoc_nd_pre(MDOC_ARGS) { struct htmlpair tag; @@ -1066,6 +1250,7 @@ mdoc_op_pre(MDOC_ARGS) /* XXX - this can contain block elements! */ print_text(h, "\\(lB"); + h->flags |= HTML_NOSPACE; tag.key = ATTR_CLASS; tag.val = "opt"; print_otag(h, TAG_SPAN, 1, &tag); @@ -1112,24 +1297,32 @@ mdoc_nm_pre(MDOC_ARGS) static int mdoc_xr_pre(MDOC_ARGS) { - struct htmlpair tag[2]; + struct htmlpair tag[2]; + const char *name, *sec; + const struct mdoc_node *nn; + nn = n->child; + name = nn && nn->string ? nn->string : ""; + nn = nn ? nn->next : NULL; + sec = nn && nn->string ? nn->string : ""; + + buffmt("%s%s%s.html", name, name && sec ? "." : "", sec); + tag[0].key = ATTR_CLASS; tag[0].val = "link-man"; tag[1].key = ATTR_HREF; - tag[1].val = "#"; /* TODO */ - + tag[1].val = buf; print_otag(h, TAG_A, 2, tag); - n = n->child; - print_text(h, n->string); - if (NULL == (n = n->next)) + nn = n->child; + print_text(h, nn->string); + if (NULL == (nn = nn->next)) return(0); h->flags |= HTML_NOSPACE; print_text(h, "("); h->flags |= HTML_NOSPACE; - print_text(h, n->string); + print_text(h, nn->string); h->flags |= HTML_NOSPACE; print_text(h, ")"); @@ -1202,14 +1395,29 @@ mdoc_xx_pre(MDOC_ARGS) /* ARGSUSED */ static int -mdoc_tbl_block_pre(MDOC_ARGS, int w, int o, int c) +mdoc_tbl_block_pre(MDOC_ARGS, int t, int w, int o, int c) { struct htmlpair tag; - buffmt("margin-left: %dem; clear: both;", w + o); + switch (t) { + case (MDOC_Column): + /* FALLTHROUGH */ + case (MDOC_Item): + /* FALLTHROUGH */ + case (MDOC_Ohang): + buffmt("margin-left: %dem; clear: both;", o); + break; + default: + buffmt("margin-left: %dem; clear: both;", w + o); + break; + } - if ( ! c) - bufcat("padding-top: 1em;"); + if ( ! c && MDOC_Column != t) { + if (n->prev && n->prev->body->child) + bufcat("padding-top: 1em;"); + else if (NULL == n->prev) + bufcat("padding-top: 1em;"); + } tag.key = ATTR_STYLE; tag.val = buf; @@ -1222,24 +1430,8 @@ mdoc_tbl_block_pre(MDOC_ARGS, int w, int o, int c) static int mdoc_tbl_body_pre(MDOC_ARGS, int t, int w) { - struct htmlpair tag; - int i; - switch (t) { - case (MDOC_Tag): - i = 1; - tag.key = ATTR_STYLE; - tag.val = buf; - bufcat("clear: right;"); - bufcat("float: left;"); - bufcat("width: 100%%;"); - break; - default: - i = 0; - break; - } - - print_otag(h, TAG_DIV, i, &tag); + print_otag(h, TAG_DIV, 0, NULL); return(1); } @@ -1249,26 +1441,61 @@ static int mdoc_tbl_head_pre(MDOC_ARGS, int t, int w) { struct htmlpair tag; - int i; + struct ord *ord; + char nbuf[BUFSIZ]; switch (t) { - case (MDOC_Hang): + case (MDOC_Item): /* FALLTHROUGH */ - case (MDOC_Tag): - i = 1; + case (MDOC_Ohang): + print_otag(h, TAG_DIV, 0, NULL); + break; + case (MDOC_Column): + buffmt("min-width: %dem;", w); + bufcat("clear: none;"); + if (n->next && MDOC_HEAD == n->next->type) + bufcat("float: left;"); tag.key = ATTR_STYLE; tag.val = buf; + print_otag(h, TAG_DIV, 1, &tag); + break; + default: buffmt("margin-left: -%dem;", w); bufcat("clear: left;"); bufcat("float: left;"); bufcat("padding-right: 1em;"); + tag.key = ATTR_STYLE; + tag.val = buf; + print_otag(h, TAG_DIV, 1, &tag); break; + } + + switch (t) { + case (MDOC_Diag): + tag.key = ATTR_CLASS; + tag.val = "diag"; + print_otag(h, TAG_SPAN, 1, &tag); + break; + case (MDOC_Enum): + ord = SLIST_FIRST(&h->ords); + assert(ord); + nbuf[BUFSIZ - 1] = 0; + (void)snprintf(nbuf, BUFSIZ - 1, "%d.", ord->pos++); + print_text(h, nbuf); + return(0); + case (MDOC_Dash): + print_text(h, "\\(en"); + return(0); + case (MDOC_Hyphen): + print_text(h, "\\-"); + return(0); + case (MDOC_Bullet): + print_text(h, "\\(bu"); + return(0); default: - i = 0; break; } - print_otag(h, TAG_DIV, i, &tag); return(1); } @@ -1276,8 +1503,8 @@ mdoc_tbl_head_pre(MDOC_ARGS, int t, int w) static int mdoc_tbl_pre(MDOC_ARGS, int type) { - int i, w, o, c; - const struct mdoc_node *bl; + int i, w, o, c, wp; + const struct mdoc_node *bl, *nn; bl = n->parent->parent; if (MDOC_BLOCK != n->type) @@ -1288,20 +1515,51 @@ mdoc_tbl_pre(MDOC_ARGS, int type) assert(bl->args); w = o = c = 0; + wp = -1; for (i = 0; i < (int)bl->args->argc; i++) if (MDOC_Width == bl->args->argv[i].arg) { assert(bl->args->argv[i].sz); + wp = i; w = a2width(bl->args->argv[i].value[0]); } else if (MDOC_Offset == bl->args->argv[i].arg) { assert(bl->args->argv[i].sz); o = a2offs(bl->args->argv[i].value[0]); } else if (MDOC_Compact == bl->args->argv[i].arg) c = 1; - - if (0 == w) - w = 10; + if (MDOC_HEAD == n->type && MDOC_Column == type) { + nn = n->parent->child; + assert(nn && MDOC_HEAD == nn->type); + for (i = 0; nn && nn != n; nn = nn->next, i++) + /* Counter... */ ; + assert(nn); + if (wp >= 0 && i < (int)bl->args[wp].argv->sz) + w = a2width(bl->args->argv[wp].value[i]); + } + + switch (type) { + case (MDOC_Enum): + /* FALLTHROUGH */ + case (MDOC_Dash): + /* FALLTHROUGH */ + case (MDOC_Hyphen): + /* FALLTHROUGH */ + case (MDOC_Bullet): + if (w < 4) + w = 4; + break; + case (MDOC_Inset): + /* FALLTHROUGH */ + case (MDOC_Diag): + w = 1; + break; + default: + if (0 == w) + w = 10; + break; + } + switch (n->type) { case (MDOC_BLOCK): break; @@ -1314,164 +1572,61 @@ mdoc_tbl_pre(MDOC_ARGS, int type) /* NOTREACHED */ } - return(mdoc_tbl_block_pre(m, n, h, w, o, c)); + return(mdoc_tbl_block_pre(m, n, h, type, w, o, c)); } /* ARGSUSED */ static int -mdoc_listitem_pre(MDOC_ARGS) +mdoc_bl_pre(MDOC_ARGS) { - int i, w, o, c; - const struct mdoc_node *bl; - struct htmlpair tag; + struct ord *ord; - /* FIXME: fmt_vspace() equivalent. */ - if (MDOC_BLOCK != n->type) return(1); + if (MDOC_Enum != a2list(n)) + return(1); - bl = n->parent->parent; - assert(bl); + ord = malloc(sizeof(struct ord)); + if (NULL == ord) + err(EXIT_FAILURE, "malloc"); + ord->cookie = n; + ord->pos = 1; + SLIST_INSERT_HEAD(&h->ords, ord, entry); - w = o = c = 0; - - for (i = 0; i < (int)bl->args->argc; i++) - if (MDOC_Width == bl->args->argv[i].arg) { - assert(bl->args->argv[i].sz); - w = a2width(bl->args->argv[i].value[0]); - } else if (MDOC_Offset == bl->args->argv[i].arg) { - assert(bl->args->argv[i].sz); - o = a2offs(bl->args->argv[i].value[0]); - } else if (MDOC_Compact == bl->args->argv[i].arg) - c = 1; - - if (o && w) - buffmt("margin-left: %dem; padding-left: %dem;", o, w); - else if (w) - buffmt("padding-left: %dem;", w > 4 ? w - 4 : w); - else if (o) - buffmt("margin-left: %dem;", o); - - if ( ! c) - bufcat("padding-top: 1em;"); - - tag.key = ATTR_STYLE; - tag.val = buf; - - print_otag(h, TAG_LI, 1, &tag); return(1); } /* ARGSUSED */ -static int -mdoc_list_pre(MDOC_ARGS, int type) +static void +mdoc_bl_post(MDOC_ARGS) { + struct ord *ord; - switch (type) { - case (MDOC_Enum): - print_otag(h, TAG_OL, 0, NULL); - break; - case (MDOC_Bullet): - print_otag(h, TAG_UL, 0, NULL); - break; - default: - break; - } - - return(1); -} - - -static int -mdoc_bl_pre(MDOC_ARGS) -{ - int i, len, type; - if (MDOC_BLOCK != n->type) - return(1); + return; + if (MDOC_Enum != a2list(n)) + return; - assert(n->args); - len = (int)n->args->argc; - - for (i = 0; i < len; i++) - switch ((type = n->args->argv[i].arg)) { - case (MDOC_Enum): - /* FALLTHROUGH */ - case (MDOC_Bullet): - return(mdoc_list_pre(m, n, h, type)); - case (MDOC_Tag): - /* FALLTHROUGH */ - case (MDOC_Hang): - /* FALLTHROUGH */ - case (MDOC_Dash): - /* FALLTHROUGH */ - case (MDOC_Hyphen): - /* FALLTHROUGH */ - case (MDOC_Inset): - /* FALLTHROUGH */ - case (MDOC_Diag): - /* FALLTHROUGH */ - case (MDOC_Item): - /* FALLTHROUGH */ - case (MDOC_Column): - /* FALLTHROUGH */ - case (MDOC_Ohang): - return(1); - default: - break; - } - - abort(); - /* NOTREACHED */ + ord = SLIST_FIRST(&h->ords); + assert(ord); + SLIST_REMOVE_HEAD(&h->ords, entry); + free(ord); } static int mdoc_it_pre(MDOC_ARGS) { - int i, len, type; - const struct mdoc_node *bl; + int type; if (MDOC_BLOCK == n->type) - bl = n->parent->parent; + type = a2list(n->parent->parent); else - bl = n->parent->parent->parent; + type = a2list(n->parent->parent->parent); - assert(bl->args); - len = (int)bl->args->argc; - - for (i = 0; i < len; i++) - switch ((type = bl->args->argv[i].arg)) { - case (MDOC_Tag): - /* FALLTHROUGH */ - case (MDOC_Hang): - return(mdoc_tbl_pre(m, n, h, type)); - case (MDOC_Enum): - /* FALLTHROUGH */ - case (MDOC_Bullet): - return(mdoc_listitem_pre(m, n, h)); - case (MDOC_Dash): - /* FALLTHROUGH */ - case (MDOC_Hyphen): - /* FALLTHROUGH */ - case (MDOC_Inset): - /* FALLTHROUGH */ - case (MDOC_Diag): - /* FALLTHROUGH */ - case (MDOC_Item): - /* FALLTHROUGH */ - case (MDOC_Column): - /* FALLTHROUGH */ - case (MDOC_Ohang): - return(0); - default: - break; - } - - abort(); - /* NOTREACHED */ + return(mdoc_tbl_pre(m, n, h, type)); } @@ -1611,7 +1766,6 @@ mdoc_d1_pre(MDOC_ARGS) return(1); buffmt("margin-left: %dem;", INDENT); - bufcat("margin-bottom: 0px;"); tag[0].key = ATTR_CLASS; tag[0].val = "lit-block"; @@ -1627,13 +1781,403 @@ mdoc_d1_pre(MDOC_ARGS) static int mdoc_sx_pre(MDOC_ARGS) { - struct htmlpair tag[2]; + struct htmlpair tag[2]; + const struct mdoc_node *nn; + bufcat("#"); + for (nn = n->child; nn; nn = nn->next) { + bufcat(nn->string); + if (nn->next) + bufcat(" "); + } + tag[0].key = ATTR_HREF; - tag[0].val = "#"; /* XXX */ + tag[0].val = buf; tag[1].key = ATTR_CLASS; tag[1].val = "link-sec"; print_otag(h, TAG_A, 2, tag); return(1); +} + + +/* ARGSUSED */ +static int +mdoc_aq_pre(MDOC_ARGS) +{ + + if (MDOC_BODY != n->type) + return(1); + print_text(h, "\\(la"); + h->flags |= HTML_NOSPACE; + return(1); +} + + +/* ARGSUSED */ +static void +mdoc_aq_post(MDOC_ARGS) +{ + + if (MDOC_BODY != n->type) + return; + h->flags |= HTML_NOSPACE; + print_text(h, "\\(ra"); +} + + +/* ARGSUSED */ +static int +mdoc_bd_pre(MDOC_ARGS) +{ + struct htmlpair tag[2]; + int t, c, o, i; + const struct mdoc_node *bl; + + /* FIXME: fmt_vspace() shit. */ + + if (MDOC_BLOCK == n->type) + bl = n; + else if (MDOC_HEAD == n->type) + return(0); + else + bl = n->parent; + + t = o = c = 0; + + for (i = 0; i < (int)bl->args->argc; i++) + switch (bl->args->argv[i].arg) { + case (MDOC_Offset): + assert(bl->args->argv[i].sz); + o = a2offs (bl->args->argv[i].value[0]); + break; + case (MDOC_Compact): + c = 1; + break; + case (MDOC_Ragged): + /* FALLTHROUGH */ + case (MDOC_Filled): + /* FALLTHROUGH */ + case (MDOC_Unfilled): + /* FALLTHROUGH */ + case (MDOC_Literal): + t = bl->args->argv[i].arg; + break; + } + + if (MDOC_BLOCK == n->type) { + if (o) + buffmt("margin-left: %dem;", o); + bufcat("margin-top: 1em;"); + tag[0].key = ATTR_STYLE; + tag[0].val = buf; + print_otag(h, TAG_DIV, 1, tag); + return(1); + } + + switch (t) { + case (MDOC_Unfilled): + case (MDOC_Literal): + break; + default: + return(1); + } + + bufcat("white-space: pre;"); + tag[0].key = ATTR_STYLE; + tag[0].val = buf; + tag[1].key = ATTR_CLASS; + tag[1].val = "lit-block"; + + print_otag(h, TAG_DIV, 2, tag); + + for (n = n->child; n; n = n->next) { + h->flags |= HTML_NOSPACE; + print_mdoc_node(m, n, h); + if (n->next) + print_text(h, "\n"); + } + + return(0); +} + + +/* ARGSUSED */ +static int +mdoc_pa_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "file"; + + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_qq_pre(MDOC_ARGS) +{ + + if (MDOC_BODY != n->type) + return(1); + print_text(h, "\\*q"); + h->flags |= HTML_NOSPACE; + return(1); +} + + +/* ARGSUSED */ +static void +mdoc_qq_post(MDOC_ARGS) +{ + + if (MDOC_BODY != n->type) + return; + h->flags |= HTML_NOSPACE; + print_text(h, "\\*q"); +} + + +/* ARGSUSED */ +static int +mdoc_ad_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "addr"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_an_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "author"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_cd_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "config"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_dv_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "define"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_ev_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "env"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_er_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + tag.key = ATTR_CLASS; + tag.val = "errno"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_fa_pre(MDOC_ARGS) +{ + const struct mdoc_node *nn; + struct htmlpair tag; + struct tag *t; + + tag.key = ATTR_CLASS; + tag.val = "farg"; + + if (n->parent->tok != MDOC_Fo) { + print_otag(h, TAG_SPAN, 1, &tag); + return(1); + } + + for (nn = n->child; nn; nn = nn->next) { + t = print_otag(h, TAG_SPAN, 1, &tag); + print_text(h, nn->string); + print_tagq(h, t); + if (nn->next) + print_text(h, ","); + } + + if (n->child && n->next && n->next->tok == MDOC_Fa) + print_text(h, ","); + + return(0); +} + + +/* ARGSUSED */ +static int +mdoc_fd_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + if (SEC_SYNOPSIS == n->sec) { + if (n->next && MDOC_Fd != n->next->tok) { + tag.key = ATTR_STYLE; + tag.val = "margin-bottom: 1em;"; + print_otag(h, TAG_DIV, 1, &tag); + } else + print_otag(h, TAG_DIV, 0, NULL); + } + + tag.key = ATTR_CLASS; + tag.val = "macro"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_vt_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + if (SEC_SYNOPSIS == n->sec) { + if (n->next && MDOC_Vt != n->next->tok) { + tag.key = ATTR_STYLE; + tag.val = "margin-bottom: 1em;"; + print_otag(h, TAG_DIV, 1, &tag); + } else + print_otag(h, TAG_DIV, 0, NULL); + } + + tag.key = ATTR_CLASS; + tag.val = "type"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + +/* ARGSUSED */ +static int +mdoc_ft_pre(MDOC_ARGS) +{ + struct htmlpair tag; + + if (SEC_SYNOPSIS == n->sec) { + if (n->prev && MDOC_Fo == n->prev->tok) { + tag.key = ATTR_STYLE; + tag.val = "magin-bottom: 1em;"; + print_otag(h, TAG_DIV, 1, &tag); + } else + print_otag(h, TAG_DIV, 0, NULL); + } + + tag.key = ATTR_CLASS; + tag.val = "type"; + print_otag(h, TAG_SPAN, 1, &tag); + return(1); +} + + +/* ARGSUSED */ +static int +mdoc_fn_pre(MDOC_ARGS) +{ + struct tag *t; + struct htmlpair tag; + const struct mdoc_node *nn; + + if (SEC_SYNOPSIS == n->sec) { + if (n->next) { + tag.key = ATTR_STYLE; + tag.val = "margin-bottom: 1em"; + print_otag(h, TAG_DIV, 1, &tag); + } else + print_otag(h, TAG_DIV, 0, NULL); + } + + tag.key = ATTR_CLASS; + tag.val = "type"; + + t = print_otag(h, TAG_SPAN, 1, &tag); + print_text(h, n->child->string); + print_tagq(h, t); + + h->flags |= HTML_NOSPACE; + print_text(h, "("); + + for (nn = n->child->next; nn; nn = nn->next) { + tag.key = ATTR_CLASS; + tag.val = "farg"; + t = print_otag(h, TAG_SPAN, 1, &tag); + print_text(h, nn->string); + print_tagq(h, t); + if (nn->next) + print_text(h, ","); + } + + print_text(h, ")"); + + if (SEC_SYNOPSIS == n->sec) + print_text(h, ";"); + + return(0); +} + + +/* ARGSUSED */ +static int +mdoc_sp_pre(MDOC_ARGS) +{ + int len; + struct htmlpair tag; + + if (MDOC_sp == n->tok) + len = n->child ? atoi(n->child->string) : 1; + else + len = 1; + + buffmt("height: %dem", len); + + tag.key = ATTR_STYLE; + tag.val = buf; + print_otag(h, TAG_DIV, 1, &tag); + return(1); + }