xref: /titanic_52/usr/src/cmd/mandoc/man_html.c (revision 95c635efb7c3b86efc493e0447eaec7aecca3f0f)
1*95c635efSGarrett D'Amore /*	$Id: man_html.c,v 1.86 2012/01/03 15:16:24 kristaps Exp $ */
2*95c635efSGarrett D'Amore /*
3*95c635efSGarrett D'Amore  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*95c635efSGarrett D'Amore  *
5*95c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
6*95c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
7*95c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
8*95c635efSGarrett D'Amore  *
9*95c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*95c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*95c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*95c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*95c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*95c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*95c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*95c635efSGarrett D'Amore  */
17*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H
18*95c635efSGarrett D'Amore #include "config.h"
19*95c635efSGarrett D'Amore #endif
20*95c635efSGarrett D'Amore 
21*95c635efSGarrett D'Amore #include <sys/types.h>
22*95c635efSGarrett D'Amore 
23*95c635efSGarrett D'Amore #include <assert.h>
24*95c635efSGarrett D'Amore #include <ctype.h>
25*95c635efSGarrett D'Amore #include <stdio.h>
26*95c635efSGarrett D'Amore #include <stdlib.h>
27*95c635efSGarrett D'Amore #include <string.h>
28*95c635efSGarrett D'Amore 
29*95c635efSGarrett D'Amore #include "mandoc.h"
30*95c635efSGarrett D'Amore #include "out.h"
31*95c635efSGarrett D'Amore #include "html.h"
32*95c635efSGarrett D'Amore #include "man.h"
33*95c635efSGarrett D'Amore #include "main.h"
34*95c635efSGarrett D'Amore 
35*95c635efSGarrett D'Amore /* TODO: preserve ident widths. */
36*95c635efSGarrett D'Amore /* FIXME: have PD set the default vspace width. */
37*95c635efSGarrett D'Amore 
38*95c635efSGarrett D'Amore #define	INDENT		  5
39*95c635efSGarrett D'Amore 
40*95c635efSGarrett D'Amore #define	MAN_ARGS	  const struct man_meta *m, \
41*95c635efSGarrett D'Amore 			  const struct man_node *n, \
42*95c635efSGarrett D'Amore 			  struct mhtml *mh, \
43*95c635efSGarrett D'Amore 			  struct html *h
44*95c635efSGarrett D'Amore 
45*95c635efSGarrett D'Amore struct	mhtml {
46*95c635efSGarrett D'Amore 	int		  fl;
47*95c635efSGarrett D'Amore #define	MANH_LITERAL	 (1 << 0) /* literal context */
48*95c635efSGarrett D'Amore };
49*95c635efSGarrett D'Amore 
50*95c635efSGarrett D'Amore struct	htmlman {
51*95c635efSGarrett D'Amore 	int		(*pre)(MAN_ARGS);
52*95c635efSGarrett D'Amore 	int		(*post)(MAN_ARGS);
53*95c635efSGarrett D'Amore };
54*95c635efSGarrett D'Amore 
55*95c635efSGarrett D'Amore static	void		  print_bvspace(struct html *,
56*95c635efSGarrett D'Amore 				const struct man_node *);
57*95c635efSGarrett D'Amore static	void		  print_man(MAN_ARGS);
58*95c635efSGarrett D'Amore static	void		  print_man_head(MAN_ARGS);
59*95c635efSGarrett D'Amore static	void		  print_man_nodelist(MAN_ARGS);
60*95c635efSGarrett D'Amore static	void		  print_man_node(MAN_ARGS);
61*95c635efSGarrett D'Amore static	int		  a2width(const struct man_node *,
62*95c635efSGarrett D'Amore 				struct roffsu *);
63*95c635efSGarrett D'Amore static	int		  man_B_pre(MAN_ARGS);
64*95c635efSGarrett D'Amore static	int		  man_HP_pre(MAN_ARGS);
65*95c635efSGarrett D'Amore static	int		  man_IP_pre(MAN_ARGS);
66*95c635efSGarrett D'Amore static	int		  man_I_pre(MAN_ARGS);
67*95c635efSGarrett D'Amore static	int		  man_OP_pre(MAN_ARGS);
68*95c635efSGarrett D'Amore static	int		  man_PP_pre(MAN_ARGS);
69*95c635efSGarrett D'Amore static	int		  man_RS_pre(MAN_ARGS);
70*95c635efSGarrett D'Amore static	int		  man_SH_pre(MAN_ARGS);
71*95c635efSGarrett D'Amore static	int		  man_SM_pre(MAN_ARGS);
72*95c635efSGarrett D'Amore static	int		  man_SS_pre(MAN_ARGS);
73*95c635efSGarrett D'Amore static	int		  man_alt_pre(MAN_ARGS);
74*95c635efSGarrett D'Amore static	int		  man_br_pre(MAN_ARGS);
75*95c635efSGarrett D'Amore static	int		  man_ign_pre(MAN_ARGS);
76*95c635efSGarrett D'Amore static	int		  man_in_pre(MAN_ARGS);
77*95c635efSGarrett D'Amore static	int		  man_literal_pre(MAN_ARGS);
78*95c635efSGarrett D'Amore static	void		  man_root_post(MAN_ARGS);
79*95c635efSGarrett D'Amore static	void		  man_root_pre(MAN_ARGS);
80*95c635efSGarrett D'Amore 
81*95c635efSGarrett D'Amore static	const struct htmlman mans[MAN_MAX] = {
82*95c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* br */
83*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* TH */
84*95c635efSGarrett D'Amore 	{ man_SH_pre, NULL }, /* SH */
85*95c635efSGarrett D'Amore 	{ man_SS_pre, NULL }, /* SS */
86*95c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* TP */
87*95c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* LP */
88*95c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* PP */
89*95c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* P */
90*95c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* IP */
91*95c635efSGarrett D'Amore 	{ man_HP_pre, NULL }, /* HP */
92*95c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SM */
93*95c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SB */
94*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BI */
95*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IB */
96*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BR */
97*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RB */
98*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* R */
99*95c635efSGarrett D'Amore 	{ man_B_pre, NULL }, /* B */
100*95c635efSGarrett D'Amore 	{ man_I_pre, NULL }, /* I */
101*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IR */
102*95c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RI */
103*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* na */
104*95c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* sp */
105*95c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* nf */
106*95c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* fi */
107*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* RE */
108*95c635efSGarrett D'Amore 	{ man_RS_pre, NULL }, /* RS */
109*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* DT */
110*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* UC */
111*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* PD */
112*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* AT */
113*95c635efSGarrett D'Amore 	{ man_in_pre, NULL }, /* in */
114*95c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* ft */
115*95c635efSGarrett D'Amore 	{ man_OP_pre, NULL }, /* OP */
116*95c635efSGarrett D'Amore };
117*95c635efSGarrett D'Amore 
118*95c635efSGarrett D'Amore /*
119*95c635efSGarrett D'Amore  * Printing leading vertical space before a block.
120*95c635efSGarrett D'Amore  * This is used for the paragraph macros.
121*95c635efSGarrett D'Amore  * The rules are pretty simple, since there's very little nesting going
122*95c635efSGarrett D'Amore  * on here.  Basically, if we're the first within another block (SS/SH),
123*95c635efSGarrett D'Amore  * then don't emit vertical space.  If we are (RS), then do.  If not the
124*95c635efSGarrett D'Amore  * first, print it.
125*95c635efSGarrett D'Amore  */
126*95c635efSGarrett D'Amore static void
127*95c635efSGarrett D'Amore print_bvspace(struct html *h, const struct man_node *n)
128*95c635efSGarrett D'Amore {
129*95c635efSGarrett D'Amore 
130*95c635efSGarrett D'Amore 	if (n->body && n->body->child)
131*95c635efSGarrett D'Amore 		if (MAN_TBL == n->body->child->type)
132*95c635efSGarrett D'Amore 			return;
133*95c635efSGarrett D'Amore 
134*95c635efSGarrett D'Amore 	if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok)
135*95c635efSGarrett D'Amore 		if (NULL == n->prev)
136*95c635efSGarrett D'Amore 			return;
137*95c635efSGarrett D'Amore 
138*95c635efSGarrett D'Amore 	print_otag(h, TAG_P, 0, NULL);
139*95c635efSGarrett D'Amore }
140*95c635efSGarrett D'Amore 
141*95c635efSGarrett D'Amore void
142*95c635efSGarrett D'Amore html_man(void *arg, const struct man *m)
143*95c635efSGarrett D'Amore {
144*95c635efSGarrett D'Amore 	struct mhtml	 mh;
145*95c635efSGarrett D'Amore 
146*95c635efSGarrett D'Amore 	memset(&mh, 0, sizeof(struct mhtml));
147*95c635efSGarrett D'Amore 	print_man(man_meta(m), man_node(m), &mh, (struct html *)arg);
148*95c635efSGarrett D'Amore 	putchar('\n');
149*95c635efSGarrett D'Amore }
150*95c635efSGarrett D'Amore 
151*95c635efSGarrett D'Amore static void
152*95c635efSGarrett D'Amore print_man(MAN_ARGS)
153*95c635efSGarrett D'Amore {
154*95c635efSGarrett D'Amore 	struct tag	*t, *tt;
155*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
156*95c635efSGarrett D'Amore 
157*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "mandoc");
158*95c635efSGarrett D'Amore 
159*95c635efSGarrett D'Amore 	if ( ! (HTML_FRAGMENT & h->oflags)) {
160*95c635efSGarrett D'Amore 		print_gen_decls(h);
161*95c635efSGarrett D'Amore 		t = print_otag(h, TAG_HTML, 0, NULL);
162*95c635efSGarrett D'Amore 		tt = print_otag(h, TAG_HEAD, 0, NULL);
163*95c635efSGarrett D'Amore 		print_man_head(m, n, mh, h);
164*95c635efSGarrett D'Amore 		print_tagq(h, tt);
165*95c635efSGarrett D'Amore 		print_otag(h, TAG_BODY, 0, NULL);
166*95c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
167*95c635efSGarrett D'Amore 	} else
168*95c635efSGarrett D'Amore 		t = print_otag(h, TAG_DIV, 1, &tag);
169*95c635efSGarrett D'Amore 
170*95c635efSGarrett D'Amore 	print_man_nodelist(m, n, mh, h);
171*95c635efSGarrett D'Amore 	print_tagq(h, t);
172*95c635efSGarrett D'Amore }
173*95c635efSGarrett D'Amore 
174*95c635efSGarrett D'Amore 
175*95c635efSGarrett D'Amore /* ARGSUSED */
176*95c635efSGarrett D'Amore static void
177*95c635efSGarrett D'Amore print_man_head(MAN_ARGS)
178*95c635efSGarrett D'Amore {
179*95c635efSGarrett D'Amore 
180*95c635efSGarrett D'Amore 	print_gen_head(h);
181*95c635efSGarrett D'Amore 	assert(m->title);
182*95c635efSGarrett D'Amore 	assert(m->msec);
183*95c635efSGarrett D'Amore 	bufcat_fmt(h, "%s(%s)", m->title, m->msec);
184*95c635efSGarrett D'Amore 	print_otag(h, TAG_TITLE, 0, NULL);
185*95c635efSGarrett D'Amore 	print_text(h, h->buf);
186*95c635efSGarrett D'Amore }
187*95c635efSGarrett D'Amore 
188*95c635efSGarrett D'Amore 
189*95c635efSGarrett D'Amore static void
190*95c635efSGarrett D'Amore print_man_nodelist(MAN_ARGS)
191*95c635efSGarrett D'Amore {
192*95c635efSGarrett D'Amore 
193*95c635efSGarrett D'Amore 	print_man_node(m, n, mh, h);
194*95c635efSGarrett D'Amore 	if (n->next)
195*95c635efSGarrett D'Amore 		print_man_nodelist(m, n->next, mh, h);
196*95c635efSGarrett D'Amore }
197*95c635efSGarrett D'Amore 
198*95c635efSGarrett D'Amore 
199*95c635efSGarrett D'Amore static void
200*95c635efSGarrett D'Amore print_man_node(MAN_ARGS)
201*95c635efSGarrett D'Amore {
202*95c635efSGarrett D'Amore 	int		 child;
203*95c635efSGarrett D'Amore 	struct tag	*t;
204*95c635efSGarrett D'Amore 
205*95c635efSGarrett D'Amore 	child = 1;
206*95c635efSGarrett D'Amore 	t = h->tags.head;
207*95c635efSGarrett D'Amore 
208*95c635efSGarrett D'Amore 	switch (n->type) {
209*95c635efSGarrett D'Amore 	case (MAN_ROOT):
210*95c635efSGarrett D'Amore 		man_root_pre(m, n, mh, h);
211*95c635efSGarrett D'Amore 		break;
212*95c635efSGarrett D'Amore 	case (MAN_TEXT):
213*95c635efSGarrett D'Amore 		/*
214*95c635efSGarrett D'Amore 		 * If we have a blank line, output a vertical space.
215*95c635efSGarrett D'Amore 		 * If we have a space as the first character, break
216*95c635efSGarrett D'Amore 		 * before printing the line's data.
217*95c635efSGarrett D'Amore 		 */
218*95c635efSGarrett D'Amore 		if ('\0' == *n->string) {
219*95c635efSGarrett D'Amore 			print_otag(h, TAG_P, 0, NULL);
220*95c635efSGarrett D'Amore 			return;
221*95c635efSGarrett D'Amore 		}
222*95c635efSGarrett D'Amore 
223*95c635efSGarrett D'Amore 		if (' ' == *n->string && MAN_LINE & n->flags)
224*95c635efSGarrett D'Amore 			print_otag(h, TAG_BR, 0, NULL);
225*95c635efSGarrett D'Amore 		else if (MANH_LITERAL & mh->fl && n->prev)
226*95c635efSGarrett D'Amore 			print_otag(h, TAG_BR, 0, NULL);
227*95c635efSGarrett D'Amore 
228*95c635efSGarrett D'Amore 		print_text(h, n->string);
229*95c635efSGarrett D'Amore 		return;
230*95c635efSGarrett D'Amore 	case (MAN_EQN):
231*95c635efSGarrett D'Amore 		print_eqn(h, n->eqn);
232*95c635efSGarrett D'Amore 		break;
233*95c635efSGarrett D'Amore 	case (MAN_TBL):
234*95c635efSGarrett D'Amore 		/*
235*95c635efSGarrett D'Amore 		 * This will take care of initialising all of the table
236*95c635efSGarrett D'Amore 		 * state data for the first table, then tearing it down
237*95c635efSGarrett D'Amore 		 * for the last one.
238*95c635efSGarrett D'Amore 		 */
239*95c635efSGarrett D'Amore 		print_tbl(h, n->span);
240*95c635efSGarrett D'Amore 		return;
241*95c635efSGarrett D'Amore 	default:
242*95c635efSGarrett D'Amore 		/*
243*95c635efSGarrett D'Amore 		 * Close out scope of font prior to opening a macro
244*95c635efSGarrett D'Amore 		 * scope.
245*95c635efSGarrett D'Amore 		 */
246*95c635efSGarrett D'Amore 		if (HTMLFONT_NONE != h->metac) {
247*95c635efSGarrett D'Amore 			h->metal = h->metac;
248*95c635efSGarrett D'Amore 			h->metac = HTMLFONT_NONE;
249*95c635efSGarrett D'Amore 		}
250*95c635efSGarrett D'Amore 
251*95c635efSGarrett D'Amore 		/*
252*95c635efSGarrett D'Amore 		 * Close out the current table, if it's open, and unset
253*95c635efSGarrett D'Amore 		 * the "meta" table state.  This will be reopened on the
254*95c635efSGarrett D'Amore 		 * next table element.
255*95c635efSGarrett D'Amore 		 */
256*95c635efSGarrett D'Amore 		if (h->tblt) {
257*95c635efSGarrett D'Amore 			print_tblclose(h);
258*95c635efSGarrett D'Amore 			t = h->tags.head;
259*95c635efSGarrett D'Amore 		}
260*95c635efSGarrett D'Amore 		if (mans[n->tok].pre)
261*95c635efSGarrett D'Amore 			child = (*mans[n->tok].pre)(m, n, mh, h);
262*95c635efSGarrett D'Amore 		break;
263*95c635efSGarrett D'Amore 	}
264*95c635efSGarrett D'Amore 
265*95c635efSGarrett D'Amore 	if (child && n->child)
266*95c635efSGarrett D'Amore 		print_man_nodelist(m, n->child, mh, h);
267*95c635efSGarrett D'Amore 
268*95c635efSGarrett D'Amore 	/* This will automatically close out any font scope. */
269*95c635efSGarrett D'Amore 	print_stagq(h, t);
270*95c635efSGarrett D'Amore 
271*95c635efSGarrett D'Amore 	switch (n->type) {
272*95c635efSGarrett D'Amore 	case (MAN_ROOT):
273*95c635efSGarrett D'Amore 		man_root_post(m, n, mh, h);
274*95c635efSGarrett D'Amore 		break;
275*95c635efSGarrett D'Amore 	case (MAN_EQN):
276*95c635efSGarrett D'Amore 		break;
277*95c635efSGarrett D'Amore 	default:
278*95c635efSGarrett D'Amore 		if (mans[n->tok].post)
279*95c635efSGarrett D'Amore 			(*mans[n->tok].post)(m, n, mh, h);
280*95c635efSGarrett D'Amore 		break;
281*95c635efSGarrett D'Amore 	}
282*95c635efSGarrett D'Amore }
283*95c635efSGarrett D'Amore 
284*95c635efSGarrett D'Amore 
285*95c635efSGarrett D'Amore static int
286*95c635efSGarrett D'Amore a2width(const struct man_node *n, struct roffsu *su)
287*95c635efSGarrett D'Amore {
288*95c635efSGarrett D'Amore 
289*95c635efSGarrett D'Amore 	if (MAN_TEXT != n->type)
290*95c635efSGarrett D'Amore 		return(0);
291*95c635efSGarrett D'Amore 	if (a2roffsu(n->string, su, SCALE_BU))
292*95c635efSGarrett D'Amore 		return(1);
293*95c635efSGarrett D'Amore 
294*95c635efSGarrett D'Amore 	return(0);
295*95c635efSGarrett D'Amore }
296*95c635efSGarrett D'Amore 
297*95c635efSGarrett D'Amore 
298*95c635efSGarrett D'Amore /* ARGSUSED */
299*95c635efSGarrett D'Amore static void
300*95c635efSGarrett D'Amore man_root_pre(MAN_ARGS)
301*95c635efSGarrett D'Amore {
302*95c635efSGarrett D'Amore 	struct htmlpair	 tag[3];
303*95c635efSGarrett D'Amore 	struct tag	*t, *tt;
304*95c635efSGarrett D'Amore 	char		 b[BUFSIZ], title[BUFSIZ];
305*95c635efSGarrett D'Amore 
306*95c635efSGarrett D'Amore 	b[0] = 0;
307*95c635efSGarrett D'Amore 	if (m->vol)
308*95c635efSGarrett D'Amore 		(void)strlcat(b, m->vol, BUFSIZ);
309*95c635efSGarrett D'Amore 
310*95c635efSGarrett D'Amore 	assert(m->title);
311*95c635efSGarrett D'Amore 	assert(m->msec);
312*95c635efSGarrett D'Amore 	snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
313*95c635efSGarrett D'Amore 
314*95c635efSGarrett D'Amore 	PAIR_SUMMARY_INIT(&tag[0], "Document Header");
315*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[1], "head");
316*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
317*95c635efSGarrett D'Amore 	t = print_otag(h, TAG_TABLE, 3, tag);
318*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
319*95c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
320*95c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
321*95c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
322*95c635efSGarrett D'Amore 
323*95c635efSGarrett D'Amore 	print_otag(h, TAG_TBODY, 0, NULL);
324*95c635efSGarrett D'Amore 
325*95c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
326*95c635efSGarrett D'Amore 
327*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-ltitle");
328*95c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 1, tag);
329*95c635efSGarrett D'Amore 	print_text(h, title);
330*95c635efSGarrett D'Amore 	print_stagq(h, tt);
331*95c635efSGarrett D'Amore 
332*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-vol");
333*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
334*95c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
335*95c635efSGarrett D'Amore 	print_text(h, b);
336*95c635efSGarrett D'Amore 	print_stagq(h, tt);
337*95c635efSGarrett D'Amore 
338*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-rtitle");
339*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
340*95c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
341*95c635efSGarrett D'Amore 	print_text(h, title);
342*95c635efSGarrett D'Amore 	print_tagq(h, t);
343*95c635efSGarrett D'Amore }
344*95c635efSGarrett D'Amore 
345*95c635efSGarrett D'Amore 
346*95c635efSGarrett D'Amore /* ARGSUSED */
347*95c635efSGarrett D'Amore static void
348*95c635efSGarrett D'Amore man_root_post(MAN_ARGS)
349*95c635efSGarrett D'Amore {
350*95c635efSGarrett D'Amore 	struct htmlpair	 tag[3];
351*95c635efSGarrett D'Amore 	struct tag	*t, *tt;
352*95c635efSGarrett D'Amore 
353*95c635efSGarrett D'Amore 	PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
354*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[1], "foot");
355*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
356*95c635efSGarrett D'Amore 	t = print_otag(h, TAG_TABLE, 3, tag);
357*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
358*95c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
359*95c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
360*95c635efSGarrett D'Amore 
361*95c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
362*95c635efSGarrett D'Amore 
363*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "foot-date");
364*95c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 1, tag);
365*95c635efSGarrett D'Amore 
366*95c635efSGarrett D'Amore 	assert(m->date);
367*95c635efSGarrett D'Amore 	print_text(h, m->date);
368*95c635efSGarrett D'Amore 	print_stagq(h, tt);
369*95c635efSGarrett D'Amore 
370*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "foot-os");
371*95c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
372*95c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
373*95c635efSGarrett D'Amore 
374*95c635efSGarrett D'Amore 	if (m->source)
375*95c635efSGarrett D'Amore 		print_text(h, m->source);
376*95c635efSGarrett D'Amore 	print_tagq(h, t);
377*95c635efSGarrett D'Amore }
378*95c635efSGarrett D'Amore 
379*95c635efSGarrett D'Amore 
380*95c635efSGarrett D'Amore /* ARGSUSED */
381*95c635efSGarrett D'Amore static int
382*95c635efSGarrett D'Amore man_br_pre(MAN_ARGS)
383*95c635efSGarrett D'Amore {
384*95c635efSGarrett D'Amore 	struct roffsu	 su;
385*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
386*95c635efSGarrett D'Amore 
387*95c635efSGarrett D'Amore 	SCALE_VS_INIT(&su, 1);
388*95c635efSGarrett D'Amore 
389*95c635efSGarrett D'Amore 	if (MAN_sp == n->tok) {
390*95c635efSGarrett D'Amore 		if (NULL != (n = n->child))
391*95c635efSGarrett D'Amore 			if ( ! a2roffsu(n->string, &su, SCALE_VS))
392*95c635efSGarrett D'Amore 				SCALE_VS_INIT(&su, atoi(n->string));
393*95c635efSGarrett D'Amore 	} else
394*95c635efSGarrett D'Amore 		su.scale = 0;
395*95c635efSGarrett D'Amore 
396*95c635efSGarrett D'Amore 	bufinit(h);
397*95c635efSGarrett D'Amore 	bufcat_su(h, "height", &su);
398*95c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
399*95c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
400*95c635efSGarrett D'Amore 
401*95c635efSGarrett D'Amore 	/* So the div isn't empty: */
402*95c635efSGarrett D'Amore 	print_text(h, "\\~");
403*95c635efSGarrett D'Amore 
404*95c635efSGarrett D'Amore 	return(0);
405*95c635efSGarrett D'Amore }
406*95c635efSGarrett D'Amore 
407*95c635efSGarrett D'Amore /* ARGSUSED */
408*95c635efSGarrett D'Amore static int
409*95c635efSGarrett D'Amore man_SH_pre(MAN_ARGS)
410*95c635efSGarrett D'Amore {
411*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
412*95c635efSGarrett D'Amore 
413*95c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
414*95c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
415*95c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "section");
416*95c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
417*95c635efSGarrett D'Amore 		return(1);
418*95c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
419*95c635efSGarrett D'Amore 		return(1);
420*95c635efSGarrett D'Amore 
421*95c635efSGarrett D'Amore 	print_otag(h, TAG_H1, 0, NULL);
422*95c635efSGarrett D'Amore 	return(1);
423*95c635efSGarrett D'Amore }
424*95c635efSGarrett D'Amore 
425*95c635efSGarrett D'Amore /* ARGSUSED */
426*95c635efSGarrett D'Amore static int
427*95c635efSGarrett D'Amore man_alt_pre(MAN_ARGS)
428*95c635efSGarrett D'Amore {
429*95c635efSGarrett D'Amore 	const struct man_node	*nn;
430*95c635efSGarrett D'Amore 	int		 i, savelit;
431*95c635efSGarrett D'Amore 	enum htmltag	 fp;
432*95c635efSGarrett D'Amore 	struct tag	*t;
433*95c635efSGarrett D'Amore 
434*95c635efSGarrett D'Amore 	if ((savelit = mh->fl & MANH_LITERAL))
435*95c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
436*95c635efSGarrett D'Amore 
437*95c635efSGarrett D'Amore 	mh->fl &= ~MANH_LITERAL;
438*95c635efSGarrett D'Amore 
439*95c635efSGarrett D'Amore 	for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
440*95c635efSGarrett D'Amore 		t = NULL;
441*95c635efSGarrett D'Amore 		switch (n->tok) {
442*95c635efSGarrett D'Amore 		case (MAN_BI):
443*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_B;
444*95c635efSGarrett D'Amore 			break;
445*95c635efSGarrett D'Amore 		case (MAN_IB):
446*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_I;
447*95c635efSGarrett D'Amore 			break;
448*95c635efSGarrett D'Amore 		case (MAN_RI):
449*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_MAX;
450*95c635efSGarrett D'Amore 			break;
451*95c635efSGarrett D'Amore 		case (MAN_IR):
452*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_I;
453*95c635efSGarrett D'Amore 			break;
454*95c635efSGarrett D'Amore 		case (MAN_BR):
455*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_B;
456*95c635efSGarrett D'Amore 			break;
457*95c635efSGarrett D'Amore 		case (MAN_RB):
458*95c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_MAX;
459*95c635efSGarrett D'Amore 			break;
460*95c635efSGarrett D'Amore 		default:
461*95c635efSGarrett D'Amore 			abort();
462*95c635efSGarrett D'Amore 			/* NOTREACHED */
463*95c635efSGarrett D'Amore 		}
464*95c635efSGarrett D'Amore 
465*95c635efSGarrett D'Amore 		if (i)
466*95c635efSGarrett D'Amore 			h->flags |= HTML_NOSPACE;
467*95c635efSGarrett D'Amore 
468*95c635efSGarrett D'Amore 		if (TAG_MAX != fp)
469*95c635efSGarrett D'Amore 			t = print_otag(h, fp, 0, NULL);
470*95c635efSGarrett D'Amore 
471*95c635efSGarrett D'Amore 		print_man_node(m, nn, mh, h);
472*95c635efSGarrett D'Amore 
473*95c635efSGarrett D'Amore 		if (t)
474*95c635efSGarrett D'Amore 			print_tagq(h, t);
475*95c635efSGarrett D'Amore 	}
476*95c635efSGarrett D'Amore 
477*95c635efSGarrett D'Amore 	if (savelit)
478*95c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
479*95c635efSGarrett D'Amore 
480*95c635efSGarrett D'Amore 	return(0);
481*95c635efSGarrett D'Amore }
482*95c635efSGarrett D'Amore 
483*95c635efSGarrett D'Amore /* ARGSUSED */
484*95c635efSGarrett D'Amore static int
485*95c635efSGarrett D'Amore man_SM_pre(MAN_ARGS)
486*95c635efSGarrett D'Amore {
487*95c635efSGarrett D'Amore 
488*95c635efSGarrett D'Amore 	print_otag(h, TAG_SMALL, 0, NULL);
489*95c635efSGarrett D'Amore 	if (MAN_SB == n->tok)
490*95c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
491*95c635efSGarrett D'Amore 	return(1);
492*95c635efSGarrett D'Amore }
493*95c635efSGarrett D'Amore 
494*95c635efSGarrett D'Amore /* ARGSUSED */
495*95c635efSGarrett D'Amore static int
496*95c635efSGarrett D'Amore man_SS_pre(MAN_ARGS)
497*95c635efSGarrett D'Amore {
498*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
499*95c635efSGarrett D'Amore 
500*95c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
501*95c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
502*95c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "subsection");
503*95c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
504*95c635efSGarrett D'Amore 		return(1);
505*95c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
506*95c635efSGarrett D'Amore 		return(1);
507*95c635efSGarrett D'Amore 
508*95c635efSGarrett D'Amore 	print_otag(h, TAG_H2, 0, NULL);
509*95c635efSGarrett D'Amore 	return(1);
510*95c635efSGarrett D'Amore }
511*95c635efSGarrett D'Amore 
512*95c635efSGarrett D'Amore /* ARGSUSED */
513*95c635efSGarrett D'Amore static int
514*95c635efSGarrett D'Amore man_PP_pre(MAN_ARGS)
515*95c635efSGarrett D'Amore {
516*95c635efSGarrett D'Amore 
517*95c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
518*95c635efSGarrett D'Amore 		return(0);
519*95c635efSGarrett D'Amore 	else if (MAN_BLOCK == n->type)
520*95c635efSGarrett D'Amore 		print_bvspace(h, n);
521*95c635efSGarrett D'Amore 
522*95c635efSGarrett D'Amore 	return(1);
523*95c635efSGarrett D'Amore }
524*95c635efSGarrett D'Amore 
525*95c635efSGarrett D'Amore /* ARGSUSED */
526*95c635efSGarrett D'Amore static int
527*95c635efSGarrett D'Amore man_IP_pre(MAN_ARGS)
528*95c635efSGarrett D'Amore {
529*95c635efSGarrett D'Amore 	const struct man_node	*nn;
530*95c635efSGarrett D'Amore 
531*95c635efSGarrett D'Amore 	if (MAN_BODY == n->type) {
532*95c635efSGarrett D'Amore 		print_otag(h, TAG_DD, 0, NULL);
533*95c635efSGarrett D'Amore 		return(1);
534*95c635efSGarrett D'Amore 	} else if (MAN_HEAD != n->type) {
535*95c635efSGarrett D'Amore 		print_otag(h, TAG_DL, 0, NULL);
536*95c635efSGarrett D'Amore 		return(1);
537*95c635efSGarrett D'Amore 	}
538*95c635efSGarrett D'Amore 
539*95c635efSGarrett D'Amore 	/* FIXME: width specification. */
540*95c635efSGarrett D'Amore 
541*95c635efSGarrett D'Amore 	print_otag(h, TAG_DT, 0, NULL);
542*95c635efSGarrett D'Amore 
543*95c635efSGarrett D'Amore 	/* For IP, only print the first header element. */
544*95c635efSGarrett D'Amore 
545*95c635efSGarrett D'Amore 	if (MAN_IP == n->tok && n->child)
546*95c635efSGarrett D'Amore 		print_man_node(m, n->child, mh, h);
547*95c635efSGarrett D'Amore 
548*95c635efSGarrett D'Amore 	/* For TP, only print next-line header elements. */
549*95c635efSGarrett D'Amore 
550*95c635efSGarrett D'Amore 	if (MAN_TP == n->tok)
551*95c635efSGarrett D'Amore 		for (nn = n->child; nn; nn = nn->next)
552*95c635efSGarrett D'Amore 			if (nn->line > n->line)
553*95c635efSGarrett D'Amore 				print_man_node(m, nn, mh, h);
554*95c635efSGarrett D'Amore 
555*95c635efSGarrett D'Amore 	return(0);
556*95c635efSGarrett D'Amore }
557*95c635efSGarrett D'Amore 
558*95c635efSGarrett D'Amore /* ARGSUSED */
559*95c635efSGarrett D'Amore static int
560*95c635efSGarrett D'Amore man_HP_pre(MAN_ARGS)
561*95c635efSGarrett D'Amore {
562*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
563*95c635efSGarrett D'Amore 	struct roffsu	 su;
564*95c635efSGarrett D'Amore 	const struct man_node *np;
565*95c635efSGarrett D'Amore 
566*95c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
567*95c635efSGarrett D'Amore 		return(0);
568*95c635efSGarrett D'Amore 	else if (MAN_BLOCK != n->type)
569*95c635efSGarrett D'Amore 		return(1);
570*95c635efSGarrett D'Amore 
571*95c635efSGarrett D'Amore 	np = n->head->child;
572*95c635efSGarrett D'Amore 
573*95c635efSGarrett D'Amore 	if (NULL == np || ! a2width(np, &su))
574*95c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, INDENT);
575*95c635efSGarrett D'Amore 
576*95c635efSGarrett D'Amore 	bufinit(h);
577*95c635efSGarrett D'Amore 
578*95c635efSGarrett D'Amore 	print_bvspace(h, n);
579*95c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
580*95c635efSGarrett D'Amore 	su.scale = -su.scale;
581*95c635efSGarrett D'Amore 	bufcat_su(h, "text-indent", &su);
582*95c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
583*95c635efSGarrett D'Amore 	print_otag(h, TAG_P, 1, &tag);
584*95c635efSGarrett D'Amore 	return(1);
585*95c635efSGarrett D'Amore }
586*95c635efSGarrett D'Amore 
587*95c635efSGarrett D'Amore /* ARGSUSED */
588*95c635efSGarrett D'Amore static int
589*95c635efSGarrett D'Amore man_OP_pre(MAN_ARGS)
590*95c635efSGarrett D'Amore {
591*95c635efSGarrett D'Amore 	struct tag	*tt;
592*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
593*95c635efSGarrett D'Amore 
594*95c635efSGarrett D'Amore 	print_text(h, "[");
595*95c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
596*95c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "opt");
597*95c635efSGarrett D'Amore 	tt = print_otag(h, TAG_SPAN, 1, &tag);
598*95c635efSGarrett D'Amore 
599*95c635efSGarrett D'Amore 	if (NULL != (n = n->child)) {
600*95c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
601*95c635efSGarrett D'Amore 		print_text(h, n->string);
602*95c635efSGarrett D'Amore 	}
603*95c635efSGarrett D'Amore 
604*95c635efSGarrett D'Amore 	print_stagq(h, tt);
605*95c635efSGarrett D'Amore 
606*95c635efSGarrett D'Amore 	if (NULL != n && NULL != n->next) {
607*95c635efSGarrett D'Amore 		print_otag(h, TAG_I, 0, NULL);
608*95c635efSGarrett D'Amore 		print_text(h, n->next->string);
609*95c635efSGarrett D'Amore 	}
610*95c635efSGarrett D'Amore 
611*95c635efSGarrett D'Amore 	print_stagq(h, tt);
612*95c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
613*95c635efSGarrett D'Amore 	print_text(h, "]");
614*95c635efSGarrett D'Amore 	return(0);
615*95c635efSGarrett D'Amore }
616*95c635efSGarrett D'Amore 
617*95c635efSGarrett D'Amore 
618*95c635efSGarrett D'Amore /* ARGSUSED */
619*95c635efSGarrett D'Amore static int
620*95c635efSGarrett D'Amore man_B_pre(MAN_ARGS)
621*95c635efSGarrett D'Amore {
622*95c635efSGarrett D'Amore 
623*95c635efSGarrett D'Amore 	print_otag(h, TAG_B, 0, NULL);
624*95c635efSGarrett D'Amore 	return(1);
625*95c635efSGarrett D'Amore }
626*95c635efSGarrett D'Amore 
627*95c635efSGarrett D'Amore /* ARGSUSED */
628*95c635efSGarrett D'Amore static int
629*95c635efSGarrett D'Amore man_I_pre(MAN_ARGS)
630*95c635efSGarrett D'Amore {
631*95c635efSGarrett D'Amore 
632*95c635efSGarrett D'Amore 	print_otag(h, TAG_I, 0, NULL);
633*95c635efSGarrett D'Amore 	return(1);
634*95c635efSGarrett D'Amore }
635*95c635efSGarrett D'Amore 
636*95c635efSGarrett D'Amore /* ARGSUSED */
637*95c635efSGarrett D'Amore static int
638*95c635efSGarrett D'Amore man_literal_pre(MAN_ARGS)
639*95c635efSGarrett D'Amore {
640*95c635efSGarrett D'Amore 
641*95c635efSGarrett D'Amore 	if (MAN_nf != n->tok) {
642*95c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
643*95c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
644*95c635efSGarrett D'Amore 	} else
645*95c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
646*95c635efSGarrett D'Amore 
647*95c635efSGarrett D'Amore 	return(0);
648*95c635efSGarrett D'Amore }
649*95c635efSGarrett D'Amore 
650*95c635efSGarrett D'Amore /* ARGSUSED */
651*95c635efSGarrett D'Amore static int
652*95c635efSGarrett D'Amore man_in_pre(MAN_ARGS)
653*95c635efSGarrett D'Amore {
654*95c635efSGarrett D'Amore 
655*95c635efSGarrett D'Amore 	print_otag(h, TAG_BR, 0, NULL);
656*95c635efSGarrett D'Amore 	return(0);
657*95c635efSGarrett D'Amore }
658*95c635efSGarrett D'Amore 
659*95c635efSGarrett D'Amore /* ARGSUSED */
660*95c635efSGarrett D'Amore static int
661*95c635efSGarrett D'Amore man_ign_pre(MAN_ARGS)
662*95c635efSGarrett D'Amore {
663*95c635efSGarrett D'Amore 
664*95c635efSGarrett D'Amore 	return(0);
665*95c635efSGarrett D'Amore }
666*95c635efSGarrett D'Amore 
667*95c635efSGarrett D'Amore /* ARGSUSED */
668*95c635efSGarrett D'Amore static int
669*95c635efSGarrett D'Amore man_RS_pre(MAN_ARGS)
670*95c635efSGarrett D'Amore {
671*95c635efSGarrett D'Amore 	struct htmlpair	 tag;
672*95c635efSGarrett D'Amore 	struct roffsu	 su;
673*95c635efSGarrett D'Amore 
674*95c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
675*95c635efSGarrett D'Amore 		return(0);
676*95c635efSGarrett D'Amore 	else if (MAN_BODY == n->type)
677*95c635efSGarrett D'Amore 		return(1);
678*95c635efSGarrett D'Amore 
679*95c635efSGarrett D'Amore 	SCALE_HS_INIT(&su, INDENT);
680*95c635efSGarrett D'Amore 	if (n->head->child)
681*95c635efSGarrett D'Amore 		a2width(n->head->child, &su);
682*95c635efSGarrett D'Amore 
683*95c635efSGarrett D'Amore 	bufinit(h);
684*95c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
685*95c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
686*95c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
687*95c635efSGarrett D'Amore 	return(1);
688*95c635efSGarrett D'Amore }
689