1241675Suqs/*	$Id: mdoc_html.c,v 1.182 2011/11/03 20:37:00 schwarze Exp $ */
2241675Suqs/*
3241675Suqs * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4241675Suqs *
5241675Suqs * Permission to use, copy, modify, and distribute this software for any
6241675Suqs * purpose with or without fee is hereby granted, provided that the above
7241675Suqs * copyright notice and this permission notice appear in all copies.
8241675Suqs *
9241675Suqs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11241675Suqs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16241675Suqs */
17241675Suqs#ifdef HAVE_CONFIG_H
18241675Suqs#include "config.h"
19241675Suqs#endif
20241675Suqs
21241675Suqs#include <sys/types.h>
22241675Suqs
23241675Suqs#include <assert.h>
24241675Suqs#include <ctype.h>
25241675Suqs#include <stdio.h>
26241675Suqs#include <stdlib.h>
27241675Suqs#include <string.h>
28241675Suqs#include <unistd.h>
29241675Suqs
30241675Suqs#include "mandoc.h"
31241675Suqs#include "out.h"
32241675Suqs#include "html.h"
33241675Suqs#include "mdoc.h"
34241675Suqs#include "main.h"
35241675Suqs
36241675Suqs#define	INDENT		 5
37241675Suqs
38241675Suqs#define	MDOC_ARGS	  const struct mdoc_meta *m, \
39241675Suqs			  const struct mdoc_node *n, \
40241675Suqs			  struct html *h
41241675Suqs
42241675Suqs#ifndef MIN
43241675Suqs#define	MIN(a,b)	((/*CONSTCOND*/(a)<(b))?(a):(b))
44241675Suqs#endif
45241675Suqs
46241675Suqsstruct	htmlmdoc {
47241675Suqs	int		(*pre)(MDOC_ARGS);
48241675Suqs	void		(*post)(MDOC_ARGS);
49241675Suqs};
50241675Suqs
51241675Suqsstatic	void		  print_mdoc(MDOC_ARGS);
52241675Suqsstatic	void		  print_mdoc_head(MDOC_ARGS);
53241675Suqsstatic	void		  print_mdoc_node(MDOC_ARGS);
54241675Suqsstatic	void		  print_mdoc_nodelist(MDOC_ARGS);
55241675Suqsstatic	void	  	  synopsis_pre(struct html *,
56241675Suqs				const struct mdoc_node *);
57241675Suqs
58241675Suqsstatic	void		  a2width(const char *, struct roffsu *);
59241675Suqsstatic	void		  a2offs(const char *, struct roffsu *);
60241675Suqs
61241675Suqsstatic	void		  mdoc_root_post(MDOC_ARGS);
62241675Suqsstatic	int		  mdoc_root_pre(MDOC_ARGS);
63241675Suqs
64241675Suqsstatic	void		  mdoc__x_post(MDOC_ARGS);
65241675Suqsstatic	int		  mdoc__x_pre(MDOC_ARGS);
66241675Suqsstatic	int		  mdoc_ad_pre(MDOC_ARGS);
67241675Suqsstatic	int		  mdoc_an_pre(MDOC_ARGS);
68241675Suqsstatic	int		  mdoc_ap_pre(MDOC_ARGS);
69241675Suqsstatic	int		  mdoc_ar_pre(MDOC_ARGS);
70241675Suqsstatic	int		  mdoc_bd_pre(MDOC_ARGS);
71241675Suqsstatic	int		  mdoc_bf_pre(MDOC_ARGS);
72241675Suqsstatic	void		  mdoc_bk_post(MDOC_ARGS);
73241675Suqsstatic	int		  mdoc_bk_pre(MDOC_ARGS);
74241675Suqsstatic	int		  mdoc_bl_pre(MDOC_ARGS);
75241675Suqsstatic	int		  mdoc_bt_pre(MDOC_ARGS);
76241675Suqsstatic	int		  mdoc_bx_pre(MDOC_ARGS);
77241675Suqsstatic	int		  mdoc_cd_pre(MDOC_ARGS);
78241675Suqsstatic	int		  mdoc_d1_pre(MDOC_ARGS);
79241675Suqsstatic	int		  mdoc_dv_pre(MDOC_ARGS);
80241675Suqsstatic	int		  mdoc_fa_pre(MDOC_ARGS);
81241675Suqsstatic	int		  mdoc_fd_pre(MDOC_ARGS);
82241675Suqsstatic	int		  mdoc_fl_pre(MDOC_ARGS);
83241675Suqsstatic	int		  mdoc_fn_pre(MDOC_ARGS);
84241675Suqsstatic	int		  mdoc_ft_pre(MDOC_ARGS);
85241675Suqsstatic	int		  mdoc_em_pre(MDOC_ARGS);
86241675Suqsstatic	int		  mdoc_er_pre(MDOC_ARGS);
87241675Suqsstatic	int		  mdoc_ev_pre(MDOC_ARGS);
88241675Suqsstatic	int		  mdoc_ex_pre(MDOC_ARGS);
89241675Suqsstatic	void		  mdoc_fo_post(MDOC_ARGS);
90241675Suqsstatic	int		  mdoc_fo_pre(MDOC_ARGS);
91241675Suqsstatic	int		  mdoc_ic_pre(MDOC_ARGS);
92241675Suqsstatic	int		  mdoc_igndelim_pre(MDOC_ARGS);
93241675Suqsstatic	int		  mdoc_in_pre(MDOC_ARGS);
94241675Suqsstatic	int		  mdoc_it_pre(MDOC_ARGS);
95241675Suqsstatic	int		  mdoc_lb_pre(MDOC_ARGS);
96241675Suqsstatic	int		  mdoc_li_pre(MDOC_ARGS);
97241675Suqsstatic	int		  mdoc_lk_pre(MDOC_ARGS);
98241675Suqsstatic	int		  mdoc_mt_pre(MDOC_ARGS);
99241675Suqsstatic	int		  mdoc_ms_pre(MDOC_ARGS);
100241675Suqsstatic	int		  mdoc_nd_pre(MDOC_ARGS);
101241675Suqsstatic	int		  mdoc_nm_pre(MDOC_ARGS);
102241675Suqsstatic	int		  mdoc_ns_pre(MDOC_ARGS);
103241675Suqsstatic	int		  mdoc_pa_pre(MDOC_ARGS);
104241675Suqsstatic	void		  mdoc_pf_post(MDOC_ARGS);
105241675Suqsstatic	int		  mdoc_pp_pre(MDOC_ARGS);
106241675Suqsstatic	void		  mdoc_quote_post(MDOC_ARGS);
107241675Suqsstatic	int		  mdoc_quote_pre(MDOC_ARGS);
108241675Suqsstatic	int		  mdoc_rs_pre(MDOC_ARGS);
109241675Suqsstatic	int		  mdoc_rv_pre(MDOC_ARGS);
110241675Suqsstatic	int		  mdoc_sh_pre(MDOC_ARGS);
111241675Suqsstatic	int		  mdoc_sm_pre(MDOC_ARGS);
112241675Suqsstatic	int		  mdoc_sp_pre(MDOC_ARGS);
113241675Suqsstatic	int		  mdoc_ss_pre(MDOC_ARGS);
114241675Suqsstatic	int		  mdoc_sx_pre(MDOC_ARGS);
115241675Suqsstatic	int		  mdoc_sy_pre(MDOC_ARGS);
116241675Suqsstatic	int		  mdoc_ud_pre(MDOC_ARGS);
117241675Suqsstatic	int		  mdoc_va_pre(MDOC_ARGS);
118241675Suqsstatic	int		  mdoc_vt_pre(MDOC_ARGS);
119241675Suqsstatic	int		  mdoc_xr_pre(MDOC_ARGS);
120241675Suqsstatic	int		  mdoc_xx_pre(MDOC_ARGS);
121241675Suqs
122241675Suqsstatic	const struct htmlmdoc mdocs[MDOC_MAX] = {
123241675Suqs	{mdoc_ap_pre, NULL}, /* Ap */
124241675Suqs	{NULL, NULL}, /* Dd */
125241675Suqs	{NULL, NULL}, /* Dt */
126241675Suqs	{NULL, NULL}, /* Os */
127241675Suqs	{mdoc_sh_pre, NULL }, /* Sh */
128241675Suqs	{mdoc_ss_pre, NULL }, /* Ss */
129241675Suqs	{mdoc_pp_pre, NULL}, /* Pp */
130241675Suqs	{mdoc_d1_pre, NULL}, /* D1 */
131241675Suqs	{mdoc_d1_pre, NULL}, /* Dl */
132241675Suqs	{mdoc_bd_pre, NULL}, /* Bd */
133241675Suqs	{NULL, NULL}, /* Ed */
134241675Suqs	{mdoc_bl_pre, NULL}, /* Bl */
135241675Suqs	{NULL, NULL}, /* El */
136241675Suqs	{mdoc_it_pre, NULL}, /* It */
137241675Suqs	{mdoc_ad_pre, NULL}, /* Ad */
138241675Suqs	{mdoc_an_pre, NULL}, /* An */
139241675Suqs	{mdoc_ar_pre, NULL}, /* Ar */
140241675Suqs	{mdoc_cd_pre, NULL}, /* Cd */
141241675Suqs	{mdoc_fl_pre, NULL}, /* Cm */
142241675Suqs	{mdoc_dv_pre, NULL}, /* Dv */
143241675Suqs	{mdoc_er_pre, NULL}, /* Er */
144241675Suqs	{mdoc_ev_pre, NULL}, /* Ev */
145241675Suqs	{mdoc_ex_pre, NULL}, /* Ex */
146241675Suqs	{mdoc_fa_pre, NULL}, /* Fa */
147241675Suqs	{mdoc_fd_pre, NULL}, /* Fd */
148241675Suqs	{mdoc_fl_pre, NULL}, /* Fl */
149241675Suqs	{mdoc_fn_pre, NULL}, /* Fn */
150241675Suqs	{mdoc_ft_pre, NULL}, /* Ft */
151241675Suqs	{mdoc_ic_pre, NULL}, /* Ic */
152241675Suqs	{mdoc_in_pre, NULL}, /* In */
153241675Suqs	{mdoc_li_pre, NULL}, /* Li */
154241675Suqs	{mdoc_nd_pre, NULL}, /* Nd */
155241675Suqs	{mdoc_nm_pre, NULL}, /* Nm */
156241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Op */
157241675Suqs	{NULL, NULL}, /* Ot */
158241675Suqs	{mdoc_pa_pre, NULL}, /* Pa */
159241675Suqs	{mdoc_rv_pre, NULL}, /* Rv */
160241675Suqs	{NULL, NULL}, /* St */
161241675Suqs	{mdoc_va_pre, NULL}, /* Va */
162241675Suqs	{mdoc_vt_pre, NULL}, /* Vt */
163241675Suqs	{mdoc_xr_pre, NULL}, /* Xr */
164241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %A */
165241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %B */
166241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %D */
167241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %I */
168241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %J */
169241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %N */
170241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %O */
171241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %P */
172241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %R */
173241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %T */
174241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %V */
175241675Suqs	{NULL, NULL}, /* Ac */
176241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Ao */
177241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Aq */
178241675Suqs	{NULL, NULL}, /* At */
179241675Suqs	{NULL, NULL}, /* Bc */
180241675Suqs	{mdoc_bf_pre, NULL}, /* Bf */
181241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Bo */
182241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Bq */
183241675Suqs	{mdoc_xx_pre, NULL}, /* Bsx */
184241675Suqs	{mdoc_bx_pre, NULL}, /* Bx */
185241675Suqs	{NULL, NULL}, /* Db */
186241675Suqs	{NULL, NULL}, /* Dc */
187241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Do */
188241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Dq */
189241675Suqs	{NULL, NULL}, /* Ec */ /* FIXME: no space */
190241675Suqs	{NULL, NULL}, /* Ef */
191241675Suqs	{mdoc_em_pre, NULL}, /* Em */
192241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Eo */
193241675Suqs	{mdoc_xx_pre, NULL}, /* Fx */
194241675Suqs	{mdoc_ms_pre, NULL}, /* Ms */
195241675Suqs	{mdoc_igndelim_pre, NULL}, /* No */
196241675Suqs	{mdoc_ns_pre, NULL}, /* Ns */
197241675Suqs	{mdoc_xx_pre, NULL}, /* Nx */
198241675Suqs	{mdoc_xx_pre, NULL}, /* Ox */
199241675Suqs	{NULL, NULL}, /* Pc */
200241675Suqs	{mdoc_igndelim_pre, mdoc_pf_post}, /* Pf */
201241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Po */
202241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Pq */
203241675Suqs	{NULL, NULL}, /* Qc */
204241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Ql */
205241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Qo */
206241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Qq */
207241675Suqs	{NULL, NULL}, /* Re */
208241675Suqs	{mdoc_rs_pre, NULL}, /* Rs */
209241675Suqs	{NULL, NULL}, /* Sc */
210241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* So */
211241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Sq */
212241675Suqs	{mdoc_sm_pre, NULL}, /* Sm */
213241675Suqs	{mdoc_sx_pre, NULL}, /* Sx */
214241675Suqs	{mdoc_sy_pre, NULL}, /* Sy */
215241675Suqs	{NULL, NULL}, /* Tn */
216241675Suqs	{mdoc_xx_pre, NULL}, /* Ux */
217241675Suqs	{NULL, NULL}, /* Xc */
218241675Suqs	{NULL, NULL}, /* Xo */
219241675Suqs	{mdoc_fo_pre, mdoc_fo_post}, /* Fo */
220241675Suqs	{NULL, NULL}, /* Fc */
221241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Oo */
222241675Suqs	{NULL, NULL}, /* Oc */
223241675Suqs	{mdoc_bk_pre, mdoc_bk_post}, /* Bk */
224241675Suqs	{NULL, NULL}, /* Ek */
225241675Suqs	{mdoc_bt_pre, NULL}, /* Bt */
226241675Suqs	{NULL, NULL}, /* Hf */
227241675Suqs	{NULL, NULL}, /* Fr */
228241675Suqs	{mdoc_ud_pre, NULL}, /* Ud */
229241675Suqs	{mdoc_lb_pre, NULL}, /* Lb */
230241675Suqs	{mdoc_pp_pre, NULL}, /* Lp */
231241675Suqs	{mdoc_lk_pre, NULL}, /* Lk */
232241675Suqs	{mdoc_mt_pre, NULL}, /* Mt */
233241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Brq */
234241675Suqs	{mdoc_quote_pre, mdoc_quote_post}, /* Bro */
235241675Suqs	{NULL, NULL}, /* Brc */
236241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %C */
237241675Suqs	{NULL, NULL}, /* Es */  /* TODO */
238241675Suqs	{NULL, NULL}, /* En */  /* TODO */
239241675Suqs	{mdoc_xx_pre, NULL}, /* Dx */
240241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %Q */
241241675Suqs	{mdoc_sp_pre, NULL}, /* br */
242241675Suqs	{mdoc_sp_pre, NULL}, /* sp */
243241675Suqs	{mdoc__x_pre, mdoc__x_post}, /* %U */
244241675Suqs	{NULL, NULL}, /* Ta */
245241675Suqs};
246241675Suqs
247241675Suqsstatic	const char * const lists[LIST_MAX] = {
248241675Suqs	NULL,
249241675Suqs	"list-bul",
250241675Suqs	"list-col",
251241675Suqs	"list-dash",
252241675Suqs	"list-diag",
253241675Suqs	"list-enum",
254241675Suqs	"list-hang",
255241675Suqs	"list-hyph",
256241675Suqs	"list-inset",
257241675Suqs	"list-item",
258241675Suqs	"list-ohang",
259241675Suqs	"list-tag"
260241675Suqs};
261241675Suqs
262241675Suqsvoid
263241675Suqshtml_mdoc(void *arg, const struct mdoc *m)
264241675Suqs{
265241675Suqs
266241675Suqs	print_mdoc(mdoc_meta(m), mdoc_node(m), (struct html *)arg);
267241675Suqs	putchar('\n');
268241675Suqs}
269241675Suqs
270241675Suqs
271241675Suqs/*
272241675Suqs * Calculate the scaling unit passed in a `-width' argument.  This uses
273241675Suqs * either a native scaling unit (e.g., 1i, 2m) or the string length of
274241675Suqs * the value.
275241675Suqs */
276241675Suqsstatic void
277241675Suqsa2width(const char *p, struct roffsu *su)
278241675Suqs{
279241675Suqs
280241675Suqs	if ( ! a2roffsu(p, su, SCALE_MAX)) {
281241675Suqs		su->unit = SCALE_BU;
282241675Suqs		su->scale = html_strlen(p);
283241675Suqs	}
284241675Suqs}
285241675Suqs
286241675Suqs
287241675Suqs/*
288241675Suqs * See the same function in mdoc_term.c for documentation.
289241675Suqs */
290241675Suqsstatic void
291241675Suqssynopsis_pre(struct html *h, const struct mdoc_node *n)
292241675Suqs{
293241675Suqs
294241675Suqs	if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
295241675Suqs		return;
296241675Suqs
297241675Suqs	if (n->prev->tok == n->tok &&
298241675Suqs			MDOC_Fo != n->tok &&
299241675Suqs			MDOC_Ft != n->tok &&
300241675Suqs			MDOC_Fn != n->tok) {
301241675Suqs		print_otag(h, TAG_BR, 0, NULL);
302241675Suqs		return;
303241675Suqs	}
304241675Suqs
305241675Suqs	switch (n->prev->tok) {
306241675Suqs	case (MDOC_Fd):
307241675Suqs		/* FALLTHROUGH */
308241675Suqs	case (MDOC_Fn):
309241675Suqs		/* FALLTHROUGH */
310241675Suqs	case (MDOC_Fo):
311241675Suqs		/* FALLTHROUGH */
312241675Suqs	case (MDOC_In):
313241675Suqs		/* FALLTHROUGH */
314241675Suqs	case (MDOC_Vt):
315241675Suqs		print_otag(h, TAG_P, 0, NULL);
316241675Suqs		break;
317241675Suqs	case (MDOC_Ft):
318241675Suqs		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
319241675Suqs			print_otag(h, TAG_P, 0, NULL);
320241675Suqs			break;
321241675Suqs		}
322241675Suqs		/* FALLTHROUGH */
323241675Suqs	default:
324241675Suqs		print_otag(h, TAG_BR, 0, NULL);
325241675Suqs		break;
326241675Suqs	}
327241675Suqs}
328241675Suqs
329241675Suqs
330241675Suqs/*
331241675Suqs * Calculate the scaling unit passed in an `-offset' argument.  This
332241675Suqs * uses either a native scaling unit (e.g., 1i, 2m), one of a set of
333241675Suqs * predefined strings (indent, etc.), or the string length of the value.
334241675Suqs */
335241675Suqsstatic void
336241675Suqsa2offs(const char *p, struct roffsu *su)
337241675Suqs{
338241675Suqs
339241675Suqs	/* FIXME: "right"? */
340241675Suqs
341241675Suqs	if (0 == strcmp(p, "left"))
342241675Suqs		SCALE_HS_INIT(su, 0);
343241675Suqs	else if (0 == strcmp(p, "indent"))
344241675Suqs		SCALE_HS_INIT(su, INDENT);
345241675Suqs	else if (0 == strcmp(p, "indent-two"))
346241675Suqs		SCALE_HS_INIT(su, INDENT * 2);
347241675Suqs	else if ( ! a2roffsu(p, su, SCALE_MAX))
348241675Suqs		SCALE_HS_INIT(su, html_strlen(p));
349241675Suqs}
350241675Suqs
351241675Suqs
352241675Suqsstatic void
353241675Suqsprint_mdoc(MDOC_ARGS)
354241675Suqs{
355241675Suqs	struct tag	*t, *tt;
356241675Suqs	struct htmlpair	 tag;
357241675Suqs
358241675Suqs	PAIR_CLASS_INIT(&tag, "mandoc");
359241675Suqs
360241675Suqs	if ( ! (HTML_FRAGMENT & h->oflags)) {
361241675Suqs		print_gen_decls(h);
362241675Suqs		t = print_otag(h, TAG_HTML, 0, NULL);
363241675Suqs		tt = print_otag(h, TAG_HEAD, 0, NULL);
364241675Suqs		print_mdoc_head(m, n, h);
365241675Suqs		print_tagq(h, tt);
366241675Suqs		print_otag(h, TAG_BODY, 0, NULL);
367241675Suqs		print_otag(h, TAG_DIV, 1, &tag);
368241675Suqs	} else
369241675Suqs		t = print_otag(h, TAG_DIV, 1, &tag);
370241675Suqs
371241675Suqs	print_mdoc_nodelist(m, n, h);
372241675Suqs	print_tagq(h, t);
373241675Suqs}
374241675Suqs
375241675Suqs
376241675Suqs/* ARGSUSED */
377241675Suqsstatic void
378241675Suqsprint_mdoc_head(MDOC_ARGS)
379241675Suqs{
380241675Suqs
381241675Suqs	print_gen_head(h);
382241675Suqs	bufinit(h);
383241675Suqs	bufcat_fmt(h, "%s(%s)", m->title, m->msec);
384241675Suqs
385241675Suqs	if (m->arch)
386241675Suqs		bufcat_fmt(h, " (%s)", m->arch);
387241675Suqs
388241675Suqs	print_otag(h, TAG_TITLE, 0, NULL);
389241675Suqs	print_text(h, h->buf);
390241675Suqs}
391241675Suqs
392241675Suqs
393241675Suqsstatic void
394241675Suqsprint_mdoc_nodelist(MDOC_ARGS)
395241675Suqs{
396241675Suqs
397241675Suqs	print_mdoc_node(m, n, h);
398241675Suqs	if (n->next)
399241675Suqs		print_mdoc_nodelist(m, n->next, h);
400241675Suqs}
401241675Suqs
402241675Suqs
403241675Suqsstatic void
404241675Suqsprint_mdoc_node(MDOC_ARGS)
405241675Suqs{
406241675Suqs	int		 child;
407241675Suqs	struct tag	*t;
408241675Suqs
409241675Suqs	child = 1;
410241675Suqs	t = h->tags.head;
411241675Suqs
412241675Suqs	switch (n->type) {
413241675Suqs	case (MDOC_ROOT):
414241675Suqs		child = mdoc_root_pre(m, n, h);
415241675Suqs		break;
416241675Suqs	case (MDOC_TEXT):
417241675Suqs		/* No tables in this mode... */
418241675Suqs		assert(NULL == h->tblt);
419241675Suqs
420241675Suqs		/*
421241675Suqs		 * Make sure that if we're in a literal mode already
422241675Suqs		 * (i.e., within a <PRE>) don't print the newline.
423241675Suqs		 */
424241675Suqs		if (' ' == *n->string && MDOC_LINE & n->flags)
425241675Suqs			if ( ! (HTML_LITERAL & h->flags))
426241675Suqs				print_otag(h, TAG_BR, 0, NULL);
427241675Suqs		if (MDOC_DELIMC & n->flags)
428241675Suqs			h->flags |= HTML_NOSPACE;
429241675Suqs		print_text(h, n->string);
430241675Suqs		if (MDOC_DELIMO & n->flags)
431241675Suqs			h->flags |= HTML_NOSPACE;
432241675Suqs		return;
433241675Suqs	case (MDOC_EQN):
434241675Suqs		print_eqn(h, n->eqn);
435241675Suqs		break;
436241675Suqs	case (MDOC_TBL):
437241675Suqs		/*
438241675Suqs		 * This will take care of initialising all of the table
439241675Suqs		 * state data for the first table, then tearing it down
440241675Suqs		 * for the last one.
441241675Suqs		 */
442241675Suqs		print_tbl(h, n->span);
443241675Suqs		return;
444241675Suqs	default:
445241675Suqs		/*
446241675Suqs		 * Close out the current table, if it's open, and unset
447241675Suqs		 * the "meta" table state.  This will be reopened on the
448241675Suqs		 * next table element.
449241675Suqs		 */
450241675Suqs		if (h->tblt) {
451241675Suqs			print_tblclose(h);
452241675Suqs			t = h->tags.head;
453241675Suqs		}
454241675Suqs
455241675Suqs		assert(NULL == h->tblt);
456241675Suqs		if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
457241675Suqs			child = (*mdocs[n->tok].pre)(m, n, h);
458241675Suqs		break;
459241675Suqs	}
460241675Suqs
461241675Suqs	if (HTML_KEEP & h->flags) {
462241675Suqs		if (n->prev && n->prev->line != n->line) {
463241675Suqs			h->flags &= ~HTML_KEEP;
464241675Suqs			h->flags |= HTML_PREKEEP;
465241675Suqs		} else if (NULL == n->prev) {
466241675Suqs			if (n->parent && n->parent->line != n->line) {
467241675Suqs				h->flags &= ~HTML_KEEP;
468241675Suqs				h->flags |= HTML_PREKEEP;
469241675Suqs			}
470241675Suqs		}
471241675Suqs	}
472241675Suqs
473241675Suqs	if (child && n->child)
474241675Suqs		print_mdoc_nodelist(m, n->child, h);
475241675Suqs
476241675Suqs	print_stagq(h, t);
477241675Suqs
478241675Suqs	switch (n->type) {
479241675Suqs	case (MDOC_ROOT):
480241675Suqs		mdoc_root_post(m, n, h);
481241675Suqs		break;
482241675Suqs	case (MDOC_EQN):
483241675Suqs		break;
484241675Suqs	default:
485241675Suqs		if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
486241675Suqs			(*mdocs[n->tok].post)(m, n, h);
487241675Suqs		break;
488241675Suqs	}
489241675Suqs}
490241675Suqs
491241675Suqs/* ARGSUSED */
492241675Suqsstatic void
493241675Suqsmdoc_root_post(MDOC_ARGS)
494241675Suqs{
495241675Suqs	struct htmlpair	 tag[3];
496241675Suqs	struct tag	*t, *tt;
497241675Suqs
498241675Suqs	PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
499241675Suqs	PAIR_CLASS_INIT(&tag[1], "foot");
500241675Suqs	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
501241675Suqs	t = print_otag(h, TAG_TABLE, 3, tag);
502241675Suqs	PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
503241675Suqs	print_otag(h, TAG_COL, 1, tag);
504241675Suqs	print_otag(h, TAG_COL, 1, tag);
505241675Suqs
506241675Suqs	print_otag(h, TAG_TBODY, 0, NULL);
507241675Suqs
508241675Suqs	tt = print_otag(h, TAG_TR, 0, NULL);
509241675Suqs
510241675Suqs	PAIR_CLASS_INIT(&tag[0], "foot-date");
511241675Suqs	print_otag(h, TAG_TD, 1, tag);
512241675Suqs	print_text(h, m->date);
513241675Suqs	print_stagq(h, tt);
514241675Suqs
515241675Suqs	PAIR_CLASS_INIT(&tag[0], "foot-os");
516241675Suqs	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
517241675Suqs	print_otag(h, TAG_TD, 2, tag);
518241675Suqs	print_text(h, m->os);
519241675Suqs	print_tagq(h, t);
520241675Suqs}
521241675Suqs
522241675Suqs
523241675Suqs/* ARGSUSED */
524241675Suqsstatic int
525241675Suqsmdoc_root_pre(MDOC_ARGS)
526241675Suqs{
527241675Suqs	struct htmlpair	 tag[3];
528241675Suqs	struct tag	*t, *tt;
529241675Suqs	char		 b[BUFSIZ], title[BUFSIZ];
530241675Suqs
531241675Suqs	strlcpy(b, m->vol, BUFSIZ);
532241675Suqs
533241675Suqs	if (m->arch) {
534241675Suqs		strlcat(b, " (", BUFSIZ);
535241675Suqs		strlcat(b, m->arch, BUFSIZ);
536241675Suqs		strlcat(b, ")", BUFSIZ);
537241675Suqs	}
538241675Suqs
539241675Suqs	snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
540241675Suqs
541241675Suqs	PAIR_SUMMARY_INIT(&tag[0], "Document Header");
542241675Suqs	PAIR_CLASS_INIT(&tag[1], "head");
543241675Suqs	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
544241675Suqs	t = print_otag(h, TAG_TABLE, 3, tag);
545241675Suqs	PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
546241675Suqs	print_otag(h, TAG_COL, 1, tag);
547241675Suqs	print_otag(h, TAG_COL, 1, tag);
548241675Suqs	print_otag(h, TAG_COL, 1, tag);
549241675Suqs
550241675Suqs	print_otag(h, TAG_TBODY, 0, NULL);
551241675Suqs
552241675Suqs	tt = print_otag(h, TAG_TR, 0, NULL);
553241675Suqs
554241675Suqs	PAIR_CLASS_INIT(&tag[0], "head-ltitle");
555241675Suqs	print_otag(h, TAG_TD, 1, tag);
556241675Suqs	print_text(h, title);
557241675Suqs	print_stagq(h, tt);
558241675Suqs
559241675Suqs	PAIR_CLASS_INIT(&tag[0], "head-vol");
560241675Suqs	PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
561241675Suqs	print_otag(h, TAG_TD, 2, tag);
562241675Suqs	print_text(h, b);
563241675Suqs	print_stagq(h, tt);
564241675Suqs
565241675Suqs	PAIR_CLASS_INIT(&tag[0], "head-rtitle");
566241675Suqs	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
567241675Suqs	print_otag(h, TAG_TD, 2, tag);
568241675Suqs	print_text(h, title);
569241675Suqs	print_tagq(h, t);
570241675Suqs	return(1);
571241675Suqs}
572241675Suqs
573241675Suqs
574241675Suqs/* ARGSUSED */
575241675Suqsstatic int
576241675Suqsmdoc_sh_pre(MDOC_ARGS)
577241675Suqs{
578241675Suqs	struct htmlpair	 tag;
579241675Suqs
580241675Suqs	if (MDOC_BLOCK == n->type) {
581241675Suqs		PAIR_CLASS_INIT(&tag, "section");
582241675Suqs		print_otag(h, TAG_DIV, 1, &tag);
583241675Suqs		return(1);
584241675Suqs	} else if (MDOC_BODY == n->type)
585241675Suqs		return(1);
586241675Suqs
587241675Suqs	bufinit(h);
588241675Suqs	bufcat(h, "x");
589241675Suqs
590241675Suqs	for (n = n->child; n && MDOC_TEXT == n->type; ) {
591241675Suqs		bufcat_id(h, n->string);
592241675Suqs		if (NULL != (n = n->next))
593241675Suqs			bufcat_id(h, " ");
594241675Suqs	}
595241675Suqs
596241675Suqs	if (NULL == n) {
597241675Suqs		PAIR_ID_INIT(&tag, h->buf);
598241675Suqs		print_otag(h, TAG_H1, 1, &tag);
599241675Suqs	} else
600241675Suqs		print_otag(h, TAG_H1, 0, NULL);
601241675Suqs
602241675Suqs	return(1);
603241675Suqs}
604241675Suqs
605241675Suqs/* ARGSUSED */
606241675Suqsstatic int
607241675Suqsmdoc_ss_pre(MDOC_ARGS)
608241675Suqs{
609241675Suqs	struct htmlpair	 tag;
610241675Suqs
611241675Suqs	if (MDOC_BLOCK == n->type) {
612241675Suqs		PAIR_CLASS_INIT(&tag, "subsection");
613241675Suqs		print_otag(h, TAG_DIV, 1, &tag);
614241675Suqs		return(1);
615241675Suqs	} else if (MDOC_BODY == n->type)
616241675Suqs		return(1);
617241675Suqs
618241675Suqs	bufinit(h);
619241675Suqs	bufcat(h, "x");
620241675Suqs
621241675Suqs	for (n = n->child; n && MDOC_TEXT == n->type; ) {
622241675Suqs		bufcat_id(h, n->string);
623241675Suqs		if (NULL != (n = n->next))
624241675Suqs			bufcat_id(h, " ");
625241675Suqs	}
626241675Suqs
627241675Suqs	if (NULL == n) {
628241675Suqs		PAIR_ID_INIT(&tag, h->buf);
629241675Suqs		print_otag(h, TAG_H2, 1, &tag);
630241675Suqs	} else
631241675Suqs		print_otag(h, TAG_H2, 0, NULL);
632241675Suqs
633241675Suqs	return(1);
634241675Suqs}
635241675Suqs
636241675Suqs
637241675Suqs/* ARGSUSED */
638241675Suqsstatic int
639241675Suqsmdoc_fl_pre(MDOC_ARGS)
640241675Suqs{
641241675Suqs	struct htmlpair	 tag;
642241675Suqs
643241675Suqs	PAIR_CLASS_INIT(&tag, "flag");
644241675Suqs	print_otag(h, TAG_B, 1, &tag);
645241675Suqs
646241675Suqs	/* `Cm' has no leading hyphen. */
647241675Suqs
648241675Suqs	if (MDOC_Cm == n->tok)
649241675Suqs		return(1);
650241675Suqs
651241675Suqs	print_text(h, "\\-");
652241675Suqs
653241675Suqs	if (n->child)
654241675Suqs		h->flags |= HTML_NOSPACE;
655241675Suqs	else if (n->next && n->next->line == n->line)
656241675Suqs		h->flags |= HTML_NOSPACE;
657241675Suqs
658241675Suqs	return(1);
659241675Suqs}
660241675Suqs
661241675Suqs
662241675Suqs/* ARGSUSED */
663241675Suqsstatic int
664241675Suqsmdoc_nd_pre(MDOC_ARGS)
665241675Suqs{
666241675Suqs	struct htmlpair	 tag;
667241675Suqs
668241675Suqs	if (MDOC_BODY != n->type)
669241675Suqs		return(1);
670241675Suqs
671241675Suqs	/* XXX: this tag in theory can contain block elements. */
672241675Suqs
673241675Suqs	print_text(h, "\\(em");
674241675Suqs	PAIR_CLASS_INIT(&tag, "desc");
675241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
676241675Suqs	return(1);
677241675Suqs}
678241675Suqs
679241675Suqs
680241675Suqsstatic int
681241675Suqsmdoc_nm_pre(MDOC_ARGS)
682241675Suqs{
683241675Suqs	struct htmlpair	 tag;
684241675Suqs	struct roffsu	 su;
685241675Suqs	int		 len;
686241675Suqs
687241675Suqs	switch (n->type) {
688241675Suqs	case (MDOC_ELEM):
689241675Suqs		synopsis_pre(h, n);
690241675Suqs		PAIR_CLASS_INIT(&tag, "name");
691241675Suqs		print_otag(h, TAG_B, 1, &tag);
692241675Suqs		if (NULL == n->child && m->name)
693241675Suqs			print_text(h, m->name);
694241675Suqs		return(1);
695241675Suqs	case (MDOC_HEAD):
696241675Suqs		print_otag(h, TAG_TD, 0, NULL);
697241675Suqs		if (NULL == n->child && m->name)
698241675Suqs			print_text(h, m->name);
699241675Suqs		return(1);
700241675Suqs	case (MDOC_BODY):
701241675Suqs		print_otag(h, TAG_TD, 0, NULL);
702241675Suqs		return(1);
703241675Suqs	default:
704241675Suqs		break;
705241675Suqs	}
706241675Suqs
707241675Suqs	synopsis_pre(h, n);
708241675Suqs	PAIR_CLASS_INIT(&tag, "synopsis");
709241675Suqs	print_otag(h, TAG_TABLE, 1, &tag);
710241675Suqs
711241675Suqs	for (len = 0, n = n->child; n; n = n->next)
712241675Suqs		if (MDOC_TEXT == n->type)
713241675Suqs			len += html_strlen(n->string);
714241675Suqs
715241675Suqs	if (0 == len && m->name)
716241675Suqs		len = html_strlen(m->name);
717241675Suqs
718241675Suqs	SCALE_HS_INIT(&su, (double)len);
719241675Suqs	bufinit(h);
720241675Suqs	bufcat_su(h, "width", &su);
721241675Suqs	PAIR_STYLE_INIT(&tag, h);
722241675Suqs	print_otag(h, TAG_COL, 1, &tag);
723241675Suqs	print_otag(h, TAG_COL, 0, NULL);
724241675Suqs	print_otag(h, TAG_TBODY, 0, NULL);
725241675Suqs	print_otag(h, TAG_TR, 0, NULL);
726241675Suqs	return(1);
727241675Suqs}
728241675Suqs
729241675Suqs
730241675Suqs/* ARGSUSED */
731241675Suqsstatic int
732241675Suqsmdoc_xr_pre(MDOC_ARGS)
733241675Suqs{
734241675Suqs	struct htmlpair	 tag[2];
735241675Suqs
736241675Suqs	if (NULL == n->child)
737241675Suqs		return(0);
738241675Suqs
739241675Suqs	PAIR_CLASS_INIT(&tag[0], "link-man");
740241675Suqs
741241675Suqs	if (h->base_man) {
742241675Suqs		buffmt_man(h, n->child->string,
743241675Suqs				n->child->next ?
744241675Suqs				n->child->next->string : NULL);
745241675Suqs		PAIR_HREF_INIT(&tag[1], h->buf);
746241675Suqs		print_otag(h, TAG_A, 2, tag);
747241675Suqs	} else
748241675Suqs		print_otag(h, TAG_A, 1, tag);
749241675Suqs
750241675Suqs	n = n->child;
751241675Suqs	print_text(h, n->string);
752241675Suqs
753241675Suqs	if (NULL == (n = n->next))
754241675Suqs		return(0);
755241675Suqs
756241675Suqs	h->flags |= HTML_NOSPACE;
757241675Suqs	print_text(h, "(");
758241675Suqs	h->flags |= HTML_NOSPACE;
759241675Suqs	print_text(h, n->string);
760241675Suqs	h->flags |= HTML_NOSPACE;
761241675Suqs	print_text(h, ")");
762241675Suqs	return(0);
763241675Suqs}
764241675Suqs
765241675Suqs
766241675Suqs/* ARGSUSED */
767241675Suqsstatic int
768241675Suqsmdoc_ns_pre(MDOC_ARGS)
769241675Suqs{
770241675Suqs
771241675Suqs	if ( ! (MDOC_LINE & n->flags))
772241675Suqs		h->flags |= HTML_NOSPACE;
773241675Suqs	return(1);
774241675Suqs}
775241675Suqs
776241675Suqs
777241675Suqs/* ARGSUSED */
778241675Suqsstatic int
779241675Suqsmdoc_ar_pre(MDOC_ARGS)
780241675Suqs{
781241675Suqs	struct htmlpair tag;
782241675Suqs
783241675Suqs	PAIR_CLASS_INIT(&tag, "arg");
784241675Suqs	print_otag(h, TAG_I, 1, &tag);
785241675Suqs	return(1);
786241675Suqs}
787241675Suqs
788241675Suqs
789241675Suqs/* ARGSUSED */
790241675Suqsstatic int
791241675Suqsmdoc_xx_pre(MDOC_ARGS)
792241675Suqs{
793241675Suqs	const char	*pp;
794241675Suqs	struct htmlpair	 tag;
795241675Suqs	int		 flags;
796241675Suqs
797241675Suqs	switch (n->tok) {
798241675Suqs	case (MDOC_Bsx):
799241675Suqs		pp = "BSD/OS";
800241675Suqs		break;
801241675Suqs	case (MDOC_Dx):
802241675Suqs		pp = "DragonFly";
803241675Suqs		break;
804241675Suqs	case (MDOC_Fx):
805241675Suqs		pp = "FreeBSD";
806241675Suqs		break;
807241675Suqs	case (MDOC_Nx):
808241675Suqs		pp = "NetBSD";
809241675Suqs		break;
810241675Suqs	case (MDOC_Ox):
811241675Suqs		pp = "OpenBSD";
812241675Suqs		break;
813241675Suqs	case (MDOC_Ux):
814241675Suqs		pp = "UNIX";
815241675Suqs		break;
816241675Suqs	default:
817241675Suqs		return(1);
818241675Suqs	}
819241675Suqs
820241675Suqs	PAIR_CLASS_INIT(&tag, "unix");
821241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
822241675Suqs
823241675Suqs	print_text(h, pp);
824241675Suqs	if (n->child) {
825241675Suqs		flags = h->flags;
826241675Suqs		h->flags |= HTML_KEEP;
827241675Suqs		print_text(h, n->child->string);
828241675Suqs		h->flags = flags;
829241675Suqs	}
830241675Suqs	return(0);
831241675Suqs}
832241675Suqs
833241675Suqs
834241675Suqs/* ARGSUSED */
835241675Suqsstatic int
836241675Suqsmdoc_bx_pre(MDOC_ARGS)
837241675Suqs{
838241675Suqs	struct htmlpair	 tag;
839241675Suqs
840241675Suqs	PAIR_CLASS_INIT(&tag, "unix");
841241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
842241675Suqs
843241675Suqs	if (NULL != (n = n->child)) {
844241675Suqs		print_text(h, n->string);
845241675Suqs		h->flags |= HTML_NOSPACE;
846241675Suqs		print_text(h, "BSD");
847241675Suqs	} else {
848241675Suqs		print_text(h, "BSD");
849241675Suqs		return(0);
850241675Suqs	}
851241675Suqs
852241675Suqs	if (NULL != (n = n->next)) {
853241675Suqs		h->flags |= HTML_NOSPACE;
854241675Suqs		print_text(h, "-");
855241675Suqs		h->flags |= HTML_NOSPACE;
856241675Suqs		print_text(h, n->string);
857241675Suqs	}
858241675Suqs
859241675Suqs	return(0);
860241675Suqs}
861241675Suqs
862241675Suqs/* ARGSUSED */
863241675Suqsstatic int
864241675Suqsmdoc_it_pre(MDOC_ARGS)
865241675Suqs{
866241675Suqs	struct roffsu	 su;
867241675Suqs	enum mdoc_list	 type;
868241675Suqs	struct htmlpair	 tag[2];
869241675Suqs	const struct mdoc_node *bl;
870241675Suqs
871241675Suqs	bl = n->parent;
872241675Suqs	while (bl && MDOC_Bl != bl->tok)
873241675Suqs		bl = bl->parent;
874241675Suqs
875241675Suqs	assert(bl);
876241675Suqs
877241675Suqs	type = bl->norm->Bl.type;
878241675Suqs
879241675Suqs	assert(lists[type]);
880241675Suqs	PAIR_CLASS_INIT(&tag[0], lists[type]);
881241675Suqs
882241675Suqs	bufinit(h);
883241675Suqs
884241675Suqs	if (MDOC_HEAD == n->type) {
885241675Suqs		switch (type) {
886241675Suqs		case(LIST_bullet):
887241675Suqs			/* FALLTHROUGH */
888241675Suqs		case(LIST_dash):
889241675Suqs			/* FALLTHROUGH */
890241675Suqs		case(LIST_item):
891241675Suqs			/* FALLTHROUGH */
892241675Suqs		case(LIST_hyphen):
893241675Suqs			/* FALLTHROUGH */
894241675Suqs		case(LIST_enum):
895241675Suqs			return(0);
896241675Suqs		case(LIST_diag):
897241675Suqs			/* FALLTHROUGH */
898241675Suqs		case(LIST_hang):
899241675Suqs			/* FALLTHROUGH */
900241675Suqs		case(LIST_inset):
901241675Suqs			/* FALLTHROUGH */
902241675Suqs		case(LIST_ohang):
903241675Suqs			/* FALLTHROUGH */
904241675Suqs		case(LIST_tag):
905241675Suqs			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
906241675Suqs			bufcat_su(h, "margin-top", &su);
907241675Suqs			PAIR_STYLE_INIT(&tag[1], h);
908241675Suqs			print_otag(h, TAG_DT, 2, tag);
909241675Suqs			if (LIST_diag != type)
910241675Suqs				break;
911241675Suqs			PAIR_CLASS_INIT(&tag[0], "diag");
912241675Suqs			print_otag(h, TAG_B, 1, tag);
913241675Suqs			break;
914241675Suqs		case(LIST_column):
915241675Suqs			break;
916241675Suqs		default:
917241675Suqs			break;
918241675Suqs		}
919241675Suqs	} else if (MDOC_BODY == n->type) {
920241675Suqs		switch (type) {
921241675Suqs		case(LIST_bullet):
922241675Suqs			/* FALLTHROUGH */
923241675Suqs		case(LIST_hyphen):
924241675Suqs			/* FALLTHROUGH */
925241675Suqs		case(LIST_dash):
926241675Suqs			/* FALLTHROUGH */
927241675Suqs		case(LIST_enum):
928241675Suqs			/* FALLTHROUGH */
929241675Suqs		case(LIST_item):
930241675Suqs			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
931241675Suqs			bufcat_su(h, "margin-top", &su);
932241675Suqs			PAIR_STYLE_INIT(&tag[1], h);
933241675Suqs			print_otag(h, TAG_LI, 2, tag);
934241675Suqs			break;
935241675Suqs		case(LIST_diag):
936241675Suqs			/* FALLTHROUGH */
937241675Suqs		case(LIST_hang):
938241675Suqs			/* FALLTHROUGH */
939241675Suqs		case(LIST_inset):
940241675Suqs			/* FALLTHROUGH */
941241675Suqs		case(LIST_ohang):
942241675Suqs			/* FALLTHROUGH */
943241675Suqs		case(LIST_tag):
944241675Suqs			if (NULL == bl->norm->Bl.width) {
945241675Suqs				print_otag(h, TAG_DD, 1, tag);
946241675Suqs				break;
947241675Suqs			}
948241675Suqs			a2width(bl->norm->Bl.width, &su);
949241675Suqs			bufcat_su(h, "margin-left", &su);
950241675Suqs			PAIR_STYLE_INIT(&tag[1], h);
951241675Suqs			print_otag(h, TAG_DD, 2, tag);
952241675Suqs			break;
953241675Suqs		case(LIST_column):
954241675Suqs			SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
955241675Suqs			bufcat_su(h, "margin-top", &su);
956241675Suqs			PAIR_STYLE_INIT(&tag[1], h);
957241675Suqs			print_otag(h, TAG_TD, 2, tag);
958241675Suqs			break;
959241675Suqs		default:
960241675Suqs			break;
961241675Suqs		}
962241675Suqs	} else {
963241675Suqs		switch (type) {
964241675Suqs		case (LIST_column):
965241675Suqs			print_otag(h, TAG_TR, 1, tag);
966241675Suqs			break;
967241675Suqs		default:
968241675Suqs			break;
969241675Suqs		}
970241675Suqs	}
971241675Suqs
972241675Suqs	return(1);
973241675Suqs}
974241675Suqs
975241675Suqs/* ARGSUSED */
976241675Suqsstatic int
977241675Suqsmdoc_bl_pre(MDOC_ARGS)
978241675Suqs{
979241675Suqs	int		 i;
980241675Suqs	struct htmlpair	 tag[3];
981241675Suqs	struct roffsu	 su;
982241675Suqs	char		 buf[BUFSIZ];
983241675Suqs
984241675Suqs	bufinit(h);
985241675Suqs
986241675Suqs	if (MDOC_BODY == n->type) {
987241675Suqs		if (LIST_column == n->norm->Bl.type)
988241675Suqs			print_otag(h, TAG_TBODY, 0, NULL);
989241675Suqs		return(1);
990241675Suqs	}
991241675Suqs
992241675Suqs	if (MDOC_HEAD == n->type) {
993241675Suqs		if (LIST_column != n->norm->Bl.type)
994241675Suqs			return(0);
995241675Suqs
996241675Suqs		/*
997241675Suqs		 * For each column, print out the <COL> tag with our
998241675Suqs		 * suggested width.  The last column gets min-width, as
999241675Suqs		 * in terminal mode it auto-sizes to the width of the
1000241675Suqs		 * screen and we want to preserve that behaviour.
1001241675Suqs		 */
1002241675Suqs
1003241675Suqs		for (i = 0; i < (int)n->norm->Bl.ncols; i++) {
1004241675Suqs			a2width(n->norm->Bl.cols[i], &su);
1005241675Suqs			if (i < (int)n->norm->Bl.ncols - 1)
1006241675Suqs				bufcat_su(h, "width", &su);
1007241675Suqs			else
1008241675Suqs				bufcat_su(h, "min-width", &su);
1009241675Suqs			PAIR_STYLE_INIT(&tag[0], h);
1010241675Suqs			print_otag(h, TAG_COL, 1, tag);
1011241675Suqs		}
1012241675Suqs
1013241675Suqs		return(0);
1014241675Suqs	}
1015241675Suqs
1016241675Suqs	SCALE_VS_INIT(&su, 0);
1017241675Suqs	bufcat_su(h, "margin-top", &su);
1018241675Suqs	bufcat_su(h, "margin-bottom", &su);
1019241675Suqs	PAIR_STYLE_INIT(&tag[0], h);
1020241675Suqs
1021241675Suqs	assert(lists[n->norm->Bl.type]);
1022241675Suqs	strlcpy(buf, "list ", BUFSIZ);
1023241675Suqs	strlcat(buf, lists[n->norm->Bl.type], BUFSIZ);
1024241675Suqs	PAIR_INIT(&tag[1], ATTR_CLASS, buf);
1025241675Suqs
1026241675Suqs	/* Set the block's left-hand margin. */
1027241675Suqs
1028241675Suqs	if (n->norm->Bl.offs) {
1029241675Suqs		a2offs(n->norm->Bl.offs, &su);
1030241675Suqs		bufcat_su(h, "margin-left", &su);
1031241675Suqs	}
1032241675Suqs
1033241675Suqs	switch (n->norm->Bl.type) {
1034241675Suqs	case(LIST_bullet):
1035241675Suqs		/* FALLTHROUGH */
1036241675Suqs	case(LIST_dash):
1037241675Suqs		/* FALLTHROUGH */
1038241675Suqs	case(LIST_hyphen):
1039241675Suqs		/* FALLTHROUGH */
1040241675Suqs	case(LIST_item):
1041241675Suqs		print_otag(h, TAG_UL, 2, tag);
1042241675Suqs		break;
1043241675Suqs	case(LIST_enum):
1044241675Suqs		print_otag(h, TAG_OL, 2, tag);
1045241675Suqs		break;
1046241675Suqs	case(LIST_diag):
1047241675Suqs		/* FALLTHROUGH */
1048241675Suqs	case(LIST_hang):
1049241675Suqs		/* FALLTHROUGH */
1050241675Suqs	case(LIST_inset):
1051241675Suqs		/* FALLTHROUGH */
1052241675Suqs	case(LIST_ohang):
1053241675Suqs		/* FALLTHROUGH */
1054241675Suqs	case(LIST_tag):
1055241675Suqs		print_otag(h, TAG_DL, 2, tag);
1056241675Suqs		break;
1057241675Suqs	case(LIST_column):
1058241675Suqs		print_otag(h, TAG_TABLE, 2, tag);
1059241675Suqs		break;
1060241675Suqs	default:
1061241675Suqs		abort();
1062241675Suqs		/* NOTREACHED */
1063241675Suqs	}
1064241675Suqs
1065241675Suqs	return(1);
1066241675Suqs}
1067241675Suqs
1068241675Suqs/* ARGSUSED */
1069241675Suqsstatic int
1070241675Suqsmdoc_ex_pre(MDOC_ARGS)
1071241675Suqs{
1072241675Suqs	struct tag	*t;
1073241675Suqs	struct htmlpair	 tag;
1074241675Suqs	int		 nchild;
1075241675Suqs
1076241675Suqs	if (n->prev)
1077241675Suqs		print_otag(h, TAG_BR, 0, NULL);
1078241675Suqs
1079241675Suqs	PAIR_CLASS_INIT(&tag, "utility");
1080241675Suqs
1081241675Suqs	print_text(h, "The");
1082241675Suqs
1083241675Suqs	nchild = n->nchild;
1084241675Suqs	for (n = n->child; n; n = n->next) {
1085241675Suqs		assert(MDOC_TEXT == n->type);
1086241675Suqs
1087241675Suqs		t = print_otag(h, TAG_B, 1, &tag);
1088241675Suqs		print_text(h, n->string);
1089241675Suqs		print_tagq(h, t);
1090241675Suqs
1091241675Suqs		if (nchild > 2 && n->next) {
1092241675Suqs			h->flags |= HTML_NOSPACE;
1093241675Suqs			print_text(h, ",");
1094241675Suqs		}
1095241675Suqs
1096241675Suqs		if (n->next && NULL == n->next->next)
1097241675Suqs			print_text(h, "and");
1098241675Suqs	}
1099241675Suqs
1100241675Suqs	if (nchild > 1)
1101241675Suqs		print_text(h, "utilities exit");
1102241675Suqs	else
1103241675Suqs		print_text(h, "utility exits");
1104241675Suqs
1105241675Suqs       	print_text(h, "0 on success, and >0 if an error occurs.");
1106241675Suqs	return(0);
1107241675Suqs}
1108241675Suqs
1109241675Suqs
1110241675Suqs/* ARGSUSED */
1111241675Suqsstatic int
1112241675Suqsmdoc_em_pre(MDOC_ARGS)
1113241675Suqs{
1114241675Suqs	struct htmlpair	tag;
1115241675Suqs
1116241675Suqs	PAIR_CLASS_INIT(&tag, "emph");
1117241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1118241675Suqs	return(1);
1119241675Suqs}
1120241675Suqs
1121241675Suqs
1122241675Suqs/* ARGSUSED */
1123241675Suqsstatic int
1124241675Suqsmdoc_d1_pre(MDOC_ARGS)
1125241675Suqs{
1126241675Suqs	struct htmlpair	 tag[2];
1127241675Suqs	struct roffsu	 su;
1128241675Suqs
1129241675Suqs	if (MDOC_BLOCK != n->type)
1130241675Suqs		return(1);
1131241675Suqs
1132241675Suqs	SCALE_VS_INIT(&su, 0);
1133241675Suqs	bufinit(h);
1134241675Suqs	bufcat_su(h, "margin-top", &su);
1135241675Suqs	bufcat_su(h, "margin-bottom", &su);
1136241675Suqs	PAIR_STYLE_INIT(&tag[0], h);
1137241675Suqs	print_otag(h, TAG_BLOCKQUOTE, 1, tag);
1138241675Suqs
1139241675Suqs	/* BLOCKQUOTE needs a block body. */
1140241675Suqs
1141241675Suqs	PAIR_CLASS_INIT(&tag[0], "display");
1142241675Suqs	print_otag(h, TAG_DIV, 1, tag);
1143241675Suqs
1144241675Suqs	if (MDOC_Dl == n->tok) {
1145241675Suqs		PAIR_CLASS_INIT(&tag[0], "lit");
1146241675Suqs		print_otag(h, TAG_CODE, 1, tag);
1147241675Suqs	}
1148241675Suqs
1149241675Suqs	return(1);
1150241675Suqs}
1151241675Suqs
1152241675Suqs
1153241675Suqs/* ARGSUSED */
1154241675Suqsstatic int
1155241675Suqsmdoc_sx_pre(MDOC_ARGS)
1156241675Suqs{
1157241675Suqs	struct htmlpair	 tag[2];
1158241675Suqs
1159241675Suqs	bufinit(h);
1160241675Suqs	bufcat(h, "#x");
1161241675Suqs
1162241675Suqs	for (n = n->child; n; ) {
1163241675Suqs		bufcat_id(h, n->string);
1164241675Suqs		if (NULL != (n = n->next))
1165241675Suqs			bufcat_id(h, " ");
1166241675Suqs	}
1167241675Suqs
1168241675Suqs	PAIR_CLASS_INIT(&tag[0], "link-sec");
1169241675Suqs	PAIR_HREF_INIT(&tag[1], h->buf);
1170241675Suqs
1171241675Suqs	print_otag(h, TAG_I, 1, tag);
1172241675Suqs	print_otag(h, TAG_A, 2, tag);
1173241675Suqs	return(1);
1174241675Suqs}
1175241675Suqs
1176241675Suqs
1177241675Suqs/* ARGSUSED */
1178241675Suqsstatic int
1179241675Suqsmdoc_bd_pre(MDOC_ARGS)
1180241675Suqs{
1181241675Suqs	struct htmlpair	 	 tag[2];
1182241675Suqs	int		 	 comp, sv;
1183241675Suqs	const struct mdoc_node	*nn;
1184241675Suqs	struct roffsu		 su;
1185241675Suqs
1186241675Suqs	if (MDOC_HEAD == n->type)
1187241675Suqs		return(0);
1188241675Suqs
1189241675Suqs	if (MDOC_BLOCK == n->type) {
1190241675Suqs		comp = n->norm->Bd.comp;
1191241675Suqs		for (nn = n; nn && ! comp; nn = nn->parent) {
1192241675Suqs			if (MDOC_BLOCK != nn->type)
1193241675Suqs				continue;
1194241675Suqs			if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok)
1195241675Suqs				comp = 1;
1196241675Suqs			if (nn->prev)
1197241675Suqs				break;
1198241675Suqs		}
1199241675Suqs		if ( ! comp)
1200241675Suqs			print_otag(h, TAG_P, 0, NULL);
1201241675Suqs		return(1);
1202241675Suqs	}
1203241675Suqs
1204241675Suqs	SCALE_HS_INIT(&su, 0);
1205241675Suqs	if (n->norm->Bd.offs)
1206241675Suqs		a2offs(n->norm->Bd.offs, &su);
1207241675Suqs
1208241675Suqs	bufinit(h);
1209241675Suqs	bufcat_su(h, "margin-left", &su);
1210241675Suqs	PAIR_STYLE_INIT(&tag[0], h);
1211241675Suqs
1212241675Suqs	if (DISP_unfilled != n->norm->Bd.type &&
1213241675Suqs			DISP_literal != n->norm->Bd.type) {
1214241675Suqs		PAIR_CLASS_INIT(&tag[1], "display");
1215241675Suqs		print_otag(h, TAG_DIV, 2, tag);
1216241675Suqs		return(1);
1217241675Suqs	}
1218241675Suqs
1219241675Suqs	PAIR_CLASS_INIT(&tag[1], "lit display");
1220241675Suqs	print_otag(h, TAG_PRE, 2, tag);
1221241675Suqs
1222241675Suqs	/* This can be recursive: save & set our literal state. */
1223241675Suqs
1224241675Suqs	sv = h->flags & HTML_LITERAL;
1225241675Suqs	h->flags |= HTML_LITERAL;
1226241675Suqs
1227241675Suqs	for (nn = n->child; nn; nn = nn->next) {
1228241675Suqs		print_mdoc_node(m, nn, h);
1229241675Suqs		/*
1230241675Suqs		 * If the printed node flushes its own line, then we
1231241675Suqs		 * needn't do it here as well.  This is hacky, but the
1232241675Suqs		 * notion of selective eoln whitespace is pretty dumb
1233241675Suqs		 * anyway, so don't sweat it.
1234241675Suqs		 */
1235241675Suqs		switch (nn->tok) {
1236241675Suqs		case (MDOC_Sm):
1237241675Suqs			/* FALLTHROUGH */
1238241675Suqs		case (MDOC_br):
1239241675Suqs			/* FALLTHROUGH */
1240241675Suqs		case (MDOC_sp):
1241241675Suqs			/* FALLTHROUGH */
1242241675Suqs		case (MDOC_Bl):
1243241675Suqs			/* FALLTHROUGH */
1244241675Suqs		case (MDOC_D1):
1245241675Suqs			/* FALLTHROUGH */
1246241675Suqs		case (MDOC_Dl):
1247241675Suqs			/* FALLTHROUGH */
1248241675Suqs		case (MDOC_Lp):
1249241675Suqs			/* FALLTHROUGH */
1250241675Suqs		case (MDOC_Pp):
1251241675Suqs			continue;
1252241675Suqs		default:
1253241675Suqs			break;
1254241675Suqs		}
1255241675Suqs		if (nn->next && nn->next->line == nn->line)
1256241675Suqs			continue;
1257241675Suqs		else if (nn->next)
1258241675Suqs			print_text(h, "\n");
1259241675Suqs
1260241675Suqs		h->flags |= HTML_NOSPACE;
1261241675Suqs	}
1262241675Suqs
1263241675Suqs	if (0 == sv)
1264241675Suqs		h->flags &= ~HTML_LITERAL;
1265241675Suqs
1266241675Suqs	return(0);
1267241675Suqs}
1268241675Suqs
1269241675Suqs
1270241675Suqs/* ARGSUSED */
1271241675Suqsstatic int
1272241675Suqsmdoc_pa_pre(MDOC_ARGS)
1273241675Suqs{
1274241675Suqs	struct htmlpair	tag;
1275241675Suqs
1276241675Suqs	PAIR_CLASS_INIT(&tag, "file");
1277241675Suqs	print_otag(h, TAG_I, 1, &tag);
1278241675Suqs	return(1);
1279241675Suqs}
1280241675Suqs
1281241675Suqs
1282241675Suqs/* ARGSUSED */
1283241675Suqsstatic int
1284241675Suqsmdoc_ad_pre(MDOC_ARGS)
1285241675Suqs{
1286241675Suqs	struct htmlpair	tag;
1287241675Suqs
1288241675Suqs	PAIR_CLASS_INIT(&tag, "addr");
1289241675Suqs	print_otag(h, TAG_I, 1, &tag);
1290241675Suqs	return(1);
1291241675Suqs}
1292241675Suqs
1293241675Suqs
1294241675Suqs/* ARGSUSED */
1295241675Suqsstatic int
1296241675Suqsmdoc_an_pre(MDOC_ARGS)
1297241675Suqs{
1298241675Suqs	struct htmlpair	tag;
1299241675Suqs
1300241675Suqs	/* TODO: -split and -nosplit (see termp_an_pre()). */
1301241675Suqs
1302241675Suqs	PAIR_CLASS_INIT(&tag, "author");
1303241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1304241675Suqs	return(1);
1305241675Suqs}
1306241675Suqs
1307241675Suqs
1308241675Suqs/* ARGSUSED */
1309241675Suqsstatic int
1310241675Suqsmdoc_cd_pre(MDOC_ARGS)
1311241675Suqs{
1312241675Suqs	struct htmlpair	tag;
1313241675Suqs
1314241675Suqs	synopsis_pre(h, n);
1315241675Suqs	PAIR_CLASS_INIT(&tag, "config");
1316241675Suqs	print_otag(h, TAG_B, 1, &tag);
1317241675Suqs	return(1);
1318241675Suqs}
1319241675Suqs
1320241675Suqs
1321241675Suqs/* ARGSUSED */
1322241675Suqsstatic int
1323241675Suqsmdoc_dv_pre(MDOC_ARGS)
1324241675Suqs{
1325241675Suqs	struct htmlpair	tag;
1326241675Suqs
1327241675Suqs	PAIR_CLASS_INIT(&tag, "define");
1328241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1329241675Suqs	return(1);
1330241675Suqs}
1331241675Suqs
1332241675Suqs
1333241675Suqs/* ARGSUSED */
1334241675Suqsstatic int
1335241675Suqsmdoc_ev_pre(MDOC_ARGS)
1336241675Suqs{
1337241675Suqs	struct htmlpair	tag;
1338241675Suqs
1339241675Suqs	PAIR_CLASS_INIT(&tag, "env");
1340241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1341241675Suqs	return(1);
1342241675Suqs}
1343241675Suqs
1344241675Suqs
1345241675Suqs/* ARGSUSED */
1346241675Suqsstatic int
1347241675Suqsmdoc_er_pre(MDOC_ARGS)
1348241675Suqs{
1349241675Suqs	struct htmlpair	tag;
1350241675Suqs
1351241675Suqs	PAIR_CLASS_INIT(&tag, "errno");
1352241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1353241675Suqs	return(1);
1354241675Suqs}
1355241675Suqs
1356241675Suqs
1357241675Suqs/* ARGSUSED */
1358241675Suqsstatic int
1359241675Suqsmdoc_fa_pre(MDOC_ARGS)
1360241675Suqs{
1361241675Suqs	const struct mdoc_node	*nn;
1362241675Suqs	struct htmlpair		 tag;
1363241675Suqs	struct tag		*t;
1364241675Suqs
1365241675Suqs	PAIR_CLASS_INIT(&tag, "farg");
1366241675Suqs	if (n->parent->tok != MDOC_Fo) {
1367241675Suqs		print_otag(h, TAG_I, 1, &tag);
1368241675Suqs		return(1);
1369241675Suqs	}
1370241675Suqs
1371241675Suqs	for (nn = n->child; nn; nn = nn->next) {
1372241675Suqs		t = print_otag(h, TAG_I, 1, &tag);
1373241675Suqs		print_text(h, nn->string);
1374241675Suqs		print_tagq(h, t);
1375241675Suqs		if (nn->next) {
1376241675Suqs			h->flags |= HTML_NOSPACE;
1377241675Suqs			print_text(h, ",");
1378241675Suqs		}
1379241675Suqs	}
1380241675Suqs
1381241675Suqs	if (n->child && n->next && n->next->tok == MDOC_Fa) {
1382241675Suqs		h->flags |= HTML_NOSPACE;
1383241675Suqs		print_text(h, ",");
1384241675Suqs	}
1385241675Suqs
1386241675Suqs	return(0);
1387241675Suqs}
1388241675Suqs
1389241675Suqs
1390241675Suqs/* ARGSUSED */
1391241675Suqsstatic int
1392241675Suqsmdoc_fd_pre(MDOC_ARGS)
1393241675Suqs{
1394241675Suqs	struct htmlpair	 tag[2];
1395241675Suqs	char		 buf[BUFSIZ];
1396241675Suqs	size_t		 sz;
1397241675Suqs	int		 i;
1398241675Suqs	struct tag	*t;
1399241675Suqs
1400241675Suqs	synopsis_pre(h, n);
1401241675Suqs
1402241675Suqs	if (NULL == (n = n->child))
1403241675Suqs		return(0);
1404241675Suqs
1405241675Suqs	assert(MDOC_TEXT == n->type);
1406241675Suqs
1407241675Suqs	if (strcmp(n->string, "#include")) {
1408241675Suqs		PAIR_CLASS_INIT(&tag[0], "macro");
1409241675Suqs		print_otag(h, TAG_B, 1, tag);
1410241675Suqs		return(1);
1411241675Suqs	}
1412241675Suqs
1413241675Suqs	PAIR_CLASS_INIT(&tag[0], "includes");
1414241675Suqs	print_otag(h, TAG_B, 1, tag);
1415241675Suqs	print_text(h, n->string);
1416241675Suqs
1417241675Suqs	if (NULL != (n = n->next)) {
1418241675Suqs		assert(MDOC_TEXT == n->type);
1419241675Suqs		strlcpy(buf, '<' == *n->string || '"' == *n->string ?
1420241675Suqs				n->string + 1 : n->string, BUFSIZ);
1421241675Suqs
1422241675Suqs		sz = strlen(buf);
1423241675Suqs		if (sz && ('>' == buf[sz - 1] || '"' == buf[sz - 1]))
1424241675Suqs			buf[sz - 1] = '\0';
1425241675Suqs
1426241675Suqs		PAIR_CLASS_INIT(&tag[0], "link-includes");
1427241675Suqs
1428241675Suqs		i = 1;
1429241675Suqs		if (h->base_includes) {
1430241675Suqs			buffmt_includes(h, buf);
1431241675Suqs			PAIR_HREF_INIT(&tag[i], h->buf);
1432241675Suqs			i++;
1433241675Suqs		}
1434241675Suqs
1435241675Suqs		t = print_otag(h, TAG_A, i, tag);
1436241675Suqs		print_text(h, n->string);
1437241675Suqs		print_tagq(h, t);
1438241675Suqs
1439241675Suqs		n = n->next;
1440241675Suqs	}
1441241675Suqs
1442241675Suqs	for ( ; n; n = n->next) {
1443241675Suqs		assert(MDOC_TEXT == n->type);
1444241675Suqs		print_text(h, n->string);
1445241675Suqs	}
1446241675Suqs
1447241675Suqs	return(0);
1448241675Suqs}
1449241675Suqs
1450241675Suqs
1451241675Suqs/* ARGSUSED */
1452241675Suqsstatic int
1453241675Suqsmdoc_vt_pre(MDOC_ARGS)
1454241675Suqs{
1455241675Suqs	struct htmlpair	 tag;
1456241675Suqs
1457241675Suqs	if (MDOC_BLOCK == n->type) {
1458241675Suqs		synopsis_pre(h, n);
1459241675Suqs		return(1);
1460241675Suqs	} else if (MDOC_ELEM == n->type) {
1461241675Suqs		synopsis_pre(h, n);
1462241675Suqs	} else if (MDOC_HEAD == n->type)
1463241675Suqs		return(0);
1464241675Suqs
1465241675Suqs	PAIR_CLASS_INIT(&tag, "type");
1466241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1467241675Suqs	return(1);
1468241675Suqs}
1469241675Suqs
1470241675Suqs
1471241675Suqs/* ARGSUSED */
1472241675Suqsstatic int
1473241675Suqsmdoc_ft_pre(MDOC_ARGS)
1474241675Suqs{
1475241675Suqs	struct htmlpair	 tag;
1476241675Suqs
1477241675Suqs	synopsis_pre(h, n);
1478241675Suqs	PAIR_CLASS_INIT(&tag, "ftype");
1479241675Suqs	print_otag(h, TAG_I, 1, &tag);
1480241675Suqs	return(1);
1481241675Suqs}
1482241675Suqs
1483241675Suqs
1484241675Suqs/* ARGSUSED */
1485241675Suqsstatic int
1486241675Suqsmdoc_fn_pre(MDOC_ARGS)
1487241675Suqs{
1488241675Suqs	struct tag	*t;
1489241675Suqs	struct htmlpair	 tag[2];
1490241675Suqs	char		 nbuf[BUFSIZ];
1491241675Suqs	const char	*sp, *ep;
1492241675Suqs	int		 sz, i, pretty;
1493241675Suqs
1494241675Suqs	pretty = MDOC_SYNPRETTY & n->flags;
1495241675Suqs	synopsis_pre(h, n);
1496241675Suqs
1497241675Suqs	/* Split apart into type and name. */
1498241675Suqs	assert(n->child->string);
1499241675Suqs	sp = n->child->string;
1500241675Suqs
1501241675Suqs	ep = strchr(sp, ' ');
1502241675Suqs	if (NULL != ep) {
1503241675Suqs		PAIR_CLASS_INIT(&tag[0], "ftype");
1504241675Suqs		t = print_otag(h, TAG_I, 1, tag);
1505241675Suqs
1506241675Suqs		while (ep) {
1507241675Suqs			sz = MIN((int)(ep - sp), BUFSIZ - 1);
1508241675Suqs			(void)memcpy(nbuf, sp, (size_t)sz);
1509241675Suqs			nbuf[sz] = '\0';
1510241675Suqs			print_text(h, nbuf);
1511241675Suqs			sp = ++ep;
1512241675Suqs			ep = strchr(sp, ' ');
1513241675Suqs		}
1514241675Suqs		print_tagq(h, t);
1515241675Suqs	}
1516241675Suqs
1517241675Suqs	PAIR_CLASS_INIT(&tag[0], "fname");
1518241675Suqs
1519241675Suqs	/*
1520241675Suqs	 * FIXME: only refer to IDs that we know exist.
1521241675Suqs	 */
1522241675Suqs
1523241675Suqs#if 0
1524241675Suqs	if (MDOC_SYNPRETTY & n->flags) {
1525241675Suqs		nbuf[0] = '\0';
1526241675Suqs		html_idcat(nbuf, sp, BUFSIZ);
1527241675Suqs		PAIR_ID_INIT(&tag[1], nbuf);
1528241675Suqs	} else {
1529241675Suqs		strlcpy(nbuf, "#", BUFSIZ);
1530241675Suqs		html_idcat(nbuf, sp, BUFSIZ);
1531241675Suqs		PAIR_HREF_INIT(&tag[1], nbuf);
1532241675Suqs	}
1533241675Suqs#endif
1534241675Suqs
1535241675Suqs	t = print_otag(h, TAG_B, 1, tag);
1536241675Suqs
1537241675Suqs	if (sp) {
1538241675Suqs		strlcpy(nbuf, sp, BUFSIZ);
1539241675Suqs		print_text(h, nbuf);
1540241675Suqs	}
1541241675Suqs
1542241675Suqs	print_tagq(h, t);
1543241675Suqs
1544241675Suqs	h->flags |= HTML_NOSPACE;
1545241675Suqs	print_text(h, "(");
1546241675Suqs	h->flags |= HTML_NOSPACE;
1547241675Suqs
1548241675Suqs	PAIR_CLASS_INIT(&tag[0], "farg");
1549241675Suqs	bufinit(h);
1550241675Suqs	bufcat_style(h, "white-space", "nowrap");
1551241675Suqs	PAIR_STYLE_INIT(&tag[1], h);
1552241675Suqs
1553241675Suqs	for (n = n->child->next; n; n = n->next) {
1554241675Suqs		i = 1;
1555241675Suqs		if (MDOC_SYNPRETTY & n->flags)
1556241675Suqs			i = 2;
1557241675Suqs		t = print_otag(h, TAG_I, i, tag);
1558241675Suqs		print_text(h, n->string);
1559241675Suqs		print_tagq(h, t);
1560241675Suqs		if (n->next) {
1561241675Suqs			h->flags |= HTML_NOSPACE;
1562241675Suqs			print_text(h, ",");
1563241675Suqs		}
1564241675Suqs	}
1565241675Suqs
1566241675Suqs	h->flags |= HTML_NOSPACE;
1567241675Suqs	print_text(h, ")");
1568241675Suqs
1569241675Suqs	if (pretty) {
1570241675Suqs		h->flags |= HTML_NOSPACE;
1571241675Suqs		print_text(h, ";");
1572241675Suqs	}
1573241675Suqs
1574241675Suqs	return(0);
1575241675Suqs}
1576241675Suqs
1577241675Suqs
1578241675Suqs/* ARGSUSED */
1579241675Suqsstatic int
1580241675Suqsmdoc_sm_pre(MDOC_ARGS)
1581241675Suqs{
1582241675Suqs
1583241675Suqs	assert(n->child && MDOC_TEXT == n->child->type);
1584241675Suqs	if (0 == strcmp("on", n->child->string)) {
1585241675Suqs		/*
1586241675Suqs		 * FIXME: no p->col to check.  Thus, if we have
1587241675Suqs		 *  .Bd -literal
1588241675Suqs		 *  .Sm off
1589241675Suqs		 *  1 2
1590241675Suqs		 *  .Sm on
1591241675Suqs		 *  3
1592241675Suqs		 *  .Ed
1593241675Suqs		 * the "3" is preceded by a space.
1594241675Suqs		 */
1595241675Suqs		h->flags &= ~HTML_NOSPACE;
1596241675Suqs		h->flags &= ~HTML_NONOSPACE;
1597241675Suqs	} else
1598241675Suqs		h->flags |= HTML_NONOSPACE;
1599241675Suqs
1600241675Suqs	return(0);
1601241675Suqs}
1602241675Suqs
1603241675Suqs/* ARGSUSED */
1604241675Suqsstatic int
1605241675Suqsmdoc_pp_pre(MDOC_ARGS)
1606241675Suqs{
1607241675Suqs
1608241675Suqs	print_otag(h, TAG_P, 0, NULL);
1609241675Suqs	return(0);
1610241675Suqs
1611241675Suqs}
1612241675Suqs
1613241675Suqs/* ARGSUSED */
1614241675Suqsstatic int
1615241675Suqsmdoc_sp_pre(MDOC_ARGS)
1616241675Suqs{
1617241675Suqs	struct roffsu	 su;
1618241675Suqs	struct htmlpair	 tag;
1619241675Suqs
1620241675Suqs	SCALE_VS_INIT(&su, 1);
1621241675Suqs
1622241675Suqs	if (MDOC_sp == n->tok) {
1623241675Suqs		if (NULL != (n = n->child))
1624241675Suqs			if ( ! a2roffsu(n->string, &su, SCALE_VS))
1625241675Suqs				SCALE_VS_INIT(&su, atoi(n->string));
1626241675Suqs	} else
1627241675Suqs		su.scale = 0;
1628241675Suqs
1629241675Suqs	bufinit(h);
1630241675Suqs	bufcat_su(h, "height", &su);
1631241675Suqs	PAIR_STYLE_INIT(&tag, h);
1632241675Suqs	print_otag(h, TAG_DIV, 1, &tag);
1633241675Suqs
1634241675Suqs	/* So the div isn't empty: */
1635241675Suqs	print_text(h, "\\~");
1636241675Suqs
1637241675Suqs	return(0);
1638241675Suqs
1639241675Suqs}
1640241675Suqs
1641241675Suqs/* ARGSUSED */
1642241675Suqsstatic int
1643241675Suqsmdoc_lk_pre(MDOC_ARGS)
1644241675Suqs{
1645241675Suqs	struct htmlpair	 tag[2];
1646241675Suqs
1647241675Suqs	if (NULL == (n = n->child))
1648241675Suqs		return(0);
1649241675Suqs
1650241675Suqs	assert(MDOC_TEXT == n->type);
1651241675Suqs
1652241675Suqs	PAIR_CLASS_INIT(&tag[0], "link-ext");
1653241675Suqs	PAIR_HREF_INIT(&tag[1], n->string);
1654241675Suqs
1655241675Suqs	print_otag(h, TAG_A, 2, tag);
1656241675Suqs
1657241675Suqs	if (NULL == n->next)
1658241675Suqs		print_text(h, n->string);
1659241675Suqs
1660241675Suqs	for (n = n->next; n; n = n->next)
1661241675Suqs		print_text(h, n->string);
1662241675Suqs
1663241675Suqs	return(0);
1664241675Suqs}
1665241675Suqs
1666241675Suqs
1667241675Suqs/* ARGSUSED */
1668241675Suqsstatic int
1669241675Suqsmdoc_mt_pre(MDOC_ARGS)
1670241675Suqs{
1671241675Suqs	struct htmlpair	 tag[2];
1672241675Suqs	struct tag	*t;
1673241675Suqs
1674241675Suqs	PAIR_CLASS_INIT(&tag[0], "link-mail");
1675241675Suqs
1676241675Suqs	for (n = n->child; n; n = n->next) {
1677241675Suqs		assert(MDOC_TEXT == n->type);
1678241675Suqs
1679241675Suqs		bufinit(h);
1680241675Suqs		bufcat(h, "mailto:");
1681241675Suqs		bufcat(h, n->string);
1682241675Suqs
1683241675Suqs		PAIR_HREF_INIT(&tag[1], h->buf);
1684241675Suqs		t = print_otag(h, TAG_A, 2, tag);
1685241675Suqs		print_text(h, n->string);
1686241675Suqs		print_tagq(h, t);
1687241675Suqs	}
1688241675Suqs
1689241675Suqs	return(0);
1690241675Suqs}
1691241675Suqs
1692241675Suqs
1693241675Suqs/* ARGSUSED */
1694241675Suqsstatic int
1695241675Suqsmdoc_fo_pre(MDOC_ARGS)
1696241675Suqs{
1697241675Suqs	struct htmlpair	 tag;
1698241675Suqs	struct tag	*t;
1699241675Suqs
1700241675Suqs	if (MDOC_BODY == n->type) {
1701241675Suqs		h->flags |= HTML_NOSPACE;
1702241675Suqs		print_text(h, "(");
1703241675Suqs		h->flags |= HTML_NOSPACE;
1704241675Suqs		return(1);
1705241675Suqs	} else if (MDOC_BLOCK == n->type) {
1706241675Suqs		synopsis_pre(h, n);
1707241675Suqs		return(1);
1708241675Suqs	}
1709241675Suqs
1710241675Suqs	/* XXX: we drop non-initial arguments as per groff. */
1711241675Suqs
1712241675Suqs	assert(n->child);
1713241675Suqs	assert(n->child->string);
1714241675Suqs
1715241675Suqs	PAIR_CLASS_INIT(&tag, "fname");
1716241675Suqs	t = print_otag(h, TAG_B, 1, &tag);
1717241675Suqs	print_text(h, n->child->string);
1718241675Suqs	print_tagq(h, t);
1719241675Suqs	return(0);
1720241675Suqs}
1721241675Suqs
1722241675Suqs
1723241675Suqs/* ARGSUSED */
1724241675Suqsstatic void
1725241675Suqsmdoc_fo_post(MDOC_ARGS)
1726241675Suqs{
1727241675Suqs
1728241675Suqs	if (MDOC_BODY != n->type)
1729241675Suqs		return;
1730241675Suqs	h->flags |= HTML_NOSPACE;
1731241675Suqs	print_text(h, ")");
1732241675Suqs	h->flags |= HTML_NOSPACE;
1733241675Suqs	print_text(h, ";");
1734241675Suqs}
1735241675Suqs
1736241675Suqs
1737241675Suqs/* ARGSUSED */
1738241675Suqsstatic int
1739241675Suqsmdoc_in_pre(MDOC_ARGS)
1740241675Suqs{
1741241675Suqs	struct tag	*t;
1742241675Suqs	struct htmlpair	 tag[2];
1743241675Suqs	int		 i;
1744241675Suqs
1745241675Suqs	synopsis_pre(h, n);
1746241675Suqs
1747241675Suqs	PAIR_CLASS_INIT(&tag[0], "includes");
1748241675Suqs	print_otag(h, TAG_B, 1, tag);
1749241675Suqs
1750241675Suqs	/*
1751241675Suqs	 * The first argument of the `In' gets special treatment as
1752241675Suqs	 * being a linked value.  Subsequent values are printed
1753241675Suqs	 * afterward.  groff does similarly.  This also handles the case
1754241675Suqs	 * of no children.
1755241675Suqs	 */
1756241675Suqs
1757241675Suqs	if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags)
1758241675Suqs		print_text(h, "#include");
1759241675Suqs
1760241675Suqs	print_text(h, "<");
1761241675Suqs	h->flags |= HTML_NOSPACE;
1762241675Suqs
1763241675Suqs	if (NULL != (n = n->child)) {
1764241675Suqs		assert(MDOC_TEXT == n->type);
1765241675Suqs
1766241675Suqs		PAIR_CLASS_INIT(&tag[0], "link-includes");
1767241675Suqs
1768241675Suqs		i = 1;
1769241675Suqs		if (h->base_includes) {
1770241675Suqs			buffmt_includes(h, n->string);
1771241675Suqs			PAIR_HREF_INIT(&tag[i], h->buf);
1772241675Suqs			i++;
1773241675Suqs		}
1774241675Suqs
1775241675Suqs		t = print_otag(h, TAG_A, i, tag);
1776241675Suqs		print_text(h, n->string);
1777241675Suqs		print_tagq(h, t);
1778241675Suqs
1779241675Suqs		n = n->next;
1780241675Suqs	}
1781241675Suqs
1782241675Suqs	h->flags |= HTML_NOSPACE;
1783241675Suqs	print_text(h, ">");
1784241675Suqs
1785241675Suqs	for ( ; n; n = n->next) {
1786241675Suqs		assert(MDOC_TEXT == n->type);
1787241675Suqs		print_text(h, n->string);
1788241675Suqs	}
1789241675Suqs
1790241675Suqs	return(0);
1791241675Suqs}
1792241675Suqs
1793241675Suqs
1794241675Suqs/* ARGSUSED */
1795241675Suqsstatic int
1796241675Suqsmdoc_ic_pre(MDOC_ARGS)
1797241675Suqs{
1798241675Suqs	struct htmlpair	tag;
1799241675Suqs
1800241675Suqs	PAIR_CLASS_INIT(&tag, "cmd");
1801241675Suqs	print_otag(h, TAG_B, 1, &tag);
1802241675Suqs	return(1);
1803241675Suqs}
1804241675Suqs
1805241675Suqs
1806241675Suqs/* ARGSUSED */
1807241675Suqsstatic int
1808241675Suqsmdoc_rv_pre(MDOC_ARGS)
1809241675Suqs{
1810241675Suqs	struct htmlpair	 tag;
1811241675Suqs	struct tag	*t;
1812241675Suqs	int		 nchild;
1813241675Suqs
1814241675Suqs	if (n->prev)
1815241675Suqs		print_otag(h, TAG_BR, 0, NULL);
1816241675Suqs
1817241675Suqs	PAIR_CLASS_INIT(&tag, "fname");
1818241675Suqs
1819241675Suqs	print_text(h, "The");
1820241675Suqs
1821241675Suqs	nchild = n->nchild;
1822241675Suqs	for (n = n->child; n; n = n->next) {
1823241675Suqs		assert(MDOC_TEXT == n->type);
1824241675Suqs
1825241675Suqs		t = print_otag(h, TAG_B, 1, &tag);
1826241675Suqs		print_text(h, n->string);
1827241675Suqs		print_tagq(h, t);
1828241675Suqs
1829241675Suqs		h->flags |= HTML_NOSPACE;
1830241675Suqs		print_text(h, "()");
1831241675Suqs
1832241675Suqs		if (nchild > 2 && n->next) {
1833241675Suqs			h->flags |= HTML_NOSPACE;
1834241675Suqs			print_text(h, ",");
1835241675Suqs		}
1836241675Suqs
1837241675Suqs		if (n->next && NULL == n->next->next)
1838241675Suqs			print_text(h, "and");
1839241675Suqs	}
1840241675Suqs
1841241675Suqs	if (nchild > 1)
1842241675Suqs		print_text(h, "functions return");
1843241675Suqs	else
1844241675Suqs		print_text(h, "function returns");
1845241675Suqs
1846241675Suqs       	print_text(h, "the value 0 if successful; otherwise the value "
1847241675Suqs			"-1 is returned and the global variable");
1848241675Suqs
1849241675Suqs	PAIR_CLASS_INIT(&tag, "var");
1850241675Suqs	t = print_otag(h, TAG_B, 1, &tag);
1851241675Suqs	print_text(h, "errno");
1852241675Suqs	print_tagq(h, t);
1853241675Suqs       	print_text(h, "is set to indicate the error.");
1854241675Suqs	return(0);
1855241675Suqs}
1856241675Suqs
1857241675Suqs
1858241675Suqs/* ARGSUSED */
1859241675Suqsstatic int
1860241675Suqsmdoc_va_pre(MDOC_ARGS)
1861241675Suqs{
1862241675Suqs	struct htmlpair	tag;
1863241675Suqs
1864241675Suqs	PAIR_CLASS_INIT(&tag, "var");
1865241675Suqs	print_otag(h, TAG_B, 1, &tag);
1866241675Suqs	return(1);
1867241675Suqs}
1868241675Suqs
1869241675Suqs
1870241675Suqs/* ARGSUSED */
1871241675Suqsstatic int
1872241675Suqsmdoc_ap_pre(MDOC_ARGS)
1873241675Suqs{
1874241675Suqs
1875241675Suqs	h->flags |= HTML_NOSPACE;
1876241675Suqs	print_text(h, "\\(aq");
1877241675Suqs	h->flags |= HTML_NOSPACE;
1878241675Suqs	return(1);
1879241675Suqs}
1880241675Suqs
1881241675Suqs
1882241675Suqs/* ARGSUSED */
1883241675Suqsstatic int
1884241675Suqsmdoc_bf_pre(MDOC_ARGS)
1885241675Suqs{
1886241675Suqs	struct htmlpair	 tag[2];
1887241675Suqs	struct roffsu	 su;
1888241675Suqs
1889241675Suqs	if (MDOC_HEAD == n->type)
1890241675Suqs		return(0);
1891241675Suqs	else if (MDOC_BODY != n->type)
1892241675Suqs		return(1);
1893241675Suqs
1894241675Suqs	if (FONT_Em == n->norm->Bf.font)
1895241675Suqs		PAIR_CLASS_INIT(&tag[0], "emph");
1896241675Suqs	else if (FONT_Sy == n->norm->Bf.font)
1897241675Suqs		PAIR_CLASS_INIT(&tag[0], "symb");
1898241675Suqs	else if (FONT_Li == n->norm->Bf.font)
1899241675Suqs		PAIR_CLASS_INIT(&tag[0], "lit");
1900241675Suqs	else
1901241675Suqs		PAIR_CLASS_INIT(&tag[0], "none");
1902241675Suqs
1903241675Suqs	/*
1904241675Suqs	 * We want this to be inline-formatted, but needs to be div to
1905241675Suqs	 * accept block children.
1906241675Suqs	 */
1907241675Suqs	bufinit(h);
1908241675Suqs	bufcat_style(h, "display", "inline");
1909241675Suqs	SCALE_HS_INIT(&su, 1);
1910241675Suqs	/* Needs a left-margin for spacing. */
1911241675Suqs	bufcat_su(h, "margin-left", &su);
1912241675Suqs	PAIR_STYLE_INIT(&tag[1], h);
1913241675Suqs	print_otag(h, TAG_DIV, 2, tag);
1914241675Suqs	return(1);
1915241675Suqs}
1916241675Suqs
1917241675Suqs
1918241675Suqs/* ARGSUSED */
1919241675Suqsstatic int
1920241675Suqsmdoc_ms_pre(MDOC_ARGS)
1921241675Suqs{
1922241675Suqs	struct htmlpair	tag;
1923241675Suqs
1924241675Suqs	PAIR_CLASS_INIT(&tag, "symb");
1925241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1926241675Suqs	return(1);
1927241675Suqs}
1928241675Suqs
1929241675Suqs
1930241675Suqs/* ARGSUSED */
1931241675Suqsstatic int
1932241675Suqsmdoc_igndelim_pre(MDOC_ARGS)
1933241675Suqs{
1934241675Suqs
1935241675Suqs	h->flags |= HTML_IGNDELIM;
1936241675Suqs	return(1);
1937241675Suqs}
1938241675Suqs
1939241675Suqs
1940241675Suqs/* ARGSUSED */
1941241675Suqsstatic void
1942241675Suqsmdoc_pf_post(MDOC_ARGS)
1943241675Suqs{
1944241675Suqs
1945241675Suqs	h->flags |= HTML_NOSPACE;
1946241675Suqs}
1947241675Suqs
1948241675Suqs
1949241675Suqs/* ARGSUSED */
1950241675Suqsstatic int
1951241675Suqsmdoc_rs_pre(MDOC_ARGS)
1952241675Suqs{
1953241675Suqs	struct htmlpair	 tag;
1954241675Suqs
1955241675Suqs	if (MDOC_BLOCK != n->type)
1956241675Suqs		return(1);
1957241675Suqs
1958241675Suqs	if (n->prev && SEC_SEE_ALSO == n->sec)
1959241675Suqs		print_otag(h, TAG_P, 0, NULL);
1960241675Suqs
1961241675Suqs	PAIR_CLASS_INIT(&tag, "ref");
1962241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1963241675Suqs	return(1);
1964241675Suqs}
1965241675Suqs
1966241675Suqs
1967241675Suqs
1968241675Suqs/* ARGSUSED */
1969241675Suqsstatic int
1970241675Suqsmdoc_li_pre(MDOC_ARGS)
1971241675Suqs{
1972241675Suqs	struct htmlpair	tag;
1973241675Suqs
1974241675Suqs	PAIR_CLASS_INIT(&tag, "lit");
1975241675Suqs	print_otag(h, TAG_CODE, 1, &tag);
1976241675Suqs	return(1);
1977241675Suqs}
1978241675Suqs
1979241675Suqs
1980241675Suqs/* ARGSUSED */
1981241675Suqsstatic int
1982241675Suqsmdoc_sy_pre(MDOC_ARGS)
1983241675Suqs{
1984241675Suqs	struct htmlpair	tag;
1985241675Suqs
1986241675Suqs	PAIR_CLASS_INIT(&tag, "symb");
1987241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
1988241675Suqs	return(1);
1989241675Suqs}
1990241675Suqs
1991241675Suqs
1992241675Suqs/* ARGSUSED */
1993241675Suqsstatic int
1994241675Suqsmdoc_bt_pre(MDOC_ARGS)
1995241675Suqs{
1996241675Suqs
1997241675Suqs	print_text(h, "is currently in beta test.");
1998241675Suqs	return(0);
1999241675Suqs}
2000241675Suqs
2001241675Suqs
2002241675Suqs/* ARGSUSED */
2003241675Suqsstatic int
2004241675Suqsmdoc_ud_pre(MDOC_ARGS)
2005241675Suqs{
2006241675Suqs
2007241675Suqs	print_text(h, "currently under development.");
2008241675Suqs	return(0);
2009241675Suqs}
2010241675Suqs
2011241675Suqs
2012241675Suqs/* ARGSUSED */
2013241675Suqsstatic int
2014241675Suqsmdoc_lb_pre(MDOC_ARGS)
2015241675Suqs{
2016241675Suqs	struct htmlpair	tag;
2017241675Suqs
2018241675Suqs	if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags && n->prev)
2019241675Suqs		print_otag(h, TAG_BR, 0, NULL);
2020241675Suqs
2021241675Suqs	PAIR_CLASS_INIT(&tag, "lib");
2022241675Suqs	print_otag(h, TAG_SPAN, 1, &tag);
2023241675Suqs	return(1);
2024241675Suqs}
2025241675Suqs
2026241675Suqs
2027241675Suqs/* ARGSUSED */
2028241675Suqsstatic int
2029241675Suqsmdoc__x_pre(MDOC_ARGS)
2030241675Suqs{
2031241675Suqs	struct htmlpair	tag[2];
2032241675Suqs	enum htmltag	t;
2033241675Suqs
2034241675Suqs	t = TAG_SPAN;
2035241675Suqs
2036241675Suqs	switch (n->tok) {
2037241675Suqs	case(MDOC__A):
2038241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-auth");
2039241675Suqs		if (n->prev && MDOC__A == n->prev->tok)
2040241675Suqs			if (NULL == n->next || MDOC__A != n->next->tok)
2041241675Suqs				print_text(h, "and");
2042241675Suqs		break;
2043241675Suqs	case(MDOC__B):
2044241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-book");
2045241675Suqs		t = TAG_I;
2046241675Suqs		break;
2047241675Suqs	case(MDOC__C):
2048241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-city");
2049241675Suqs		break;
2050241675Suqs	case(MDOC__D):
2051241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-date");
2052241675Suqs		break;
2053241675Suqs	case(MDOC__I):
2054241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-issue");
2055241675Suqs		t = TAG_I;
2056241675Suqs		break;
2057241675Suqs	case(MDOC__J):
2058241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-jrnl");
2059241675Suqs		t = TAG_I;
2060241675Suqs		break;
2061241675Suqs	case(MDOC__N):
2062241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-num");
2063241675Suqs		break;
2064241675Suqs	case(MDOC__O):
2065241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-opt");
2066241675Suqs		break;
2067241675Suqs	case(MDOC__P):
2068241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-page");
2069241675Suqs		break;
2070241675Suqs	case(MDOC__Q):
2071241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-corp");
2072241675Suqs		break;
2073241675Suqs	case(MDOC__R):
2074241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-rep");
2075241675Suqs		break;
2076241675Suqs	case(MDOC__T):
2077241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-title");
2078241675Suqs		break;
2079241675Suqs	case(MDOC__U):
2080241675Suqs		PAIR_CLASS_INIT(&tag[0], "link-ref");
2081241675Suqs		break;
2082241675Suqs	case(MDOC__V):
2083241675Suqs		PAIR_CLASS_INIT(&tag[0], "ref-vol");
2084241675Suqs		break;
2085241675Suqs	default:
2086241675Suqs		abort();
2087241675Suqs		/* NOTREACHED */
2088241675Suqs	}
2089241675Suqs
2090241675Suqs	if (MDOC__U != n->tok) {
2091241675Suqs		print_otag(h, t, 1, tag);
2092241675Suqs		return(1);
2093241675Suqs	}
2094241675Suqs
2095241675Suqs	PAIR_HREF_INIT(&tag[1], n->child->string);
2096241675Suqs	print_otag(h, TAG_A, 2, tag);
2097241675Suqs
2098241675Suqs	return(1);
2099241675Suqs}
2100241675Suqs
2101241675Suqs
2102241675Suqs/* ARGSUSED */
2103241675Suqsstatic void
2104241675Suqsmdoc__x_post(MDOC_ARGS)
2105241675Suqs{
2106241675Suqs
2107241675Suqs	if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
2108241675Suqs		if (NULL == n->next->next || MDOC__A != n->next->next->tok)
2109241675Suqs			if (NULL == n->prev || MDOC__A != n->prev->tok)
2110241675Suqs				return;
2111241675Suqs
2112241675Suqs	/* TODO: %U */
2113241675Suqs
2114241675Suqs	if (NULL == n->parent || MDOC_Rs != n->parent->tok)
2115241675Suqs		return;
2116241675Suqs
2117241675Suqs	h->flags |= HTML_NOSPACE;
2118241675Suqs	print_text(h, n->next ? "," : ".");
2119241675Suqs}
2120241675Suqs
2121241675Suqs
2122241675Suqs/* ARGSUSED */
2123241675Suqsstatic int
2124241675Suqsmdoc_bk_pre(MDOC_ARGS)
2125241675Suqs{
2126241675Suqs
2127241675Suqs	switch (n->type) {
2128241675Suqs	case (MDOC_BLOCK):
2129241675Suqs		break;
2130241675Suqs	case (MDOC_HEAD):
2131241675Suqs		return(0);
2132241675Suqs	case (MDOC_BODY):
2133241675Suqs		if (n->parent->args || 0 == n->prev->nchild)
2134241675Suqs			h->flags |= HTML_PREKEEP;
2135241675Suqs		break;
2136241675Suqs	default:
2137241675Suqs		abort();
2138241675Suqs		/* NOTREACHED */
2139241675Suqs	}
2140241675Suqs
2141241675Suqs	return(1);
2142241675Suqs}
2143241675Suqs
2144241675Suqs
2145241675Suqs/* ARGSUSED */
2146241675Suqsstatic void
2147241675Suqsmdoc_bk_post(MDOC_ARGS)
2148241675Suqs{
2149241675Suqs
2150241675Suqs	if (MDOC_BODY == n->type)
2151241675Suqs		h->flags &= ~(HTML_KEEP | HTML_PREKEEP);
2152241675Suqs}
2153241675Suqs
2154241675Suqs
2155241675Suqs/* ARGSUSED */
2156241675Suqsstatic int
2157241675Suqsmdoc_quote_pre(MDOC_ARGS)
2158241675Suqs{
2159241675Suqs	struct htmlpair	tag;
2160241675Suqs
2161241675Suqs	if (MDOC_BODY != n->type)
2162241675Suqs		return(1);
2163241675Suqs
2164241675Suqs	switch (n->tok) {
2165241675Suqs	case (MDOC_Ao):
2166241675Suqs		/* FALLTHROUGH */
2167241675Suqs	case (MDOC_Aq):
2168241675Suqs		print_text(h, "\\(la");
2169241675Suqs		break;
2170241675Suqs	case (MDOC_Bro):
2171241675Suqs		/* FALLTHROUGH */
2172241675Suqs	case (MDOC_Brq):
2173241675Suqs		print_text(h, "\\(lC");
2174241675Suqs		break;
2175241675Suqs	case (MDOC_Bo):
2176241675Suqs		/* FALLTHROUGH */
2177241675Suqs	case (MDOC_Bq):
2178241675Suqs		print_text(h, "\\(lB");
2179241675Suqs		break;
2180241675Suqs	case (MDOC_Oo):
2181241675Suqs		/* FALLTHROUGH */
2182241675Suqs	case (MDOC_Op):
2183241675Suqs		print_text(h, "\\(lB");
2184241675Suqs		h->flags |= HTML_NOSPACE;
2185241675Suqs		PAIR_CLASS_INIT(&tag, "opt");
2186241675Suqs		print_otag(h, TAG_SPAN, 1, &tag);
2187241675Suqs		break;
2188241675Suqs	case (MDOC_Eo):
2189241675Suqs		break;
2190241675Suqs	case (MDOC_Do):
2191241675Suqs		/* FALLTHROUGH */
2192241675Suqs	case (MDOC_Dq):
2193241675Suqs		/* FALLTHROUGH */
2194241675Suqs	case (MDOC_Qo):
2195241675Suqs		/* FALLTHROUGH */
2196241675Suqs	case (MDOC_Qq):
2197241675Suqs		print_text(h, "\\(lq");
2198241675Suqs		break;
2199241675Suqs	case (MDOC_Po):
2200241675Suqs		/* FALLTHROUGH */
2201241675Suqs	case (MDOC_Pq):
2202241675Suqs		print_text(h, "(");
2203241675Suqs		break;
2204241675Suqs	case (MDOC_Ql):
2205241675Suqs		print_text(h, "\\(oq");
2206241675Suqs		h->flags |= HTML_NOSPACE;
2207241675Suqs		PAIR_CLASS_INIT(&tag, "lit");
2208241675Suqs		print_otag(h, TAG_CODE, 1, &tag);
2209241675Suqs		break;
2210241675Suqs	case (MDOC_So):
2211241675Suqs		/* FALLTHROUGH */
2212241675Suqs	case (MDOC_Sq):
2213241675Suqs		print_text(h, "\\(oq");
2214241675Suqs		break;
2215241675Suqs	default:
2216241675Suqs		abort();
2217241675Suqs		/* NOTREACHED */
2218241675Suqs	}
2219241675Suqs
2220241675Suqs	h->flags |= HTML_NOSPACE;
2221241675Suqs	return(1);
2222241675Suqs}
2223241675Suqs
2224241675Suqs
2225241675Suqs/* ARGSUSED */
2226241675Suqsstatic void
2227241675Suqsmdoc_quote_post(MDOC_ARGS)
2228241675Suqs{
2229241675Suqs
2230241675Suqs	if (MDOC_BODY != n->type)
2231241675Suqs		return;
2232241675Suqs
2233241675Suqs	h->flags |= HTML_NOSPACE;
2234241675Suqs
2235241675Suqs	switch (n->tok) {
2236241675Suqs	case (MDOC_Ao):
2237241675Suqs		/* FALLTHROUGH */
2238241675Suqs	case (MDOC_Aq):
2239241675Suqs		print_text(h, "\\(ra");
2240241675Suqs		break;
2241241675Suqs	case (MDOC_Bro):
2242241675Suqs		/* FALLTHROUGH */
2243241675Suqs	case (MDOC_Brq):
2244241675Suqs		print_text(h, "\\(rC");
2245241675Suqs		break;
2246241675Suqs	case (MDOC_Oo):
2247241675Suqs		/* FALLTHROUGH */
2248241675Suqs	case (MDOC_Op):
2249241675Suqs		/* FALLTHROUGH */
2250241675Suqs	case (MDOC_Bo):
2251241675Suqs		/* FALLTHROUGH */
2252241675Suqs	case (MDOC_Bq):
2253241675Suqs		print_text(h, "\\(rB");
2254241675Suqs		break;
2255241675Suqs	case (MDOC_Eo):
2256241675Suqs		break;
2257241675Suqs	case (MDOC_Qo):
2258241675Suqs		/* FALLTHROUGH */
2259241675Suqs	case (MDOC_Qq):
2260241675Suqs		/* FALLTHROUGH */
2261241675Suqs	case (MDOC_Do):
2262241675Suqs		/* FALLTHROUGH */
2263241675Suqs	case (MDOC_Dq):
2264241675Suqs		print_text(h, "\\(rq");
2265241675Suqs		break;
2266241675Suqs	case (MDOC_Po):
2267241675Suqs		/* FALLTHROUGH */
2268241675Suqs	case (MDOC_Pq):
2269241675Suqs		print_text(h, ")");
2270241675Suqs		break;
2271241675Suqs	case (MDOC_Ql):
2272241675Suqs		/* FALLTHROUGH */
2273241675Suqs	case (MDOC_So):
2274241675Suqs		/* FALLTHROUGH */
2275241675Suqs	case (MDOC_Sq):
2276241675Suqs		print_text(h, "\\(aq");
2277241675Suqs		break;
2278241675Suqs	default:
2279241675Suqs		abort();
2280241675Suqs		/* NOTREACHED */
2281241675Suqs	}
2282241675Suqs}
2283241675Suqs
2284241675Suqs
2285