xref: /titanic_52/usr/src/cmd/mandoc/man_html.c (revision 698f87a48e2e945bfe5493ce168e0d0ae1cedd5c)
1*698f87a4SGarrett D'Amore /*	$Id: man_html.c,v 1.90 2013/10/17 20:54:58 schwarze Exp $ */
295c635efSGarrett D'Amore /*
3*698f87a4SGarrett D'Amore  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
4*698f87a4SGarrett D'Amore  * Copyright (c) 2013 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 #ifdef HAVE_CONFIG_H
1995c635efSGarrett D'Amore #include "config.h"
2095c635efSGarrett D'Amore #endif
2195c635efSGarrett D'Amore 
2295c635efSGarrett D'Amore #include <sys/types.h>
2395c635efSGarrett D'Amore 
2495c635efSGarrett D'Amore #include <assert.h>
2595c635efSGarrett D'Amore #include <ctype.h>
2695c635efSGarrett D'Amore #include <stdio.h>
2795c635efSGarrett D'Amore #include <stdlib.h>
2895c635efSGarrett D'Amore #include <string.h>
2995c635efSGarrett D'Amore 
3095c635efSGarrett D'Amore #include "mandoc.h"
3195c635efSGarrett D'Amore #include "out.h"
3295c635efSGarrett D'Amore #include "html.h"
3395c635efSGarrett D'Amore #include "man.h"
3495c635efSGarrett D'Amore #include "main.h"
3595c635efSGarrett D'Amore 
3695c635efSGarrett D'Amore /* TODO: preserve ident widths. */
3795c635efSGarrett D'Amore /* FIXME: have PD set the default vspace width. */
3895c635efSGarrett D'Amore 
3995c635efSGarrett D'Amore #define	INDENT		  5
4095c635efSGarrett D'Amore 
41*698f87a4SGarrett D'Amore #define	MAN_ARGS	  const struct man_meta *man, \
4295c635efSGarrett D'Amore 			  const struct man_node *n, \
4395c635efSGarrett D'Amore 			  struct mhtml *mh, \
4495c635efSGarrett D'Amore 			  struct html *h
4595c635efSGarrett D'Amore 
4695c635efSGarrett D'Amore struct	mhtml {
4795c635efSGarrett D'Amore 	int		  fl;
4895c635efSGarrett D'Amore #define	MANH_LITERAL	 (1 << 0) /* literal context */
4995c635efSGarrett D'Amore };
5095c635efSGarrett D'Amore 
5195c635efSGarrett D'Amore struct	htmlman {
5295c635efSGarrett D'Amore 	int		(*pre)(MAN_ARGS);
5395c635efSGarrett D'Amore 	int		(*post)(MAN_ARGS);
5495c635efSGarrett D'Amore };
5595c635efSGarrett D'Amore 
5695c635efSGarrett D'Amore static	void		  print_bvspace(struct html *,
5795c635efSGarrett D'Amore 				const struct man_node *);
5895c635efSGarrett D'Amore static	void		  print_man(MAN_ARGS);
5995c635efSGarrett D'Amore static	void		  print_man_head(MAN_ARGS);
6095c635efSGarrett D'Amore static	void		  print_man_nodelist(MAN_ARGS);
6195c635efSGarrett D'Amore static	void		  print_man_node(MAN_ARGS);
6295c635efSGarrett D'Amore static	int		  a2width(const struct man_node *,
6395c635efSGarrett D'Amore 				struct roffsu *);
6495c635efSGarrett D'Amore static	int		  man_B_pre(MAN_ARGS);
6595c635efSGarrett D'Amore static	int		  man_HP_pre(MAN_ARGS);
6695c635efSGarrett D'Amore static	int		  man_IP_pre(MAN_ARGS);
6795c635efSGarrett D'Amore static	int		  man_I_pre(MAN_ARGS);
6895c635efSGarrett D'Amore static	int		  man_OP_pre(MAN_ARGS);
6995c635efSGarrett D'Amore static	int		  man_PP_pre(MAN_ARGS);
7095c635efSGarrett D'Amore static	int		  man_RS_pre(MAN_ARGS);
7195c635efSGarrett D'Amore static	int		  man_SH_pre(MAN_ARGS);
7295c635efSGarrett D'Amore static	int		  man_SM_pre(MAN_ARGS);
7395c635efSGarrett D'Amore static	int		  man_SS_pre(MAN_ARGS);
74*698f87a4SGarrett D'Amore static	int		  man_UR_pre(MAN_ARGS);
7595c635efSGarrett D'Amore static	int		  man_alt_pre(MAN_ARGS);
7695c635efSGarrett D'Amore static	int		  man_br_pre(MAN_ARGS);
7795c635efSGarrett D'Amore static	int		  man_ign_pre(MAN_ARGS);
7895c635efSGarrett D'Amore static	int		  man_in_pre(MAN_ARGS);
7995c635efSGarrett D'Amore static	int		  man_literal_pre(MAN_ARGS);
8095c635efSGarrett D'Amore static	void		  man_root_post(MAN_ARGS);
8195c635efSGarrett D'Amore static	void		  man_root_pre(MAN_ARGS);
8295c635efSGarrett D'Amore 
8395c635efSGarrett D'Amore static	const struct htmlman mans[MAN_MAX] = {
8495c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* br */
8595c635efSGarrett D'Amore 	{ NULL, NULL }, /* TH */
8695c635efSGarrett D'Amore 	{ man_SH_pre, NULL }, /* SH */
8795c635efSGarrett D'Amore 	{ man_SS_pre, NULL }, /* SS */
8895c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* TP */
8995c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* LP */
9095c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* PP */
9195c635efSGarrett D'Amore 	{ man_PP_pre, NULL }, /* P */
9295c635efSGarrett D'Amore 	{ man_IP_pre, NULL }, /* IP */
9395c635efSGarrett D'Amore 	{ man_HP_pre, NULL }, /* HP */
9495c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SM */
9595c635efSGarrett D'Amore 	{ man_SM_pre, NULL }, /* SB */
9695c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BI */
9795c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IB */
9895c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* BR */
9995c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RB */
10095c635efSGarrett D'Amore 	{ NULL, NULL }, /* R */
10195c635efSGarrett D'Amore 	{ man_B_pre, NULL }, /* B */
10295c635efSGarrett D'Amore 	{ man_I_pre, NULL }, /* I */
10395c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* IR */
10495c635efSGarrett D'Amore 	{ man_alt_pre, NULL }, /* RI */
10595c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* na */
10695c635efSGarrett D'Amore 	{ man_br_pre, NULL }, /* sp */
10795c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* nf */
10895c635efSGarrett D'Amore 	{ man_literal_pre, NULL }, /* fi */
10995c635efSGarrett D'Amore 	{ NULL, NULL }, /* RE */
11095c635efSGarrett D'Amore 	{ man_RS_pre, NULL }, /* RS */
11195c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* DT */
11295c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* UC */
11395c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* PD */
11495c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* AT */
11595c635efSGarrett D'Amore 	{ man_in_pre, NULL }, /* in */
11695c635efSGarrett D'Amore 	{ man_ign_pre, NULL }, /* ft */
11795c635efSGarrett D'Amore 	{ man_OP_pre, NULL }, /* OP */
118*698f87a4SGarrett D'Amore 	{ man_literal_pre, NULL }, /* EX */
119*698f87a4SGarrett D'Amore 	{ man_literal_pre, NULL }, /* EE */
120*698f87a4SGarrett D'Amore 	{ man_UR_pre, NULL }, /* UR */
121*698f87a4SGarrett D'Amore 	{ NULL, NULL }, /* UE */
12295c635efSGarrett D'Amore };
12395c635efSGarrett D'Amore 
12495c635efSGarrett D'Amore /*
12595c635efSGarrett D'Amore  * Printing leading vertical space before a block.
12695c635efSGarrett D'Amore  * This is used for the paragraph macros.
12795c635efSGarrett D'Amore  * The rules are pretty simple, since there's very little nesting going
12895c635efSGarrett D'Amore  * on here.  Basically, if we're the first within another block (SS/SH),
12995c635efSGarrett D'Amore  * then don't emit vertical space.  If we are (RS), then do.  If not the
13095c635efSGarrett D'Amore  * first, print it.
13195c635efSGarrett D'Amore  */
13295c635efSGarrett D'Amore static void
13395c635efSGarrett D'Amore print_bvspace(struct html *h, const struct man_node *n)
13495c635efSGarrett D'Amore {
13595c635efSGarrett D'Amore 
13695c635efSGarrett D'Amore 	if (n->body && n->body->child)
13795c635efSGarrett D'Amore 		if (MAN_TBL == n->body->child->type)
13895c635efSGarrett D'Amore 			return;
13995c635efSGarrett D'Amore 
14095c635efSGarrett D'Amore 	if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok)
14195c635efSGarrett D'Amore 		if (NULL == n->prev)
14295c635efSGarrett D'Amore 			return;
14395c635efSGarrett D'Amore 
14495c635efSGarrett D'Amore 	print_otag(h, TAG_P, 0, NULL);
14595c635efSGarrett D'Amore }
14695c635efSGarrett D'Amore 
14795c635efSGarrett D'Amore void
148*698f87a4SGarrett D'Amore html_man(void *arg, const struct man *man)
14995c635efSGarrett D'Amore {
15095c635efSGarrett D'Amore 	struct mhtml	 mh;
15195c635efSGarrett D'Amore 
15295c635efSGarrett D'Amore 	memset(&mh, 0, sizeof(struct mhtml));
153*698f87a4SGarrett D'Amore 	print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
15495c635efSGarrett D'Amore 	putchar('\n');
15595c635efSGarrett D'Amore }
15695c635efSGarrett D'Amore 
15795c635efSGarrett D'Amore static void
15895c635efSGarrett D'Amore print_man(MAN_ARGS)
15995c635efSGarrett D'Amore {
16095c635efSGarrett D'Amore 	struct tag	*t, *tt;
16195c635efSGarrett D'Amore 	struct htmlpair	 tag;
16295c635efSGarrett D'Amore 
16395c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "mandoc");
16495c635efSGarrett D'Amore 
16595c635efSGarrett D'Amore 	if ( ! (HTML_FRAGMENT & h->oflags)) {
16695c635efSGarrett D'Amore 		print_gen_decls(h);
16795c635efSGarrett D'Amore 		t = print_otag(h, TAG_HTML, 0, NULL);
16895c635efSGarrett D'Amore 		tt = print_otag(h, TAG_HEAD, 0, NULL);
169*698f87a4SGarrett D'Amore 		print_man_head(man, n, mh, h);
17095c635efSGarrett D'Amore 		print_tagq(h, tt);
17195c635efSGarrett D'Amore 		print_otag(h, TAG_BODY, 0, NULL);
17295c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
17395c635efSGarrett D'Amore 	} else
17495c635efSGarrett D'Amore 		t = print_otag(h, TAG_DIV, 1, &tag);
17595c635efSGarrett D'Amore 
176*698f87a4SGarrett D'Amore 	print_man_nodelist(man, n, mh, h);
17795c635efSGarrett D'Amore 	print_tagq(h, t);
17895c635efSGarrett D'Amore }
17995c635efSGarrett D'Amore 
18095c635efSGarrett D'Amore 
18195c635efSGarrett D'Amore /* ARGSUSED */
18295c635efSGarrett D'Amore static void
18395c635efSGarrett D'Amore print_man_head(MAN_ARGS)
18495c635efSGarrett D'Amore {
18595c635efSGarrett D'Amore 
18695c635efSGarrett D'Amore 	print_gen_head(h);
187*698f87a4SGarrett D'Amore 	assert(man->title);
188*698f87a4SGarrett D'Amore 	assert(man->msec);
189*698f87a4SGarrett D'Amore 	bufcat_fmt(h, "%s(%s)", man->title, man->msec);
19095c635efSGarrett D'Amore 	print_otag(h, TAG_TITLE, 0, NULL);
19195c635efSGarrett D'Amore 	print_text(h, h->buf);
19295c635efSGarrett D'Amore }
19395c635efSGarrett D'Amore 
19495c635efSGarrett D'Amore 
19595c635efSGarrett D'Amore static void
19695c635efSGarrett D'Amore print_man_nodelist(MAN_ARGS)
19795c635efSGarrett D'Amore {
19895c635efSGarrett D'Amore 
199*698f87a4SGarrett D'Amore 	print_man_node(man, n, mh, h);
20095c635efSGarrett D'Amore 	if (n->next)
201*698f87a4SGarrett D'Amore 		print_man_nodelist(man, n->next, mh, h);
20295c635efSGarrett D'Amore }
20395c635efSGarrett D'Amore 
20495c635efSGarrett D'Amore 
20595c635efSGarrett D'Amore static void
20695c635efSGarrett D'Amore print_man_node(MAN_ARGS)
20795c635efSGarrett D'Amore {
20895c635efSGarrett D'Amore 	int		 child;
20995c635efSGarrett D'Amore 	struct tag	*t;
21095c635efSGarrett D'Amore 
21195c635efSGarrett D'Amore 	child = 1;
21295c635efSGarrett D'Amore 	t = h->tags.head;
21395c635efSGarrett D'Amore 
21495c635efSGarrett D'Amore 	switch (n->type) {
21595c635efSGarrett D'Amore 	case (MAN_ROOT):
216*698f87a4SGarrett D'Amore 		man_root_pre(man, n, mh, h);
21795c635efSGarrett D'Amore 		break;
21895c635efSGarrett D'Amore 	case (MAN_TEXT):
21995c635efSGarrett D'Amore 		/*
22095c635efSGarrett D'Amore 		 * If we have a blank line, output a vertical space.
22195c635efSGarrett D'Amore 		 * If we have a space as the first character, break
22295c635efSGarrett D'Amore 		 * before printing the line's data.
22395c635efSGarrett D'Amore 		 */
22495c635efSGarrett D'Amore 		if ('\0' == *n->string) {
22595c635efSGarrett D'Amore 			print_otag(h, TAG_P, 0, NULL);
22695c635efSGarrett D'Amore 			return;
22795c635efSGarrett D'Amore 		}
22895c635efSGarrett D'Amore 
22995c635efSGarrett D'Amore 		if (' ' == *n->string && MAN_LINE & n->flags)
23095c635efSGarrett D'Amore 			print_otag(h, TAG_BR, 0, NULL);
23195c635efSGarrett D'Amore 		else if (MANH_LITERAL & mh->fl && n->prev)
23295c635efSGarrett D'Amore 			print_otag(h, TAG_BR, 0, NULL);
23395c635efSGarrett D'Amore 
23495c635efSGarrett D'Amore 		print_text(h, n->string);
23595c635efSGarrett D'Amore 		return;
23695c635efSGarrett D'Amore 	case (MAN_EQN):
23795c635efSGarrett D'Amore 		print_eqn(h, n->eqn);
23895c635efSGarrett D'Amore 		break;
23995c635efSGarrett D'Amore 	case (MAN_TBL):
24095c635efSGarrett D'Amore 		/*
24195c635efSGarrett D'Amore 		 * This will take care of initialising all of the table
24295c635efSGarrett D'Amore 		 * state data for the first table, then tearing it down
24395c635efSGarrett D'Amore 		 * for the last one.
24495c635efSGarrett D'Amore 		 */
24595c635efSGarrett D'Amore 		print_tbl(h, n->span);
24695c635efSGarrett D'Amore 		return;
24795c635efSGarrett D'Amore 	default:
24895c635efSGarrett D'Amore 		/*
24995c635efSGarrett D'Amore 		 * Close out scope of font prior to opening a macro
25095c635efSGarrett D'Amore 		 * scope.
25195c635efSGarrett D'Amore 		 */
25295c635efSGarrett D'Amore 		if (HTMLFONT_NONE != h->metac) {
25395c635efSGarrett D'Amore 			h->metal = h->metac;
25495c635efSGarrett D'Amore 			h->metac = HTMLFONT_NONE;
25595c635efSGarrett D'Amore 		}
25695c635efSGarrett D'Amore 
25795c635efSGarrett D'Amore 		/*
25895c635efSGarrett D'Amore 		 * Close out the current table, if it's open, and unset
25995c635efSGarrett D'Amore 		 * the "meta" table state.  This will be reopened on the
26095c635efSGarrett D'Amore 		 * next table element.
26195c635efSGarrett D'Amore 		 */
26295c635efSGarrett D'Amore 		if (h->tblt) {
26395c635efSGarrett D'Amore 			print_tblclose(h);
26495c635efSGarrett D'Amore 			t = h->tags.head;
26595c635efSGarrett D'Amore 		}
26695c635efSGarrett D'Amore 		if (mans[n->tok].pre)
267*698f87a4SGarrett D'Amore 			child = (*mans[n->tok].pre)(man, n, mh, h);
26895c635efSGarrett D'Amore 		break;
26995c635efSGarrett D'Amore 	}
27095c635efSGarrett D'Amore 
27195c635efSGarrett D'Amore 	if (child && n->child)
272*698f87a4SGarrett D'Amore 		print_man_nodelist(man, n->child, mh, h);
27395c635efSGarrett D'Amore 
27495c635efSGarrett D'Amore 	/* This will automatically close out any font scope. */
27595c635efSGarrett D'Amore 	print_stagq(h, t);
27695c635efSGarrett D'Amore 
27795c635efSGarrett D'Amore 	switch (n->type) {
27895c635efSGarrett D'Amore 	case (MAN_ROOT):
279*698f87a4SGarrett D'Amore 		man_root_post(man, n, mh, h);
28095c635efSGarrett D'Amore 		break;
28195c635efSGarrett D'Amore 	case (MAN_EQN):
28295c635efSGarrett D'Amore 		break;
28395c635efSGarrett D'Amore 	default:
28495c635efSGarrett D'Amore 		if (mans[n->tok].post)
285*698f87a4SGarrett D'Amore 			(*mans[n->tok].post)(man, n, mh, h);
28695c635efSGarrett D'Amore 		break;
28795c635efSGarrett D'Amore 	}
28895c635efSGarrett D'Amore }
28995c635efSGarrett D'Amore 
29095c635efSGarrett D'Amore 
29195c635efSGarrett D'Amore static int
29295c635efSGarrett D'Amore a2width(const struct man_node *n, struct roffsu *su)
29395c635efSGarrett D'Amore {
29495c635efSGarrett D'Amore 
29595c635efSGarrett D'Amore 	if (MAN_TEXT != n->type)
29695c635efSGarrett D'Amore 		return(0);
29795c635efSGarrett D'Amore 	if (a2roffsu(n->string, su, SCALE_BU))
29895c635efSGarrett D'Amore 		return(1);
29995c635efSGarrett D'Amore 
30095c635efSGarrett D'Amore 	return(0);
30195c635efSGarrett D'Amore }
30295c635efSGarrett D'Amore 
30395c635efSGarrett D'Amore 
30495c635efSGarrett D'Amore /* ARGSUSED */
30595c635efSGarrett D'Amore static void
30695c635efSGarrett D'Amore man_root_pre(MAN_ARGS)
30795c635efSGarrett D'Amore {
30895c635efSGarrett D'Amore 	struct htmlpair	 tag[3];
30995c635efSGarrett D'Amore 	struct tag	*t, *tt;
31095c635efSGarrett D'Amore 	char		 b[BUFSIZ], title[BUFSIZ];
31195c635efSGarrett D'Amore 
31295c635efSGarrett D'Amore 	b[0] = 0;
313*698f87a4SGarrett D'Amore 	if (man->vol)
314*698f87a4SGarrett D'Amore 		(void)strlcat(b, man->vol, BUFSIZ);
31595c635efSGarrett D'Amore 
316*698f87a4SGarrett D'Amore 	assert(man->title);
317*698f87a4SGarrett D'Amore 	assert(man->msec);
318*698f87a4SGarrett D'Amore 	snprintf(title, BUFSIZ - 1, "%s(%s)", man->title, man->msec);
31995c635efSGarrett D'Amore 
32095c635efSGarrett D'Amore 	PAIR_SUMMARY_INIT(&tag[0], "Document Header");
32195c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[1], "head");
32295c635efSGarrett D'Amore 	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
32395c635efSGarrett D'Amore 	t = print_otag(h, TAG_TABLE, 3, tag);
32495c635efSGarrett D'Amore 	PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
32595c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
32695c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
32795c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
32895c635efSGarrett D'Amore 
32995c635efSGarrett D'Amore 	print_otag(h, TAG_TBODY, 0, NULL);
33095c635efSGarrett D'Amore 
33195c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
33295c635efSGarrett D'Amore 
33395c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-ltitle");
33495c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 1, tag);
33595c635efSGarrett D'Amore 	print_text(h, title);
33695c635efSGarrett D'Amore 	print_stagq(h, tt);
33795c635efSGarrett D'Amore 
33895c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-vol");
33995c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
34095c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
34195c635efSGarrett D'Amore 	print_text(h, b);
34295c635efSGarrett D'Amore 	print_stagq(h, tt);
34395c635efSGarrett D'Amore 
34495c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "head-rtitle");
34595c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
34695c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
34795c635efSGarrett D'Amore 	print_text(h, title);
34895c635efSGarrett D'Amore 	print_tagq(h, t);
34995c635efSGarrett D'Amore }
35095c635efSGarrett D'Amore 
35195c635efSGarrett D'Amore 
35295c635efSGarrett D'Amore /* ARGSUSED */
35395c635efSGarrett D'Amore static void
35495c635efSGarrett D'Amore man_root_post(MAN_ARGS)
35595c635efSGarrett D'Amore {
35695c635efSGarrett D'Amore 	struct htmlpair	 tag[3];
35795c635efSGarrett D'Amore 	struct tag	*t, *tt;
35895c635efSGarrett D'Amore 
35995c635efSGarrett D'Amore 	PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
36095c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[1], "foot");
36195c635efSGarrett D'Amore 	PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
36295c635efSGarrett D'Amore 	t = print_otag(h, TAG_TABLE, 3, tag);
36395c635efSGarrett D'Amore 	PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
36495c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
36595c635efSGarrett D'Amore 	print_otag(h, TAG_COL, 1, tag);
36695c635efSGarrett D'Amore 
36795c635efSGarrett D'Amore 	tt = print_otag(h, TAG_TR, 0, NULL);
36895c635efSGarrett D'Amore 
36995c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "foot-date");
37095c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 1, tag);
37195c635efSGarrett D'Amore 
372*698f87a4SGarrett D'Amore 	assert(man->date);
373*698f87a4SGarrett D'Amore 	print_text(h, man->date);
37495c635efSGarrett D'Amore 	print_stagq(h, tt);
37595c635efSGarrett D'Amore 
37695c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag[0], "foot-os");
37795c635efSGarrett D'Amore 	PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
37895c635efSGarrett D'Amore 	print_otag(h, TAG_TD, 2, tag);
37995c635efSGarrett D'Amore 
380*698f87a4SGarrett D'Amore 	if (man->source)
381*698f87a4SGarrett D'Amore 		print_text(h, man->source);
38295c635efSGarrett D'Amore 	print_tagq(h, t);
38395c635efSGarrett D'Amore }
38495c635efSGarrett D'Amore 
38595c635efSGarrett D'Amore 
38695c635efSGarrett D'Amore /* ARGSUSED */
38795c635efSGarrett D'Amore static int
38895c635efSGarrett D'Amore man_br_pre(MAN_ARGS)
38995c635efSGarrett D'Amore {
39095c635efSGarrett D'Amore 	struct roffsu	 su;
39195c635efSGarrett D'Amore 	struct htmlpair	 tag;
39295c635efSGarrett D'Amore 
39395c635efSGarrett D'Amore 	SCALE_VS_INIT(&su, 1);
39495c635efSGarrett D'Amore 
39595c635efSGarrett D'Amore 	if (MAN_sp == n->tok) {
39695c635efSGarrett D'Amore 		if (NULL != (n = n->child))
39795c635efSGarrett D'Amore 			if ( ! a2roffsu(n->string, &su, SCALE_VS))
39895c635efSGarrett D'Amore 				SCALE_VS_INIT(&su, atoi(n->string));
39995c635efSGarrett D'Amore 	} else
40095c635efSGarrett D'Amore 		su.scale = 0;
40195c635efSGarrett D'Amore 
40295c635efSGarrett D'Amore 	bufinit(h);
40395c635efSGarrett D'Amore 	bufcat_su(h, "height", &su);
40495c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
40595c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
40695c635efSGarrett D'Amore 
40795c635efSGarrett D'Amore 	/* So the div isn't empty: */
40895c635efSGarrett D'Amore 	print_text(h, "\\~");
40995c635efSGarrett D'Amore 
41095c635efSGarrett D'Amore 	return(0);
41195c635efSGarrett D'Amore }
41295c635efSGarrett D'Amore 
41395c635efSGarrett D'Amore /* ARGSUSED */
41495c635efSGarrett D'Amore static int
41595c635efSGarrett D'Amore man_SH_pre(MAN_ARGS)
41695c635efSGarrett D'Amore {
41795c635efSGarrett D'Amore 	struct htmlpair	 tag;
41895c635efSGarrett D'Amore 
41995c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
42095c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
42195c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "section");
42295c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
42395c635efSGarrett D'Amore 		return(1);
42495c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
42595c635efSGarrett D'Amore 		return(1);
42695c635efSGarrett D'Amore 
42795c635efSGarrett D'Amore 	print_otag(h, TAG_H1, 0, NULL);
42895c635efSGarrett D'Amore 	return(1);
42995c635efSGarrett D'Amore }
43095c635efSGarrett D'Amore 
43195c635efSGarrett D'Amore /* ARGSUSED */
43295c635efSGarrett D'Amore static int
43395c635efSGarrett D'Amore man_alt_pre(MAN_ARGS)
43495c635efSGarrett D'Amore {
43595c635efSGarrett D'Amore 	const struct man_node	*nn;
43695c635efSGarrett D'Amore 	int		 i, savelit;
43795c635efSGarrett D'Amore 	enum htmltag	 fp;
43895c635efSGarrett D'Amore 	struct tag	*t;
43995c635efSGarrett D'Amore 
44095c635efSGarrett D'Amore 	if ((savelit = mh->fl & MANH_LITERAL))
44195c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
44295c635efSGarrett D'Amore 
44395c635efSGarrett D'Amore 	mh->fl &= ~MANH_LITERAL;
44495c635efSGarrett D'Amore 
44595c635efSGarrett D'Amore 	for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
44695c635efSGarrett D'Amore 		t = NULL;
44795c635efSGarrett D'Amore 		switch (n->tok) {
44895c635efSGarrett D'Amore 		case (MAN_BI):
44995c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_B;
45095c635efSGarrett D'Amore 			break;
45195c635efSGarrett D'Amore 		case (MAN_IB):
45295c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_I;
45395c635efSGarrett D'Amore 			break;
45495c635efSGarrett D'Amore 		case (MAN_RI):
45595c635efSGarrett D'Amore 			fp = i % 2 ? TAG_I : TAG_MAX;
45695c635efSGarrett D'Amore 			break;
45795c635efSGarrett D'Amore 		case (MAN_IR):
45895c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_I;
45995c635efSGarrett D'Amore 			break;
46095c635efSGarrett D'Amore 		case (MAN_BR):
46195c635efSGarrett D'Amore 			fp = i % 2 ? TAG_MAX : TAG_B;
46295c635efSGarrett D'Amore 			break;
46395c635efSGarrett D'Amore 		case (MAN_RB):
46495c635efSGarrett D'Amore 			fp = i % 2 ? TAG_B : TAG_MAX;
46595c635efSGarrett D'Amore 			break;
46695c635efSGarrett D'Amore 		default:
46795c635efSGarrett D'Amore 			abort();
46895c635efSGarrett D'Amore 			/* NOTREACHED */
46995c635efSGarrett D'Amore 		}
47095c635efSGarrett D'Amore 
47195c635efSGarrett D'Amore 		if (i)
47295c635efSGarrett D'Amore 			h->flags |= HTML_NOSPACE;
47395c635efSGarrett D'Amore 
47495c635efSGarrett D'Amore 		if (TAG_MAX != fp)
47595c635efSGarrett D'Amore 			t = print_otag(h, fp, 0, NULL);
47695c635efSGarrett D'Amore 
477*698f87a4SGarrett D'Amore 		print_man_node(man, nn, mh, h);
47895c635efSGarrett D'Amore 
47995c635efSGarrett D'Amore 		if (t)
48095c635efSGarrett D'Amore 			print_tagq(h, t);
48195c635efSGarrett D'Amore 	}
48295c635efSGarrett D'Amore 
48395c635efSGarrett D'Amore 	if (savelit)
48495c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
48595c635efSGarrett D'Amore 
48695c635efSGarrett D'Amore 	return(0);
48795c635efSGarrett D'Amore }
48895c635efSGarrett D'Amore 
48995c635efSGarrett D'Amore /* ARGSUSED */
49095c635efSGarrett D'Amore static int
49195c635efSGarrett D'Amore man_SM_pre(MAN_ARGS)
49295c635efSGarrett D'Amore {
49395c635efSGarrett D'Amore 
49495c635efSGarrett D'Amore 	print_otag(h, TAG_SMALL, 0, NULL);
49595c635efSGarrett D'Amore 	if (MAN_SB == n->tok)
49695c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
49795c635efSGarrett D'Amore 	return(1);
49895c635efSGarrett D'Amore }
49995c635efSGarrett D'Amore 
50095c635efSGarrett D'Amore /* ARGSUSED */
50195c635efSGarrett D'Amore static int
50295c635efSGarrett D'Amore man_SS_pre(MAN_ARGS)
50395c635efSGarrett D'Amore {
50495c635efSGarrett D'Amore 	struct htmlpair	 tag;
50595c635efSGarrett D'Amore 
50695c635efSGarrett D'Amore 	if (MAN_BLOCK == n->type) {
50795c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
50895c635efSGarrett D'Amore 		PAIR_CLASS_INIT(&tag, "subsection");
50995c635efSGarrett D'Amore 		print_otag(h, TAG_DIV, 1, &tag);
51095c635efSGarrett D'Amore 		return(1);
51195c635efSGarrett D'Amore 	} else if (MAN_BODY == n->type)
51295c635efSGarrett D'Amore 		return(1);
51395c635efSGarrett D'Amore 
51495c635efSGarrett D'Amore 	print_otag(h, TAG_H2, 0, NULL);
51595c635efSGarrett D'Amore 	return(1);
51695c635efSGarrett D'Amore }
51795c635efSGarrett D'Amore 
51895c635efSGarrett D'Amore /* ARGSUSED */
51995c635efSGarrett D'Amore static int
52095c635efSGarrett D'Amore man_PP_pre(MAN_ARGS)
52195c635efSGarrett D'Amore {
52295c635efSGarrett D'Amore 
52395c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
52495c635efSGarrett D'Amore 		return(0);
52595c635efSGarrett D'Amore 	else if (MAN_BLOCK == n->type)
52695c635efSGarrett D'Amore 		print_bvspace(h, n);
52795c635efSGarrett D'Amore 
52895c635efSGarrett D'Amore 	return(1);
52995c635efSGarrett D'Amore }
53095c635efSGarrett D'Amore 
53195c635efSGarrett D'Amore /* ARGSUSED */
53295c635efSGarrett D'Amore static int
53395c635efSGarrett D'Amore man_IP_pre(MAN_ARGS)
53495c635efSGarrett D'Amore {
53595c635efSGarrett D'Amore 	const struct man_node	*nn;
53695c635efSGarrett D'Amore 
53795c635efSGarrett D'Amore 	if (MAN_BODY == n->type) {
53895c635efSGarrett D'Amore 		print_otag(h, TAG_DD, 0, NULL);
53995c635efSGarrett D'Amore 		return(1);
54095c635efSGarrett D'Amore 	} else if (MAN_HEAD != n->type) {
54195c635efSGarrett D'Amore 		print_otag(h, TAG_DL, 0, NULL);
54295c635efSGarrett D'Amore 		return(1);
54395c635efSGarrett D'Amore 	}
54495c635efSGarrett D'Amore 
54595c635efSGarrett D'Amore 	/* FIXME: width specification. */
54695c635efSGarrett D'Amore 
54795c635efSGarrett D'Amore 	print_otag(h, TAG_DT, 0, NULL);
54895c635efSGarrett D'Amore 
54995c635efSGarrett D'Amore 	/* For IP, only print the first header element. */
55095c635efSGarrett D'Amore 
55195c635efSGarrett D'Amore 	if (MAN_IP == n->tok && n->child)
552*698f87a4SGarrett D'Amore 		print_man_node(man, n->child, mh, h);
55395c635efSGarrett D'Amore 
55495c635efSGarrett D'Amore 	/* For TP, only print next-line header elements. */
55595c635efSGarrett D'Amore 
55695c635efSGarrett D'Amore 	if (MAN_TP == n->tok)
55795c635efSGarrett D'Amore 		for (nn = n->child; nn; nn = nn->next)
55895c635efSGarrett D'Amore 			if (nn->line > n->line)
559*698f87a4SGarrett D'Amore 				print_man_node(man, nn, mh, h);
56095c635efSGarrett D'Amore 
56195c635efSGarrett D'Amore 	return(0);
56295c635efSGarrett D'Amore }
56395c635efSGarrett D'Amore 
56495c635efSGarrett D'Amore /* ARGSUSED */
56595c635efSGarrett D'Amore static int
56695c635efSGarrett D'Amore man_HP_pre(MAN_ARGS)
56795c635efSGarrett D'Amore {
56895c635efSGarrett D'Amore 	struct htmlpair	 tag;
56995c635efSGarrett D'Amore 	struct roffsu	 su;
57095c635efSGarrett D'Amore 	const struct man_node *np;
57195c635efSGarrett D'Amore 
57295c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
57395c635efSGarrett D'Amore 		return(0);
57495c635efSGarrett D'Amore 	else if (MAN_BLOCK != n->type)
57595c635efSGarrett D'Amore 		return(1);
57695c635efSGarrett D'Amore 
57795c635efSGarrett D'Amore 	np = n->head->child;
57895c635efSGarrett D'Amore 
57995c635efSGarrett D'Amore 	if (NULL == np || ! a2width(np, &su))
58095c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, INDENT);
58195c635efSGarrett D'Amore 
58295c635efSGarrett D'Amore 	bufinit(h);
58395c635efSGarrett D'Amore 
58495c635efSGarrett D'Amore 	print_bvspace(h, n);
58595c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
58695c635efSGarrett D'Amore 	su.scale = -su.scale;
58795c635efSGarrett D'Amore 	bufcat_su(h, "text-indent", &su);
58895c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
58995c635efSGarrett D'Amore 	print_otag(h, TAG_P, 1, &tag);
59095c635efSGarrett D'Amore 	return(1);
59195c635efSGarrett D'Amore }
59295c635efSGarrett D'Amore 
59395c635efSGarrett D'Amore /* ARGSUSED */
59495c635efSGarrett D'Amore static int
59595c635efSGarrett D'Amore man_OP_pre(MAN_ARGS)
59695c635efSGarrett D'Amore {
59795c635efSGarrett D'Amore 	struct tag	*tt;
59895c635efSGarrett D'Amore 	struct htmlpair	 tag;
59995c635efSGarrett D'Amore 
60095c635efSGarrett D'Amore 	print_text(h, "[");
60195c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
60295c635efSGarrett D'Amore 	PAIR_CLASS_INIT(&tag, "opt");
60395c635efSGarrett D'Amore 	tt = print_otag(h, TAG_SPAN, 1, &tag);
60495c635efSGarrett D'Amore 
60595c635efSGarrett D'Amore 	if (NULL != (n = n->child)) {
60695c635efSGarrett D'Amore 		print_otag(h, TAG_B, 0, NULL);
60795c635efSGarrett D'Amore 		print_text(h, n->string);
60895c635efSGarrett D'Amore 	}
60995c635efSGarrett D'Amore 
61095c635efSGarrett D'Amore 	print_stagq(h, tt);
61195c635efSGarrett D'Amore 
61295c635efSGarrett D'Amore 	if (NULL != n && NULL != n->next) {
61395c635efSGarrett D'Amore 		print_otag(h, TAG_I, 0, NULL);
61495c635efSGarrett D'Amore 		print_text(h, n->next->string);
61595c635efSGarrett D'Amore 	}
61695c635efSGarrett D'Amore 
61795c635efSGarrett D'Amore 	print_stagq(h, tt);
61895c635efSGarrett D'Amore 	h->flags |= HTML_NOSPACE;
61995c635efSGarrett D'Amore 	print_text(h, "]");
62095c635efSGarrett D'Amore 	return(0);
62195c635efSGarrett D'Amore }
62295c635efSGarrett D'Amore 
62395c635efSGarrett D'Amore 
62495c635efSGarrett D'Amore /* ARGSUSED */
62595c635efSGarrett D'Amore static int
62695c635efSGarrett D'Amore man_B_pre(MAN_ARGS)
62795c635efSGarrett D'Amore {
62895c635efSGarrett D'Amore 
62995c635efSGarrett D'Amore 	print_otag(h, TAG_B, 0, NULL);
63095c635efSGarrett D'Amore 	return(1);
63195c635efSGarrett D'Amore }
63295c635efSGarrett D'Amore 
63395c635efSGarrett D'Amore /* ARGSUSED */
63495c635efSGarrett D'Amore static int
63595c635efSGarrett D'Amore man_I_pre(MAN_ARGS)
63695c635efSGarrett D'Amore {
63795c635efSGarrett D'Amore 
63895c635efSGarrett D'Amore 	print_otag(h, TAG_I, 0, NULL);
63995c635efSGarrett D'Amore 	return(1);
64095c635efSGarrett D'Amore }
64195c635efSGarrett D'Amore 
64295c635efSGarrett D'Amore /* ARGSUSED */
64395c635efSGarrett D'Amore static int
64495c635efSGarrett D'Amore man_literal_pre(MAN_ARGS)
64595c635efSGarrett D'Amore {
64695c635efSGarrett D'Amore 
647*698f87a4SGarrett D'Amore 	if (MAN_fi == n->tok || MAN_EE == n->tok) {
64895c635efSGarrett D'Amore 		print_otag(h, TAG_BR, 0, NULL);
64995c635efSGarrett D'Amore 		mh->fl &= ~MANH_LITERAL;
65095c635efSGarrett D'Amore 	} else
65195c635efSGarrett D'Amore 		mh->fl |= MANH_LITERAL;
65295c635efSGarrett D'Amore 
65395c635efSGarrett D'Amore 	return(0);
65495c635efSGarrett D'Amore }
65595c635efSGarrett D'Amore 
65695c635efSGarrett D'Amore /* ARGSUSED */
65795c635efSGarrett D'Amore static int
65895c635efSGarrett D'Amore man_in_pre(MAN_ARGS)
65995c635efSGarrett D'Amore {
66095c635efSGarrett D'Amore 
66195c635efSGarrett D'Amore 	print_otag(h, TAG_BR, 0, NULL);
66295c635efSGarrett D'Amore 	return(0);
66395c635efSGarrett D'Amore }
66495c635efSGarrett D'Amore 
66595c635efSGarrett D'Amore /* ARGSUSED */
66695c635efSGarrett D'Amore static int
66795c635efSGarrett D'Amore man_ign_pre(MAN_ARGS)
66895c635efSGarrett D'Amore {
66995c635efSGarrett D'Amore 
67095c635efSGarrett D'Amore 	return(0);
67195c635efSGarrett D'Amore }
67295c635efSGarrett D'Amore 
67395c635efSGarrett D'Amore /* ARGSUSED */
67495c635efSGarrett D'Amore static int
67595c635efSGarrett D'Amore man_RS_pre(MAN_ARGS)
67695c635efSGarrett D'Amore {
67795c635efSGarrett D'Amore 	struct htmlpair	 tag;
67895c635efSGarrett D'Amore 	struct roffsu	 su;
67995c635efSGarrett D'Amore 
68095c635efSGarrett D'Amore 	if (MAN_HEAD == n->type)
68195c635efSGarrett D'Amore 		return(0);
68295c635efSGarrett D'Amore 	else if (MAN_BODY == n->type)
68395c635efSGarrett D'Amore 		return(1);
68495c635efSGarrett D'Amore 
68595c635efSGarrett D'Amore 	SCALE_HS_INIT(&su, INDENT);
68695c635efSGarrett D'Amore 	if (n->head->child)
68795c635efSGarrett D'Amore 		a2width(n->head->child, &su);
68895c635efSGarrett D'Amore 
68995c635efSGarrett D'Amore 	bufinit(h);
69095c635efSGarrett D'Amore 	bufcat_su(h, "margin-left", &su);
69195c635efSGarrett D'Amore 	PAIR_STYLE_INIT(&tag, h);
69295c635efSGarrett D'Amore 	print_otag(h, TAG_DIV, 1, &tag);
69395c635efSGarrett D'Amore 	return(1);
69495c635efSGarrett D'Amore }
695*698f87a4SGarrett D'Amore 
696*698f87a4SGarrett D'Amore /* ARGSUSED */
697*698f87a4SGarrett D'Amore static int
698*698f87a4SGarrett D'Amore man_UR_pre(MAN_ARGS)
699*698f87a4SGarrett D'Amore {
700*698f87a4SGarrett D'Amore 	struct htmlpair		 tag[2];
701*698f87a4SGarrett D'Amore 
702*698f87a4SGarrett D'Amore 	n = n->child;
703*698f87a4SGarrett D'Amore 	assert(MAN_HEAD == n->type);
704*698f87a4SGarrett D'Amore 	if (n->nchild) {
705*698f87a4SGarrett D'Amore 		assert(MAN_TEXT == n->child->type);
706*698f87a4SGarrett D'Amore 		PAIR_CLASS_INIT(&tag[0], "link-ext");
707*698f87a4SGarrett D'Amore 		PAIR_HREF_INIT(&tag[1], n->child->string);
708*698f87a4SGarrett D'Amore 		print_otag(h, TAG_A, 2, tag);
709*698f87a4SGarrett D'Amore 	}
710*698f87a4SGarrett D'Amore 
711*698f87a4SGarrett D'Amore 	assert(MAN_BODY == n->next->type);
712*698f87a4SGarrett D'Amore 	if (n->next->nchild)
713*698f87a4SGarrett D'Amore 		n = n->next;
714*698f87a4SGarrett D'Amore 
715*698f87a4SGarrett D'Amore 	print_man_nodelist(man, n->child, mh, h);
716*698f87a4SGarrett D'Amore 
717*698f87a4SGarrett D'Amore 	return(0);
718*698f87a4SGarrett D'Amore }
719