xref: /titanic_52/usr/src/cmd/mandoc/man_html.c (revision 260e9a87725c090ba5835b1f9f0b62fa2f96036f)
1*260e9a87SYuri Pankov /*	$Id: man_html.c,v 1.112 2015/03/03 21:11:34 schwarze Exp $ */
295c635efSGarrett D'Amore /*
3*260e9a87SYuri Pankov  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4*260e9a87SYuri Pankov  * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore  *
695c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore  *
1095c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1195c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1295c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1395c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1795c635efSGarrett D'Amore  */
1895c635efSGarrett D'Amore #include "config.h"
1995c635efSGarrett D'Amore 
2095c635efSGarrett D'Amore #include <sys/types.h>
2195c635efSGarrett D'Amore 
2295c635efSGarrett D'Amore #include <assert.h>
2395c635efSGarrett D'Amore #include <ctype.h>
2495c635efSGarrett D'Amore #include <stdio.h>
2595c635efSGarrett D'Amore #include <stdlib.h>
2695c635efSGarrett D'Amore #include <string.h>
2795c635efSGarrett D'Amore 
28*260e9a87SYuri Pankov #include "mandoc_aux.h"
29*260e9a87SYuri Pankov #include "man.h"
3095c635efSGarrett D'Amore #include "out.h"
3195c635efSGarrett D'Amore #include "html.h"
3295c635efSGarrett D'Amore #include "main.h"
3395c635efSGarrett D'Amore 
3495c635efSGarrett D'Amore /* TODO: preserve ident widths. */
3595c635efSGarrett D'Amore /* FIXME: have PD set the default vspace width. */
3695c635efSGarrett D'Amore 
3795c635efSGarrett D'Amore #define	INDENT		  5
3895c635efSGarrett D'Amore 
39698f87a4SGarrett D'Amore #define	MAN_ARGS	  const struct man_meta *man, \
4095c635efSGarrett D'Amore 			  const struct man_node *n, \
4195c635efSGarrett D'Amore 			  struct mhtml *mh, \
4295c635efSGarrett D'Amore 			  struct html *h
4395c635efSGarrett D'Amore 
4495c635efSGarrett D'Amore struct	mhtml {
4595c635efSGarrett D'Amore 	int		  fl;
4695c635efSGarrett D'Amore #define	MANH_LITERAL	 (1 << 0) /* literal context */
4795c635efSGarrett D'Amore };
4895c635efSGarrett D'Amore 
4995c635efSGarrett D'Amore struct	htmlman {
5095c635efSGarrett D'Amore 	int		(*pre)(MAN_ARGS);
5195c635efSGarrett D'Amore 	int		(*post)(MAN_ARGS);
5295c635efSGarrett D'Amore };
5395c635efSGarrett D'Amore 
5495c635efSGarrett D'Amore static	void		  print_bvspace(struct html *,
5595c635efSGarrett D'Amore 				const struct man_node *);
5695c635efSGarrett D'Amore static	void		  print_man(MAN_ARGS);
5795c635efSGarrett D'Amore static	void		  print_man_head(MAN_ARGS);
5895c635efSGarrett D'Amore static	void		  print_man_nodelist(MAN_ARGS);
5995c635efSGarrett D'Amore static	void		  print_man_node(MAN_ARGS);
6095c635efSGarrett D'Amore static	int		  a2width(const struct man_node *,
6195c635efSGarrett D'Amore 				struct roffsu *);
6295c635efSGarrett D'Amore static	int		  man_B_pre(MAN_ARGS);
6395c635efSGarrett D'Amore static	int		  man_HP_pre(MAN_ARGS);
6495c635efSGarrett D'Amore static	int		  man_IP_pre(MAN_ARGS);
6595c635efSGarrett D'Amore static	int		  man_I_pre(MAN_ARGS);
6695c635efSGarrett D'Amore static	int		  man_OP_pre(MAN_ARGS);
6795c635efSGarrett D'Amore static	int		  man_PP_pre(MAN_ARGS);
6895c635efSGarrett D'Amore static	int		  man_RS_pre(MAN_ARGS);
6995c635efSGarrett D'Amore static	int		  man_SH_pre(MAN_ARGS);
7095c635efSGarrett D'Amore static	int		  man_SM_pre(MAN_ARGS);
7195c635efSGarrett D'Amore static	int		  man_SS_pre(MAN_ARGS);
72698f87a4SGarrett D'Amore static	int		  man_UR_pre(MAN_ARGS);
7395c635efSGarrett D'Amore static	int		  man_alt_pre(MAN_ARGS);
7495c635efSGarrett D'Amore static	int		  man_br_pre(MAN_ARGS);
7595c635efSGarrett D'Amore static	int		  man_ign_pre(MAN_ARGS);
7695c635efSGarrett D'Amore static	int		  man_in_pre(MAN_ARGS);
7795c635efSGarrett D'Amore static	int		  man_literal_pre(MAN_ARGS);
7895c635efSGarrett D'Amore static	void		  man_root_post(MAN_ARGS);
7995c635efSGarrett D'Amore static	void		  man_root_pre(MAN_ARGS);
8095c635efSGarrett D'Amore 
8195c635efSGarrett D'Amore static	const struct htmlman mans[MAN_MAX] = {
8295c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* br */
8395c635efSGarrett D'Amore 	{ NULL, NULL }, /* TH */
8495c635efSGarrett D'Amore 	{ man_SH_pre, NULL }, /* SH */
8595c635efSGarrett D'Amore 	{ man_SS_pre, NULL }, /* SS */
8695c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* TP */
8795c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* LP */
8895c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* PP */
8995c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* P */
9095c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* IP */
9195c635efSGarrett D'Amore 	{ man_HP_pre, NULL }, /* HP */
9295c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SM */
9395c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SB */
9495c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BI */
9595c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IB */
9695c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BR */
9795c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RB */
9895c635efSGarrett D'Amore 	{ NULL, NULL }, /* R */
9995c635efSGarrett D'Amore 	{ man_B_pre, NULL }, /* B */
10095c635efSGarrett D'Amore 	{ man_I_pre, NULL }, /* I */
10195c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IR */
10295c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RI */
10395c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* sp */
10495c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* nf */
10595c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* fi */
10695c635efSGarrett D'Amore 	{ NULL, NULL }, /* RE */
10795c635efSGarrett D'Amore 	{ man_RS_pre, NULL }, /* RS */
10895c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* DT */
10995c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* UC */
11095c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* PD */
11195c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* AT */
11295c635efSGarrett D'Amore 	{ man_in_pre, NULL }, /* in */
11395c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* ft */
11495c635efSGarrett D'Amore 	{ man_OP_pre, NULL }, /* OP */
115698f87a4SGarrett D'Amore 	{ man_literal_pre, NULL }, /* EX */
116698f87a4SGarrett D'Amore 	{ man_literal_pre, NULL }, /* EE */
117698f87a4SGarrett D'Amore 	{ man_UR_pre, NULL }, /* UR */
118698f87a4SGarrett D'Amore 	{ NULL, NULL }, /* UE */
119*260e9a87SYuri Pankov 	{ man_ign_pre, NULL }, /* ll */
12095c635efSGarrett D'Amore };
12195c635efSGarrett D'Amore 
122*260e9a87SYuri Pankov 
12395c635efSGarrett D'Amore /*
12495c635efSGarrett D'Amore  * Printing leading vertical space before a block.
12595c635efSGarrett D'Amore  * This is used for the paragraph macros.
12695c635efSGarrett D'Amore  * The rules are pretty simple, since there's very little nesting going
12795c635efSGarrett D'Amore  * on here.  Basically, if we're the first within another block (SS/SH),
12895c635efSGarrett D'Amore  * then don't emit vertical space.  If we are (RS), then do.  If not the
12995c635efSGarrett D'Amore  * first, print it.
13095c635efSGarrett D'Amore  */
13195c635efSGarrett D'Amore static void
13295c635efSGarrett D'Amore print_bvspace(struct html *h, const struct man_node *n)
13395c635efSGarrett D'Amore {
13495c635efSGarrett D'Amore 
13595c635efSGarrett D'Amore 	if (n->body && n->body->child)
13695c635efSGarrett D'Amore 		if (MAN_TBL == n->body->child->type)
13795c635efSGarrett D'Amore 			return;
13895c635efSGarrett D'Amore 
13995c635efSGarrett D'Amore 	if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok)
14095c635efSGarrett D'Amore 		if (NULL == n->prev)
14195c635efSGarrett D'Amore 			return;
14295c635efSGarrett D'Amore 
143*260e9a87SYuri Pankov 	print_paragraph(h);
14495c635efSGarrett D'Amore }
14595c635efSGarrett D'Amore 
14695c635efSGarrett D'Amore void
147698f87a4SGarrett D'Amore html_man(void *arg, const struct man *man)
14895c635efSGarrett D'Amore {
14995c635efSGarrett D'Amore 	struct mhtml	 mh;
15095c635efSGarrett D'Amore 
15195c635efSGarrett D'Amore 	memset(&mh, 0, sizeof(struct mhtml));
152698f87a4SGarrett D'Amore 	print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
15395c635efSGarrett D'Amore 	putchar('\n');
15495c635efSGarrett D'Amore }
15595c635efSGarrett D'Amore 
15695c635efSGarrett D'Amore static void
15795c635efSGarrett D'Amore print_man(MAN_ARGS)
15895c635efSGarrett D'Amore {
15995c635efSGarrett D'Amore 	struct tag	*t, *tt;
16095c635efSGarrett D'Amore 	struct htmlpair	 tag;
16195c635efSGarrett D'Amore 
16295c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "mandoc");
16395c635efSGarrett D'Amore 
16495c635efSGarrett D'Amore 	if ( ! (HTML_FRAGMENT & h->oflags)) {
16595c635efSGarrett D'Amore 		print_gen_decls(h);
16695c635efSGarrett D'Amore 		t = print_otag(h, TAG_HTML, 0, NULL);
16795c635efSGarrett D'Amore 		tt = print_otag(h, TAG_HEAD, 0, NULL);
168698f87a4SGarrett D'Amore 		print_man_head(man, n, mh, h);
16995c635efSGarrett D'Amore 		print_tagq(h, tt);
17095c635efSGarrett D'Amore 		print_otag(h, TAG_BODY, 0, NULL);
17195c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
17295c635efSGarrett D'Amore 	} else
17395c635efSGarrett D'Amore 		t = print_otag(h, TAG_DIV, 1, &tag);
17495c635efSGarrett D'Amore 
175698f87a4SGarrett D'Amore 	print_man_nodelist(man, n, mh, h);
17695c635efSGarrett D'Amore 	print_tagq(h, t);
17795c635efSGarrett D'Amore }
17895c635efSGarrett D'Amore 
17995c635efSGarrett D'Amore static void
18095c635efSGarrett D'Amore print_man_head(MAN_ARGS)
18195c635efSGarrett D'Amore {
18295c635efSGarrett D'Amore 
18395c635efSGarrett D'Amore 	print_gen_head(h);
184698f87a4SGarrett D'Amore 	assert(man->title);
185698f87a4SGarrett D'Amore 	assert(man->msec);
186698f87a4SGarrett D'Amore 	bufcat_fmt(h, "%s(%s)", man->title, man->msec);
18795c635efSGarrett D'Amore 	print_otag(h, TAG_TITLE, 0, NULL);
18895c635efSGarrett D'Amore 	print_text(h, h->buf);
18995c635efSGarrett D'Amore }
19095c635efSGarrett D'Amore 
19195c635efSGarrett D'Amore static void
19295c635efSGarrett D'Amore print_man_nodelist(MAN_ARGS)
19395c635efSGarrett D'Amore {
19495c635efSGarrett D'Amore 
195*260e9a87SYuri Pankov 	while (n != NULL) {
196698f87a4SGarrett D'Amore 		print_man_node(man, n, mh, h);
197*260e9a87SYuri Pankov 		n = n->next;
19895c635efSGarrett D'Amore 	}
199*260e9a87SYuri Pankov }
20095c635efSGarrett D'Amore 
20195c635efSGarrett D'Amore static void
20295c635efSGarrett D'Amore print_man_node(MAN_ARGS)
20395c635efSGarrett D'Amore {
20495c635efSGarrett D'Amore 	int		 child;
20595c635efSGarrett D'Amore 	struct tag	*t;
20695c635efSGarrett D'Amore 
20795c635efSGarrett D'Amore 	child = 1;
20895c635efSGarrett D'Amore 	t = h->tags.head;
20995c635efSGarrett D'Amore 
21095c635efSGarrett D'Amore 	switch (n->type) {
211*260e9a87SYuri Pankov 	case MAN_ROOT:
212698f87a4SGarrett D'Amore 		man_root_pre(man, n, mh, h);
21395c635efSGarrett D'Amore 		break;
214*260e9a87SYuri Pankov 	case MAN_TEXT:
21595c635efSGarrett D'Amore 		if ('\0' == *n->string) {
216*260e9a87SYuri Pankov 			print_paragraph(h);
21795c635efSGarrett D'Amore 			return;
21895c635efSGarrett D'Amore 		}
219*260e9a87SYuri Pankov 		if (n->flags & MAN_LINE && (*n->string == ' ' ||
220*260e9a87SYuri Pankov 		    (n->prev != NULL && mh->fl & MANH_LITERAL &&
221*260e9a87SYuri Pankov 		     ! (h->flags & HTML_NONEWLINE))))
22295c635efSGarrett D'Amore 			print_otag(h, TAG_BR, 0, NULL);
22395c635efSGarrett D'Amore 		print_text(h, n->string);
22495c635efSGarrett D'Amore 		return;
225*260e9a87SYuri Pankov 	case MAN_EQN:
226*260e9a87SYuri Pankov 		if (n->flags & MAN_LINE)
227*260e9a87SYuri Pankov 			putchar('\n');
22895c635efSGarrett D'Amore 		print_eqn(h, n->eqn);
22995c635efSGarrett D'Amore 		break;
230*260e9a87SYuri Pankov 	case MAN_TBL:
23195c635efSGarrett D'Amore 		/*
23295c635efSGarrett D'Amore 		 * This will take care of initialising all of the table
23395c635efSGarrett D'Amore 		 * state data for the first table, then tearing it down
23495c635efSGarrett D'Amore 		 * for the last one.
23595c635efSGarrett D'Amore 		 */
23695c635efSGarrett D'Amore 		print_tbl(h, n->span);
23795c635efSGarrett D'Amore 		return;
23895c635efSGarrett D'Amore 	default:
23995c635efSGarrett D'Amore 		/*
24095c635efSGarrett D'Amore 		 * Close out scope of font prior to opening a macro
24195c635efSGarrett D'Amore 		 * scope.
24295c635efSGarrett D'Amore 		 */
24395c635efSGarrett D'Amore 		if (HTMLFONT_NONE != h->metac) {
24495c635efSGarrett D'Amore 			h->metal = h->metac;
24595c635efSGarrett D'Amore 			h->metac = HTMLFONT_NONE;
24695c635efSGarrett D'Amore 		}
24795c635efSGarrett D'Amore 
24895c635efSGarrett D'Amore 		/*
24995c635efSGarrett D'Amore 		 * Close out the current table, if it's open, and unset
25095c635efSGarrett D'Amore 		 * the "meta" table state.  This will be reopened on the
25195c635efSGarrett D'Amore 		 * next table element.
25295c635efSGarrett D'Amore 		 */
25395c635efSGarrett D'Amore 		if (h->tblt) {
25495c635efSGarrett D'Amore 			print_tblclose(h);
25595c635efSGarrett D'Amore 			t = h->tags.head;
25695c635efSGarrett D'Amore 		}
25795c635efSGarrett D'Amore 		if (mans[n->tok].pre)
258698f87a4SGarrett D'Amore 			child = (*mans[n->tok].pre)(man, n, mh, h);
25995c635efSGarrett D'Amore 		break;
26095c635efSGarrett D'Amore 	}
26195c635efSGarrett D'Amore 
26295c635efSGarrett D'Amore 	if (child && n->child)
263698f87a4SGarrett D'Amore 		print_man_nodelist(man, n->child, mh, h);
26495c635efSGarrett D'Amore 
26595c635efSGarrett D'Amore 	/* This will automatically close out any font scope. */
26695c635efSGarrett D'Amore 	print_stagq(h, t);
26795c635efSGarrett D'Amore 
26895c635efSGarrett D'Amore 	switch (n->type) {
269*260e9a87SYuri Pankov 	case MAN_ROOT:
270698f87a4SGarrett D'Amore 		man_root_post(man, n, mh, h);
27195c635efSGarrett D'Amore 		break;
272*260e9a87SYuri Pankov 	case MAN_EQN:
27395c635efSGarrett D'Amore 		break;
27495c635efSGarrett D'Amore 	default:
27595c635efSGarrett D'Amore 		if (mans[n->tok].post)
276698f87a4SGarrett D'Amore 			(*mans[n->tok].post)(man, n, mh, h);
27795c635efSGarrett D'Amore 		break;
27895c635efSGarrett D'Amore 	}
27995c635efSGarrett D'Amore }
28095c635efSGarrett D'Amore 
28195c635efSGarrett D'Amore static int
28295c635efSGarrett D'Amore a2width(const struct man_node *n, struct roffsu *su)
28395c635efSGarrett D'Amore {
28495c635efSGarrett D'Amore 
28595c635efSGarrett D'Amore 	if (MAN_TEXT != n->type)
28695c635efSGarrett D'Amore 		return(0);
287*260e9a87SYuri Pankov 	if (a2roffsu(n->string, su, SCALE_EN))
28895c635efSGarrett D'Amore 		return(1);
28995c635efSGarrett D'Amore 
29095c635efSGarrett D'Amore 	return(0);
29195c635efSGarrett D'Amore }
29295c635efSGarrett D'Amore 
29395c635efSGarrett D'Amore static void
29495c635efSGarrett D'Amore man_root_pre(MAN_ARGS)
29595c635efSGarrett D'Amore {
296*260e9a87SYuri Pankov 	struct htmlpair	 tag;
29795c635efSGarrett D'Amore 	struct tag	*t, *tt;
298*260e9a87SYuri Pankov 	char		*title;
29995c635efSGarrett D'Amore 
300698f87a4SGarrett D'Amore 	assert(man->title);
301698f87a4SGarrett D'Amore 	assert(man->msec);
302*260e9a87SYuri Pankov 	mandoc_asprintf(&title, "%s(%s)", man->title, man->msec);
30395c635efSGarrett D'Amore 
304*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "head");
305*260e9a87SYuri Pankov 	t = print_otag(h, TAG_TABLE, 1, &tag);
30695c635efSGarrett D'Amore 
30795c635efSGarrett D'Amore 	print_otag(h, TAG_TBODY, 0, NULL);
30895c635efSGarrett D'Amore 
30995c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
31095c635efSGarrett D'Amore 
311*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "head-ltitle");
312*260e9a87SYuri Pankov 	print_otag(h, TAG_TD, 1, &tag);
31395c635efSGarrett D'Amore 	print_text(h, title);
31495c635efSGarrett D'Amore 	print_stagq(h, tt);
31595c635efSGarrett D'Amore 
316*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "head-vol");
317*260e9a87SYuri Pankov 	print_otag(h, TAG_TD, 1, &tag);
318*260e9a87SYuri Pankov 	if (NULL != man->vol)
319*260e9a87SYuri Pankov 		print_text(h, man->vol);
32095c635efSGarrett D'Amore 	print_stagq(h, tt);
32195c635efSGarrett D'Amore 
322*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "head-rtitle");
323*260e9a87SYuri Pankov 	print_otag(h, TAG_TD, 1, &tag);
32495c635efSGarrett D'Amore 	print_text(h, title);
32595c635efSGarrett D'Amore 	print_tagq(h, t);
326*260e9a87SYuri Pankov 	free(title);
32795c635efSGarrett D'Amore }
32895c635efSGarrett D'Amore 
32995c635efSGarrett D'Amore static void
33095c635efSGarrett D'Amore man_root_post(MAN_ARGS)
33195c635efSGarrett D'Amore {
332*260e9a87SYuri Pankov 	struct htmlpair	 tag;
33395c635efSGarrett D'Amore 	struct tag	*t, *tt;
33495c635efSGarrett D'Amore 
335*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "foot");
336*260e9a87SYuri Pankov 	t = print_otag(h, TAG_TABLE, 1, &tag);
33795c635efSGarrett D'Amore 
33895c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
33995c635efSGarrett D'Amore 
340*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "foot-date");
341*260e9a87SYuri Pankov 	print_otag(h, TAG_TD, 1, &tag);
34295c635efSGarrett D'Amore 
343698f87a4SGarrett D'Amore 	assert(man->date);
344698f87a4SGarrett D'Amore 	print_text(h, man->date);
34595c635efSGarrett D'Amore 	print_stagq(h, tt);
34695c635efSGarrett D'Amore 
347*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag, "foot-os");
348*260e9a87SYuri Pankov 	print_otag(h, TAG_TD, 1, &tag);
34995c635efSGarrett D'Amore 
350698f87a4SGarrett D'Amore 	if (man->source)
351698f87a4SGarrett D'Amore 		print_text(h, man->source);
35295c635efSGarrett D'Amore 	print_tagq(h, t);
35395c635efSGarrett D'Amore }
35495c635efSGarrett D'Amore 
35595c635efSGarrett D'Amore 
35695c635efSGarrett D'Amore static int
35795c635efSGarrett D'Amore man_br_pre(MAN_ARGS)
35895c635efSGarrett D'Amore {
35995c635efSGarrett D'Amore 	struct roffsu	 su;
36095c635efSGarrett D'Amore 	struct htmlpair	 tag;
36195c635efSGarrett D'Amore 
36295c635efSGarrett D'Amore 	SCALE_VS_INIT(&su, 1);
36395c635efSGarrett D'Amore 
36495c635efSGarrett D'Amore 	if (MAN_sp == n->tok) {
36595c635efSGarrett D'Amore 		if (NULL != (n = n->child))
36695c635efSGarrett D'Amore 			if ( ! a2roffsu(n->string, &su, SCALE_VS))
367*260e9a87SYuri Pankov 				su.scale = 1.0;
36895c635efSGarrett D'Amore 	} else
369*260e9a87SYuri Pankov 		su.scale = 0.0;
37095c635efSGarrett D'Amore 
37195c635efSGarrett D'Amore 	bufinit(h);
37295c635efSGarrett D'Amore 	bufcat_su(h, "height", &su);
37395c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
37495c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
37595c635efSGarrett D'Amore 
37695c635efSGarrett D'Amore 	/* So the div isn't empty: */
37795c635efSGarrett D'Amore 	print_text(h, "\\~");
37895c635efSGarrett D'Amore 
37995c635efSGarrett D'Amore 	return(0);
38095c635efSGarrett D'Amore }
38195c635efSGarrett D'Amore 
38295c635efSGarrett D'Amore static int
38395c635efSGarrett D'Amore man_SH_pre(MAN_ARGS)
38495c635efSGarrett D'Amore {
38595c635efSGarrett D'Amore 	struct htmlpair	 tag;
38695c635efSGarrett D'Amore 
38795c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
38895c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
38995c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "section");
39095c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
39195c635efSGarrett D'Amore 		return(1);
39295c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
39395c635efSGarrett D'Amore 		return(1);
39495c635efSGarrett D'Amore 
39595c635efSGarrett D'Amore 	print_otag(h, TAG_H1, 0, NULL);
39695c635efSGarrett D'Amore 	return(1);
39795c635efSGarrett D'Amore }
39895c635efSGarrett D'Amore 
39995c635efSGarrett D'Amore static int
40095c635efSGarrett D'Amore man_alt_pre(MAN_ARGS)
40195c635efSGarrett D'Amore {
40295c635efSGarrett D'Amore 	const struct man_node	*nn;
40395c635efSGarrett D'Amore 	int		 i, savelit;
40495c635efSGarrett D'Amore 	enum htmltag	 fp;
40595c635efSGarrett D'Amore 	struct tag	*t;
40695c635efSGarrett D'Amore 
40795c635efSGarrett D'Amore 	if ((savelit = mh->fl & MANH_LITERAL))
40895c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
40995c635efSGarrett D'Amore 
41095c635efSGarrett D'Amore 	mh->fl &= ~MANH_LITERAL;
41195c635efSGarrett D'Amore 
41295c635efSGarrett D'Amore 	for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
41395c635efSGarrett D'Amore 		t = NULL;
41495c635efSGarrett D'Amore 		switch (n->tok) {
415*260e9a87SYuri Pankov 		case MAN_BI:
41695c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_B;
41795c635efSGarrett D'Amore 			break;
418*260e9a87SYuri Pankov 		case MAN_IB:
41995c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_I;
42095c635efSGarrett D'Amore 			break;
421*260e9a87SYuri Pankov 		case MAN_RI:
42295c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_MAX;
42395c635efSGarrett D'Amore 			break;
424*260e9a87SYuri Pankov 		case MAN_IR:
42595c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_I;
42695c635efSGarrett D'Amore 			break;
427*260e9a87SYuri Pankov 		case MAN_BR:
42895c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_B;
42995c635efSGarrett D'Amore 			break;
430*260e9a87SYuri Pankov 		case MAN_RB:
43195c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_MAX;
43295c635efSGarrett D'Amore 			break;
43395c635efSGarrett D'Amore 		default:
43495c635efSGarrett D'Amore 			abort();
43595c635efSGarrett D'Amore 			/* NOTREACHED */
43695c635efSGarrett D'Amore 		}
43795c635efSGarrett D'Amore 
43895c635efSGarrett D'Amore 		if (i)
43995c635efSGarrett D'Amore 			h->flags |= HTML_NOSPACE;
44095c635efSGarrett D'Amore 
44195c635efSGarrett D'Amore 		if (TAG_MAX != fp)
44295c635efSGarrett D'Amore 			t = print_otag(h, fp, 0, NULL);
44395c635efSGarrett D'Amore 
444698f87a4SGarrett D'Amore 		print_man_node(man, nn, mh, h);
44595c635efSGarrett D'Amore 
44695c635efSGarrett D'Amore 		if (t)
44795c635efSGarrett D'Amore 			print_tagq(h, t);
44895c635efSGarrett D'Amore 	}
44995c635efSGarrett D'Amore 
45095c635efSGarrett D'Amore 	if (savelit)
45195c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
45295c635efSGarrett D'Amore 
45395c635efSGarrett D'Amore 	return(0);
45495c635efSGarrett D'Amore }
45595c635efSGarrett D'Amore 
45695c635efSGarrett D'Amore static int
45795c635efSGarrett D'Amore man_SM_pre(MAN_ARGS)
45895c635efSGarrett D'Amore {
45995c635efSGarrett D'Amore 
46095c635efSGarrett D'Amore 	print_otag(h, TAG_SMALL, 0, NULL);
46195c635efSGarrett D'Amore 	if (MAN_SB == n->tok)
46295c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
46395c635efSGarrett D'Amore 	return(1);
46495c635efSGarrett D'Amore }
46595c635efSGarrett D'Amore 
46695c635efSGarrett D'Amore static int
46795c635efSGarrett D'Amore man_SS_pre(MAN_ARGS)
46895c635efSGarrett D'Amore {
46995c635efSGarrett D'Amore 	struct htmlpair	 tag;
47095c635efSGarrett D'Amore 
47195c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
47295c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
47395c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "subsection");
47495c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
47595c635efSGarrett D'Amore 		return(1);
47695c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
47795c635efSGarrett D'Amore 		return(1);
47895c635efSGarrett D'Amore 
47995c635efSGarrett D'Amore 	print_otag(h, TAG_H2, 0, NULL);
48095c635efSGarrett D'Amore 	return(1);
48195c635efSGarrett D'Amore }
48295c635efSGarrett D'Amore 
48395c635efSGarrett D'Amore static int
48495c635efSGarrett D'Amore man_PP_pre(MAN_ARGS)
48595c635efSGarrett D'Amore {
48695c635efSGarrett D'Amore 
48795c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
48895c635efSGarrett D'Amore 		return(0);
48995c635efSGarrett D'Amore 	else if (MAN_BLOCK == n->type)
49095c635efSGarrett D'Amore 		print_bvspace(h, n);
49195c635efSGarrett D'Amore 
49295c635efSGarrett D'Amore 	return(1);
49395c635efSGarrett D'Amore }
49495c635efSGarrett D'Amore 
49595c635efSGarrett D'Amore static int
49695c635efSGarrett D'Amore man_IP_pre(MAN_ARGS)
49795c635efSGarrett D'Amore {
49895c635efSGarrett D'Amore 	const struct man_node	*nn;
49995c635efSGarrett D'Amore 
50095c635efSGarrett D'Amore 	if (MAN_BODY == n->type) {
50195c635efSGarrett D'Amore 		print_otag(h, TAG_DD, 0, NULL);
50295c635efSGarrett D'Amore 		return(1);
50395c635efSGarrett D'Amore 	} else if (MAN_HEAD != n->type) {
50495c635efSGarrett D'Amore 		print_otag(h, TAG_DL, 0, NULL);
50595c635efSGarrett D'Amore 		return(1);
50695c635efSGarrett D'Amore 	}
50795c635efSGarrett D'Amore 
50895c635efSGarrett D'Amore 	/* FIXME: width specification. */
50995c635efSGarrett D'Amore 
51095c635efSGarrett D'Amore 	print_otag(h, TAG_DT, 0, NULL);
51195c635efSGarrett D'Amore 
51295c635efSGarrett D'Amore 	/* For IP, only print the first header element. */
51395c635efSGarrett D'Amore 
51495c635efSGarrett D'Amore 	if (MAN_IP == n->tok && n->child)
515698f87a4SGarrett D'Amore 		print_man_node(man, n->child, mh, h);
51695c635efSGarrett D'Amore 
51795c635efSGarrett D'Amore 	/* For TP, only print next-line header elements. */
51895c635efSGarrett D'Amore 
519*260e9a87SYuri Pankov 	if (MAN_TP == n->tok) {
520*260e9a87SYuri Pankov 		nn = n->child;
521*260e9a87SYuri Pankov 		while (NULL != nn && 0 == (MAN_LINE & nn->flags))
522*260e9a87SYuri Pankov 			nn = nn->next;
523*260e9a87SYuri Pankov 		while (NULL != nn) {
524698f87a4SGarrett D'Amore 			print_man_node(man, nn, mh, h);
525*260e9a87SYuri Pankov 			nn = nn->next;
526*260e9a87SYuri Pankov 		}
527*260e9a87SYuri Pankov 	}
52895c635efSGarrett D'Amore 
52995c635efSGarrett D'Amore 	return(0);
53095c635efSGarrett D'Amore }
53195c635efSGarrett D'Amore 
53295c635efSGarrett D'Amore static int
53395c635efSGarrett D'Amore man_HP_pre(MAN_ARGS)
53495c635efSGarrett D'Amore {
535*260e9a87SYuri Pankov 	struct htmlpair	 tag[2];
53695c635efSGarrett D'Amore 	struct roffsu	 su;
53795c635efSGarrett D'Amore 	const struct man_node *np;
53895c635efSGarrett D'Amore 
53995c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
54095c635efSGarrett D'Amore 		return(0);
54195c635efSGarrett D'Amore 	else if (MAN_BLOCK != n->type)
54295c635efSGarrett D'Amore 		return(1);
54395c635efSGarrett D'Amore 
54495c635efSGarrett D'Amore 	np = n->head->child;
54595c635efSGarrett D'Amore 
54695c635efSGarrett D'Amore 	if (NULL == np || ! a2width(np, &su))
54795c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, INDENT);
54895c635efSGarrett D'Amore 
54995c635efSGarrett D'Amore 	bufinit(h);
55095c635efSGarrett D'Amore 
55195c635efSGarrett D'Amore 	print_bvspace(h, n);
55295c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
55395c635efSGarrett D'Amore 	su.scale = -su.scale;
55495c635efSGarrett D'Amore 	bufcat_su(h, "text-indent", &su);
555*260e9a87SYuri Pankov 	PAIR_STYLE_INIT(&tag[0], h);
556*260e9a87SYuri Pankov 	PAIR_CLASS_INIT(&tag[1], "spacer");
557*260e9a87SYuri Pankov 	print_otag(h, TAG_DIV, 2, tag);
55895c635efSGarrett D'Amore 	return(1);
55995c635efSGarrett D'Amore }
56095c635efSGarrett D'Amore 
56195c635efSGarrett D'Amore static int
56295c635efSGarrett D'Amore man_OP_pre(MAN_ARGS)
56395c635efSGarrett D'Amore {
56495c635efSGarrett D'Amore 	struct tag	*tt;
56595c635efSGarrett D'Amore 	struct htmlpair	 tag;
56695c635efSGarrett D'Amore 
56795c635efSGarrett D'Amore 	print_text(h, "[");
56895c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
56995c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "opt");
57095c635efSGarrett D'Amore 	tt = print_otag(h, TAG_SPAN, 1, &tag);
57195c635efSGarrett D'Amore 
57295c635efSGarrett D'Amore 	if (NULL != (n = n->child)) {
57395c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
57495c635efSGarrett D'Amore 		print_text(h, n->string);
57595c635efSGarrett D'Amore 	}
57695c635efSGarrett D'Amore 
57795c635efSGarrett D'Amore 	print_stagq(h, tt);
57895c635efSGarrett D'Amore 
57995c635efSGarrett D'Amore 	if (NULL != n && NULL != n->next) {
58095c635efSGarrett D'Amore 		print_otag(h, TAG_I, 0, NULL);
58195c635efSGarrett D'Amore 		print_text(h, n->next->string);
58295c635efSGarrett D'Amore 	}
58395c635efSGarrett D'Amore 
58495c635efSGarrett D'Amore 	print_stagq(h, tt);
58595c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
58695c635efSGarrett D'Amore 	print_text(h, "]");
58795c635efSGarrett D'Amore 	return(0);
58895c635efSGarrett D'Amore }
58995c635efSGarrett D'Amore 
59095c635efSGarrett D'Amore static int
59195c635efSGarrett D'Amore man_B_pre(MAN_ARGS)
59295c635efSGarrett D'Amore {
59395c635efSGarrett D'Amore 
59495c635efSGarrett D'Amore 	print_otag(h, TAG_B, 0, NULL);
59595c635efSGarrett D'Amore 	return(1);
59695c635efSGarrett D'Amore }
59795c635efSGarrett D'Amore 
59895c635efSGarrett D'Amore static int
59995c635efSGarrett D'Amore man_I_pre(MAN_ARGS)
60095c635efSGarrett D'Amore {
60195c635efSGarrett D'Amore 
60295c635efSGarrett D'Amore 	print_otag(h, TAG_I, 0, NULL);
60395c635efSGarrett D'Amore 	return(1);
60495c635efSGarrett D'Amore }
60595c635efSGarrett D'Amore 
60695c635efSGarrett D'Amore static int
60795c635efSGarrett D'Amore man_literal_pre(MAN_ARGS)
60895c635efSGarrett D'Amore {
60995c635efSGarrett D'Amore 
610698f87a4SGarrett D'Amore 	if (MAN_fi == n->tok || MAN_EE == n->tok) {
61195c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
61295c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
61395c635efSGarrett D'Amore 	} else
61495c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
61595c635efSGarrett D'Amore 
61695c635efSGarrett D'Amore 	return(0);
61795c635efSGarrett D'Amore }
61895c635efSGarrett D'Amore 
61995c635efSGarrett D'Amore static int
62095c635efSGarrett D'Amore man_in_pre(MAN_ARGS)
62195c635efSGarrett D'Amore {
62295c635efSGarrett D'Amore 
62395c635efSGarrett D'Amore 	print_otag(h, TAG_BR, 0, NULL);
62495c635efSGarrett D'Amore 	return(0);
62595c635efSGarrett D'Amore }
62695c635efSGarrett D'Amore 
62795c635efSGarrett D'Amore static int
62895c635efSGarrett D'Amore man_ign_pre(MAN_ARGS)
62995c635efSGarrett D'Amore {
63095c635efSGarrett D'Amore 
63195c635efSGarrett D'Amore 	return(0);
63295c635efSGarrett D'Amore }
63395c635efSGarrett D'Amore 
63495c635efSGarrett D'Amore static int
63595c635efSGarrett D'Amore man_RS_pre(MAN_ARGS)
63695c635efSGarrett D'Amore {
63795c635efSGarrett D'Amore 	struct htmlpair	 tag;
63895c635efSGarrett D'Amore 	struct roffsu	 su;
63995c635efSGarrett D'Amore 
64095c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
64195c635efSGarrett D'Amore 		return(0);
64295c635efSGarrett D'Amore 	else if (MAN_BODY == n->type)
64395c635efSGarrett D'Amore 		return(1);
64495c635efSGarrett D'Amore 
64595c635efSGarrett D'Amore 	SCALE_HS_INIT(&su, INDENT);
64695c635efSGarrett D'Amore 	if (n->head->child)
64795c635efSGarrett D'Amore 		a2width(n->head->child, &su);
64895c635efSGarrett D'Amore 
64995c635efSGarrett D'Amore 	bufinit(h);
65095c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
65195c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
65295c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
65395c635efSGarrett D'Amore 	return(1);
65495c635efSGarrett D'Amore }
655698f87a4SGarrett D'Amore 
656698f87a4SGarrett D'Amore static int
657698f87a4SGarrett D'Amore man_UR_pre(MAN_ARGS)
658698f87a4SGarrett D'Amore {
659698f87a4SGarrett D'Amore 	struct htmlpair		 tag[2];
660698f87a4SGarrett D'Amore 
661698f87a4SGarrett D'Amore 	n = n->child;
662698f87a4SGarrett D'Amore 	assert(MAN_HEAD == n->type);
663698f87a4SGarrett D'Amore 	if (n->nchild) {
664698f87a4SGarrett D'Amore 		assert(MAN_TEXT == n->child->type);
665698f87a4SGarrett D'Amore 		PAIR_CLASS_INIT(&tag[0], "link-ext");
666698f87a4SGarrett D'Amore 		PAIR_HREF_INIT(&tag[1], n->child->string);
667698f87a4SGarrett D'Amore 		print_otag(h, TAG_A, 2, tag);
668698f87a4SGarrett D'Amore 	}
669698f87a4SGarrett D'Amore 
670698f87a4SGarrett D'Amore 	assert(MAN_BODY == n->next->type);
671698f87a4SGarrett D'Amore 	if (n->next->nchild)
672698f87a4SGarrett D'Amore 		n = n->next;
673698f87a4SGarrett D'Amore 
674698f87a4SGarrett D'Amore 	print_man_nodelist(man, n->child, mh, h);
675698f87a4SGarrett D'Amore 
676698f87a4SGarrett D'Amore 	return(0);
677698f87a4SGarrett D'Amore }
678