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