1*0a6a1f1dSLionel Sambuc /* Id: man_html.c,v 1.90 2013/10/17 20:54:58 schwarze Exp */
2d65f6f70SBen Gras /*
3*0a6a1f1dSLionel Sambuc * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4*0a6a1f1dSLionel Sambuc * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
5d65f6f70SBen Gras *
6d65f6f70SBen Gras * Permission to use, copy, modify, and distribute this software for any
7d65f6f70SBen Gras * purpose with or without fee is hereby granted, provided that the above
8d65f6f70SBen Gras * copyright notice and this permission notice appear in all copies.
9d65f6f70SBen Gras *
10d65f6f70SBen Gras * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d65f6f70SBen Gras * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d65f6f70SBen Gras * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d65f6f70SBen Gras * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d65f6f70SBen Gras * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d65f6f70SBen Gras * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d65f6f70SBen Gras * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17d65f6f70SBen Gras */
18d65f6f70SBen Gras #ifdef HAVE_CONFIG_H
19d65f6f70SBen Gras #include "config.h"
20d65f6f70SBen Gras #endif
21d65f6f70SBen Gras
22d65f6f70SBen Gras #include <sys/types.h>
23d65f6f70SBen Gras
24d65f6f70SBen Gras #include <assert.h>
25d65f6f70SBen Gras #include <ctype.h>
26d65f6f70SBen Gras #include <stdio.h>
27d65f6f70SBen Gras #include <stdlib.h>
28d65f6f70SBen Gras #include <string.h>
29d65f6f70SBen Gras
30d65f6f70SBen Gras #include "mandoc.h"
31d65f6f70SBen Gras #include "out.h"
32d65f6f70SBen Gras #include "html.h"
33d65f6f70SBen Gras #include "man.h"
34d65f6f70SBen Gras #include "main.h"
35d65f6f70SBen Gras
36d65f6f70SBen Gras /* TODO: preserve ident widths. */
37d65f6f70SBen Gras /* FIXME: have PD set the default vspace width. */
38d65f6f70SBen Gras
39d65f6f70SBen Gras #define INDENT 5
40d65f6f70SBen Gras
41*0a6a1f1dSLionel Sambuc #define MAN_ARGS const struct man_meta *man, \
42d65f6f70SBen Gras const struct man_node *n, \
43d65f6f70SBen Gras struct mhtml *mh, \
44d65f6f70SBen Gras struct html *h
45d65f6f70SBen Gras
46d65f6f70SBen Gras struct mhtml {
47d65f6f70SBen Gras int fl;
48d65f6f70SBen Gras #define MANH_LITERAL (1 << 0) /* literal context */
49d65f6f70SBen Gras };
50d65f6f70SBen Gras
51d65f6f70SBen Gras struct htmlman {
52d65f6f70SBen Gras int (*pre)(MAN_ARGS);
53d65f6f70SBen Gras int (*post)(MAN_ARGS);
54d65f6f70SBen Gras };
55d65f6f70SBen Gras
5692395e9cSLionel Sambuc static void print_bvspace(struct html *,
5792395e9cSLionel Sambuc const struct man_node *);
58d65f6f70SBen Gras static void print_man(MAN_ARGS);
59d65f6f70SBen Gras static void print_man_head(MAN_ARGS);
60d65f6f70SBen Gras static void print_man_nodelist(MAN_ARGS);
61d65f6f70SBen Gras static void print_man_node(MAN_ARGS);
62d65f6f70SBen Gras static int a2width(const struct man_node *,
63d65f6f70SBen Gras struct roffsu *);
6492395e9cSLionel Sambuc static int man_B_pre(MAN_ARGS);
6592395e9cSLionel Sambuc static int man_HP_pre(MAN_ARGS);
6692395e9cSLionel Sambuc static int man_IP_pre(MAN_ARGS);
6792395e9cSLionel Sambuc static int man_I_pre(MAN_ARGS);
6892395e9cSLionel Sambuc static int man_OP_pre(MAN_ARGS);
6992395e9cSLionel Sambuc static int man_PP_pre(MAN_ARGS);
7092395e9cSLionel Sambuc static int man_RS_pre(MAN_ARGS);
7192395e9cSLionel Sambuc static int man_SH_pre(MAN_ARGS);
7292395e9cSLionel Sambuc static int man_SM_pre(MAN_ARGS);
7392395e9cSLionel Sambuc static int man_SS_pre(MAN_ARGS);
74*0a6a1f1dSLionel Sambuc static int man_UR_pre(MAN_ARGS);
75d65f6f70SBen Gras static int man_alt_pre(MAN_ARGS);
76d65f6f70SBen Gras static int man_br_pre(MAN_ARGS);
77d65f6f70SBen Gras static int man_ign_pre(MAN_ARGS);
78d65f6f70SBen Gras static int man_in_pre(MAN_ARGS);
79d65f6f70SBen Gras static int man_literal_pre(MAN_ARGS);
80d65f6f70SBen Gras static void man_root_post(MAN_ARGS);
8192395e9cSLionel Sambuc static void man_root_pre(MAN_ARGS);
82d65f6f70SBen Gras
83d65f6f70SBen Gras static const struct htmlman mans[MAN_MAX] = {
84d65f6f70SBen Gras { man_br_pre, NULL }, /* br */
85d65f6f70SBen Gras { NULL, NULL }, /* TH */
86d65f6f70SBen Gras { man_SH_pre, NULL }, /* SH */
87d65f6f70SBen Gras { man_SS_pre, NULL }, /* SS */
88d65f6f70SBen Gras { man_IP_pre, NULL }, /* TP */
89d65f6f70SBen Gras { man_PP_pre, NULL }, /* LP */
90d65f6f70SBen Gras { man_PP_pre, NULL }, /* PP */
91d65f6f70SBen Gras { man_PP_pre, NULL }, /* P */
92d65f6f70SBen Gras { man_IP_pre, NULL }, /* IP */
93d65f6f70SBen Gras { man_HP_pre, NULL }, /* HP */
94d65f6f70SBen Gras { man_SM_pre, NULL }, /* SM */
95d65f6f70SBen Gras { man_SM_pre, NULL }, /* SB */
96d65f6f70SBen Gras { man_alt_pre, NULL }, /* BI */
97d65f6f70SBen Gras { man_alt_pre, NULL }, /* IB */
98d65f6f70SBen Gras { man_alt_pre, NULL }, /* BR */
99d65f6f70SBen Gras { man_alt_pre, NULL }, /* RB */
100d65f6f70SBen Gras { NULL, NULL }, /* R */
101d65f6f70SBen Gras { man_B_pre, NULL }, /* B */
102d65f6f70SBen Gras { man_I_pre, NULL }, /* I */
103d65f6f70SBen Gras { man_alt_pre, NULL }, /* IR */
104d65f6f70SBen Gras { man_alt_pre, NULL }, /* RI */
10592395e9cSLionel Sambuc { man_ign_pre, NULL }, /* na */
106d65f6f70SBen Gras { man_br_pre, NULL }, /* sp */
107d65f6f70SBen Gras { man_literal_pre, NULL }, /* nf */
108d65f6f70SBen Gras { man_literal_pre, NULL }, /* fi */
109d65f6f70SBen Gras { NULL, NULL }, /* RE */
110d65f6f70SBen Gras { man_RS_pre, NULL }, /* RS */
111d65f6f70SBen Gras { man_ign_pre, NULL }, /* DT */
112d65f6f70SBen Gras { man_ign_pre, NULL }, /* UC */
113d65f6f70SBen Gras { man_ign_pre, NULL }, /* PD */
114d65f6f70SBen Gras { man_ign_pre, NULL }, /* AT */
115d65f6f70SBen Gras { man_in_pre, NULL }, /* in */
116d65f6f70SBen Gras { man_ign_pre, NULL }, /* ft */
11792395e9cSLionel Sambuc { man_OP_pre, NULL }, /* OP */
118*0a6a1f1dSLionel Sambuc { man_literal_pre, NULL }, /* EX */
119*0a6a1f1dSLionel Sambuc { man_literal_pre, NULL }, /* EE */
120*0a6a1f1dSLionel Sambuc { man_UR_pre, NULL }, /* UR */
121*0a6a1f1dSLionel Sambuc { NULL, NULL }, /* UE */
122d65f6f70SBen Gras };
123d65f6f70SBen Gras
12492395e9cSLionel Sambuc /*
12592395e9cSLionel Sambuc * Printing leading vertical space before a block.
12692395e9cSLionel Sambuc * This is used for the paragraph macros.
12792395e9cSLionel Sambuc * The rules are pretty simple, since there's very little nesting going
12892395e9cSLionel Sambuc * on here. Basically, if we're the first within another block (SS/SH),
12992395e9cSLionel Sambuc * then don't emit vertical space. If we are (RS), then do. If not the
13092395e9cSLionel Sambuc * first, print it.
13192395e9cSLionel Sambuc */
13292395e9cSLionel Sambuc static void
print_bvspace(struct html * h,const struct man_node * n)13392395e9cSLionel Sambuc print_bvspace(struct html *h, const struct man_node *n)
13492395e9cSLionel Sambuc {
13592395e9cSLionel Sambuc
13692395e9cSLionel Sambuc if (n->body && n->body->child)
13792395e9cSLionel Sambuc if (MAN_TBL == n->body->child->type)
13892395e9cSLionel Sambuc return;
13992395e9cSLionel Sambuc
14092395e9cSLionel Sambuc if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok)
14192395e9cSLionel Sambuc if (NULL == n->prev)
14292395e9cSLionel Sambuc return;
14392395e9cSLionel Sambuc
14492395e9cSLionel Sambuc print_otag(h, TAG_P, 0, NULL);
14592395e9cSLionel Sambuc }
146d65f6f70SBen Gras
147d65f6f70SBen Gras void
html_man(void * arg,const struct man * man)148*0a6a1f1dSLionel Sambuc html_man(void *arg, const struct man *man)
149d65f6f70SBen Gras {
150d65f6f70SBen Gras struct mhtml mh;
151d65f6f70SBen Gras
152d65f6f70SBen Gras memset(&mh, 0, sizeof(struct mhtml));
153*0a6a1f1dSLionel Sambuc print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
15492395e9cSLionel Sambuc putchar('\n');
155d65f6f70SBen Gras }
156d65f6f70SBen Gras
157d65f6f70SBen Gras static void
print_man(MAN_ARGS)158d65f6f70SBen Gras print_man(MAN_ARGS)
159d65f6f70SBen Gras {
16092395e9cSLionel Sambuc struct tag *t, *tt;
16192395e9cSLionel Sambuc struct htmlpair tag;
162d65f6f70SBen Gras
16392395e9cSLionel Sambuc PAIR_CLASS_INIT(&tag, "mandoc");
16492395e9cSLionel Sambuc
16592395e9cSLionel Sambuc if ( ! (HTML_FRAGMENT & h->oflags)) {
16692395e9cSLionel Sambuc print_gen_decls(h);
16792395e9cSLionel Sambuc t = print_otag(h, TAG_HTML, 0, NULL);
16892395e9cSLionel Sambuc tt = print_otag(h, TAG_HEAD, 0, NULL);
169*0a6a1f1dSLionel Sambuc print_man_head(man, n, mh, h);
17092395e9cSLionel Sambuc print_tagq(h, tt);
17192395e9cSLionel Sambuc print_otag(h, TAG_BODY, 0, NULL);
17292395e9cSLionel Sambuc print_otag(h, TAG_DIV, 1, &tag);
17392395e9cSLionel Sambuc } else
17492395e9cSLionel Sambuc t = print_otag(h, TAG_DIV, 1, &tag);
175d65f6f70SBen Gras
176*0a6a1f1dSLionel Sambuc print_man_nodelist(man, n, mh, h);
177d65f6f70SBen Gras print_tagq(h, t);
178d65f6f70SBen Gras }
179d65f6f70SBen Gras
180d65f6f70SBen Gras
181d65f6f70SBen Gras /* ARGSUSED */
182d65f6f70SBen Gras static void
print_man_head(MAN_ARGS)183d65f6f70SBen Gras print_man_head(MAN_ARGS)
184d65f6f70SBen Gras {
185d65f6f70SBen Gras
186d65f6f70SBen Gras print_gen_head(h);
187*0a6a1f1dSLionel Sambuc assert(man->title);
188*0a6a1f1dSLionel Sambuc assert(man->msec);
189*0a6a1f1dSLionel Sambuc bufcat_fmt(h, "%s(%s)", man->title, man->msec);
190d65f6f70SBen Gras print_otag(h, TAG_TITLE, 0, NULL);
191d65f6f70SBen Gras print_text(h, h->buf);
192d65f6f70SBen Gras }
193d65f6f70SBen Gras
194d65f6f70SBen Gras
195d65f6f70SBen Gras static void
print_man_nodelist(MAN_ARGS)196d65f6f70SBen Gras print_man_nodelist(MAN_ARGS)
197d65f6f70SBen Gras {
198d65f6f70SBen Gras
199*0a6a1f1dSLionel Sambuc print_man_node(man, n, mh, h);
200d65f6f70SBen Gras if (n->next)
201*0a6a1f1dSLionel Sambuc print_man_nodelist(man, n->next, mh, h);
202d65f6f70SBen Gras }
203d65f6f70SBen Gras
204d65f6f70SBen Gras
205d65f6f70SBen Gras static void
print_man_node(MAN_ARGS)206d65f6f70SBen Gras print_man_node(MAN_ARGS)
207d65f6f70SBen Gras {
208d65f6f70SBen Gras int child;
209d65f6f70SBen Gras struct tag *t;
210d65f6f70SBen Gras
211d65f6f70SBen Gras child = 1;
212d65f6f70SBen Gras t = h->tags.head;
213d65f6f70SBen Gras
214d65f6f70SBen Gras switch (n->type) {
215d65f6f70SBen Gras case (MAN_ROOT):
216*0a6a1f1dSLionel Sambuc man_root_pre(man, n, mh, h);
217d65f6f70SBen Gras break;
218d65f6f70SBen Gras case (MAN_TEXT):
21992395e9cSLionel Sambuc /*
22092395e9cSLionel Sambuc * If we have a blank line, output a vertical space.
22192395e9cSLionel Sambuc * If we have a space as the first character, break
22292395e9cSLionel Sambuc * before printing the line's data.
22392395e9cSLionel Sambuc */
22492395e9cSLionel Sambuc if ('\0' == *n->string) {
22592395e9cSLionel Sambuc print_otag(h, TAG_P, 0, NULL);
226d65f6f70SBen Gras return;
22792395e9cSLionel Sambuc }
22892395e9cSLionel Sambuc
22992395e9cSLionel Sambuc if (' ' == *n->string && MAN_LINE & n->flags)
23092395e9cSLionel Sambuc print_otag(h, TAG_BR, 0, NULL);
23192395e9cSLionel Sambuc else if (MANH_LITERAL & mh->fl && n->prev)
23292395e9cSLionel Sambuc print_otag(h, TAG_BR, 0, NULL);
23392395e9cSLionel Sambuc
23492395e9cSLionel Sambuc print_text(h, n->string);
23592395e9cSLionel Sambuc return;
23692395e9cSLionel Sambuc case (MAN_EQN):
23792395e9cSLionel Sambuc print_eqn(h, n->eqn);
238d65f6f70SBen Gras break;
23992395e9cSLionel Sambuc case (MAN_TBL):
24092395e9cSLionel Sambuc /*
24192395e9cSLionel Sambuc * This will take care of initialising all of the table
24292395e9cSLionel Sambuc * state data for the first table, then tearing it down
24392395e9cSLionel Sambuc * for the last one.
24492395e9cSLionel Sambuc */
24592395e9cSLionel Sambuc print_tbl(h, n->span);
24692395e9cSLionel Sambuc return;
247d65f6f70SBen Gras default:
248d65f6f70SBen Gras /*
249d65f6f70SBen Gras * Close out scope of font prior to opening a macro
25092395e9cSLionel Sambuc * scope.
251d65f6f70SBen Gras */
252d65f6f70SBen Gras if (HTMLFONT_NONE != h->metac) {
253d65f6f70SBen Gras h->metal = h->metac;
254d65f6f70SBen Gras h->metac = HTMLFONT_NONE;
255d65f6f70SBen Gras }
25692395e9cSLionel Sambuc
25792395e9cSLionel Sambuc /*
25892395e9cSLionel Sambuc * Close out the current table, if it's open, and unset
25992395e9cSLionel Sambuc * the "meta" table state. This will be reopened on the
26092395e9cSLionel Sambuc * next table element.
26192395e9cSLionel Sambuc */
26292395e9cSLionel Sambuc if (h->tblt) {
26392395e9cSLionel Sambuc print_tblclose(h);
26492395e9cSLionel Sambuc t = h->tags.head;
26592395e9cSLionel Sambuc }
266d65f6f70SBen Gras if (mans[n->tok].pre)
267*0a6a1f1dSLionel Sambuc child = (*mans[n->tok].pre)(man, n, mh, h);
268d65f6f70SBen Gras break;
269d65f6f70SBen Gras }
270d65f6f70SBen Gras
271d65f6f70SBen Gras if (child && n->child)
272*0a6a1f1dSLionel Sambuc print_man_nodelist(man, n->child, mh, h);
273d65f6f70SBen Gras
274d65f6f70SBen Gras /* This will automatically close out any font scope. */
275d65f6f70SBen Gras print_stagq(h, t);
276d65f6f70SBen Gras
277d65f6f70SBen Gras switch (n->type) {
278d65f6f70SBen Gras case (MAN_ROOT):
279*0a6a1f1dSLionel Sambuc man_root_post(man, n, mh, h);
280d65f6f70SBen Gras break;
28192395e9cSLionel Sambuc case (MAN_EQN):
282d65f6f70SBen Gras break;
283d65f6f70SBen Gras default:
284d65f6f70SBen Gras if (mans[n->tok].post)
285*0a6a1f1dSLionel Sambuc (*mans[n->tok].post)(man, n, mh, h);
286d65f6f70SBen Gras break;
287d65f6f70SBen Gras }
288d65f6f70SBen Gras }
289d65f6f70SBen Gras
290d65f6f70SBen Gras
291d65f6f70SBen Gras static int
a2width(const struct man_node * n,struct roffsu * su)292d65f6f70SBen Gras a2width(const struct man_node *n, struct roffsu *su)
293d65f6f70SBen Gras {
294d65f6f70SBen Gras
295d65f6f70SBen Gras if (MAN_TEXT != n->type)
296d65f6f70SBen Gras return(0);
297d65f6f70SBen Gras if (a2roffsu(n->string, su, SCALE_BU))
298d65f6f70SBen Gras return(1);
299d65f6f70SBen Gras
300d65f6f70SBen Gras return(0);
301d65f6f70SBen Gras }
302d65f6f70SBen Gras
303d65f6f70SBen Gras
304d65f6f70SBen Gras /* ARGSUSED */
30592395e9cSLionel Sambuc static void
man_root_pre(MAN_ARGS)306d65f6f70SBen Gras man_root_pre(MAN_ARGS)
307d65f6f70SBen Gras {
308d65f6f70SBen Gras struct htmlpair tag[3];
309d65f6f70SBen Gras struct tag *t, *tt;
310d65f6f70SBen Gras char b[BUFSIZ], title[BUFSIZ];
311d65f6f70SBen Gras
312d65f6f70SBen Gras b[0] = 0;
313*0a6a1f1dSLionel Sambuc if (man->vol)
314*0a6a1f1dSLionel Sambuc (void)strlcat(b, man->vol, BUFSIZ);
315d65f6f70SBen Gras
316*0a6a1f1dSLionel Sambuc assert(man->title);
317*0a6a1f1dSLionel Sambuc assert(man->msec);
318*0a6a1f1dSLionel Sambuc snprintf(title, BUFSIZ - 1, "%s(%s)", man->title, man->msec);
319d65f6f70SBen Gras
320d65f6f70SBen Gras PAIR_SUMMARY_INIT(&tag[0], "Document Header");
321d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[1], "head");
322d65f6f70SBen Gras PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
323d65f6f70SBen Gras t = print_otag(h, TAG_TABLE, 3, tag);
324d65f6f70SBen Gras PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
325d65f6f70SBen Gras print_otag(h, TAG_COL, 1, tag);
326d65f6f70SBen Gras print_otag(h, TAG_COL, 1, tag);
327d65f6f70SBen Gras print_otag(h, TAG_COL, 1, tag);
328d65f6f70SBen Gras
329d65f6f70SBen Gras print_otag(h, TAG_TBODY, 0, NULL);
330d65f6f70SBen Gras
331d65f6f70SBen Gras tt = print_otag(h, TAG_TR, 0, NULL);
332d65f6f70SBen Gras
333d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[0], "head-ltitle");
334d65f6f70SBen Gras print_otag(h, TAG_TD, 1, tag);
335d65f6f70SBen Gras print_text(h, title);
336d65f6f70SBen Gras print_stagq(h, tt);
337d65f6f70SBen Gras
338d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[0], "head-vol");
339d65f6f70SBen Gras PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
340d65f6f70SBen Gras print_otag(h, TAG_TD, 2, tag);
341d65f6f70SBen Gras print_text(h, b);
342d65f6f70SBen Gras print_stagq(h, tt);
343d65f6f70SBen Gras
344d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[0], "head-rtitle");
345d65f6f70SBen Gras PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
346d65f6f70SBen Gras print_otag(h, TAG_TD, 2, tag);
347d65f6f70SBen Gras print_text(h, title);
348d65f6f70SBen Gras print_tagq(h, t);
349d65f6f70SBen Gras }
350d65f6f70SBen Gras
351d65f6f70SBen Gras
352d65f6f70SBen Gras /* ARGSUSED */
353d65f6f70SBen Gras static void
man_root_post(MAN_ARGS)354d65f6f70SBen Gras man_root_post(MAN_ARGS)
355d65f6f70SBen Gras {
356d65f6f70SBen Gras struct htmlpair tag[3];
357d65f6f70SBen Gras struct tag *t, *tt;
358d65f6f70SBen Gras
359d65f6f70SBen Gras PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
360d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[1], "foot");
361d65f6f70SBen Gras PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
362d65f6f70SBen Gras t = print_otag(h, TAG_TABLE, 3, tag);
363d65f6f70SBen Gras PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
364d65f6f70SBen Gras print_otag(h, TAG_COL, 1, tag);
365d65f6f70SBen Gras print_otag(h, TAG_COL, 1, tag);
366d65f6f70SBen Gras
367d65f6f70SBen Gras tt = print_otag(h, TAG_TR, 0, NULL);
368d65f6f70SBen Gras
369d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[0], "foot-date");
370d65f6f70SBen Gras print_otag(h, TAG_TD, 1, tag);
371d65f6f70SBen Gras
372*0a6a1f1dSLionel Sambuc assert(man->date);
373*0a6a1f1dSLionel Sambuc print_text(h, man->date);
374d65f6f70SBen Gras print_stagq(h, tt);
375d65f6f70SBen Gras
376d65f6f70SBen Gras PAIR_CLASS_INIT(&tag[0], "foot-os");
377d65f6f70SBen Gras PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
378d65f6f70SBen Gras print_otag(h, TAG_TD, 2, tag);
379d65f6f70SBen Gras
380*0a6a1f1dSLionel Sambuc if (man->source)
381*0a6a1f1dSLionel Sambuc print_text(h, man->source);
382d65f6f70SBen Gras print_tagq(h, t);
383d65f6f70SBen Gras }
384d65f6f70SBen Gras
385d65f6f70SBen Gras
386d65f6f70SBen Gras /* ARGSUSED */
387d65f6f70SBen Gras static int
man_br_pre(MAN_ARGS)388d65f6f70SBen Gras man_br_pre(MAN_ARGS)
389d65f6f70SBen Gras {
390d65f6f70SBen Gras struct roffsu su;
391d65f6f70SBen Gras struct htmlpair tag;
392d65f6f70SBen Gras
393d65f6f70SBen Gras SCALE_VS_INIT(&su, 1);
394d65f6f70SBen Gras
395d65f6f70SBen Gras if (MAN_sp == n->tok) {
39692395e9cSLionel Sambuc if (NULL != (n = n->child))
39792395e9cSLionel Sambuc if ( ! a2roffsu(n->string, &su, SCALE_VS))
39892395e9cSLionel Sambuc SCALE_VS_INIT(&su, atoi(n->string));
399d65f6f70SBen Gras } else
400d65f6f70SBen Gras su.scale = 0;
401d65f6f70SBen Gras
40292395e9cSLionel Sambuc bufinit(h);
403d65f6f70SBen Gras bufcat_su(h, "height", &su);
404d65f6f70SBen Gras PAIR_STYLE_INIT(&tag, h);
405d65f6f70SBen Gras print_otag(h, TAG_DIV, 1, &tag);
406d65f6f70SBen Gras
407d65f6f70SBen Gras /* So the div isn't empty: */
408d65f6f70SBen Gras print_text(h, "\\~");
409d65f6f70SBen Gras
410d65f6f70SBen Gras return(0);
411d65f6f70SBen Gras }
412d65f6f70SBen Gras
413d65f6f70SBen Gras /* ARGSUSED */
414d65f6f70SBen Gras static int
man_SH_pre(MAN_ARGS)415d65f6f70SBen Gras man_SH_pre(MAN_ARGS)
416d65f6f70SBen Gras {
417d65f6f70SBen Gras struct htmlpair tag;
418d65f6f70SBen Gras
419d65f6f70SBen Gras if (MAN_BLOCK == n->type) {
42092395e9cSLionel Sambuc mh->fl &= ~MANH_LITERAL;
421d65f6f70SBen Gras PAIR_CLASS_INIT(&tag, "section");
422d65f6f70SBen Gras print_otag(h, TAG_DIV, 1, &tag);
423d65f6f70SBen Gras return(1);
424d65f6f70SBen Gras } else if (MAN_BODY == n->type)
425d65f6f70SBen Gras return(1);
426d65f6f70SBen Gras
427d65f6f70SBen Gras print_otag(h, TAG_H1, 0, NULL);
428d65f6f70SBen Gras return(1);
429d65f6f70SBen Gras }
430d65f6f70SBen Gras
431d65f6f70SBen Gras /* ARGSUSED */
432d65f6f70SBen Gras static int
man_alt_pre(MAN_ARGS)433d65f6f70SBen Gras man_alt_pre(MAN_ARGS)
434d65f6f70SBen Gras {
435d65f6f70SBen Gras const struct man_node *nn;
43692395e9cSLionel Sambuc int i, savelit;
437d65f6f70SBen Gras enum htmltag fp;
438d65f6f70SBen Gras struct tag *t;
439d65f6f70SBen Gras
44092395e9cSLionel Sambuc if ((savelit = mh->fl & MANH_LITERAL))
44192395e9cSLionel Sambuc print_otag(h, TAG_BR, 0, NULL);
44292395e9cSLionel Sambuc
44392395e9cSLionel Sambuc mh->fl &= ~MANH_LITERAL;
44492395e9cSLionel Sambuc
445d65f6f70SBen Gras for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
446d65f6f70SBen Gras t = NULL;
447d65f6f70SBen Gras switch (n->tok) {
448d65f6f70SBen Gras case (MAN_BI):
449d65f6f70SBen Gras fp = i % 2 ? TAG_I : TAG_B;
450d65f6f70SBen Gras break;
451d65f6f70SBen Gras case (MAN_IB):
452d65f6f70SBen Gras fp = i % 2 ? TAG_B : TAG_I;
453d65f6f70SBen Gras break;
454d65f6f70SBen Gras case (MAN_RI):
455d65f6f70SBen Gras fp = i % 2 ? TAG_I : TAG_MAX;
456d65f6f70SBen Gras break;
457d65f6f70SBen Gras case (MAN_IR):
458d65f6f70SBen Gras fp = i % 2 ? TAG_MAX : TAG_I;
459d65f6f70SBen Gras break;
460d65f6f70SBen Gras case (MAN_BR):
461d65f6f70SBen Gras fp = i % 2 ? TAG_MAX : TAG_B;
462d65f6f70SBen Gras break;
463d65f6f70SBen Gras case (MAN_RB):
464d65f6f70SBen Gras fp = i % 2 ? TAG_B : TAG_MAX;
465d65f6f70SBen Gras break;
466d65f6f70SBen Gras default:
467d65f6f70SBen Gras abort();
468d65f6f70SBen Gras /* NOTREACHED */
469d65f6f70SBen Gras }
470d65f6f70SBen Gras
471d65f6f70SBen Gras if (i)
472d65f6f70SBen Gras h->flags |= HTML_NOSPACE;
473d65f6f70SBen Gras
474d65f6f70SBen Gras if (TAG_MAX != fp)
475d65f6f70SBen Gras t = print_otag(h, fp, 0, NULL);
476d65f6f70SBen Gras
477*0a6a1f1dSLionel Sambuc print_man_node(man, nn, mh, h);
478d65f6f70SBen Gras
479d65f6f70SBen Gras if (t)
480d65f6f70SBen Gras print_tagq(h, t);
481d65f6f70SBen Gras }
482d65f6f70SBen Gras
48392395e9cSLionel Sambuc if (savelit)
48492395e9cSLionel Sambuc mh->fl |= MANH_LITERAL;
48592395e9cSLionel Sambuc
486d65f6f70SBen Gras return(0);
487d65f6f70SBen Gras }
488d65f6f70SBen Gras
489d65f6f70SBen Gras /* ARGSUSED */
490d65f6f70SBen Gras static int
man_SM_pre(MAN_ARGS)491d65f6f70SBen Gras man_SM_pre(MAN_ARGS)
492d65f6f70SBen Gras {
493d65f6f70SBen Gras
494d65f6f70SBen Gras print_otag(h, TAG_SMALL, 0, NULL);
495d65f6f70SBen Gras if (MAN_SB == n->tok)
496d65f6f70SBen Gras print_otag(h, TAG_B, 0, NULL);
497d65f6f70SBen Gras return(1);
498d65f6f70SBen Gras }
499d65f6f70SBen Gras
500d65f6f70SBen Gras /* ARGSUSED */
501d65f6f70SBen Gras static int
man_SS_pre(MAN_ARGS)502d65f6f70SBen Gras man_SS_pre(MAN_ARGS)
503d65f6f70SBen Gras {
504d65f6f70SBen Gras struct htmlpair tag;
505d65f6f70SBen Gras
506d65f6f70SBen Gras if (MAN_BLOCK == n->type) {
50792395e9cSLionel Sambuc mh->fl &= ~MANH_LITERAL;
508d65f6f70SBen Gras PAIR_CLASS_INIT(&tag, "subsection");
509d65f6f70SBen Gras print_otag(h, TAG_DIV, 1, &tag);
510d65f6f70SBen Gras return(1);
511d65f6f70SBen Gras } else if (MAN_BODY == n->type)
512d65f6f70SBen Gras return(1);
513d65f6f70SBen Gras
514d65f6f70SBen Gras print_otag(h, TAG_H2, 0, NULL);
515d65f6f70SBen Gras return(1);
516d65f6f70SBen Gras }
517d65f6f70SBen Gras
518d65f6f70SBen Gras /* ARGSUSED */
519d65f6f70SBen Gras static int
man_PP_pre(MAN_ARGS)520d65f6f70SBen Gras man_PP_pre(MAN_ARGS)
521d65f6f70SBen Gras {
522d65f6f70SBen Gras
523d65f6f70SBen Gras if (MAN_HEAD == n->type)
524d65f6f70SBen Gras return(0);
52592395e9cSLionel Sambuc else if (MAN_BLOCK == n->type)
52692395e9cSLionel Sambuc print_bvspace(h, n);
527d65f6f70SBen Gras
528d65f6f70SBen Gras return(1);
529d65f6f70SBen Gras }
530d65f6f70SBen Gras
531d65f6f70SBen Gras /* ARGSUSED */
532d65f6f70SBen Gras static int
man_IP_pre(MAN_ARGS)533d65f6f70SBen Gras man_IP_pre(MAN_ARGS)
534d65f6f70SBen Gras {
535d65f6f70SBen Gras const struct man_node *nn;
536d65f6f70SBen Gras
537d65f6f70SBen Gras if (MAN_BODY == n->type) {
53892395e9cSLionel Sambuc print_otag(h, TAG_DD, 0, NULL);
53992395e9cSLionel Sambuc return(1);
54092395e9cSLionel Sambuc } else if (MAN_HEAD != n->type) {
54192395e9cSLionel Sambuc print_otag(h, TAG_DL, 0, NULL);
542d65f6f70SBen Gras return(1);
543d65f6f70SBen Gras }
544d65f6f70SBen Gras
54592395e9cSLionel Sambuc /* FIXME: width specification. */
546d65f6f70SBen Gras
54792395e9cSLionel Sambuc print_otag(h, TAG_DT, 0, NULL);
548d65f6f70SBen Gras
549d65f6f70SBen Gras /* For IP, only print the first header element. */
550d65f6f70SBen Gras
551d65f6f70SBen Gras if (MAN_IP == n->tok && n->child)
552*0a6a1f1dSLionel Sambuc print_man_node(man, n->child, mh, h);
553d65f6f70SBen Gras
554d65f6f70SBen Gras /* For TP, only print next-line header elements. */
555d65f6f70SBen Gras
556d65f6f70SBen Gras if (MAN_TP == n->tok)
557d65f6f70SBen Gras for (nn = n->child; nn; nn = nn->next)
558d65f6f70SBen Gras if (nn->line > n->line)
559*0a6a1f1dSLionel Sambuc print_man_node(man, nn, mh, h);
560d65f6f70SBen Gras
561d65f6f70SBen Gras return(0);
562d65f6f70SBen Gras }
563d65f6f70SBen Gras
564d65f6f70SBen Gras /* ARGSUSED */
565d65f6f70SBen Gras static int
man_HP_pre(MAN_ARGS)566d65f6f70SBen Gras man_HP_pre(MAN_ARGS)
567d65f6f70SBen Gras {
568d65f6f70SBen Gras struct htmlpair tag;
569d65f6f70SBen Gras struct roffsu su;
570d65f6f70SBen Gras const struct man_node *np;
571d65f6f70SBen Gras
57292395e9cSLionel Sambuc if (MAN_HEAD == n->type)
57392395e9cSLionel Sambuc return(0);
57492395e9cSLionel Sambuc else if (MAN_BLOCK != n->type)
57592395e9cSLionel Sambuc return(1);
57692395e9cSLionel Sambuc
57792395e9cSLionel Sambuc np = n->head->child;
578d65f6f70SBen Gras
579d65f6f70SBen Gras if (NULL == np || ! a2width(np, &su))
580d65f6f70SBen Gras SCALE_HS_INIT(&su, INDENT);
581d65f6f70SBen Gras
58292395e9cSLionel Sambuc bufinit(h);
583d65f6f70SBen Gras
58492395e9cSLionel Sambuc print_bvspace(h, n);
58592395e9cSLionel Sambuc bufcat_su(h, "margin-left", &su);
586d65f6f70SBen Gras su.scale = -su.scale;
587d65f6f70SBen Gras bufcat_su(h, "text-indent", &su);
588d65f6f70SBen Gras PAIR_STYLE_INIT(&tag, h);
58992395e9cSLionel Sambuc print_otag(h, TAG_P, 1, &tag);
590d65f6f70SBen Gras return(1);
591d65f6f70SBen Gras }
592d65f6f70SBen Gras
59392395e9cSLionel Sambuc /* ARGSUSED */
59492395e9cSLionel Sambuc static int
man_OP_pre(MAN_ARGS)59592395e9cSLionel Sambuc man_OP_pre(MAN_ARGS)
59692395e9cSLionel Sambuc {
59792395e9cSLionel Sambuc struct tag *tt;
59892395e9cSLionel Sambuc struct htmlpair tag;
59992395e9cSLionel Sambuc
60092395e9cSLionel Sambuc print_text(h, "[");
60192395e9cSLionel Sambuc h->flags |= HTML_NOSPACE;
60292395e9cSLionel Sambuc PAIR_CLASS_INIT(&tag, "opt");
60392395e9cSLionel Sambuc tt = print_otag(h, TAG_SPAN, 1, &tag);
60492395e9cSLionel Sambuc
60592395e9cSLionel Sambuc if (NULL != (n = n->child)) {
60692395e9cSLionel Sambuc print_otag(h, TAG_B, 0, NULL);
60792395e9cSLionel Sambuc print_text(h, n->string);
60892395e9cSLionel Sambuc }
60992395e9cSLionel Sambuc
61092395e9cSLionel Sambuc print_stagq(h, tt);
61192395e9cSLionel Sambuc
61292395e9cSLionel Sambuc if (NULL != n && NULL != n->next) {
61392395e9cSLionel Sambuc print_otag(h, TAG_I, 0, NULL);
61492395e9cSLionel Sambuc print_text(h, n->next->string);
61592395e9cSLionel Sambuc }
61692395e9cSLionel Sambuc
61792395e9cSLionel Sambuc print_stagq(h, tt);
61892395e9cSLionel Sambuc h->flags |= HTML_NOSPACE;
61992395e9cSLionel Sambuc print_text(h, "]");
62092395e9cSLionel Sambuc return(0);
62192395e9cSLionel Sambuc }
62292395e9cSLionel Sambuc
623d65f6f70SBen Gras
624d65f6f70SBen Gras /* ARGSUSED */
625d65f6f70SBen Gras static int
man_B_pre(MAN_ARGS)626d65f6f70SBen Gras man_B_pre(MAN_ARGS)
627d65f6f70SBen Gras {
628d65f6f70SBen Gras
629d65f6f70SBen Gras print_otag(h, TAG_B, 0, NULL);
630d65f6f70SBen Gras return(1);
631d65f6f70SBen Gras }
632d65f6f70SBen Gras
633d65f6f70SBen Gras /* ARGSUSED */
634d65f6f70SBen Gras static int
man_I_pre(MAN_ARGS)635d65f6f70SBen Gras man_I_pre(MAN_ARGS)
636d65f6f70SBen Gras {
637d65f6f70SBen Gras
638d65f6f70SBen Gras print_otag(h, TAG_I, 0, NULL);
639d65f6f70SBen Gras return(1);
640d65f6f70SBen Gras }
641d65f6f70SBen Gras
642d65f6f70SBen Gras /* ARGSUSED */
643d65f6f70SBen Gras static int
man_literal_pre(MAN_ARGS)644d65f6f70SBen Gras man_literal_pre(MAN_ARGS)
645d65f6f70SBen Gras {
646d65f6f70SBen Gras
647*0a6a1f1dSLionel Sambuc if (MAN_fi == n->tok || MAN_EE == n->tok) {
648d65f6f70SBen Gras print_otag(h, TAG_BR, 0, NULL);
649d65f6f70SBen Gras mh->fl &= ~MANH_LITERAL;
65092395e9cSLionel Sambuc } else
65192395e9cSLionel Sambuc mh->fl |= MANH_LITERAL;
652d65f6f70SBen Gras
65392395e9cSLionel Sambuc return(0);
654d65f6f70SBen Gras }
655d65f6f70SBen Gras
656d65f6f70SBen Gras /* ARGSUSED */
657d65f6f70SBen Gras static int
man_in_pre(MAN_ARGS)658d65f6f70SBen Gras man_in_pre(MAN_ARGS)
659d65f6f70SBen Gras {
660d65f6f70SBen Gras
661d65f6f70SBen Gras print_otag(h, TAG_BR, 0, NULL);
662d65f6f70SBen Gras return(0);
663d65f6f70SBen Gras }
664d65f6f70SBen Gras
665d65f6f70SBen Gras /* ARGSUSED */
666d65f6f70SBen Gras static int
man_ign_pre(MAN_ARGS)667d65f6f70SBen Gras man_ign_pre(MAN_ARGS)
668d65f6f70SBen Gras {
669d65f6f70SBen Gras
670d65f6f70SBen Gras return(0);
671d65f6f70SBen Gras }
672d65f6f70SBen Gras
673d65f6f70SBen Gras /* ARGSUSED */
674d65f6f70SBen Gras static int
man_RS_pre(MAN_ARGS)675d65f6f70SBen Gras man_RS_pre(MAN_ARGS)
676d65f6f70SBen Gras {
677d65f6f70SBen Gras struct htmlpair tag;
678d65f6f70SBen Gras struct roffsu su;
679d65f6f70SBen Gras
680d65f6f70SBen Gras if (MAN_HEAD == n->type)
681d65f6f70SBen Gras return(0);
682d65f6f70SBen Gras else if (MAN_BODY == n->type)
683d65f6f70SBen Gras return(1);
684d65f6f70SBen Gras
685d65f6f70SBen Gras SCALE_HS_INIT(&su, INDENT);
686d65f6f70SBen Gras if (n->head->child)
687d65f6f70SBen Gras a2width(n->head->child, &su);
688d65f6f70SBen Gras
68992395e9cSLionel Sambuc bufinit(h);
690d65f6f70SBen Gras bufcat_su(h, "margin-left", &su);
691d65f6f70SBen Gras PAIR_STYLE_INIT(&tag, h);
692d65f6f70SBen Gras print_otag(h, TAG_DIV, 1, &tag);
693d65f6f70SBen Gras return(1);
694d65f6f70SBen Gras }
695*0a6a1f1dSLionel Sambuc
696*0a6a1f1dSLionel Sambuc /* ARGSUSED */
697*0a6a1f1dSLionel Sambuc static int
man_UR_pre(MAN_ARGS)698*0a6a1f1dSLionel Sambuc man_UR_pre(MAN_ARGS)
699*0a6a1f1dSLionel Sambuc {
700*0a6a1f1dSLionel Sambuc struct htmlpair tag[2];
701*0a6a1f1dSLionel Sambuc
702*0a6a1f1dSLionel Sambuc n = n->child;
703*0a6a1f1dSLionel Sambuc assert(MAN_HEAD == n->type);
704*0a6a1f1dSLionel Sambuc if (n->nchild) {
705*0a6a1f1dSLionel Sambuc assert(MAN_TEXT == n->child->type);
706*0a6a1f1dSLionel Sambuc PAIR_CLASS_INIT(&tag[0], "link-ext");
707*0a6a1f1dSLionel Sambuc PAIR_HREF_INIT(&tag[1], n->child->string);
708*0a6a1f1dSLionel Sambuc print_otag(h, TAG_A, 2, tag);
709*0a6a1f1dSLionel Sambuc }
710*0a6a1f1dSLionel Sambuc
711*0a6a1f1dSLionel Sambuc assert(MAN_BODY == n->next->type);
712*0a6a1f1dSLionel Sambuc if (n->next->nchild)
713*0a6a1f1dSLionel Sambuc n = n->next;
714*0a6a1f1dSLionel Sambuc
715*0a6a1f1dSLionel Sambuc print_man_nodelist(man, n->child, mh, h);
716*0a6a1f1dSLionel Sambuc
717*0a6a1f1dSLionel Sambuc return(0);
718*0a6a1f1dSLionel Sambuc }
719