xref: /titanic_41/usr/src/cmd/mandoc/mdoc_term.c (revision ffb8ebfab4941f959e7caea93ecfb348cfa3515e)
1*ffb8ebfaSGarrett D'Amore /*	$Id: mdoc_term.c,v 1.258 2013/12/25 21:24:12 schwarze Exp $ */
232a712daSGarrett D'Amore /*
332a712daSGarrett D'Amore  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*ffb8ebfaSGarrett D'Amore  * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5*ffb8ebfaSGarrett D'Amore  * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
632a712daSGarrett D'Amore  *
732a712daSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
832a712daSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
932a712daSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
1032a712daSGarrett D'Amore  *
1132a712daSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1232a712daSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1332a712daSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1432a712daSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1532a712daSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1632a712daSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1732a712daSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1832a712daSGarrett D'Amore  */
1932a712daSGarrett D'Amore #ifdef HAVE_CONFIG_H
2032a712daSGarrett D'Amore #include "config.h"
2132a712daSGarrett D'Amore #endif
2232a712daSGarrett D'Amore 
2332a712daSGarrett D'Amore #include <sys/types.h>
2432a712daSGarrett D'Amore 
2532a712daSGarrett D'Amore #include <assert.h>
2632a712daSGarrett D'Amore #include <ctype.h>
2732a712daSGarrett D'Amore #include <stdint.h>
2832a712daSGarrett D'Amore #include <stdio.h>
2932a712daSGarrett D'Amore #include <stdlib.h>
3032a712daSGarrett D'Amore #include <string.h>
3132a712daSGarrett D'Amore 
3232a712daSGarrett D'Amore #include "mandoc.h"
3332a712daSGarrett D'Amore #include "out.h"
3432a712daSGarrett D'Amore #include "term.h"
3532a712daSGarrett D'Amore #include "mdoc.h"
3632a712daSGarrett D'Amore #include "main.h"
3732a712daSGarrett D'Amore 
3832a712daSGarrett D'Amore struct	termpair {
3932a712daSGarrett D'Amore 	struct termpair	 *ppair;
4032a712daSGarrett D'Amore 	int		  count;
4132a712daSGarrett D'Amore };
4232a712daSGarrett D'Amore 
4332a712daSGarrett D'Amore #define	DECL_ARGS struct termp *p, \
4432a712daSGarrett D'Amore 		  struct termpair *pair, \
45*ffb8ebfaSGarrett D'Amore 	  	  const struct mdoc_meta *meta, \
46*ffb8ebfaSGarrett D'Amore 		  struct mdoc_node *n
4732a712daSGarrett D'Amore 
4832a712daSGarrett D'Amore struct	termact {
4932a712daSGarrett D'Amore 	int	(*pre)(DECL_ARGS);
5032a712daSGarrett D'Amore 	void	(*post)(DECL_ARGS);
5132a712daSGarrett D'Amore };
5232a712daSGarrett D'Amore 
5332a712daSGarrett D'Amore static	size_t	  a2width(const struct termp *, const char *);
5432a712daSGarrett D'Amore static	size_t	  a2height(const struct termp *, const char *);
5532a712daSGarrett D'Amore static	size_t	  a2offs(const struct termp *, const char *);
5632a712daSGarrett D'Amore 
5732a712daSGarrett D'Amore static	void	  print_bvspace(struct termp *,
5832a712daSGarrett D'Amore 			const struct mdoc_node *,
5932a712daSGarrett D'Amore 			const struct mdoc_node *);
6032a712daSGarrett D'Amore static	void  	  print_mdoc_node(DECL_ARGS);
6132a712daSGarrett D'Amore static	void	  print_mdoc_nodelist(DECL_ARGS);
6232a712daSGarrett D'Amore static	void	  print_mdoc_head(struct termp *, const void *);
6332a712daSGarrett D'Amore static	void	  print_mdoc_foot(struct termp *, const void *);
6432a712daSGarrett D'Amore static	void	  synopsis_pre(struct termp *,
6532a712daSGarrett D'Amore 			const struct mdoc_node *);
6632a712daSGarrett D'Amore 
6732a712daSGarrett D'Amore static	void	  termp____post(DECL_ARGS);
6832a712daSGarrett D'Amore static	void	  termp__t_post(DECL_ARGS);
6932a712daSGarrett D'Amore static	void	  termp_an_post(DECL_ARGS);
7032a712daSGarrett D'Amore static	void	  termp_bd_post(DECL_ARGS);
7132a712daSGarrett D'Amore static	void	  termp_bk_post(DECL_ARGS);
7232a712daSGarrett D'Amore static	void	  termp_bl_post(DECL_ARGS);
73*ffb8ebfaSGarrett D'Amore static	void	  termp_fd_post(DECL_ARGS);
7432a712daSGarrett D'Amore static	void	  termp_fo_post(DECL_ARGS);
7532a712daSGarrett D'Amore static	void	  termp_in_post(DECL_ARGS);
7632a712daSGarrett D'Amore static	void	  termp_it_post(DECL_ARGS);
7732a712daSGarrett D'Amore static	void	  termp_lb_post(DECL_ARGS);
7832a712daSGarrett D'Amore static	void	  termp_nm_post(DECL_ARGS);
7932a712daSGarrett D'Amore static	void	  termp_pf_post(DECL_ARGS);
8032a712daSGarrett D'Amore static	void	  termp_quote_post(DECL_ARGS);
8132a712daSGarrett D'Amore static	void	  termp_sh_post(DECL_ARGS);
8232a712daSGarrett D'Amore static	void	  termp_ss_post(DECL_ARGS);
8332a712daSGarrett D'Amore 
8432a712daSGarrett D'Amore static	int	  termp__a_pre(DECL_ARGS);
8532a712daSGarrett D'Amore static	int	  termp__t_pre(DECL_ARGS);
8632a712daSGarrett D'Amore static	int	  termp_an_pre(DECL_ARGS);
8732a712daSGarrett D'Amore static	int	  termp_ap_pre(DECL_ARGS);
8832a712daSGarrett D'Amore static	int	  termp_bd_pre(DECL_ARGS);
8932a712daSGarrett D'Amore static	int	  termp_bf_pre(DECL_ARGS);
9032a712daSGarrett D'Amore static	int	  termp_bk_pre(DECL_ARGS);
9132a712daSGarrett D'Amore static	int	  termp_bl_pre(DECL_ARGS);
9232a712daSGarrett D'Amore static	int	  termp_bold_pre(DECL_ARGS);
9332a712daSGarrett D'Amore static	int	  termp_bt_pre(DECL_ARGS);
9432a712daSGarrett D'Amore static	int	  termp_bx_pre(DECL_ARGS);
9532a712daSGarrett D'Amore static	int	  termp_cd_pre(DECL_ARGS);
9632a712daSGarrett D'Amore static	int	  termp_d1_pre(DECL_ARGS);
9732a712daSGarrett D'Amore static	int	  termp_ex_pre(DECL_ARGS);
9832a712daSGarrett D'Amore static	int	  termp_fa_pre(DECL_ARGS);
9932a712daSGarrett D'Amore static	int	  termp_fd_pre(DECL_ARGS);
10032a712daSGarrett D'Amore static	int	  termp_fl_pre(DECL_ARGS);
10132a712daSGarrett D'Amore static	int	  termp_fn_pre(DECL_ARGS);
10232a712daSGarrett D'Amore static	int	  termp_fo_pre(DECL_ARGS);
10332a712daSGarrett D'Amore static	int	  termp_ft_pre(DECL_ARGS);
10432a712daSGarrett D'Amore static	int	  termp_in_pre(DECL_ARGS);
10532a712daSGarrett D'Amore static	int	  termp_it_pre(DECL_ARGS);
10632a712daSGarrett D'Amore static	int	  termp_li_pre(DECL_ARGS);
10732a712daSGarrett D'Amore static	int	  termp_lk_pre(DECL_ARGS);
10832a712daSGarrett D'Amore static	int	  termp_nd_pre(DECL_ARGS);
10932a712daSGarrett D'Amore static	int	  termp_nm_pre(DECL_ARGS);
11032a712daSGarrett D'Amore static	int	  termp_ns_pre(DECL_ARGS);
11132a712daSGarrett D'Amore static	int	  termp_quote_pre(DECL_ARGS);
11232a712daSGarrett D'Amore static	int	  termp_rs_pre(DECL_ARGS);
11332a712daSGarrett D'Amore static	int	  termp_rv_pre(DECL_ARGS);
11432a712daSGarrett D'Amore static	int	  termp_sh_pre(DECL_ARGS);
11532a712daSGarrett D'Amore static	int	  termp_sm_pre(DECL_ARGS);
11632a712daSGarrett D'Amore static	int	  termp_sp_pre(DECL_ARGS);
11732a712daSGarrett D'Amore static	int	  termp_ss_pre(DECL_ARGS);
11832a712daSGarrett D'Amore static	int	  termp_under_pre(DECL_ARGS);
11932a712daSGarrett D'Amore static	int	  termp_ud_pre(DECL_ARGS);
12032a712daSGarrett D'Amore static	int	  termp_vt_pre(DECL_ARGS);
12132a712daSGarrett D'Amore static	int	  termp_xr_pre(DECL_ARGS);
12232a712daSGarrett D'Amore static	int	  termp_xx_pre(DECL_ARGS);
12332a712daSGarrett D'Amore 
12432a712daSGarrett D'Amore static	const struct termact termacts[MDOC_MAX] = {
12532a712daSGarrett D'Amore 	{ termp_ap_pre, NULL }, /* Ap */
12632a712daSGarrett D'Amore 	{ NULL, NULL }, /* Dd */
12732a712daSGarrett D'Amore 	{ NULL, NULL }, /* Dt */
12832a712daSGarrett D'Amore 	{ NULL, NULL }, /* Os */
12932a712daSGarrett D'Amore 	{ termp_sh_pre, termp_sh_post }, /* Sh */
13032a712daSGarrett D'Amore 	{ termp_ss_pre, termp_ss_post }, /* Ss */
13132a712daSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Pp */
132*ffb8ebfaSGarrett D'Amore 	{ termp_d1_pre, termp_bl_post }, /* D1 */
133*ffb8ebfaSGarrett D'Amore 	{ termp_d1_pre, termp_bl_post }, /* Dl */
13432a712daSGarrett D'Amore 	{ termp_bd_pre, termp_bd_post }, /* Bd */
13532a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ed */
13632a712daSGarrett D'Amore 	{ termp_bl_pre, termp_bl_post }, /* Bl */
13732a712daSGarrett D'Amore 	{ NULL, NULL }, /* El */
13832a712daSGarrett D'Amore 	{ termp_it_pre, termp_it_post }, /* It */
13932a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ad */
14032a712daSGarrett D'Amore 	{ termp_an_pre, termp_an_post }, /* An */
14132a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ar */
14232a712daSGarrett D'Amore 	{ termp_cd_pre, NULL }, /* Cd */
14332a712daSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Cm */
14432a712daSGarrett D'Amore 	{ NULL, NULL }, /* Dv */
14532a712daSGarrett D'Amore 	{ NULL, NULL }, /* Er */
14632a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ev */
14732a712daSGarrett D'Amore 	{ termp_ex_pre, NULL }, /* Ex */
14832a712daSGarrett D'Amore 	{ termp_fa_pre, NULL }, /* Fa */
149*ffb8ebfaSGarrett D'Amore 	{ termp_fd_pre, termp_fd_post }, /* Fd */
15032a712daSGarrett D'Amore 	{ termp_fl_pre, NULL }, /* Fl */
15132a712daSGarrett D'Amore 	{ termp_fn_pre, NULL }, /* Fn */
15232a712daSGarrett D'Amore 	{ termp_ft_pre, NULL }, /* Ft */
15332a712daSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ic */
15432a712daSGarrett D'Amore 	{ termp_in_pre, termp_in_post }, /* In */
15532a712daSGarrett D'Amore 	{ termp_li_pre, NULL }, /* Li */
15632a712daSGarrett D'Amore 	{ termp_nd_pre, NULL }, /* Nd */
15732a712daSGarrett D'Amore 	{ termp_nm_pre, termp_nm_post }, /* Nm */
15832a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Op */
15932a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ot */
16032a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Pa */
16132a712daSGarrett D'Amore 	{ termp_rv_pre, NULL }, /* Rv */
16232a712daSGarrett D'Amore 	{ NULL, NULL }, /* St */
16332a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Va */
16432a712daSGarrett D'Amore 	{ termp_vt_pre, NULL }, /* Vt */
16532a712daSGarrett D'Amore 	{ termp_xr_pre, NULL }, /* Xr */
16632a712daSGarrett D'Amore 	{ termp__a_pre, termp____post }, /* %A */
16732a712daSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %B */
16832a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %D */
16932a712daSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %I */
17032a712daSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %J */
17132a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %N */
17232a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %O */
17332a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %P */
17432a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %R */
17532a712daSGarrett D'Amore 	{ termp__t_pre, termp__t_post }, /* %T */
17632a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %V */
17732a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ac */
17832a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ao */
17932a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Aq */
18032a712daSGarrett D'Amore 	{ NULL, NULL }, /* At */
18132a712daSGarrett D'Amore 	{ NULL, NULL }, /* Bc */
18232a712daSGarrett D'Amore 	{ termp_bf_pre, NULL }, /* Bf */
18332a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bo */
18432a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bq */
18532a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Bsx */
18632a712daSGarrett D'Amore 	{ termp_bx_pre, NULL }, /* Bx */
18732a712daSGarrett D'Amore 	{ NULL, NULL }, /* Db */
18832a712daSGarrett D'Amore 	{ NULL, NULL }, /* Dc */
18932a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Do */
19032a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Dq */
19132a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ec */ /* FIXME: no space */
19232a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ef */
19332a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Em */
19432a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Eo */
19532a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Fx */
19632a712daSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ms */
197*ffb8ebfaSGarrett D'Amore 	{ NULL, NULL }, /* No */
19832a712daSGarrett D'Amore 	{ termp_ns_pre, NULL }, /* Ns */
19932a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Nx */
20032a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ox */
20132a712daSGarrett D'Amore 	{ NULL, NULL }, /* Pc */
202*ffb8ebfaSGarrett D'Amore 	{ NULL, termp_pf_post }, /* Pf */
20332a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Po */
20432a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Pq */
20532a712daSGarrett D'Amore 	{ NULL, NULL }, /* Qc */
20632a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ql */
20732a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qo */
20832a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qq */
20932a712daSGarrett D'Amore 	{ NULL, NULL }, /* Re */
21032a712daSGarrett D'Amore 	{ termp_rs_pre, NULL }, /* Rs */
21132a712daSGarrett D'Amore 	{ NULL, NULL }, /* Sc */
21232a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* So */
21332a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Sq */
21432a712daSGarrett D'Amore 	{ termp_sm_pre, NULL }, /* Sm */
21532a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Sx */
21632a712daSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Sy */
21732a712daSGarrett D'Amore 	{ NULL, NULL }, /* Tn */
21832a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ux */
21932a712daSGarrett D'Amore 	{ NULL, NULL }, /* Xc */
22032a712daSGarrett D'Amore 	{ NULL, NULL }, /* Xo */
22132a712daSGarrett D'Amore 	{ termp_fo_pre, termp_fo_post }, /* Fo */
22232a712daSGarrett D'Amore 	{ NULL, NULL }, /* Fc */
22332a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Oo */
22432a712daSGarrett D'Amore 	{ NULL, NULL }, /* Oc */
22532a712daSGarrett D'Amore 	{ termp_bk_pre, termp_bk_post }, /* Bk */
22632a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ek */
22732a712daSGarrett D'Amore 	{ termp_bt_pre, NULL }, /* Bt */
22832a712daSGarrett D'Amore 	{ NULL, NULL }, /* Hf */
22932a712daSGarrett D'Amore 	{ NULL, NULL }, /* Fr */
23032a712daSGarrett D'Amore 	{ termp_ud_pre, NULL }, /* Ud */
23132a712daSGarrett D'Amore 	{ NULL, termp_lb_post }, /* Lb */
23232a712daSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Lp */
23332a712daSGarrett D'Amore 	{ termp_lk_pre, NULL }, /* Lk */
23432a712daSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Mt */
23532a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Brq */
23632a712daSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bro */
23732a712daSGarrett D'Amore 	{ NULL, NULL }, /* Brc */
23832a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %C */
23932a712daSGarrett D'Amore 	{ NULL, NULL }, /* Es */ /* TODO */
24032a712daSGarrett D'Amore 	{ NULL, NULL }, /* En */ /* TODO */
24132a712daSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Dx */
24232a712daSGarrett D'Amore 	{ NULL, termp____post }, /* %Q */
24332a712daSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* br */
24432a712daSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* sp */
245*ffb8ebfaSGarrett D'Amore 	{ NULL, termp____post }, /* %U */
24632a712daSGarrett D'Amore 	{ NULL, NULL }, /* Ta */
24732a712daSGarrett D'Amore };
24832a712daSGarrett D'Amore 
24932a712daSGarrett D'Amore 
25032a712daSGarrett D'Amore void
terminal_mdoc(void * arg,const struct mdoc * mdoc)25132a712daSGarrett D'Amore terminal_mdoc(void *arg, const struct mdoc *mdoc)
25232a712daSGarrett D'Amore {
25332a712daSGarrett D'Amore 	const struct mdoc_node	*n;
254*ffb8ebfaSGarrett D'Amore 	const struct mdoc_meta	*meta;
25532a712daSGarrett D'Amore 	struct termp		*p;
25632a712daSGarrett D'Amore 
25732a712daSGarrett D'Amore 	p = (struct termp *)arg;
25832a712daSGarrett D'Amore 
25932a712daSGarrett D'Amore 	if (0 == p->defindent)
26032a712daSGarrett D'Amore 		p->defindent = 5;
26132a712daSGarrett D'Amore 
26232a712daSGarrett D'Amore 	p->overstep = 0;
26332a712daSGarrett D'Amore 	p->maxrmargin = p->defrmargin;
26432a712daSGarrett D'Amore 	p->tabwidth = term_len(p, 5);
26532a712daSGarrett D'Amore 
26632a712daSGarrett D'Amore 	if (NULL == p->symtab)
26732a712daSGarrett D'Amore 		p->symtab = mchars_alloc();
26832a712daSGarrett D'Amore 
26932a712daSGarrett D'Amore 	n = mdoc_node(mdoc);
270*ffb8ebfaSGarrett D'Amore 	meta = mdoc_meta(mdoc);
27132a712daSGarrett D'Amore 
272*ffb8ebfaSGarrett D'Amore 	term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
27332a712daSGarrett D'Amore 
27432a712daSGarrett D'Amore 	if (n->child)
275*ffb8ebfaSGarrett D'Amore 		print_mdoc_nodelist(p, NULL, meta, n->child);
27632a712daSGarrett D'Amore 
27732a712daSGarrett D'Amore 	term_end(p);
27832a712daSGarrett D'Amore }
27932a712daSGarrett D'Amore 
28032a712daSGarrett D'Amore 
28132a712daSGarrett D'Amore static void
print_mdoc_nodelist(DECL_ARGS)28232a712daSGarrett D'Amore print_mdoc_nodelist(DECL_ARGS)
28332a712daSGarrett D'Amore {
28432a712daSGarrett D'Amore 
285*ffb8ebfaSGarrett D'Amore 	print_mdoc_node(p, pair, meta, n);
28632a712daSGarrett D'Amore 	if (n->next)
287*ffb8ebfaSGarrett D'Amore 		print_mdoc_nodelist(p, pair, meta, n->next);
28832a712daSGarrett D'Amore }
28932a712daSGarrett D'Amore 
29032a712daSGarrett D'Amore 
29132a712daSGarrett D'Amore /* ARGSUSED */
29232a712daSGarrett D'Amore static void
print_mdoc_node(DECL_ARGS)29332a712daSGarrett D'Amore print_mdoc_node(DECL_ARGS)
29432a712daSGarrett D'Amore {
29532a712daSGarrett D'Amore 	int		 chld;
29632a712daSGarrett D'Amore 	struct termpair	 npair;
29732a712daSGarrett D'Amore 	size_t		 offset, rmargin;
29832a712daSGarrett D'Amore 
29932a712daSGarrett D'Amore 	chld = 1;
30032a712daSGarrett D'Amore 	offset = p->offset;
30132a712daSGarrett D'Amore 	rmargin = p->rmargin;
302*ffb8ebfaSGarrett D'Amore 	n->prev_font = term_fontq(p);
30332a712daSGarrett D'Amore 
30432a712daSGarrett D'Amore 	memset(&npair, 0, sizeof(struct termpair));
30532a712daSGarrett D'Amore 	npair.ppair = pair;
30632a712daSGarrett D'Amore 
30732a712daSGarrett D'Amore 	/*
30832a712daSGarrett D'Amore 	 * Keeps only work until the end of a line.  If a keep was
30932a712daSGarrett D'Amore 	 * invoked in a prior line, revert it to PREKEEP.
31032a712daSGarrett D'Amore 	 */
31132a712daSGarrett D'Amore 
312*ffb8ebfaSGarrett D'Amore 	if (TERMP_KEEP & p->flags) {
313*ffb8ebfaSGarrett D'Amore 		if (n->prev ? (n->prev->lastline != n->line) :
314*ffb8ebfaSGarrett D'Amore 		    (n->parent && n->parent->line != n->line)) {
31532a712daSGarrett D'Amore 			p->flags &= ~TERMP_KEEP;
31632a712daSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
31732a712daSGarrett D'Amore 		}
31832a712daSGarrett D'Amore 	}
31932a712daSGarrett D'Amore 
32032a712daSGarrett D'Amore 	/*
32132a712daSGarrett D'Amore 	 * After the keep flags have been set up, we may now
32232a712daSGarrett D'Amore 	 * produce output.  Note that some pre-handlers do so.
32332a712daSGarrett D'Amore 	 */
32432a712daSGarrett D'Amore 
32532a712daSGarrett D'Amore 	switch (n->type) {
32632a712daSGarrett D'Amore 	case (MDOC_TEXT):
32732a712daSGarrett D'Amore 		if (' ' == *n->string && MDOC_LINE & n->flags)
32832a712daSGarrett D'Amore 			term_newln(p);
32932a712daSGarrett D'Amore 		if (MDOC_DELIMC & n->flags)
33032a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
33132a712daSGarrett D'Amore 		term_word(p, n->string);
33232a712daSGarrett D'Amore 		if (MDOC_DELIMO & n->flags)
33332a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
33432a712daSGarrett D'Amore 		break;
33532a712daSGarrett D'Amore 	case (MDOC_EQN):
33632a712daSGarrett D'Amore 		term_eqn(p, n->eqn);
33732a712daSGarrett D'Amore 		break;
33832a712daSGarrett D'Amore 	case (MDOC_TBL):
33932a712daSGarrett D'Amore 		term_tbl(p, n->span);
34032a712daSGarrett D'Amore 		break;
34132a712daSGarrett D'Amore 	default:
34232a712daSGarrett D'Amore 		if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
34332a712daSGarrett D'Amore 			chld = (*termacts[n->tok].pre)
344*ffb8ebfaSGarrett D'Amore 				(p, &npair, meta, n);
34532a712daSGarrett D'Amore 		break;
34632a712daSGarrett D'Amore 	}
34732a712daSGarrett D'Amore 
34832a712daSGarrett D'Amore 	if (chld && n->child)
349*ffb8ebfaSGarrett D'Amore 		print_mdoc_nodelist(p, &npair, meta, n->child);
35032a712daSGarrett D'Amore 
351*ffb8ebfaSGarrett D'Amore 	term_fontpopq(p,
352*ffb8ebfaSGarrett D'Amore 	    (ENDBODY_NOT == n->end ? n : n->pending)->prev_font);
35332a712daSGarrett D'Amore 
35432a712daSGarrett D'Amore 	switch (n->type) {
35532a712daSGarrett D'Amore 	case (MDOC_TEXT):
35632a712daSGarrett D'Amore 		break;
35732a712daSGarrett D'Amore 	case (MDOC_TBL):
35832a712daSGarrett D'Amore 		break;
35932a712daSGarrett D'Amore 	case (MDOC_EQN):
36032a712daSGarrett D'Amore 		break;
36132a712daSGarrett D'Amore 	default:
36232a712daSGarrett D'Amore 		if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
36332a712daSGarrett D'Amore 			break;
364*ffb8ebfaSGarrett D'Amore 		(void)(*termacts[n->tok].post)(p, &npair, meta, n);
36532a712daSGarrett D'Amore 
36632a712daSGarrett D'Amore 		/*
36732a712daSGarrett D'Amore 		 * Explicit end tokens not only call the post
36832a712daSGarrett D'Amore 		 * handler, but also tell the respective block
36932a712daSGarrett D'Amore 		 * that it must not call the post handler again.
37032a712daSGarrett D'Amore 		 */
37132a712daSGarrett D'Amore 		if (ENDBODY_NOT != n->end)
37232a712daSGarrett D'Amore 			n->pending->flags |= MDOC_ENDED;
37332a712daSGarrett D'Amore 
37432a712daSGarrett D'Amore 		/*
37532a712daSGarrett D'Amore 		 * End of line terminating an implicit block
37632a712daSGarrett D'Amore 		 * while an explicit block is still open.
37732a712daSGarrett D'Amore 		 * Continue the explicit block without spacing.
37832a712daSGarrett D'Amore 		 */
37932a712daSGarrett D'Amore 		if (ENDBODY_NOSPACE == n->end)
38032a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
38132a712daSGarrett D'Amore 		break;
38232a712daSGarrett D'Amore 	}
38332a712daSGarrett D'Amore 
38432a712daSGarrett D'Amore 	if (MDOC_EOS & n->flags)
38532a712daSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
38632a712daSGarrett D'Amore 
38732a712daSGarrett D'Amore 	p->offset = offset;
38832a712daSGarrett D'Amore 	p->rmargin = rmargin;
38932a712daSGarrett D'Amore }
39032a712daSGarrett D'Amore 
39132a712daSGarrett D'Amore 
39232a712daSGarrett D'Amore static void
print_mdoc_foot(struct termp * p,const void * arg)39332a712daSGarrett D'Amore print_mdoc_foot(struct termp *p, const void *arg)
39432a712daSGarrett D'Amore {
395*ffb8ebfaSGarrett D'Amore 	const struct mdoc_meta *meta;
39632a712daSGarrett D'Amore 
397*ffb8ebfaSGarrett D'Amore 	meta = (const struct mdoc_meta *)arg;
39832a712daSGarrett D'Amore 
39932a712daSGarrett D'Amore 	term_fontrepl(p, TERMFONT_NONE);
40032a712daSGarrett D'Amore 
40132a712daSGarrett D'Amore 	/*
40232a712daSGarrett D'Amore 	 * Output the footer in new-groff style, that is, three columns
40332a712daSGarrett D'Amore 	 * with the middle being the manual date and flanking columns
40432a712daSGarrett D'Amore 	 * being the operating system:
40532a712daSGarrett D'Amore 	 *
40632a712daSGarrett D'Amore 	 * SYSTEM                  DATE                    SYSTEM
40732a712daSGarrett D'Amore 	 */
40832a712daSGarrett D'Amore 
40932a712daSGarrett D'Amore 	term_vspace(p);
41032a712daSGarrett D'Amore 
41132a712daSGarrett D'Amore 	p->offset = 0;
41232a712daSGarrett D'Amore 	p->rmargin = (p->maxrmargin -
413*ffb8ebfaSGarrett D'Amore 			term_strlen(p, meta->date) + term_len(p, 1)) / 2;
414*ffb8ebfaSGarrett D'Amore 	p->trailspace = 1;
41532a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
41632a712daSGarrett D'Amore 
417*ffb8ebfaSGarrett D'Amore 	term_word(p, meta->os);
41832a712daSGarrett D'Amore 	term_flushln(p);
41932a712daSGarrett D'Amore 
42032a712daSGarrett D'Amore 	p->offset = p->rmargin;
421*ffb8ebfaSGarrett D'Amore 	p->rmargin = p->maxrmargin - term_strlen(p, meta->os);
42232a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
42332a712daSGarrett D'Amore 
424*ffb8ebfaSGarrett D'Amore 	term_word(p, meta->date);
42532a712daSGarrett D'Amore 	term_flushln(p);
42632a712daSGarrett D'Amore 
42732a712daSGarrett D'Amore 	p->offset = p->rmargin;
42832a712daSGarrett D'Amore 	p->rmargin = p->maxrmargin;
429*ffb8ebfaSGarrett D'Amore 	p->trailspace = 0;
43032a712daSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
43132a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
43232a712daSGarrett D'Amore 
433*ffb8ebfaSGarrett D'Amore 	term_word(p, meta->os);
43432a712daSGarrett D'Amore 	term_flushln(p);
43532a712daSGarrett D'Amore 
43632a712daSGarrett D'Amore 	p->offset = 0;
43732a712daSGarrett D'Amore 	p->rmargin = p->maxrmargin;
43832a712daSGarrett D'Amore 	p->flags = 0;
43932a712daSGarrett D'Amore }
44032a712daSGarrett D'Amore 
44132a712daSGarrett D'Amore 
44232a712daSGarrett D'Amore static void
print_mdoc_head(struct termp * p,const void * arg)44332a712daSGarrett D'Amore print_mdoc_head(struct termp *p, const void *arg)
44432a712daSGarrett D'Amore {
44532a712daSGarrett D'Amore 	char		buf[BUFSIZ], title[BUFSIZ];
44632a712daSGarrett D'Amore 	size_t		buflen, titlen;
447*ffb8ebfaSGarrett D'Amore 	const struct mdoc_meta *meta;
44832a712daSGarrett D'Amore 
449*ffb8ebfaSGarrett D'Amore 	meta = (const struct mdoc_meta *)arg;
45032a712daSGarrett D'Amore 
45132a712daSGarrett D'Amore 	/*
45232a712daSGarrett D'Amore 	 * The header is strange.  It has three components, which are
45332a712daSGarrett D'Amore 	 * really two with the first duplicated.  It goes like this:
45432a712daSGarrett D'Amore 	 *
45532a712daSGarrett D'Amore 	 * IDENTIFIER              TITLE                   IDENTIFIER
45632a712daSGarrett D'Amore 	 *
45732a712daSGarrett D'Amore 	 * The IDENTIFIER is NAME(SECTION), which is the command-name
45832a712daSGarrett D'Amore 	 * (if given, or "unknown" if not) followed by the manual page
45932a712daSGarrett D'Amore 	 * section.  These are given in `Dt'.  The TITLE is a free-form
46032a712daSGarrett D'Amore 	 * string depending on the manual volume.  If not specified, it
46132a712daSGarrett D'Amore 	 * switches on the manual section.
46232a712daSGarrett D'Amore 	 */
46332a712daSGarrett D'Amore 
46432a712daSGarrett D'Amore 	p->offset = 0;
46532a712daSGarrett D'Amore 	p->rmargin = p->maxrmargin;
46632a712daSGarrett D'Amore 
467*ffb8ebfaSGarrett D'Amore 	assert(meta->vol);
468*ffb8ebfaSGarrett D'Amore 	strlcpy(buf, meta->vol, BUFSIZ);
46932a712daSGarrett D'Amore 	buflen = term_strlen(p, buf);
47032a712daSGarrett D'Amore 
471*ffb8ebfaSGarrett D'Amore 	if (meta->arch) {
47232a712daSGarrett D'Amore 		strlcat(buf, " (", BUFSIZ);
473*ffb8ebfaSGarrett D'Amore 		strlcat(buf, meta->arch, BUFSIZ);
47432a712daSGarrett D'Amore 		strlcat(buf, ")", BUFSIZ);
47532a712daSGarrett D'Amore 	}
47632a712daSGarrett D'Amore 
477*ffb8ebfaSGarrett D'Amore 	snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
47832a712daSGarrett D'Amore 	titlen = term_strlen(p, title);
47932a712daSGarrett D'Amore 
48032a712daSGarrett D'Amore 	p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
481*ffb8ebfaSGarrett D'Amore 	p->trailspace = 1;
48232a712daSGarrett D'Amore 	p->offset = 0;
48332a712daSGarrett D'Amore 	p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
48432a712daSGarrett D'Amore 	    (p->maxrmargin -
48532a712daSGarrett D'Amore 	     term_strlen(p, buf) + term_len(p, 1)) / 2 :
48632a712daSGarrett D'Amore 	    p->maxrmargin - buflen;
48732a712daSGarrett D'Amore 
48832a712daSGarrett D'Amore 	term_word(p, title);
48932a712daSGarrett D'Amore 	term_flushln(p);
49032a712daSGarrett D'Amore 
49132a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
49232a712daSGarrett D'Amore 	p->offset = p->rmargin;
49332a712daSGarrett D'Amore 	p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
49432a712daSGarrett D'Amore 	    p->maxrmargin - titlen : p->maxrmargin;
49532a712daSGarrett D'Amore 
49632a712daSGarrett D'Amore 	term_word(p, buf);
49732a712daSGarrett D'Amore 	term_flushln(p);
49832a712daSGarrett D'Amore 
49932a712daSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
500*ffb8ebfaSGarrett D'Amore 	p->trailspace = 0;
50132a712daSGarrett D'Amore 	if (p->rmargin + titlen <= p->maxrmargin) {
50232a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
50332a712daSGarrett D'Amore 		p->offset = p->rmargin;
50432a712daSGarrett D'Amore 		p->rmargin = p->maxrmargin;
50532a712daSGarrett D'Amore 		term_word(p, title);
50632a712daSGarrett D'Amore 		term_flushln(p);
50732a712daSGarrett D'Amore 	}
50832a712daSGarrett D'Amore 
50932a712daSGarrett D'Amore 	p->flags &= ~TERMP_NOSPACE;
51032a712daSGarrett D'Amore 	p->offset = 0;
51132a712daSGarrett D'Amore 	p->rmargin = p->maxrmargin;
51232a712daSGarrett D'Amore }
51332a712daSGarrett D'Amore 
51432a712daSGarrett D'Amore 
51532a712daSGarrett D'Amore static size_t
a2height(const struct termp * p,const char * v)51632a712daSGarrett D'Amore a2height(const struct termp *p, const char *v)
51732a712daSGarrett D'Amore {
51832a712daSGarrett D'Amore 	struct roffsu	 su;
51932a712daSGarrett D'Amore 
52032a712daSGarrett D'Amore 
52132a712daSGarrett D'Amore 	assert(v);
52232a712daSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_VS))
52332a712daSGarrett D'Amore 		SCALE_VS_INIT(&su, atoi(v));
52432a712daSGarrett D'Amore 
52532a712daSGarrett D'Amore 	return(term_vspan(p, &su));
52632a712daSGarrett D'Amore }
52732a712daSGarrett D'Amore 
52832a712daSGarrett D'Amore 
52932a712daSGarrett D'Amore static size_t
a2width(const struct termp * p,const char * v)53032a712daSGarrett D'Amore a2width(const struct termp *p, const char *v)
53132a712daSGarrett D'Amore {
53232a712daSGarrett D'Amore 	struct roffsu	 su;
53332a712daSGarrett D'Amore 
53432a712daSGarrett D'Amore 	assert(v);
53532a712daSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_MAX))
53632a712daSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
53732a712daSGarrett D'Amore 
53832a712daSGarrett D'Amore 	return(term_hspan(p, &su));
53932a712daSGarrett D'Amore }
54032a712daSGarrett D'Amore 
54132a712daSGarrett D'Amore 
54232a712daSGarrett D'Amore static size_t
a2offs(const struct termp * p,const char * v)54332a712daSGarrett D'Amore a2offs(const struct termp *p, const char *v)
54432a712daSGarrett D'Amore {
54532a712daSGarrett D'Amore 	struct roffsu	 su;
54632a712daSGarrett D'Amore 
54732a712daSGarrett D'Amore 	if ('\0' == *v)
54832a712daSGarrett D'Amore 		return(0);
54932a712daSGarrett D'Amore 	else if (0 == strcmp(v, "left"))
55032a712daSGarrett D'Amore 		return(0);
55132a712daSGarrett D'Amore 	else if (0 == strcmp(v, "indent"))
55232a712daSGarrett D'Amore 		return(term_len(p, p->defindent + 1));
55332a712daSGarrett D'Amore 	else if (0 == strcmp(v, "indent-two"))
55432a712daSGarrett D'Amore 		return(term_len(p, (p->defindent + 1) * 2));
55532a712daSGarrett D'Amore 	else if ( ! a2roffsu(v, &su, SCALE_MAX))
55632a712daSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
55732a712daSGarrett D'Amore 
55832a712daSGarrett D'Amore 	return(term_hspan(p, &su));
55932a712daSGarrett D'Amore }
56032a712daSGarrett D'Amore 
56132a712daSGarrett D'Amore 
56232a712daSGarrett D'Amore /*
56332a712daSGarrett D'Amore  * Determine how much space to print out before block elements of `It'
56432a712daSGarrett D'Amore  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
56532a712daSGarrett D'Amore  * too.
56632a712daSGarrett D'Amore  */
56732a712daSGarrett D'Amore static void
print_bvspace(struct termp * p,const struct mdoc_node * bl,const struct mdoc_node * n)56832a712daSGarrett D'Amore print_bvspace(struct termp *p,
56932a712daSGarrett D'Amore 		const struct mdoc_node *bl,
57032a712daSGarrett D'Amore 		const struct mdoc_node *n)
57132a712daSGarrett D'Amore {
57232a712daSGarrett D'Amore 	const struct mdoc_node	*nn;
57332a712daSGarrett D'Amore 
57432a712daSGarrett D'Amore 	assert(n);
57532a712daSGarrett D'Amore 
57632a712daSGarrett D'Amore 	term_newln(p);
57732a712daSGarrett D'Amore 
57832a712daSGarrett D'Amore 	if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
57932a712daSGarrett D'Amore 		return;
58032a712daSGarrett D'Amore 	if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
58132a712daSGarrett D'Amore 		return;
58232a712daSGarrett D'Amore 
58332a712daSGarrett D'Amore 	/* Do not vspace directly after Ss/Sh. */
58432a712daSGarrett D'Amore 
58532a712daSGarrett D'Amore 	for (nn = n; nn; nn = nn->parent) {
58632a712daSGarrett D'Amore 		if (MDOC_BLOCK != nn->type)
58732a712daSGarrett D'Amore 			continue;
58832a712daSGarrett D'Amore 		if (MDOC_Ss == nn->tok)
58932a712daSGarrett D'Amore 			return;
59032a712daSGarrett D'Amore 		if (MDOC_Sh == nn->tok)
59132a712daSGarrett D'Amore 			return;
59232a712daSGarrett D'Amore 		if (NULL == nn->prev)
59332a712daSGarrett D'Amore 			continue;
59432a712daSGarrett D'Amore 		break;
59532a712daSGarrett D'Amore 	}
59632a712daSGarrett D'Amore 
59732a712daSGarrett D'Amore 	/* A `-column' does not assert vspace within the list. */
59832a712daSGarrett D'Amore 
59932a712daSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
60032a712daSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok)
60132a712daSGarrett D'Amore 			return;
60232a712daSGarrett D'Amore 
60332a712daSGarrett D'Amore 	/* A `-diag' without body does not vspace. */
60432a712daSGarrett D'Amore 
60532a712daSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_diag == bl->norm->Bl.type)
60632a712daSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok) {
60732a712daSGarrett D'Amore 			assert(n->prev->body);
60832a712daSGarrett D'Amore 			if (NULL == n->prev->body->child)
60932a712daSGarrett D'Amore 				return;
61032a712daSGarrett D'Amore 		}
61132a712daSGarrett D'Amore 
61232a712daSGarrett D'Amore 	term_vspace(p);
61332a712daSGarrett D'Amore }
61432a712daSGarrett D'Amore 
61532a712daSGarrett D'Amore 
61632a712daSGarrett D'Amore /* ARGSUSED */
61732a712daSGarrett D'Amore static int
termp_it_pre(DECL_ARGS)61832a712daSGarrett D'Amore termp_it_pre(DECL_ARGS)
61932a712daSGarrett D'Amore {
62032a712daSGarrett D'Amore 	const struct mdoc_node *bl, *nn;
62132a712daSGarrett D'Amore 	char		        buf[7];
62232a712daSGarrett D'Amore 	int		        i;
62332a712daSGarrett D'Amore 	size_t		        width, offset, ncols, dcol;
62432a712daSGarrett D'Amore 	enum mdoc_list		type;
62532a712daSGarrett D'Amore 
62632a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
62732a712daSGarrett D'Amore 		print_bvspace(p, n->parent->parent, n);
62832a712daSGarrett D'Amore 		return(1);
62932a712daSGarrett D'Amore 	}
63032a712daSGarrett D'Amore 
63132a712daSGarrett D'Amore 	bl = n->parent->parent->parent;
63232a712daSGarrett D'Amore 	type = bl->norm->Bl.type;
63332a712daSGarrett D'Amore 
63432a712daSGarrett D'Amore 	/*
63532a712daSGarrett D'Amore 	 * First calculate width and offset.  This is pretty easy unless
63632a712daSGarrett D'Amore 	 * we're a -column list, in which case all prior columns must
63732a712daSGarrett D'Amore 	 * be accounted for.
63832a712daSGarrett D'Amore 	 */
63932a712daSGarrett D'Amore 
64032a712daSGarrett D'Amore 	width = offset = 0;
64132a712daSGarrett D'Amore 
64232a712daSGarrett D'Amore 	if (bl->norm->Bl.offs)
64332a712daSGarrett D'Amore 		offset = a2offs(p, bl->norm->Bl.offs);
64432a712daSGarrett D'Amore 
64532a712daSGarrett D'Amore 	switch (type) {
64632a712daSGarrett D'Amore 	case (LIST_column):
64732a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
64832a712daSGarrett D'Amore 			break;
64932a712daSGarrett D'Amore 
65032a712daSGarrett D'Amore 		/*
65132a712daSGarrett D'Amore 		 * Imitate groff's column handling:
65232a712daSGarrett D'Amore 		 * - For each earlier column, add its width.
65332a712daSGarrett D'Amore 		 * - For less than 5 columns, add four more blanks per
65432a712daSGarrett D'Amore 		 *   column.
65532a712daSGarrett D'Amore 		 * - For exactly 5 columns, add three more blank per
65632a712daSGarrett D'Amore 		 *   column.
65732a712daSGarrett D'Amore 		 * - For more than 5 columns, add only one column.
65832a712daSGarrett D'Amore 		 */
65932a712daSGarrett D'Amore 		ncols = bl->norm->Bl.ncols;
66032a712daSGarrett D'Amore 
66132a712daSGarrett D'Amore 		/* LINTED */
66232a712daSGarrett D'Amore 		dcol = ncols < 5 ? term_len(p, 4) :
66332a712daSGarrett D'Amore 			ncols == 5 ? term_len(p, 3) : term_len(p, 1);
66432a712daSGarrett D'Amore 
66532a712daSGarrett D'Amore 		/*
66632a712daSGarrett D'Amore 		 * Calculate the offset by applying all prior MDOC_BODY,
66732a712daSGarrett D'Amore 		 * so we stop at the MDOC_HEAD (NULL == nn->prev).
66832a712daSGarrett D'Amore 		 */
66932a712daSGarrett D'Amore 
67032a712daSGarrett D'Amore 		for (i = 0, nn = n->prev;
67132a712daSGarrett D'Amore 				nn->prev && i < (int)ncols;
67232a712daSGarrett D'Amore 				nn = nn->prev, i++)
67332a712daSGarrett D'Amore 			offset += dcol + a2width
67432a712daSGarrett D'Amore 				(p, bl->norm->Bl.cols[i]);
67532a712daSGarrett D'Amore 
67632a712daSGarrett D'Amore 		/*
67732a712daSGarrett D'Amore 		 * When exceeding the declared number of columns, leave
67832a712daSGarrett D'Amore 		 * the remaining widths at 0.  This will later be
67932a712daSGarrett D'Amore 		 * adjusted to the default width of 10, or, for the last
68032a712daSGarrett D'Amore 		 * column, stretched to the right margin.
68132a712daSGarrett D'Amore 		 */
68232a712daSGarrett D'Amore 		if (i >= (int)ncols)
68332a712daSGarrett D'Amore 			break;
68432a712daSGarrett D'Amore 
68532a712daSGarrett D'Amore 		/*
68632a712daSGarrett D'Amore 		 * Use the declared column widths, extended as explained
68732a712daSGarrett D'Amore 		 * in the preceding paragraph.
68832a712daSGarrett D'Amore 		 */
68932a712daSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
69032a712daSGarrett D'Amore 		break;
69132a712daSGarrett D'Amore 	default:
69232a712daSGarrett D'Amore 		if (NULL == bl->norm->Bl.width)
69332a712daSGarrett D'Amore 			break;
69432a712daSGarrett D'Amore 
69532a712daSGarrett D'Amore 		/*
69632a712daSGarrett D'Amore 		 * Note: buffer the width by 2, which is groff's magic
69732a712daSGarrett D'Amore 		 * number for buffering single arguments.  See the above
69832a712daSGarrett D'Amore 		 * handling for column for how this changes.
69932a712daSGarrett D'Amore 		 */
70032a712daSGarrett D'Amore 		assert(bl->norm->Bl.width);
70132a712daSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
70232a712daSGarrett D'Amore 		break;
70332a712daSGarrett D'Amore 	}
70432a712daSGarrett D'Amore 
70532a712daSGarrett D'Amore 	/*
70632a712daSGarrett D'Amore 	 * List-type can override the width in the case of fixed-head
70732a712daSGarrett D'Amore 	 * values (bullet, dash/hyphen, enum).  Tags need a non-zero
70832a712daSGarrett D'Amore 	 * offset.
70932a712daSGarrett D'Amore 	 */
71032a712daSGarrett D'Amore 
71132a712daSGarrett D'Amore 	switch (type) {
71232a712daSGarrett D'Amore 	case (LIST_bullet):
71332a712daSGarrett D'Amore 		/* FALLTHROUGH */
71432a712daSGarrett D'Amore 	case (LIST_dash):
71532a712daSGarrett D'Amore 		/* FALLTHROUGH */
71632a712daSGarrett D'Amore 	case (LIST_hyphen):
717*ffb8ebfaSGarrett D'Amore 		/* FALLTHROUGH */
71832a712daSGarrett D'Amore 	case (LIST_enum):
719*ffb8ebfaSGarrett D'Amore 		if (width < term_len(p, 2))
720*ffb8ebfaSGarrett D'Amore 			width = term_len(p, 2);
72132a712daSGarrett D'Amore 		break;
72232a712daSGarrett D'Amore 	case (LIST_hang):
72332a712daSGarrett D'Amore 		if (0 == width)
72432a712daSGarrett D'Amore 			width = term_len(p, 8);
72532a712daSGarrett D'Amore 		break;
72632a712daSGarrett D'Amore 	case (LIST_column):
72732a712daSGarrett D'Amore 		/* FALLTHROUGH */
72832a712daSGarrett D'Amore 	case (LIST_tag):
72932a712daSGarrett D'Amore 		if (0 == width)
73032a712daSGarrett D'Amore 			width = term_len(p, 10);
73132a712daSGarrett D'Amore 		break;
73232a712daSGarrett D'Amore 	default:
73332a712daSGarrett D'Amore 		break;
73432a712daSGarrett D'Amore 	}
73532a712daSGarrett D'Amore 
73632a712daSGarrett D'Amore 	/*
73732a712daSGarrett D'Amore 	 * Whitespace control.  Inset bodies need an initial space,
73832a712daSGarrett D'Amore 	 * while diagonal bodies need two.
73932a712daSGarrett D'Amore 	 */
74032a712daSGarrett D'Amore 
74132a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
74232a712daSGarrett D'Amore 
74332a712daSGarrett D'Amore 	switch (type) {
74432a712daSGarrett D'Amore 	case (LIST_diag):
74532a712daSGarrett D'Amore 		if (MDOC_BODY == n->type)
74632a712daSGarrett D'Amore 			term_word(p, "\\ \\ ");
74732a712daSGarrett D'Amore 		break;
74832a712daSGarrett D'Amore 	case (LIST_inset):
74932a712daSGarrett D'Amore 		if (MDOC_BODY == n->type)
75032a712daSGarrett D'Amore 			term_word(p, "\\ ");
75132a712daSGarrett D'Amore 		break;
75232a712daSGarrett D'Amore 	default:
75332a712daSGarrett D'Amore 		break;
75432a712daSGarrett D'Amore 	}
75532a712daSGarrett D'Amore 
75632a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
75732a712daSGarrett D'Amore 
75832a712daSGarrett D'Amore 	switch (type) {
75932a712daSGarrett D'Amore 	case (LIST_diag):
76032a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
76132a712daSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
76232a712daSGarrett D'Amore 		break;
76332a712daSGarrett D'Amore 	default:
76432a712daSGarrett D'Amore 		break;
76532a712daSGarrett D'Amore 	}
76632a712daSGarrett D'Amore 
76732a712daSGarrett D'Amore 	/*
76832a712daSGarrett D'Amore 	 * Pad and break control.  This is the tricky part.  These flags
76932a712daSGarrett D'Amore 	 * are documented in term_flushln() in term.c.  Note that we're
77032a712daSGarrett D'Amore 	 * going to unset all of these flags in termp_it_post() when we
77132a712daSGarrett D'Amore 	 * exit.
77232a712daSGarrett D'Amore 	 */
77332a712daSGarrett D'Amore 
77432a712daSGarrett D'Amore 	switch (type) {
775*ffb8ebfaSGarrett D'Amore 	case (LIST_enum):
776*ffb8ebfaSGarrett D'Amore 		/*
777*ffb8ebfaSGarrett D'Amore 		 * Weird special case.
778*ffb8ebfaSGarrett D'Amore 		 * Very narrow enum lists actually hang.
779*ffb8ebfaSGarrett D'Amore 		 */
780*ffb8ebfaSGarrett D'Amore 		if (width == term_len(p, 2))
781*ffb8ebfaSGarrett D'Amore 			p->flags |= TERMP_HANG;
782*ffb8ebfaSGarrett D'Amore 		/* FALLTHROUGH */
78332a712daSGarrett D'Amore 	case (LIST_bullet):
78432a712daSGarrett D'Amore 		/* FALLTHROUGH */
78532a712daSGarrett D'Amore 	case (LIST_dash):
78632a712daSGarrett D'Amore 		/* FALLTHROUGH */
78732a712daSGarrett D'Amore 	case (LIST_hyphen):
788*ffb8ebfaSGarrett D'Amore 		if (MDOC_HEAD != n->type)
789*ffb8ebfaSGarrett D'Amore 			break;
79032a712daSGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
791*ffb8ebfaSGarrett D'Amore 		p->trailspace = 1;
79232a712daSGarrett D'Amore 		break;
79332a712daSGarrett D'Amore 	case (LIST_hang):
794*ffb8ebfaSGarrett D'Amore 		if (MDOC_HEAD != n->type)
79532a712daSGarrett D'Amore 			break;
79632a712daSGarrett D'Amore 
79732a712daSGarrett D'Amore 		/*
79832a712daSGarrett D'Amore 		 * This is ugly.  If `-hang' is specified and the body
79932a712daSGarrett D'Amore 		 * is a `Bl' or `Bd', then we want basically to nullify
80032a712daSGarrett D'Amore 		 * the "overstep" effect in term_flushln() and treat
80132a712daSGarrett D'Amore 		 * this as a `-ohang' list instead.
80232a712daSGarrett D'Amore 		 */
80332a712daSGarrett D'Amore 		if (n->next->child &&
80432a712daSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
80532a712daSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
806*ffb8ebfaSGarrett D'Amore 			break;
807*ffb8ebfaSGarrett D'Amore 
808*ffb8ebfaSGarrett D'Amore 		p->flags |= TERMP_NOBREAK | TERMP_HANG;
809*ffb8ebfaSGarrett D'Amore 		p->trailspace = 1;
81032a712daSGarrett D'Amore 		break;
81132a712daSGarrett D'Amore 	case (LIST_tag):
81232a712daSGarrett D'Amore 		if (MDOC_HEAD != n->type)
81332a712daSGarrett D'Amore 			break;
814*ffb8ebfaSGarrett D'Amore 
815*ffb8ebfaSGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
816*ffb8ebfaSGarrett D'Amore 		p->trailspace = 2;
817*ffb8ebfaSGarrett D'Amore 
81832a712daSGarrett D'Amore 		if (NULL == n->next || NULL == n->next->child)
81932a712daSGarrett D'Amore 			p->flags |= TERMP_DANGLE;
82032a712daSGarrett D'Amore 		break;
82132a712daSGarrett D'Amore 	case (LIST_column):
82232a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
82332a712daSGarrett D'Amore 			break;
82432a712daSGarrett D'Amore 
825*ffb8ebfaSGarrett D'Amore 		if (NULL == n->next) {
82632a712daSGarrett D'Amore 			p->flags &= ~TERMP_NOBREAK;
827*ffb8ebfaSGarrett D'Amore 			p->trailspace = 0;
828*ffb8ebfaSGarrett D'Amore 		} else {
82932a712daSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
830*ffb8ebfaSGarrett D'Amore 			p->trailspace = 1;
831*ffb8ebfaSGarrett D'Amore 		}
83232a712daSGarrett D'Amore 
83332a712daSGarrett D'Amore 		break;
83432a712daSGarrett D'Amore 	case (LIST_diag):
835*ffb8ebfaSGarrett D'Amore 		if (MDOC_HEAD != n->type)
836*ffb8ebfaSGarrett D'Amore 			break;
83732a712daSGarrett D'Amore 		p->flags |= TERMP_NOBREAK;
838*ffb8ebfaSGarrett D'Amore 		p->trailspace = 1;
83932a712daSGarrett D'Amore 		break;
84032a712daSGarrett D'Amore 	default:
84132a712daSGarrett D'Amore 		break;
84232a712daSGarrett D'Amore 	}
84332a712daSGarrett D'Amore 
84432a712daSGarrett D'Amore 	/*
84532a712daSGarrett D'Amore 	 * Margin control.  Set-head-width lists have their right
84632a712daSGarrett D'Amore 	 * margins shortened.  The body for these lists has the offset
84732a712daSGarrett D'Amore 	 * necessarily lengthened.  Everybody gets the offset.
84832a712daSGarrett D'Amore 	 */
84932a712daSGarrett D'Amore 
85032a712daSGarrett D'Amore 	p->offset += offset;
85132a712daSGarrett D'Amore 
85232a712daSGarrett D'Amore 	switch (type) {
85332a712daSGarrett D'Amore 	case (LIST_hang):
85432a712daSGarrett D'Amore 		/*
85532a712daSGarrett D'Amore 		 * Same stipulation as above, regarding `-hang'.  We
85632a712daSGarrett D'Amore 		 * don't want to recalculate rmargin and offsets when
85732a712daSGarrett D'Amore 		 * using `Bd' or `Bl' within `-hang' overstep lists.
85832a712daSGarrett D'Amore 		 */
85932a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type && n->next->child &&
86032a712daSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
86132a712daSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
86232a712daSGarrett D'Amore 			break;
86332a712daSGarrett D'Amore 		/* FALLTHROUGH */
86432a712daSGarrett D'Amore 	case (LIST_bullet):
86532a712daSGarrett D'Amore 		/* FALLTHROUGH */
86632a712daSGarrett D'Amore 	case (LIST_dash):
86732a712daSGarrett D'Amore 		/* FALLTHROUGH */
86832a712daSGarrett D'Amore 	case (LIST_enum):
86932a712daSGarrett D'Amore 		/* FALLTHROUGH */
87032a712daSGarrett D'Amore 	case (LIST_hyphen):
87132a712daSGarrett D'Amore 		/* FALLTHROUGH */
87232a712daSGarrett D'Amore 	case (LIST_tag):
87332a712daSGarrett D'Amore 		assert(width);
87432a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
87532a712daSGarrett D'Amore 			p->rmargin = p->offset + width;
87632a712daSGarrett D'Amore 		else
87732a712daSGarrett D'Amore 			p->offset += width;
87832a712daSGarrett D'Amore 		break;
87932a712daSGarrett D'Amore 	case (LIST_column):
88032a712daSGarrett D'Amore 		assert(width);
88132a712daSGarrett D'Amore 		p->rmargin = p->offset + width;
88232a712daSGarrett D'Amore 		/*
88332a712daSGarrett D'Amore 		 * XXX - this behaviour is not documented: the
88432a712daSGarrett D'Amore 		 * right-most column is filled to the right margin.
88532a712daSGarrett D'Amore 		 */
88632a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
88732a712daSGarrett D'Amore 			break;
88832a712daSGarrett D'Amore 		if (NULL == n->next && p->rmargin < p->maxrmargin)
88932a712daSGarrett D'Amore 			p->rmargin = p->maxrmargin;
89032a712daSGarrett D'Amore 		break;
89132a712daSGarrett D'Amore 	default:
89232a712daSGarrett D'Amore 		break;
89332a712daSGarrett D'Amore 	}
89432a712daSGarrett D'Amore 
89532a712daSGarrett D'Amore 	/*
89632a712daSGarrett D'Amore 	 * The dash, hyphen, bullet and enum lists all have a special
89732a712daSGarrett D'Amore 	 * HEAD character (temporarily bold, in some cases).
89832a712daSGarrett D'Amore 	 */
89932a712daSGarrett D'Amore 
90032a712daSGarrett D'Amore 	if (MDOC_HEAD == n->type)
90132a712daSGarrett D'Amore 		switch (type) {
90232a712daSGarrett D'Amore 		case (LIST_bullet):
90332a712daSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
90432a712daSGarrett D'Amore 			term_word(p, "\\[bu]");
90532a712daSGarrett D'Amore 			term_fontpop(p);
90632a712daSGarrett D'Amore 			break;
90732a712daSGarrett D'Amore 		case (LIST_dash):
90832a712daSGarrett D'Amore 			/* FALLTHROUGH */
90932a712daSGarrett D'Amore 		case (LIST_hyphen):
91032a712daSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
91132a712daSGarrett D'Amore 			term_word(p, "\\(hy");
91232a712daSGarrett D'Amore 			term_fontpop(p);
91332a712daSGarrett D'Amore 			break;
91432a712daSGarrett D'Amore 		case (LIST_enum):
91532a712daSGarrett D'Amore 			(pair->ppair->ppair->count)++;
91632a712daSGarrett D'Amore 			snprintf(buf, sizeof(buf), "%d.",
91732a712daSGarrett D'Amore 					pair->ppair->ppair->count);
91832a712daSGarrett D'Amore 			term_word(p, buf);
91932a712daSGarrett D'Amore 			break;
92032a712daSGarrett D'Amore 		default:
92132a712daSGarrett D'Amore 			break;
92232a712daSGarrett D'Amore 		}
92332a712daSGarrett D'Amore 
92432a712daSGarrett D'Amore 	/*
92532a712daSGarrett D'Amore 	 * If we're not going to process our children, indicate so here.
92632a712daSGarrett D'Amore 	 */
92732a712daSGarrett D'Amore 
92832a712daSGarrett D'Amore 	switch (type) {
92932a712daSGarrett D'Amore 	case (LIST_bullet):
93032a712daSGarrett D'Amore 		/* FALLTHROUGH */
93132a712daSGarrett D'Amore 	case (LIST_item):
93232a712daSGarrett D'Amore 		/* FALLTHROUGH */
93332a712daSGarrett D'Amore 	case (LIST_dash):
93432a712daSGarrett D'Amore 		/* FALLTHROUGH */
93532a712daSGarrett D'Amore 	case (LIST_hyphen):
93632a712daSGarrett D'Amore 		/* FALLTHROUGH */
93732a712daSGarrett D'Amore 	case (LIST_enum):
93832a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
93932a712daSGarrett D'Amore 			return(0);
94032a712daSGarrett D'Amore 		break;
94132a712daSGarrett D'Amore 	case (LIST_column):
94232a712daSGarrett D'Amore 		if (MDOC_HEAD == n->type)
94332a712daSGarrett D'Amore 			return(0);
94432a712daSGarrett D'Amore 		break;
94532a712daSGarrett D'Amore 	default:
94632a712daSGarrett D'Amore 		break;
94732a712daSGarrett D'Amore 	}
94832a712daSGarrett D'Amore 
94932a712daSGarrett D'Amore 	return(1);
95032a712daSGarrett D'Amore }
95132a712daSGarrett D'Amore 
95232a712daSGarrett D'Amore 
95332a712daSGarrett D'Amore /* ARGSUSED */
95432a712daSGarrett D'Amore static void
termp_it_post(DECL_ARGS)95532a712daSGarrett D'Amore termp_it_post(DECL_ARGS)
95632a712daSGarrett D'Amore {
95732a712daSGarrett D'Amore 	enum mdoc_list	   type;
95832a712daSGarrett D'Amore 
95932a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
96032a712daSGarrett D'Amore 		return;
96132a712daSGarrett D'Amore 
96232a712daSGarrett D'Amore 	type = n->parent->parent->parent->norm->Bl.type;
96332a712daSGarrett D'Amore 
96432a712daSGarrett D'Amore 	switch (type) {
96532a712daSGarrett D'Amore 	case (LIST_item):
96632a712daSGarrett D'Amore 		/* FALLTHROUGH */
96732a712daSGarrett D'Amore 	case (LIST_diag):
96832a712daSGarrett D'Amore 		/* FALLTHROUGH */
96932a712daSGarrett D'Amore 	case (LIST_inset):
97032a712daSGarrett D'Amore 		if (MDOC_BODY == n->type)
97132a712daSGarrett D'Amore 			term_newln(p);
97232a712daSGarrett D'Amore 		break;
97332a712daSGarrett D'Amore 	case (LIST_column):
97432a712daSGarrett D'Amore 		if (MDOC_BODY == n->type)
97532a712daSGarrett D'Amore 			term_flushln(p);
97632a712daSGarrett D'Amore 		break;
97732a712daSGarrett D'Amore 	default:
97832a712daSGarrett D'Amore 		term_newln(p);
97932a712daSGarrett D'Amore 		break;
98032a712daSGarrett D'Amore 	}
98132a712daSGarrett D'Amore 
98232a712daSGarrett D'Amore 	/*
98332a712daSGarrett D'Amore 	 * Now that our output is flushed, we can reset our tags.  Since
98432a712daSGarrett D'Amore 	 * only `It' sets these flags, we're free to assume that nobody
98532a712daSGarrett D'Amore 	 * has munged them in the meanwhile.
98632a712daSGarrett D'Amore 	 */
98732a712daSGarrett D'Amore 
98832a712daSGarrett D'Amore 	p->flags &= ~TERMP_DANGLE;
98932a712daSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
99032a712daSGarrett D'Amore 	p->flags &= ~TERMP_HANG;
991*ffb8ebfaSGarrett D'Amore 	p->trailspace = 0;
99232a712daSGarrett D'Amore }
99332a712daSGarrett D'Amore 
99432a712daSGarrett D'Amore 
99532a712daSGarrett D'Amore /* ARGSUSED */
99632a712daSGarrett D'Amore static int
termp_nm_pre(DECL_ARGS)99732a712daSGarrett D'Amore termp_nm_pre(DECL_ARGS)
99832a712daSGarrett D'Amore {
99932a712daSGarrett D'Amore 
1000*ffb8ebfaSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
1001*ffb8ebfaSGarrett D'Amore 		p->flags |= TERMP_PREKEEP;
100232a712daSGarrett D'Amore 		return(1);
1003*ffb8ebfaSGarrett D'Amore 	}
100432a712daSGarrett D'Amore 
100532a712daSGarrett D'Amore 	if (MDOC_BODY == n->type) {
100632a712daSGarrett D'Amore 		if (NULL == n->child)
100732a712daSGarrett D'Amore 			return(0);
100832a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
100932a712daSGarrett D'Amore 		p->offset += term_len(p, 1) +
1010*ffb8ebfaSGarrett D'Amore 		    (NULL == n->prev->child ?
1011*ffb8ebfaSGarrett D'Amore 		     term_strlen(p, meta->name) :
101232a712daSGarrett D'Amore 		     MDOC_TEXT == n->prev->child->type ?
101332a712daSGarrett D'Amore 		     term_strlen(p, n->prev->child->string) :
101432a712daSGarrett D'Amore 		     term_len(p, 5));
101532a712daSGarrett D'Amore 		return(1);
101632a712daSGarrett D'Amore 	}
101732a712daSGarrett D'Amore 
1018*ffb8ebfaSGarrett D'Amore 	if (NULL == n->child && NULL == meta->name)
101932a712daSGarrett D'Amore 		return(0);
102032a712daSGarrett D'Amore 
102132a712daSGarrett D'Amore 	if (MDOC_HEAD == n->type)
102232a712daSGarrett D'Amore 		synopsis_pre(p, n->parent);
102332a712daSGarrett D'Amore 
102432a712daSGarrett D'Amore 	if (MDOC_HEAD == n->type && n->next->child) {
102532a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
1026*ffb8ebfaSGarrett D'Amore 		p->trailspace = 1;
102732a712daSGarrett D'Amore 		p->rmargin = p->offset + term_len(p, 1);
102832a712daSGarrett D'Amore 		if (NULL == n->child) {
1029*ffb8ebfaSGarrett D'Amore 			p->rmargin += term_strlen(p, meta->name);
103032a712daSGarrett D'Amore 		} else if (MDOC_TEXT == n->child->type) {
103132a712daSGarrett D'Amore 			p->rmargin += term_strlen(p, n->child->string);
103232a712daSGarrett D'Amore 			if (n->child->next)
103332a712daSGarrett D'Amore 				p->flags |= TERMP_HANG;
103432a712daSGarrett D'Amore 		} else {
103532a712daSGarrett D'Amore 			p->rmargin += term_len(p, 5);
103632a712daSGarrett D'Amore 			p->flags |= TERMP_HANG;
103732a712daSGarrett D'Amore 		}
103832a712daSGarrett D'Amore 	}
103932a712daSGarrett D'Amore 
104032a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
104132a712daSGarrett D'Amore 	if (NULL == n->child)
1042*ffb8ebfaSGarrett D'Amore 		term_word(p, meta->name);
104332a712daSGarrett D'Amore 	return(1);
104432a712daSGarrett D'Amore }
104532a712daSGarrett D'Amore 
104632a712daSGarrett D'Amore 
104732a712daSGarrett D'Amore /* ARGSUSED */
104832a712daSGarrett D'Amore static void
termp_nm_post(DECL_ARGS)104932a712daSGarrett D'Amore termp_nm_post(DECL_ARGS)
105032a712daSGarrett D'Amore {
105132a712daSGarrett D'Amore 
1052*ffb8ebfaSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
1053*ffb8ebfaSGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1054*ffb8ebfaSGarrett D'Amore 	} else if (MDOC_HEAD == n->type && n->next->child) {
105532a712daSGarrett D'Amore 		term_flushln(p);
105632a712daSGarrett D'Amore 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
1057*ffb8ebfaSGarrett D'Amore 		p->trailspace = 0;
105832a712daSGarrett D'Amore 	} else if (MDOC_BODY == n->type && n->child)
105932a712daSGarrett D'Amore 		term_flushln(p);
106032a712daSGarrett D'Amore }
106132a712daSGarrett D'Amore 
106232a712daSGarrett D'Amore 
106332a712daSGarrett D'Amore /* ARGSUSED */
106432a712daSGarrett D'Amore static int
termp_fl_pre(DECL_ARGS)106532a712daSGarrett D'Amore termp_fl_pre(DECL_ARGS)
106632a712daSGarrett D'Amore {
106732a712daSGarrett D'Amore 
106832a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
106932a712daSGarrett D'Amore 	term_word(p, "\\-");
107032a712daSGarrett D'Amore 
107132a712daSGarrett D'Amore 	if (n->child)
107232a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
107332a712daSGarrett D'Amore 	else if (n->next && n->next->line == n->line)
107432a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
107532a712daSGarrett D'Amore 
107632a712daSGarrett D'Amore 	return(1);
107732a712daSGarrett D'Amore }
107832a712daSGarrett D'Amore 
107932a712daSGarrett D'Amore 
108032a712daSGarrett D'Amore /* ARGSUSED */
108132a712daSGarrett D'Amore static int
termp__a_pre(DECL_ARGS)108232a712daSGarrett D'Amore termp__a_pre(DECL_ARGS)
108332a712daSGarrett D'Amore {
108432a712daSGarrett D'Amore 
108532a712daSGarrett D'Amore 	if (n->prev && MDOC__A == n->prev->tok)
108632a712daSGarrett D'Amore 		if (NULL == n->next || MDOC__A != n->next->tok)
108732a712daSGarrett D'Amore 			term_word(p, "and");
108832a712daSGarrett D'Amore 
108932a712daSGarrett D'Amore 	return(1);
109032a712daSGarrett D'Amore }
109132a712daSGarrett D'Amore 
109232a712daSGarrett D'Amore 
109332a712daSGarrett D'Amore /* ARGSUSED */
109432a712daSGarrett D'Amore static int
termp_an_pre(DECL_ARGS)109532a712daSGarrett D'Amore termp_an_pre(DECL_ARGS)
109632a712daSGarrett D'Amore {
109732a712daSGarrett D'Amore 
109832a712daSGarrett D'Amore 	if (NULL == n->child)
109932a712daSGarrett D'Amore 		return(1);
110032a712daSGarrett D'Amore 
110132a712daSGarrett D'Amore 	/*
110232a712daSGarrett D'Amore 	 * If not in the AUTHORS section, `An -split' will cause
110332a712daSGarrett D'Amore 	 * newlines to occur before the author name.  If in the AUTHORS
110432a712daSGarrett D'Amore 	 * section, by default, the first `An' invocation is nosplit,
110532a712daSGarrett D'Amore 	 * then all subsequent ones, regardless of whether interspersed
110632a712daSGarrett D'Amore 	 * with other macros/text, are split.  -split, in this case,
110732a712daSGarrett D'Amore 	 * will override the condition of the implied first -nosplit.
110832a712daSGarrett D'Amore 	 */
110932a712daSGarrett D'Amore 
111032a712daSGarrett D'Amore 	if (n->sec == SEC_AUTHORS) {
111132a712daSGarrett D'Amore 		if ( ! (TERMP_ANPREC & p->flags)) {
111232a712daSGarrett D'Amore 			if (TERMP_SPLIT & p->flags)
111332a712daSGarrett D'Amore 				term_newln(p);
111432a712daSGarrett D'Amore 			return(1);
111532a712daSGarrett D'Amore 		}
111632a712daSGarrett D'Amore 		if (TERMP_NOSPLIT & p->flags)
111732a712daSGarrett D'Amore 			return(1);
111832a712daSGarrett D'Amore 		term_newln(p);
111932a712daSGarrett D'Amore 		return(1);
112032a712daSGarrett D'Amore 	}
112132a712daSGarrett D'Amore 
112232a712daSGarrett D'Amore 	if (TERMP_SPLIT & p->flags)
112332a712daSGarrett D'Amore 		term_newln(p);
112432a712daSGarrett D'Amore 
112532a712daSGarrett D'Amore 	return(1);
112632a712daSGarrett D'Amore }
112732a712daSGarrett D'Amore 
112832a712daSGarrett D'Amore 
112932a712daSGarrett D'Amore /* ARGSUSED */
113032a712daSGarrett D'Amore static void
termp_an_post(DECL_ARGS)113132a712daSGarrett D'Amore termp_an_post(DECL_ARGS)
113232a712daSGarrett D'Amore {
113332a712daSGarrett D'Amore 
113432a712daSGarrett D'Amore 	if (n->child) {
113532a712daSGarrett D'Amore 		if (SEC_AUTHORS == n->sec)
113632a712daSGarrett D'Amore 			p->flags |= TERMP_ANPREC;
113732a712daSGarrett D'Amore 		return;
113832a712daSGarrett D'Amore 	}
113932a712daSGarrett D'Amore 
114032a712daSGarrett D'Amore 	if (AUTH_split == n->norm->An.auth) {
114132a712daSGarrett D'Amore 		p->flags &= ~TERMP_NOSPLIT;
114232a712daSGarrett D'Amore 		p->flags |= TERMP_SPLIT;
114332a712daSGarrett D'Amore 	} else if (AUTH_nosplit == n->norm->An.auth) {
114432a712daSGarrett D'Amore 		p->flags &= ~TERMP_SPLIT;
114532a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPLIT;
114632a712daSGarrett D'Amore 	}
114732a712daSGarrett D'Amore 
114832a712daSGarrett D'Amore }
114932a712daSGarrett D'Amore 
115032a712daSGarrett D'Amore 
115132a712daSGarrett D'Amore /* ARGSUSED */
115232a712daSGarrett D'Amore static int
termp_ns_pre(DECL_ARGS)115332a712daSGarrett D'Amore termp_ns_pre(DECL_ARGS)
115432a712daSGarrett D'Amore {
115532a712daSGarrett D'Amore 
115632a712daSGarrett D'Amore 	if ( ! (MDOC_LINE & n->flags))
115732a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
115832a712daSGarrett D'Amore 	return(1);
115932a712daSGarrett D'Amore }
116032a712daSGarrett D'Amore 
116132a712daSGarrett D'Amore 
116232a712daSGarrett D'Amore /* ARGSUSED */
116332a712daSGarrett D'Amore static int
termp_rs_pre(DECL_ARGS)116432a712daSGarrett D'Amore termp_rs_pre(DECL_ARGS)
116532a712daSGarrett D'Amore {
116632a712daSGarrett D'Amore 
116732a712daSGarrett D'Amore 	if (SEC_SEE_ALSO != n->sec)
116832a712daSGarrett D'Amore 		return(1);
116932a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type && n->prev)
117032a712daSGarrett D'Amore 		term_vspace(p);
117132a712daSGarrett D'Amore 	return(1);
117232a712daSGarrett D'Amore }
117332a712daSGarrett D'Amore 
117432a712daSGarrett D'Amore 
117532a712daSGarrett D'Amore /* ARGSUSED */
117632a712daSGarrett D'Amore static int
termp_rv_pre(DECL_ARGS)117732a712daSGarrett D'Amore termp_rv_pre(DECL_ARGS)
117832a712daSGarrett D'Amore {
117932a712daSGarrett D'Amore 	int		 nchild;
118032a712daSGarrett D'Amore 
118132a712daSGarrett D'Amore 	term_newln(p);
118232a712daSGarrett D'Amore 	term_word(p, "The");
118332a712daSGarrett D'Amore 
118432a712daSGarrett D'Amore 	nchild = n->nchild;
118532a712daSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
118632a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
118732a712daSGarrett D'Amore 		term_word(p, n->string);
118832a712daSGarrett D'Amore 		term_fontpop(p);
118932a712daSGarrett D'Amore 
119032a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
119132a712daSGarrett D'Amore 		term_word(p, "()");
119232a712daSGarrett D'Amore 
119332a712daSGarrett D'Amore 		if (nchild > 2 && n->next) {
119432a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
119532a712daSGarrett D'Amore 			term_word(p, ",");
119632a712daSGarrett D'Amore 		}
119732a712daSGarrett D'Amore 
119832a712daSGarrett D'Amore 		if (n->next && NULL == n->next->next)
119932a712daSGarrett D'Amore 			term_word(p, "and");
120032a712daSGarrett D'Amore 	}
120132a712daSGarrett D'Amore 
120232a712daSGarrett D'Amore 	if (nchild > 1)
120332a712daSGarrett D'Amore 		term_word(p, "functions return");
120432a712daSGarrett D'Amore 	else
120532a712daSGarrett D'Amore 		term_word(p, "function returns");
120632a712daSGarrett D'Amore 
120732a712daSGarrett D'Amore        	term_word(p, "the value 0 if successful; otherwise the value "
120832a712daSGarrett D'Amore 			"-1 is returned and the global variable");
120932a712daSGarrett D'Amore 
121032a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
121132a712daSGarrett D'Amore 	term_word(p, "errno");
121232a712daSGarrett D'Amore 	term_fontpop(p);
121332a712daSGarrett D'Amore 
121432a712daSGarrett D'Amore        	term_word(p, "is set to indicate the error.");
121532a712daSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
121632a712daSGarrett D'Amore 
121732a712daSGarrett D'Amore 	return(0);
121832a712daSGarrett D'Amore }
121932a712daSGarrett D'Amore 
122032a712daSGarrett D'Amore 
122132a712daSGarrett D'Amore /* ARGSUSED */
122232a712daSGarrett D'Amore static int
termp_ex_pre(DECL_ARGS)122332a712daSGarrett D'Amore termp_ex_pre(DECL_ARGS)
122432a712daSGarrett D'Amore {
122532a712daSGarrett D'Amore 	int		 nchild;
122632a712daSGarrett D'Amore 
122732a712daSGarrett D'Amore 	term_newln(p);
122832a712daSGarrett D'Amore 	term_word(p, "The");
122932a712daSGarrett D'Amore 
123032a712daSGarrett D'Amore 	nchild = n->nchild;
123132a712daSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
123232a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
123332a712daSGarrett D'Amore 		term_word(p, n->string);
123432a712daSGarrett D'Amore 		term_fontpop(p);
123532a712daSGarrett D'Amore 
123632a712daSGarrett D'Amore 		if (nchild > 2 && n->next) {
123732a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
123832a712daSGarrett D'Amore 			term_word(p, ",");
123932a712daSGarrett D'Amore 		}
124032a712daSGarrett D'Amore 
124132a712daSGarrett D'Amore 		if (n->next && NULL == n->next->next)
124232a712daSGarrett D'Amore 			term_word(p, "and");
124332a712daSGarrett D'Amore 	}
124432a712daSGarrett D'Amore 
124532a712daSGarrett D'Amore 	if (nchild > 1)
124632a712daSGarrett D'Amore 		term_word(p, "utilities exit");
124732a712daSGarrett D'Amore 	else
124832a712daSGarrett D'Amore 		term_word(p, "utility exits");
124932a712daSGarrett D'Amore 
125032a712daSGarrett D'Amore        	term_word(p, "0 on success, and >0 if an error occurs.");
125132a712daSGarrett D'Amore 
125232a712daSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
125332a712daSGarrett D'Amore 	return(0);
125432a712daSGarrett D'Amore }
125532a712daSGarrett D'Amore 
125632a712daSGarrett D'Amore 
125732a712daSGarrett D'Amore /* ARGSUSED */
125832a712daSGarrett D'Amore static int
termp_nd_pre(DECL_ARGS)125932a712daSGarrett D'Amore termp_nd_pre(DECL_ARGS)
126032a712daSGarrett D'Amore {
126132a712daSGarrett D'Amore 
126232a712daSGarrett D'Amore 	if (MDOC_BODY != n->type)
126332a712daSGarrett D'Amore 		return(1);
126432a712daSGarrett D'Amore 
126532a712daSGarrett D'Amore #if defined(__OpenBSD__) || defined(__linux__)
126632a712daSGarrett D'Amore 	term_word(p, "\\(en");
126732a712daSGarrett D'Amore #else
126832a712daSGarrett D'Amore 	term_word(p, "\\(em");
126932a712daSGarrett D'Amore #endif
127032a712daSGarrett D'Amore 	return(1);
127132a712daSGarrett D'Amore }
127232a712daSGarrett D'Amore 
127332a712daSGarrett D'Amore 
127432a712daSGarrett D'Amore /* ARGSUSED */
127532a712daSGarrett D'Amore static int
termp_bl_pre(DECL_ARGS)127632a712daSGarrett D'Amore termp_bl_pre(DECL_ARGS)
127732a712daSGarrett D'Amore {
127832a712daSGarrett D'Amore 
127932a712daSGarrett D'Amore 	return(MDOC_HEAD != n->type);
128032a712daSGarrett D'Amore }
128132a712daSGarrett D'Amore 
128232a712daSGarrett D'Amore 
128332a712daSGarrett D'Amore /* ARGSUSED */
128432a712daSGarrett D'Amore static void
termp_bl_post(DECL_ARGS)128532a712daSGarrett D'Amore termp_bl_post(DECL_ARGS)
128632a712daSGarrett D'Amore {
128732a712daSGarrett D'Amore 
128832a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
128932a712daSGarrett D'Amore 		term_newln(p);
129032a712daSGarrett D'Amore }
129132a712daSGarrett D'Amore 
129232a712daSGarrett D'Amore /* ARGSUSED */
129332a712daSGarrett D'Amore static int
termp_xr_pre(DECL_ARGS)129432a712daSGarrett D'Amore termp_xr_pre(DECL_ARGS)
129532a712daSGarrett D'Amore {
129632a712daSGarrett D'Amore 
129732a712daSGarrett D'Amore 	if (NULL == (n = n->child))
129832a712daSGarrett D'Amore 		return(0);
129932a712daSGarrett D'Amore 
130032a712daSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
130132a712daSGarrett D'Amore 	term_word(p, n->string);
130232a712daSGarrett D'Amore 
130332a712daSGarrett D'Amore 	if (NULL == (n = n->next))
130432a712daSGarrett D'Amore 		return(0);
130532a712daSGarrett D'Amore 
130632a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
130732a712daSGarrett D'Amore 	term_word(p, "(");
130832a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
130932a712daSGarrett D'Amore 
131032a712daSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
131132a712daSGarrett D'Amore 	term_word(p, n->string);
131232a712daSGarrett D'Amore 
131332a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
131432a712daSGarrett D'Amore 	term_word(p, ")");
131532a712daSGarrett D'Amore 
131632a712daSGarrett D'Amore 	return(0);
131732a712daSGarrett D'Amore }
131832a712daSGarrett D'Amore 
131932a712daSGarrett D'Amore /*
132032a712daSGarrett D'Amore  * This decides how to assert whitespace before any of the SYNOPSIS set
132132a712daSGarrett D'Amore  * of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
132232a712daSGarrett D'Amore  * macro combos).
132332a712daSGarrett D'Amore  */
132432a712daSGarrett D'Amore static void
synopsis_pre(struct termp * p,const struct mdoc_node * n)132532a712daSGarrett D'Amore synopsis_pre(struct termp *p, const struct mdoc_node *n)
132632a712daSGarrett D'Amore {
132732a712daSGarrett D'Amore 	/*
132832a712daSGarrett D'Amore 	 * Obviously, if we're not in a SYNOPSIS or no prior macros
132932a712daSGarrett D'Amore 	 * exist, do nothing.
133032a712daSGarrett D'Amore 	 */
133132a712daSGarrett D'Amore 	if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
133232a712daSGarrett D'Amore 		return;
133332a712daSGarrett D'Amore 
133432a712daSGarrett D'Amore 	/*
133532a712daSGarrett D'Amore 	 * If we're the second in a pair of like elements, emit our
133632a712daSGarrett D'Amore 	 * newline and return.  UNLESS we're `Fo', `Fn', `Fn', in which
133732a712daSGarrett D'Amore 	 * case we soldier on.
133832a712daSGarrett D'Amore 	 */
133932a712daSGarrett D'Amore 	if (n->prev->tok == n->tok &&
134032a712daSGarrett D'Amore 			MDOC_Ft != n->tok &&
134132a712daSGarrett D'Amore 			MDOC_Fo != n->tok &&
134232a712daSGarrett D'Amore 			MDOC_Fn != n->tok) {
134332a712daSGarrett D'Amore 		term_newln(p);
134432a712daSGarrett D'Amore 		return;
134532a712daSGarrett D'Amore 	}
134632a712daSGarrett D'Amore 
134732a712daSGarrett D'Amore 	/*
134832a712daSGarrett D'Amore 	 * If we're one of the SYNOPSIS set and non-like pair-wise after
134932a712daSGarrett D'Amore 	 * another (or Fn/Fo, which we've let slip through) then assert
135032a712daSGarrett D'Amore 	 * vertical space, else only newline and move on.
135132a712daSGarrett D'Amore 	 */
135232a712daSGarrett D'Amore 	switch (n->prev->tok) {
135332a712daSGarrett D'Amore 	case (MDOC_Fd):
135432a712daSGarrett D'Amore 		/* FALLTHROUGH */
135532a712daSGarrett D'Amore 	case (MDOC_Fn):
135632a712daSGarrett D'Amore 		/* FALLTHROUGH */
135732a712daSGarrett D'Amore 	case (MDOC_Fo):
135832a712daSGarrett D'Amore 		/* FALLTHROUGH */
135932a712daSGarrett D'Amore 	case (MDOC_In):
136032a712daSGarrett D'Amore 		/* FALLTHROUGH */
136132a712daSGarrett D'Amore 	case (MDOC_Vt):
136232a712daSGarrett D'Amore 		term_vspace(p);
136332a712daSGarrett D'Amore 		break;
136432a712daSGarrett D'Amore 	case (MDOC_Ft):
136532a712daSGarrett D'Amore 		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
136632a712daSGarrett D'Amore 			term_vspace(p);
136732a712daSGarrett D'Amore 			break;
136832a712daSGarrett D'Amore 		}
136932a712daSGarrett D'Amore 		/* FALLTHROUGH */
137032a712daSGarrett D'Amore 	default:
137132a712daSGarrett D'Amore 		term_newln(p);
137232a712daSGarrett D'Amore 		break;
137332a712daSGarrett D'Amore 	}
137432a712daSGarrett D'Amore }
137532a712daSGarrett D'Amore 
137632a712daSGarrett D'Amore 
137732a712daSGarrett D'Amore static int
termp_vt_pre(DECL_ARGS)137832a712daSGarrett D'Amore termp_vt_pre(DECL_ARGS)
137932a712daSGarrett D'Amore {
138032a712daSGarrett D'Amore 
138132a712daSGarrett D'Amore 	if (MDOC_ELEM == n->type) {
138232a712daSGarrett D'Amore 		synopsis_pre(p, n);
1383*ffb8ebfaSGarrett D'Amore 		return(termp_under_pre(p, pair, meta, n));
138432a712daSGarrett D'Amore 	} else if (MDOC_BLOCK == n->type) {
138532a712daSGarrett D'Amore 		synopsis_pre(p, n);
138632a712daSGarrett D'Amore 		return(1);
138732a712daSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
138832a712daSGarrett D'Amore 		return(0);
138932a712daSGarrett D'Amore 
1390*ffb8ebfaSGarrett D'Amore 	return(termp_under_pre(p, pair, meta, n));
139132a712daSGarrett D'Amore }
139232a712daSGarrett D'Amore 
139332a712daSGarrett D'Amore 
139432a712daSGarrett D'Amore /* ARGSUSED */
139532a712daSGarrett D'Amore static int
termp_bold_pre(DECL_ARGS)139632a712daSGarrett D'Amore termp_bold_pre(DECL_ARGS)
139732a712daSGarrett D'Amore {
139832a712daSGarrett D'Amore 
139932a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
140032a712daSGarrett D'Amore 	return(1);
140132a712daSGarrett D'Amore }
140232a712daSGarrett D'Amore 
140332a712daSGarrett D'Amore 
140432a712daSGarrett D'Amore /* ARGSUSED */
140532a712daSGarrett D'Amore static int
termp_fd_pre(DECL_ARGS)140632a712daSGarrett D'Amore termp_fd_pre(DECL_ARGS)
140732a712daSGarrett D'Amore {
140832a712daSGarrett D'Amore 
140932a712daSGarrett D'Amore 	synopsis_pre(p, n);
1410*ffb8ebfaSGarrett D'Amore 	return(termp_bold_pre(p, pair, meta, n));
1411*ffb8ebfaSGarrett D'Amore }
1412*ffb8ebfaSGarrett D'Amore 
1413*ffb8ebfaSGarrett D'Amore 
1414*ffb8ebfaSGarrett D'Amore /* ARGSUSED */
1415*ffb8ebfaSGarrett D'Amore static void
termp_fd_post(DECL_ARGS)1416*ffb8ebfaSGarrett D'Amore termp_fd_post(DECL_ARGS)
1417*ffb8ebfaSGarrett D'Amore {
1418*ffb8ebfaSGarrett D'Amore 
1419*ffb8ebfaSGarrett D'Amore 	term_newln(p);
142032a712daSGarrett D'Amore }
142132a712daSGarrett D'Amore 
142232a712daSGarrett D'Amore 
142332a712daSGarrett D'Amore /* ARGSUSED */
142432a712daSGarrett D'Amore static int
termp_sh_pre(DECL_ARGS)142532a712daSGarrett D'Amore termp_sh_pre(DECL_ARGS)
142632a712daSGarrett D'Amore {
142732a712daSGarrett D'Amore 
142832a712daSGarrett D'Amore 	/* No vspace between consecutive `Sh' calls. */
142932a712daSGarrett D'Amore 
143032a712daSGarrett D'Amore 	switch (n->type) {
143132a712daSGarrett D'Amore 	case (MDOC_BLOCK):
143232a712daSGarrett D'Amore 		if (n->prev && MDOC_Sh == n->prev->tok)
143332a712daSGarrett D'Amore 			if (NULL == n->prev->body->child)
143432a712daSGarrett D'Amore 				break;
143532a712daSGarrett D'Amore 		term_vspace(p);
143632a712daSGarrett D'Amore 		break;
143732a712daSGarrett D'Amore 	case (MDOC_HEAD):
143832a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
143932a712daSGarrett D'Amore 		break;
144032a712daSGarrett D'Amore 	case (MDOC_BODY):
144132a712daSGarrett D'Amore 		p->offset = term_len(p, p->defindent);
1442*ffb8ebfaSGarrett D'Amore 		if (SEC_AUTHORS == n->sec)
1443*ffb8ebfaSGarrett D'Amore 			p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
144432a712daSGarrett D'Amore 		break;
144532a712daSGarrett D'Amore 	default:
144632a712daSGarrett D'Amore 		break;
144732a712daSGarrett D'Amore 	}
144832a712daSGarrett D'Amore 	return(1);
144932a712daSGarrett D'Amore }
145032a712daSGarrett D'Amore 
145132a712daSGarrett D'Amore 
145232a712daSGarrett D'Amore /* ARGSUSED */
145332a712daSGarrett D'Amore static void
termp_sh_post(DECL_ARGS)145432a712daSGarrett D'Amore termp_sh_post(DECL_ARGS)
145532a712daSGarrett D'Amore {
145632a712daSGarrett D'Amore 
145732a712daSGarrett D'Amore 	switch (n->type) {
145832a712daSGarrett D'Amore 	case (MDOC_HEAD):
145932a712daSGarrett D'Amore 		term_newln(p);
146032a712daSGarrett D'Amore 		break;
146132a712daSGarrett D'Amore 	case (MDOC_BODY):
146232a712daSGarrett D'Amore 		term_newln(p);
146332a712daSGarrett D'Amore 		p->offset = 0;
146432a712daSGarrett D'Amore 		break;
146532a712daSGarrett D'Amore 	default:
146632a712daSGarrett D'Amore 		break;
146732a712daSGarrett D'Amore 	}
146832a712daSGarrett D'Amore }
146932a712daSGarrett D'Amore 
147032a712daSGarrett D'Amore 
147132a712daSGarrett D'Amore /* ARGSUSED */
147232a712daSGarrett D'Amore static int
termp_bt_pre(DECL_ARGS)147332a712daSGarrett D'Amore termp_bt_pre(DECL_ARGS)
147432a712daSGarrett D'Amore {
147532a712daSGarrett D'Amore 
147632a712daSGarrett D'Amore 	term_word(p, "is currently in beta test.");
147732a712daSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
147832a712daSGarrett D'Amore 	return(0);
147932a712daSGarrett D'Amore }
148032a712daSGarrett D'Amore 
148132a712daSGarrett D'Amore 
148232a712daSGarrett D'Amore /* ARGSUSED */
148332a712daSGarrett D'Amore static void
termp_lb_post(DECL_ARGS)148432a712daSGarrett D'Amore termp_lb_post(DECL_ARGS)
148532a712daSGarrett D'Amore {
148632a712daSGarrett D'Amore 
148732a712daSGarrett D'Amore 	if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags)
148832a712daSGarrett D'Amore 		term_newln(p);
148932a712daSGarrett D'Amore }
149032a712daSGarrett D'Amore 
149132a712daSGarrett D'Amore 
149232a712daSGarrett D'Amore /* ARGSUSED */
149332a712daSGarrett D'Amore static int
termp_ud_pre(DECL_ARGS)149432a712daSGarrett D'Amore termp_ud_pre(DECL_ARGS)
149532a712daSGarrett D'Amore {
149632a712daSGarrett D'Amore 
149732a712daSGarrett D'Amore 	term_word(p, "currently under development.");
149832a712daSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
149932a712daSGarrett D'Amore 	return(0);
150032a712daSGarrett D'Amore }
150132a712daSGarrett D'Amore 
150232a712daSGarrett D'Amore 
150332a712daSGarrett D'Amore /* ARGSUSED */
150432a712daSGarrett D'Amore static int
termp_d1_pre(DECL_ARGS)150532a712daSGarrett D'Amore termp_d1_pre(DECL_ARGS)
150632a712daSGarrett D'Amore {
150732a712daSGarrett D'Amore 
150832a712daSGarrett D'Amore 	if (MDOC_BLOCK != n->type)
150932a712daSGarrett D'Amore 		return(1);
151032a712daSGarrett D'Amore 	term_newln(p);
151132a712daSGarrett D'Amore 	p->offset += term_len(p, p->defindent + 1);
151232a712daSGarrett D'Amore 	return(1);
151332a712daSGarrett D'Amore }
151432a712daSGarrett D'Amore 
151532a712daSGarrett D'Amore 
151632a712daSGarrett D'Amore /* ARGSUSED */
151732a712daSGarrett D'Amore static int
termp_ft_pre(DECL_ARGS)151832a712daSGarrett D'Amore termp_ft_pre(DECL_ARGS)
151932a712daSGarrett D'Amore {
152032a712daSGarrett D'Amore 
152132a712daSGarrett D'Amore 	/* NB: MDOC_LINE does not effect this! */
152232a712daSGarrett D'Amore 	synopsis_pre(p, n);
152332a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
152432a712daSGarrett D'Amore 	return(1);
152532a712daSGarrett D'Amore }
152632a712daSGarrett D'Amore 
152732a712daSGarrett D'Amore 
152832a712daSGarrett D'Amore /* ARGSUSED */
152932a712daSGarrett D'Amore static int
termp_fn_pre(DECL_ARGS)153032a712daSGarrett D'Amore termp_fn_pre(DECL_ARGS)
153132a712daSGarrett D'Amore {
1532*ffb8ebfaSGarrett D'Amore 	size_t		 rmargin = 0;
153332a712daSGarrett D'Amore 	int		 pretty;
153432a712daSGarrett D'Amore 
153532a712daSGarrett D'Amore 	pretty = MDOC_SYNPRETTY & n->flags;
153632a712daSGarrett D'Amore 
153732a712daSGarrett D'Amore 	synopsis_pre(p, n);
153832a712daSGarrett D'Amore 
153932a712daSGarrett D'Amore 	if (NULL == (n = n->child))
154032a712daSGarrett D'Amore 		return(0);
154132a712daSGarrett D'Amore 
1542*ffb8ebfaSGarrett D'Amore 	if (pretty) {
1543*ffb8ebfaSGarrett D'Amore 		rmargin = p->rmargin;
1544*ffb8ebfaSGarrett D'Amore 		p->rmargin = p->offset + term_len(p, 4);
1545*ffb8ebfaSGarrett D'Amore 		p->flags |= TERMP_NOBREAK | TERMP_HANG;
1546*ffb8ebfaSGarrett D'Amore 	}
1547*ffb8ebfaSGarrett D'Amore 
154832a712daSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
154932a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
155032a712daSGarrett D'Amore 	term_word(p, n->string);
155132a712daSGarrett D'Amore 	term_fontpop(p);
155232a712daSGarrett D'Amore 
1553*ffb8ebfaSGarrett D'Amore 	if (pretty) {
1554*ffb8ebfaSGarrett D'Amore 		term_flushln(p);
1555*ffb8ebfaSGarrett D'Amore 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
1556*ffb8ebfaSGarrett D'Amore 		p->offset = p->rmargin;
1557*ffb8ebfaSGarrett D'Amore 		p->rmargin = rmargin;
1558*ffb8ebfaSGarrett D'Amore 	}
1559*ffb8ebfaSGarrett D'Amore 
156032a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
156132a712daSGarrett D'Amore 	term_word(p, "(");
156232a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
156332a712daSGarrett D'Amore 
156432a712daSGarrett D'Amore 	for (n = n->next; n; n = n->next) {
156532a712daSGarrett D'Amore 		assert(MDOC_TEXT == n->type);
156632a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1567*ffb8ebfaSGarrett D'Amore 		if (pretty)
1568*ffb8ebfaSGarrett D'Amore 			p->flags |= TERMP_NBRWORD;
156932a712daSGarrett D'Amore 		term_word(p, n->string);
157032a712daSGarrett D'Amore 		term_fontpop(p);
157132a712daSGarrett D'Amore 
157232a712daSGarrett D'Amore 		if (n->next) {
157332a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
157432a712daSGarrett D'Amore 			term_word(p, ",");
157532a712daSGarrett D'Amore 		}
157632a712daSGarrett D'Amore 	}
157732a712daSGarrett D'Amore 
157832a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
157932a712daSGarrett D'Amore 	term_word(p, ")");
158032a712daSGarrett D'Amore 
158132a712daSGarrett D'Amore 	if (pretty) {
158232a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
158332a712daSGarrett D'Amore 		term_word(p, ";");
1584*ffb8ebfaSGarrett D'Amore 		term_flushln(p);
158532a712daSGarrett D'Amore 	}
158632a712daSGarrett D'Amore 
158732a712daSGarrett D'Amore 	return(0);
158832a712daSGarrett D'Amore }
158932a712daSGarrett D'Amore 
159032a712daSGarrett D'Amore 
159132a712daSGarrett D'Amore /* ARGSUSED */
159232a712daSGarrett D'Amore static int
termp_fa_pre(DECL_ARGS)159332a712daSGarrett D'Amore termp_fa_pre(DECL_ARGS)
159432a712daSGarrett D'Amore {
159532a712daSGarrett D'Amore 	const struct mdoc_node	*nn;
159632a712daSGarrett D'Amore 
159732a712daSGarrett D'Amore 	if (n->parent->tok != MDOC_Fo) {
159832a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
159932a712daSGarrett D'Amore 		return(1);
160032a712daSGarrett D'Amore 	}
160132a712daSGarrett D'Amore 
160232a712daSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
160332a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1604*ffb8ebfaSGarrett D'Amore 		p->flags |= TERMP_NBRWORD;
160532a712daSGarrett D'Amore 		term_word(p, nn->string);
160632a712daSGarrett D'Amore 		term_fontpop(p);
160732a712daSGarrett D'Amore 
1608*ffb8ebfaSGarrett D'Amore 		if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
160932a712daSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
161032a712daSGarrett D'Amore 			term_word(p, ",");
161132a712daSGarrett D'Amore 		}
161232a712daSGarrett D'Amore 	}
161332a712daSGarrett D'Amore 
161432a712daSGarrett D'Amore 	return(0);
161532a712daSGarrett D'Amore }
161632a712daSGarrett D'Amore 
161732a712daSGarrett D'Amore 
161832a712daSGarrett D'Amore /* ARGSUSED */
161932a712daSGarrett D'Amore static int
termp_bd_pre(DECL_ARGS)162032a712daSGarrett D'Amore termp_bd_pre(DECL_ARGS)
162132a712daSGarrett D'Amore {
162232a712daSGarrett D'Amore 	size_t			 tabwidth, rm, rmax;
1623*ffb8ebfaSGarrett D'Amore 	struct mdoc_node	*nn;
162432a712daSGarrett D'Amore 
162532a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
162632a712daSGarrett D'Amore 		print_bvspace(p, n, n);
162732a712daSGarrett D'Amore 		return(1);
162832a712daSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
162932a712daSGarrett D'Amore 		return(0);
163032a712daSGarrett D'Amore 
163132a712daSGarrett D'Amore 	if (n->norm->Bd.offs)
163232a712daSGarrett D'Amore 		p->offset += a2offs(p, n->norm->Bd.offs);
163332a712daSGarrett D'Amore 
163432a712daSGarrett D'Amore 	/*
163532a712daSGarrett D'Amore 	 * If -ragged or -filled are specified, the block does nothing
163632a712daSGarrett D'Amore 	 * but change the indentation.  If -unfilled or -literal are
163732a712daSGarrett D'Amore 	 * specified, text is printed exactly as entered in the display:
163832a712daSGarrett D'Amore 	 * for macro lines, a newline is appended to the line.  Blank
163932a712daSGarrett D'Amore 	 * lines are allowed.
164032a712daSGarrett D'Amore 	 */
164132a712daSGarrett D'Amore 
164232a712daSGarrett D'Amore 	if (DISP_literal != n->norm->Bd.type &&
164332a712daSGarrett D'Amore 			DISP_unfilled != n->norm->Bd.type)
164432a712daSGarrett D'Amore 		return(1);
164532a712daSGarrett D'Amore 
164632a712daSGarrett D'Amore 	tabwidth = p->tabwidth;
164732a712daSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type)
164832a712daSGarrett D'Amore 		p->tabwidth = term_len(p, 8);
164932a712daSGarrett D'Amore 
165032a712daSGarrett D'Amore 	rm = p->rmargin;
165132a712daSGarrett D'Amore 	rmax = p->maxrmargin;
165232a712daSGarrett D'Amore 	p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
165332a712daSGarrett D'Amore 
165432a712daSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
1655*ffb8ebfaSGarrett D'Amore 		print_mdoc_node(p, pair, meta, nn);
165632a712daSGarrett D'Amore 		/*
165732a712daSGarrett D'Amore 		 * If the printed node flushes its own line, then we
165832a712daSGarrett D'Amore 		 * needn't do it here as well.  This is hacky, but the
165932a712daSGarrett D'Amore 		 * notion of selective eoln whitespace is pretty dumb
166032a712daSGarrett D'Amore 		 * anyway, so don't sweat it.
166132a712daSGarrett D'Amore 		 */
166232a712daSGarrett D'Amore 		switch (nn->tok) {
166332a712daSGarrett D'Amore 		case (MDOC_Sm):
166432a712daSGarrett D'Amore 			/* FALLTHROUGH */
166532a712daSGarrett D'Amore 		case (MDOC_br):
166632a712daSGarrett D'Amore 			/* FALLTHROUGH */
166732a712daSGarrett D'Amore 		case (MDOC_sp):
166832a712daSGarrett D'Amore 			/* FALLTHROUGH */
166932a712daSGarrett D'Amore 		case (MDOC_Bl):
167032a712daSGarrett D'Amore 			/* FALLTHROUGH */
167132a712daSGarrett D'Amore 		case (MDOC_D1):
167232a712daSGarrett D'Amore 			/* FALLTHROUGH */
167332a712daSGarrett D'Amore 		case (MDOC_Dl):
167432a712daSGarrett D'Amore 			/* FALLTHROUGH */
167532a712daSGarrett D'Amore 		case (MDOC_Lp):
167632a712daSGarrett D'Amore 			/* FALLTHROUGH */
167732a712daSGarrett D'Amore 		case (MDOC_Pp):
167832a712daSGarrett D'Amore 			continue;
167932a712daSGarrett D'Amore 		default:
168032a712daSGarrett D'Amore 			break;
168132a712daSGarrett D'Amore 		}
168232a712daSGarrett D'Amore 		if (nn->next && nn->next->line == nn->line)
168332a712daSGarrett D'Amore 			continue;
168432a712daSGarrett D'Amore 		term_flushln(p);
168532a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
168632a712daSGarrett D'Amore 	}
168732a712daSGarrett D'Amore 
168832a712daSGarrett D'Amore 	p->tabwidth = tabwidth;
168932a712daSGarrett D'Amore 	p->rmargin = rm;
169032a712daSGarrett D'Amore 	p->maxrmargin = rmax;
169132a712daSGarrett D'Amore 	return(0);
169232a712daSGarrett D'Amore }
169332a712daSGarrett D'Amore 
169432a712daSGarrett D'Amore 
169532a712daSGarrett D'Amore /* ARGSUSED */
169632a712daSGarrett D'Amore static void
termp_bd_post(DECL_ARGS)169732a712daSGarrett D'Amore termp_bd_post(DECL_ARGS)
169832a712daSGarrett D'Amore {
169932a712daSGarrett D'Amore 	size_t		 rm, rmax;
170032a712daSGarrett D'Amore 
170132a712daSGarrett D'Amore 	if (MDOC_BODY != n->type)
170232a712daSGarrett D'Amore 		return;
170332a712daSGarrett D'Amore 
170432a712daSGarrett D'Amore 	rm = p->rmargin;
170532a712daSGarrett D'Amore 	rmax = p->maxrmargin;
170632a712daSGarrett D'Amore 
170732a712daSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type ||
170832a712daSGarrett D'Amore 			DISP_unfilled == n->norm->Bd.type)
170932a712daSGarrett D'Amore 		p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
171032a712daSGarrett D'Amore 
171132a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
171232a712daSGarrett D'Amore 	term_newln(p);
171332a712daSGarrett D'Amore 
171432a712daSGarrett D'Amore 	p->rmargin = rm;
171532a712daSGarrett D'Amore 	p->maxrmargin = rmax;
171632a712daSGarrett D'Amore }
171732a712daSGarrett D'Amore 
171832a712daSGarrett D'Amore 
171932a712daSGarrett D'Amore /* ARGSUSED */
172032a712daSGarrett D'Amore static int
termp_bx_pre(DECL_ARGS)172132a712daSGarrett D'Amore termp_bx_pre(DECL_ARGS)
172232a712daSGarrett D'Amore {
172332a712daSGarrett D'Amore 
172432a712daSGarrett D'Amore 	if (NULL != (n = n->child)) {
172532a712daSGarrett D'Amore 		term_word(p, n->string);
172632a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
172732a712daSGarrett D'Amore 		term_word(p, "BSD");
172832a712daSGarrett D'Amore 	} else {
172932a712daSGarrett D'Amore 		term_word(p, "BSD");
173032a712daSGarrett D'Amore 		return(0);
173132a712daSGarrett D'Amore 	}
173232a712daSGarrett D'Amore 
173332a712daSGarrett D'Amore 	if (NULL != (n = n->next)) {
173432a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
173532a712daSGarrett D'Amore 		term_word(p, "-");
173632a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
173732a712daSGarrett D'Amore 		term_word(p, n->string);
173832a712daSGarrett D'Amore 	}
173932a712daSGarrett D'Amore 
174032a712daSGarrett D'Amore 	return(0);
174132a712daSGarrett D'Amore }
174232a712daSGarrett D'Amore 
174332a712daSGarrett D'Amore 
174432a712daSGarrett D'Amore /* ARGSUSED */
174532a712daSGarrett D'Amore static int
termp_xx_pre(DECL_ARGS)174632a712daSGarrett D'Amore termp_xx_pre(DECL_ARGS)
174732a712daSGarrett D'Amore {
174832a712daSGarrett D'Amore 	const char	*pp;
174932a712daSGarrett D'Amore 	int		 flags;
175032a712daSGarrett D'Amore 
175132a712daSGarrett D'Amore 	pp = NULL;
175232a712daSGarrett D'Amore 	switch (n->tok) {
175332a712daSGarrett D'Amore 	case (MDOC_Bsx):
175432a712daSGarrett D'Amore 		pp = "BSD/OS";
175532a712daSGarrett D'Amore 		break;
175632a712daSGarrett D'Amore 	case (MDOC_Dx):
175732a712daSGarrett D'Amore 		pp = "DragonFly";
175832a712daSGarrett D'Amore 		break;
175932a712daSGarrett D'Amore 	case (MDOC_Fx):
176032a712daSGarrett D'Amore 		pp = "FreeBSD";
176132a712daSGarrett D'Amore 		break;
176232a712daSGarrett D'Amore 	case (MDOC_Nx):
176332a712daSGarrett D'Amore 		pp = "NetBSD";
176432a712daSGarrett D'Amore 		break;
176532a712daSGarrett D'Amore 	case (MDOC_Ox):
176632a712daSGarrett D'Amore 		pp = "OpenBSD";
176732a712daSGarrett D'Amore 		break;
176832a712daSGarrett D'Amore 	case (MDOC_Ux):
176932a712daSGarrett D'Amore 		pp = "UNIX";
177032a712daSGarrett D'Amore 		break;
177132a712daSGarrett D'Amore 	default:
1772*ffb8ebfaSGarrett D'Amore 		abort();
1773*ffb8ebfaSGarrett D'Amore 		/* NOTREACHED */
177432a712daSGarrett D'Amore 	}
177532a712daSGarrett D'Amore 
177632a712daSGarrett D'Amore 	term_word(p, pp);
177732a712daSGarrett D'Amore 	if (n->child) {
177832a712daSGarrett D'Amore 		flags = p->flags;
177932a712daSGarrett D'Amore 		p->flags |= TERMP_KEEP;
178032a712daSGarrett D'Amore 		term_word(p, n->child->string);
178132a712daSGarrett D'Amore 		p->flags = flags;
178232a712daSGarrett D'Amore 	}
178332a712daSGarrett D'Amore 	return(0);
178432a712daSGarrett D'Amore }
178532a712daSGarrett D'Amore 
178632a712daSGarrett D'Amore 
178732a712daSGarrett D'Amore /* ARGSUSED */
178832a712daSGarrett D'Amore static void
termp_pf_post(DECL_ARGS)178932a712daSGarrett D'Amore termp_pf_post(DECL_ARGS)
179032a712daSGarrett D'Amore {
179132a712daSGarrett D'Amore 
179232a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
179332a712daSGarrett D'Amore }
179432a712daSGarrett D'Amore 
179532a712daSGarrett D'Amore 
179632a712daSGarrett D'Amore /* ARGSUSED */
179732a712daSGarrett D'Amore static int
termp_ss_pre(DECL_ARGS)179832a712daSGarrett D'Amore termp_ss_pre(DECL_ARGS)
179932a712daSGarrett D'Amore {
180032a712daSGarrett D'Amore 
180132a712daSGarrett D'Amore 	switch (n->type) {
180232a712daSGarrett D'Amore 	case (MDOC_BLOCK):
180332a712daSGarrett D'Amore 		term_newln(p);
180432a712daSGarrett D'Amore 		if (n->prev)
180532a712daSGarrett D'Amore 			term_vspace(p);
180632a712daSGarrett D'Amore 		break;
180732a712daSGarrett D'Amore 	case (MDOC_HEAD):
180832a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
180932a712daSGarrett D'Amore 		p->offset = term_len(p, (p->defindent+1)/2);
181032a712daSGarrett D'Amore 		break;
181132a712daSGarrett D'Amore 	default:
181232a712daSGarrett D'Amore 		break;
181332a712daSGarrett D'Amore 	}
181432a712daSGarrett D'Amore 
181532a712daSGarrett D'Amore 	return(1);
181632a712daSGarrett D'Amore }
181732a712daSGarrett D'Amore 
181832a712daSGarrett D'Amore 
181932a712daSGarrett D'Amore /* ARGSUSED */
182032a712daSGarrett D'Amore static void
termp_ss_post(DECL_ARGS)182132a712daSGarrett D'Amore termp_ss_post(DECL_ARGS)
182232a712daSGarrett D'Amore {
182332a712daSGarrett D'Amore 
182432a712daSGarrett D'Amore 	if (MDOC_HEAD == n->type)
182532a712daSGarrett D'Amore 		term_newln(p);
182632a712daSGarrett D'Amore }
182732a712daSGarrett D'Amore 
182832a712daSGarrett D'Amore 
182932a712daSGarrett D'Amore /* ARGSUSED */
183032a712daSGarrett D'Amore static int
termp_cd_pre(DECL_ARGS)183132a712daSGarrett D'Amore termp_cd_pre(DECL_ARGS)
183232a712daSGarrett D'Amore {
183332a712daSGarrett D'Amore 
183432a712daSGarrett D'Amore 	synopsis_pre(p, n);
183532a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
183632a712daSGarrett D'Amore 	return(1);
183732a712daSGarrett D'Amore }
183832a712daSGarrett D'Amore 
183932a712daSGarrett D'Amore 
184032a712daSGarrett D'Amore /* ARGSUSED */
184132a712daSGarrett D'Amore static int
termp_in_pre(DECL_ARGS)184232a712daSGarrett D'Amore termp_in_pre(DECL_ARGS)
184332a712daSGarrett D'Amore {
184432a712daSGarrett D'Amore 
184532a712daSGarrett D'Amore 	synopsis_pre(p, n);
184632a712daSGarrett D'Amore 
184732a712daSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags) {
184832a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
184932a712daSGarrett D'Amore 		term_word(p, "#include");
185032a712daSGarrett D'Amore 		term_word(p, "<");
185132a712daSGarrett D'Amore 	} else {
185232a712daSGarrett D'Amore 		term_word(p, "<");
185332a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
185432a712daSGarrett D'Amore 	}
185532a712daSGarrett D'Amore 
185632a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
185732a712daSGarrett D'Amore 	return(1);
185832a712daSGarrett D'Amore }
185932a712daSGarrett D'Amore 
186032a712daSGarrett D'Amore 
186132a712daSGarrett D'Amore /* ARGSUSED */
186232a712daSGarrett D'Amore static void
termp_in_post(DECL_ARGS)186332a712daSGarrett D'Amore termp_in_post(DECL_ARGS)
186432a712daSGarrett D'Amore {
186532a712daSGarrett D'Amore 
186632a712daSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
186732a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
186832a712daSGarrett D'Amore 
186932a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
187032a712daSGarrett D'Amore 	term_word(p, ">");
187132a712daSGarrett D'Amore 
187232a712daSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
187332a712daSGarrett D'Amore 		term_fontpop(p);
187432a712daSGarrett D'Amore }
187532a712daSGarrett D'Amore 
187632a712daSGarrett D'Amore 
187732a712daSGarrett D'Amore /* ARGSUSED */
187832a712daSGarrett D'Amore static int
termp_sp_pre(DECL_ARGS)187932a712daSGarrett D'Amore termp_sp_pre(DECL_ARGS)
188032a712daSGarrett D'Amore {
188132a712daSGarrett D'Amore 	size_t		 i, len;
188232a712daSGarrett D'Amore 
188332a712daSGarrett D'Amore 	switch (n->tok) {
188432a712daSGarrett D'Amore 	case (MDOC_sp):
188532a712daSGarrett D'Amore 		len = n->child ? a2height(p, n->child->string) : 1;
188632a712daSGarrett D'Amore 		break;
188732a712daSGarrett D'Amore 	case (MDOC_br):
188832a712daSGarrett D'Amore 		len = 0;
188932a712daSGarrett D'Amore 		break;
189032a712daSGarrett D'Amore 	default:
189132a712daSGarrett D'Amore 		len = 1;
189232a712daSGarrett D'Amore 		break;
189332a712daSGarrett D'Amore 	}
189432a712daSGarrett D'Amore 
189532a712daSGarrett D'Amore 	if (0 == len)
189632a712daSGarrett D'Amore 		term_newln(p);
189732a712daSGarrett D'Amore 	for (i = 0; i < len; i++)
189832a712daSGarrett D'Amore 		term_vspace(p);
189932a712daSGarrett D'Amore 
190032a712daSGarrett D'Amore 	return(0);
190132a712daSGarrett D'Amore }
190232a712daSGarrett D'Amore 
190332a712daSGarrett D'Amore 
190432a712daSGarrett D'Amore /* ARGSUSED */
190532a712daSGarrett D'Amore static int
termp_quote_pre(DECL_ARGS)190632a712daSGarrett D'Amore termp_quote_pre(DECL_ARGS)
190732a712daSGarrett D'Amore {
190832a712daSGarrett D'Amore 
190932a712daSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
191032a712daSGarrett D'Amore 		return(1);
191132a712daSGarrett D'Amore 
191232a712daSGarrett D'Amore 	switch (n->tok) {
191332a712daSGarrett D'Amore 	case (MDOC_Ao):
191432a712daSGarrett D'Amore 		/* FALLTHROUGH */
191532a712daSGarrett D'Amore 	case (MDOC_Aq):
191632a712daSGarrett D'Amore 		term_word(p, "<");
191732a712daSGarrett D'Amore 		break;
191832a712daSGarrett D'Amore 	case (MDOC_Bro):
191932a712daSGarrett D'Amore 		/* FALLTHROUGH */
192032a712daSGarrett D'Amore 	case (MDOC_Brq):
192132a712daSGarrett D'Amore 		term_word(p, "{");
192232a712daSGarrett D'Amore 		break;
192332a712daSGarrett D'Amore 	case (MDOC_Oo):
192432a712daSGarrett D'Amore 		/* FALLTHROUGH */
192532a712daSGarrett D'Amore 	case (MDOC_Op):
192632a712daSGarrett D'Amore 		/* FALLTHROUGH */
192732a712daSGarrett D'Amore 	case (MDOC_Bo):
192832a712daSGarrett D'Amore 		/* FALLTHROUGH */
192932a712daSGarrett D'Amore 	case (MDOC_Bq):
193032a712daSGarrett D'Amore 		term_word(p, "[");
193132a712daSGarrett D'Amore 		break;
193232a712daSGarrett D'Amore 	case (MDOC_Do):
193332a712daSGarrett D'Amore 		/* FALLTHROUGH */
193432a712daSGarrett D'Amore 	case (MDOC_Dq):
1935*ffb8ebfaSGarrett D'Amore 		term_word(p, "\\(lq");
193632a712daSGarrett D'Amore 		break;
193732a712daSGarrett D'Amore 	case (MDOC_Eo):
193832a712daSGarrett D'Amore 		break;
193932a712daSGarrett D'Amore 	case (MDOC_Po):
194032a712daSGarrett D'Amore 		/* FALLTHROUGH */
194132a712daSGarrett D'Amore 	case (MDOC_Pq):
194232a712daSGarrett D'Amore 		term_word(p, "(");
194332a712daSGarrett D'Amore 		break;
194432a712daSGarrett D'Amore 	case (MDOC__T):
194532a712daSGarrett D'Amore 		/* FALLTHROUGH */
194632a712daSGarrett D'Amore 	case (MDOC_Qo):
194732a712daSGarrett D'Amore 		/* FALLTHROUGH */
194832a712daSGarrett D'Amore 	case (MDOC_Qq):
194932a712daSGarrett D'Amore 		term_word(p, "\"");
195032a712daSGarrett D'Amore 		break;
195132a712daSGarrett D'Amore 	case (MDOC_Ql):
195232a712daSGarrett D'Amore 		/* FALLTHROUGH */
195332a712daSGarrett D'Amore 	case (MDOC_So):
195432a712daSGarrett D'Amore 		/* FALLTHROUGH */
195532a712daSGarrett D'Amore 	case (MDOC_Sq):
1956*ffb8ebfaSGarrett D'Amore 		term_word(p, "\\(oq");
195732a712daSGarrett D'Amore 		break;
195832a712daSGarrett D'Amore 	default:
195932a712daSGarrett D'Amore 		abort();
196032a712daSGarrett D'Amore 		/* NOTREACHED */
196132a712daSGarrett D'Amore 	}
196232a712daSGarrett D'Amore 
196332a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
196432a712daSGarrett D'Amore 	return(1);
196532a712daSGarrett D'Amore }
196632a712daSGarrett D'Amore 
196732a712daSGarrett D'Amore 
196832a712daSGarrett D'Amore /* ARGSUSED */
196932a712daSGarrett D'Amore static void
termp_quote_post(DECL_ARGS)197032a712daSGarrett D'Amore termp_quote_post(DECL_ARGS)
197132a712daSGarrett D'Amore {
197232a712daSGarrett D'Amore 
197332a712daSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
197432a712daSGarrett D'Amore 		return;
197532a712daSGarrett D'Amore 
197632a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
197732a712daSGarrett D'Amore 
197832a712daSGarrett D'Amore 	switch (n->tok) {
197932a712daSGarrett D'Amore 	case (MDOC_Ao):
198032a712daSGarrett D'Amore 		/* FALLTHROUGH */
198132a712daSGarrett D'Amore 	case (MDOC_Aq):
198232a712daSGarrett D'Amore 		term_word(p, ">");
198332a712daSGarrett D'Amore 		break;
198432a712daSGarrett D'Amore 	case (MDOC_Bro):
198532a712daSGarrett D'Amore 		/* FALLTHROUGH */
198632a712daSGarrett D'Amore 	case (MDOC_Brq):
198732a712daSGarrett D'Amore 		term_word(p, "}");
198832a712daSGarrett D'Amore 		break;
198932a712daSGarrett D'Amore 	case (MDOC_Oo):
199032a712daSGarrett D'Amore 		/* FALLTHROUGH */
199132a712daSGarrett D'Amore 	case (MDOC_Op):
199232a712daSGarrett D'Amore 		/* FALLTHROUGH */
199332a712daSGarrett D'Amore 	case (MDOC_Bo):
199432a712daSGarrett D'Amore 		/* FALLTHROUGH */
199532a712daSGarrett D'Amore 	case (MDOC_Bq):
199632a712daSGarrett D'Amore 		term_word(p, "]");
199732a712daSGarrett D'Amore 		break;
199832a712daSGarrett D'Amore 	case (MDOC_Do):
199932a712daSGarrett D'Amore 		/* FALLTHROUGH */
200032a712daSGarrett D'Amore 	case (MDOC_Dq):
2001*ffb8ebfaSGarrett D'Amore 		term_word(p, "\\(rq");
200232a712daSGarrett D'Amore 		break;
200332a712daSGarrett D'Amore 	case (MDOC_Eo):
200432a712daSGarrett D'Amore 		break;
200532a712daSGarrett D'Amore 	case (MDOC_Po):
200632a712daSGarrett D'Amore 		/* FALLTHROUGH */
200732a712daSGarrett D'Amore 	case (MDOC_Pq):
200832a712daSGarrett D'Amore 		term_word(p, ")");
200932a712daSGarrett D'Amore 		break;
201032a712daSGarrett D'Amore 	case (MDOC__T):
201132a712daSGarrett D'Amore 		/* FALLTHROUGH */
201232a712daSGarrett D'Amore 	case (MDOC_Qo):
201332a712daSGarrett D'Amore 		/* FALLTHROUGH */
201432a712daSGarrett D'Amore 	case (MDOC_Qq):
201532a712daSGarrett D'Amore 		term_word(p, "\"");
201632a712daSGarrett D'Amore 		break;
201732a712daSGarrett D'Amore 	case (MDOC_Ql):
201832a712daSGarrett D'Amore 		/* FALLTHROUGH */
201932a712daSGarrett D'Amore 	case (MDOC_So):
202032a712daSGarrett D'Amore 		/* FALLTHROUGH */
202132a712daSGarrett D'Amore 	case (MDOC_Sq):
2022*ffb8ebfaSGarrett D'Amore 		term_word(p, "\\(cq");
202332a712daSGarrett D'Amore 		break;
202432a712daSGarrett D'Amore 	default:
202532a712daSGarrett D'Amore 		abort();
202632a712daSGarrett D'Amore 		/* NOTREACHED */
202732a712daSGarrett D'Amore 	}
202832a712daSGarrett D'Amore }
202932a712daSGarrett D'Amore 
203032a712daSGarrett D'Amore 
203132a712daSGarrett D'Amore /* ARGSUSED */
203232a712daSGarrett D'Amore static int
termp_fo_pre(DECL_ARGS)203332a712daSGarrett D'Amore termp_fo_pre(DECL_ARGS)
203432a712daSGarrett D'Amore {
2035*ffb8ebfaSGarrett D'Amore 	size_t		 rmargin = 0;
2036*ffb8ebfaSGarrett D'Amore 	int		 pretty;
2037*ffb8ebfaSGarrett D'Amore 
2038*ffb8ebfaSGarrett D'Amore 	pretty = MDOC_SYNPRETTY & n->flags;
203932a712daSGarrett D'Amore 
204032a712daSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
204132a712daSGarrett D'Amore 		synopsis_pre(p, n);
204232a712daSGarrett D'Amore 		return(1);
204332a712daSGarrett D'Amore 	} else if (MDOC_BODY == n->type) {
2044*ffb8ebfaSGarrett D'Amore 		if (pretty) {
2045*ffb8ebfaSGarrett D'Amore 			rmargin = p->rmargin;
2046*ffb8ebfaSGarrett D'Amore 			p->rmargin = p->offset + term_len(p, 4);
2047*ffb8ebfaSGarrett D'Amore 			p->flags |= TERMP_NOBREAK | TERMP_HANG;
2048*ffb8ebfaSGarrett D'Amore 		}
204932a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
205032a712daSGarrett D'Amore 		term_word(p, "(");
205132a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
2052*ffb8ebfaSGarrett D'Amore 		if (pretty) {
2053*ffb8ebfaSGarrett D'Amore 			term_flushln(p);
2054*ffb8ebfaSGarrett D'Amore 			p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
2055*ffb8ebfaSGarrett D'Amore 			p->offset = p->rmargin;
2056*ffb8ebfaSGarrett D'Amore 			p->rmargin = rmargin;
2057*ffb8ebfaSGarrett D'Amore 		}
205832a712daSGarrett D'Amore 		return(1);
205932a712daSGarrett D'Amore 	}
206032a712daSGarrett D'Amore 
206132a712daSGarrett D'Amore 	if (NULL == n->child)
206232a712daSGarrett D'Amore 		return(0);
206332a712daSGarrett D'Amore 
206432a712daSGarrett D'Amore 	/* XXX: we drop non-initial arguments as per groff. */
206532a712daSGarrett D'Amore 
206632a712daSGarrett D'Amore 	assert(n->child->string);
206732a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
206832a712daSGarrett D'Amore 	term_word(p, n->child->string);
206932a712daSGarrett D'Amore 	return(0);
207032a712daSGarrett D'Amore }
207132a712daSGarrett D'Amore 
207232a712daSGarrett D'Amore 
207332a712daSGarrett D'Amore /* ARGSUSED */
207432a712daSGarrett D'Amore static void
termp_fo_post(DECL_ARGS)207532a712daSGarrett D'Amore termp_fo_post(DECL_ARGS)
207632a712daSGarrett D'Amore {
207732a712daSGarrett D'Amore 
207832a712daSGarrett D'Amore 	if (MDOC_BODY != n->type)
207932a712daSGarrett D'Amore 		return;
208032a712daSGarrett D'Amore 
208132a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
208232a712daSGarrett D'Amore 	term_word(p, ")");
208332a712daSGarrett D'Amore 
208432a712daSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags) {
208532a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
208632a712daSGarrett D'Amore 		term_word(p, ";");
2087*ffb8ebfaSGarrett D'Amore 		term_flushln(p);
208832a712daSGarrett D'Amore 	}
208932a712daSGarrett D'Amore }
209032a712daSGarrett D'Amore 
209132a712daSGarrett D'Amore 
209232a712daSGarrett D'Amore /* ARGSUSED */
209332a712daSGarrett D'Amore static int
termp_bf_pre(DECL_ARGS)209432a712daSGarrett D'Amore termp_bf_pre(DECL_ARGS)
209532a712daSGarrett D'Amore {
209632a712daSGarrett D'Amore 
209732a712daSGarrett D'Amore 	if (MDOC_HEAD == n->type)
209832a712daSGarrett D'Amore 		return(0);
2099*ffb8ebfaSGarrett D'Amore 	else if (MDOC_BODY != n->type)
210032a712daSGarrett D'Amore 		return(1);
210132a712daSGarrett D'Amore 
210232a712daSGarrett D'Amore 	if (FONT_Em == n->norm->Bf.font)
210332a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
210432a712daSGarrett D'Amore 	else if (FONT_Sy == n->norm->Bf.font)
210532a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
210632a712daSGarrett D'Amore 	else
210732a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_NONE);
210832a712daSGarrett D'Amore 
210932a712daSGarrett D'Amore 	return(1);
211032a712daSGarrett D'Amore }
211132a712daSGarrett D'Amore 
211232a712daSGarrett D'Amore 
211332a712daSGarrett D'Amore /* ARGSUSED */
211432a712daSGarrett D'Amore static int
termp_sm_pre(DECL_ARGS)211532a712daSGarrett D'Amore termp_sm_pre(DECL_ARGS)
211632a712daSGarrett D'Amore {
211732a712daSGarrett D'Amore 
211832a712daSGarrett D'Amore 	assert(n->child && MDOC_TEXT == n->child->type);
211932a712daSGarrett D'Amore 	if (0 == strcmp("on", n->child->string)) {
212032a712daSGarrett D'Amore 		if (p->col)
212132a712daSGarrett D'Amore 			p->flags &= ~TERMP_NOSPACE;
212232a712daSGarrett D'Amore 		p->flags &= ~TERMP_NONOSPACE;
212332a712daSGarrett D'Amore 	} else
212432a712daSGarrett D'Amore 		p->flags |= TERMP_NONOSPACE;
212532a712daSGarrett D'Amore 
212632a712daSGarrett D'Amore 	return(0);
212732a712daSGarrett D'Amore }
212832a712daSGarrett D'Amore 
212932a712daSGarrett D'Amore 
213032a712daSGarrett D'Amore /* ARGSUSED */
213132a712daSGarrett D'Amore static int
termp_ap_pre(DECL_ARGS)213232a712daSGarrett D'Amore termp_ap_pre(DECL_ARGS)
213332a712daSGarrett D'Amore {
213432a712daSGarrett D'Amore 
213532a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
213632a712daSGarrett D'Amore 	term_word(p, "'");
213732a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
213832a712daSGarrett D'Amore 	return(1);
213932a712daSGarrett D'Amore }
214032a712daSGarrett D'Amore 
214132a712daSGarrett D'Amore 
214232a712daSGarrett D'Amore /* ARGSUSED */
214332a712daSGarrett D'Amore static void
termp____post(DECL_ARGS)214432a712daSGarrett D'Amore termp____post(DECL_ARGS)
214532a712daSGarrett D'Amore {
214632a712daSGarrett D'Amore 
214732a712daSGarrett D'Amore 	/*
214832a712daSGarrett D'Amore 	 * Handle lists of authors.  In general, print each followed by
214932a712daSGarrett D'Amore 	 * a comma.  Don't print the comma if there are only two
215032a712daSGarrett D'Amore 	 * authors.
215132a712daSGarrett D'Amore 	 */
215232a712daSGarrett D'Amore 	if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
215332a712daSGarrett D'Amore 		if (NULL == n->next->next || MDOC__A != n->next->next->tok)
215432a712daSGarrett D'Amore 			if (NULL == n->prev || MDOC__A != n->prev->tok)
215532a712daSGarrett D'Amore 				return;
215632a712daSGarrett D'Amore 
215732a712daSGarrett D'Amore 	/* TODO: %U. */
215832a712daSGarrett D'Amore 
215932a712daSGarrett D'Amore 	if (NULL == n->parent || MDOC_Rs != n->parent->tok)
216032a712daSGarrett D'Amore 		return;
216132a712daSGarrett D'Amore 
216232a712daSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
216332a712daSGarrett D'Amore 	if (NULL == n->next) {
216432a712daSGarrett D'Amore 		term_word(p, ".");
216532a712daSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
216632a712daSGarrett D'Amore 	} else
216732a712daSGarrett D'Amore 		term_word(p, ",");
216832a712daSGarrett D'Amore }
216932a712daSGarrett D'Amore 
217032a712daSGarrett D'Amore 
217132a712daSGarrett D'Amore /* ARGSUSED */
217232a712daSGarrett D'Amore static int
termp_li_pre(DECL_ARGS)217332a712daSGarrett D'Amore termp_li_pre(DECL_ARGS)
217432a712daSGarrett D'Amore {
217532a712daSGarrett D'Amore 
217632a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_NONE);
217732a712daSGarrett D'Amore 	return(1);
217832a712daSGarrett D'Amore }
217932a712daSGarrett D'Amore 
218032a712daSGarrett D'Amore 
218132a712daSGarrett D'Amore /* ARGSUSED */
218232a712daSGarrett D'Amore static int
termp_lk_pre(DECL_ARGS)218332a712daSGarrett D'Amore termp_lk_pre(DECL_ARGS)
218432a712daSGarrett D'Amore {
2185*ffb8ebfaSGarrett D'Amore 	const struct mdoc_node *link, *descr;
218632a712daSGarrett D'Amore 
2187*ffb8ebfaSGarrett D'Amore 	if (NULL == (link = n->child))
2188*ffb8ebfaSGarrett D'Amore 		return(0);
2189*ffb8ebfaSGarrett D'Amore 
2190*ffb8ebfaSGarrett D'Amore 	if (NULL != (descr = link->next)) {
219132a712daSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
2192*ffb8ebfaSGarrett D'Amore 		while (NULL != descr) {
2193*ffb8ebfaSGarrett D'Amore 			term_word(p, descr->string);
2194*ffb8ebfaSGarrett D'Amore 			descr = descr->next;
2195*ffb8ebfaSGarrett D'Amore 		}
219632a712daSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
219732a712daSGarrett D'Amore 		term_word(p, ":");
2198*ffb8ebfaSGarrett D'Amore 		term_fontpop(p);
2199*ffb8ebfaSGarrett D'Amore 	}
220032a712daSGarrett D'Amore 
220132a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
2202*ffb8ebfaSGarrett D'Amore 	term_word(p, link->string);
220332a712daSGarrett D'Amore 	term_fontpop(p);
220432a712daSGarrett D'Amore 
220532a712daSGarrett D'Amore 	return(0);
220632a712daSGarrett D'Amore }
220732a712daSGarrett D'Amore 
220832a712daSGarrett D'Amore 
220932a712daSGarrett D'Amore /* ARGSUSED */
221032a712daSGarrett D'Amore static int
termp_bk_pre(DECL_ARGS)221132a712daSGarrett D'Amore termp_bk_pre(DECL_ARGS)
221232a712daSGarrett D'Amore {
221332a712daSGarrett D'Amore 
221432a712daSGarrett D'Amore 	switch (n->type) {
221532a712daSGarrett D'Amore 	case (MDOC_BLOCK):
221632a712daSGarrett D'Amore 		break;
221732a712daSGarrett D'Amore 	case (MDOC_HEAD):
221832a712daSGarrett D'Amore 		return(0);
221932a712daSGarrett D'Amore 	case (MDOC_BODY):
222032a712daSGarrett D'Amore 		if (n->parent->args || 0 == n->prev->nchild)
222132a712daSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
222232a712daSGarrett D'Amore 		break;
222332a712daSGarrett D'Amore 	default:
222432a712daSGarrett D'Amore 		abort();
222532a712daSGarrett D'Amore 		/* NOTREACHED */
222632a712daSGarrett D'Amore 	}
222732a712daSGarrett D'Amore 
222832a712daSGarrett D'Amore 	return(1);
222932a712daSGarrett D'Amore }
223032a712daSGarrett D'Amore 
223132a712daSGarrett D'Amore 
223232a712daSGarrett D'Amore /* ARGSUSED */
223332a712daSGarrett D'Amore static void
termp_bk_post(DECL_ARGS)223432a712daSGarrett D'Amore termp_bk_post(DECL_ARGS)
223532a712daSGarrett D'Amore {
223632a712daSGarrett D'Amore 
223732a712daSGarrett D'Amore 	if (MDOC_BODY == n->type)
223832a712daSGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
223932a712daSGarrett D'Amore }
224032a712daSGarrett D'Amore 
224132a712daSGarrett D'Amore /* ARGSUSED */
224232a712daSGarrett D'Amore static void
termp__t_post(DECL_ARGS)224332a712daSGarrett D'Amore termp__t_post(DECL_ARGS)
224432a712daSGarrett D'Amore {
224532a712daSGarrett D'Amore 
224632a712daSGarrett D'Amore 	/*
224732a712daSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
224832a712daSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
224932a712daSGarrett D'Amore 	 */
225032a712daSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
225132a712daSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2252*ffb8ebfaSGarrett D'Amore 		termp_quote_post(p, pair, meta, n);
225332a712daSGarrett D'Amore 
2254*ffb8ebfaSGarrett D'Amore 	termp____post(p, pair, meta, n);
225532a712daSGarrett D'Amore }
225632a712daSGarrett D'Amore 
225732a712daSGarrett D'Amore /* ARGSUSED */
225832a712daSGarrett D'Amore static int
termp__t_pre(DECL_ARGS)225932a712daSGarrett D'Amore termp__t_pre(DECL_ARGS)
226032a712daSGarrett D'Amore {
226132a712daSGarrett D'Amore 
226232a712daSGarrett D'Amore 	/*
226332a712daSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
226432a712daSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
226532a712daSGarrett D'Amore 	 */
226632a712daSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
226732a712daSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2268*ffb8ebfaSGarrett D'Amore 		return(termp_quote_pre(p, pair, meta, n));
226932a712daSGarrett D'Amore 
227032a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
227132a712daSGarrett D'Amore 	return(1);
227232a712daSGarrett D'Amore }
227332a712daSGarrett D'Amore 
227432a712daSGarrett D'Amore /* ARGSUSED */
227532a712daSGarrett D'Amore static int
termp_under_pre(DECL_ARGS)227632a712daSGarrett D'Amore termp_under_pre(DECL_ARGS)
227732a712daSGarrett D'Amore {
227832a712daSGarrett D'Amore 
227932a712daSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
228032a712daSGarrett D'Amore 	return(1);
228132a712daSGarrett D'Amore }
2282