xref: /titanic_51/usr/src/cmd/mandoc/mdoc_term.c (revision 95c635efb7c3b86efc493e0447eaec7aecca3f0f)
1*95c635efSGarrett D'Amore /*	$Id: mdoc_term.c,v 1.238 2011/11/13 13:15:14 schwarze Exp $ */
2*95c635efSGarrett D'Amore /*
3*95c635efSGarrett D'Amore  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*95c635efSGarrett D'Amore  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
5*95c635efSGarrett D'Amore  *
6*95c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
7*95c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
8*95c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
9*95c635efSGarrett D'Amore  *
10*95c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*95c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*95c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*95c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*95c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*95c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*95c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*95c635efSGarrett D'Amore  */
18*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H
19*95c635efSGarrett D'Amore #include "config.h"
20*95c635efSGarrett D'Amore #endif
21*95c635efSGarrett D'Amore 
22*95c635efSGarrett D'Amore #include <sys/types.h>
23*95c635efSGarrett D'Amore 
24*95c635efSGarrett D'Amore #include <assert.h>
25*95c635efSGarrett D'Amore #include <ctype.h>
26*95c635efSGarrett D'Amore #include <stdint.h>
27*95c635efSGarrett D'Amore #include <stdio.h>
28*95c635efSGarrett D'Amore #include <stdlib.h>
29*95c635efSGarrett D'Amore #include <string.h>
30*95c635efSGarrett D'Amore 
31*95c635efSGarrett D'Amore #include "mandoc.h"
32*95c635efSGarrett D'Amore #include "out.h"
33*95c635efSGarrett D'Amore #include "term.h"
34*95c635efSGarrett D'Amore #include "mdoc.h"
35*95c635efSGarrett D'Amore #include "main.h"
36*95c635efSGarrett D'Amore 
37*95c635efSGarrett D'Amore struct	termpair {
38*95c635efSGarrett D'Amore 	struct termpair	 *ppair;
39*95c635efSGarrett D'Amore 	int		  count;
40*95c635efSGarrett D'Amore };
41*95c635efSGarrett D'Amore 
42*95c635efSGarrett D'Amore #define	DECL_ARGS struct termp *p, \
43*95c635efSGarrett D'Amore 		  struct termpair *pair, \
44*95c635efSGarrett D'Amore 	  	  const struct mdoc_meta *m, \
45*95c635efSGarrett D'Amore 		  const struct mdoc_node *n
46*95c635efSGarrett D'Amore 
47*95c635efSGarrett D'Amore struct	termact {
48*95c635efSGarrett D'Amore 	int	(*pre)(DECL_ARGS);
49*95c635efSGarrett D'Amore 	void	(*post)(DECL_ARGS);
50*95c635efSGarrett D'Amore };
51*95c635efSGarrett D'Amore 
52*95c635efSGarrett D'Amore static	size_t	  a2width(const struct termp *, const char *);
53*95c635efSGarrett D'Amore static	size_t	  a2height(const struct termp *, const char *);
54*95c635efSGarrett D'Amore static	size_t	  a2offs(const struct termp *, const char *);
55*95c635efSGarrett D'Amore 
56*95c635efSGarrett D'Amore static	void	  print_bvspace(struct termp *,
57*95c635efSGarrett D'Amore 			const struct mdoc_node *,
58*95c635efSGarrett D'Amore 			const struct mdoc_node *);
59*95c635efSGarrett D'Amore static	void  	  print_mdoc_node(DECL_ARGS);
60*95c635efSGarrett D'Amore static	void	  print_mdoc_nodelist(DECL_ARGS);
61*95c635efSGarrett D'Amore static	void	  print_mdoc_head(struct termp *, const void *);
62*95c635efSGarrett D'Amore static	void	  print_mdoc_foot(struct termp *, const void *);
63*95c635efSGarrett D'Amore static	void	  synopsis_pre(struct termp *,
64*95c635efSGarrett D'Amore 			const struct mdoc_node *);
65*95c635efSGarrett D'Amore 
66*95c635efSGarrett D'Amore static	void	  termp____post(DECL_ARGS);
67*95c635efSGarrett D'Amore static	void	  termp__t_post(DECL_ARGS);
68*95c635efSGarrett D'Amore static	void	  termp_an_post(DECL_ARGS);
69*95c635efSGarrett D'Amore static	void	  termp_bd_post(DECL_ARGS);
70*95c635efSGarrett D'Amore static	void	  termp_bk_post(DECL_ARGS);
71*95c635efSGarrett D'Amore static	void	  termp_bl_post(DECL_ARGS);
72*95c635efSGarrett D'Amore static	void	  termp_d1_post(DECL_ARGS);
73*95c635efSGarrett D'Amore static	void	  termp_fo_post(DECL_ARGS);
74*95c635efSGarrett D'Amore static	void	  termp_in_post(DECL_ARGS);
75*95c635efSGarrett D'Amore static	void	  termp_it_post(DECL_ARGS);
76*95c635efSGarrett D'Amore static	void	  termp_lb_post(DECL_ARGS);
77*95c635efSGarrett D'Amore static	void	  termp_nm_post(DECL_ARGS);
78*95c635efSGarrett D'Amore static	void	  termp_pf_post(DECL_ARGS);
79*95c635efSGarrett D'Amore static	void	  termp_quote_post(DECL_ARGS);
80*95c635efSGarrett D'Amore static	void	  termp_sh_post(DECL_ARGS);
81*95c635efSGarrett D'Amore static	void	  termp_ss_post(DECL_ARGS);
82*95c635efSGarrett D'Amore 
83*95c635efSGarrett D'Amore static	int	  termp__a_pre(DECL_ARGS);
84*95c635efSGarrett D'Amore static	int	  termp__t_pre(DECL_ARGS);
85*95c635efSGarrett D'Amore static	int	  termp_an_pre(DECL_ARGS);
86*95c635efSGarrett D'Amore static	int	  termp_ap_pre(DECL_ARGS);
87*95c635efSGarrett D'Amore static	int	  termp_bd_pre(DECL_ARGS);
88*95c635efSGarrett D'Amore static	int	  termp_bf_pre(DECL_ARGS);
89*95c635efSGarrett D'Amore static	int	  termp_bk_pre(DECL_ARGS);
90*95c635efSGarrett D'Amore static	int	  termp_bl_pre(DECL_ARGS);
91*95c635efSGarrett D'Amore static	int	  termp_bold_pre(DECL_ARGS);
92*95c635efSGarrett D'Amore static	int	  termp_bt_pre(DECL_ARGS);
93*95c635efSGarrett D'Amore static	int	  termp_bx_pre(DECL_ARGS);
94*95c635efSGarrett D'Amore static	int	  termp_cd_pre(DECL_ARGS);
95*95c635efSGarrett D'Amore static	int	  termp_d1_pre(DECL_ARGS);
96*95c635efSGarrett D'Amore static	int	  termp_ex_pre(DECL_ARGS);
97*95c635efSGarrett D'Amore static	int	  termp_fa_pre(DECL_ARGS);
98*95c635efSGarrett D'Amore static	int	  termp_fd_pre(DECL_ARGS);
99*95c635efSGarrett D'Amore static	int	  termp_fl_pre(DECL_ARGS);
100*95c635efSGarrett D'Amore static	int	  termp_fn_pre(DECL_ARGS);
101*95c635efSGarrett D'Amore static	int	  termp_fo_pre(DECL_ARGS);
102*95c635efSGarrett D'Amore static	int	  termp_ft_pre(DECL_ARGS);
103*95c635efSGarrett D'Amore static	int	  termp_igndelim_pre(DECL_ARGS);
104*95c635efSGarrett D'Amore static	int	  termp_in_pre(DECL_ARGS);
105*95c635efSGarrett D'Amore static	int	  termp_it_pre(DECL_ARGS);
106*95c635efSGarrett D'Amore static	int	  termp_li_pre(DECL_ARGS);
107*95c635efSGarrett D'Amore static	int	  termp_lk_pre(DECL_ARGS);
108*95c635efSGarrett D'Amore static	int	  termp_nd_pre(DECL_ARGS);
109*95c635efSGarrett D'Amore static	int	  termp_nm_pre(DECL_ARGS);
110*95c635efSGarrett D'Amore static	int	  termp_ns_pre(DECL_ARGS);
111*95c635efSGarrett D'Amore static	int	  termp_quote_pre(DECL_ARGS);
112*95c635efSGarrett D'Amore static	int	  termp_rs_pre(DECL_ARGS);
113*95c635efSGarrett D'Amore static	int	  termp_rv_pre(DECL_ARGS);
114*95c635efSGarrett D'Amore static	int	  termp_sh_pre(DECL_ARGS);
115*95c635efSGarrett D'Amore static	int	  termp_sm_pre(DECL_ARGS);
116*95c635efSGarrett D'Amore static	int	  termp_sp_pre(DECL_ARGS);
117*95c635efSGarrett D'Amore static	int	  termp_ss_pre(DECL_ARGS);
118*95c635efSGarrett D'Amore static	int	  termp_under_pre(DECL_ARGS);
119*95c635efSGarrett D'Amore static	int	  termp_ud_pre(DECL_ARGS);
120*95c635efSGarrett D'Amore static	int	  termp_vt_pre(DECL_ARGS);
121*95c635efSGarrett D'Amore static	int	  termp_xr_pre(DECL_ARGS);
122*95c635efSGarrett D'Amore static	int	  termp_xx_pre(DECL_ARGS);
123*95c635efSGarrett D'Amore 
124*95c635efSGarrett D'Amore static	const struct termact termacts[MDOC_MAX] = {
125*95c635efSGarrett D'Amore 	{ termp_ap_pre, NULL }, /* Ap */
126*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dd */
127*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dt */
128*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Os */
129*95c635efSGarrett D'Amore 	{ termp_sh_pre, termp_sh_post }, /* Sh */
130*95c635efSGarrett D'Amore 	{ termp_ss_pre, termp_ss_post }, /* Ss */
131*95c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Pp */
132*95c635efSGarrett D'Amore 	{ termp_d1_pre, termp_d1_post }, /* D1 */
133*95c635efSGarrett D'Amore 	{ termp_d1_pre, termp_d1_post }, /* Dl */
134*95c635efSGarrett D'Amore 	{ termp_bd_pre, termp_bd_post }, /* Bd */
135*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ed */
136*95c635efSGarrett D'Amore 	{ termp_bl_pre, termp_bl_post }, /* Bl */
137*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* El */
138*95c635efSGarrett D'Amore 	{ termp_it_pre, termp_it_post }, /* It */
139*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ad */
140*95c635efSGarrett D'Amore 	{ termp_an_pre, termp_an_post }, /* An */
141*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Ar */
142*95c635efSGarrett D'Amore 	{ termp_cd_pre, NULL }, /* Cd */
143*95c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Cm */
144*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dv */
145*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Er */
146*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ev */
147*95c635efSGarrett D'Amore 	{ termp_ex_pre, NULL }, /* Ex */
148*95c635efSGarrett D'Amore 	{ termp_fa_pre, NULL }, /* Fa */
149*95c635efSGarrett D'Amore 	{ termp_fd_pre, NULL }, /* Fd */
150*95c635efSGarrett D'Amore 	{ termp_fl_pre, NULL }, /* Fl */
151*95c635efSGarrett D'Amore 	{ termp_fn_pre, NULL }, /* Fn */
152*95c635efSGarrett D'Amore 	{ termp_ft_pre, NULL }, /* Ft */
153*95c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ic */
154*95c635efSGarrett D'Amore 	{ termp_in_pre, termp_in_post }, /* In */
155*95c635efSGarrett D'Amore 	{ termp_li_pre, NULL }, /* Li */
156*95c635efSGarrett D'Amore 	{ termp_nd_pre, NULL }, /* Nd */
157*95c635efSGarrett D'Amore 	{ termp_nm_pre, termp_nm_post }, /* Nm */
158*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Op */
159*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ot */
160*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Pa */
161*95c635efSGarrett D'Amore 	{ termp_rv_pre, NULL }, /* Rv */
162*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* St */
163*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Va */
164*95c635efSGarrett D'Amore 	{ termp_vt_pre, NULL }, /* Vt */
165*95c635efSGarrett D'Amore 	{ termp_xr_pre, NULL }, /* Xr */
166*95c635efSGarrett D'Amore 	{ termp__a_pre, termp____post }, /* %A */
167*95c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %B */
168*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %D */
169*95c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %I */
170*95c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %J */
171*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %N */
172*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %O */
173*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %P */
174*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %R */
175*95c635efSGarrett D'Amore 	{ termp__t_pre, termp__t_post }, /* %T */
176*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %V */
177*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ac */
178*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ao */
179*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Aq */
180*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* At */
181*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Bc */
182*95c635efSGarrett D'Amore 	{ termp_bf_pre, NULL }, /* Bf */
183*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bo */
184*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bq */
185*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Bsx */
186*95c635efSGarrett D'Amore 	{ termp_bx_pre, NULL }, /* Bx */
187*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Db */
188*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Dc */
189*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Do */
190*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Dq */
191*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ec */ /* FIXME: no space */
192*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ef */
193*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Em */
194*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Eo */
195*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Fx */
196*95c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Ms */
197*95c635efSGarrett D'Amore 	{ termp_igndelim_pre, NULL }, /* No */
198*95c635efSGarrett D'Amore 	{ termp_ns_pre, NULL }, /* Ns */
199*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Nx */
200*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ox */
201*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Pc */
202*95c635efSGarrett D'Amore 	{ termp_igndelim_pre, termp_pf_post }, /* Pf */
203*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Po */
204*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Pq */
205*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Qc */
206*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Ql */
207*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qo */
208*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Qq */
209*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Re */
210*95c635efSGarrett D'Amore 	{ termp_rs_pre, NULL }, /* Rs */
211*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Sc */
212*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* So */
213*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Sq */
214*95c635efSGarrett D'Amore 	{ termp_sm_pre, NULL }, /* Sm */
215*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Sx */
216*95c635efSGarrett D'Amore 	{ termp_bold_pre, NULL }, /* Sy */
217*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Tn */
218*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Ux */
219*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Xc */
220*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Xo */
221*95c635efSGarrett D'Amore 	{ termp_fo_pre, termp_fo_post }, /* Fo */
222*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Fc */
223*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Oo */
224*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Oc */
225*95c635efSGarrett D'Amore 	{ termp_bk_pre, termp_bk_post }, /* Bk */
226*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ek */
227*95c635efSGarrett D'Amore 	{ termp_bt_pre, NULL }, /* Bt */
228*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Hf */
229*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Fr */
230*95c635efSGarrett D'Amore 	{ termp_ud_pre, NULL }, /* Ud */
231*95c635efSGarrett D'Amore 	{ NULL, termp_lb_post }, /* Lb */
232*95c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* Lp */
233*95c635efSGarrett D'Amore 	{ termp_lk_pre, NULL }, /* Lk */
234*95c635efSGarrett D'Amore 	{ termp_under_pre, NULL }, /* Mt */
235*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Brq */
236*95c635efSGarrett D'Amore 	{ termp_quote_pre, termp_quote_post }, /* Bro */
237*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Brc */
238*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %C */
239*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Es */ /* TODO */
240*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* En */ /* TODO */
241*95c635efSGarrett D'Amore 	{ termp_xx_pre, NULL }, /* Dx */
242*95c635efSGarrett D'Amore 	{ NULL, termp____post }, /* %Q */
243*95c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* br */
244*95c635efSGarrett D'Amore 	{ termp_sp_pre, NULL }, /* sp */
245*95c635efSGarrett D'Amore 	{ termp_under_pre, termp____post }, /* %U */
246*95c635efSGarrett D'Amore 	{ NULL, NULL }, /* Ta */
247*95c635efSGarrett D'Amore };
248*95c635efSGarrett D'Amore 
249*95c635efSGarrett D'Amore 
250*95c635efSGarrett D'Amore void
251*95c635efSGarrett D'Amore terminal_mdoc(void *arg, const struct mdoc *mdoc)
252*95c635efSGarrett D'Amore {
253*95c635efSGarrett D'Amore 	const struct mdoc_node	*n;
254*95c635efSGarrett D'Amore 	const struct mdoc_meta	*m;
255*95c635efSGarrett D'Amore 	struct termp		*p;
256*95c635efSGarrett D'Amore 
257*95c635efSGarrett D'Amore 	p = (struct termp *)arg;
258*95c635efSGarrett D'Amore 
259*95c635efSGarrett D'Amore 	if (0 == p->defindent)
260*95c635efSGarrett D'Amore 		p->defindent = 5;
261*95c635efSGarrett D'Amore 
262*95c635efSGarrett D'Amore 	p->overstep = 0;
263*95c635efSGarrett D'Amore 	p->maxrmargin = p->defrmargin;
264*95c635efSGarrett D'Amore 	p->tabwidth = term_len(p, 5);
265*95c635efSGarrett D'Amore 
266*95c635efSGarrett D'Amore 	if (NULL == p->symtab)
267*95c635efSGarrett D'Amore 		p->symtab = mchars_alloc();
268*95c635efSGarrett D'Amore 
269*95c635efSGarrett D'Amore 	n = mdoc_node(mdoc);
270*95c635efSGarrett D'Amore 	m = mdoc_meta(mdoc);
271*95c635efSGarrett D'Amore 
272*95c635efSGarrett D'Amore 	term_begin(p, print_mdoc_head, print_mdoc_foot, m);
273*95c635efSGarrett D'Amore 
274*95c635efSGarrett D'Amore 	if (n->child)
275*95c635efSGarrett D'Amore 		print_mdoc_nodelist(p, NULL, m, n->child);
276*95c635efSGarrett D'Amore 
277*95c635efSGarrett D'Amore 	term_end(p);
278*95c635efSGarrett D'Amore }
279*95c635efSGarrett D'Amore 
280*95c635efSGarrett D'Amore 
281*95c635efSGarrett D'Amore static void
282*95c635efSGarrett D'Amore print_mdoc_nodelist(DECL_ARGS)
283*95c635efSGarrett D'Amore {
284*95c635efSGarrett D'Amore 
285*95c635efSGarrett D'Amore 	print_mdoc_node(p, pair, m, n);
286*95c635efSGarrett D'Amore 	if (n->next)
287*95c635efSGarrett D'Amore 		print_mdoc_nodelist(p, pair, m, n->next);
288*95c635efSGarrett D'Amore }
289*95c635efSGarrett D'Amore 
290*95c635efSGarrett D'Amore 
291*95c635efSGarrett D'Amore /* ARGSUSED */
292*95c635efSGarrett D'Amore static void
293*95c635efSGarrett D'Amore print_mdoc_node(DECL_ARGS)
294*95c635efSGarrett D'Amore {
295*95c635efSGarrett D'Amore 	int		 chld;
296*95c635efSGarrett D'Amore 	const void	*font;
297*95c635efSGarrett D'Amore 	struct termpair	 npair;
298*95c635efSGarrett D'Amore 	size_t		 offset, rmargin;
299*95c635efSGarrett D'Amore 
300*95c635efSGarrett D'Amore 	chld = 1;
301*95c635efSGarrett D'Amore 	offset = p->offset;
302*95c635efSGarrett D'Amore 	rmargin = p->rmargin;
303*95c635efSGarrett D'Amore 	font = term_fontq(p);
304*95c635efSGarrett D'Amore 
305*95c635efSGarrett D'Amore 	memset(&npair, 0, sizeof(struct termpair));
306*95c635efSGarrett D'Amore 	npair.ppair = pair;
307*95c635efSGarrett D'Amore 
308*95c635efSGarrett D'Amore 	/*
309*95c635efSGarrett D'Amore 	 * Keeps only work until the end of a line.  If a keep was
310*95c635efSGarrett D'Amore 	 * invoked in a prior line, revert it to PREKEEP.
311*95c635efSGarrett D'Amore 	 *
312*95c635efSGarrett D'Amore 	 * Also let SYNPRETTY sections behave as if they were wrapped
313*95c635efSGarrett D'Amore 	 * in a `Bk' block.
314*95c635efSGarrett D'Amore 	 */
315*95c635efSGarrett D'Amore 
316*95c635efSGarrett D'Amore 	if (TERMP_KEEP & p->flags || MDOC_SYNPRETTY & n->flags) {
317*95c635efSGarrett D'Amore 		if (n->prev && n->prev->line != n->line) {
318*95c635efSGarrett D'Amore 			p->flags &= ~TERMP_KEEP;
319*95c635efSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
320*95c635efSGarrett D'Amore 		} else if (NULL == n->prev) {
321*95c635efSGarrett D'Amore 			if (n->parent && n->parent->line != n->line) {
322*95c635efSGarrett D'Amore 				p->flags &= ~TERMP_KEEP;
323*95c635efSGarrett D'Amore 				p->flags |= TERMP_PREKEEP;
324*95c635efSGarrett D'Amore 			}
325*95c635efSGarrett D'Amore 		}
326*95c635efSGarrett D'Amore 	}
327*95c635efSGarrett D'Amore 
328*95c635efSGarrett D'Amore 	/*
329*95c635efSGarrett D'Amore 	 * Since SYNPRETTY sections aren't "turned off" with `Ek',
330*95c635efSGarrett D'Amore 	 * we have to intuit whether we should disable formatting.
331*95c635efSGarrett D'Amore 	 */
332*95c635efSGarrett D'Amore 
333*95c635efSGarrett D'Amore 	if ( ! (MDOC_SYNPRETTY & n->flags) &&
334*95c635efSGarrett D'Amore 	    ((n->prev   && MDOC_SYNPRETTY & n->prev->flags) ||
335*95c635efSGarrett D'Amore 	     (n->parent && MDOC_SYNPRETTY & n->parent->flags)))
336*95c635efSGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
337*95c635efSGarrett D'Amore 
338*95c635efSGarrett D'Amore 	/*
339*95c635efSGarrett D'Amore 	 * After the keep flags have been set up, we may now
340*95c635efSGarrett D'Amore 	 * produce output.  Note that some pre-handlers do so.
341*95c635efSGarrett D'Amore 	 */
342*95c635efSGarrett D'Amore 
343*95c635efSGarrett D'Amore 	switch (n->type) {
344*95c635efSGarrett D'Amore 	case (MDOC_TEXT):
345*95c635efSGarrett D'Amore 		if (' ' == *n->string && MDOC_LINE & n->flags)
346*95c635efSGarrett D'Amore 			term_newln(p);
347*95c635efSGarrett D'Amore 		if (MDOC_DELIMC & n->flags)
348*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
349*95c635efSGarrett D'Amore 		term_word(p, n->string);
350*95c635efSGarrett D'Amore 		if (MDOC_DELIMO & n->flags)
351*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
352*95c635efSGarrett D'Amore 		break;
353*95c635efSGarrett D'Amore 	case (MDOC_EQN):
354*95c635efSGarrett D'Amore 		term_eqn(p, n->eqn);
355*95c635efSGarrett D'Amore 		break;
356*95c635efSGarrett D'Amore 	case (MDOC_TBL):
357*95c635efSGarrett D'Amore 		term_tbl(p, n->span);
358*95c635efSGarrett D'Amore 		break;
359*95c635efSGarrett D'Amore 	default:
360*95c635efSGarrett D'Amore 		if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
361*95c635efSGarrett D'Amore 			chld = (*termacts[n->tok].pre)
362*95c635efSGarrett D'Amore 				(p, &npair, m, n);
363*95c635efSGarrett D'Amore 		break;
364*95c635efSGarrett D'Amore 	}
365*95c635efSGarrett D'Amore 
366*95c635efSGarrett D'Amore 	if (chld && n->child)
367*95c635efSGarrett D'Amore 		print_mdoc_nodelist(p, &npair, m, n->child);
368*95c635efSGarrett D'Amore 
369*95c635efSGarrett D'Amore 	term_fontpopq(p, font);
370*95c635efSGarrett D'Amore 
371*95c635efSGarrett D'Amore 	switch (n->type) {
372*95c635efSGarrett D'Amore 	case (MDOC_TEXT):
373*95c635efSGarrett D'Amore 		break;
374*95c635efSGarrett D'Amore 	case (MDOC_TBL):
375*95c635efSGarrett D'Amore 		break;
376*95c635efSGarrett D'Amore 	case (MDOC_EQN):
377*95c635efSGarrett D'Amore 		break;
378*95c635efSGarrett D'Amore 	default:
379*95c635efSGarrett D'Amore 		if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
380*95c635efSGarrett D'Amore 			break;
381*95c635efSGarrett D'Amore 		(void)(*termacts[n->tok].post)(p, &npair, m, n);
382*95c635efSGarrett D'Amore 
383*95c635efSGarrett D'Amore 		/*
384*95c635efSGarrett D'Amore 		 * Explicit end tokens not only call the post
385*95c635efSGarrett D'Amore 		 * handler, but also tell the respective block
386*95c635efSGarrett D'Amore 		 * that it must not call the post handler again.
387*95c635efSGarrett D'Amore 		 */
388*95c635efSGarrett D'Amore 		if (ENDBODY_NOT != n->end)
389*95c635efSGarrett D'Amore 			n->pending->flags |= MDOC_ENDED;
390*95c635efSGarrett D'Amore 
391*95c635efSGarrett D'Amore 		/*
392*95c635efSGarrett D'Amore 		 * End of line terminating an implicit block
393*95c635efSGarrett D'Amore 		 * while an explicit block is still open.
394*95c635efSGarrett D'Amore 		 * Continue the explicit block without spacing.
395*95c635efSGarrett D'Amore 		 */
396*95c635efSGarrett D'Amore 		if (ENDBODY_NOSPACE == n->end)
397*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
398*95c635efSGarrett D'Amore 		break;
399*95c635efSGarrett D'Amore 	}
400*95c635efSGarrett D'Amore 
401*95c635efSGarrett D'Amore 	if (MDOC_EOS & n->flags)
402*95c635efSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
403*95c635efSGarrett D'Amore 
404*95c635efSGarrett D'Amore 	p->offset = offset;
405*95c635efSGarrett D'Amore 	p->rmargin = rmargin;
406*95c635efSGarrett D'Amore }
407*95c635efSGarrett D'Amore 
408*95c635efSGarrett D'Amore 
409*95c635efSGarrett D'Amore static void
410*95c635efSGarrett D'Amore print_mdoc_foot(struct termp *p, const void *arg)
411*95c635efSGarrett D'Amore {
412*95c635efSGarrett D'Amore 	const struct mdoc_meta *m;
413*95c635efSGarrett D'Amore 
414*95c635efSGarrett D'Amore 	m = (const struct mdoc_meta *)arg;
415*95c635efSGarrett D'Amore 
416*95c635efSGarrett D'Amore 	term_fontrepl(p, TERMFONT_NONE);
417*95c635efSGarrett D'Amore 
418*95c635efSGarrett D'Amore 	/*
419*95c635efSGarrett D'Amore 	 * Output the footer in new-groff style, that is, three columns
420*95c635efSGarrett D'Amore 	 * with the middle being the manual date and flanking columns
421*95c635efSGarrett D'Amore 	 * being the operating system:
422*95c635efSGarrett D'Amore 	 *
423*95c635efSGarrett D'Amore 	 * SYSTEM                  DATE                    SYSTEM
424*95c635efSGarrett D'Amore 	 */
425*95c635efSGarrett D'Amore 
426*95c635efSGarrett D'Amore 	term_vspace(p);
427*95c635efSGarrett D'Amore 
428*95c635efSGarrett D'Amore 	p->offset = 0;
429*95c635efSGarrett D'Amore 	p->rmargin = (p->maxrmargin -
430*95c635efSGarrett D'Amore 			term_strlen(p, m->date) + term_len(p, 1)) / 2;
431*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
432*95c635efSGarrett D'Amore 
433*95c635efSGarrett D'Amore 	term_word(p, m->os);
434*95c635efSGarrett D'Amore 	term_flushln(p);
435*95c635efSGarrett D'Amore 
436*95c635efSGarrett D'Amore 	p->offset = p->rmargin;
437*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin - term_strlen(p, m->os);
438*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
439*95c635efSGarrett D'Amore 
440*95c635efSGarrett D'Amore 	term_word(p, m->date);
441*95c635efSGarrett D'Amore 	term_flushln(p);
442*95c635efSGarrett D'Amore 
443*95c635efSGarrett D'Amore 	p->offset = p->rmargin;
444*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
445*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
446*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
447*95c635efSGarrett D'Amore 
448*95c635efSGarrett D'Amore 	term_word(p, m->os);
449*95c635efSGarrett D'Amore 	term_flushln(p);
450*95c635efSGarrett D'Amore 
451*95c635efSGarrett D'Amore 	p->offset = 0;
452*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
453*95c635efSGarrett D'Amore 	p->flags = 0;
454*95c635efSGarrett D'Amore }
455*95c635efSGarrett D'Amore 
456*95c635efSGarrett D'Amore 
457*95c635efSGarrett D'Amore static void
458*95c635efSGarrett D'Amore print_mdoc_head(struct termp *p, const void *arg)
459*95c635efSGarrett D'Amore {
460*95c635efSGarrett D'Amore 	char		buf[BUFSIZ], title[BUFSIZ];
461*95c635efSGarrett D'Amore 	size_t		buflen, titlen;
462*95c635efSGarrett D'Amore 	const struct mdoc_meta *m;
463*95c635efSGarrett D'Amore 
464*95c635efSGarrett D'Amore 	m = (const struct mdoc_meta *)arg;
465*95c635efSGarrett D'Amore 
466*95c635efSGarrett D'Amore 	/*
467*95c635efSGarrett D'Amore 	 * The header is strange.  It has three components, which are
468*95c635efSGarrett D'Amore 	 * really two with the first duplicated.  It goes like this:
469*95c635efSGarrett D'Amore 	 *
470*95c635efSGarrett D'Amore 	 * IDENTIFIER              TITLE                   IDENTIFIER
471*95c635efSGarrett D'Amore 	 *
472*95c635efSGarrett D'Amore 	 * The IDENTIFIER is NAME(SECTION), which is the command-name
473*95c635efSGarrett D'Amore 	 * (if given, or "unknown" if not) followed by the manual page
474*95c635efSGarrett D'Amore 	 * section.  These are given in `Dt'.  The TITLE is a free-form
475*95c635efSGarrett D'Amore 	 * string depending on the manual volume.  If not specified, it
476*95c635efSGarrett D'Amore 	 * switches on the manual section.
477*95c635efSGarrett D'Amore 	 */
478*95c635efSGarrett D'Amore 
479*95c635efSGarrett D'Amore 	p->offset = 0;
480*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
481*95c635efSGarrett D'Amore 
482*95c635efSGarrett D'Amore 	assert(m->vol);
483*95c635efSGarrett D'Amore 	strlcpy(buf, m->vol, BUFSIZ);
484*95c635efSGarrett D'Amore 	buflen = term_strlen(p, buf);
485*95c635efSGarrett D'Amore 
486*95c635efSGarrett D'Amore 	if (m->arch) {
487*95c635efSGarrett D'Amore 		strlcat(buf, " (", BUFSIZ);
488*95c635efSGarrett D'Amore 		strlcat(buf, m->arch, BUFSIZ);
489*95c635efSGarrett D'Amore 		strlcat(buf, ")", BUFSIZ);
490*95c635efSGarrett D'Amore 	}
491*95c635efSGarrett D'Amore 
492*95c635efSGarrett D'Amore 	snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
493*95c635efSGarrett D'Amore 	titlen = term_strlen(p, title);
494*95c635efSGarrett D'Amore 
495*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
496*95c635efSGarrett D'Amore 	p->offset = 0;
497*95c635efSGarrett D'Amore 	p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
498*95c635efSGarrett D'Amore 	    (p->maxrmargin -
499*95c635efSGarrett D'Amore 	     term_strlen(p, buf) + term_len(p, 1)) / 2 :
500*95c635efSGarrett D'Amore 	    p->maxrmargin - buflen;
501*95c635efSGarrett D'Amore 
502*95c635efSGarrett D'Amore 	term_word(p, title);
503*95c635efSGarrett D'Amore 	term_flushln(p);
504*95c635efSGarrett D'Amore 
505*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
506*95c635efSGarrett D'Amore 	p->offset = p->rmargin;
507*95c635efSGarrett D'Amore 	p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
508*95c635efSGarrett D'Amore 	    p->maxrmargin - titlen : p->maxrmargin;
509*95c635efSGarrett D'Amore 
510*95c635efSGarrett D'Amore 	term_word(p, buf);
511*95c635efSGarrett D'Amore 	term_flushln(p);
512*95c635efSGarrett D'Amore 
513*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
514*95c635efSGarrett D'Amore 	if (p->rmargin + titlen <= p->maxrmargin) {
515*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
516*95c635efSGarrett D'Amore 		p->offset = p->rmargin;
517*95c635efSGarrett D'Amore 		p->rmargin = p->maxrmargin;
518*95c635efSGarrett D'Amore 		term_word(p, title);
519*95c635efSGarrett D'Amore 		term_flushln(p);
520*95c635efSGarrett D'Amore 	}
521*95c635efSGarrett D'Amore 
522*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOSPACE;
523*95c635efSGarrett D'Amore 	p->offset = 0;
524*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin;
525*95c635efSGarrett D'Amore }
526*95c635efSGarrett D'Amore 
527*95c635efSGarrett D'Amore 
528*95c635efSGarrett D'Amore static size_t
529*95c635efSGarrett D'Amore a2height(const struct termp *p, const char *v)
530*95c635efSGarrett D'Amore {
531*95c635efSGarrett D'Amore 	struct roffsu	 su;
532*95c635efSGarrett D'Amore 
533*95c635efSGarrett D'Amore 
534*95c635efSGarrett D'Amore 	assert(v);
535*95c635efSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_VS))
536*95c635efSGarrett D'Amore 		SCALE_VS_INIT(&su, atoi(v));
537*95c635efSGarrett D'Amore 
538*95c635efSGarrett D'Amore 	return(term_vspan(p, &su));
539*95c635efSGarrett D'Amore }
540*95c635efSGarrett D'Amore 
541*95c635efSGarrett D'Amore 
542*95c635efSGarrett D'Amore static size_t
543*95c635efSGarrett D'Amore a2width(const struct termp *p, const char *v)
544*95c635efSGarrett D'Amore {
545*95c635efSGarrett D'Amore 	struct roffsu	 su;
546*95c635efSGarrett D'Amore 
547*95c635efSGarrett D'Amore 	assert(v);
548*95c635efSGarrett D'Amore 	if ( ! a2roffsu(v, &su, SCALE_MAX))
549*95c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
550*95c635efSGarrett D'Amore 
551*95c635efSGarrett D'Amore 	return(term_hspan(p, &su));
552*95c635efSGarrett D'Amore }
553*95c635efSGarrett D'Amore 
554*95c635efSGarrett D'Amore 
555*95c635efSGarrett D'Amore static size_t
556*95c635efSGarrett D'Amore a2offs(const struct termp *p, const char *v)
557*95c635efSGarrett D'Amore {
558*95c635efSGarrett D'Amore 	struct roffsu	 su;
559*95c635efSGarrett D'Amore 
560*95c635efSGarrett D'Amore 	if ('\0' == *v)
561*95c635efSGarrett D'Amore 		return(0);
562*95c635efSGarrett D'Amore 	else if (0 == strcmp(v, "left"))
563*95c635efSGarrett D'Amore 		return(0);
564*95c635efSGarrett D'Amore 	else if (0 == strcmp(v, "indent"))
565*95c635efSGarrett D'Amore 		return(term_len(p, p->defindent + 1));
566*95c635efSGarrett D'Amore 	else if (0 == strcmp(v, "indent-two"))
567*95c635efSGarrett D'Amore 		return(term_len(p, (p->defindent + 1) * 2));
568*95c635efSGarrett D'Amore 	else if ( ! a2roffsu(v, &su, SCALE_MAX))
569*95c635efSGarrett D'Amore 		SCALE_HS_INIT(&su, term_strlen(p, v));
570*95c635efSGarrett D'Amore 
571*95c635efSGarrett D'Amore 	return(term_hspan(p, &su));
572*95c635efSGarrett D'Amore }
573*95c635efSGarrett D'Amore 
574*95c635efSGarrett D'Amore 
575*95c635efSGarrett D'Amore /*
576*95c635efSGarrett D'Amore  * Determine how much space to print out before block elements of `It'
577*95c635efSGarrett D'Amore  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
578*95c635efSGarrett D'Amore  * too.
579*95c635efSGarrett D'Amore  */
580*95c635efSGarrett D'Amore static void
581*95c635efSGarrett D'Amore print_bvspace(struct termp *p,
582*95c635efSGarrett D'Amore 		const struct mdoc_node *bl,
583*95c635efSGarrett D'Amore 		const struct mdoc_node *n)
584*95c635efSGarrett D'Amore {
585*95c635efSGarrett D'Amore 	const struct mdoc_node	*nn;
586*95c635efSGarrett D'Amore 
587*95c635efSGarrett D'Amore 	assert(n);
588*95c635efSGarrett D'Amore 
589*95c635efSGarrett D'Amore 	term_newln(p);
590*95c635efSGarrett D'Amore 
591*95c635efSGarrett D'Amore 	if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
592*95c635efSGarrett D'Amore 		return;
593*95c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
594*95c635efSGarrett D'Amore 		return;
595*95c635efSGarrett D'Amore 
596*95c635efSGarrett D'Amore 	/* Do not vspace directly after Ss/Sh. */
597*95c635efSGarrett D'Amore 
598*95c635efSGarrett D'Amore 	for (nn = n; nn; nn = nn->parent) {
599*95c635efSGarrett D'Amore 		if (MDOC_BLOCK != nn->type)
600*95c635efSGarrett D'Amore 			continue;
601*95c635efSGarrett D'Amore 		if (MDOC_Ss == nn->tok)
602*95c635efSGarrett D'Amore 			return;
603*95c635efSGarrett D'Amore 		if (MDOC_Sh == nn->tok)
604*95c635efSGarrett D'Amore 			return;
605*95c635efSGarrett D'Amore 		if (NULL == nn->prev)
606*95c635efSGarrett D'Amore 			continue;
607*95c635efSGarrett D'Amore 		break;
608*95c635efSGarrett D'Amore 	}
609*95c635efSGarrett D'Amore 
610*95c635efSGarrett D'Amore 	/* A `-column' does not assert vspace within the list. */
611*95c635efSGarrett D'Amore 
612*95c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
613*95c635efSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok)
614*95c635efSGarrett D'Amore 			return;
615*95c635efSGarrett D'Amore 
616*95c635efSGarrett D'Amore 	/* A `-diag' without body does not vspace. */
617*95c635efSGarrett D'Amore 
618*95c635efSGarrett D'Amore 	if (MDOC_Bl == bl->tok && LIST_diag == bl->norm->Bl.type)
619*95c635efSGarrett D'Amore 		if (n->prev && MDOC_It == n->prev->tok) {
620*95c635efSGarrett D'Amore 			assert(n->prev->body);
621*95c635efSGarrett D'Amore 			if (NULL == n->prev->body->child)
622*95c635efSGarrett D'Amore 				return;
623*95c635efSGarrett D'Amore 		}
624*95c635efSGarrett D'Amore 
625*95c635efSGarrett D'Amore 	term_vspace(p);
626*95c635efSGarrett D'Amore }
627*95c635efSGarrett D'Amore 
628*95c635efSGarrett D'Amore 
629*95c635efSGarrett D'Amore /* ARGSUSED */
630*95c635efSGarrett D'Amore static int
631*95c635efSGarrett D'Amore termp_it_pre(DECL_ARGS)
632*95c635efSGarrett D'Amore {
633*95c635efSGarrett D'Amore 	const struct mdoc_node *bl, *nn;
634*95c635efSGarrett D'Amore 	char		        buf[7];
635*95c635efSGarrett D'Amore 	int		        i;
636*95c635efSGarrett D'Amore 	size_t		        width, offset, ncols, dcol;
637*95c635efSGarrett D'Amore 	enum mdoc_list		type;
638*95c635efSGarrett D'Amore 
639*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
640*95c635efSGarrett D'Amore 		print_bvspace(p, n->parent->parent, n);
641*95c635efSGarrett D'Amore 		return(1);
642*95c635efSGarrett D'Amore 	}
643*95c635efSGarrett D'Amore 
644*95c635efSGarrett D'Amore 	bl = n->parent->parent->parent;
645*95c635efSGarrett D'Amore 	type = bl->norm->Bl.type;
646*95c635efSGarrett D'Amore 
647*95c635efSGarrett D'Amore 	/*
648*95c635efSGarrett D'Amore 	 * First calculate width and offset.  This is pretty easy unless
649*95c635efSGarrett D'Amore 	 * we're a -column list, in which case all prior columns must
650*95c635efSGarrett D'Amore 	 * be accounted for.
651*95c635efSGarrett D'Amore 	 */
652*95c635efSGarrett D'Amore 
653*95c635efSGarrett D'Amore 	width = offset = 0;
654*95c635efSGarrett D'Amore 
655*95c635efSGarrett D'Amore 	if (bl->norm->Bl.offs)
656*95c635efSGarrett D'Amore 		offset = a2offs(p, bl->norm->Bl.offs);
657*95c635efSGarrett D'Amore 
658*95c635efSGarrett D'Amore 	switch (type) {
659*95c635efSGarrett D'Amore 	case (LIST_column):
660*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
661*95c635efSGarrett D'Amore 			break;
662*95c635efSGarrett D'Amore 
663*95c635efSGarrett D'Amore 		/*
664*95c635efSGarrett D'Amore 		 * Imitate groff's column handling:
665*95c635efSGarrett D'Amore 		 * - For each earlier column, add its width.
666*95c635efSGarrett D'Amore 		 * - For less than 5 columns, add four more blanks per
667*95c635efSGarrett D'Amore 		 *   column.
668*95c635efSGarrett D'Amore 		 * - For exactly 5 columns, add three more blank per
669*95c635efSGarrett D'Amore 		 *   column.
670*95c635efSGarrett D'Amore 		 * - For more than 5 columns, add only one column.
671*95c635efSGarrett D'Amore 		 */
672*95c635efSGarrett D'Amore 		ncols = bl->norm->Bl.ncols;
673*95c635efSGarrett D'Amore 
674*95c635efSGarrett D'Amore 		/* LINTED */
675*95c635efSGarrett D'Amore 		dcol = ncols < 5 ? term_len(p, 4) :
676*95c635efSGarrett D'Amore 			ncols == 5 ? term_len(p, 3) : term_len(p, 1);
677*95c635efSGarrett D'Amore 
678*95c635efSGarrett D'Amore 		/*
679*95c635efSGarrett D'Amore 		 * Calculate the offset by applying all prior MDOC_BODY,
680*95c635efSGarrett D'Amore 		 * so we stop at the MDOC_HEAD (NULL == nn->prev).
681*95c635efSGarrett D'Amore 		 */
682*95c635efSGarrett D'Amore 
683*95c635efSGarrett D'Amore 		for (i = 0, nn = n->prev;
684*95c635efSGarrett D'Amore 				nn->prev && i < (int)ncols;
685*95c635efSGarrett D'Amore 				nn = nn->prev, i++)
686*95c635efSGarrett D'Amore 			offset += dcol + a2width
687*95c635efSGarrett D'Amore 				(p, bl->norm->Bl.cols[i]);
688*95c635efSGarrett D'Amore 
689*95c635efSGarrett D'Amore 		/*
690*95c635efSGarrett D'Amore 		 * When exceeding the declared number of columns, leave
691*95c635efSGarrett D'Amore 		 * the remaining widths at 0.  This will later be
692*95c635efSGarrett D'Amore 		 * adjusted to the default width of 10, or, for the last
693*95c635efSGarrett D'Amore 		 * column, stretched to the right margin.
694*95c635efSGarrett D'Amore 		 */
695*95c635efSGarrett D'Amore 		if (i >= (int)ncols)
696*95c635efSGarrett D'Amore 			break;
697*95c635efSGarrett D'Amore 
698*95c635efSGarrett D'Amore 		/*
699*95c635efSGarrett D'Amore 		 * Use the declared column widths, extended as explained
700*95c635efSGarrett D'Amore 		 * in the preceding paragraph.
701*95c635efSGarrett D'Amore 		 */
702*95c635efSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
703*95c635efSGarrett D'Amore 		break;
704*95c635efSGarrett D'Amore 	default:
705*95c635efSGarrett D'Amore 		if (NULL == bl->norm->Bl.width)
706*95c635efSGarrett D'Amore 			break;
707*95c635efSGarrett D'Amore 
708*95c635efSGarrett D'Amore 		/*
709*95c635efSGarrett D'Amore 		 * Note: buffer the width by 2, which is groff's magic
710*95c635efSGarrett D'Amore 		 * number for buffering single arguments.  See the above
711*95c635efSGarrett D'Amore 		 * handling for column for how this changes.
712*95c635efSGarrett D'Amore 		 */
713*95c635efSGarrett D'Amore 		assert(bl->norm->Bl.width);
714*95c635efSGarrett D'Amore 		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
715*95c635efSGarrett D'Amore 		break;
716*95c635efSGarrett D'Amore 	}
717*95c635efSGarrett D'Amore 
718*95c635efSGarrett D'Amore 	/*
719*95c635efSGarrett D'Amore 	 * List-type can override the width in the case of fixed-head
720*95c635efSGarrett D'Amore 	 * values (bullet, dash/hyphen, enum).  Tags need a non-zero
721*95c635efSGarrett D'Amore 	 * offset.
722*95c635efSGarrett D'Amore 	 */
723*95c635efSGarrett D'Amore 
724*95c635efSGarrett D'Amore 	switch (type) {
725*95c635efSGarrett D'Amore 	case (LIST_bullet):
726*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
727*95c635efSGarrett D'Amore 	case (LIST_dash):
728*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
729*95c635efSGarrett D'Amore 	case (LIST_hyphen):
730*95c635efSGarrett D'Amore 		if (width < term_len(p, 4))
731*95c635efSGarrett D'Amore 			width = term_len(p, 4);
732*95c635efSGarrett D'Amore 		break;
733*95c635efSGarrett D'Amore 	case (LIST_enum):
734*95c635efSGarrett D'Amore 		if (width < term_len(p, 5))
735*95c635efSGarrett D'Amore 			width = term_len(p, 5);
736*95c635efSGarrett D'Amore 		break;
737*95c635efSGarrett D'Amore 	case (LIST_hang):
738*95c635efSGarrett D'Amore 		if (0 == width)
739*95c635efSGarrett D'Amore 			width = term_len(p, 8);
740*95c635efSGarrett D'Amore 		break;
741*95c635efSGarrett D'Amore 	case (LIST_column):
742*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
743*95c635efSGarrett D'Amore 	case (LIST_tag):
744*95c635efSGarrett D'Amore 		if (0 == width)
745*95c635efSGarrett D'Amore 			width = term_len(p, 10);
746*95c635efSGarrett D'Amore 		break;
747*95c635efSGarrett D'Amore 	default:
748*95c635efSGarrett D'Amore 		break;
749*95c635efSGarrett D'Amore 	}
750*95c635efSGarrett D'Amore 
751*95c635efSGarrett D'Amore 	/*
752*95c635efSGarrett D'Amore 	 * Whitespace control.  Inset bodies need an initial space,
753*95c635efSGarrett D'Amore 	 * while diagonal bodies need two.
754*95c635efSGarrett D'Amore 	 */
755*95c635efSGarrett D'Amore 
756*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
757*95c635efSGarrett D'Amore 
758*95c635efSGarrett D'Amore 	switch (type) {
759*95c635efSGarrett D'Amore 	case (LIST_diag):
760*95c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
761*95c635efSGarrett D'Amore 			term_word(p, "\\ \\ ");
762*95c635efSGarrett D'Amore 		break;
763*95c635efSGarrett D'Amore 	case (LIST_inset):
764*95c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
765*95c635efSGarrett D'Amore 			term_word(p, "\\ ");
766*95c635efSGarrett D'Amore 		break;
767*95c635efSGarrett D'Amore 	default:
768*95c635efSGarrett D'Amore 		break;
769*95c635efSGarrett D'Amore 	}
770*95c635efSGarrett D'Amore 
771*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
772*95c635efSGarrett D'Amore 
773*95c635efSGarrett D'Amore 	switch (type) {
774*95c635efSGarrett D'Amore 	case (LIST_diag):
775*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
776*95c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
777*95c635efSGarrett D'Amore 		break;
778*95c635efSGarrett D'Amore 	default:
779*95c635efSGarrett D'Amore 		break;
780*95c635efSGarrett D'Amore 	}
781*95c635efSGarrett D'Amore 
782*95c635efSGarrett D'Amore 	/*
783*95c635efSGarrett D'Amore 	 * Pad and break control.  This is the tricky part.  These flags
784*95c635efSGarrett D'Amore 	 * are documented in term_flushln() in term.c.  Note that we're
785*95c635efSGarrett D'Amore 	 * going to unset all of these flags in termp_it_post() when we
786*95c635efSGarrett D'Amore 	 * exit.
787*95c635efSGarrett D'Amore 	 */
788*95c635efSGarrett D'Amore 
789*95c635efSGarrett D'Amore 	switch (type) {
790*95c635efSGarrett D'Amore 	case (LIST_bullet):
791*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
792*95c635efSGarrett D'Amore 	case (LIST_dash):
793*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
794*95c635efSGarrett D'Amore 	case (LIST_enum):
795*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
796*95c635efSGarrett D'Amore 	case (LIST_hyphen):
797*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
798*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
799*95c635efSGarrett D'Amore 		break;
800*95c635efSGarrett D'Amore 	case (LIST_hang):
801*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
802*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
803*95c635efSGarrett D'Amore 		else
804*95c635efSGarrett D'Amore 			break;
805*95c635efSGarrett D'Amore 
806*95c635efSGarrett D'Amore 		/*
807*95c635efSGarrett D'Amore 		 * This is ugly.  If `-hang' is specified and the body
808*95c635efSGarrett D'Amore 		 * is a `Bl' or `Bd', then we want basically to nullify
809*95c635efSGarrett D'Amore 		 * the "overstep" effect in term_flushln() and treat
810*95c635efSGarrett D'Amore 		 * this as a `-ohang' list instead.
811*95c635efSGarrett D'Amore 		 */
812*95c635efSGarrett D'Amore 		if (n->next->child &&
813*95c635efSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
814*95c635efSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
815*95c635efSGarrett D'Amore 			p->flags &= ~TERMP_NOBREAK;
816*95c635efSGarrett D'Amore 		else
817*95c635efSGarrett D'Amore 			p->flags |= TERMP_HANG;
818*95c635efSGarrett D'Amore 		break;
819*95c635efSGarrett D'Amore 	case (LIST_tag):
820*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
821*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
822*95c635efSGarrett D'Amore 
823*95c635efSGarrett D'Amore 		if (MDOC_HEAD != n->type)
824*95c635efSGarrett D'Amore 			break;
825*95c635efSGarrett D'Amore 		if (NULL == n->next || NULL == n->next->child)
826*95c635efSGarrett D'Amore 			p->flags |= TERMP_DANGLE;
827*95c635efSGarrett D'Amore 		break;
828*95c635efSGarrett D'Amore 	case (LIST_column):
829*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
830*95c635efSGarrett D'Amore 			break;
831*95c635efSGarrett D'Amore 
832*95c635efSGarrett D'Amore 		if (NULL == n->next)
833*95c635efSGarrett D'Amore 			p->flags &= ~TERMP_NOBREAK;
834*95c635efSGarrett D'Amore 		else
835*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
836*95c635efSGarrett D'Amore 
837*95c635efSGarrett D'Amore 		break;
838*95c635efSGarrett D'Amore 	case (LIST_diag):
839*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
840*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOBREAK;
841*95c635efSGarrett D'Amore 		break;
842*95c635efSGarrett D'Amore 	default:
843*95c635efSGarrett D'Amore 		break;
844*95c635efSGarrett D'Amore 	}
845*95c635efSGarrett D'Amore 
846*95c635efSGarrett D'Amore 	/*
847*95c635efSGarrett D'Amore 	 * Margin control.  Set-head-width lists have their right
848*95c635efSGarrett D'Amore 	 * margins shortened.  The body for these lists has the offset
849*95c635efSGarrett D'Amore 	 * necessarily lengthened.  Everybody gets the offset.
850*95c635efSGarrett D'Amore 	 */
851*95c635efSGarrett D'Amore 
852*95c635efSGarrett D'Amore 	p->offset += offset;
853*95c635efSGarrett D'Amore 
854*95c635efSGarrett D'Amore 	switch (type) {
855*95c635efSGarrett D'Amore 	case (LIST_hang):
856*95c635efSGarrett D'Amore 		/*
857*95c635efSGarrett D'Amore 		 * Same stipulation as above, regarding `-hang'.  We
858*95c635efSGarrett D'Amore 		 * don't want to recalculate rmargin and offsets when
859*95c635efSGarrett D'Amore 		 * using `Bd' or `Bl' within `-hang' overstep lists.
860*95c635efSGarrett D'Amore 		 */
861*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type && n->next->child &&
862*95c635efSGarrett D'Amore 				(MDOC_Bl == n->next->child->tok ||
863*95c635efSGarrett D'Amore 				 MDOC_Bd == n->next->child->tok))
864*95c635efSGarrett D'Amore 			break;
865*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
866*95c635efSGarrett D'Amore 	case (LIST_bullet):
867*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
868*95c635efSGarrett D'Amore 	case (LIST_dash):
869*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
870*95c635efSGarrett D'Amore 	case (LIST_enum):
871*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
872*95c635efSGarrett D'Amore 	case (LIST_hyphen):
873*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
874*95c635efSGarrett D'Amore 	case (LIST_tag):
875*95c635efSGarrett D'Amore 		assert(width);
876*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
877*95c635efSGarrett D'Amore 			p->rmargin = p->offset + width;
878*95c635efSGarrett D'Amore 		else
879*95c635efSGarrett D'Amore 			p->offset += width;
880*95c635efSGarrett D'Amore 		break;
881*95c635efSGarrett D'Amore 	case (LIST_column):
882*95c635efSGarrett D'Amore 		assert(width);
883*95c635efSGarrett D'Amore 		p->rmargin = p->offset + width;
884*95c635efSGarrett D'Amore 		/*
885*95c635efSGarrett D'Amore 		 * XXX - this behaviour is not documented: the
886*95c635efSGarrett D'Amore 		 * right-most column is filled to the right margin.
887*95c635efSGarrett D'Amore 		 */
888*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
889*95c635efSGarrett D'Amore 			break;
890*95c635efSGarrett D'Amore 		if (NULL == n->next && p->rmargin < p->maxrmargin)
891*95c635efSGarrett D'Amore 			p->rmargin = p->maxrmargin;
892*95c635efSGarrett D'Amore 		break;
893*95c635efSGarrett D'Amore 	default:
894*95c635efSGarrett D'Amore 		break;
895*95c635efSGarrett D'Amore 	}
896*95c635efSGarrett D'Amore 
897*95c635efSGarrett D'Amore 	/*
898*95c635efSGarrett D'Amore 	 * The dash, hyphen, bullet and enum lists all have a special
899*95c635efSGarrett D'Amore 	 * HEAD character (temporarily bold, in some cases).
900*95c635efSGarrett D'Amore 	 */
901*95c635efSGarrett D'Amore 
902*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
903*95c635efSGarrett D'Amore 		switch (type) {
904*95c635efSGarrett D'Amore 		case (LIST_bullet):
905*95c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
906*95c635efSGarrett D'Amore 			term_word(p, "\\[bu]");
907*95c635efSGarrett D'Amore 			term_fontpop(p);
908*95c635efSGarrett D'Amore 			break;
909*95c635efSGarrett D'Amore 		case (LIST_dash):
910*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
911*95c635efSGarrett D'Amore 		case (LIST_hyphen):
912*95c635efSGarrett D'Amore 			term_fontpush(p, TERMFONT_BOLD);
913*95c635efSGarrett D'Amore 			term_word(p, "\\(hy");
914*95c635efSGarrett D'Amore 			term_fontpop(p);
915*95c635efSGarrett D'Amore 			break;
916*95c635efSGarrett D'Amore 		case (LIST_enum):
917*95c635efSGarrett D'Amore 			(pair->ppair->ppair->count)++;
918*95c635efSGarrett D'Amore 			snprintf(buf, sizeof(buf), "%d.",
919*95c635efSGarrett D'Amore 					pair->ppair->ppair->count);
920*95c635efSGarrett D'Amore 			term_word(p, buf);
921*95c635efSGarrett D'Amore 			break;
922*95c635efSGarrett D'Amore 		default:
923*95c635efSGarrett D'Amore 			break;
924*95c635efSGarrett D'Amore 		}
925*95c635efSGarrett D'Amore 
926*95c635efSGarrett D'Amore 	/*
927*95c635efSGarrett D'Amore 	 * If we're not going to process our children, indicate so here.
928*95c635efSGarrett D'Amore 	 */
929*95c635efSGarrett D'Amore 
930*95c635efSGarrett D'Amore 	switch (type) {
931*95c635efSGarrett D'Amore 	case (LIST_bullet):
932*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
933*95c635efSGarrett D'Amore 	case (LIST_item):
934*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
935*95c635efSGarrett D'Amore 	case (LIST_dash):
936*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
937*95c635efSGarrett D'Amore 	case (LIST_hyphen):
938*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
939*95c635efSGarrett D'Amore 	case (LIST_enum):
940*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
941*95c635efSGarrett D'Amore 			return(0);
942*95c635efSGarrett D'Amore 		break;
943*95c635efSGarrett D'Amore 	case (LIST_column):
944*95c635efSGarrett D'Amore 		if (MDOC_HEAD == n->type)
945*95c635efSGarrett D'Amore 			return(0);
946*95c635efSGarrett D'Amore 		break;
947*95c635efSGarrett D'Amore 	default:
948*95c635efSGarrett D'Amore 		break;
949*95c635efSGarrett D'Amore 	}
950*95c635efSGarrett D'Amore 
951*95c635efSGarrett D'Amore 	return(1);
952*95c635efSGarrett D'Amore }
953*95c635efSGarrett D'Amore 
954*95c635efSGarrett D'Amore 
955*95c635efSGarrett D'Amore /* ARGSUSED */
956*95c635efSGarrett D'Amore static void
957*95c635efSGarrett D'Amore termp_it_post(DECL_ARGS)
958*95c635efSGarrett D'Amore {
959*95c635efSGarrett D'Amore 	enum mdoc_list	   type;
960*95c635efSGarrett D'Amore 
961*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
962*95c635efSGarrett D'Amore 		return;
963*95c635efSGarrett D'Amore 
964*95c635efSGarrett D'Amore 	type = n->parent->parent->parent->norm->Bl.type;
965*95c635efSGarrett D'Amore 
966*95c635efSGarrett D'Amore 	switch (type) {
967*95c635efSGarrett D'Amore 	case (LIST_item):
968*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
969*95c635efSGarrett D'Amore 	case (LIST_diag):
970*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
971*95c635efSGarrett D'Amore 	case (LIST_inset):
972*95c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
973*95c635efSGarrett D'Amore 			term_newln(p);
974*95c635efSGarrett D'Amore 		break;
975*95c635efSGarrett D'Amore 	case (LIST_column):
976*95c635efSGarrett D'Amore 		if (MDOC_BODY == n->type)
977*95c635efSGarrett D'Amore 			term_flushln(p);
978*95c635efSGarrett D'Amore 		break;
979*95c635efSGarrett D'Amore 	default:
980*95c635efSGarrett D'Amore 		term_newln(p);
981*95c635efSGarrett D'Amore 		break;
982*95c635efSGarrett D'Amore 	}
983*95c635efSGarrett D'Amore 
984*95c635efSGarrett D'Amore 	/*
985*95c635efSGarrett D'Amore 	 * Now that our output is flushed, we can reset our tags.  Since
986*95c635efSGarrett D'Amore 	 * only `It' sets these flags, we're free to assume that nobody
987*95c635efSGarrett D'Amore 	 * has munged them in the meanwhile.
988*95c635efSGarrett D'Amore 	 */
989*95c635efSGarrett D'Amore 
990*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_DANGLE;
991*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_NOBREAK;
992*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_TWOSPACE;
993*95c635efSGarrett D'Amore 	p->flags &= ~TERMP_HANG;
994*95c635efSGarrett D'Amore }
995*95c635efSGarrett D'Amore 
996*95c635efSGarrett D'Amore 
997*95c635efSGarrett D'Amore /* ARGSUSED */
998*95c635efSGarrett D'Amore static int
999*95c635efSGarrett D'Amore termp_nm_pre(DECL_ARGS)
1000*95c635efSGarrett D'Amore {
1001*95c635efSGarrett D'Amore 
1002*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
1003*95c635efSGarrett D'Amore 		return(1);
1004*95c635efSGarrett D'Amore 
1005*95c635efSGarrett D'Amore 	if (MDOC_BODY == n->type) {
1006*95c635efSGarrett D'Amore 		if (NULL == n->child)
1007*95c635efSGarrett D'Amore 			return(0);
1008*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1009*95c635efSGarrett D'Amore 		p->offset += term_len(p, 1) +
1010*95c635efSGarrett D'Amore 		    (NULL == n->prev->child ? term_strlen(p, m->name) :
1011*95c635efSGarrett D'Amore 		     MDOC_TEXT == n->prev->child->type ?
1012*95c635efSGarrett D'Amore 			term_strlen(p, n->prev->child->string) :
1013*95c635efSGarrett D'Amore 		     term_len(p, 5));
1014*95c635efSGarrett D'Amore 		return(1);
1015*95c635efSGarrett D'Amore 	}
1016*95c635efSGarrett D'Amore 
1017*95c635efSGarrett D'Amore 	if (NULL == n->child && NULL == m->name)
1018*95c635efSGarrett D'Amore 		return(0);
1019*95c635efSGarrett D'Amore 
1020*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
1021*95c635efSGarrett D'Amore 		synopsis_pre(p, n->parent);
1022*95c635efSGarrett D'Amore 
1023*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type && n->next->child) {
1024*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
1025*95c635efSGarrett D'Amore 		p->rmargin = p->offset + term_len(p, 1);
1026*95c635efSGarrett D'Amore 		if (NULL == n->child) {
1027*95c635efSGarrett D'Amore 			p->rmargin += term_strlen(p, m->name);
1028*95c635efSGarrett D'Amore 		} else if (MDOC_TEXT == n->child->type) {
1029*95c635efSGarrett D'Amore 			p->rmargin += term_strlen(p, n->child->string);
1030*95c635efSGarrett D'Amore 			if (n->child->next)
1031*95c635efSGarrett D'Amore 				p->flags |= TERMP_HANG;
1032*95c635efSGarrett D'Amore 		} else {
1033*95c635efSGarrett D'Amore 			p->rmargin += term_len(p, 5);
1034*95c635efSGarrett D'Amore 			p->flags |= TERMP_HANG;
1035*95c635efSGarrett D'Amore 		}
1036*95c635efSGarrett D'Amore 	}
1037*95c635efSGarrett D'Amore 
1038*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
1039*95c635efSGarrett D'Amore 	if (NULL == n->child)
1040*95c635efSGarrett D'Amore 		term_word(p, m->name);
1041*95c635efSGarrett D'Amore 	return(1);
1042*95c635efSGarrett D'Amore }
1043*95c635efSGarrett D'Amore 
1044*95c635efSGarrett D'Amore 
1045*95c635efSGarrett D'Amore /* ARGSUSED */
1046*95c635efSGarrett D'Amore static void
1047*95c635efSGarrett D'Amore termp_nm_post(DECL_ARGS)
1048*95c635efSGarrett D'Amore {
1049*95c635efSGarrett D'Amore 
1050*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type && n->next->child) {
1051*95c635efSGarrett D'Amore 		term_flushln(p);
1052*95c635efSGarrett D'Amore 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
1053*95c635efSGarrett D'Amore 	} else if (MDOC_BODY == n->type && n->child)
1054*95c635efSGarrett D'Amore 		term_flushln(p);
1055*95c635efSGarrett D'Amore }
1056*95c635efSGarrett D'Amore 
1057*95c635efSGarrett D'Amore 
1058*95c635efSGarrett D'Amore /* ARGSUSED */
1059*95c635efSGarrett D'Amore static int
1060*95c635efSGarrett D'Amore termp_fl_pre(DECL_ARGS)
1061*95c635efSGarrett D'Amore {
1062*95c635efSGarrett D'Amore 
1063*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
1064*95c635efSGarrett D'Amore 	term_word(p, "\\-");
1065*95c635efSGarrett D'Amore 
1066*95c635efSGarrett D'Amore 	if (n->child)
1067*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1068*95c635efSGarrett D'Amore 	else if (n->next && n->next->line == n->line)
1069*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1070*95c635efSGarrett D'Amore 
1071*95c635efSGarrett D'Amore 	return(1);
1072*95c635efSGarrett D'Amore }
1073*95c635efSGarrett D'Amore 
1074*95c635efSGarrett D'Amore 
1075*95c635efSGarrett D'Amore /* ARGSUSED */
1076*95c635efSGarrett D'Amore static int
1077*95c635efSGarrett D'Amore termp__a_pre(DECL_ARGS)
1078*95c635efSGarrett D'Amore {
1079*95c635efSGarrett D'Amore 
1080*95c635efSGarrett D'Amore 	if (n->prev && MDOC__A == n->prev->tok)
1081*95c635efSGarrett D'Amore 		if (NULL == n->next || MDOC__A != n->next->tok)
1082*95c635efSGarrett D'Amore 			term_word(p, "and");
1083*95c635efSGarrett D'Amore 
1084*95c635efSGarrett D'Amore 	return(1);
1085*95c635efSGarrett D'Amore }
1086*95c635efSGarrett D'Amore 
1087*95c635efSGarrett D'Amore 
1088*95c635efSGarrett D'Amore /* ARGSUSED */
1089*95c635efSGarrett D'Amore static int
1090*95c635efSGarrett D'Amore termp_an_pre(DECL_ARGS)
1091*95c635efSGarrett D'Amore {
1092*95c635efSGarrett D'Amore 
1093*95c635efSGarrett D'Amore 	if (NULL == n->child)
1094*95c635efSGarrett D'Amore 		return(1);
1095*95c635efSGarrett D'Amore 
1096*95c635efSGarrett D'Amore 	/*
1097*95c635efSGarrett D'Amore 	 * If not in the AUTHORS section, `An -split' will cause
1098*95c635efSGarrett D'Amore 	 * newlines to occur before the author name.  If in the AUTHORS
1099*95c635efSGarrett D'Amore 	 * section, by default, the first `An' invocation is nosplit,
1100*95c635efSGarrett D'Amore 	 * then all subsequent ones, regardless of whether interspersed
1101*95c635efSGarrett D'Amore 	 * with other macros/text, are split.  -split, in this case,
1102*95c635efSGarrett D'Amore 	 * will override the condition of the implied first -nosplit.
1103*95c635efSGarrett D'Amore 	 */
1104*95c635efSGarrett D'Amore 
1105*95c635efSGarrett D'Amore 	if (n->sec == SEC_AUTHORS) {
1106*95c635efSGarrett D'Amore 		if ( ! (TERMP_ANPREC & p->flags)) {
1107*95c635efSGarrett D'Amore 			if (TERMP_SPLIT & p->flags)
1108*95c635efSGarrett D'Amore 				term_newln(p);
1109*95c635efSGarrett D'Amore 			return(1);
1110*95c635efSGarrett D'Amore 		}
1111*95c635efSGarrett D'Amore 		if (TERMP_NOSPLIT & p->flags)
1112*95c635efSGarrett D'Amore 			return(1);
1113*95c635efSGarrett D'Amore 		term_newln(p);
1114*95c635efSGarrett D'Amore 		return(1);
1115*95c635efSGarrett D'Amore 	}
1116*95c635efSGarrett D'Amore 
1117*95c635efSGarrett D'Amore 	if (TERMP_SPLIT & p->flags)
1118*95c635efSGarrett D'Amore 		term_newln(p);
1119*95c635efSGarrett D'Amore 
1120*95c635efSGarrett D'Amore 	return(1);
1121*95c635efSGarrett D'Amore }
1122*95c635efSGarrett D'Amore 
1123*95c635efSGarrett D'Amore 
1124*95c635efSGarrett D'Amore /* ARGSUSED */
1125*95c635efSGarrett D'Amore static void
1126*95c635efSGarrett D'Amore termp_an_post(DECL_ARGS)
1127*95c635efSGarrett D'Amore {
1128*95c635efSGarrett D'Amore 
1129*95c635efSGarrett D'Amore 	if (n->child) {
1130*95c635efSGarrett D'Amore 		if (SEC_AUTHORS == n->sec)
1131*95c635efSGarrett D'Amore 			p->flags |= TERMP_ANPREC;
1132*95c635efSGarrett D'Amore 		return;
1133*95c635efSGarrett D'Amore 	}
1134*95c635efSGarrett D'Amore 
1135*95c635efSGarrett D'Amore 	if (AUTH_split == n->norm->An.auth) {
1136*95c635efSGarrett D'Amore 		p->flags &= ~TERMP_NOSPLIT;
1137*95c635efSGarrett D'Amore 		p->flags |= TERMP_SPLIT;
1138*95c635efSGarrett D'Amore 	} else if (AUTH_nosplit == n->norm->An.auth) {
1139*95c635efSGarrett D'Amore 		p->flags &= ~TERMP_SPLIT;
1140*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPLIT;
1141*95c635efSGarrett D'Amore 	}
1142*95c635efSGarrett D'Amore 
1143*95c635efSGarrett D'Amore }
1144*95c635efSGarrett D'Amore 
1145*95c635efSGarrett D'Amore 
1146*95c635efSGarrett D'Amore /* ARGSUSED */
1147*95c635efSGarrett D'Amore static int
1148*95c635efSGarrett D'Amore termp_ns_pre(DECL_ARGS)
1149*95c635efSGarrett D'Amore {
1150*95c635efSGarrett D'Amore 
1151*95c635efSGarrett D'Amore 	if ( ! (MDOC_LINE & n->flags))
1152*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1153*95c635efSGarrett D'Amore 	return(1);
1154*95c635efSGarrett D'Amore }
1155*95c635efSGarrett D'Amore 
1156*95c635efSGarrett D'Amore 
1157*95c635efSGarrett D'Amore /* ARGSUSED */
1158*95c635efSGarrett D'Amore static int
1159*95c635efSGarrett D'Amore termp_rs_pre(DECL_ARGS)
1160*95c635efSGarrett D'Amore {
1161*95c635efSGarrett D'Amore 
1162*95c635efSGarrett D'Amore 	if (SEC_SEE_ALSO != n->sec)
1163*95c635efSGarrett D'Amore 		return(1);
1164*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type && n->prev)
1165*95c635efSGarrett D'Amore 		term_vspace(p);
1166*95c635efSGarrett D'Amore 	return(1);
1167*95c635efSGarrett D'Amore }
1168*95c635efSGarrett D'Amore 
1169*95c635efSGarrett D'Amore 
1170*95c635efSGarrett D'Amore /* ARGSUSED */
1171*95c635efSGarrett D'Amore static int
1172*95c635efSGarrett D'Amore termp_rv_pre(DECL_ARGS)
1173*95c635efSGarrett D'Amore {
1174*95c635efSGarrett D'Amore 	int		 nchild;
1175*95c635efSGarrett D'Amore 
1176*95c635efSGarrett D'Amore 	term_newln(p);
1177*95c635efSGarrett D'Amore 	term_word(p, "The");
1178*95c635efSGarrett D'Amore 
1179*95c635efSGarrett D'Amore 	nchild = n->nchild;
1180*95c635efSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
1181*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1182*95c635efSGarrett D'Amore 		term_word(p, n->string);
1183*95c635efSGarrett D'Amore 		term_fontpop(p);
1184*95c635efSGarrett D'Amore 
1185*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1186*95c635efSGarrett D'Amore 		term_word(p, "()");
1187*95c635efSGarrett D'Amore 
1188*95c635efSGarrett D'Amore 		if (nchild > 2 && n->next) {
1189*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
1190*95c635efSGarrett D'Amore 			term_word(p, ",");
1191*95c635efSGarrett D'Amore 		}
1192*95c635efSGarrett D'Amore 
1193*95c635efSGarrett D'Amore 		if (n->next && NULL == n->next->next)
1194*95c635efSGarrett D'Amore 			term_word(p, "and");
1195*95c635efSGarrett D'Amore 	}
1196*95c635efSGarrett D'Amore 
1197*95c635efSGarrett D'Amore 	if (nchild > 1)
1198*95c635efSGarrett D'Amore 		term_word(p, "functions return");
1199*95c635efSGarrett D'Amore 	else
1200*95c635efSGarrett D'Amore 		term_word(p, "function returns");
1201*95c635efSGarrett D'Amore 
1202*95c635efSGarrett D'Amore        	term_word(p, "the value 0 if successful; otherwise the value "
1203*95c635efSGarrett D'Amore 			"-1 is returned and the global variable");
1204*95c635efSGarrett D'Amore 
1205*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
1206*95c635efSGarrett D'Amore 	term_word(p, "errno");
1207*95c635efSGarrett D'Amore 	term_fontpop(p);
1208*95c635efSGarrett D'Amore 
1209*95c635efSGarrett D'Amore        	term_word(p, "is set to indicate the error.");
1210*95c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
1211*95c635efSGarrett D'Amore 
1212*95c635efSGarrett D'Amore 	return(0);
1213*95c635efSGarrett D'Amore }
1214*95c635efSGarrett D'Amore 
1215*95c635efSGarrett D'Amore 
1216*95c635efSGarrett D'Amore /* ARGSUSED */
1217*95c635efSGarrett D'Amore static int
1218*95c635efSGarrett D'Amore termp_ex_pre(DECL_ARGS)
1219*95c635efSGarrett D'Amore {
1220*95c635efSGarrett D'Amore 	int		 nchild;
1221*95c635efSGarrett D'Amore 
1222*95c635efSGarrett D'Amore 	term_newln(p);
1223*95c635efSGarrett D'Amore 	term_word(p, "The");
1224*95c635efSGarrett D'Amore 
1225*95c635efSGarrett D'Amore 	nchild = n->nchild;
1226*95c635efSGarrett D'Amore 	for (n = n->child; n; n = n->next) {
1227*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1228*95c635efSGarrett D'Amore 		term_word(p, n->string);
1229*95c635efSGarrett D'Amore 		term_fontpop(p);
1230*95c635efSGarrett D'Amore 
1231*95c635efSGarrett D'Amore 		if (nchild > 2 && n->next) {
1232*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
1233*95c635efSGarrett D'Amore 			term_word(p, ",");
1234*95c635efSGarrett D'Amore 		}
1235*95c635efSGarrett D'Amore 
1236*95c635efSGarrett D'Amore 		if (n->next && NULL == n->next->next)
1237*95c635efSGarrett D'Amore 			term_word(p, "and");
1238*95c635efSGarrett D'Amore 	}
1239*95c635efSGarrett D'Amore 
1240*95c635efSGarrett D'Amore 	if (nchild > 1)
1241*95c635efSGarrett D'Amore 		term_word(p, "utilities exit");
1242*95c635efSGarrett D'Amore 	else
1243*95c635efSGarrett D'Amore 		term_word(p, "utility exits");
1244*95c635efSGarrett D'Amore 
1245*95c635efSGarrett D'Amore        	term_word(p, "0 on success, and >0 if an error occurs.");
1246*95c635efSGarrett D'Amore 
1247*95c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
1248*95c635efSGarrett D'Amore 	return(0);
1249*95c635efSGarrett D'Amore }
1250*95c635efSGarrett D'Amore 
1251*95c635efSGarrett D'Amore 
1252*95c635efSGarrett D'Amore /* ARGSUSED */
1253*95c635efSGarrett D'Amore static int
1254*95c635efSGarrett D'Amore termp_nd_pre(DECL_ARGS)
1255*95c635efSGarrett D'Amore {
1256*95c635efSGarrett D'Amore 
1257*95c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
1258*95c635efSGarrett D'Amore 		return(1);
1259*95c635efSGarrett D'Amore 
1260*95c635efSGarrett D'Amore #if defined(__OpenBSD__) || defined(__linux__)
1261*95c635efSGarrett D'Amore 	term_word(p, "\\(en");
1262*95c635efSGarrett D'Amore #else
1263*95c635efSGarrett D'Amore 	term_word(p, "\\(em");
1264*95c635efSGarrett D'Amore #endif
1265*95c635efSGarrett D'Amore 	return(1);
1266*95c635efSGarrett D'Amore }
1267*95c635efSGarrett D'Amore 
1268*95c635efSGarrett D'Amore 
1269*95c635efSGarrett D'Amore /* ARGSUSED */
1270*95c635efSGarrett D'Amore static int
1271*95c635efSGarrett D'Amore termp_bl_pre(DECL_ARGS)
1272*95c635efSGarrett D'Amore {
1273*95c635efSGarrett D'Amore 
1274*95c635efSGarrett D'Amore 	return(MDOC_HEAD != n->type);
1275*95c635efSGarrett D'Amore }
1276*95c635efSGarrett D'Amore 
1277*95c635efSGarrett D'Amore 
1278*95c635efSGarrett D'Amore /* ARGSUSED */
1279*95c635efSGarrett D'Amore static void
1280*95c635efSGarrett D'Amore termp_bl_post(DECL_ARGS)
1281*95c635efSGarrett D'Amore {
1282*95c635efSGarrett D'Amore 
1283*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type)
1284*95c635efSGarrett D'Amore 		term_newln(p);
1285*95c635efSGarrett D'Amore }
1286*95c635efSGarrett D'Amore 
1287*95c635efSGarrett D'Amore /* ARGSUSED */
1288*95c635efSGarrett D'Amore static int
1289*95c635efSGarrett D'Amore termp_xr_pre(DECL_ARGS)
1290*95c635efSGarrett D'Amore {
1291*95c635efSGarrett D'Amore 
1292*95c635efSGarrett D'Amore 	if (NULL == (n = n->child))
1293*95c635efSGarrett D'Amore 		return(0);
1294*95c635efSGarrett D'Amore 
1295*95c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
1296*95c635efSGarrett D'Amore 	term_word(p, n->string);
1297*95c635efSGarrett D'Amore 
1298*95c635efSGarrett D'Amore 	if (NULL == (n = n->next))
1299*95c635efSGarrett D'Amore 		return(0);
1300*95c635efSGarrett D'Amore 
1301*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1302*95c635efSGarrett D'Amore 	term_word(p, "(");
1303*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1304*95c635efSGarrett D'Amore 
1305*95c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
1306*95c635efSGarrett D'Amore 	term_word(p, n->string);
1307*95c635efSGarrett D'Amore 
1308*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1309*95c635efSGarrett D'Amore 	term_word(p, ")");
1310*95c635efSGarrett D'Amore 
1311*95c635efSGarrett D'Amore 	return(0);
1312*95c635efSGarrett D'Amore }
1313*95c635efSGarrett D'Amore 
1314*95c635efSGarrett D'Amore /*
1315*95c635efSGarrett D'Amore  * This decides how to assert whitespace before any of the SYNOPSIS set
1316*95c635efSGarrett D'Amore  * of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
1317*95c635efSGarrett D'Amore  * macro combos).
1318*95c635efSGarrett D'Amore  */
1319*95c635efSGarrett D'Amore static void
1320*95c635efSGarrett D'Amore synopsis_pre(struct termp *p, const struct mdoc_node *n)
1321*95c635efSGarrett D'Amore {
1322*95c635efSGarrett D'Amore 	/*
1323*95c635efSGarrett D'Amore 	 * Obviously, if we're not in a SYNOPSIS or no prior macros
1324*95c635efSGarrett D'Amore 	 * exist, do nothing.
1325*95c635efSGarrett D'Amore 	 */
1326*95c635efSGarrett D'Amore 	if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
1327*95c635efSGarrett D'Amore 		return;
1328*95c635efSGarrett D'Amore 
1329*95c635efSGarrett D'Amore 	/*
1330*95c635efSGarrett D'Amore 	 * If we're the second in a pair of like elements, emit our
1331*95c635efSGarrett D'Amore 	 * newline and return.  UNLESS we're `Fo', `Fn', `Fn', in which
1332*95c635efSGarrett D'Amore 	 * case we soldier on.
1333*95c635efSGarrett D'Amore 	 */
1334*95c635efSGarrett D'Amore 	if (n->prev->tok == n->tok &&
1335*95c635efSGarrett D'Amore 			MDOC_Ft != n->tok &&
1336*95c635efSGarrett D'Amore 			MDOC_Fo != n->tok &&
1337*95c635efSGarrett D'Amore 			MDOC_Fn != n->tok) {
1338*95c635efSGarrett D'Amore 		term_newln(p);
1339*95c635efSGarrett D'Amore 		return;
1340*95c635efSGarrett D'Amore 	}
1341*95c635efSGarrett D'Amore 
1342*95c635efSGarrett D'Amore 	/*
1343*95c635efSGarrett D'Amore 	 * If we're one of the SYNOPSIS set and non-like pair-wise after
1344*95c635efSGarrett D'Amore 	 * another (or Fn/Fo, which we've let slip through) then assert
1345*95c635efSGarrett D'Amore 	 * vertical space, else only newline and move on.
1346*95c635efSGarrett D'Amore 	 */
1347*95c635efSGarrett D'Amore 	switch (n->prev->tok) {
1348*95c635efSGarrett D'Amore 	case (MDOC_Fd):
1349*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1350*95c635efSGarrett D'Amore 	case (MDOC_Fn):
1351*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1352*95c635efSGarrett D'Amore 	case (MDOC_Fo):
1353*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1354*95c635efSGarrett D'Amore 	case (MDOC_In):
1355*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1356*95c635efSGarrett D'Amore 	case (MDOC_Vt):
1357*95c635efSGarrett D'Amore 		term_vspace(p);
1358*95c635efSGarrett D'Amore 		break;
1359*95c635efSGarrett D'Amore 	case (MDOC_Ft):
1360*95c635efSGarrett D'Amore 		if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
1361*95c635efSGarrett D'Amore 			term_vspace(p);
1362*95c635efSGarrett D'Amore 			break;
1363*95c635efSGarrett D'Amore 		}
1364*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1365*95c635efSGarrett D'Amore 	default:
1366*95c635efSGarrett D'Amore 		term_newln(p);
1367*95c635efSGarrett D'Amore 		break;
1368*95c635efSGarrett D'Amore 	}
1369*95c635efSGarrett D'Amore }
1370*95c635efSGarrett D'Amore 
1371*95c635efSGarrett D'Amore 
1372*95c635efSGarrett D'Amore static int
1373*95c635efSGarrett D'Amore termp_vt_pre(DECL_ARGS)
1374*95c635efSGarrett D'Amore {
1375*95c635efSGarrett D'Amore 
1376*95c635efSGarrett D'Amore 	if (MDOC_ELEM == n->type) {
1377*95c635efSGarrett D'Amore 		synopsis_pre(p, n);
1378*95c635efSGarrett D'Amore 		return(termp_under_pre(p, pair, m, n));
1379*95c635efSGarrett D'Amore 	} else if (MDOC_BLOCK == n->type) {
1380*95c635efSGarrett D'Amore 		synopsis_pre(p, n);
1381*95c635efSGarrett D'Amore 		return(1);
1382*95c635efSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
1383*95c635efSGarrett D'Amore 		return(0);
1384*95c635efSGarrett D'Amore 
1385*95c635efSGarrett D'Amore 	return(termp_under_pre(p, pair, m, n));
1386*95c635efSGarrett D'Amore }
1387*95c635efSGarrett D'Amore 
1388*95c635efSGarrett D'Amore 
1389*95c635efSGarrett D'Amore /* ARGSUSED */
1390*95c635efSGarrett D'Amore static int
1391*95c635efSGarrett D'Amore termp_bold_pre(DECL_ARGS)
1392*95c635efSGarrett D'Amore {
1393*95c635efSGarrett D'Amore 
1394*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
1395*95c635efSGarrett D'Amore 	return(1);
1396*95c635efSGarrett D'Amore }
1397*95c635efSGarrett D'Amore 
1398*95c635efSGarrett D'Amore 
1399*95c635efSGarrett D'Amore /* ARGSUSED */
1400*95c635efSGarrett D'Amore static int
1401*95c635efSGarrett D'Amore termp_fd_pre(DECL_ARGS)
1402*95c635efSGarrett D'Amore {
1403*95c635efSGarrett D'Amore 
1404*95c635efSGarrett D'Amore 	synopsis_pre(p, n);
1405*95c635efSGarrett D'Amore 	return(termp_bold_pre(p, pair, m, n));
1406*95c635efSGarrett D'Amore }
1407*95c635efSGarrett D'Amore 
1408*95c635efSGarrett D'Amore 
1409*95c635efSGarrett D'Amore /* ARGSUSED */
1410*95c635efSGarrett D'Amore static int
1411*95c635efSGarrett D'Amore termp_sh_pre(DECL_ARGS)
1412*95c635efSGarrett D'Amore {
1413*95c635efSGarrett D'Amore 
1414*95c635efSGarrett D'Amore 	/* No vspace between consecutive `Sh' calls. */
1415*95c635efSGarrett D'Amore 
1416*95c635efSGarrett D'Amore 	switch (n->type) {
1417*95c635efSGarrett D'Amore 	case (MDOC_BLOCK):
1418*95c635efSGarrett D'Amore 		if (n->prev && MDOC_Sh == n->prev->tok)
1419*95c635efSGarrett D'Amore 			if (NULL == n->prev->body->child)
1420*95c635efSGarrett D'Amore 				break;
1421*95c635efSGarrett D'Amore 		term_vspace(p);
1422*95c635efSGarrett D'Amore 		break;
1423*95c635efSGarrett D'Amore 	case (MDOC_HEAD):
1424*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1425*95c635efSGarrett D'Amore 		break;
1426*95c635efSGarrett D'Amore 	case (MDOC_BODY):
1427*95c635efSGarrett D'Amore 		p->offset = term_len(p, p->defindent);
1428*95c635efSGarrett D'Amore 		break;
1429*95c635efSGarrett D'Amore 	default:
1430*95c635efSGarrett D'Amore 		break;
1431*95c635efSGarrett D'Amore 	}
1432*95c635efSGarrett D'Amore 	return(1);
1433*95c635efSGarrett D'Amore }
1434*95c635efSGarrett D'Amore 
1435*95c635efSGarrett D'Amore 
1436*95c635efSGarrett D'Amore /* ARGSUSED */
1437*95c635efSGarrett D'Amore static void
1438*95c635efSGarrett D'Amore termp_sh_post(DECL_ARGS)
1439*95c635efSGarrett D'Amore {
1440*95c635efSGarrett D'Amore 
1441*95c635efSGarrett D'Amore 	switch (n->type) {
1442*95c635efSGarrett D'Amore 	case (MDOC_HEAD):
1443*95c635efSGarrett D'Amore 		term_newln(p);
1444*95c635efSGarrett D'Amore 		break;
1445*95c635efSGarrett D'Amore 	case (MDOC_BODY):
1446*95c635efSGarrett D'Amore 		term_newln(p);
1447*95c635efSGarrett D'Amore 		p->offset = 0;
1448*95c635efSGarrett D'Amore 		break;
1449*95c635efSGarrett D'Amore 	default:
1450*95c635efSGarrett D'Amore 		break;
1451*95c635efSGarrett D'Amore 	}
1452*95c635efSGarrett D'Amore }
1453*95c635efSGarrett D'Amore 
1454*95c635efSGarrett D'Amore 
1455*95c635efSGarrett D'Amore /* ARGSUSED */
1456*95c635efSGarrett D'Amore static int
1457*95c635efSGarrett D'Amore termp_bt_pre(DECL_ARGS)
1458*95c635efSGarrett D'Amore {
1459*95c635efSGarrett D'Amore 
1460*95c635efSGarrett D'Amore 	term_word(p, "is currently in beta test.");
1461*95c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
1462*95c635efSGarrett D'Amore 	return(0);
1463*95c635efSGarrett D'Amore }
1464*95c635efSGarrett D'Amore 
1465*95c635efSGarrett D'Amore 
1466*95c635efSGarrett D'Amore /* ARGSUSED */
1467*95c635efSGarrett D'Amore static void
1468*95c635efSGarrett D'Amore termp_lb_post(DECL_ARGS)
1469*95c635efSGarrett D'Amore {
1470*95c635efSGarrett D'Amore 
1471*95c635efSGarrett D'Amore 	if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags)
1472*95c635efSGarrett D'Amore 		term_newln(p);
1473*95c635efSGarrett D'Amore }
1474*95c635efSGarrett D'Amore 
1475*95c635efSGarrett D'Amore 
1476*95c635efSGarrett D'Amore /* ARGSUSED */
1477*95c635efSGarrett D'Amore static int
1478*95c635efSGarrett D'Amore termp_ud_pre(DECL_ARGS)
1479*95c635efSGarrett D'Amore {
1480*95c635efSGarrett D'Amore 
1481*95c635efSGarrett D'Amore 	term_word(p, "currently under development.");
1482*95c635efSGarrett D'Amore 	p->flags |= TERMP_SENTENCE;
1483*95c635efSGarrett D'Amore 	return(0);
1484*95c635efSGarrett D'Amore }
1485*95c635efSGarrett D'Amore 
1486*95c635efSGarrett D'Amore 
1487*95c635efSGarrett D'Amore /* ARGSUSED */
1488*95c635efSGarrett D'Amore static int
1489*95c635efSGarrett D'Amore termp_d1_pre(DECL_ARGS)
1490*95c635efSGarrett D'Amore {
1491*95c635efSGarrett D'Amore 
1492*95c635efSGarrett D'Amore 	if (MDOC_BLOCK != n->type)
1493*95c635efSGarrett D'Amore 		return(1);
1494*95c635efSGarrett D'Amore 	term_newln(p);
1495*95c635efSGarrett D'Amore 	p->offset += term_len(p, p->defindent + 1);
1496*95c635efSGarrett D'Amore 	return(1);
1497*95c635efSGarrett D'Amore }
1498*95c635efSGarrett D'Amore 
1499*95c635efSGarrett D'Amore 
1500*95c635efSGarrett D'Amore /* ARGSUSED */
1501*95c635efSGarrett D'Amore static void
1502*95c635efSGarrett D'Amore termp_d1_post(DECL_ARGS)
1503*95c635efSGarrett D'Amore {
1504*95c635efSGarrett D'Amore 
1505*95c635efSGarrett D'Amore 	if (MDOC_BLOCK != n->type)
1506*95c635efSGarrett D'Amore 		return;
1507*95c635efSGarrett D'Amore 	term_newln(p);
1508*95c635efSGarrett D'Amore }
1509*95c635efSGarrett D'Amore 
1510*95c635efSGarrett D'Amore 
1511*95c635efSGarrett D'Amore /* ARGSUSED */
1512*95c635efSGarrett D'Amore static int
1513*95c635efSGarrett D'Amore termp_ft_pre(DECL_ARGS)
1514*95c635efSGarrett D'Amore {
1515*95c635efSGarrett D'Amore 
1516*95c635efSGarrett D'Amore 	/* NB: MDOC_LINE does not effect this! */
1517*95c635efSGarrett D'Amore 	synopsis_pre(p, n);
1518*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
1519*95c635efSGarrett D'Amore 	return(1);
1520*95c635efSGarrett D'Amore }
1521*95c635efSGarrett D'Amore 
1522*95c635efSGarrett D'Amore 
1523*95c635efSGarrett D'Amore /* ARGSUSED */
1524*95c635efSGarrett D'Amore static int
1525*95c635efSGarrett D'Amore termp_fn_pre(DECL_ARGS)
1526*95c635efSGarrett D'Amore {
1527*95c635efSGarrett D'Amore 	int		 pretty;
1528*95c635efSGarrett D'Amore 
1529*95c635efSGarrett D'Amore 	pretty = MDOC_SYNPRETTY & n->flags;
1530*95c635efSGarrett D'Amore 
1531*95c635efSGarrett D'Amore 	synopsis_pre(p, n);
1532*95c635efSGarrett D'Amore 
1533*95c635efSGarrett D'Amore 	if (NULL == (n = n->child))
1534*95c635efSGarrett D'Amore 		return(0);
1535*95c635efSGarrett D'Amore 
1536*95c635efSGarrett D'Amore 	assert(MDOC_TEXT == n->type);
1537*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
1538*95c635efSGarrett D'Amore 	term_word(p, n->string);
1539*95c635efSGarrett D'Amore 	term_fontpop(p);
1540*95c635efSGarrett D'Amore 
1541*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1542*95c635efSGarrett D'Amore 	term_word(p, "(");
1543*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1544*95c635efSGarrett D'Amore 
1545*95c635efSGarrett D'Amore 	for (n = n->next; n; n = n->next) {
1546*95c635efSGarrett D'Amore 		assert(MDOC_TEXT == n->type);
1547*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1548*95c635efSGarrett D'Amore 		term_word(p, n->string);
1549*95c635efSGarrett D'Amore 		term_fontpop(p);
1550*95c635efSGarrett D'Amore 
1551*95c635efSGarrett D'Amore 		if (n->next) {
1552*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
1553*95c635efSGarrett D'Amore 			term_word(p, ",");
1554*95c635efSGarrett D'Amore 		}
1555*95c635efSGarrett D'Amore 	}
1556*95c635efSGarrett D'Amore 
1557*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1558*95c635efSGarrett D'Amore 	term_word(p, ")");
1559*95c635efSGarrett D'Amore 
1560*95c635efSGarrett D'Amore 	if (pretty) {
1561*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1562*95c635efSGarrett D'Amore 		term_word(p, ";");
1563*95c635efSGarrett D'Amore 	}
1564*95c635efSGarrett D'Amore 
1565*95c635efSGarrett D'Amore 	return(0);
1566*95c635efSGarrett D'Amore }
1567*95c635efSGarrett D'Amore 
1568*95c635efSGarrett D'Amore 
1569*95c635efSGarrett D'Amore /* ARGSUSED */
1570*95c635efSGarrett D'Amore static int
1571*95c635efSGarrett D'Amore termp_fa_pre(DECL_ARGS)
1572*95c635efSGarrett D'Amore {
1573*95c635efSGarrett D'Amore 	const struct mdoc_node	*nn;
1574*95c635efSGarrett D'Amore 
1575*95c635efSGarrett D'Amore 	if (n->parent->tok != MDOC_Fo) {
1576*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1577*95c635efSGarrett D'Amore 		return(1);
1578*95c635efSGarrett D'Amore 	}
1579*95c635efSGarrett D'Amore 
1580*95c635efSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
1581*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1582*95c635efSGarrett D'Amore 		term_word(p, nn->string);
1583*95c635efSGarrett D'Amore 		term_fontpop(p);
1584*95c635efSGarrett D'Amore 
1585*95c635efSGarrett D'Amore 		if (nn->next) {
1586*95c635efSGarrett D'Amore 			p->flags |= TERMP_NOSPACE;
1587*95c635efSGarrett D'Amore 			term_word(p, ",");
1588*95c635efSGarrett D'Amore 		}
1589*95c635efSGarrett D'Amore 	}
1590*95c635efSGarrett D'Amore 
1591*95c635efSGarrett D'Amore 	if (n->child && n->next && n->next->tok == MDOC_Fa) {
1592*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1593*95c635efSGarrett D'Amore 		term_word(p, ",");
1594*95c635efSGarrett D'Amore 	}
1595*95c635efSGarrett D'Amore 
1596*95c635efSGarrett D'Amore 	return(0);
1597*95c635efSGarrett D'Amore }
1598*95c635efSGarrett D'Amore 
1599*95c635efSGarrett D'Amore 
1600*95c635efSGarrett D'Amore /* ARGSUSED */
1601*95c635efSGarrett D'Amore static int
1602*95c635efSGarrett D'Amore termp_bd_pre(DECL_ARGS)
1603*95c635efSGarrett D'Amore {
1604*95c635efSGarrett D'Amore 	size_t			 tabwidth, rm, rmax;
1605*95c635efSGarrett D'Amore 	const struct mdoc_node	*nn;
1606*95c635efSGarrett D'Amore 
1607*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
1608*95c635efSGarrett D'Amore 		print_bvspace(p, n, n);
1609*95c635efSGarrett D'Amore 		return(1);
1610*95c635efSGarrett D'Amore 	} else if (MDOC_HEAD == n->type)
1611*95c635efSGarrett D'Amore 		return(0);
1612*95c635efSGarrett D'Amore 
1613*95c635efSGarrett D'Amore 	if (n->norm->Bd.offs)
1614*95c635efSGarrett D'Amore 		p->offset += a2offs(p, n->norm->Bd.offs);
1615*95c635efSGarrett D'Amore 
1616*95c635efSGarrett D'Amore 	/*
1617*95c635efSGarrett D'Amore 	 * If -ragged or -filled are specified, the block does nothing
1618*95c635efSGarrett D'Amore 	 * but change the indentation.  If -unfilled or -literal are
1619*95c635efSGarrett D'Amore 	 * specified, text is printed exactly as entered in the display:
1620*95c635efSGarrett D'Amore 	 * for macro lines, a newline is appended to the line.  Blank
1621*95c635efSGarrett D'Amore 	 * lines are allowed.
1622*95c635efSGarrett D'Amore 	 */
1623*95c635efSGarrett D'Amore 
1624*95c635efSGarrett D'Amore 	if (DISP_literal != n->norm->Bd.type &&
1625*95c635efSGarrett D'Amore 			DISP_unfilled != n->norm->Bd.type)
1626*95c635efSGarrett D'Amore 		return(1);
1627*95c635efSGarrett D'Amore 
1628*95c635efSGarrett D'Amore 	tabwidth = p->tabwidth;
1629*95c635efSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type)
1630*95c635efSGarrett D'Amore 		p->tabwidth = term_len(p, 8);
1631*95c635efSGarrett D'Amore 
1632*95c635efSGarrett D'Amore 	rm = p->rmargin;
1633*95c635efSGarrett D'Amore 	rmax = p->maxrmargin;
1634*95c635efSGarrett D'Amore 	p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
1635*95c635efSGarrett D'Amore 
1636*95c635efSGarrett D'Amore 	for (nn = n->child; nn; nn = nn->next) {
1637*95c635efSGarrett D'Amore 		print_mdoc_node(p, pair, m, nn);
1638*95c635efSGarrett D'Amore 		/*
1639*95c635efSGarrett D'Amore 		 * If the printed node flushes its own line, then we
1640*95c635efSGarrett D'Amore 		 * needn't do it here as well.  This is hacky, but the
1641*95c635efSGarrett D'Amore 		 * notion of selective eoln whitespace is pretty dumb
1642*95c635efSGarrett D'Amore 		 * anyway, so don't sweat it.
1643*95c635efSGarrett D'Amore 		 */
1644*95c635efSGarrett D'Amore 		switch (nn->tok) {
1645*95c635efSGarrett D'Amore 		case (MDOC_Sm):
1646*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1647*95c635efSGarrett D'Amore 		case (MDOC_br):
1648*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1649*95c635efSGarrett D'Amore 		case (MDOC_sp):
1650*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1651*95c635efSGarrett D'Amore 		case (MDOC_Bl):
1652*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1653*95c635efSGarrett D'Amore 		case (MDOC_D1):
1654*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1655*95c635efSGarrett D'Amore 		case (MDOC_Dl):
1656*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1657*95c635efSGarrett D'Amore 		case (MDOC_Lp):
1658*95c635efSGarrett D'Amore 			/* FALLTHROUGH */
1659*95c635efSGarrett D'Amore 		case (MDOC_Pp):
1660*95c635efSGarrett D'Amore 			continue;
1661*95c635efSGarrett D'Amore 		default:
1662*95c635efSGarrett D'Amore 			break;
1663*95c635efSGarrett D'Amore 		}
1664*95c635efSGarrett D'Amore 		if (nn->next && nn->next->line == nn->line)
1665*95c635efSGarrett D'Amore 			continue;
1666*95c635efSGarrett D'Amore 		term_flushln(p);
1667*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1668*95c635efSGarrett D'Amore 	}
1669*95c635efSGarrett D'Amore 
1670*95c635efSGarrett D'Amore 	p->tabwidth = tabwidth;
1671*95c635efSGarrett D'Amore 	p->rmargin = rm;
1672*95c635efSGarrett D'Amore 	p->maxrmargin = rmax;
1673*95c635efSGarrett D'Amore 	return(0);
1674*95c635efSGarrett D'Amore }
1675*95c635efSGarrett D'Amore 
1676*95c635efSGarrett D'Amore 
1677*95c635efSGarrett D'Amore /* ARGSUSED */
1678*95c635efSGarrett D'Amore static void
1679*95c635efSGarrett D'Amore termp_bd_post(DECL_ARGS)
1680*95c635efSGarrett D'Amore {
1681*95c635efSGarrett D'Amore 	size_t		 rm, rmax;
1682*95c635efSGarrett D'Amore 
1683*95c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
1684*95c635efSGarrett D'Amore 		return;
1685*95c635efSGarrett D'Amore 
1686*95c635efSGarrett D'Amore 	rm = p->rmargin;
1687*95c635efSGarrett D'Amore 	rmax = p->maxrmargin;
1688*95c635efSGarrett D'Amore 
1689*95c635efSGarrett D'Amore 	if (DISP_literal == n->norm->Bd.type ||
1690*95c635efSGarrett D'Amore 			DISP_unfilled == n->norm->Bd.type)
1691*95c635efSGarrett D'Amore 		p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
1692*95c635efSGarrett D'Amore 
1693*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1694*95c635efSGarrett D'Amore 	term_newln(p);
1695*95c635efSGarrett D'Amore 
1696*95c635efSGarrett D'Amore 	p->rmargin = rm;
1697*95c635efSGarrett D'Amore 	p->maxrmargin = rmax;
1698*95c635efSGarrett D'Amore }
1699*95c635efSGarrett D'Amore 
1700*95c635efSGarrett D'Amore 
1701*95c635efSGarrett D'Amore /* ARGSUSED */
1702*95c635efSGarrett D'Amore static int
1703*95c635efSGarrett D'Amore termp_bx_pre(DECL_ARGS)
1704*95c635efSGarrett D'Amore {
1705*95c635efSGarrett D'Amore 
1706*95c635efSGarrett D'Amore 	if (NULL != (n = n->child)) {
1707*95c635efSGarrett D'Amore 		term_word(p, n->string);
1708*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1709*95c635efSGarrett D'Amore 		term_word(p, "BSD");
1710*95c635efSGarrett D'Amore 	} else {
1711*95c635efSGarrett D'Amore 		term_word(p, "BSD");
1712*95c635efSGarrett D'Amore 		return(0);
1713*95c635efSGarrett D'Amore 	}
1714*95c635efSGarrett D'Amore 
1715*95c635efSGarrett D'Amore 	if (NULL != (n = n->next)) {
1716*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1717*95c635efSGarrett D'Amore 		term_word(p, "-");
1718*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
1719*95c635efSGarrett D'Amore 		term_word(p, n->string);
1720*95c635efSGarrett D'Amore 	}
1721*95c635efSGarrett D'Amore 
1722*95c635efSGarrett D'Amore 	return(0);
1723*95c635efSGarrett D'Amore }
1724*95c635efSGarrett D'Amore 
1725*95c635efSGarrett D'Amore 
1726*95c635efSGarrett D'Amore /* ARGSUSED */
1727*95c635efSGarrett D'Amore static int
1728*95c635efSGarrett D'Amore termp_xx_pre(DECL_ARGS)
1729*95c635efSGarrett D'Amore {
1730*95c635efSGarrett D'Amore 	const char	*pp;
1731*95c635efSGarrett D'Amore 	int		 flags;
1732*95c635efSGarrett D'Amore 
1733*95c635efSGarrett D'Amore 	pp = NULL;
1734*95c635efSGarrett D'Amore 	switch (n->tok) {
1735*95c635efSGarrett D'Amore 	case (MDOC_Bsx):
1736*95c635efSGarrett D'Amore 		pp = "BSD/OS";
1737*95c635efSGarrett D'Amore 		break;
1738*95c635efSGarrett D'Amore 	case (MDOC_Dx):
1739*95c635efSGarrett D'Amore 		pp = "DragonFly";
1740*95c635efSGarrett D'Amore 		break;
1741*95c635efSGarrett D'Amore 	case (MDOC_Fx):
1742*95c635efSGarrett D'Amore 		pp = "FreeBSD";
1743*95c635efSGarrett D'Amore 		break;
1744*95c635efSGarrett D'Amore 	case (MDOC_Nx):
1745*95c635efSGarrett D'Amore 		pp = "NetBSD";
1746*95c635efSGarrett D'Amore 		break;
1747*95c635efSGarrett D'Amore 	case (MDOC_Ox):
1748*95c635efSGarrett D'Amore 		pp = "OpenBSD";
1749*95c635efSGarrett D'Amore 		break;
1750*95c635efSGarrett D'Amore 	case (MDOC_Ux):
1751*95c635efSGarrett D'Amore 		pp = "UNIX";
1752*95c635efSGarrett D'Amore 		break;
1753*95c635efSGarrett D'Amore 	default:
1754*95c635efSGarrett D'Amore 		break;
1755*95c635efSGarrett D'Amore 	}
1756*95c635efSGarrett D'Amore 
1757*95c635efSGarrett D'Amore 	term_word(p, pp);
1758*95c635efSGarrett D'Amore 	if (n->child) {
1759*95c635efSGarrett D'Amore 		flags = p->flags;
1760*95c635efSGarrett D'Amore 		p->flags |= TERMP_KEEP;
1761*95c635efSGarrett D'Amore 		term_word(p, n->child->string);
1762*95c635efSGarrett D'Amore 		p->flags = flags;
1763*95c635efSGarrett D'Amore 	}
1764*95c635efSGarrett D'Amore 	return(0);
1765*95c635efSGarrett D'Amore }
1766*95c635efSGarrett D'Amore 
1767*95c635efSGarrett D'Amore 
1768*95c635efSGarrett D'Amore /* ARGSUSED */
1769*95c635efSGarrett D'Amore static int
1770*95c635efSGarrett D'Amore termp_igndelim_pre(DECL_ARGS)
1771*95c635efSGarrett D'Amore {
1772*95c635efSGarrett D'Amore 
1773*95c635efSGarrett D'Amore 	p->flags |= TERMP_IGNDELIM;
1774*95c635efSGarrett D'Amore 	return(1);
1775*95c635efSGarrett D'Amore }
1776*95c635efSGarrett D'Amore 
1777*95c635efSGarrett D'Amore 
1778*95c635efSGarrett D'Amore /* ARGSUSED */
1779*95c635efSGarrett D'Amore static void
1780*95c635efSGarrett D'Amore termp_pf_post(DECL_ARGS)
1781*95c635efSGarrett D'Amore {
1782*95c635efSGarrett D'Amore 
1783*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1784*95c635efSGarrett D'Amore }
1785*95c635efSGarrett D'Amore 
1786*95c635efSGarrett D'Amore 
1787*95c635efSGarrett D'Amore /* ARGSUSED */
1788*95c635efSGarrett D'Amore static int
1789*95c635efSGarrett D'Amore termp_ss_pre(DECL_ARGS)
1790*95c635efSGarrett D'Amore {
1791*95c635efSGarrett D'Amore 
1792*95c635efSGarrett D'Amore 	switch (n->type) {
1793*95c635efSGarrett D'Amore 	case (MDOC_BLOCK):
1794*95c635efSGarrett D'Amore 		term_newln(p);
1795*95c635efSGarrett D'Amore 		if (n->prev)
1796*95c635efSGarrett D'Amore 			term_vspace(p);
1797*95c635efSGarrett D'Amore 		break;
1798*95c635efSGarrett D'Amore 	case (MDOC_HEAD):
1799*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1800*95c635efSGarrett D'Amore 		p->offset = term_len(p, (p->defindent+1)/2);
1801*95c635efSGarrett D'Amore 		break;
1802*95c635efSGarrett D'Amore 	default:
1803*95c635efSGarrett D'Amore 		break;
1804*95c635efSGarrett D'Amore 	}
1805*95c635efSGarrett D'Amore 
1806*95c635efSGarrett D'Amore 	return(1);
1807*95c635efSGarrett D'Amore }
1808*95c635efSGarrett D'Amore 
1809*95c635efSGarrett D'Amore 
1810*95c635efSGarrett D'Amore /* ARGSUSED */
1811*95c635efSGarrett D'Amore static void
1812*95c635efSGarrett D'Amore termp_ss_post(DECL_ARGS)
1813*95c635efSGarrett D'Amore {
1814*95c635efSGarrett D'Amore 
1815*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
1816*95c635efSGarrett D'Amore 		term_newln(p);
1817*95c635efSGarrett D'Amore }
1818*95c635efSGarrett D'Amore 
1819*95c635efSGarrett D'Amore 
1820*95c635efSGarrett D'Amore /* ARGSUSED */
1821*95c635efSGarrett D'Amore static int
1822*95c635efSGarrett D'Amore termp_cd_pre(DECL_ARGS)
1823*95c635efSGarrett D'Amore {
1824*95c635efSGarrett D'Amore 
1825*95c635efSGarrett D'Amore 	synopsis_pre(p, n);
1826*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
1827*95c635efSGarrett D'Amore 	return(1);
1828*95c635efSGarrett D'Amore }
1829*95c635efSGarrett D'Amore 
1830*95c635efSGarrett D'Amore 
1831*95c635efSGarrett D'Amore /* ARGSUSED */
1832*95c635efSGarrett D'Amore static int
1833*95c635efSGarrett D'Amore termp_in_pre(DECL_ARGS)
1834*95c635efSGarrett D'Amore {
1835*95c635efSGarrett D'Amore 
1836*95c635efSGarrett D'Amore 	synopsis_pre(p, n);
1837*95c635efSGarrett D'Amore 
1838*95c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags) {
1839*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1840*95c635efSGarrett D'Amore 		term_word(p, "#include");
1841*95c635efSGarrett D'Amore 		term_word(p, "<");
1842*95c635efSGarrett D'Amore 	} else {
1843*95c635efSGarrett D'Amore 		term_word(p, "<");
1844*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
1845*95c635efSGarrett D'Amore 	}
1846*95c635efSGarrett D'Amore 
1847*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1848*95c635efSGarrett D'Amore 	return(1);
1849*95c635efSGarrett D'Amore }
1850*95c635efSGarrett D'Amore 
1851*95c635efSGarrett D'Amore 
1852*95c635efSGarrett D'Amore /* ARGSUSED */
1853*95c635efSGarrett D'Amore static void
1854*95c635efSGarrett D'Amore termp_in_post(DECL_ARGS)
1855*95c635efSGarrett D'Amore {
1856*95c635efSGarrett D'Amore 
1857*95c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
1858*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
1859*95c635efSGarrett D'Amore 
1860*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1861*95c635efSGarrett D'Amore 	term_word(p, ">");
1862*95c635efSGarrett D'Amore 
1863*95c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags)
1864*95c635efSGarrett D'Amore 		term_fontpop(p);
1865*95c635efSGarrett D'Amore }
1866*95c635efSGarrett D'Amore 
1867*95c635efSGarrett D'Amore 
1868*95c635efSGarrett D'Amore /* ARGSUSED */
1869*95c635efSGarrett D'Amore static int
1870*95c635efSGarrett D'Amore termp_sp_pre(DECL_ARGS)
1871*95c635efSGarrett D'Amore {
1872*95c635efSGarrett D'Amore 	size_t		 i, len;
1873*95c635efSGarrett D'Amore 
1874*95c635efSGarrett D'Amore 	switch (n->tok) {
1875*95c635efSGarrett D'Amore 	case (MDOC_sp):
1876*95c635efSGarrett D'Amore 		len = n->child ? a2height(p, n->child->string) : 1;
1877*95c635efSGarrett D'Amore 		break;
1878*95c635efSGarrett D'Amore 	case (MDOC_br):
1879*95c635efSGarrett D'Amore 		len = 0;
1880*95c635efSGarrett D'Amore 		break;
1881*95c635efSGarrett D'Amore 	default:
1882*95c635efSGarrett D'Amore 		len = 1;
1883*95c635efSGarrett D'Amore 		break;
1884*95c635efSGarrett D'Amore 	}
1885*95c635efSGarrett D'Amore 
1886*95c635efSGarrett D'Amore 	if (0 == len)
1887*95c635efSGarrett D'Amore 		term_newln(p);
1888*95c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
1889*95c635efSGarrett D'Amore 		term_vspace(p);
1890*95c635efSGarrett D'Amore 
1891*95c635efSGarrett D'Amore 	return(0);
1892*95c635efSGarrett D'Amore }
1893*95c635efSGarrett D'Amore 
1894*95c635efSGarrett D'Amore 
1895*95c635efSGarrett D'Amore /* ARGSUSED */
1896*95c635efSGarrett D'Amore static int
1897*95c635efSGarrett D'Amore termp_quote_pre(DECL_ARGS)
1898*95c635efSGarrett D'Amore {
1899*95c635efSGarrett D'Amore 
1900*95c635efSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
1901*95c635efSGarrett D'Amore 		return(1);
1902*95c635efSGarrett D'Amore 
1903*95c635efSGarrett D'Amore 	switch (n->tok) {
1904*95c635efSGarrett D'Amore 	case (MDOC_Ao):
1905*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1906*95c635efSGarrett D'Amore 	case (MDOC_Aq):
1907*95c635efSGarrett D'Amore 		term_word(p, "<");
1908*95c635efSGarrett D'Amore 		break;
1909*95c635efSGarrett D'Amore 	case (MDOC_Bro):
1910*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1911*95c635efSGarrett D'Amore 	case (MDOC_Brq):
1912*95c635efSGarrett D'Amore 		term_word(p, "{");
1913*95c635efSGarrett D'Amore 		break;
1914*95c635efSGarrett D'Amore 	case (MDOC_Oo):
1915*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1916*95c635efSGarrett D'Amore 	case (MDOC_Op):
1917*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1918*95c635efSGarrett D'Amore 	case (MDOC_Bo):
1919*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1920*95c635efSGarrett D'Amore 	case (MDOC_Bq):
1921*95c635efSGarrett D'Amore 		term_word(p, "[");
1922*95c635efSGarrett D'Amore 		break;
1923*95c635efSGarrett D'Amore 	case (MDOC_Do):
1924*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1925*95c635efSGarrett D'Amore 	case (MDOC_Dq):
1926*95c635efSGarrett D'Amore 		term_word(p, "``");
1927*95c635efSGarrett D'Amore 		break;
1928*95c635efSGarrett D'Amore 	case (MDOC_Eo):
1929*95c635efSGarrett D'Amore 		break;
1930*95c635efSGarrett D'Amore 	case (MDOC_Po):
1931*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1932*95c635efSGarrett D'Amore 	case (MDOC_Pq):
1933*95c635efSGarrett D'Amore 		term_word(p, "(");
1934*95c635efSGarrett D'Amore 		break;
1935*95c635efSGarrett D'Amore 	case (MDOC__T):
1936*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1937*95c635efSGarrett D'Amore 	case (MDOC_Qo):
1938*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1939*95c635efSGarrett D'Amore 	case (MDOC_Qq):
1940*95c635efSGarrett D'Amore 		term_word(p, "\"");
1941*95c635efSGarrett D'Amore 		break;
1942*95c635efSGarrett D'Amore 	case (MDOC_Ql):
1943*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1944*95c635efSGarrett D'Amore 	case (MDOC_So):
1945*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1946*95c635efSGarrett D'Amore 	case (MDOC_Sq):
1947*95c635efSGarrett D'Amore 		term_word(p, "`");
1948*95c635efSGarrett D'Amore 		break;
1949*95c635efSGarrett D'Amore 	default:
1950*95c635efSGarrett D'Amore 		abort();
1951*95c635efSGarrett D'Amore 		/* NOTREACHED */
1952*95c635efSGarrett D'Amore 	}
1953*95c635efSGarrett D'Amore 
1954*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1955*95c635efSGarrett D'Amore 	return(1);
1956*95c635efSGarrett D'Amore }
1957*95c635efSGarrett D'Amore 
1958*95c635efSGarrett D'Amore 
1959*95c635efSGarrett D'Amore /* ARGSUSED */
1960*95c635efSGarrett D'Amore static void
1961*95c635efSGarrett D'Amore termp_quote_post(DECL_ARGS)
1962*95c635efSGarrett D'Amore {
1963*95c635efSGarrett D'Amore 
1964*95c635efSGarrett D'Amore 	if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
1965*95c635efSGarrett D'Amore 		return;
1966*95c635efSGarrett D'Amore 
1967*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
1968*95c635efSGarrett D'Amore 
1969*95c635efSGarrett D'Amore 	switch (n->tok) {
1970*95c635efSGarrett D'Amore 	case (MDOC_Ao):
1971*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1972*95c635efSGarrett D'Amore 	case (MDOC_Aq):
1973*95c635efSGarrett D'Amore 		term_word(p, ">");
1974*95c635efSGarrett D'Amore 		break;
1975*95c635efSGarrett D'Amore 	case (MDOC_Bro):
1976*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1977*95c635efSGarrett D'Amore 	case (MDOC_Brq):
1978*95c635efSGarrett D'Amore 		term_word(p, "}");
1979*95c635efSGarrett D'Amore 		break;
1980*95c635efSGarrett D'Amore 	case (MDOC_Oo):
1981*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1982*95c635efSGarrett D'Amore 	case (MDOC_Op):
1983*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1984*95c635efSGarrett D'Amore 	case (MDOC_Bo):
1985*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1986*95c635efSGarrett D'Amore 	case (MDOC_Bq):
1987*95c635efSGarrett D'Amore 		term_word(p, "]");
1988*95c635efSGarrett D'Amore 		break;
1989*95c635efSGarrett D'Amore 	case (MDOC_Do):
1990*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1991*95c635efSGarrett D'Amore 	case (MDOC_Dq):
1992*95c635efSGarrett D'Amore 		term_word(p, "''");
1993*95c635efSGarrett D'Amore 		break;
1994*95c635efSGarrett D'Amore 	case (MDOC_Eo):
1995*95c635efSGarrett D'Amore 		break;
1996*95c635efSGarrett D'Amore 	case (MDOC_Po):
1997*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
1998*95c635efSGarrett D'Amore 	case (MDOC_Pq):
1999*95c635efSGarrett D'Amore 		term_word(p, ")");
2000*95c635efSGarrett D'Amore 		break;
2001*95c635efSGarrett D'Amore 	case (MDOC__T):
2002*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
2003*95c635efSGarrett D'Amore 	case (MDOC_Qo):
2004*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
2005*95c635efSGarrett D'Amore 	case (MDOC_Qq):
2006*95c635efSGarrett D'Amore 		term_word(p, "\"");
2007*95c635efSGarrett D'Amore 		break;
2008*95c635efSGarrett D'Amore 	case (MDOC_Ql):
2009*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
2010*95c635efSGarrett D'Amore 	case (MDOC_So):
2011*95c635efSGarrett D'Amore 		/* FALLTHROUGH */
2012*95c635efSGarrett D'Amore 	case (MDOC_Sq):
2013*95c635efSGarrett D'Amore 		term_word(p, "'");
2014*95c635efSGarrett D'Amore 		break;
2015*95c635efSGarrett D'Amore 	default:
2016*95c635efSGarrett D'Amore 		abort();
2017*95c635efSGarrett D'Amore 		/* NOTREACHED */
2018*95c635efSGarrett D'Amore 	}
2019*95c635efSGarrett D'Amore }
2020*95c635efSGarrett D'Amore 
2021*95c635efSGarrett D'Amore 
2022*95c635efSGarrett D'Amore /* ARGSUSED */
2023*95c635efSGarrett D'Amore static int
2024*95c635efSGarrett D'Amore termp_fo_pre(DECL_ARGS)
2025*95c635efSGarrett D'Amore {
2026*95c635efSGarrett D'Amore 
2027*95c635efSGarrett D'Amore 	if (MDOC_BLOCK == n->type) {
2028*95c635efSGarrett D'Amore 		synopsis_pre(p, n);
2029*95c635efSGarrett D'Amore 		return(1);
2030*95c635efSGarrett D'Amore 	} else if (MDOC_BODY == n->type) {
2031*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
2032*95c635efSGarrett D'Amore 		term_word(p, "(");
2033*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
2034*95c635efSGarrett D'Amore 		return(1);
2035*95c635efSGarrett D'Amore 	}
2036*95c635efSGarrett D'Amore 
2037*95c635efSGarrett D'Amore 	if (NULL == n->child)
2038*95c635efSGarrett D'Amore 		return(0);
2039*95c635efSGarrett D'Amore 
2040*95c635efSGarrett D'Amore 	/* XXX: we drop non-initial arguments as per groff. */
2041*95c635efSGarrett D'Amore 
2042*95c635efSGarrett D'Amore 	assert(n->child->string);
2043*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
2044*95c635efSGarrett D'Amore 	term_word(p, n->child->string);
2045*95c635efSGarrett D'Amore 	return(0);
2046*95c635efSGarrett D'Amore }
2047*95c635efSGarrett D'Amore 
2048*95c635efSGarrett D'Amore 
2049*95c635efSGarrett D'Amore /* ARGSUSED */
2050*95c635efSGarrett D'Amore static void
2051*95c635efSGarrett D'Amore termp_fo_post(DECL_ARGS)
2052*95c635efSGarrett D'Amore {
2053*95c635efSGarrett D'Amore 
2054*95c635efSGarrett D'Amore 	if (MDOC_BODY != n->type)
2055*95c635efSGarrett D'Amore 		return;
2056*95c635efSGarrett D'Amore 
2057*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
2058*95c635efSGarrett D'Amore 	term_word(p, ")");
2059*95c635efSGarrett D'Amore 
2060*95c635efSGarrett D'Amore 	if (MDOC_SYNPRETTY & n->flags) {
2061*95c635efSGarrett D'Amore 		p->flags |= TERMP_NOSPACE;
2062*95c635efSGarrett D'Amore 		term_word(p, ";");
2063*95c635efSGarrett D'Amore 	}
2064*95c635efSGarrett D'Amore }
2065*95c635efSGarrett D'Amore 
2066*95c635efSGarrett D'Amore 
2067*95c635efSGarrett D'Amore /* ARGSUSED */
2068*95c635efSGarrett D'Amore static int
2069*95c635efSGarrett D'Amore termp_bf_pre(DECL_ARGS)
2070*95c635efSGarrett D'Amore {
2071*95c635efSGarrett D'Amore 
2072*95c635efSGarrett D'Amore 	if (MDOC_HEAD == n->type)
2073*95c635efSGarrett D'Amore 		return(0);
2074*95c635efSGarrett D'Amore 	else if (MDOC_BLOCK != n->type)
2075*95c635efSGarrett D'Amore 		return(1);
2076*95c635efSGarrett D'Amore 
2077*95c635efSGarrett D'Amore 	if (FONT_Em == n->norm->Bf.font)
2078*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_UNDER);
2079*95c635efSGarrett D'Amore 	else if (FONT_Sy == n->norm->Bf.font)
2080*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_BOLD);
2081*95c635efSGarrett D'Amore 	else
2082*95c635efSGarrett D'Amore 		term_fontpush(p, TERMFONT_NONE);
2083*95c635efSGarrett D'Amore 
2084*95c635efSGarrett D'Amore 	return(1);
2085*95c635efSGarrett D'Amore }
2086*95c635efSGarrett D'Amore 
2087*95c635efSGarrett D'Amore 
2088*95c635efSGarrett D'Amore /* ARGSUSED */
2089*95c635efSGarrett D'Amore static int
2090*95c635efSGarrett D'Amore termp_sm_pre(DECL_ARGS)
2091*95c635efSGarrett D'Amore {
2092*95c635efSGarrett D'Amore 
2093*95c635efSGarrett D'Amore 	assert(n->child && MDOC_TEXT == n->child->type);
2094*95c635efSGarrett D'Amore 	if (0 == strcmp("on", n->child->string)) {
2095*95c635efSGarrett D'Amore 		if (p->col)
2096*95c635efSGarrett D'Amore 			p->flags &= ~TERMP_NOSPACE;
2097*95c635efSGarrett D'Amore 		p->flags &= ~TERMP_NONOSPACE;
2098*95c635efSGarrett D'Amore 	} else
2099*95c635efSGarrett D'Amore 		p->flags |= TERMP_NONOSPACE;
2100*95c635efSGarrett D'Amore 
2101*95c635efSGarrett D'Amore 	return(0);
2102*95c635efSGarrett D'Amore }
2103*95c635efSGarrett D'Amore 
2104*95c635efSGarrett D'Amore 
2105*95c635efSGarrett D'Amore /* ARGSUSED */
2106*95c635efSGarrett D'Amore static int
2107*95c635efSGarrett D'Amore termp_ap_pre(DECL_ARGS)
2108*95c635efSGarrett D'Amore {
2109*95c635efSGarrett D'Amore 
2110*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
2111*95c635efSGarrett D'Amore 	term_word(p, "'");
2112*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
2113*95c635efSGarrett D'Amore 	return(1);
2114*95c635efSGarrett D'Amore }
2115*95c635efSGarrett D'Amore 
2116*95c635efSGarrett D'Amore 
2117*95c635efSGarrett D'Amore /* ARGSUSED */
2118*95c635efSGarrett D'Amore static void
2119*95c635efSGarrett D'Amore termp____post(DECL_ARGS)
2120*95c635efSGarrett D'Amore {
2121*95c635efSGarrett D'Amore 
2122*95c635efSGarrett D'Amore 	/*
2123*95c635efSGarrett D'Amore 	 * Handle lists of authors.  In general, print each followed by
2124*95c635efSGarrett D'Amore 	 * a comma.  Don't print the comma if there are only two
2125*95c635efSGarrett D'Amore 	 * authors.
2126*95c635efSGarrett D'Amore 	 */
2127*95c635efSGarrett D'Amore 	if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
2128*95c635efSGarrett D'Amore 		if (NULL == n->next->next || MDOC__A != n->next->next->tok)
2129*95c635efSGarrett D'Amore 			if (NULL == n->prev || MDOC__A != n->prev->tok)
2130*95c635efSGarrett D'Amore 				return;
2131*95c635efSGarrett D'Amore 
2132*95c635efSGarrett D'Amore 	/* TODO: %U. */
2133*95c635efSGarrett D'Amore 
2134*95c635efSGarrett D'Amore 	if (NULL == n->parent || MDOC_Rs != n->parent->tok)
2135*95c635efSGarrett D'Amore 		return;
2136*95c635efSGarrett D'Amore 
2137*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
2138*95c635efSGarrett D'Amore 	if (NULL == n->next) {
2139*95c635efSGarrett D'Amore 		term_word(p, ".");
2140*95c635efSGarrett D'Amore 		p->flags |= TERMP_SENTENCE;
2141*95c635efSGarrett D'Amore 	} else
2142*95c635efSGarrett D'Amore 		term_word(p, ",");
2143*95c635efSGarrett D'Amore }
2144*95c635efSGarrett D'Amore 
2145*95c635efSGarrett D'Amore 
2146*95c635efSGarrett D'Amore /* ARGSUSED */
2147*95c635efSGarrett D'Amore static int
2148*95c635efSGarrett D'Amore termp_li_pre(DECL_ARGS)
2149*95c635efSGarrett D'Amore {
2150*95c635efSGarrett D'Amore 
2151*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_NONE);
2152*95c635efSGarrett D'Amore 	return(1);
2153*95c635efSGarrett D'Amore }
2154*95c635efSGarrett D'Amore 
2155*95c635efSGarrett D'Amore 
2156*95c635efSGarrett D'Amore /* ARGSUSED */
2157*95c635efSGarrett D'Amore static int
2158*95c635efSGarrett D'Amore termp_lk_pre(DECL_ARGS)
2159*95c635efSGarrett D'Amore {
2160*95c635efSGarrett D'Amore 	const struct mdoc_node *nn, *sv;
2161*95c635efSGarrett D'Amore 
2162*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
2163*95c635efSGarrett D'Amore 
2164*95c635efSGarrett D'Amore 	nn = sv = n->child;
2165*95c635efSGarrett D'Amore 
2166*95c635efSGarrett D'Amore 	if (NULL == nn || NULL == nn->next)
2167*95c635efSGarrett D'Amore 		return(1);
2168*95c635efSGarrett D'Amore 
2169*95c635efSGarrett D'Amore 	for (nn = nn->next; nn; nn = nn->next)
2170*95c635efSGarrett D'Amore 		term_word(p, nn->string);
2171*95c635efSGarrett D'Amore 
2172*95c635efSGarrett D'Amore 	term_fontpop(p);
2173*95c635efSGarrett D'Amore 
2174*95c635efSGarrett D'Amore 	p->flags |= TERMP_NOSPACE;
2175*95c635efSGarrett D'Amore 	term_word(p, ":");
2176*95c635efSGarrett D'Amore 
2177*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_BOLD);
2178*95c635efSGarrett D'Amore 	term_word(p, sv->string);
2179*95c635efSGarrett D'Amore 	term_fontpop(p);
2180*95c635efSGarrett D'Amore 
2181*95c635efSGarrett D'Amore 	return(0);
2182*95c635efSGarrett D'Amore }
2183*95c635efSGarrett D'Amore 
2184*95c635efSGarrett D'Amore 
2185*95c635efSGarrett D'Amore /* ARGSUSED */
2186*95c635efSGarrett D'Amore static int
2187*95c635efSGarrett D'Amore termp_bk_pre(DECL_ARGS)
2188*95c635efSGarrett D'Amore {
2189*95c635efSGarrett D'Amore 
2190*95c635efSGarrett D'Amore 	switch (n->type) {
2191*95c635efSGarrett D'Amore 	case (MDOC_BLOCK):
2192*95c635efSGarrett D'Amore 		break;
2193*95c635efSGarrett D'Amore 	case (MDOC_HEAD):
2194*95c635efSGarrett D'Amore 		return(0);
2195*95c635efSGarrett D'Amore 	case (MDOC_BODY):
2196*95c635efSGarrett D'Amore 		if (n->parent->args || 0 == n->prev->nchild)
2197*95c635efSGarrett D'Amore 			p->flags |= TERMP_PREKEEP;
2198*95c635efSGarrett D'Amore 		break;
2199*95c635efSGarrett D'Amore 	default:
2200*95c635efSGarrett D'Amore 		abort();
2201*95c635efSGarrett D'Amore 		/* NOTREACHED */
2202*95c635efSGarrett D'Amore 	}
2203*95c635efSGarrett D'Amore 
2204*95c635efSGarrett D'Amore 	return(1);
2205*95c635efSGarrett D'Amore }
2206*95c635efSGarrett D'Amore 
2207*95c635efSGarrett D'Amore 
2208*95c635efSGarrett D'Amore /* ARGSUSED */
2209*95c635efSGarrett D'Amore static void
2210*95c635efSGarrett D'Amore termp_bk_post(DECL_ARGS)
2211*95c635efSGarrett D'Amore {
2212*95c635efSGarrett D'Amore 
2213*95c635efSGarrett D'Amore 	if (MDOC_BODY == n->type)
2214*95c635efSGarrett D'Amore 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
2215*95c635efSGarrett D'Amore }
2216*95c635efSGarrett D'Amore 
2217*95c635efSGarrett D'Amore /* ARGSUSED */
2218*95c635efSGarrett D'Amore static void
2219*95c635efSGarrett D'Amore termp__t_post(DECL_ARGS)
2220*95c635efSGarrett D'Amore {
2221*95c635efSGarrett D'Amore 
2222*95c635efSGarrett D'Amore 	/*
2223*95c635efSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
2224*95c635efSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
2225*95c635efSGarrett D'Amore 	 */
2226*95c635efSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
2227*95c635efSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2228*95c635efSGarrett D'Amore 		termp_quote_post(p, pair, m, n);
2229*95c635efSGarrett D'Amore 
2230*95c635efSGarrett D'Amore 	termp____post(p, pair, m, n);
2231*95c635efSGarrett D'Amore }
2232*95c635efSGarrett D'Amore 
2233*95c635efSGarrett D'Amore /* ARGSUSED */
2234*95c635efSGarrett D'Amore static int
2235*95c635efSGarrett D'Amore termp__t_pre(DECL_ARGS)
2236*95c635efSGarrett D'Amore {
2237*95c635efSGarrett D'Amore 
2238*95c635efSGarrett D'Amore 	/*
2239*95c635efSGarrett D'Amore 	 * If we're in an `Rs' and there's a journal present, then quote
2240*95c635efSGarrett D'Amore 	 * us instead of underlining us (for disambiguation).
2241*95c635efSGarrett D'Amore 	 */
2242*95c635efSGarrett D'Amore 	if (n->parent && MDOC_Rs == n->parent->tok &&
2243*95c635efSGarrett D'Amore 			n->parent->norm->Rs.quote_T)
2244*95c635efSGarrett D'Amore 		return(termp_quote_pre(p, pair, m, n));
2245*95c635efSGarrett D'Amore 
2246*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
2247*95c635efSGarrett D'Amore 	return(1);
2248*95c635efSGarrett D'Amore }
2249*95c635efSGarrett D'Amore 
2250*95c635efSGarrett D'Amore /* ARGSUSED */
2251*95c635efSGarrett D'Amore static int
2252*95c635efSGarrett D'Amore termp_under_pre(DECL_ARGS)
2253*95c635efSGarrett D'Amore {
2254*95c635efSGarrett D'Amore 
2255*95c635efSGarrett D'Amore 	term_fontpush(p, TERMFONT_UNDER);
2256*95c635efSGarrett D'Amore 	return(1);
2257*95c635efSGarrett D'Amore }
2258