xref: /titanic_44/usr/src/cmd/mandoc/mdoc_term.c (revision 698f87a48e2e945bfe5493ce168e0d0ae1cedd5c)
1*698f87a4SGarrett D'Amore /*	$Id: mdoc_term.c,v 1.258 2013/12/25 21:24:12 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*698f87a4SGarrett D'Amore  * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5*698f87a4SGarrett D'Amore  * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
695c635efSGarrett D'Amore  *
795c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
895c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
995c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
1095c635efSGarrett D'Amore  *
1195c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1295c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1395c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1495c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1595c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1695c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1795c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1895c635efSGarrett D'Amore  */
1995c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H
2095c635efSGarrett D'Amore #include "config.h"
2195c635efSGarrett D'Amore #endif
2295c635efSGarrett D'Amore 
2395c635efSGarrett D'Amore #include <sys/types.h>
2495c635efSGarrett D'Amore 
2595c635efSGarrett D'Amore #include <assert.h>
2695c635efSGarrett D'Amore #include <ctype.h>
2795c635efSGarrett D'Amore #include <stdint.h>
2895c635efSGarrett D'Amore #include <stdio.h>
2995c635efSGarrett D'Amore #include <stdlib.h>
3095c635efSGarrett D'Amore #include <string.h>
3195c635efSGarrett D'Amore 
3295c635efSGarrett D'Amore #include "mandoc.h"
3395c635efSGarrett D'Amore #include "out.h"
3495c635efSGarrett D'Amore #include "term.h"
3595c635efSGarrett D'Amore #include "mdoc.h"
3695c635efSGarrett D'Amore #include "main.h"
3795c635efSGarrett D'Amore 
3895c635efSGarrett D'Amore struct	termpair {
3995c635efSGarrett D'Amore 	struct termpair	 *ppair;
4095c635efSGarrett D'Amore 	int		  count;
4195c635efSGarrett D'Amore };
4295c635efSGarrett D'Amore 
4395c635efSGarrett D'Amore #define	DECL_ARGS struct termp *p, \
4495c635efSGarrett D'Amore 		  struct termpair *pair, \
45*698f87a4SGarrett D'Amore 	  	  const struct mdoc_meta *meta, \
46*698f87a4SGarrett D'Amore 		  struct mdoc_node *n
4795c635efSGarrett D'Amore 
4895c635efSGarrett D'Amore struct	termact {
4995c635efSGarrett D'Amore 	int	(*pre)(DECL_ARGS);
5095c635efSGarrett D'Amore 	void	(*post)(DECL_ARGS);
5195c635efSGarrett D'Amore };
5295c635efSGarrett D'Amore 
5395c635efSGarrett D'Amore static	size_t	  a2width(const struct termp *, const char *);
5495c635efSGarrett D'Amore static	size_t	  a2height(const struct termp *, const char *);
5595c635efSGarrett D'Amore static	size_t	  a2offs(const struct termp *, const char *);
5695c635efSGarrett D'Amore 
5795c635efSGarrett D'Amore static	void	  print_bvspace(struct termp *,
5895c635efSGarrett D'Amore 			const struct mdoc_node *,
5995c635efSGarrett D'Amore 			const struct mdoc_node *);
6095c635efSGarrett D'Amore static	void  	  print_mdoc_node(DECL_ARGS);
6195c635efSGarrett D'Amore static	void	  print_mdoc_nodelist(DECL_ARGS);
6295c635efSGarrett D'Amore static	void	  print_mdoc_head(struct termp *, const void *);
6395c635efSGarrett D'Amore static	void	  print_mdoc_foot(struct termp *, const void *);
6495c635efSGarrett D'Amore static	void	  synopsis_pre(struct termp *,
6595c635efSGarrett D'Amore 			const struct mdoc_node *);
6695c635efSGarrett D'Amore 
6795c635efSGarrett D'Amore static	void	  termp____post(DECL_ARGS);
6895c635efSGarrett D'Amore static	void	  termp__t_post(DECL_ARGS);
6995c635efSGarrett D'Amore static	void	  termp_an_post(DECL_ARGS);
7095c635efSGarrett D'Amore static	void	  termp_bd_post(DECL_ARGS);
7195c635efSGarrett D'Amore static	void	  termp_bk_post(DECL_ARGS);
7295c635efSGarrett D'Amore static	void	  termp_bl_post(DECL_ARGS);
73*698f87a4SGarrett D'Amore static	void	  termp_fd_post(DECL_ARGS);
7495c635efSGarrett D'Amore static	void	  termp_fo_post(DECL_ARGS);
7595c635efSGarrett D'Amore static	void	  termp_in_post(DECL_ARGS);
7695c635efSGarrett D'Amore static	void	  termp_it_post(DECL_ARGS);
7795c635efSGarrett D'Amore static	void	  termp_lb_post(DECL_ARGS);
7895c635efSGarrett D'Amore static	void	  termp_nm_post(DECL_ARGS);
7995c635efSGarrett D'Amore static	void	  termp_pf_post(DECL_ARGS);
8095c635efSGarrett D'Amore static	void	  termp_quote_post(DECL_ARGS);
8195c635efSGarrett D'Amore static	void	  termp_sh_post(DECL_ARGS);
8295c635efSGarrett D'Amore static	void	  termp_ss_post(DECL_ARGS);
8395c635efSGarrett D'Amore 
8495c635efSGarrett D'Amore static	int	  termp__a_pre(DECL_ARGS);
8595c635efSGarrett D'Amore static	int	  termp__t_pre(DECL_ARGS);
8695c635efSGarrett D'Amore static	int	  termp_an_pre(DECL_ARGS);
8795c635efSGarrett D'Amore static	int	  termp_ap_pre(DECL_ARGS);
8895c635efSGarrett D'Amore static	int	  termp_bd_pre(DECL_ARGS);
8995c635efSGarrett D'Amore static	int	  termp_bf_pre(DECL_ARGS);
9095c635efSGarrett D'Amore static	int	  termp_bk_pre(DECL_ARGS);
9195c635efSGarrett D'Amore static	int	  termp_bl_pre(DECL_ARGS);
9295c635efSGarrett D'Amore static	int	  termp_bold_pre(DECL_ARGS);
9395c635efSGarrett D'Amore static	int	  termp_bt_pre(DECL_ARGS);
9495c635efSGarrett D'Amore static	int	  termp_bx_pre(DECL_ARGS);
9595c635efSGarrett D'Amore static	int	  termp_cd_pre(DECL_ARGS);
9695c635efSGarrett D'Amore static	int	  termp_d1_pre(DECL_ARGS);
9795c635efSGarrett D'Amore static	int	  termp_ex_pre(DECL_ARGS);
9895c635efSGarrett D'Amore static	int	  termp_fa_pre(DECL_ARGS);
9995c635efSGarrett D'Amore static	int	  termp_fd_pre(DECL_ARGS);
10095c635efSGarrett D'Amore static	int	  termp_fl_pre(DECL_ARGS);
10195c635efSGarrett D'Amore static	int	  termp_fn_pre(DECL_ARGS);
10295c635efSGarrett D'Amore static	int	  termp_fo_pre(DECL_ARGS);
10395c635efSGarrett D'Amore static	int	  termp_ft_pre(DECL_ARGS);
10495c635efSGarrett D'Amore static	int	  termp_in_pre(DECL_ARGS);
10595c635efSGarrett D'Amore static	int	  termp_it_pre(DECL_ARGS);
10695c635efSGarrett D'Amore static	int	  termp_li_pre(DECL_ARGS);
10795c635efSGarrett D'Amore static	int	  termp_lk_pre(DECL_ARGS);
10895c635efSGarrett D'Amore static	int	  termp_nd_pre(DECL_ARGS);
10995c635efSGarrett D'Amore static	int	  termp_nm_pre(DECL_ARGS);
11095c635efSGarrett D'Amore static	int	  termp_ns_pre(DECL_ARGS);
11195c635efSGarrett D'Amore static	int	  termp_quote_pre(DECL_ARGS);
11295c635efSGarrett D'Amore static	int	  termp_rs_pre(DECL_ARGS);
11395c635efSGarrett D'Amore static	int	  termp_rv_pre(DECL_ARGS);
11495c635efSGarrett D'Amore static	int	  termp_sh_pre(DECL_ARGS);
11595c635efSGarrett D'Amore static	int	  termp_sm_pre(DECL_ARGS);
11695c635efSGarrett D'Amore static	int	  termp_sp_pre(DECL_ARGS);
11795c635efSGarrett D'Amore static	int	  termp_ss_pre(DECL_ARGS);
11895c635efSGarrett D'Amore static	int	  termp_under_pre(DECL_ARGS);
11995c635efSGarrett D'Amore static	int	  termp_ud_pre(DECL_ARGS);
12095c635efSGarrett D'Amore static	int	  termp_vt_pre(DECL_ARGS);
12195c635efSGarrett D'Amore static	int	  termp_xr_pre(DECL_ARGS);
12295c635efSGarrett D'Amore static	int	  termp_xx_pre(DECL_ARGS);
12395c635efSGarrett D'Amore 
12495c635efSGarrett D'Amore static	const struct termact termacts[MDOC_MAX] = {
12595c635efSGarrett D'Amore 	{ termp_ap_pre, NULL }, /* Ap */
12695c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dd */
12795c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dt */
12895c635efSGarrett D'Amore 	{ NULL, NULL }, /* Os */
12995c635efSGarrett D'Amore 	{ termp_sh_pre, termp_sh_post }, /* Sh */
13095c635efSGarrett D'Amore 	{ termp_ss_pre, termp_ss_post }, /* Ss */
13195c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Pp */
132*698f87a4SGarrett D'Amore 	{ termp_d1_pre, termp_bl_post }, /* D1 */
133*698f87a4SGarrett D'Amore 	{ termp_d1_pre, termp_bl_post }, /* Dl */
13495c635efSGarrett D'Amore 	{ termp_bd_pre, termp_bd_post }, /* Bd */
13595c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ed */
13695c635efSGarrett D'Amore 	{ termp_bl_pre, termp_bl_post }, /* Bl */
13795c635efSGarrett D'Amore 	{ NULL, NULL }, /* El */
13895c635efSGarrett D'Amore 	{ termp_it_pre, termp_it_post }, /* It */
13995c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ad */
14095c635efSGarrett D'Amore 	{ termp_an_pre, termp_an_post }, /* An */
14195c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ar */
14295c635efSGarrett D'Amore 	{ termp_cd_pre, NULL }, /* Cd */
14395c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Cm */
14495c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dv */
14595c635efSGarrett D'Amore 	{ NULL, NULL }, /* Er */
14695c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ev */
14795c635efSGarrett D'Amore 	{ termp_ex_pre, NULL }, /* Ex */
14895c635efSGarrett D'Amore 	{ termp_fa_pre, NULL }, /* Fa */
149*698f87a4SGarrett D'Amore 	{ termp_fd_pre, termp_fd_post }, /* Fd */
15095c635efSGarrett D'Amore 	{ termp_fl_pre, NULL }, /* Fl */
15195c635efSGarrett D'Amore 	{ termp_fn_pre, NULL }, /* Fn */
15295c635efSGarrett D'Amore 	{ termp_ft_pre, NULL }, /* Ft */
15395c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ic */
15495c635efSGarrett D'Amore 	{ termp_in_pre, termp_in_post }, /* In */
15595c635efSGarrett D'Amore 	{ termp_li_pre, NULL }, /* Li */
15695c635efSGarrett D'Amore 	{ termp_nd_pre, NULL }, /* Nd */
15795c635efSGarrett D'Amore 	{ termp_nm_pre, termp_nm_post }, /* Nm */
15895c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Op */
15995c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ot */
16095c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Pa */
16195c635efSGarrett D'Amore 	{ termp_rv_pre, NULL }, /* Rv */
16295c635efSGarrett D'Amore 	{ NULL, NULL }, /* St */
16395c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Va */
16495c635efSGarrett D'Amore 	{ termp_vt_pre, NULL }, /* Vt */
16595c635efSGarrett D'Amore 	{ termp_xr_pre, NULL }, /* Xr */
16695c635efSGarrett D'Amore 	{ termp__a_pre, termp____post }, /* %A */
16795c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %B */
16895c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %D */
16995c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %I */
17095c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %J */
17195c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %N */
17295c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %O */
17395c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %P */
17495c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %R */
17595c635efSGarrett D'Amore 	{ termp__t_pre, termp__t_post }, /* %T */
17695c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %V */
17795c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ac */
17895c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ao */
17995c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Aq */
18095c635efSGarrett D'Amore 	{ NULL, NULL }, /* At */
18195c635efSGarrett D'Amore 	{ NULL, NULL }, /* Bc */
18295c635efSGarrett D'Amore 	{ termp_bf_pre, NULL }, /* Bf */
18395c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bo */
18495c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bq */
18595c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Bsx */
18695c635efSGarrett D'Amore 	{ termp_bx_pre, NULL }, /* Bx */
18795c635efSGarrett D'Amore 	{ NULL, NULL }, /* Db */
18895c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dc */
18995c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Do */
19095c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Dq */
19195c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ec */ /* FIXME: no space */
19295c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ef */
19395c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Em */
19495c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Eo */
19595c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Fx */
19695c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ms */
197*698f87a4SGarrett D'Amore 	{ NULL, NULL }, /* No */
19895c635efSGarrett D'Amore 	{ termp_ns_pre, NULL }, /* Ns */
19995c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Nx */
20095c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ox */
20195c635efSGarrett D'Amore 	{ NULL, NULL }, /* Pc */
202*698f87a4SGarrett D'Amore 	{ NULL, termp_pf_post }, /* Pf */
20395c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Po */
20495c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Pq */
20595c635efSGarrett D'Amore 	{ NULL, NULL }, /* Qc */
20695c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ql */
20795c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qo */
20895c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qq */
20995c635efSGarrett D'Amore 	{ NULL, NULL }, /* Re */
21095c635efSGarrett D'Amore 	{ termp_rs_pre, NULL }, /* Rs */
21195c635efSGarrett D'Amore 	{ NULL, NULL }, /* Sc */
21295c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* So */
21395c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Sq */
21495c635efSGarrett D'Amore 	{ termp_sm_pre, NULL }, /* Sm */
21595c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Sx */
21695c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Sy */
21795c635efSGarrett D'Amore 	{ NULL, NULL }, /* Tn */
21895c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ux */
21995c635efSGarrett D'Amore 	{ NULL, NULL }, /* Xc */
22095c635efSGarrett D'Amore 	{ NULL, NULL }, /* Xo */
22195c635efSGarrett D'Amore 	{ termp_fo_pre, termp_fo_post }, /* Fo */
22295c635efSGarrett D'Amore 	{ NULL, NULL }, /* Fc */
22395c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Oo */
22495c635efSGarrett D'Amore 	{ NULL, NULL }, /* Oc */
22595c635efSGarrett D'Amore 	{ termp_bk_pre, termp_bk_post }, /* Bk */
22695c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ek */
22795c635efSGarrett D'Amore 	{ termp_bt_pre, NULL }, /* Bt */
22895c635efSGarrett D'Amore 	{ NULL, NULL }, /* Hf */
22995c635efSGarrett D'Amore 	{ NULL, NULL }, /* Fr */
23095c635efSGarrett D'Amore 	{ termp_ud_pre, NULL }, /* Ud */
23195c635efSGarrett D'Amore 	{ NULL, termp_lb_post }, /* Lb */
23295c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Lp */
23395c635efSGarrett D'Amore 	{ termp_lk_pre, NULL }, /* Lk */
23495c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Mt */
23595c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Brq */
23695c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bro */
23795c635efSGarrett D'Amore 	{ NULL, NULL }, /* Brc */
23895c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %C */
23995c635efSGarrett D'Amore 	{ NULL, NULL }, /* Es */ /* TODO */
24095c635efSGarrett D'Amore 	{ NULL, NULL }, /* En */ /* TODO */
24195c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Dx */
24295c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %Q */
24395c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* br */
24495c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* sp */
245*698f87a4SGarrett D'Amore 	{ NULL, termp____post }, /* %U */
24695c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ta */
24795c635efSGarrett D'Amore };
24895c635efSGarrett D'Amore 
24995c635efSGarrett D'Amore 
25095c635efSGarrett D'Amore void
terminal_mdoc(void * arg,const struct mdoc * mdoc)25195c635efSGarrett D'Amore terminal_mdoc(void *arg, const struct mdoc *mdoc)
25295c635efSGarrett D'Amore {
25395c635efSGarrett D'Amore 	const struct mdoc_node	*n;
254*698f87a4SGarrett D'Amore 	const struct mdoc_meta	*meta;
25595c635efSGarrett D'Amore 	struct termp		*p;
25695c635efSGarrett D'Amore 
25795c635efSGarrett D'Amore 	p = (struct termp *)arg;
25895c635efSGarrett D'Amore 
25995c635efSGarrett D'Amore 	if (0 == p->defindent)
26095c635efSGarrett D'Amore 		p->defindent = 5;
26195c635efSGarrett D'Amore 
26295c635efSGarrett D'Amore 	p->overstep = 0;
26395c635efSGarrett D'Amore 	p->maxrmargin = p->defrmargin;
26495c635efSGarrett D'Amore 	p->tabwidth = term_len(p, 5);
26595c635efSGarrett D'Amore 
26695c635efSGarrett D'Amore 	if (NULL == p->symtab)
26795c635efSGarrett D'Amore 		p->symtab = mchars_alloc();
26895c635efSGarrett D'Amore 
26995c635efSGarrett D'Amore 	n = mdoc_node(mdoc);
270*698f87a4SGarrett D'Amore 	meta = mdoc_meta(mdoc);
27195c635efSGarrett D'Amore 
272*698f87a4SGarrett D'Amore 	term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
27395c635efSGarrett D'Amore 
27495c635efSGarrett D'Amore 	if (n->child)
275*698f87a4SGarrett D'Amore 		print_mdoc_nodelist(p, NULL, meta, n->child);
27695c635efSGarrett D'Amore 
27795c635efSGarrett D'Amore 	term_end(p);
27895c635efSGarrett D'Amore }
27995c635efSGarrett D'Amore 
28095c635efSGarrett D'Amore 
28195c635efSGarrett D'Amore static void
print_mdoc_nodelist(DECL_ARGS)28295c635efSGarrett D'Amore print_mdoc_nodelist(DECL_ARGS)
28395c635efSGarrett D'Amore {
28495c635efSGarrett D'Amore 
285*698f87a4SGarrett D'Amore 	print_mdoc_node(p, pair, meta, n);
28695c635efSGarrett D'Amore 	if (n->next)
287*698f87a4SGarrett D'Amore 		print_mdoc_nodelist(p, pair, meta, n->next);
28895c635efSGarrett D'Amore }
28995c635efSGarrett D'Amore 
29095c635efSGarrett D'Amore 
29195c635efSGarrett D'Amore /* ARGSUSED */
29295c635efSGarrett D'Amore static void
print_mdoc_node(DECL_ARGS)29395c635efSGarrett D'Amore print_mdoc_node(DECL_ARGS)
29495c635efSGarrett D'Amore {
29595c635efSGarrett D'Amore 	int		 chld;
29695c635efSGarrett D'Amore 	struct termpair	 npair;
29795c635efSGarrett D'Amore 	size_t		 offset, rmargin;
29895c635efSGarrett D'Amore 
29995c635efSGarrett D'Amore 	chld = 1;
30095c635efSGarrett D'Amore 	offset = p->offset;
30195c635efSGarrett D'Amore 	rmargin = p->rmargin;
302*698f87a4SGarrett D'Amore 	n->prev_font = term_fontq(p);
30395c635efSGarrett D'Amore 
30495c635efSGarrett D'Amore 	memset(&npair, 0, sizeof(struct termpair));
30595c635efSGarrett D'Amore 	npair.ppair = pair;
30695c635efSGarrett D'Amore 
30795c635efSGarrett D'Amore 	/*
30895c635efSGarrett D'Amore 	 * Keeps only work until the end of a line.  If a keep was
30995c635efSGarrett D'Amore 	 * invoked in a prior line, revert it to PREKEEP.
31095c635efSGarrett D'Amore 	 */
31195c635efSGarrett D'Amore 
312*698f87a4SGarrett D'Amore 	if (TERMP_KEEP & p->flags) {
313*698f87a4SGarrett D'Amore 		if (n->prev ? (n->prev->lastline != n->line) :
314*698f87a4SGarrett D'Amore 		    (n->parent && n->parent->line != n->line)) {
31595c635efSGarrett D'Amore 			p->flags &= ~TERMP_KEEP;
31695c635efSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
31795c635efSGarrett D'Amore 		}
31895c635efSGarrett D'Amore 	}
31995c635efSGarrett D'Amore 
32095c635efSGarrett D'Amore 	/*
32195c635efSGarrett D'Amore 	 * After the keep flags have been set up, we may now
32295c635efSGarrett D'Amore 	 * produce output.  Note that some pre-handlers do so.
32395c635efSGarrett D'Amore 	 */
32495c635efSGarrett D'Amore 
32595c635efSGarrett D'Amore 	switch (n->type) {
32695c635efSGarrett D'Amore 	case (MDOC_TEXT):
32795c635efSGarrett D'Amore 		if (' ' == *n->string && MDOC_LINE & n->flags)
32895c635efSGarrett D'Amore 			term_newln(p);
32995c635efSGarrett D'Amore 		if (MDOC_DELIMC & n->flags)
33095c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
33195c635efSGarrett D'Amore 		term_word(p, n->string);
33295c635efSGarrett D'Amore 		if (MDOC_DELIMO & n->flags)
33395c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
33495c635efSGarrett D'Amore 		break;
33595c635efSGarrett D'Amore 	case (MDOC_EQN):
33695c635efSGarrett D'Amore 		term_eqn(p, n->eqn);
33795c635efSGarrett D'Amore 		break;
33895c635efSGarrett D'Amore 	case (MDOC_TBL):
33995c635efSGarrett D'Amore 		term_tbl(p, n->span);
34095c635efSGarrett D'Amore 		break;
34195c635efSGarrett D'Amore 	default:
34295c635efSGarrett D'Amore 		if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
34395c635efSGarrett D'Amore 			chld = (*termacts[n->tok].pre)
344*698f87a4SGarrett D'Amore 				(p, &npair, meta, n);
34595c635efSGarrett D'Amore 		break;
34695c635efSGarrett D'Amore 	}
34795c635efSGarrett D'Amore 
34895c635efSGarrett D'Amore 	if (chld && n->child)
349*698f87a4SGarrett D'Amore 		print_mdoc_nodelist(p, &npair, meta, n->child);
35095c635efSGarrett D'Amore 
351*698f87a4SGarrett D'Amore 	term_fontpopq(p,
352*698f87a4SGarrett D'Amore 	    (ENDBODY_NOT == n->end ? n : n->pending)->prev_font);
35395c635efSGarrett D'Amore 
35495c635efSGarrett D'Amore 	switch (n->type) {
35595c635efSGarrett D'Amore 	case (MDOC_TEXT):
35695c635efSGarrett D'Amore 		break;
35795c635efSGarrett D'Amore 	case (MDOC_TBL):
35895c635efSGarrett D'Amore 		break;
35995c635efSGarrett D'Amore 	case (MDOC_EQN):
36095c635efSGarrett D'Amore 		break;
36195c635efSGarrett D'Amore 	default:
36295c635efSGarrett D'Amore 		if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
36395c635efSGarrett D'Amore 			break;
364*698f87a4SGarrett D'Amore 		(void)(*termacts[n->tok].post)(p, &npair, meta, n);
36595c635efSGarrett D'Amore 
36695c635efSGarrett D'Amore 		/*
36795c635efSGarrett D'Amore 		 * Explicit end tokens not only call the post
36895c635efSGarrett D'Amore 		 * handler, but also tell the respective block
36995c635efSGarrett D'Amore 		 * that it must not call the post handler again.
37095c635efSGarrett D'Amore 		 */
37195c635efSGarrett D'Amore 		if (ENDBODY_NOT != n->end)
37295c635efSGarrett D'Amore 			n->pending->flags |= MDOC_ENDED;
37395c635efSGarrett D'Amore 
37495c635efSGarrett D'Amore 		/*
37595c635efSGarrett D'Amore 		 * End of line terminating an implicit block
37695c635efSGarrett D'Amore 		 * while an explicit block is still open.
37795c635efSGarrett D'Amore 		 * Continue the explicit block without spacing.
37895c635efSGarrett D'Amore 		 */
37995c635efSGarrett D'Amore 		if (ENDBODY_NOSPACE == n->end)
38095c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
38195c635efSGarrett D'Amore 		break;
38295c635efSGarrett D'Amore 	}
38395c635efSGarrett D'Amore 
38495c635efSGarrett D'Amore 	if (MDOC_EOS & n->flags)
38595c635efSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
38695c635efSGarrett D'Amore 
38795c635efSGarrett D'Amore 	p->offset = offset;
38895c635efSGarrett D'Amore 	p->rmargin = rmargin;
38995c635efSGarrett D'Amore }
39095c635efSGarrett D'Amore 
39195c635efSGarrett D'Amore 
39295c635efSGarrett D'Amore static void
print_mdoc_foot(struct termp * p,const void * arg)39395c635efSGarrett D'Amore print_mdoc_foot(struct termp *p, const void *arg)
39495c635efSGarrett D'Amore {
395*698f87a4SGarrett D'Amore 	const struct mdoc_meta *meta;
39695c635efSGarrett D'Amore 
397*698f87a4SGarrett D'Amore 	meta = (const struct mdoc_meta *)arg;
39895c635efSGarrett D'Amore 
39995c635efSGarrett D'Amore 	term_fontrepl(p, TERMFONT_NONE);
40095c635efSGarrett D'Amore 
40195c635efSGarrett D'Amore 	/*
40295c635efSGarrett D'Amore 	 * Output the footer in new-groff style, that is, three columns
40395c635efSGarrett D'Amore 	 * with the middle being the manual date and flanking columns
40495c635efSGarrett D'Amore 	 * being the operating system:
40595c635efSGarrett D'Amore 	 *
40695c635efSGarrett D'Amore 	 * SYSTEM                  DATE                    SYSTEM
40795c635efSGarrett D'Amore 	 */
40895c635efSGarrett D'Amore 
40995c635efSGarrett D'Amore 	term_vspace(p);
41095c635efSGarrett D'Amore 
41195c635efSGarrett D'Amore 	p->offset = 0;
41295c635efSGarrett D'Amore 	p->rmargin = (p->maxrmargin -
413*698f87a4SGarrett D'Amore 			term_strlen(p, meta->date) + term_len(p, 1)) / 2;
414*698f87a4SGarrett D'Amore 	p->trailspace = 1;
41595c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
41695c635efSGarrett D'Amore 
417*698f87a4SGarrett D'Amore 	term_word(p, meta->os);
41895c635efSGarrett D'Amore 	term_flushln(p);
41995c635efSGarrett D'Amore 
42095c635efSGarrett D'Amore 	p->offset = p->rmargin;
421*698f87a4SGarrett D'Amore 	p->rmargin = p->maxrmargin - term_strlen(p, meta->os);
42295c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
42395c635efSGarrett D'Amore 
424*698f87a4SGarrett D'Amore 	term_word(p, meta->date);
42595c635efSGarrett D'Amore 	term_flushln(p);
42695c635efSGarrett D'Amore 
42795c635efSGarrett D'Amore 	p->offset = p->rmargin;
42895c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
429*698f87a4SGarrett D'Amore 	p->trailspace = 0;
43095c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
43195c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
43295c635efSGarrett D'Amore 
433*698f87a4SGarrett D'Amore 	term_word(p, meta->os);
43495c635efSGarrett D'Amore 	term_flushln(p);
43595c635efSGarrett D'Amore 
43695c635efSGarrett D'Amore 	p->offset = 0;
43795c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
43895c635efSGarrett D'Amore 	p->flags = 0;
43995c635efSGarrett D'Amore }
44095c635efSGarrett D'Amore 
44195c635efSGarrett D'Amore 
44295c635efSGarrett D'Amore static void
print_mdoc_head(struct termp * p,const void * arg)44395c635efSGarrett D'Amore print_mdoc_head(struct termp *p, const void *arg)
44495c635efSGarrett D'Amore {
44595c635efSGarrett D'Amore 	char		buf[BUFSIZ], title[BUFSIZ];
44695c635efSGarrett D'Amore 	size_t		buflen, titlen;
447*698f87a4SGarrett D'Amore 	const struct mdoc_meta *meta;
44895c635efSGarrett D'Amore 
449*698f87a4SGarrett D'Amore 	meta = (const struct mdoc_meta *)arg;
45095c635efSGarrett D'Amore 
45195c635efSGarrett D'Amore 	/*
45295c635efSGarrett D'Amore 	 * The header is strange.  It has three components, which are
45395c635efSGarrett D'Amore 	 * really two with the first duplicated.  It goes like this:
45495c635efSGarrett D'Amore 	 *
45595c635efSGarrett D'Amore 	 * IDENTIFIER              TITLE                   IDENTIFIER
45695c635efSGarrett D'Amore 	 *
45795c635efSGarrett D'Amore 	 * The IDENTIFIER is NAME(SECTION), which is the command-name
45895c635efSGarrett D'Amore 	 * (if given, or "unknown" if not) followed by the manual page
45995c635efSGarrett D'Amore 	 * section.  These are given in `Dt'.  The TITLE is a free-form
46095c635efSGarrett D'Amore 	 * string depending on the manual volume.  If not specified, it
46195c635efSGarrett D'Amore 	 * switches on the manual section.
46295c635efSGarrett D'Amore 	 */
46395c635efSGarrett D'Amore 
46495c635efSGarrett D'Amore 	p->offset = 0;
46595c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
46695c635efSGarrett D'Amore 
467*698f87a4SGarrett D'Amore 	assert(meta->vol);
468*698f87a4SGarrett D'Amore 	strlcpy(buf, meta->vol, BUFSIZ);
46995c635efSGarrett D'Amore 	buflen = term_strlen(p, buf);
47095c635efSGarrett D'Amore 
471*698f87a4SGarrett D'Amore 	if (meta->arch) {
47295c635efSGarrett D'Amore 		strlcat(buf, " (", BUFSIZ);
473*698f87a4SGarrett D'Amore 		strlcat(buf, meta->arch, BUFSIZ);
47495c635efSGarrett D'Amore 		strlcat(buf, ")", BUFSIZ);
47595c635efSGarrett D'Amore 	}
47695c635efSGarrett D'Amore 
477*698f87a4SGarrett D'Amore 	snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
47895c635efSGarrett D'Amore 	titlen = term_strlen(p, title);
47995c635efSGarrett D'Amore 
48095c635efSGarrett D'Amore 	p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
481*698f87a4SGarrett D'Amore 	p->trailspace = 1;
48295c635efSGarrett D'Amore 	p->offset = 0;
48395c635efSGarrett D'Amore 	p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
48495c635efSGarrett D'Amore 	    (p->maxrmargin -
48595c635efSGarrett D'Amore 	     term_strlen(p, buf) + term_len(p, 1)) / 2 :
48695c635efSGarrett D'Amore 	    p->maxrmargin - buflen;
48795c635efSGarrett D'Amore 
48895c635efSGarrett D'Amore 	term_word(p, title);
48995c635efSGarrett D'Amore 	term_flushln(p);
49095c635efSGarrett D'Amore 
49195c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
49295c635efSGarrett D'Amore 	p->offset = p->rmargin;
49395c635efSGarrett D'Amore 	p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
49495c635efSGarrett D'Amore 	    p->maxrmargin - titlen : p->maxrmargin;
49595c635efSGarrett D'Amore 
49695c635efSGarrett D'Amore 	term_word(p, buf);
49795c635efSGarrett D'Amore 	term_flushln(p);
49895c635efSGarrett D'Amore 
49995c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
500*698f87a4SGarrett D'Amore 	p->trailspace = 0;
50195c635efSGarrett D'Amore 	if (p->rmargin + titlen <= p->maxrmargin) {
50295c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
50395c635efSGarrett D'Amore 		p->offset = p->rmargin;
50495c635efSGarrett D'Amore 		p->rmargin = p->maxrmargin;
50595c635efSGarrett D'Amore 		term_word(p, title);
50695c635efSGarrett D'Amore 		term_flushln(p);
50795c635efSGarrett D'Amore 	}
50895c635efSGarrett D'Amore 
50995c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOSPACE;
51095c635efSGarrett D'Amore 	p->offset = 0;
51195c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
51295c635efSGarrett D'Amore }
51395c635efSGarrett D'Amore 
51495c635efSGarrett D'Amore 
51595c635efSGarrett D'Amore static size_t
a2height(const struct termp * p,const char * v)51695c635efSGarrett D'Amore a2height(const struct termp *p, const char *v)
51795c635efSGarrett D'Amore {
51895c635efSGarrett D'Amore 	struct roffsu	 su;
51995c635efSGarrett D'Amore 
52095c635efSGarrett D'Amore 
52195c635efSGarrett D'Amore 	assert(v);
52295c635efSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_VS))
52395c635efSGarrett D'Amore 		SCALE_VS_INIT(&su, atoi(v));
52495c635efSGarrett D'Amore 
52595c635efSGarrett D'Amore 	return(term_vspan(p, &su));
52695c635efSGarrett D'Amore }
52795c635efSGarrett D'Amore 
52895c635efSGarrett D'Amore 
52995c635efSGarrett D'Amore static size_t
a2width(const struct termp * p,const char * v)53095c635efSGarrett D'Amore a2width(const struct termp *p, const char *v)
53195c635efSGarrett D'Amore {
53295c635efSGarrett D'Amore 	struct roffsu	 su;
53395c635efSGarrett D'Amore 
53495c635efSGarrett D'Amore 	assert(v);
53595c635efSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_MAX))
53695c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
53795c635efSGarrett D'Amore 
53895c635efSGarrett D'Amore 	return(term_hspan(p, &su));
53995c635efSGarrett D'Amore }
54095c635efSGarrett D'Amore 
54195c635efSGarrett D'Amore 
54295c635efSGarrett D'Amore static size_t
a2offs(const struct termp * p,const char * v)54395c635efSGarrett D'Amore a2offs(const struct termp *p, const char *v)
54495c635efSGarrett D'Amore {
54595c635efSGarrett D'Amore 	struct roffsu	 su;
54695c635efSGarrett D'Amore 
54795c635efSGarrett D'Amore 	if ('\0' == *v)
54895c635efSGarrett D'Amore 		return(0);
54995c635efSGarrett D'Amore 	else if (0 == strcmp(v, "left"))
55095c635efSGarrett D'Amore 		return(0);
55195c635efSGarrett D'Amore 	else if (0 == strcmp(v, "indent"))
55295c635efSGarrett D'Amore 		return(term_len(p, p->defindent + 1));
55395c635efSGarrett D'Amore 	else if (0 == strcmp(v, "indent-two"))
55495c635efSGarrett D'Amore 		return(term_len(p, (p->defindent + 1) * 2));
55595c635efSGarrett D'Amore 	else if ( ! a2roffsu(v, &su, SCALE_MAX))
55695c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
55795c635efSGarrett D'Amore 
55895c635efSGarrett D'Amore 	return(term_hspan(p, &su));
55995c635efSGarrett D'Amore }
56095c635efSGarrett D'Amore 
56195c635efSGarrett D'Amore 
56295c635efSGarrett D'Amore /*
56395c635efSGarrett D'Amore  * Determine how much space to print out before block elements of `It'
56495c635efSGarrett D'Amore  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
56595c635efSGarrett D'Amore  * too.
56695c635efSGarrett D'Amore  */
56795c635efSGarrett D'Amore static void
print_bvspace(struct termp * p,const struct mdoc_node * bl,const struct mdoc_node * n)56895c635efSGarrett D'Amore print_bvspace(struct termp *p,
56995c635efSGarrett D'Amore 		const struct mdoc_node *bl,
57095c635efSGarrett D'Amore 		const struct mdoc_node *n)
57195c635efSGarrett D'Amore {
57295c635efSGarrett D'Amore 	const struct mdoc_node	*nn;
57395c635efSGarrett D'Amore 
57495c635efSGarrett D'Amore 	assert(n);
57595c635efSGarrett D'Amore 
57695c635efSGarrett D'Amore 	term_newln(p);
57795c635efSGarrett D'Amore 
57895c635efSGarrett D'Amore 	if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
57995c635efSGarrett D'Amore 		return;
58095c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
58195c635efSGarrett D'Amore 		return;
58295c635efSGarrett D'Amore 
58395c635efSGarrett D'Amore 	/* Do not vspace directly after Ss/Sh. */
58495c635efSGarrett D'Amore 
58595c635efSGarrett D'Amore 	for (nn = n; nn; nn = nn->parent) {
58695c635efSGarrett D'Amore 		if (MDOC_BLOCK != nn->type)
58795c635efSGarrett D'Amore 			continue;
58895c635efSGarrett D'Amore 		if (MDOC_Ss == nn->tok)
58995c635efSGarrett D'Amore 			return;
59095c635efSGarrett D'Amore 		if (MDOC_Sh == nn->tok)
59195c635efSGarrett D'Amore 			return;
59295c635efSGarrett D'Amore 		if (NULL == nn->prev)
59395c635efSGarrett D'Amore 			continue;
59495c635efSGarrett D'Amore 		break;
59595c635efSGarrett D'Amore 	}
59695c635efSGarrett D'Amore 
59795c635efSGarrett D'Amore 	/* A `-column' does not assert vspace within the list. */
59895c635efSGarrett D'Amore 
59995c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
60095c635efSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok)
60195c635efSGarrett D'Amore 			return;
60295c635efSGarrett D'Amore 
60395c635efSGarrett D'Amore 	/* A `-diag' without body does not vspace. */
60495c635efSGarrett D'Amore 
60595c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_diag == bl->norm->Bl.type)
60695c635efSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok) {
60795c635efSGarrett D'Amore 			assert(n->prev->body);
60895c635efSGarrett D'Amore 			if (NULL == n->prev->body->child)
60995c635efSGarrett D'Amore 				return;
61095c635efSGarrett D'Amore 		}
61195c635efSGarrett D'Amore 
61295c635efSGarrett D'Amore 	term_vspace(p);
61395c635efSGarrett D'Amore }
61495c635efSGarrett D'Amore 
61595c635efSGarrett D'Amore 
61695c635efSGarrett D'Amore /* ARGSUSED */
61795c635efSGarrett D'Amore static int
termp_it_pre(DECL_ARGS)61895c635efSGarrett D'Amore termp_it_pre(DECL_ARGS)
61995c635efSGarrett D'Amore {
62095c635efSGarrett D'Amore 	const struct mdoc_node *bl, *nn;
62195c635efSGarrett D'Amore 	char		        buf[7];
62295c635efSGarrett D'Amore 	int		        i;
62395c635efSGarrett D'Amore 	size_t		        width, offset, ncols, dcol;
62495c635efSGarrett D'Amore 	enum mdoc_list		type;
62595c635efSGarrett D'Amore 
62695c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
62795c635efSGarrett D'Amore 		print_bvspace(p, n->parent->parent, n);
62895c635efSGarrett D'Amore 		return(1);
62995c635efSGarrett D'Amore 	}
63095c635efSGarrett D'Amore 
63195c635efSGarrett D'Amore 	bl = n->parent->parent->parent;
63295c635efSGarrett D'Amore 	type = bl->norm->Bl.type;
63395c635efSGarrett D'Amore 
63495c635efSGarrett D'Amore 	/*
63595c635efSGarrett D'Amore 	 * First calculate width and offset.  This is pretty easy unless
63695c635efSGarrett D'Amore 	 * we're a -column list, in which case all prior columns must
63795c635efSGarrett D'Amore 	 * be accounted for.
63895c635efSGarrett D'Amore 	 */
63995c635efSGarrett D'Amore 
64095c635efSGarrett D'Amore 	width = offset = 0;
64195c635efSGarrett D'Amore 
64295c635efSGarrett D'Amore 	if (bl->norm->Bl.offs)
64395c635efSGarrett D'Amore 		offset = a2offs(p, bl->norm->Bl.offs);
64495c635efSGarrett D'Amore 
64595c635efSGarrett D'Amore 	switch (type) {
64695c635efSGarrett D'Amore 	case (LIST_column):
64795c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
64895c635efSGarrett D'Amore 			break;
64995c635efSGarrett D'Amore 
65095c635efSGarrett D'Amore 		/*
65195c635efSGarrett D'Amore 		 * Imitate groff's column handling:
65295c635efSGarrett D'Amore 		 * - For each earlier column, add its width.
65395c635efSGarrett D'Amore 		 * - For less than 5 columns, add four more blanks per
65495c635efSGarrett D'Amore 		 *   column.
65595c635efSGarrett D'Amore 		 * - For exactly 5 columns, add three more blank per
65695c635efSGarrett D'Amore 		 *   column.
65795c635efSGarrett D'Amore 		 * - For more than 5 columns, add only one column.
65895c635efSGarrett D'Amore 		 */
65995c635efSGarrett D'Amore 		ncols = bl->norm->Bl.ncols;
66095c635efSGarrett D'Amore 
66195c635efSGarrett D'Amore 		/* LINTED */
66295c635efSGarrett D'Amore 		dcol = ncols < 5 ? term_len(p, 4) :
66395c635efSGarrett D'Amore 			ncols == 5 ? term_len(p, 3) : term_len(p, 1);
66495c635efSGarrett D'Amore 
66595c635efSGarrett D'Amore 		/*
66695c635efSGarrett D'Amore 		 * Calculate the offset by applying all prior MDOC_BODY,
66795c635efSGarrett D'Amore 		 * so we stop at the MDOC_HEAD (NULL == nn->prev).
66895c635efSGarrett D'Amore 		 */
66995c635efSGarrett D'Amore 
67095c635efSGarrett D'Amore 		for (i = 0, nn = n->prev;
67195c635efSGarrett D'Amore 				nn->prev && i < (int)ncols;
67295c635efSGarrett D'Amore 				nn = nn->prev, i++)
67395c635efSGarrett D'Amore 			offset += dcol + a2width
67495c635efSGarrett D'Amore 				(p, bl->norm->Bl.cols[i]);
67595c635efSGarrett D'Amore 
67695c635efSGarrett D'Amore 		/*
67795c635efSGarrett D'Amore 		 * When exceeding the declared number of columns, leave
67895c635efSGarrett D'Amore 		 * the remaining widths at 0.  This will later be
67995c635efSGarrett D'Amore 		 * adjusted to the default width of 10, or, for the last
68095c635efSGarrett D'Amore 		 * column, stretched to the right margin.
68195c635efSGarrett D'Amore 		 */
68295c635efSGarrett D'Amore 		if (i >= (int)ncols)
68395c635efSGarrett D'Amore 			break;
68495c635efSGarrett D'Amore 
68595c635efSGarrett D'Amore 		/*
68695c635efSGarrett D'Amore 		 * Use the declared column widths, extended as explained
68795c635efSGarrett D'Amore 		 * in the preceding paragraph.
68895c635efSGarrett D'Amore 		 */
68995c635efSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
69095c635efSGarrett D'Amore 		break;
69195c635efSGarrett D'Amore 	default:
69295c635efSGarrett D'Amore 		if (NULL == bl->norm->Bl.width)
69395c635efSGarrett D'Amore 			break;
69495c635efSGarrett D'Amore 
69595c635efSGarrett D'Amore 		/*
69695c635efSGarrett D'Amore 		 * Note: buffer the width by 2, which is groff's magic
69795c635efSGarrett D'Amore 		 * number for buffering single arguments.  See the above
69895c635efSGarrett D'Amore 		 * handling for column for how this changes.
69995c635efSGarrett D'Amore 		 */
70095c635efSGarrett D'Amore 		assert(bl->norm->Bl.width);
70195c635efSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
70295c635efSGarrett D'Amore 		break;
70395c635efSGarrett D'Amore 	}
70495c635efSGarrett D'Amore 
70595c635efSGarrett D'Amore 	/*
70695c635efSGarrett D'Amore 	 * List-type can override the width in the case of fixed-head
70795c635efSGarrett D'Amore 	 * values (bullet, dash/hyphen, enum).  Tags need a non-zero
70895c635efSGarrett D'Amore 	 * offset.
70995c635efSGarrett D'Amore 	 */
71095c635efSGarrett D'Amore 
71195c635efSGarrett D'Amore 	switch (type) {
71295c635efSGarrett D'Amore 	case (LIST_bullet):
71395c635efSGarrett D'Amore 		/* FALLTHROUGH */
71495c635efSGarrett D'Amore 	case (LIST_dash):
71595c635efSGarrett D'Amore 		/* FALLTHROUGH */
71695c635efSGarrett D'Amore 	case (LIST_hyphen):
717*698f87a4SGarrett D'Amore 		/* FALLTHROUGH */
71895c635efSGarrett D'Amore 	case (LIST_enum):
719*698f87a4SGarrett D'Amore 		if (width < term_len(p, 2))
720*698f87a4SGarrett D'Amore 			width = term_len(p, 2);
72195c635efSGarrett D'Amore 		break;
72295c635efSGarrett D'Amore 	case (LIST_hang):
72395c635efSGarrett D'Amore 		if (0 == width)
72495c635efSGarrett D'Amore 			width = term_len(p, 8);
72595c635efSGarrett D'Amore 		break;
72695c635efSGarrett D'Amore 	case (LIST_column):
72795c635efSGarrett D'Amore 		/* FALLTHROUGH */
72895c635efSGarrett D'Amore 	case (LIST_tag):
72995c635efSGarrett D'Amore 		if (0 == width)
73095c635efSGarrett D'Amore 			width = term_len(p, 10);
73195c635efSGarrett D'Amore 		break;
73295c635efSGarrett D'Amore 	default:
73395c635efSGarrett D'Amore 		break;
73495c635efSGarrett D'Amore 	}
73595c635efSGarrett D'Amore 
73695c635efSGarrett D'Amore 	/*
73795c635efSGarrett D'Amore 	 * Whitespace control.  Inset bodies need an initial space,
73895c635efSGarrett D'Amore 	 * while diagonal bodies need two.
73995c635efSGarrett D'Amore 	 */
74095c635efSGarrett D'Amore 
74195c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
74295c635efSGarrett D'Amore 
74395c635efSGarrett D'Amore 	switch (type) {
74495c635efSGarrett D'Amore 	case (LIST_diag):
74595c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
74695c635efSGarrett D'Amore 			term_word(p, "\\ \\ ");
74795c635efSGarrett D'Amore 		break;
74895c635efSGarrett D'Amore 	case (LIST_inset):
74995c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
75095c635efSGarrett D'Amore 			term_word(p, "\\ ");
75195c635efSGarrett D'Amore 		break;
75295c635efSGarrett D'Amore 	default:
75395c635efSGarrett D'Amore 		break;
75495c635efSGarrett D'Amore 	}
75595c635efSGarrett D'Amore 
75695c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
75795c635efSGarrett D'Amore 
75895c635efSGarrett D'Amore 	switch (type) {
75995c635efSGarrett D'Amore 	case (LIST_diag):
76095c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
76195c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
76295c635efSGarrett D'Amore 		break;
76395c635efSGarrett D'Amore 	default:
76495c635efSGarrett D'Amore 		break;
76595c635efSGarrett D'Amore 	}
76695c635efSGarrett D'Amore 
76795c635efSGarrett D'Amore 	/*
76895c635efSGarrett D'Amore 	 * Pad and break control.  This is the tricky part.  These flags
76995c635efSGarrett D'Amore 	 * are documented in term_flushln() in term.c.  Note that we're
77095c635efSGarrett D'Amore 	 * going to unset all of these flags in termp_it_post() when we
77195c635efSGarrett D'Amore 	 * exit.
77295c635efSGarrett D'Amore 	 */
77395c635efSGarrett D'Amore 
77495c635efSGarrett D'Amore 	switch (type) {
775*698f87a4SGarrett D'Amore 	case (LIST_enum):
776*698f87a4SGarrett D'Amore 		/*
777*698f87a4SGarrett D'Amore 		 * Weird special case.
778*698f87a4SGarrett D'Amore 		 * Very narrow enum lists actually hang.
779*698f87a4SGarrett D'Amore 		 */
780*698f87a4SGarrett D'Amore 		if (width == term_len(p, 2))
781*698f87a4SGarrett D'Amore 			p->flags |= TERMP_HANG;
782*698f87a4SGarrett D'Amore 		/* FALLTHROUGH */
78395c635efSGarrett D'Amore 	case (LIST_bullet):
78495c635efSGarrett D'Amore 		/* FALLTHROUGH */
78595c635efSGarrett D'Amore 	case (LIST_dash):
78695c635efSGarrett D'Amore 		/* FALLTHROUGH */
78795c635efSGarrett D'Amore 	case (LIST_hyphen):
788*698f87a4SGarrett D'Amore 		if (MDOC_HEAD != n->type)
789*698f87a4SGarrett D'Amore 			break;
79095c635efSGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
791*698f87a4SGarrett D'Amore 		p->trailspace = 1;
79295c635efSGarrett D'Amore 		break;
79395c635efSGarrett D'Amore 	case (LIST_hang):
794*698f87a4SGarrett D'Amore 		if (MDOC_HEAD != n->type)
79595c635efSGarrett D'Amore 			break;
79695c635efSGarrett D'Amore 
79795c635efSGarrett D'Amore 		/*
79895c635efSGarrett D'Amore 		 * This is ugly.  If `-hang' is specified and the body
79995c635efSGarrett D'Amore 		 * is a `Bl' or `Bd', then we want basically to nullify
80095c635efSGarrett D'Amore 		 * the "overstep" effect in term_flushln() and treat
80195c635efSGarrett D'Amore 		 * this as a `-ohang' list instead.
80295c635efSGarrett D'Amore 		 */
80395c635efSGarrett D'Amore 		if (n->next->child &&
80495c635efSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
80595c635efSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
806*698f87a4SGarrett D'Amore 			break;
807*698f87a4SGarrett D'Amore 
808*698f87a4SGarrett D'Amore 		p->flags |= TERMP_NOBREAK | TERMP_HANG;
809*698f87a4SGarrett D'Amore 		p->trailspace = 1;
81095c635efSGarrett D'Amore 		break;
81195c635efSGarrett D'Amore 	case (LIST_tag):
81295c635efSGarrett D'Amore 		if (MDOC_HEAD != n->type)
81395c635efSGarrett D'Amore 			break;
814*698f87a4SGarrett D'Amore 
815*698f87a4SGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
816*698f87a4SGarrett D'Amore 		p->trailspace = 2;
817*698f87a4SGarrett D'Amore 
81895c635efSGarrett D'Amore 		if (NULL == n->next || NULL == n->next->child)
81995c635efSGarrett D'Amore 			p->flags |= TERMP_DANGLE;
82095c635efSGarrett D'Amore 		break;
82195c635efSGarrett D'Amore 	case (LIST_column):
82295c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
82395c635efSGarrett D'Amore 			break;
82495c635efSGarrett D'Amore 
825*698f87a4SGarrett D'Amore 		if (NULL == n->next) {
82695c635efSGarrett D'Amore 			p->flags &= ~TERMP_NOBREAK;
827*698f87a4SGarrett D'Amore 			p->trailspace = 0;
828*698f87a4SGarrett D'Amore 		} else {
82995c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
830*698f87a4SGarrett D'Amore 			p->trailspace = 1;
831*698f87a4SGarrett D'Amore 		}
83295c635efSGarrett D'Amore 
83395c635efSGarrett D'Amore 		break;
83495c635efSGarrett D'Amore 	case (LIST_diag):
835*698f87a4SGarrett D'Amore 		if (MDOC_HEAD != n->type)
836*698f87a4SGarrett D'Amore 			break;
83795c635efSGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
838*698f87a4SGarrett D'Amore 		p->trailspace = 1;
83995c635efSGarrett D'Amore 		break;
84095c635efSGarrett D'Amore 	default:
84195c635efSGarrett D'Amore 		break;
84295c635efSGarrett D'Amore 	}
84395c635efSGarrett D'Amore 
84495c635efSGarrett D'Amore 	/*
84595c635efSGarrett D'Amore 	 * Margin control.  Set-head-width lists have their right
84695c635efSGarrett D'Amore 	 * margins shortened.  The body for these lists has the offset
84795c635efSGarrett D'Amore 	 * necessarily lengthened.  Everybody gets the offset.
84895c635efSGarrett D'Amore 	 */
84995c635efSGarrett D'Amore 
85095c635efSGarrett D'Amore 	p->offset += offset;
85195c635efSGarrett D'Amore 
85295c635efSGarrett D'Amore 	switch (type) {
85395c635efSGarrett D'Amore 	case (LIST_hang):
85495c635efSGarrett D'Amore 		/*
85595c635efSGarrett D'Amore 		 * Same stipulation as above, regarding `-hang'.  We
85695c635efSGarrett D'Amore 		 * don't want to recalculate rmargin and offsets when
85795c635efSGarrett D'Amore 		 * using `Bd' or `Bl' within `-hang' overstep lists.
85895c635efSGarrett D'Amore 		 */
85995c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type && n->next->child &&
86095c635efSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
86195c635efSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
86295c635efSGarrett D'Amore 			break;
86395c635efSGarrett D'Amore 		/* FALLTHROUGH */
86495c635efSGarrett D'Amore 	case (LIST_bullet):
86595c635efSGarrett D'Amore 		/* FALLTHROUGH */
86695c635efSGarrett D'Amore 	case (LIST_dash):
86795c635efSGarrett D'Amore 		/* FALLTHROUGH */
86895c635efSGarrett D'Amore 	case (LIST_enum):
86995c635efSGarrett D'Amore 		/* FALLTHROUGH */
87095c635efSGarrett D'Amore 	case (LIST_hyphen):
87195c635efSGarrett D'Amore 		/* FALLTHROUGH */
87295c635efSGarrett D'Amore 	case (LIST_tag):
87395c635efSGarrett D'Amore 		assert(width);
87495c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
87595c635efSGarrett D'Amore 			p->rmargin = p->offset + width;
87695c635efSGarrett D'Amore 		else
87795c635efSGarrett D'Amore 			p->offset += width;
87895c635efSGarrett D'Amore 		break;
87995c635efSGarrett D'Amore 	case (LIST_column):
88095c635efSGarrett D'Amore 		assert(width);
88195c635efSGarrett D'Amore 		p->rmargin = p->offset + width;
88295c635efSGarrett D'Amore 		/*
88395c635efSGarrett D'Amore 		 * XXX - this behaviour is not documented: the
88495c635efSGarrett D'Amore 		 * right-most column is filled to the right margin.
88595c635efSGarrett D'Amore 		 */
88695c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
88795c635efSGarrett D'Amore 			break;
88895c635efSGarrett D'Amore 		if (NULL == n->next && p->rmargin < p->maxrmargin)
88995c635efSGarrett D'Amore 			p->rmargin = p->maxrmargin;
89095c635efSGarrett D'Amore 		break;
89195c635efSGarrett D'Amore 	default:
89295c635efSGarrett D'Amore 		break;
89395c635efSGarrett D'Amore 	}
89495c635efSGarrett D'Amore 
89595c635efSGarrett D'Amore 	/*
89695c635efSGarrett D'Amore 	 * The dash, hyphen, bullet and enum lists all have a special
89795c635efSGarrett D'Amore 	 * HEAD character (temporarily bold, in some cases).
89895c635efSGarrett D'Amore 	 */
89995c635efSGarrett D'Amore 
90095c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
90195c635efSGarrett D'Amore 		switch (type) {
90295c635efSGarrett D'Amore 		case (LIST_bullet):
90395c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
90495c635efSGarrett D'Amore 			term_word(p, "\\[bu]");
90595c635efSGarrett D'Amore 			term_fontpop(p);
90695c635efSGarrett D'Amore 			break;
90795c635efSGarrett D'Amore 		case (LIST_dash):
90895c635efSGarrett D'Amore 			/* FALLTHROUGH */
90995c635efSGarrett D'Amore 		case (LIST_hyphen):
91095c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
91195c635efSGarrett D'Amore 			term_word(p, "\\(hy");
91295c635efSGarrett D'Amore 			term_fontpop(p);
91395c635efSGarrett D'Amore 			break;
91495c635efSGarrett D'Amore 		case (LIST_enum):
91595c635efSGarrett D'Amore 			(pair->ppair->ppair->count)++;
91695c635efSGarrett D'Amore 			snprintf(buf, sizeof(buf), "%d.",
91795c635efSGarrett D'Amore 					pair->ppair->ppair->count);
91895c635efSGarrett D'Amore 			term_word(p, buf);
91995c635efSGarrett D'Amore 			break;
92095c635efSGarrett D'Amore 		default:
92195c635efSGarrett D'Amore 			break;
92295c635efSGarrett D'Amore 		}
92395c635efSGarrett D'Amore 
92495c635efSGarrett D'Amore 	/*
92595c635efSGarrett D'Amore 	 * If we're not going to process our children, indicate so here.
92695c635efSGarrett D'Amore 	 */
92795c635efSGarrett D'Amore 
92895c635efSGarrett D'Amore 	switch (type) {
92995c635efSGarrett D'Amore 	case (LIST_bullet):
93095c635efSGarrett D'Amore 		/* FALLTHROUGH */
93195c635efSGarrett D'Amore 	case (LIST_item):
93295c635efSGarrett D'Amore 		/* FALLTHROUGH */
93395c635efSGarrett D'Amore 	case (LIST_dash):
93495c635efSGarrett D'Amore 		/* FALLTHROUGH */
93595c635efSGarrett D'Amore 	case (LIST_hyphen):
93695c635efSGarrett D'Amore 		/* FALLTHROUGH */
93795c635efSGarrett D'Amore 	case (LIST_enum):
93895c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
93995c635efSGarrett D'Amore 			return(0);
94095c635efSGarrett D'Amore 		break;
94195c635efSGarrett D'Amore 	case (LIST_column):
94295c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
94395c635efSGarrett D'Amore 			return(0);
94495c635efSGarrett D'Amore 		break;
94595c635efSGarrett D'Amore 	default:
94695c635efSGarrett D'Amore 		break;
94795c635efSGarrett D'Amore 	}
94895c635efSGarrett D'Amore 
94995c635efSGarrett D'Amore 	return(1);
95095c635efSGarrett D'Amore }
95195c635efSGarrett D'Amore 
95295c635efSGarrett D'Amore 
95395c635efSGarrett D'Amore /* ARGSUSED */
95495c635efSGarrett D'Amore static void
termp_it_post(DECL_ARGS)95595c635efSGarrett D'Amore termp_it_post(DECL_ARGS)
95695c635efSGarrett D'Amore {
95795c635efSGarrett D'Amore 	enum mdoc_list	   type;
95895c635efSGarrett D'Amore 
95995c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
96095c635efSGarrett D'Amore 		return;
96195c635efSGarrett D'Amore 
96295c635efSGarrett D'Amore 	type = n->parent->parent->parent->norm->Bl.type;
96395c635efSGarrett D'Amore 
96495c635efSGarrett D'Amore 	switch (type) {
96595c635efSGarrett D'Amore 	case (LIST_item):
96695c635efSGarrett D'Amore 		/* FALLTHROUGH */
96795c635efSGarrett D'Amore 	case (LIST_diag):
96895c635efSGarrett D'Amore 		/* FALLTHROUGH */
96995c635efSGarrett D'Amore 	case (LIST_inset):
97095c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
97195c635efSGarrett D'Amore 			term_newln(p);
97295c635efSGarrett D'Amore 		break;
97395c635efSGarrett D'Amore 	case (LIST_column):
97495c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
97595c635efSGarrett D'Amore 			term_flushln(p);
97695c635efSGarrett D'Amore 		break;
97795c635efSGarrett D'Amore 	default:
97895c635efSGarrett D'Amore 		term_newln(p);
97995c635efSGarrett D'Amore 		break;
98095c635efSGarrett D'Amore 	}
98195c635efSGarrett D'Amore 
98295c635efSGarrett D'Amore 	/*
98395c635efSGarrett D'Amore 	 * Now that our output is flushed, we can reset our tags.  Since
98495c635efSGarrett D'Amore 	 * only `It' sets these flags, we're free to assume that nobody
98595c635efSGarrett D'Amore 	 * has munged them in the meanwhile.
98695c635efSGarrett D'Amore 	 */
98795c635efSGarrett D'Amore 
98895c635efSGarrett D'Amore 	p->flags &= ~TERMP_DANGLE;
98995c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
99095c635efSGarrett D'Amore 	p->flags &= ~TERMP_HANG;
991*698f87a4SGarrett D'Amore 	p->trailspace = 0;
99295c635efSGarrett D'Amore }
99395c635efSGarrett D'Amore 
99495c635efSGarrett D'Amore 
99595c635efSGarrett D'Amore /* ARGSUSED */
99695c635efSGarrett D'Amore static int
termp_nm_pre(DECL_ARGS)99795c635efSGarrett D'Amore termp_nm_pre(DECL_ARGS)
99895c635efSGarrett D'Amore {
99995c635efSGarrett D'Amore 
1000*698f87a4SGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
1001*698f87a4SGarrett D'Amore 		p->flags |= TERMP_PREKEEP;
100295c635efSGarrett D'Amore 		return(1);
1003*698f87a4SGarrett D'Amore 	}
100495c635efSGarrett D'Amore 
100595c635efSGarrett D'Amore 	if (MDOC_BODY == n->type) {
100695c635efSGarrett D'Amore 		if (NULL == n->child)
100795c635efSGarrett D'Amore 			return(0);
100895c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
100995c635efSGarrett D'Amore 		p->offset += term_len(p, 1) +
1010*698f87a4SGarrett D'Amore 		    (NULL == n->prev->child ?
1011*698f87a4SGarrett D'Amore 		     term_strlen(p, meta->name) :
101295c635efSGarrett D'Amore 		     MDOC_TEXT == n->prev->child->type ?
101395c635efSGarrett D'Amore 		     term_strlen(p, n->prev->child->string) :
101495c635efSGarrett D'Amore 		     term_len(p, 5));
101595c635efSGarrett D'Amore 		return(1);
101695c635efSGarrett D'Amore 	}
101795c635efSGarrett D'Amore 
1018*698f87a4SGarrett D'Amore 	if (NULL == n->child && NULL == meta->name)
101995c635efSGarrett D'Amore 		return(0);
102095c635efSGarrett D'Amore 
102195c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
102295c635efSGarrett D'Amore 		synopsis_pre(p, n->parent);
102395c635efSGarrett D'Amore 
102495c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type && n->next->child) {
102595c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
1026*698f87a4SGarrett D'Amore 		p->trailspace = 1;
102795c635efSGarrett D'Amore 		p->rmargin = p->offset + term_len(p, 1);
102895c635efSGarrett D'Amore 		if (NULL == n->child) {
1029*698f87a4SGarrett D'Amore 			p->rmargin += term_strlen(p, meta->name);
103095c635efSGarrett D'Amore 		} else if (MDOC_TEXT == n->child->type) {
103195c635efSGarrett D'Amore 			p->rmargin += term_strlen(p, n->child->string);
103295c635efSGarrett D'Amore 			if (n->child->next)
103395c635efSGarrett D'Amore 				p->flags |= TERMP_HANG;
103495c635efSGarrett D'Amore 		} else {
103595c635efSGarrett D'Amore 			p->rmargin += term_len(p, 5);
103695c635efSGarrett D'Amore 			p->flags |= TERMP_HANG;
103795c635efSGarrett D'Amore 		}
103895c635efSGarrett D'Amore 	}
103995c635efSGarrett D'Amore 
104095c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
104195c635efSGarrett D'Amore 	if (NULL == n->child)
1042*698f87a4SGarrett D'Amore 		term_word(p, meta->name);
104395c635efSGarrett D'Amore 	return(1);
104495c635efSGarrett D'Amore }
104595c635efSGarrett D'Amore 
104695c635efSGarrett D'Amore 
104795c635efSGarrett D'Amore /* ARGSUSED */
104895c635efSGarrett D'Amore static void
termp_nm_post(DECL_ARGS)104995c635efSGarrett D'Amore termp_nm_post(DECL_ARGS)
105095c635efSGarrett D'Amore {
105195c635efSGarrett D'Amore 
1052*698f87a4SGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
1053*698f87a4SGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1054*698f87a4SGarrett D'Amore 	} else if (MDOC_HEAD == n->type && n->next->child) {
105595c635efSGarrett D'Amore 		term_flushln(p);
105695c635efSGarrett D'Amore 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
1057*698f87a4SGarrett D'Amore 		p->trailspace = 0;
105895c635efSGarrett D'Amore 	} else if (MDOC_BODY == n->type && n->child)
105995c635efSGarrett D'Amore 		term_flushln(p);
106095c635efSGarrett D'Amore }
106195c635efSGarrett D'Amore 
106295c635efSGarrett D'Amore 
106395c635efSGarrett D'Amore /* ARGSUSED */
106495c635efSGarrett D'Amore static int
termp_fl_pre(DECL_ARGS)106595c635efSGarrett D'Amore termp_fl_pre(DECL_ARGS)
106695c635efSGarrett D'Amore {
106795c635efSGarrett D'Amore 
106895c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
106995c635efSGarrett D'Amore 	term_word(p, "\\-");
107095c635efSGarrett D'Amore 
107195c635efSGarrett D'Amore 	if (n->child)
107295c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
107395c635efSGarrett D'Amore 	else if (n->next && n->next->line == n->line)
107495c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
107595c635efSGarrett D'Amore 
107695c635efSGarrett D'Amore 	return(1);
107795c635efSGarrett D'Amore }
107895c635efSGarrett D'Amore 
107995c635efSGarrett D'Amore 
108095c635efSGarrett D'Amore /* ARGSUSED */
108195c635efSGarrett D'Amore static int
termp__a_pre(DECL_ARGS)108295c635efSGarrett D'Amore termp__a_pre(DECL_ARGS)
108395c635efSGarrett D'Amore {
108495c635efSGarrett D'Amore 
108595c635efSGarrett D'Amore 	if (n->prev && MDOC__A == n->prev->tok)
108695c635efSGarrett D'Amore 		if (NULL == n->next || MDOC__A != n->next->tok)
108795c635efSGarrett D'Amore 			term_word(p, "and");
108895c635efSGarrett D'Amore 
108995c635efSGarrett D'Amore 	return(1);
109095c635efSGarrett D'Amore }
109195c635efSGarrett D'Amore 
109295c635efSGarrett D'Amore 
109395c635efSGarrett D'Amore /* ARGSUSED */
109495c635efSGarrett D'Amore static int
termp_an_pre(DECL_ARGS)109595c635efSGarrett D'Amore termp_an_pre(DECL_ARGS)
109695c635efSGarrett D'Amore {
109795c635efSGarrett D'Amore 
109895c635efSGarrett D'Amore 	if (NULL == n->child)
109995c635efSGarrett D'Amore 		return(1);
110095c635efSGarrett D'Amore 
110195c635efSGarrett D'Amore 	/*
110295c635efSGarrett D'Amore 	 * If not in the AUTHORS section, `An -split' will cause
110395c635efSGarrett D'Amore 	 * newlines to occur before the author name.  If in the AUTHORS
110495c635efSGarrett D'Amore 	 * section, by default, the first `An' invocation is nosplit,
110595c635efSGarrett D'Amore 	 * then all subsequent ones, regardless of whether interspersed
110695c635efSGarrett D'Amore 	 * with other macros/text, are split.  -split, in this case,
110795c635efSGarrett D'Amore 	 * will override the condition of the implied first -nosplit.
110895c635efSGarrett D'Amore 	 */
110995c635efSGarrett D'Amore 
111095c635efSGarrett D'Amore 	if (n->sec == SEC_AUTHORS) {
111195c635efSGarrett D'Amore 		if ( ! (TERMP_ANPREC & p->flags)) {
111295c635efSGarrett D'Amore 			if (TERMP_SPLIT & p->flags)
111395c635efSGarrett D'Amore 				term_newln(p);
111495c635efSGarrett D'Amore 			return(1);
111595c635efSGarrett D'Amore 		}
111695c635efSGarrett D'Amore 		if (TERMP_NOSPLIT & p->flags)
111795c635efSGarrett D'Amore 			return(1);
111895c635efSGarrett D'Amore 		term_newln(p);
111995c635efSGarrett D'Amore 		return(1);
112095c635efSGarrett D'Amore 	}
112195c635efSGarrett D'Amore 
112295c635efSGarrett D'Amore 	if (TERMP_SPLIT & p->flags)
112395c635efSGarrett D'Amore 		term_newln(p);
112495c635efSGarrett D'Amore 
112595c635efSGarrett D'Amore 	return(1);
112695c635efSGarrett D'Amore }
112795c635efSGarrett D'Amore 
112895c635efSGarrett D'Amore 
112995c635efSGarrett D'Amore /* ARGSUSED */
113095c635efSGarrett D'Amore static void
termp_an_post(DECL_ARGS)113195c635efSGarrett D'Amore termp_an_post(DECL_ARGS)
113295c635efSGarrett D'Amore {
113395c635efSGarrett D'Amore 
113495c635efSGarrett D'Amore 	if (n->child) {
113595c635efSGarrett D'Amore 		if (SEC_AUTHORS == n->sec)
113695c635efSGarrett D'Amore 			p->flags |= TERMP_ANPREC;
113795c635efSGarrett D'Amore 		return;
113895c635efSGarrett D'Amore 	}
113995c635efSGarrett D'Amore 
114095c635efSGarrett D'Amore 	if (AUTH_split == n->norm->An.auth) {
114195c635efSGarrett D'Amore 		p->flags &= ~TERMP_NOSPLIT;
114295c635efSGarrett D'Amore 		p->flags |= TERMP_SPLIT;
114395c635efSGarrett D'Amore 	} else if (AUTH_nosplit == n->norm->An.auth) {
114495c635efSGarrett D'Amore 		p->flags &= ~TERMP_SPLIT;
114595c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPLIT;
114695c635efSGarrett D'Amore 	}
114795c635efSGarrett D'Amore 
114895c635efSGarrett D'Amore }
114995c635efSGarrett D'Amore 
115095c635efSGarrett D'Amore 
115195c635efSGarrett D'Amore /* ARGSUSED */
115295c635efSGarrett D'Amore static int
termp_ns_pre(DECL_ARGS)115395c635efSGarrett D'Amore termp_ns_pre(DECL_ARGS)
115495c635efSGarrett D'Amore {
115595c635efSGarrett D'Amore 
115695c635efSGarrett D'Amore 	if ( ! (MDOC_LINE & n->flags))
115795c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
115895c635efSGarrett D'Amore 	return(1);
115995c635efSGarrett D'Amore }
116095c635efSGarrett D'Amore 
116195c635efSGarrett D'Amore 
116295c635efSGarrett D'Amore /* ARGSUSED */
116395c635efSGarrett D'Amore static int
termp_rs_pre(DECL_ARGS)116495c635efSGarrett D'Amore termp_rs_pre(DECL_ARGS)
116595c635efSGarrett D'Amore {
116695c635efSGarrett D'Amore 
116795c635efSGarrett D'Amore 	if (SEC_SEE_ALSO != n->sec)
116895c635efSGarrett D'Amore 		return(1);
116995c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type && n->prev)
117095c635efSGarrett D'Amore 		term_vspace(p);
117195c635efSGarrett D'Amore 	return(1);
117295c635efSGarrett D'Amore }
117395c635efSGarrett D'Amore 
117495c635efSGarrett D'Amore 
117595c635efSGarrett D'Amore /* ARGSUSED */
117695c635efSGarrett D'Amore static int
termp_rv_pre(DECL_ARGS)117795c635efSGarrett D'Amore termp_rv_pre(DECL_ARGS)
117895c635efSGarrett D'Amore {
117995c635efSGarrett D'Amore 	int		 nchild;
118095c635efSGarrett D'Amore 
118195c635efSGarrett D'Amore 	term_newln(p);
118295c635efSGarrett D'Amore 	term_word(p, "The");
118395c635efSGarrett D'Amore 
118495c635efSGarrett D'Amore 	nchild = n->nchild;
118595c635efSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
118695c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
118795c635efSGarrett D'Amore 		term_word(p, n->string);
118895c635efSGarrett D'Amore 		term_fontpop(p);
118995c635efSGarrett D'Amore 
119095c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
119195c635efSGarrett D'Amore 		term_word(p, "()");
119295c635efSGarrett D'Amore 
119395c635efSGarrett D'Amore 		if (nchild > 2 && n->next) {
119495c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
119595c635efSGarrett D'Amore 			term_word(p, ",");
119695c635efSGarrett D'Amore 		}
119795c635efSGarrett D'Amore 
119895c635efSGarrett D'Amore 		if (n->next && NULL == n->next->next)
119995c635efSGarrett D'Amore 			term_word(p, "and");
120095c635efSGarrett D'Amore 	}
120195c635efSGarrett D'Amore 
120295c635efSGarrett D'Amore 	if (nchild > 1)
120395c635efSGarrett D'Amore 		term_word(p, "functions return");
120495c635efSGarrett D'Amore 	else
120595c635efSGarrett D'Amore 		term_word(p, "function returns");
120695c635efSGarrett D'Amore 
120795c635efSGarrett D'Amore        	term_word(p, "the value 0 if successful; otherwise the value "
120895c635efSGarrett D'Amore 			"-1 is returned and the global variable");
120995c635efSGarrett D'Amore 
121095c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
121195c635efSGarrett D'Amore 	term_word(p, "errno");
121295c635efSGarrett D'Amore 	term_fontpop(p);
121395c635efSGarrett D'Amore 
121495c635efSGarrett D'Amore        	term_word(p, "is set to indicate the error.");
121595c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
121695c635efSGarrett D'Amore 
121795c635efSGarrett D'Amore 	return(0);
121895c635efSGarrett D'Amore }
121995c635efSGarrett D'Amore 
122095c635efSGarrett D'Amore 
122195c635efSGarrett D'Amore /* ARGSUSED */
122295c635efSGarrett D'Amore static int
termp_ex_pre(DECL_ARGS)122395c635efSGarrett D'Amore termp_ex_pre(DECL_ARGS)
122495c635efSGarrett D'Amore {
122595c635efSGarrett D'Amore 	int		 nchild;
122695c635efSGarrett D'Amore 
122795c635efSGarrett D'Amore 	term_newln(p);
122895c635efSGarrett D'Amore 	term_word(p, "The");
122995c635efSGarrett D'Amore 
123095c635efSGarrett D'Amore 	nchild = n->nchild;
123195c635efSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
123295c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
123395c635efSGarrett D'Amore 		term_word(p, n->string);
123495c635efSGarrett D'Amore 		term_fontpop(p);
123595c635efSGarrett D'Amore 
123695c635efSGarrett D'Amore 		if (nchild > 2 && n->next) {
123795c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
123895c635efSGarrett D'Amore 			term_word(p, ",");
123995c635efSGarrett D'Amore 		}
124095c635efSGarrett D'Amore 
124195c635efSGarrett D'Amore 		if (n->next && NULL == n->next->next)
124295c635efSGarrett D'Amore 			term_word(p, "and");
124395c635efSGarrett D'Amore 	}
124495c635efSGarrett D'Amore 
124595c635efSGarrett D'Amore 	if (nchild > 1)
124695c635efSGarrett D'Amore 		term_word(p, "utilities exit");
124795c635efSGarrett D'Amore 	else
124895c635efSGarrett D'Amore 		term_word(p, "utility exits");
124995c635efSGarrett D'Amore 
125095c635efSGarrett D'Amore        	term_word(p, "0 on success, and >0 if an error occurs.");
125195c635efSGarrett D'Amore 
125295c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
125395c635efSGarrett D'Amore 	return(0);
125495c635efSGarrett D'Amore }
125595c635efSGarrett D'Amore 
125695c635efSGarrett D'Amore 
125795c635efSGarrett D'Amore /* ARGSUSED */
125895c635efSGarrett D'Amore static int
termp_nd_pre(DECL_ARGS)125995c635efSGarrett D'Amore termp_nd_pre(DECL_ARGS)
126095c635efSGarrett D'Amore {
126195c635efSGarrett D'Amore 
126295c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
126395c635efSGarrett D'Amore 		return(1);
126495c635efSGarrett D'Amore 
126595c635efSGarrett D'Amore #if defined(__OpenBSD__) || defined(__linux__)
126695c635efSGarrett D'Amore 	term_word(p, "\\(en");
126795c635efSGarrett D'Amore #else
126895c635efSGarrett D'Amore 	term_word(p, "\\(em");
126995c635efSGarrett D'Amore #endif
127095c635efSGarrett D'Amore 	return(1);
127195c635efSGarrett D'Amore }
127295c635efSGarrett D'Amore 
127395c635efSGarrett D'Amore 
127495c635efSGarrett D'Amore /* ARGSUSED */
127595c635efSGarrett D'Amore static int
termp_bl_pre(DECL_ARGS)127695c635efSGarrett D'Amore termp_bl_pre(DECL_ARGS)
127795c635efSGarrett D'Amore {
127895c635efSGarrett D'Amore 
127995c635efSGarrett D'Amore 	return(MDOC_HEAD != n->type);
128095c635efSGarrett D'Amore }
128195c635efSGarrett D'Amore 
128295c635efSGarrett D'Amore 
128395c635efSGarrett D'Amore /* ARGSUSED */
128495c635efSGarrett D'Amore static void
termp_bl_post(DECL_ARGS)128595c635efSGarrett D'Amore termp_bl_post(DECL_ARGS)
128695c635efSGarrett D'Amore {
128795c635efSGarrett D'Amore 
128895c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
128995c635efSGarrett D'Amore 		term_newln(p);
129095c635efSGarrett D'Amore }
129195c635efSGarrett D'Amore 
129295c635efSGarrett D'Amore /* ARGSUSED */
129395c635efSGarrett D'Amore static int
termp_xr_pre(DECL_ARGS)129495c635efSGarrett D'Amore termp_xr_pre(DECL_ARGS)
129595c635efSGarrett D'Amore {
129695c635efSGarrett D'Amore 
129795c635efSGarrett D'Amore 	if (NULL == (n = n->child))
129895c635efSGarrett D'Amore 		return(0);
129995c635efSGarrett D'Amore 
130095c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
130195c635efSGarrett D'Amore 	term_word(p, n->string);
130295c635efSGarrett D'Amore 
130395c635efSGarrett D'Amore 	if (NULL == (n = n->next))
130495c635efSGarrett D'Amore 		return(0);
130595c635efSGarrett D'Amore 
130695c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
130795c635efSGarrett D'Amore 	term_word(p, "(");
130895c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
130995c635efSGarrett D'Amore 
131095c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
131195c635efSGarrett D'Amore 	term_word(p, n->string);
131295c635efSGarrett D'Amore 
131395c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
131495c635efSGarrett D'Amore 	term_word(p, ")");
131595c635efSGarrett D'Amore 
131695c635efSGarrett D'Amore 	return(0);
131795c635efSGarrett D'Amore }
131895c635efSGarrett D'Amore 
131995c635efSGarrett D'Amore /*
132095c635efSGarrett D'Amore  * This decides how to assert whitespace before any of the SYNOPSIS set
132195c635efSGarrett D'Amore  * of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
132295c635efSGarrett D'Amore  * macro combos).
132395c635efSGarrett D'Amore  */
132495c635efSGarrett D'Amore static void
synopsis_pre(struct termp * p,const struct mdoc_node * n)132595c635efSGarrett D'Amore synopsis_pre(struct termp *p, const struct mdoc_node *n)
132695c635efSGarrett D'Amore {
132795c635efSGarrett D'Amore 	/*
132895c635efSGarrett D'Amore 	 * Obviously, if we're not in a SYNOPSIS or no prior macros
132995c635efSGarrett D'Amore 	 * exist, do nothing.
133095c635efSGarrett D'Amore 	 */
133195c635efSGarrett D'Amore 	if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
133295c635efSGarrett D'Amore 		return;
133395c635efSGarrett D'Amore 
133495c635efSGarrett D'Amore 	/*
133595c635efSGarrett D'Amore 	 * If we're the second in a pair of like elements, emit our
133695c635efSGarrett D'Amore 	 * newline and return.  UNLESS we're `Fo', `Fn', `Fn', in which
133795c635efSGarrett D'Amore 	 * case we soldier on.
133895c635efSGarrett D'Amore 	 */
133995c635efSGarrett D'Amore 	if (n->prev->tok == n->tok &&
134095c635efSGarrett D'Amore 			MDOC_Ft != n->tok &&
134195c635efSGarrett D'Amore 			MDOC_Fo != n->tok &&
134295c635efSGarrett D'Amore 			MDOC_Fn != n->tok) {
134395c635efSGarrett D'Amore 		term_newln(p);
134495c635efSGarrett D'Amore 		return;
134595c635efSGarrett D'Amore 	}
134695c635efSGarrett D'Amore 
134795c635efSGarrett D'Amore 	/*
134895c635efSGarrett D'Amore 	 * If we're one of the SYNOPSIS set and non-like pair-wise after
134995c635efSGarrett D'Amore 	 * another (or Fn/Fo, which we've let slip through) then assert
135095c635efSGarrett D'Amore 	 * vertical space, else only newline and move on.
135195c635efSGarrett D'Amore 	 */
135295c635efSGarrett D'Amore 	switch (n->prev->tok) {
135395c635efSGarrett D'Amore 	case (MDOC_Fd):
135495c635efSGarrett D'Amore 		/* FALLTHROUGH */
135595c635efSGarrett D'Amore 	case (MDOC_Fn):
135695c635efSGarrett D'Amore 		/* FALLTHROUGH */
135795c635efSGarrett D'Amore 	case (MDOC_Fo):
135895c635efSGarrett D'Amore 		/* FALLTHROUGH */
135995c635efSGarrett D'Amore 	case (MDOC_In):
136095c635efSGarrett D'Amore 		/* FALLTHROUGH */
136195c635efSGarrett D'Amore 	case (MDOC_Vt):
136295c635efSGarrett D'Amore 		term_vspace(p);
136395c635efSGarrett D'Amore 		break;
136495c635efSGarrett D'Amore 	case (MDOC_Ft):
136595c635efSGarrett D'Amore 		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
136695c635efSGarrett D'Amore 			term_vspace(p);
136795c635efSGarrett D'Amore 			break;
136895c635efSGarrett D'Amore 		}
136995c635efSGarrett D'Amore 		/* FALLTHROUGH */
137095c635efSGarrett D'Amore 	default:
137195c635efSGarrett D'Amore 		term_newln(p);
137295c635efSGarrett D'Amore 		break;
137395c635efSGarrett D'Amore 	}
137495c635efSGarrett D'Amore }
137595c635efSGarrett D'Amore 
137695c635efSGarrett D'Amore 
137795c635efSGarrett D'Amore static int
termp_vt_pre(DECL_ARGS)137895c635efSGarrett D'Amore termp_vt_pre(DECL_ARGS)
137995c635efSGarrett D'Amore {
138095c635efSGarrett D'Amore 
138195c635efSGarrett D'Amore 	if (MDOC_ELEM == n->type) {
138295c635efSGarrett D'Amore 		synopsis_pre(p, n);
1383*698f87a4SGarrett D'Amore 		return(termp_under_pre(p, pair, meta, n));
138495c635efSGarrett D'Amore 	} else if (MDOC_BLOCK == n->type) {
138595c635efSGarrett D'Amore 		synopsis_pre(p, n);
138695c635efSGarrett D'Amore 		return(1);
138795c635efSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
138895c635efSGarrett D'Amore 		return(0);
138995c635efSGarrett D'Amore 
1390*698f87a4SGarrett D'Amore 	return(termp_under_pre(p, pair, meta, n));
139195c635efSGarrett D'Amore }
139295c635efSGarrett D'Amore 
139395c635efSGarrett D'Amore 
139495c635efSGarrett D'Amore /* ARGSUSED */
139595c635efSGarrett D'Amore static int
termp_bold_pre(DECL_ARGS)139695c635efSGarrett D'Amore termp_bold_pre(DECL_ARGS)
139795c635efSGarrett D'Amore {
139895c635efSGarrett D'Amore 
139995c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
140095c635efSGarrett D'Amore 	return(1);
140195c635efSGarrett D'Amore }
140295c635efSGarrett D'Amore 
140395c635efSGarrett D'Amore 
140495c635efSGarrett D'Amore /* ARGSUSED */
140595c635efSGarrett D'Amore static int
termp_fd_pre(DECL_ARGS)140695c635efSGarrett D'Amore termp_fd_pre(DECL_ARGS)
140795c635efSGarrett D'Amore {
140895c635efSGarrett D'Amore 
140995c635efSGarrett D'Amore 	synopsis_pre(p, n);
1410*698f87a4SGarrett D'Amore 	return(termp_bold_pre(p, pair, meta, n));
1411*698f87a4SGarrett D'Amore }
1412*698f87a4SGarrett D'Amore 
1413*698f87a4SGarrett D'Amore 
1414*698f87a4SGarrett D'Amore /* ARGSUSED */
1415*698f87a4SGarrett D'Amore static void
termp_fd_post(DECL_ARGS)1416*698f87a4SGarrett D'Amore termp_fd_post(DECL_ARGS)
1417*698f87a4SGarrett D'Amore {
1418*698f87a4SGarrett D'Amore 
1419*698f87a4SGarrett D'Amore 	term_newln(p);
142095c635efSGarrett D'Amore }
142195c635efSGarrett D'Amore 
142295c635efSGarrett D'Amore 
142395c635efSGarrett D'Amore /* ARGSUSED */
142495c635efSGarrett D'Amore static int
termp_sh_pre(DECL_ARGS)142595c635efSGarrett D'Amore termp_sh_pre(DECL_ARGS)
142695c635efSGarrett D'Amore {
142795c635efSGarrett D'Amore 
142895c635efSGarrett D'Amore 	/* No vspace between consecutive `Sh' calls. */
142995c635efSGarrett D'Amore 
143095c635efSGarrett D'Amore 	switch (n->type) {
143195c635efSGarrett D'Amore 	case (MDOC_BLOCK):
143295c635efSGarrett D'Amore 		if (n->prev && MDOC_Sh == n->prev->tok)
143395c635efSGarrett D'Amore 			if (NULL == n->prev->body->child)
143495c635efSGarrett D'Amore 				break;
143595c635efSGarrett D'Amore 		term_vspace(p);
143695c635efSGarrett D'Amore 		break;
143795c635efSGarrett D'Amore 	case (MDOC_HEAD):
143895c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
143995c635efSGarrett D'Amore 		break;
144095c635efSGarrett D'Amore 	case (MDOC_BODY):
144195c635efSGarrett D'Amore 		p->offset = term_len(p, p->defindent);
1442*698f87a4SGarrett D'Amore 		if (SEC_AUTHORS == n->sec)
1443*698f87a4SGarrett D'Amore 			p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
144495c635efSGarrett D'Amore 		break;
144595c635efSGarrett D'Amore 	default:
144695c635efSGarrett D'Amore 		break;
144795c635efSGarrett D'Amore 	}
144895c635efSGarrett D'Amore 	return(1);
144995c635efSGarrett D'Amore }
145095c635efSGarrett D'Amore 
145195c635efSGarrett D'Amore 
145295c635efSGarrett D'Amore /* ARGSUSED */
145395c635efSGarrett D'Amore static void
termp_sh_post(DECL_ARGS)145495c635efSGarrett D'Amore termp_sh_post(DECL_ARGS)
145595c635efSGarrett D'Amore {
145695c635efSGarrett D'Amore 
145795c635efSGarrett D'Amore 	switch (n->type) {
145895c635efSGarrett D'Amore 	case (MDOC_HEAD):
145995c635efSGarrett D'Amore 		term_newln(p);
146095c635efSGarrett D'Amore 		break;
146195c635efSGarrett D'Amore 	case (MDOC_BODY):
146295c635efSGarrett D'Amore 		term_newln(p);
146395c635efSGarrett D'Amore 		p->offset = 0;
146495c635efSGarrett D'Amore 		break;
146595c635efSGarrett D'Amore 	default:
146695c635efSGarrett D'Amore 		break;
146795c635efSGarrett D'Amore 	}
146895c635efSGarrett D'Amore }
146995c635efSGarrett D'Amore 
147095c635efSGarrett D'Amore 
147195c635efSGarrett D'Amore /* ARGSUSED */
147295c635efSGarrett D'Amore static int
termp_bt_pre(DECL_ARGS)147395c635efSGarrett D'Amore termp_bt_pre(DECL_ARGS)
147495c635efSGarrett D'Amore {
147595c635efSGarrett D'Amore 
147695c635efSGarrett D'Amore 	term_word(p, "is currently in beta test.");
147795c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
147895c635efSGarrett D'Amore 	return(0);
147995c635efSGarrett D'Amore }
148095c635efSGarrett D'Amore 
148195c635efSGarrett D'Amore 
148295c635efSGarrett D'Amore /* ARGSUSED */
148395c635efSGarrett D'Amore static void
termp_lb_post(DECL_ARGS)148495c635efSGarrett D'Amore termp_lb_post(DECL_ARGS)
148595c635efSGarrett D'Amore {
148695c635efSGarrett D'Amore 
148795c635efSGarrett D'Amore 	if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags)
148895c635efSGarrett D'Amore 		term_newln(p);
148995c635efSGarrett D'Amore }
149095c635efSGarrett D'Amore 
149195c635efSGarrett D'Amore 
149295c635efSGarrett D'Amore /* ARGSUSED */
149395c635efSGarrett D'Amore static int
termp_ud_pre(DECL_ARGS)149495c635efSGarrett D'Amore termp_ud_pre(DECL_ARGS)
149595c635efSGarrett D'Amore {
149695c635efSGarrett D'Amore 
149795c635efSGarrett D'Amore 	term_word(p, "currently under development.");
149895c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
149995c635efSGarrett D'Amore 	return(0);
150095c635efSGarrett D'Amore }
150195c635efSGarrett D'Amore 
150295c635efSGarrett D'Amore 
150395c635efSGarrett D'Amore /* ARGSUSED */
150495c635efSGarrett D'Amore static int
termp_d1_pre(DECL_ARGS)150595c635efSGarrett D'Amore termp_d1_pre(DECL_ARGS)
150695c635efSGarrett D'Amore {
150795c635efSGarrett D'Amore 
150895c635efSGarrett D'Amore 	if (MDOC_BLOCK != n->type)
150995c635efSGarrett D'Amore 		return(1);
151095c635efSGarrett D'Amore 	term_newln(p);
151195c635efSGarrett D'Amore 	p->offset += term_len(p, p->defindent + 1);
151295c635efSGarrett D'Amore 	return(1);
151395c635efSGarrett D'Amore }
151495c635efSGarrett D'Amore 
151595c635efSGarrett D'Amore 
151695c635efSGarrett D'Amore /* ARGSUSED */
151795c635efSGarrett D'Amore static int
termp_ft_pre(DECL_ARGS)151895c635efSGarrett D'Amore termp_ft_pre(DECL_ARGS)
151995c635efSGarrett D'Amore {
152095c635efSGarrett D'Amore 
152195c635efSGarrett D'Amore 	/* NB: MDOC_LINE does not effect this! */
152295c635efSGarrett D'Amore 	synopsis_pre(p, n);
152395c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
152495c635efSGarrett D'Amore 	return(1);
152595c635efSGarrett D'Amore }
152695c635efSGarrett D'Amore 
152795c635efSGarrett D'Amore 
152895c635efSGarrett D'Amore /* ARGSUSED */
152995c635efSGarrett D'Amore static int
termp_fn_pre(DECL_ARGS)153095c635efSGarrett D'Amore termp_fn_pre(DECL_ARGS)
153195c635efSGarrett D'Amore {
1532*698f87a4SGarrett D'Amore 	size_t		 rmargin = 0;
153395c635efSGarrett D'Amore 	int		 pretty;
153495c635efSGarrett D'Amore 
153595c635efSGarrett D'Amore 	pretty = MDOC_SYNPRETTY & n->flags;
153695c635efSGarrett D'Amore 
153795c635efSGarrett D'Amore 	synopsis_pre(p, n);
153895c635efSGarrett D'Amore 
153995c635efSGarrett D'Amore 	if (NULL == (n = n->child))
154095c635efSGarrett D'Amore 		return(0);
154195c635efSGarrett D'Amore 
1542*698f87a4SGarrett D'Amore 	if (pretty) {
1543*698f87a4SGarrett D'Amore 		rmargin = p->rmargin;
1544*698f87a4SGarrett D'Amore 		p->rmargin = p->offset + term_len(p, 4);
1545*698f87a4SGarrett D'Amore 		p->flags |= TERMP_NOBREAK | TERMP_HANG;
1546*698f87a4SGarrett D'Amore 	}
1547*698f87a4SGarrett D'Amore 
154895c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
154995c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
155095c635efSGarrett D'Amore 	term_word(p, n->string);
155195c635efSGarrett D'Amore 	term_fontpop(p);
155295c635efSGarrett D'Amore 
1553*698f87a4SGarrett D'Amore 	if (pretty) {
1554*698f87a4SGarrett D'Amore 		term_flushln(p);
1555*698f87a4SGarrett D'Amore 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
1556*698f87a4SGarrett D'Amore 		p->offset = p->rmargin;
1557*698f87a4SGarrett D'Amore 		p->rmargin = rmargin;
1558*698f87a4SGarrett D'Amore 	}
1559*698f87a4SGarrett D'Amore 
156095c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
156195c635efSGarrett D'Amore 	term_word(p, "(");
156295c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
156395c635efSGarrett D'Amore 
156495c635efSGarrett D'Amore 	for (n = n->next; n; n = n->next) {
156595c635efSGarrett D'Amore 		assert(MDOC_TEXT == n->type);
156695c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1567*698f87a4SGarrett D'Amore 		if (pretty)
1568*698f87a4SGarrett D'Amore 			p->flags |= TERMP_NBRWORD;
156995c635efSGarrett D'Amore 		term_word(p, n->string);
157095c635efSGarrett D'Amore 		term_fontpop(p);
157195c635efSGarrett D'Amore 
157295c635efSGarrett D'Amore 		if (n->next) {
157395c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
157495c635efSGarrett D'Amore 			term_word(p, ",");
157595c635efSGarrett D'Amore 		}
157695c635efSGarrett D'Amore 	}
157795c635efSGarrett D'Amore 
157895c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
157995c635efSGarrett D'Amore 	term_word(p, ")");
158095c635efSGarrett D'Amore 
158195c635efSGarrett D'Amore 	if (pretty) {
158295c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
158395c635efSGarrett D'Amore 		term_word(p, ";");
1584*698f87a4SGarrett D'Amore 		term_flushln(p);
158595c635efSGarrett D'Amore 	}
158695c635efSGarrett D'Amore 
158795c635efSGarrett D'Amore 	return(0);
158895c635efSGarrett D'Amore }
158995c635efSGarrett D'Amore 
159095c635efSGarrett D'Amore 
159195c635efSGarrett D'Amore /* ARGSUSED */
159295c635efSGarrett D'Amore static int
termp_fa_pre(DECL_ARGS)159395c635efSGarrett D'Amore termp_fa_pre(DECL_ARGS)
159495c635efSGarrett D'Amore {
159595c635efSGarrett D'Amore 	const struct mdoc_node	*nn;
159695c635efSGarrett D'Amore 
159795c635efSGarrett D'Amore 	if (n->parent->tok != MDOC_Fo) {
159895c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
159995c635efSGarrett D'Amore 		return(1);
160095c635efSGarrett D'Amore 	}
160195c635efSGarrett D'Amore 
160295c635efSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
160395c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1604*698f87a4SGarrett D'Amore 		p->flags |= TERMP_NBRWORD;
160595c635efSGarrett D'Amore 		term_word(p, nn->string);
160695c635efSGarrett D'Amore 		term_fontpop(p);
160795c635efSGarrett D'Amore 
1608*698f87a4SGarrett D'Amore 		if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
160995c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
161095c635efSGarrett D'Amore 			term_word(p, ",");
161195c635efSGarrett D'Amore 		}
161295c635efSGarrett D'Amore 	}
161395c635efSGarrett D'Amore 
161495c635efSGarrett D'Amore 	return(0);
161595c635efSGarrett D'Amore }
161695c635efSGarrett D'Amore 
161795c635efSGarrett D'Amore 
161895c635efSGarrett D'Amore /* ARGSUSED */
161995c635efSGarrett D'Amore static int
termp_bd_pre(DECL_ARGS)162095c635efSGarrett D'Amore termp_bd_pre(DECL_ARGS)
162195c635efSGarrett D'Amore {
162295c635efSGarrett D'Amore 	size_t			 tabwidth, rm, rmax;
1623*698f87a4SGarrett D'Amore 	struct mdoc_node	*nn;
162495c635efSGarrett D'Amore 
162595c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
162695c635efSGarrett D'Amore 		print_bvspace(p, n, n);
162795c635efSGarrett D'Amore 		return(1);
162895c635efSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
162995c635efSGarrett D'Amore 		return(0);
163095c635efSGarrett D'Amore 
163195c635efSGarrett D'Amore 	if (n->norm->Bd.offs)
163295c635efSGarrett D'Amore 		p->offset += a2offs(p, n->norm->Bd.offs);
163395c635efSGarrett D'Amore 
163495c635efSGarrett D'Amore 	/*
163595c635efSGarrett D'Amore 	 * If -ragged or -filled are specified, the block does nothing
163695c635efSGarrett D'Amore 	 * but change the indentation.  If -unfilled or -literal are
163795c635efSGarrett D'Amore 	 * specified, text is printed exactly as entered in the display:
163895c635efSGarrett D'Amore 	 * for macro lines, a newline is appended to the line.  Blank
163995c635efSGarrett D'Amore 	 * lines are allowed.
164095c635efSGarrett D'Amore 	 */
164195c635efSGarrett D'Amore 
164295c635efSGarrett D'Amore 	if (DISP_literal != n->norm->Bd.type &&
164395c635efSGarrett D'Amore 			DISP_unfilled != n->norm->Bd.type)
164495c635efSGarrett D'Amore 		return(1);
164595c635efSGarrett D'Amore 
164695c635efSGarrett D'Amore 	tabwidth = p->tabwidth;
164795c635efSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type)
164895c635efSGarrett D'Amore 		p->tabwidth = term_len(p, 8);
164995c635efSGarrett D'Amore 
165095c635efSGarrett D'Amore 	rm = p->rmargin;
165195c635efSGarrett D'Amore 	rmax = p->maxrmargin;
165295c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
165395c635efSGarrett D'Amore 
165495c635efSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
1655*698f87a4SGarrett D'Amore 		print_mdoc_node(p, pair, meta, nn);
165695c635efSGarrett D'Amore 		/*
165795c635efSGarrett D'Amore 		 * If the printed node flushes its own line, then we
165895c635efSGarrett D'Amore 		 * needn't do it here as well.  This is hacky, but the
165995c635efSGarrett D'Amore 		 * notion of selective eoln whitespace is pretty dumb
166095c635efSGarrett D'Amore 		 * anyway, so don't sweat it.
166195c635efSGarrett D'Amore 		 */
166295c635efSGarrett D'Amore 		switch (nn->tok) {
166395c635efSGarrett D'Amore 		case (MDOC_Sm):
166495c635efSGarrett D'Amore 			/* FALLTHROUGH */
166595c635efSGarrett D'Amore 		case (MDOC_br):
166695c635efSGarrett D'Amore 			/* FALLTHROUGH */
166795c635efSGarrett D'Amore 		case (MDOC_sp):
166895c635efSGarrett D'Amore 			/* FALLTHROUGH */
166995c635efSGarrett D'Amore 		case (MDOC_Bl):
167095c635efSGarrett D'Amore 			/* FALLTHROUGH */
167195c635efSGarrett D'Amore 		case (MDOC_D1):
167295c635efSGarrett D'Amore 			/* FALLTHROUGH */
167395c635efSGarrett D'Amore 		case (MDOC_Dl):
167495c635efSGarrett D'Amore 			/* FALLTHROUGH */
167595c635efSGarrett D'Amore 		case (MDOC_Lp):
167695c635efSGarrett D'Amore 			/* FALLTHROUGH */
167795c635efSGarrett D'Amore 		case (MDOC_Pp):
167895c635efSGarrett D'Amore 			continue;
167995c635efSGarrett D'Amore 		default:
168095c635efSGarrett D'Amore 			break;
168195c635efSGarrett D'Amore 		}
168295c635efSGarrett D'Amore 		if (nn->next && nn->next->line == nn->line)
168395c635efSGarrett D'Amore 			continue;
168495c635efSGarrett D'Amore 		term_flushln(p);
168595c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
168695c635efSGarrett D'Amore 	}
168795c635efSGarrett D'Amore 
168895c635efSGarrett D'Amore 	p->tabwidth = tabwidth;
168995c635efSGarrett D'Amore 	p->rmargin = rm;
169095c635efSGarrett D'Amore 	p->maxrmargin = rmax;
169195c635efSGarrett D'Amore 	return(0);
169295c635efSGarrett D'Amore }
169395c635efSGarrett D'Amore 
169495c635efSGarrett D'Amore 
169595c635efSGarrett D'Amore /* ARGSUSED */
169695c635efSGarrett D'Amore static void
termp_bd_post(DECL_ARGS)169795c635efSGarrett D'Amore termp_bd_post(DECL_ARGS)
169895c635efSGarrett D'Amore {
169995c635efSGarrett D'Amore 	size_t		 rm, rmax;
170095c635efSGarrett D'Amore 
170195c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
170295c635efSGarrett D'Amore 		return;
170395c635efSGarrett D'Amore 
170495c635efSGarrett D'Amore 	rm = p->rmargin;
170595c635efSGarrett D'Amore 	rmax = p->maxrmargin;
170695c635efSGarrett D'Amore 
170795c635efSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type ||
170895c635efSGarrett D'Amore 			DISP_unfilled == n->norm->Bd.type)
170995c635efSGarrett D'Amore 		p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
171095c635efSGarrett D'Amore 
171195c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
171295c635efSGarrett D'Amore 	term_newln(p);
171395c635efSGarrett D'Amore 
171495c635efSGarrett D'Amore 	p->rmargin = rm;
171595c635efSGarrett D'Amore 	p->maxrmargin = rmax;
171695c635efSGarrett D'Amore }
171795c635efSGarrett D'Amore 
171895c635efSGarrett D'Amore 
171995c635efSGarrett D'Amore /* ARGSUSED */
172095c635efSGarrett D'Amore static int
termp_bx_pre(DECL_ARGS)172195c635efSGarrett D'Amore termp_bx_pre(DECL_ARGS)
172295c635efSGarrett D'Amore {
172395c635efSGarrett D'Amore 
172495c635efSGarrett D'Amore 	if (NULL != (n = n->child)) {
172595c635efSGarrett D'Amore 		term_word(p, n->string);
172695c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
172795c635efSGarrett D'Amore 		term_word(p, "BSD");
172895c635efSGarrett D'Amore 	} else {
172995c635efSGarrett D'Amore 		term_word(p, "BSD");
173095c635efSGarrett D'Amore 		return(0);
173195c635efSGarrett D'Amore 	}
173295c635efSGarrett D'Amore 
173395c635efSGarrett D'Amore 	if (NULL != (n = n->next)) {
173495c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
173595c635efSGarrett D'Amore 		term_word(p, "-");
173695c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
173795c635efSGarrett D'Amore 		term_word(p, n->string);
173895c635efSGarrett D'Amore 	}
173995c635efSGarrett D'Amore 
174095c635efSGarrett D'Amore 	return(0);
174195c635efSGarrett D'Amore }
174295c635efSGarrett D'Amore 
174395c635efSGarrett D'Amore 
174495c635efSGarrett D'Amore /* ARGSUSED */
174595c635efSGarrett D'Amore static int
termp_xx_pre(DECL_ARGS)174695c635efSGarrett D'Amore termp_xx_pre(DECL_ARGS)
174795c635efSGarrett D'Amore {
174895c635efSGarrett D'Amore 	const char	*pp;
174995c635efSGarrett D'Amore 	int		 flags;
175095c635efSGarrett D'Amore 
175195c635efSGarrett D'Amore 	pp = NULL;
175295c635efSGarrett D'Amore 	switch (n->tok) {
175395c635efSGarrett D'Amore 	case (MDOC_Bsx):
175495c635efSGarrett D'Amore 		pp = "BSD/OS";
175595c635efSGarrett D'Amore 		break;
175695c635efSGarrett D'Amore 	case (MDOC_Dx):
175795c635efSGarrett D'Amore 		pp = "DragonFly";
175895c635efSGarrett D'Amore 		break;
175995c635efSGarrett D'Amore 	case (MDOC_Fx):
176095c635efSGarrett D'Amore 		pp = "FreeBSD";
176195c635efSGarrett D'Amore 		break;
176295c635efSGarrett D'Amore 	case (MDOC_Nx):
176395c635efSGarrett D'Amore 		pp = "NetBSD";
176495c635efSGarrett D'Amore 		break;
176595c635efSGarrett D'Amore 	case (MDOC_Ox):
176695c635efSGarrett D'Amore 		pp = "OpenBSD";
176795c635efSGarrett D'Amore 		break;
176895c635efSGarrett D'Amore 	case (MDOC_Ux):
176995c635efSGarrett D'Amore 		pp = "UNIX";
177095c635efSGarrett D'Amore 		break;
177195c635efSGarrett D'Amore 	default:
1772*698f87a4SGarrett D'Amore 		abort();
1773*698f87a4SGarrett D'Amore 		/* NOTREACHED */
177495c635efSGarrett D'Amore 	}
177595c635efSGarrett D'Amore 
177695c635efSGarrett D'Amore 	term_word(p, pp);
177795c635efSGarrett D'Amore 	if (n->child) {
177895c635efSGarrett D'Amore 		flags = p->flags;
177995c635efSGarrett D'Amore 		p->flags |= TERMP_KEEP;
178095c635efSGarrett D'Amore 		term_word(p, n->child->string);
178195c635efSGarrett D'Amore 		p->flags = flags;
178295c635efSGarrett D'Amore 	}
178395c635efSGarrett D'Amore 	return(0);
178495c635efSGarrett D'Amore }
178595c635efSGarrett D'Amore 
178695c635efSGarrett D'Amore 
178795c635efSGarrett D'Amore /* ARGSUSED */
178895c635efSGarrett D'Amore static void
termp_pf_post(DECL_ARGS)178995c635efSGarrett D'Amore termp_pf_post(DECL_ARGS)
179095c635efSGarrett D'Amore {
179195c635efSGarrett D'Amore 
179295c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
179395c635efSGarrett D'Amore }
179495c635efSGarrett D'Amore 
179595c635efSGarrett D'Amore 
179695c635efSGarrett D'Amore /* ARGSUSED */
179795c635efSGarrett D'Amore static int
termp_ss_pre(DECL_ARGS)179895c635efSGarrett D'Amore termp_ss_pre(DECL_ARGS)
179995c635efSGarrett D'Amore {
180095c635efSGarrett D'Amore 
180195c635efSGarrett D'Amore 	switch (n->type) {
180295c635efSGarrett D'Amore 	case (MDOC_BLOCK):
180395c635efSGarrett D'Amore 		term_newln(p);
180495c635efSGarrett D'Amore 		if (n->prev)
180595c635efSGarrett D'Amore 			term_vspace(p);
180695c635efSGarrett D'Amore 		break;
180795c635efSGarrett D'Amore 	case (MDOC_HEAD):
180895c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
180995c635efSGarrett D'Amore 		p->offset = term_len(p, (p->defindent+1)/2);
181095c635efSGarrett D'Amore 		break;
181195c635efSGarrett D'Amore 	default:
181295c635efSGarrett D'Amore 		break;
181395c635efSGarrett D'Amore 	}
181495c635efSGarrett D'Amore 
181595c635efSGarrett D'Amore 	return(1);
181695c635efSGarrett D'Amore }
181795c635efSGarrett D'Amore 
181895c635efSGarrett D'Amore 
181995c635efSGarrett D'Amore /* ARGSUSED */
182095c635efSGarrett D'Amore static void
termp_ss_post(DECL_ARGS)182195c635efSGarrett D'Amore termp_ss_post(DECL_ARGS)
182295c635efSGarrett D'Amore {
182395c635efSGarrett D'Amore 
182495c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
182595c635efSGarrett D'Amore 		term_newln(p);
182695c635efSGarrett D'Amore }
182795c635efSGarrett D'Amore 
182895c635efSGarrett D'Amore 
182995c635efSGarrett D'Amore /* ARGSUSED */
183095c635efSGarrett D'Amore static int
termp_cd_pre(DECL_ARGS)183195c635efSGarrett D'Amore termp_cd_pre(DECL_ARGS)
183295c635efSGarrett D'Amore {
183395c635efSGarrett D'Amore 
183495c635efSGarrett D'Amore 	synopsis_pre(p, n);
183595c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
183695c635efSGarrett D'Amore 	return(1);
183795c635efSGarrett D'Amore }
183895c635efSGarrett D'Amore 
183995c635efSGarrett D'Amore 
184095c635efSGarrett D'Amore /* ARGSUSED */
184195c635efSGarrett D'Amore static int
termp_in_pre(DECL_ARGS)184295c635efSGarrett D'Amore termp_in_pre(DECL_ARGS)
184395c635efSGarrett D'Amore {
184495c635efSGarrett D'Amore 
184595c635efSGarrett D'Amore 	synopsis_pre(p, n);
184695c635efSGarrett D'Amore 
184795c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags) {
184895c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
184995c635efSGarrett D'Amore 		term_word(p, "#include");
185095c635efSGarrett D'Amore 		term_word(p, "<");
185195c635efSGarrett D'Amore 	} else {
185295c635efSGarrett D'Amore 		term_word(p, "<");
185395c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
185495c635efSGarrett D'Amore 	}
185595c635efSGarrett D'Amore 
185695c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
185795c635efSGarrett D'Amore 	return(1);
185895c635efSGarrett D'Amore }
185995c635efSGarrett D'Amore 
186095c635efSGarrett D'Amore 
186195c635efSGarrett D'Amore /* ARGSUSED */
186295c635efSGarrett D'Amore static void
termp_in_post(DECL_ARGS)186395c635efSGarrett D'Amore termp_in_post(DECL_ARGS)
186495c635efSGarrett D'Amore {
186595c635efSGarrett D'Amore 
186695c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
186795c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
186895c635efSGarrett D'Amore 
186995c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
187095c635efSGarrett D'Amore 	term_word(p, ">");
187195c635efSGarrett D'Amore 
187295c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
187395c635efSGarrett D'Amore 		term_fontpop(p);
187495c635efSGarrett D'Amore }
187595c635efSGarrett D'Amore 
187695c635efSGarrett D'Amore 
187795c635efSGarrett D'Amore /* ARGSUSED */
187895c635efSGarrett D'Amore static int
termp_sp_pre(DECL_ARGS)187995c635efSGarrett D'Amore termp_sp_pre(DECL_ARGS)
188095c635efSGarrett D'Amore {
188195c635efSGarrett D'Amore 	size_t		 i, len;
188295c635efSGarrett D'Amore 
188395c635efSGarrett D'Amore 	switch (n->tok) {
188495c635efSGarrett D'Amore 	case (MDOC_sp):
188595c635efSGarrett D'Amore 		len = n->child ? a2height(p, n->child->string) : 1;
188695c635efSGarrett D'Amore 		break;
188795c635efSGarrett D'Amore 	case (MDOC_br):
188895c635efSGarrett D'Amore 		len = 0;
188995c635efSGarrett D'Amore 		break;
189095c635efSGarrett D'Amore 	default:
189195c635efSGarrett D'Amore 		len = 1;
189295c635efSGarrett D'Amore 		break;
189395c635efSGarrett D'Amore 	}
189495c635efSGarrett D'Amore 
189595c635efSGarrett D'Amore 	if (0 == len)
189695c635efSGarrett D'Amore 		term_newln(p);
189795c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
189895c635efSGarrett D'Amore 		term_vspace(p);
189995c635efSGarrett D'Amore 
190095c635efSGarrett D'Amore 	return(0);
190195c635efSGarrett D'Amore }
190295c635efSGarrett D'Amore 
190395c635efSGarrett D'Amore 
190495c635efSGarrett D'Amore /* ARGSUSED */
190595c635efSGarrett D'Amore static int
termp_quote_pre(DECL_ARGS)190695c635efSGarrett D'Amore termp_quote_pre(DECL_ARGS)
190795c635efSGarrett D'Amore {
190895c635efSGarrett D'Amore 
190995c635efSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
191095c635efSGarrett D'Amore 		return(1);
191195c635efSGarrett D'Amore 
191295c635efSGarrett D'Amore 	switch (n->tok) {
191395c635efSGarrett D'Amore 	case (MDOC_Ao):
191495c635efSGarrett D'Amore 		/* FALLTHROUGH */
191595c635efSGarrett D'Amore 	case (MDOC_Aq):
191695c635efSGarrett D'Amore 		term_word(p, "<");
191795c635efSGarrett D'Amore 		break;
191895c635efSGarrett D'Amore 	case (MDOC_Bro):
191995c635efSGarrett D'Amore 		/* FALLTHROUGH */
192095c635efSGarrett D'Amore 	case (MDOC_Brq):
192195c635efSGarrett D'Amore 		term_word(p, "{");
192295c635efSGarrett D'Amore 		break;
192395c635efSGarrett D'Amore 	case (MDOC_Oo):
192495c635efSGarrett D'Amore 		/* FALLTHROUGH */
192595c635efSGarrett D'Amore 	case (MDOC_Op):
192695c635efSGarrett D'Amore 		/* FALLTHROUGH */
192795c635efSGarrett D'Amore 	case (MDOC_Bo):
192895c635efSGarrett D'Amore 		/* FALLTHROUGH */
192995c635efSGarrett D'Amore 	case (MDOC_Bq):
193095c635efSGarrett D'Amore 		term_word(p, "[");
193195c635efSGarrett D'Amore 		break;
193295c635efSGarrett D'Amore 	case (MDOC_Do):
193395c635efSGarrett D'Amore 		/* FALLTHROUGH */
193495c635efSGarrett D'Amore 	case (MDOC_Dq):
1935*698f87a4SGarrett D'Amore 		term_word(p, "\\(lq");
193695c635efSGarrett D'Amore 		break;
193795c635efSGarrett D'Amore 	case (MDOC_Eo):
193895c635efSGarrett D'Amore 		break;
193995c635efSGarrett D'Amore 	case (MDOC_Po):
194095c635efSGarrett D'Amore 		/* FALLTHROUGH */
194195c635efSGarrett D'Amore 	case (MDOC_Pq):
194295c635efSGarrett D'Amore 		term_word(p, "(");
194395c635efSGarrett D'Amore 		break;
194495c635efSGarrett D'Amore 	case (MDOC__T):
194595c635efSGarrett D'Amore 		/* FALLTHROUGH */
194695c635efSGarrett D'Amore 	case (MDOC_Qo):
194795c635efSGarrett D'Amore 		/* FALLTHROUGH */
194895c635efSGarrett D'Amore 	case (MDOC_Qq):
194995c635efSGarrett D'Amore 		term_word(p, "\"");
195095c635efSGarrett D'Amore 		break;
195195c635efSGarrett D'Amore 	case (MDOC_Ql):
195295c635efSGarrett D'Amore 		/* FALLTHROUGH */
195395c635efSGarrett D'Amore 	case (MDOC_So):
195495c635efSGarrett D'Amore 		/* FALLTHROUGH */
195595c635efSGarrett D'Amore 	case (MDOC_Sq):
1956*698f87a4SGarrett D'Amore 		term_word(p, "\\(oq");
195795c635efSGarrett D'Amore 		break;
195895c635efSGarrett D'Amore 	default:
195995c635efSGarrett D'Amore 		abort();
196095c635efSGarrett D'Amore 		/* NOTREACHED */
196195c635efSGarrett D'Amore 	}
196295c635efSGarrett D'Amore 
196395c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
196495c635efSGarrett D'Amore 	return(1);
196595c635efSGarrett D'Amore }
196695c635efSGarrett D'Amore 
196795c635efSGarrett D'Amore 
196895c635efSGarrett D'Amore /* ARGSUSED */
196995c635efSGarrett D'Amore static void
termp_quote_post(DECL_ARGS)197095c635efSGarrett D'Amore termp_quote_post(DECL_ARGS)
197195c635efSGarrett D'Amore {
197295c635efSGarrett D'Amore 
197395c635efSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
197495c635efSGarrett D'Amore 		return;
197595c635efSGarrett D'Amore 
197695c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
197795c635efSGarrett D'Amore 
197895c635efSGarrett D'Amore 	switch (n->tok) {
197995c635efSGarrett D'Amore 	case (MDOC_Ao):
198095c635efSGarrett D'Amore 		/* FALLTHROUGH */
198195c635efSGarrett D'Amore 	case (MDOC_Aq):
198295c635efSGarrett D'Amore 		term_word(p, ">");
198395c635efSGarrett D'Amore 		break;
198495c635efSGarrett D'Amore 	case (MDOC_Bro):
198595c635efSGarrett D'Amore 		/* FALLTHROUGH */
198695c635efSGarrett D'Amore 	case (MDOC_Brq):
198795c635efSGarrett D'Amore 		term_word(p, "}");
198895c635efSGarrett D'Amore 		break;
198995c635efSGarrett D'Amore 	case (MDOC_Oo):
199095c635efSGarrett D'Amore 		/* FALLTHROUGH */
199195c635efSGarrett D'Amore 	case (MDOC_Op):
199295c635efSGarrett D'Amore 		/* FALLTHROUGH */
199395c635efSGarrett D'Amore 	case (MDOC_Bo):
199495c635efSGarrett D'Amore 		/* FALLTHROUGH */
199595c635efSGarrett D'Amore 	case (MDOC_Bq):
199695c635efSGarrett D'Amore 		term_word(p, "]");
199795c635efSGarrett D'Amore 		break;
199895c635efSGarrett D'Amore 	case (MDOC_Do):
199995c635efSGarrett D'Amore 		/* FALLTHROUGH */
200095c635efSGarrett D'Amore 	case (MDOC_Dq):
2001*698f87a4SGarrett D'Amore 		term_word(p, "\\(rq");
200295c635efSGarrett D'Amore 		break;
200395c635efSGarrett D'Amore 	case (MDOC_Eo):
200495c635efSGarrett D'Amore 		break;
200595c635efSGarrett D'Amore 	case (MDOC_Po):
200695c635efSGarrett D'Amore 		/* FALLTHROUGH */
200795c635efSGarrett D'Amore 	case (MDOC_Pq):
200895c635efSGarrett D'Amore 		term_word(p, ")");
200995c635efSGarrett D'Amore 		break;
201095c635efSGarrett D'Amore 	case (MDOC__T):
201195c635efSGarrett D'Amore 		/* FALLTHROUGH */
201295c635efSGarrett D'Amore 	case (MDOC_Qo):
201395c635efSGarrett D'Amore 		/* FALLTHROUGH */
201495c635efSGarrett D'Amore 	case (MDOC_Qq):
201595c635efSGarrett D'Amore 		term_word(p, "\"");
201695c635efSGarrett D'Amore 		break;
201795c635efSGarrett D'Amore 	case (MDOC_Ql):
201895c635efSGarrett D'Amore 		/* FALLTHROUGH */
201995c635efSGarrett D'Amore 	case (MDOC_So):
202095c635efSGarrett D'Amore 		/* FALLTHROUGH */
202195c635efSGarrett D'Amore 	case (MDOC_Sq):
2022*698f87a4SGarrett D'Amore 		term_word(p, "\\(cq");
202395c635efSGarrett D'Amore 		break;
202495c635efSGarrett D'Amore 	default:
202595c635efSGarrett D'Amore 		abort();
202695c635efSGarrett D'Amore 		/* NOTREACHED */
202795c635efSGarrett D'Amore 	}
202895c635efSGarrett D'Amore }
202995c635efSGarrett D'Amore 
203095c635efSGarrett D'Amore 
203195c635efSGarrett D'Amore /* ARGSUSED */
203295c635efSGarrett D'Amore static int
termp_fo_pre(DECL_ARGS)203395c635efSGarrett D'Amore termp_fo_pre(DECL_ARGS)
203495c635efSGarrett D'Amore {
2035*698f87a4SGarrett D'Amore 	size_t		 rmargin = 0;
2036*698f87a4SGarrett D'Amore 	int		 pretty;
2037*698f87a4SGarrett D'Amore 
2038*698f87a4SGarrett D'Amore 	pretty = MDOC_SYNPRETTY & n->flags;
203995c635efSGarrett D'Amore 
204095c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
204195c635efSGarrett D'Amore 		synopsis_pre(p, n);
204295c635efSGarrett D'Amore 		return(1);
204395c635efSGarrett D'Amore 	} else if (MDOC_BODY == n->type) {
2044*698f87a4SGarrett D'Amore 		if (pretty) {
2045*698f87a4SGarrett D'Amore 			rmargin = p->rmargin;
2046*698f87a4SGarrett D'Amore 			p->rmargin = p->offset + term_len(p, 4);
2047*698f87a4SGarrett D'Amore 			p->flags |= TERMP_NOBREAK | TERMP_HANG;
2048*698f87a4SGarrett D'Amore 		}
204995c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
205095c635efSGarrett D'Amore 		term_word(p, "(");
205195c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
2052*698f87a4SGarrett D'Amore 		if (pretty) {
2053*698f87a4SGarrett D'Amore 			term_flushln(p);
2054*698f87a4SGarrett D'Amore 			p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
2055*698f87a4SGarrett D'Amore 			p->offset = p->rmargin;
2056*698f87a4SGarrett D'Amore 			p->rmargin = rmargin;
2057*698f87a4SGarrett D'Amore 		}
205895c635efSGarrett D'Amore 		return(1);
205995c635efSGarrett D'Amore 	}
206095c635efSGarrett D'Amore 
206195c635efSGarrett D'Amore 	if (NULL == n->child)
206295c635efSGarrett D'Amore 		return(0);
206395c635efSGarrett D'Amore 
206495c635efSGarrett D'Amore 	/* XXX: we drop non-initial arguments as per groff. */
206595c635efSGarrett D'Amore 
206695c635efSGarrett D'Amore 	assert(n->child->string);
206795c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
206895c635efSGarrett D'Amore 	term_word(p, n->child->string);
206995c635efSGarrett D'Amore 	return(0);
207095c635efSGarrett D'Amore }
207195c635efSGarrett D'Amore 
207295c635efSGarrett D'Amore 
207395c635efSGarrett D'Amore /* ARGSUSED */
207495c635efSGarrett D'Amore static void
termp_fo_post(DECL_ARGS)207595c635efSGarrett D'Amore termp_fo_post(DECL_ARGS)
207695c635efSGarrett D'Amore {
207795c635efSGarrett D'Amore 
207895c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
207995c635efSGarrett D'Amore 		return;
208095c635efSGarrett D'Amore 
208195c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
208295c635efSGarrett D'Amore 	term_word(p, ")");
208395c635efSGarrett D'Amore 
208495c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags) {
208595c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
208695c635efSGarrett D'Amore 		term_word(p, ";");
2087*698f87a4SGarrett D'Amore 		term_flushln(p);
208895c635efSGarrett D'Amore 	}
208995c635efSGarrett D'Amore }
209095c635efSGarrett D'Amore 
209195c635efSGarrett D'Amore 
209295c635efSGarrett D'Amore /* ARGSUSED */
209395c635efSGarrett D'Amore static int
termp_bf_pre(DECL_ARGS)209495c635efSGarrett D'Amore termp_bf_pre(DECL_ARGS)
209595c635efSGarrett D'Amore {
209695c635efSGarrett D'Amore 
209795c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
209895c635efSGarrett D'Amore 		return(0);
2099*698f87a4SGarrett D'Amore 	else if (MDOC_BODY != n->type)
210095c635efSGarrett D'Amore 		return(1);
210195c635efSGarrett D'Amore 
210295c635efSGarrett D'Amore 	if (FONT_Em == n->norm->Bf.font)
210395c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
210495c635efSGarrett D'Amore 	else if (FONT_Sy == n->norm->Bf.font)
210595c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
210695c635efSGarrett D'Amore 	else
210795c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_NONE);
210895c635efSGarrett D'Amore 
210995c635efSGarrett D'Amore 	return(1);
211095c635efSGarrett D'Amore }
211195c635efSGarrett D'Amore 
211295c635efSGarrett D'Amore 
211395c635efSGarrett D'Amore /* ARGSUSED */
211495c635efSGarrett D'Amore static int
termp_sm_pre(DECL_ARGS)211595c635efSGarrett D'Amore termp_sm_pre(DECL_ARGS)
211695c635efSGarrett D'Amore {
211795c635efSGarrett D'Amore 
211895c635efSGarrett D'Amore 	assert(n->child && MDOC_TEXT == n->child->type);
211995c635efSGarrett D'Amore 	if (0 == strcmp("on", n->child->string)) {
212095c635efSGarrett D'Amore 		if (p->col)
212195c635efSGarrett D'Amore 			p->flags &= ~TERMP_NOSPACE;
212295c635efSGarrett D'Amore 		p->flags &= ~TERMP_NONOSPACE;
212395c635efSGarrett D'Amore 	} else
212495c635efSGarrett D'Amore 		p->flags |= TERMP_NONOSPACE;
212595c635efSGarrett D'Amore 
212695c635efSGarrett D'Amore 	return(0);
212795c635efSGarrett D'Amore }
212895c635efSGarrett D'Amore 
212995c635efSGarrett D'Amore 
213095c635efSGarrett D'Amore /* ARGSUSED */
213195c635efSGarrett D'Amore static int
termp_ap_pre(DECL_ARGS)213295c635efSGarrett D'Amore termp_ap_pre(DECL_ARGS)
213395c635efSGarrett D'Amore {
213495c635efSGarrett D'Amore 
213595c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
213695c635efSGarrett D'Amore 	term_word(p, "'");
213795c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
213895c635efSGarrett D'Amore 	return(1);
213995c635efSGarrett D'Amore }
214095c635efSGarrett D'Amore 
214195c635efSGarrett D'Amore 
214295c635efSGarrett D'Amore /* ARGSUSED */
214395c635efSGarrett D'Amore static void
termp____post(DECL_ARGS)214495c635efSGarrett D'Amore termp____post(DECL_ARGS)
214595c635efSGarrett D'Amore {
214695c635efSGarrett D'Amore 
214795c635efSGarrett D'Amore 	/*
214895c635efSGarrett D'Amore 	 * Handle lists of authors.  In general, print each followed by
214995c635efSGarrett D'Amore 	 * a comma.  Don't print the comma if there are only two
215095c635efSGarrett D'Amore 	 * authors.
215195c635efSGarrett D'Amore 	 */
215295c635efSGarrett D'Amore 	if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
215395c635efSGarrett D'Amore 		if (NULL == n->next->next || MDOC__A != n->next->next->tok)
215495c635efSGarrett D'Amore 			if (NULL == n->prev || MDOC__A != n->prev->tok)
215595c635efSGarrett D'Amore 				return;
215695c635efSGarrett D'Amore 
215795c635efSGarrett D'Amore 	/* TODO: %U. */
215895c635efSGarrett D'Amore 
215995c635efSGarrett D'Amore 	if (NULL == n->parent || MDOC_Rs != n->parent->tok)
216095c635efSGarrett D'Amore 		return;
216195c635efSGarrett D'Amore 
216295c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
216395c635efSGarrett D'Amore 	if (NULL == n->next) {
216495c635efSGarrett D'Amore 		term_word(p, ".");
216595c635efSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
216695c635efSGarrett D'Amore 	} else
216795c635efSGarrett D'Amore 		term_word(p, ",");
216895c635efSGarrett D'Amore }
216995c635efSGarrett D'Amore 
217095c635efSGarrett D'Amore 
217195c635efSGarrett D'Amore /* ARGSUSED */
217295c635efSGarrett D'Amore static int
termp_li_pre(DECL_ARGS)217395c635efSGarrett D'Amore termp_li_pre(DECL_ARGS)
217495c635efSGarrett D'Amore {
217595c635efSGarrett D'Amore 
217695c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_NONE);
217795c635efSGarrett D'Amore 	return(1);
217895c635efSGarrett D'Amore }
217995c635efSGarrett D'Amore 
218095c635efSGarrett D'Amore 
218195c635efSGarrett D'Amore /* ARGSUSED */
218295c635efSGarrett D'Amore static int
termp_lk_pre(DECL_ARGS)218395c635efSGarrett D'Amore termp_lk_pre(DECL_ARGS)
218495c635efSGarrett D'Amore {
2185*698f87a4SGarrett D'Amore 	const struct mdoc_node *link, *descr;
218695c635efSGarrett D'Amore 
2187*698f87a4SGarrett D'Amore 	if (NULL == (link = n->child))
2188*698f87a4SGarrett D'Amore 		return(0);
2189*698f87a4SGarrett D'Amore 
2190*698f87a4SGarrett D'Amore 	if (NULL != (descr = link->next)) {
219195c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
2192*698f87a4SGarrett D'Amore 		while (NULL != descr) {
2193*698f87a4SGarrett D'Amore 			term_word(p, descr->string);
2194*698f87a4SGarrett D'Amore 			descr = descr->next;
2195*698f87a4SGarrett D'Amore 		}
219695c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
219795c635efSGarrett D'Amore 		term_word(p, ":");
2198*698f87a4SGarrett D'Amore 		term_fontpop(p);
2199*698f87a4SGarrett D'Amore 	}
220095c635efSGarrett D'Amore 
220195c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
2202*698f87a4SGarrett D'Amore 	term_word(p, link->string);
220395c635efSGarrett D'Amore 	term_fontpop(p);
220495c635efSGarrett D'Amore 
220595c635efSGarrett D'Amore 	return(0);
220695c635efSGarrett D'Amore }
220795c635efSGarrett D'Amore 
220895c635efSGarrett D'Amore 
220995c635efSGarrett D'Amore /* ARGSUSED */
221095c635efSGarrett D'Amore static int
termp_bk_pre(DECL_ARGS)221195c635efSGarrett D'Amore termp_bk_pre(DECL_ARGS)
221295c635efSGarrett D'Amore {
221395c635efSGarrett D'Amore 
221495c635efSGarrett D'Amore 	switch (n->type) {
221595c635efSGarrett D'Amore 	case (MDOC_BLOCK):
221695c635efSGarrett D'Amore 		break;
221795c635efSGarrett D'Amore 	case (MDOC_HEAD):
221895c635efSGarrett D'Amore 		return(0);
221995c635efSGarrett D'Amore 	case (MDOC_BODY):
222095c635efSGarrett D'Amore 		if (n->parent->args || 0 == n->prev->nchild)
222195c635efSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
222295c635efSGarrett D'Amore 		break;
222395c635efSGarrett D'Amore 	default:
222495c635efSGarrett D'Amore 		abort();
222595c635efSGarrett D'Amore 		/* NOTREACHED */
222695c635efSGarrett D'Amore 	}
222795c635efSGarrett D'Amore 
222895c635efSGarrett D'Amore 	return(1);
222995c635efSGarrett D'Amore }
223095c635efSGarrett D'Amore 
223195c635efSGarrett D'Amore 
223295c635efSGarrett D'Amore /* ARGSUSED */
223395c635efSGarrett D'Amore static void
termp_bk_post(DECL_ARGS)223495c635efSGarrett D'Amore termp_bk_post(DECL_ARGS)
223595c635efSGarrett D'Amore {
223695c635efSGarrett D'Amore 
223795c635efSGarrett D'Amore 	if (MDOC_BODY == n->type)
223895c635efSGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
223995c635efSGarrett D'Amore }
224095c635efSGarrett D'Amore 
224195c635efSGarrett D'Amore /* ARGSUSED */
224295c635efSGarrett D'Amore static void
termp__t_post(DECL_ARGS)224395c635efSGarrett D'Amore termp__t_post(DECL_ARGS)
224495c635efSGarrett D'Amore {
224595c635efSGarrett D'Amore 
224695c635efSGarrett D'Amore 	/*
224795c635efSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
224895c635efSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
224995c635efSGarrett D'Amore 	 */
225095c635efSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
225195c635efSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2252*698f87a4SGarrett D'Amore 		termp_quote_post(p, pair, meta, n);
225395c635efSGarrett D'Amore 
2254*698f87a4SGarrett D'Amore 	termp____post(p, pair, meta, n);
225595c635efSGarrett D'Amore }
225695c635efSGarrett D'Amore 
225795c635efSGarrett D'Amore /* ARGSUSED */
225895c635efSGarrett D'Amore static int
termp__t_pre(DECL_ARGS)225995c635efSGarrett D'Amore termp__t_pre(DECL_ARGS)
226095c635efSGarrett D'Amore {
226195c635efSGarrett D'Amore 
226295c635efSGarrett D'Amore 	/*
226395c635efSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
226495c635efSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
226595c635efSGarrett D'Amore 	 */
226695c635efSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
226795c635efSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2268*698f87a4SGarrett D'Amore 		return(termp_quote_pre(p, pair, meta, n));
226995c635efSGarrett D'Amore 
227095c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
227195c635efSGarrett D'Amore 	return(1);
227295c635efSGarrett D'Amore }
227395c635efSGarrett D'Amore 
227495c635efSGarrett D'Amore /* ARGSUSED */
227595c635efSGarrett D'Amore static int
termp_under_pre(DECL_ARGS)227695c635efSGarrett D'Amore termp_under_pre(DECL_ARGS)
227795c635efSGarrett D'Amore {
227895c635efSGarrett D'Amore 
227995c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
228095c635efSGarrett D'Amore 	return(1);
228195c635efSGarrett D'Amore }
2282