xref: /freebsd/contrib/mandoc/mdoc_term.c (revision 6d38604fc532a3fc060788e3ce40464b46047eaf)
1*6d38604fSBaptiste Daroussin /* $Id: mdoc_term.c,v 1.380 2020/04/06 10:16:17 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
3*6d38604fSBaptiste Daroussin  * Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
561d06d6bSBaptiste Daroussin  * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
661d06d6bSBaptiste Daroussin  *
761d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
861d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
961d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
1061d06d6bSBaptiste Daroussin  *
1161d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1261d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1361d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1461d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1561d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1661d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1761d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*6d38604fSBaptiste Daroussin  *
19*6d38604fSBaptiste Daroussin  * Plain text formatter for mdoc(7), used by mandoc(1)
20*6d38604fSBaptiste Daroussin  * for ASCII, UTF-8, PostScript, and PDF output.
2161d06d6bSBaptiste Daroussin  */
2261d06d6bSBaptiste Daroussin #include "config.h"
2361d06d6bSBaptiste Daroussin 
2461d06d6bSBaptiste Daroussin #include <sys/types.h>
2561d06d6bSBaptiste Daroussin 
2661d06d6bSBaptiste Daroussin #include <assert.h>
2761d06d6bSBaptiste Daroussin #include <ctype.h>
2861d06d6bSBaptiste Daroussin #include <limits.h>
2961d06d6bSBaptiste Daroussin #include <stdint.h>
3061d06d6bSBaptiste Daroussin #include <stdio.h>
3161d06d6bSBaptiste Daroussin #include <stdlib.h>
3261d06d6bSBaptiste Daroussin #include <string.h>
3361d06d6bSBaptiste Daroussin 
3461d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
3561d06d6bSBaptiste Daroussin #include "roff.h"
3661d06d6bSBaptiste Daroussin #include "mdoc.h"
3761d06d6bSBaptiste Daroussin #include "out.h"
3861d06d6bSBaptiste Daroussin #include "term.h"
39*6d38604fSBaptiste Daroussin #include "term_tag.h"
4061d06d6bSBaptiste Daroussin #include "main.h"
4161d06d6bSBaptiste Daroussin 
4261d06d6bSBaptiste Daroussin struct	termpair {
4361d06d6bSBaptiste Daroussin 	struct termpair	 *ppair;
4461d06d6bSBaptiste Daroussin 	int		  count;
4561d06d6bSBaptiste Daroussin };
4661d06d6bSBaptiste Daroussin 
4761d06d6bSBaptiste Daroussin #define	DECL_ARGS struct termp *p, \
4861d06d6bSBaptiste Daroussin 		  struct termpair *pair, \
4961d06d6bSBaptiste Daroussin 		  const struct roff_meta *meta, \
5061d06d6bSBaptiste Daroussin 		  struct roff_node *n
5161d06d6bSBaptiste Daroussin 
527295610fSBaptiste Daroussin struct	mdoc_term_act {
5361d06d6bSBaptiste Daroussin 	int	(*pre)(DECL_ARGS);
5461d06d6bSBaptiste Daroussin 	void	(*post)(DECL_ARGS);
5561d06d6bSBaptiste Daroussin };
5661d06d6bSBaptiste Daroussin 
5761d06d6bSBaptiste Daroussin static	int	  a2width(const struct termp *, const char *);
5861d06d6bSBaptiste Daroussin 
5961d06d6bSBaptiste Daroussin static	void	  print_bvspace(struct termp *,
60*6d38604fSBaptiste Daroussin 			struct roff_node *, struct roff_node *);
6161d06d6bSBaptiste Daroussin static	void	  print_mdoc_node(DECL_ARGS);
6261d06d6bSBaptiste Daroussin static	void	  print_mdoc_nodelist(DECL_ARGS);
6361d06d6bSBaptiste Daroussin static	void	  print_mdoc_head(struct termp *, const struct roff_meta *);
6461d06d6bSBaptiste Daroussin static	void	  print_mdoc_foot(struct termp *, const struct roff_meta *);
65*6d38604fSBaptiste Daroussin static	void	  synopsis_pre(struct termp *, struct roff_node *);
6661d06d6bSBaptiste Daroussin 
6761d06d6bSBaptiste Daroussin static	void	  termp____post(DECL_ARGS);
6861d06d6bSBaptiste Daroussin static	void	  termp__t_post(DECL_ARGS);
6961d06d6bSBaptiste Daroussin static	void	  termp_bd_post(DECL_ARGS);
7061d06d6bSBaptiste Daroussin static	void	  termp_bk_post(DECL_ARGS);
7161d06d6bSBaptiste Daroussin static	void	  termp_bl_post(DECL_ARGS);
7261d06d6bSBaptiste Daroussin static	void	  termp_eo_post(DECL_ARGS);
7361d06d6bSBaptiste Daroussin static	void	  termp_fd_post(DECL_ARGS);
7461d06d6bSBaptiste Daroussin static	void	  termp_fo_post(DECL_ARGS);
7561d06d6bSBaptiste Daroussin static	void	  termp_in_post(DECL_ARGS);
7661d06d6bSBaptiste Daroussin static	void	  termp_it_post(DECL_ARGS);
7761d06d6bSBaptiste Daroussin static	void	  termp_lb_post(DECL_ARGS);
7861d06d6bSBaptiste Daroussin static	void	  termp_nm_post(DECL_ARGS);
7961d06d6bSBaptiste Daroussin static	void	  termp_pf_post(DECL_ARGS);
8061d06d6bSBaptiste Daroussin static	void	  termp_quote_post(DECL_ARGS);
8161d06d6bSBaptiste Daroussin static	void	  termp_sh_post(DECL_ARGS);
8261d06d6bSBaptiste Daroussin static	void	  termp_ss_post(DECL_ARGS);
8361d06d6bSBaptiste Daroussin static	void	  termp_xx_post(DECL_ARGS);
8461d06d6bSBaptiste Daroussin 
8561d06d6bSBaptiste Daroussin static	int	  termp__a_pre(DECL_ARGS);
8661d06d6bSBaptiste Daroussin static	int	  termp__t_pre(DECL_ARGS);
877295610fSBaptiste Daroussin static	int	  termp_abort_pre(DECL_ARGS);
8861d06d6bSBaptiste Daroussin static	int	  termp_an_pre(DECL_ARGS);
8961d06d6bSBaptiste Daroussin static	int	  termp_ap_pre(DECL_ARGS);
9061d06d6bSBaptiste Daroussin static	int	  termp_bd_pre(DECL_ARGS);
9161d06d6bSBaptiste Daroussin static	int	  termp_bf_pre(DECL_ARGS);
9261d06d6bSBaptiste Daroussin static	int	  termp_bk_pre(DECL_ARGS);
9361d06d6bSBaptiste Daroussin static	int	  termp_bl_pre(DECL_ARGS);
9461d06d6bSBaptiste Daroussin static	int	  termp_bold_pre(DECL_ARGS);
9561d06d6bSBaptiste Daroussin static	int	  termp_d1_pre(DECL_ARGS);
9661d06d6bSBaptiste Daroussin static	int	  termp_eo_pre(DECL_ARGS);
9761d06d6bSBaptiste Daroussin static	int	  termp_ex_pre(DECL_ARGS);
9861d06d6bSBaptiste Daroussin static	int	  termp_fa_pre(DECL_ARGS);
9961d06d6bSBaptiste Daroussin static	int	  termp_fd_pre(DECL_ARGS);
10061d06d6bSBaptiste Daroussin static	int	  termp_fl_pre(DECL_ARGS);
10161d06d6bSBaptiste Daroussin static	int	  termp_fn_pre(DECL_ARGS);
10261d06d6bSBaptiste Daroussin static	int	  termp_fo_pre(DECL_ARGS);
10361d06d6bSBaptiste Daroussin static	int	  termp_ft_pre(DECL_ARGS);
10461d06d6bSBaptiste Daroussin static	int	  termp_in_pre(DECL_ARGS);
10561d06d6bSBaptiste Daroussin static	int	  termp_it_pre(DECL_ARGS);
10661d06d6bSBaptiste Daroussin static	int	  termp_li_pre(DECL_ARGS);
10761d06d6bSBaptiste Daroussin static	int	  termp_lk_pre(DECL_ARGS);
10861d06d6bSBaptiste Daroussin static	int	  termp_nd_pre(DECL_ARGS);
10961d06d6bSBaptiste Daroussin static	int	  termp_nm_pre(DECL_ARGS);
11061d06d6bSBaptiste Daroussin static	int	  termp_ns_pre(DECL_ARGS);
11161d06d6bSBaptiste Daroussin static	int	  termp_quote_pre(DECL_ARGS);
11261d06d6bSBaptiste Daroussin static	int	  termp_rs_pre(DECL_ARGS);
11361d06d6bSBaptiste Daroussin static	int	  termp_sh_pre(DECL_ARGS);
11461d06d6bSBaptiste Daroussin static	int	  termp_skip_pre(DECL_ARGS);
11561d06d6bSBaptiste Daroussin static	int	  termp_sm_pre(DECL_ARGS);
11661d06d6bSBaptiste Daroussin static	int	  termp_pp_pre(DECL_ARGS);
11761d06d6bSBaptiste Daroussin static	int	  termp_ss_pre(DECL_ARGS);
11861d06d6bSBaptiste Daroussin static	int	  termp_under_pre(DECL_ARGS);
11961d06d6bSBaptiste Daroussin static	int	  termp_vt_pre(DECL_ARGS);
12061d06d6bSBaptiste Daroussin static	int	  termp_xr_pre(DECL_ARGS);
12161d06d6bSBaptiste Daroussin static	int	  termp_xx_pre(DECL_ARGS);
12261d06d6bSBaptiste Daroussin 
1237295610fSBaptiste Daroussin static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
12461d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Dd */
12561d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Dt */
12661d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Os */
12761d06d6bSBaptiste Daroussin 	{ termp_sh_pre, termp_sh_post }, /* Sh */
12861d06d6bSBaptiste Daroussin 	{ termp_ss_pre, termp_ss_post }, /* Ss */
12961d06d6bSBaptiste Daroussin 	{ termp_pp_pre, NULL }, /* Pp */
13061d06d6bSBaptiste Daroussin 	{ termp_d1_pre, termp_bl_post }, /* D1 */
13161d06d6bSBaptiste Daroussin 	{ termp_d1_pre, termp_bl_post }, /* Dl */
13261d06d6bSBaptiste Daroussin 	{ termp_bd_pre, termp_bd_post }, /* Bd */
13361d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ed */
13461d06d6bSBaptiste Daroussin 	{ termp_bl_pre, termp_bl_post }, /* Bl */
13561d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* El */
13661d06d6bSBaptiste Daroussin 	{ termp_it_pre, termp_it_post }, /* It */
13761d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Ad */
13861d06d6bSBaptiste Daroussin 	{ termp_an_pre, NULL }, /* An */
13961d06d6bSBaptiste Daroussin 	{ termp_ap_pre, NULL }, /* Ap */
14061d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Ar */
141*6d38604fSBaptiste Daroussin 	{ termp_fd_pre, NULL }, /* Cd */
14261d06d6bSBaptiste Daroussin 	{ termp_bold_pre, NULL }, /* Cm */
14361d06d6bSBaptiste Daroussin 	{ termp_li_pre, NULL }, /* Dv */
144*6d38604fSBaptiste Daroussin 	{ NULL, NULL }, /* Er */
145*6d38604fSBaptiste Daroussin 	{ NULL, NULL }, /* Ev */
14661d06d6bSBaptiste Daroussin 	{ termp_ex_pre, NULL }, /* Ex */
14761d06d6bSBaptiste Daroussin 	{ termp_fa_pre, NULL }, /* Fa */
14861d06d6bSBaptiste Daroussin 	{ termp_fd_pre, termp_fd_post }, /* Fd */
14961d06d6bSBaptiste Daroussin 	{ termp_fl_pre, NULL }, /* Fl */
15061d06d6bSBaptiste Daroussin 	{ termp_fn_pre, NULL }, /* Fn */
15161d06d6bSBaptiste Daroussin 	{ termp_ft_pre, NULL }, /* Ft */
15261d06d6bSBaptiste Daroussin 	{ termp_bold_pre, NULL }, /* Ic */
15361d06d6bSBaptiste Daroussin 	{ termp_in_pre, termp_in_post }, /* In */
15461d06d6bSBaptiste Daroussin 	{ termp_li_pre, NULL }, /* Li */
15561d06d6bSBaptiste Daroussin 	{ termp_nd_pre, NULL }, /* Nd */
15661d06d6bSBaptiste Daroussin 	{ termp_nm_pre, termp_nm_post }, /* Nm */
15761d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Op */
1587295610fSBaptiste Daroussin 	{ termp_abort_pre, NULL }, /* Ot */
15961d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Pa */
16061d06d6bSBaptiste Daroussin 	{ termp_ex_pre, NULL }, /* Rv */
16161d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* St */
16261d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Va */
16361d06d6bSBaptiste Daroussin 	{ termp_vt_pre, NULL }, /* Vt */
16461d06d6bSBaptiste Daroussin 	{ termp_xr_pre, NULL }, /* Xr */
16561d06d6bSBaptiste Daroussin 	{ termp__a_pre, termp____post }, /* %A */
16661d06d6bSBaptiste Daroussin 	{ termp_under_pre, termp____post }, /* %B */
16761d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %D */
16861d06d6bSBaptiste Daroussin 	{ termp_under_pre, termp____post }, /* %I */
16961d06d6bSBaptiste Daroussin 	{ termp_under_pre, termp____post }, /* %J */
17061d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %N */
17161d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %O */
17261d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %P */
17361d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %R */
17461d06d6bSBaptiste Daroussin 	{ termp__t_pre, termp__t_post }, /* %T */
17561d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %V */
17661d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ac */
17761d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Ao */
17861d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Aq */
17961d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* At */
18061d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Bc */
18161d06d6bSBaptiste Daroussin 	{ termp_bf_pre, NULL }, /* Bf */
18261d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Bo */
18361d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Bq */
18461d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Bsx */
18561d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Bx */
18661d06d6bSBaptiste Daroussin 	{ termp_skip_pre, NULL }, /* Db */
18761d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Dc */
18861d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Do */
18961d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Dq */
19061d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ec */ /* FIXME: no space */
19161d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ef */
192*6d38604fSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Em */
19361d06d6bSBaptiste Daroussin 	{ termp_eo_pre, termp_eo_post }, /* Eo */
19461d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Fx */
19561d06d6bSBaptiste Daroussin 	{ termp_bold_pre, NULL }, /* Ms */
19661d06d6bSBaptiste Daroussin 	{ termp_li_pre, NULL }, /* No */
19761d06d6bSBaptiste Daroussin 	{ termp_ns_pre, NULL }, /* Ns */
19861d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Nx */
19961d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Ox */
20061d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Pc */
20161d06d6bSBaptiste Daroussin 	{ NULL, termp_pf_post }, /* Pf */
20261d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Po */
20361d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Pq */
20461d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Qc */
20561d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Ql */
20661d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Qo */
20761d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Qq */
20861d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Re */
20961d06d6bSBaptiste Daroussin 	{ termp_rs_pre, NULL }, /* Rs */
21061d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Sc */
21161d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* So */
21261d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Sq */
21361d06d6bSBaptiste Daroussin 	{ termp_sm_pre, NULL }, /* Sm */
21461d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Sx */
215*6d38604fSBaptiste Daroussin 	{ termp_bold_pre, NULL }, /* Sy */
21661d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Tn */
21761d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Ux */
21861d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Xc */
21961d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Xo */
22061d06d6bSBaptiste Daroussin 	{ termp_fo_pre, termp_fo_post }, /* Fo */
22161d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Fc */
22261d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Oo */
22361d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Oc */
22461d06d6bSBaptiste Daroussin 	{ termp_bk_pre, termp_bk_post }, /* Bk */
22561d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ek */
22661d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Bt */
22761d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Hf */
22861d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Fr */
22961d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ud */
23061d06d6bSBaptiste Daroussin 	{ NULL, termp_lb_post }, /* Lb */
2317295610fSBaptiste Daroussin 	{ termp_abort_pre, NULL }, /* Lp */
23261d06d6bSBaptiste Daroussin 	{ termp_lk_pre, NULL }, /* Lk */
23361d06d6bSBaptiste Daroussin 	{ termp_under_pre, NULL }, /* Mt */
23461d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Brq */
23561d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* Bro */
23661d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Brc */
23761d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %C */
23861d06d6bSBaptiste Daroussin 	{ termp_skip_pre, NULL }, /* Es */
23961d06d6bSBaptiste Daroussin 	{ termp_quote_pre, termp_quote_post }, /* En */
24061d06d6bSBaptiste Daroussin 	{ termp_xx_pre, termp_xx_post }, /* Dx */
24161d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %Q */
24261d06d6bSBaptiste Daroussin 	{ NULL, termp____post }, /* %U */
24361d06d6bSBaptiste Daroussin 	{ NULL, NULL }, /* Ta */
244*6d38604fSBaptiste Daroussin 	{ termp_skip_pre, NULL }, /* Tg */
24561d06d6bSBaptiste Daroussin };
24661d06d6bSBaptiste Daroussin 
24761d06d6bSBaptiste Daroussin 
24861d06d6bSBaptiste Daroussin void
2497295610fSBaptiste Daroussin terminal_mdoc(void *arg, const struct roff_meta *mdoc)
25061d06d6bSBaptiste Daroussin {
25145a5aec3SBaptiste Daroussin 	struct roff_node	*n, *nn;
25261d06d6bSBaptiste Daroussin 	struct termp		*p;
25361d06d6bSBaptiste Daroussin 	size_t			 save_defindent;
25461d06d6bSBaptiste Daroussin 
25561d06d6bSBaptiste Daroussin 	p = (struct termp *)arg;
25661d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin = p->defrmargin;
25761d06d6bSBaptiste Daroussin 	term_tab_set(p, NULL);
25861d06d6bSBaptiste Daroussin 	term_tab_set(p, "T");
25961d06d6bSBaptiste Daroussin 	term_tab_set(p, ".5i");
26061d06d6bSBaptiste Daroussin 
26161d06d6bSBaptiste Daroussin 	n = mdoc->first->child;
26261d06d6bSBaptiste Daroussin 	if (p->synopsisonly) {
26345a5aec3SBaptiste Daroussin 		for (nn = NULL; n != NULL; n = n->next) {
26445a5aec3SBaptiste Daroussin 			if (n->tok != MDOC_Sh)
26545a5aec3SBaptiste Daroussin 				continue;
26645a5aec3SBaptiste Daroussin 			if (n->sec == SEC_SYNOPSIS)
26761d06d6bSBaptiste Daroussin 				break;
26845a5aec3SBaptiste Daroussin 			if (nn == NULL && n->sec == SEC_NAME)
26945a5aec3SBaptiste Daroussin 				nn = n;
27061d06d6bSBaptiste Daroussin 		}
27145a5aec3SBaptiste Daroussin 		if (n == NULL)
27245a5aec3SBaptiste Daroussin 			n = nn;
27345a5aec3SBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
27445a5aec3SBaptiste Daroussin 		if (n != NULL && (n = n->child->next->child) != NULL)
27545a5aec3SBaptiste Daroussin 			print_mdoc_nodelist(p, NULL, mdoc, n);
27645a5aec3SBaptiste Daroussin 		term_newln(p);
27761d06d6bSBaptiste Daroussin 	} else {
27861d06d6bSBaptiste Daroussin 		save_defindent = p->defindent;
27961d06d6bSBaptiste Daroussin 		if (p->defindent == 0)
28061d06d6bSBaptiste Daroussin 			p->defindent = 5;
2817295610fSBaptiste Daroussin 		term_begin(p, print_mdoc_head, print_mdoc_foot, mdoc);
28261d06d6bSBaptiste Daroussin 		while (n != NULL &&
28361d06d6bSBaptiste Daroussin 		    (n->type == ROFFT_COMMENT ||
28461d06d6bSBaptiste Daroussin 		     n->flags & NODE_NOPRT))
28561d06d6bSBaptiste Daroussin 			n = n->next;
28661d06d6bSBaptiste Daroussin 		if (n != NULL) {
28761d06d6bSBaptiste Daroussin 			if (n->tok != MDOC_Sh)
28861d06d6bSBaptiste Daroussin 				term_vspace(p);
2897295610fSBaptiste Daroussin 			print_mdoc_nodelist(p, NULL, mdoc, n);
29061d06d6bSBaptiste Daroussin 		}
29161d06d6bSBaptiste Daroussin 		term_end(p);
29261d06d6bSBaptiste Daroussin 		p->defindent = save_defindent;
29361d06d6bSBaptiste Daroussin 	}
29461d06d6bSBaptiste Daroussin }
29561d06d6bSBaptiste Daroussin 
29661d06d6bSBaptiste Daroussin static void
29761d06d6bSBaptiste Daroussin print_mdoc_nodelist(DECL_ARGS)
29861d06d6bSBaptiste Daroussin {
29961d06d6bSBaptiste Daroussin 	while (n != NULL) {
30061d06d6bSBaptiste Daroussin 		print_mdoc_node(p, pair, meta, n);
30161d06d6bSBaptiste Daroussin 		n = n->next;
30261d06d6bSBaptiste Daroussin 	}
30361d06d6bSBaptiste Daroussin }
30461d06d6bSBaptiste Daroussin 
30561d06d6bSBaptiste Daroussin static void
30661d06d6bSBaptiste Daroussin print_mdoc_node(DECL_ARGS)
30761d06d6bSBaptiste Daroussin {
3087295610fSBaptiste Daroussin 	const struct mdoc_term_act *act;
30961d06d6bSBaptiste Daroussin 	struct termpair	 npair;
31061d06d6bSBaptiste Daroussin 	size_t		 offset, rmargin;
3117295610fSBaptiste Daroussin 	int		 chld;
3127295610fSBaptiste Daroussin 
3137295610fSBaptiste Daroussin 	/*
3147295610fSBaptiste Daroussin 	 * In no-fill mode, break the output line at the beginning
3157295610fSBaptiste Daroussin 	 * of new input lines except after \c, and nowhere else.
3167295610fSBaptiste Daroussin 	 */
3177295610fSBaptiste Daroussin 
3187295610fSBaptiste Daroussin 	if (n->flags & NODE_NOFILL) {
3197295610fSBaptiste Daroussin 		if (n->flags & NODE_LINE &&
3207295610fSBaptiste Daroussin 		    (p->flags & TERMP_NONEWLINE) == 0)
3217295610fSBaptiste Daroussin 			term_newln(p);
3227295610fSBaptiste Daroussin 		p->flags |= TERMP_BRNEVER;
3237295610fSBaptiste Daroussin 	} else
3247295610fSBaptiste Daroussin 		p->flags &= ~TERMP_BRNEVER;
32561d06d6bSBaptiste Daroussin 
32661d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
32761d06d6bSBaptiste Daroussin 		return;
32861d06d6bSBaptiste Daroussin 
32961d06d6bSBaptiste Daroussin 	chld = 1;
33061d06d6bSBaptiste Daroussin 	offset = p->tcol->offset;
33161d06d6bSBaptiste Daroussin 	rmargin = p->tcol->rmargin;
33261d06d6bSBaptiste Daroussin 	n->flags &= ~NODE_ENDED;
33361d06d6bSBaptiste Daroussin 	n->prev_font = p->fonti;
33461d06d6bSBaptiste Daroussin 
33561d06d6bSBaptiste Daroussin 	memset(&npair, 0, sizeof(struct termpair));
33661d06d6bSBaptiste Daroussin 	npair.ppair = pair;
33761d06d6bSBaptiste Daroussin 
338*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_ID && n->tok != MDOC_Pp &&
339*6d38604fSBaptiste Daroussin 	    (n->tok != MDOC_It || n->type != ROFFT_BLOCK))
340*6d38604fSBaptiste Daroussin 		term_tag_write(n, p->line);
341*6d38604fSBaptiste Daroussin 
34261d06d6bSBaptiste Daroussin 	/*
34361d06d6bSBaptiste Daroussin 	 * Keeps only work until the end of a line.  If a keep was
34461d06d6bSBaptiste Daroussin 	 * invoked in a prior line, revert it to PREKEEP.
34561d06d6bSBaptiste Daroussin 	 */
34661d06d6bSBaptiste Daroussin 
34761d06d6bSBaptiste Daroussin 	if (p->flags & TERMP_KEEP && n->flags & NODE_LINE) {
34861d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_KEEP;
34961d06d6bSBaptiste Daroussin 		p->flags |= TERMP_PREKEEP;
35061d06d6bSBaptiste Daroussin 	}
35161d06d6bSBaptiste Daroussin 
35261d06d6bSBaptiste Daroussin 	/*
35361d06d6bSBaptiste Daroussin 	 * After the keep flags have been set up, we may now
35461d06d6bSBaptiste Daroussin 	 * produce output.  Note that some pre-handlers do so.
35561d06d6bSBaptiste Daroussin 	 */
35661d06d6bSBaptiste Daroussin 
35745a5aec3SBaptiste Daroussin 	act = NULL;
35861d06d6bSBaptiste Daroussin 	switch (n->type) {
35961d06d6bSBaptiste Daroussin 	case ROFFT_TEXT:
3607295610fSBaptiste Daroussin 		if (n->flags & NODE_LINE) {
3617295610fSBaptiste Daroussin 			switch (*n->string) {
3627295610fSBaptiste Daroussin 			case '\0':
3637295610fSBaptiste Daroussin 				if (p->flags & TERMP_NONEWLINE)
36461d06d6bSBaptiste Daroussin 					term_newln(p);
3657295610fSBaptiste Daroussin 				else
3667295610fSBaptiste Daroussin 					term_vspace(p);
3677295610fSBaptiste Daroussin 				return;
3687295610fSBaptiste Daroussin 			case ' ':
3697295610fSBaptiste Daroussin 				if ((p->flags & TERMP_NONEWLINE) == 0)
3707295610fSBaptiste Daroussin 					term_newln(p);
3717295610fSBaptiste Daroussin 				break;
3727295610fSBaptiste Daroussin 			default:
3737295610fSBaptiste Daroussin 				break;
3747295610fSBaptiste Daroussin 			}
3757295610fSBaptiste Daroussin 		}
37661d06d6bSBaptiste Daroussin 		if (NODE_DELIMC & n->flags)
37761d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
37861d06d6bSBaptiste Daroussin 		term_word(p, n->string);
37961d06d6bSBaptiste Daroussin 		if (NODE_DELIMO & n->flags)
38061d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
38161d06d6bSBaptiste Daroussin 		break;
38261d06d6bSBaptiste Daroussin 	case ROFFT_EQN:
38361d06d6bSBaptiste Daroussin 		if ( ! (n->flags & NODE_LINE))
38461d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
38561d06d6bSBaptiste Daroussin 		term_eqn(p, n->eqn);
38661d06d6bSBaptiste Daroussin 		if (n->next != NULL && ! (n->next->flags & NODE_LINE))
38761d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
38861d06d6bSBaptiste Daroussin 		break;
38961d06d6bSBaptiste Daroussin 	case ROFFT_TBL:
39061d06d6bSBaptiste Daroussin 		if (p->tbl.cols == NULL)
39161d06d6bSBaptiste Daroussin 			term_newln(p);
39261d06d6bSBaptiste Daroussin 		term_tbl(p, n->span);
39361d06d6bSBaptiste Daroussin 		break;
39461d06d6bSBaptiste Daroussin 	default:
39561d06d6bSBaptiste Daroussin 		if (n->tok < ROFF_MAX) {
39661d06d6bSBaptiste Daroussin 			roff_term_pre(p, n);
39761d06d6bSBaptiste Daroussin 			return;
39861d06d6bSBaptiste Daroussin 		}
39961d06d6bSBaptiste Daroussin 		assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
4007295610fSBaptiste Daroussin 		act = mdoc_term_acts + (n->tok - MDOC_Dd);
4017295610fSBaptiste Daroussin 		if (act->pre != NULL &&
40261d06d6bSBaptiste Daroussin 		    (n->end == ENDBODY_NOT || n->child != NULL))
4037295610fSBaptiste Daroussin 			chld = (*act->pre)(p, &npair, meta, n);
40461d06d6bSBaptiste Daroussin 		break;
40561d06d6bSBaptiste Daroussin 	}
40661d06d6bSBaptiste Daroussin 
40761d06d6bSBaptiste Daroussin 	if (chld && n->child)
40861d06d6bSBaptiste Daroussin 		print_mdoc_nodelist(p, &npair, meta, n->child);
40961d06d6bSBaptiste Daroussin 
41061d06d6bSBaptiste Daroussin 	term_fontpopq(p,
41161d06d6bSBaptiste Daroussin 	    (ENDBODY_NOT == n->end ? n : n->body)->prev_font);
41261d06d6bSBaptiste Daroussin 
41361d06d6bSBaptiste Daroussin 	switch (n->type) {
41461d06d6bSBaptiste Daroussin 	case ROFFT_TEXT:
41561d06d6bSBaptiste Daroussin 		break;
41661d06d6bSBaptiste Daroussin 	case ROFFT_TBL:
41761d06d6bSBaptiste Daroussin 		break;
41861d06d6bSBaptiste Daroussin 	case ROFFT_EQN:
41961d06d6bSBaptiste Daroussin 		break;
42061d06d6bSBaptiste Daroussin 	default:
4217295610fSBaptiste Daroussin 		if (act->post == NULL || n->flags & NODE_ENDED)
42261d06d6bSBaptiste Daroussin 			break;
4237295610fSBaptiste Daroussin 		(void)(*act->post)(p, &npair, meta, n);
42461d06d6bSBaptiste Daroussin 
42561d06d6bSBaptiste Daroussin 		/*
42661d06d6bSBaptiste Daroussin 		 * Explicit end tokens not only call the post
42761d06d6bSBaptiste Daroussin 		 * handler, but also tell the respective block
42861d06d6bSBaptiste Daroussin 		 * that it must not call the post handler again.
42961d06d6bSBaptiste Daroussin 		 */
43061d06d6bSBaptiste Daroussin 		if (ENDBODY_NOT != n->end)
43161d06d6bSBaptiste Daroussin 			n->body->flags |= NODE_ENDED;
43261d06d6bSBaptiste Daroussin 		break;
43361d06d6bSBaptiste Daroussin 	}
43461d06d6bSBaptiste Daroussin 
43561d06d6bSBaptiste Daroussin 	if (NODE_EOS & n->flags)
43661d06d6bSBaptiste Daroussin 		p->flags |= TERMP_SENTENCE;
43761d06d6bSBaptiste Daroussin 
43861d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_TEXT)
43961d06d6bSBaptiste Daroussin 		p->tcol->offset = offset;
44061d06d6bSBaptiste Daroussin 	p->tcol->rmargin = rmargin;
44161d06d6bSBaptiste Daroussin }
44261d06d6bSBaptiste Daroussin 
44361d06d6bSBaptiste Daroussin static void
44461d06d6bSBaptiste Daroussin print_mdoc_foot(struct termp *p, const struct roff_meta *meta)
44561d06d6bSBaptiste Daroussin {
44661d06d6bSBaptiste Daroussin 	size_t sz;
44761d06d6bSBaptiste Daroussin 
44861d06d6bSBaptiste Daroussin 	term_fontrepl(p, TERMFONT_NONE);
44961d06d6bSBaptiste Daroussin 
45061d06d6bSBaptiste Daroussin 	/*
45161d06d6bSBaptiste Daroussin 	 * Output the footer in new-groff style, that is, three columns
45261d06d6bSBaptiste Daroussin 	 * with the middle being the manual date and flanking columns
45361d06d6bSBaptiste Daroussin 	 * being the operating system:
45461d06d6bSBaptiste Daroussin 	 *
45561d06d6bSBaptiste Daroussin 	 * SYSTEM                  DATE                    SYSTEM
45661d06d6bSBaptiste Daroussin 	 */
45761d06d6bSBaptiste Daroussin 
45861d06d6bSBaptiste Daroussin 	term_vspace(p);
45961d06d6bSBaptiste Daroussin 
46061d06d6bSBaptiste Daroussin 	p->tcol->offset = 0;
46161d06d6bSBaptiste Daroussin 	sz = term_strlen(p, meta->date);
46261d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin > sz ?
46361d06d6bSBaptiste Daroussin 	    (p->maxrmargin + term_len(p, 1) - sz) / 2 : 0;
46461d06d6bSBaptiste Daroussin 	p->trailspace = 1;
46561d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
46661d06d6bSBaptiste Daroussin 
46761d06d6bSBaptiste Daroussin 	term_word(p, meta->os);
46861d06d6bSBaptiste Daroussin 	term_flushln(p);
46961d06d6bSBaptiste Daroussin 
47061d06d6bSBaptiste Daroussin 	p->tcol->offset = p->tcol->rmargin;
47161d06d6bSBaptiste Daroussin 	sz = term_strlen(p, meta->os);
47261d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin > sz ? p->maxrmargin - sz : 0;
47361d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
47461d06d6bSBaptiste Daroussin 
47561d06d6bSBaptiste Daroussin 	term_word(p, meta->date);
47661d06d6bSBaptiste Daroussin 	term_flushln(p);
47761d06d6bSBaptiste Daroussin 
47861d06d6bSBaptiste Daroussin 	p->tcol->offset = p->tcol->rmargin;
47961d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin;
48061d06d6bSBaptiste Daroussin 	p->trailspace = 0;
48161d06d6bSBaptiste Daroussin 	p->flags &= ~TERMP_NOBREAK;
48261d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
48361d06d6bSBaptiste Daroussin 
48461d06d6bSBaptiste Daroussin 	term_word(p, meta->os);
48561d06d6bSBaptiste Daroussin 	term_flushln(p);
48661d06d6bSBaptiste Daroussin 
48761d06d6bSBaptiste Daroussin 	p->tcol->offset = 0;
48861d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin;
48961d06d6bSBaptiste Daroussin 	p->flags = 0;
49061d06d6bSBaptiste Daroussin }
49161d06d6bSBaptiste Daroussin 
49261d06d6bSBaptiste Daroussin static void
49361d06d6bSBaptiste Daroussin print_mdoc_head(struct termp *p, const struct roff_meta *meta)
49461d06d6bSBaptiste Daroussin {
49561d06d6bSBaptiste Daroussin 	char			*volume, *title;
49661d06d6bSBaptiste Daroussin 	size_t			 vollen, titlen;
49761d06d6bSBaptiste Daroussin 
49861d06d6bSBaptiste Daroussin 	/*
49961d06d6bSBaptiste Daroussin 	 * The header is strange.  It has three components, which are
50061d06d6bSBaptiste Daroussin 	 * really two with the first duplicated.  It goes like this:
50161d06d6bSBaptiste Daroussin 	 *
50261d06d6bSBaptiste Daroussin 	 * IDENTIFIER              TITLE                   IDENTIFIER
50361d06d6bSBaptiste Daroussin 	 *
50461d06d6bSBaptiste Daroussin 	 * The IDENTIFIER is NAME(SECTION), which is the command-name
50561d06d6bSBaptiste Daroussin 	 * (if given, or "unknown" if not) followed by the manual page
50661d06d6bSBaptiste Daroussin 	 * section.  These are given in `Dt'.  The TITLE is a free-form
50761d06d6bSBaptiste Daroussin 	 * string depending on the manual volume.  If not specified, it
50861d06d6bSBaptiste Daroussin 	 * switches on the manual section.
50961d06d6bSBaptiste Daroussin 	 */
51061d06d6bSBaptiste Daroussin 
51161d06d6bSBaptiste Daroussin 	assert(meta->vol);
51261d06d6bSBaptiste Daroussin 	if (NULL == meta->arch)
51361d06d6bSBaptiste Daroussin 		volume = mandoc_strdup(meta->vol);
51461d06d6bSBaptiste Daroussin 	else
51561d06d6bSBaptiste Daroussin 		mandoc_asprintf(&volume, "%s (%s)",
51661d06d6bSBaptiste Daroussin 		    meta->vol, meta->arch);
51761d06d6bSBaptiste Daroussin 	vollen = term_strlen(p, volume);
51861d06d6bSBaptiste Daroussin 
51961d06d6bSBaptiste Daroussin 	if (NULL == meta->msec)
52061d06d6bSBaptiste Daroussin 		title = mandoc_strdup(meta->title);
52161d06d6bSBaptiste Daroussin 	else
52261d06d6bSBaptiste Daroussin 		mandoc_asprintf(&title, "%s(%s)",
52361d06d6bSBaptiste Daroussin 		    meta->title, meta->msec);
52461d06d6bSBaptiste Daroussin 	titlen = term_strlen(p, title);
52561d06d6bSBaptiste Daroussin 
52661d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
52761d06d6bSBaptiste Daroussin 	p->trailspace = 1;
52861d06d6bSBaptiste Daroussin 	p->tcol->offset = 0;
52961d06d6bSBaptiste Daroussin 	p->tcol->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
53061d06d6bSBaptiste Daroussin 	    (p->maxrmargin - vollen + term_len(p, 1)) / 2 :
53161d06d6bSBaptiste Daroussin 	    vollen < p->maxrmargin ?  p->maxrmargin - vollen : 0;
53261d06d6bSBaptiste Daroussin 
53361d06d6bSBaptiste Daroussin 	term_word(p, title);
53461d06d6bSBaptiste Daroussin 	term_flushln(p);
53561d06d6bSBaptiste Daroussin 
53661d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
53761d06d6bSBaptiste Daroussin 	p->tcol->offset = p->tcol->rmargin;
53861d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->tcol->offset + vollen + titlen <
53961d06d6bSBaptiste Daroussin 	    p->maxrmargin ? p->maxrmargin - titlen : p->maxrmargin;
54061d06d6bSBaptiste Daroussin 
54161d06d6bSBaptiste Daroussin 	term_word(p, volume);
54261d06d6bSBaptiste Daroussin 	term_flushln(p);
54361d06d6bSBaptiste Daroussin 
54461d06d6bSBaptiste Daroussin 	p->flags &= ~TERMP_NOBREAK;
54561d06d6bSBaptiste Daroussin 	p->trailspace = 0;
54661d06d6bSBaptiste Daroussin 	if (p->tcol->rmargin + titlen <= p->maxrmargin) {
54761d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
54861d06d6bSBaptiste Daroussin 		p->tcol->offset = p->tcol->rmargin;
54961d06d6bSBaptiste Daroussin 		p->tcol->rmargin = p->maxrmargin;
55061d06d6bSBaptiste Daroussin 		term_word(p, title);
55161d06d6bSBaptiste Daroussin 		term_flushln(p);
55261d06d6bSBaptiste Daroussin 	}
55361d06d6bSBaptiste Daroussin 
55461d06d6bSBaptiste Daroussin 	p->flags &= ~TERMP_NOSPACE;
55561d06d6bSBaptiste Daroussin 	p->tcol->offset = 0;
55661d06d6bSBaptiste Daroussin 	p->tcol->rmargin = p->maxrmargin;
55761d06d6bSBaptiste Daroussin 	free(title);
55861d06d6bSBaptiste Daroussin 	free(volume);
55961d06d6bSBaptiste Daroussin }
56061d06d6bSBaptiste Daroussin 
56161d06d6bSBaptiste Daroussin static int
56261d06d6bSBaptiste Daroussin a2width(const struct termp *p, const char *v)
56361d06d6bSBaptiste Daroussin {
56461d06d6bSBaptiste Daroussin 	struct roffsu	 su;
56561d06d6bSBaptiste Daroussin 	const char	*end;
56661d06d6bSBaptiste Daroussin 
56761d06d6bSBaptiste Daroussin 	end = a2roffsu(v, &su, SCALE_MAX);
56861d06d6bSBaptiste Daroussin 	if (end == NULL || *end != '\0') {
56961d06d6bSBaptiste Daroussin 		SCALE_HS_INIT(&su, term_strlen(p, v));
57061d06d6bSBaptiste Daroussin 		su.scale /= term_strlen(p, "0");
57161d06d6bSBaptiste Daroussin 	}
57261d06d6bSBaptiste Daroussin 	return term_hen(p, &su);
57361d06d6bSBaptiste Daroussin }
57461d06d6bSBaptiste Daroussin 
57561d06d6bSBaptiste Daroussin /*
57661d06d6bSBaptiste Daroussin  * Determine how much space to print out before block elements of `It'
57761d06d6bSBaptiste Daroussin  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
57861d06d6bSBaptiste Daroussin  * too.
57961d06d6bSBaptiste Daroussin  */
58061d06d6bSBaptiste Daroussin static void
581*6d38604fSBaptiste Daroussin print_bvspace(struct termp *p, struct roff_node *bl, struct roff_node *n)
58261d06d6bSBaptiste Daroussin {
583*6d38604fSBaptiste Daroussin 	struct roff_node *nn;
58461d06d6bSBaptiste Daroussin 
58561d06d6bSBaptiste Daroussin 	term_newln(p);
58661d06d6bSBaptiste Daroussin 
587*6d38604fSBaptiste Daroussin 	if ((bl->tok == MDOC_Bd && bl->norm->Bd.comp) ||
588*6d38604fSBaptiste Daroussin 	    (bl->tok == MDOC_Bl && bl->norm->Bl.comp))
58961d06d6bSBaptiste Daroussin 		return;
59061d06d6bSBaptiste Daroussin 
59161d06d6bSBaptiste Daroussin 	/* Do not vspace directly after Ss/Sh. */
59261d06d6bSBaptiste Daroussin 
59361d06d6bSBaptiste Daroussin 	nn = n;
594*6d38604fSBaptiste Daroussin 	while (roff_node_prev(nn) == NULL) {
59561d06d6bSBaptiste Daroussin 		do {
59661d06d6bSBaptiste Daroussin 			nn = nn->parent;
59761d06d6bSBaptiste Daroussin 			if (nn->type == ROFFT_ROOT)
59861d06d6bSBaptiste Daroussin 				return;
59961d06d6bSBaptiste Daroussin 		} while (nn->type != ROFFT_BLOCK);
60061d06d6bSBaptiste Daroussin 		if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
60161d06d6bSBaptiste Daroussin 			return;
60261d06d6bSBaptiste Daroussin 		if (nn->tok == MDOC_It &&
60361d06d6bSBaptiste Daroussin 		    nn->parent->parent->norm->Bl.type != LIST_item)
60461d06d6bSBaptiste Daroussin 			break;
60561d06d6bSBaptiste Daroussin 	}
60661d06d6bSBaptiste Daroussin 
607*6d38604fSBaptiste Daroussin 	/*
608*6d38604fSBaptiste Daroussin 	 * No vertical space after:
609*6d38604fSBaptiste Daroussin 	 * items in .Bl -column
610*6d38604fSBaptiste Daroussin 	 * items without a body in .Bl -diag
611*6d38604fSBaptiste Daroussin 	 */
61261d06d6bSBaptiste Daroussin 
613*6d38604fSBaptiste Daroussin 	if (bl->tok != MDOC_Bl ||
614*6d38604fSBaptiste Daroussin 	    n->prev == NULL || n->prev->tok != MDOC_It ||
615*6d38604fSBaptiste Daroussin 	    (bl->norm->Bl.type != LIST_column &&
616*6d38604fSBaptiste Daroussin 	     (bl->norm->Bl.type != LIST_diag ||
617*6d38604fSBaptiste Daroussin 	      n->prev->body->child != NULL)))
61861d06d6bSBaptiste Daroussin 		term_vspace(p);
61961d06d6bSBaptiste Daroussin }
62061d06d6bSBaptiste Daroussin 
62161d06d6bSBaptiste Daroussin 
62261d06d6bSBaptiste Daroussin static int
62361d06d6bSBaptiste Daroussin termp_it_pre(DECL_ARGS)
62461d06d6bSBaptiste Daroussin {
62561d06d6bSBaptiste Daroussin 	struct roffsu		su;
62661d06d6bSBaptiste Daroussin 	char			buf[24];
62761d06d6bSBaptiste Daroussin 	const struct roff_node *bl, *nn;
62861d06d6bSBaptiste Daroussin 	size_t			ncols, dcol;
62961d06d6bSBaptiste Daroussin 	int			i, offset, width;
63061d06d6bSBaptiste Daroussin 	enum mdoc_list		type;
63161d06d6bSBaptiste Daroussin 
63261d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK) {
63361d06d6bSBaptiste Daroussin 		print_bvspace(p, n->parent->parent, n);
634*6d38604fSBaptiste Daroussin 		if (n->flags & NODE_ID)
635*6d38604fSBaptiste Daroussin 			term_tag_write(n, p->line);
63661d06d6bSBaptiste Daroussin 		return 1;
63761d06d6bSBaptiste Daroussin 	}
63861d06d6bSBaptiste Daroussin 
63961d06d6bSBaptiste Daroussin 	bl = n->parent->parent->parent;
64061d06d6bSBaptiste Daroussin 	type = bl->norm->Bl.type;
64161d06d6bSBaptiste Daroussin 
64261d06d6bSBaptiste Daroussin 	/*
64361d06d6bSBaptiste Daroussin 	 * Defaults for specific list types.
64461d06d6bSBaptiste Daroussin 	 */
64561d06d6bSBaptiste Daroussin 
64661d06d6bSBaptiste Daroussin 	switch (type) {
64761d06d6bSBaptiste Daroussin 	case LIST_bullet:
64861d06d6bSBaptiste Daroussin 	case LIST_dash:
64961d06d6bSBaptiste Daroussin 	case LIST_hyphen:
65061d06d6bSBaptiste Daroussin 	case LIST_enum:
65161d06d6bSBaptiste Daroussin 		width = term_len(p, 2);
65261d06d6bSBaptiste Daroussin 		break;
65361d06d6bSBaptiste Daroussin 	case LIST_hang:
65461d06d6bSBaptiste Daroussin 	case LIST_tag:
65561d06d6bSBaptiste Daroussin 		width = term_len(p, 8);
65661d06d6bSBaptiste Daroussin 		break;
65761d06d6bSBaptiste Daroussin 	case LIST_column:
65861d06d6bSBaptiste Daroussin 		width = term_len(p, 10);
65961d06d6bSBaptiste Daroussin 		break;
66061d06d6bSBaptiste Daroussin 	default:
66161d06d6bSBaptiste Daroussin 		width = 0;
66261d06d6bSBaptiste Daroussin 		break;
66361d06d6bSBaptiste Daroussin 	}
66461d06d6bSBaptiste Daroussin 	offset = 0;
66561d06d6bSBaptiste Daroussin 
66661d06d6bSBaptiste Daroussin 	/*
66761d06d6bSBaptiste Daroussin 	 * First calculate width and offset.  This is pretty easy unless
66861d06d6bSBaptiste Daroussin 	 * we're a -column list, in which case all prior columns must
66961d06d6bSBaptiste Daroussin 	 * be accounted for.
67061d06d6bSBaptiste Daroussin 	 */
67161d06d6bSBaptiste Daroussin 
67261d06d6bSBaptiste Daroussin 	if (bl->norm->Bl.offs != NULL) {
67361d06d6bSBaptiste Daroussin 		offset = a2width(p, bl->norm->Bl.offs);
67461d06d6bSBaptiste Daroussin 		if (offset < 0 && (size_t)(-offset) > p->tcol->offset)
67561d06d6bSBaptiste Daroussin 			offset = -p->tcol->offset;
67661d06d6bSBaptiste Daroussin 		else if (offset > SHRT_MAX)
67761d06d6bSBaptiste Daroussin 			offset = 0;
67861d06d6bSBaptiste Daroussin 	}
67961d06d6bSBaptiste Daroussin 
68061d06d6bSBaptiste Daroussin 	switch (type) {
68161d06d6bSBaptiste Daroussin 	case LIST_column:
68261d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
68361d06d6bSBaptiste Daroussin 			break;
68461d06d6bSBaptiste Daroussin 
68561d06d6bSBaptiste Daroussin 		/*
68661d06d6bSBaptiste Daroussin 		 * Imitate groff's column handling:
68761d06d6bSBaptiste Daroussin 		 * - For each earlier column, add its width.
68861d06d6bSBaptiste Daroussin 		 * - For less than 5 columns, add four more blanks per
68961d06d6bSBaptiste Daroussin 		 *   column.
69061d06d6bSBaptiste Daroussin 		 * - For exactly 5 columns, add three more blank per
69161d06d6bSBaptiste Daroussin 		 *   column.
69261d06d6bSBaptiste Daroussin 		 * - For more than 5 columns, add only one column.
69361d06d6bSBaptiste Daroussin 		 */
69461d06d6bSBaptiste Daroussin 		ncols = bl->norm->Bl.ncols;
69561d06d6bSBaptiste Daroussin 		dcol = ncols < 5 ? term_len(p, 4) :
69661d06d6bSBaptiste Daroussin 		    ncols == 5 ? term_len(p, 3) : term_len(p, 1);
69761d06d6bSBaptiste Daroussin 
69861d06d6bSBaptiste Daroussin 		/*
69961d06d6bSBaptiste Daroussin 		 * Calculate the offset by applying all prior ROFFT_BODY,
70061d06d6bSBaptiste Daroussin 		 * so we stop at the ROFFT_HEAD (nn->prev == NULL).
70161d06d6bSBaptiste Daroussin 		 */
70261d06d6bSBaptiste Daroussin 
70361d06d6bSBaptiste Daroussin 		for (i = 0, nn = n->prev;
70461d06d6bSBaptiste Daroussin 		    nn->prev && i < (int)ncols;
70561d06d6bSBaptiste Daroussin 		    nn = nn->prev, i++) {
70661d06d6bSBaptiste Daroussin 			SCALE_HS_INIT(&su,
70761d06d6bSBaptiste Daroussin 			    term_strlen(p, bl->norm->Bl.cols[i]));
70861d06d6bSBaptiste Daroussin 			su.scale /= term_strlen(p, "0");
70961d06d6bSBaptiste Daroussin 			offset += term_hen(p, &su) + dcol;
71061d06d6bSBaptiste Daroussin 		}
71161d06d6bSBaptiste Daroussin 
71261d06d6bSBaptiste Daroussin 		/*
71361d06d6bSBaptiste Daroussin 		 * When exceeding the declared number of columns, leave
71461d06d6bSBaptiste Daroussin 		 * the remaining widths at 0.  This will later be
71561d06d6bSBaptiste Daroussin 		 * adjusted to the default width of 10, or, for the last
71661d06d6bSBaptiste Daroussin 		 * column, stretched to the right margin.
71761d06d6bSBaptiste Daroussin 		 */
71861d06d6bSBaptiste Daroussin 		if (i >= (int)ncols)
71961d06d6bSBaptiste Daroussin 			break;
72061d06d6bSBaptiste Daroussin 
72161d06d6bSBaptiste Daroussin 		/*
72261d06d6bSBaptiste Daroussin 		 * Use the declared column widths, extended as explained
72361d06d6bSBaptiste Daroussin 		 * in the preceding paragraph.
72461d06d6bSBaptiste Daroussin 		 */
72561d06d6bSBaptiste Daroussin 		SCALE_HS_INIT(&su, term_strlen(p, bl->norm->Bl.cols[i]));
72661d06d6bSBaptiste Daroussin 		su.scale /= term_strlen(p, "0");
72761d06d6bSBaptiste Daroussin 		width = term_hen(p, &su) + dcol;
72861d06d6bSBaptiste Daroussin 		break;
72961d06d6bSBaptiste Daroussin 	default:
73061d06d6bSBaptiste Daroussin 		if (NULL == bl->norm->Bl.width)
73161d06d6bSBaptiste Daroussin 			break;
73261d06d6bSBaptiste Daroussin 
73361d06d6bSBaptiste Daroussin 		/*
73461d06d6bSBaptiste Daroussin 		 * Note: buffer the width by 2, which is groff's magic
73561d06d6bSBaptiste Daroussin 		 * number for buffering single arguments.  See the above
73661d06d6bSBaptiste Daroussin 		 * handling for column for how this changes.
73761d06d6bSBaptiste Daroussin 		 */
73861d06d6bSBaptiste Daroussin 		width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
73961d06d6bSBaptiste Daroussin 		if (width < 0 && (size_t)(-width) > p->tcol->offset)
74061d06d6bSBaptiste Daroussin 			width = -p->tcol->offset;
74161d06d6bSBaptiste Daroussin 		else if (width > SHRT_MAX)
74261d06d6bSBaptiste Daroussin 			width = 0;
74361d06d6bSBaptiste Daroussin 		break;
74461d06d6bSBaptiste Daroussin 	}
74561d06d6bSBaptiste Daroussin 
74661d06d6bSBaptiste Daroussin 	/*
74761d06d6bSBaptiste Daroussin 	 * Whitespace control.  Inset bodies need an initial space,
74861d06d6bSBaptiste Daroussin 	 * while diagonal bodies need two.
74961d06d6bSBaptiste Daroussin 	 */
75061d06d6bSBaptiste Daroussin 
75161d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
75261d06d6bSBaptiste Daroussin 
75361d06d6bSBaptiste Daroussin 	switch (type) {
75461d06d6bSBaptiste Daroussin 	case LIST_diag:
75561d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_BODY)
75661d06d6bSBaptiste Daroussin 			term_word(p, "\\ \\ ");
75761d06d6bSBaptiste Daroussin 		break;
75861d06d6bSBaptiste Daroussin 	case LIST_inset:
75961d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_BODY && n->parent->head->child != NULL)
76061d06d6bSBaptiste Daroussin 			term_word(p, "\\ ");
76161d06d6bSBaptiste Daroussin 		break;
76261d06d6bSBaptiste Daroussin 	default:
76361d06d6bSBaptiste Daroussin 		break;
76461d06d6bSBaptiste Daroussin 	}
76561d06d6bSBaptiste Daroussin 
76661d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
76761d06d6bSBaptiste Daroussin 
76861d06d6bSBaptiste Daroussin 	switch (type) {
76961d06d6bSBaptiste Daroussin 	case LIST_diag:
77061d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
77161d06d6bSBaptiste Daroussin 			term_fontpush(p, TERMFONT_BOLD);
77261d06d6bSBaptiste Daroussin 		break;
77361d06d6bSBaptiste Daroussin 	default:
77461d06d6bSBaptiste Daroussin 		break;
77561d06d6bSBaptiste Daroussin 	}
77661d06d6bSBaptiste Daroussin 
77761d06d6bSBaptiste Daroussin 	/*
77861d06d6bSBaptiste Daroussin 	 * Pad and break control.  This is the tricky part.  These flags
77961d06d6bSBaptiste Daroussin 	 * are documented in term_flushln() in term.c.  Note that we're
78061d06d6bSBaptiste Daroussin 	 * going to unset all of these flags in termp_it_post() when we
78161d06d6bSBaptiste Daroussin 	 * exit.
78261d06d6bSBaptiste Daroussin 	 */
78361d06d6bSBaptiste Daroussin 
78461d06d6bSBaptiste Daroussin 	switch (type) {
78561d06d6bSBaptiste Daroussin 	case LIST_enum:
78661d06d6bSBaptiste Daroussin 	case LIST_bullet:
78761d06d6bSBaptiste Daroussin 	case LIST_dash:
78861d06d6bSBaptiste Daroussin 	case LIST_hyphen:
78961d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD) {
79061d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOBREAK | TERMP_HANG;
79161d06d6bSBaptiste Daroussin 			p->trailspace = 1;
79261d06d6bSBaptiste Daroussin 		} else if (width <= (int)term_len(p, 2))
79361d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOPAD;
79461d06d6bSBaptiste Daroussin 		break;
79561d06d6bSBaptiste Daroussin 	case LIST_hang:
79661d06d6bSBaptiste Daroussin 		if (n->type != ROFFT_HEAD)
79761d06d6bSBaptiste Daroussin 			break;
79861d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG;
79961d06d6bSBaptiste Daroussin 		p->trailspace = 1;
80061d06d6bSBaptiste Daroussin 		break;
80161d06d6bSBaptiste Daroussin 	case LIST_tag:
80261d06d6bSBaptiste Daroussin 		if (n->type != ROFFT_HEAD)
80361d06d6bSBaptiste Daroussin 			break;
80461d06d6bSBaptiste Daroussin 
80561d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND;
80661d06d6bSBaptiste Daroussin 		p->trailspace = 2;
80761d06d6bSBaptiste Daroussin 
80861d06d6bSBaptiste Daroussin 		if (NULL == n->next || NULL == n->next->child)
80961d06d6bSBaptiste Daroussin 			p->flags |= TERMP_HANG;
81061d06d6bSBaptiste Daroussin 		break;
81161d06d6bSBaptiste Daroussin 	case LIST_column:
81261d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
81361d06d6bSBaptiste Daroussin 			break;
81461d06d6bSBaptiste Daroussin 
81561d06d6bSBaptiste Daroussin 		if (NULL == n->next) {
81661d06d6bSBaptiste Daroussin 			p->flags &= ~TERMP_NOBREAK;
81761d06d6bSBaptiste Daroussin 			p->trailspace = 0;
81861d06d6bSBaptiste Daroussin 		} else {
81961d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOBREAK;
82061d06d6bSBaptiste Daroussin 			p->trailspace = 1;
82161d06d6bSBaptiste Daroussin 		}
82261d06d6bSBaptiste Daroussin 
82361d06d6bSBaptiste Daroussin 		break;
82461d06d6bSBaptiste Daroussin 	case LIST_diag:
82561d06d6bSBaptiste Daroussin 		if (n->type != ROFFT_HEAD)
82661d06d6bSBaptiste Daroussin 			break;
82761d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOBREAK | TERMP_BRIND;
82861d06d6bSBaptiste Daroussin 		p->trailspace = 1;
82961d06d6bSBaptiste Daroussin 		break;
83061d06d6bSBaptiste Daroussin 	default:
83161d06d6bSBaptiste Daroussin 		break;
83261d06d6bSBaptiste Daroussin 	}
83361d06d6bSBaptiste Daroussin 
83461d06d6bSBaptiste Daroussin 	/*
83561d06d6bSBaptiste Daroussin 	 * Margin control.  Set-head-width lists have their right
83661d06d6bSBaptiste Daroussin 	 * margins shortened.  The body for these lists has the offset
83761d06d6bSBaptiste Daroussin 	 * necessarily lengthened.  Everybody gets the offset.
83861d06d6bSBaptiste Daroussin 	 */
83961d06d6bSBaptiste Daroussin 
84061d06d6bSBaptiste Daroussin 	p->tcol->offset += offset;
84161d06d6bSBaptiste Daroussin 
84261d06d6bSBaptiste Daroussin 	switch (type) {
84361d06d6bSBaptiste Daroussin 	case LIST_bullet:
84461d06d6bSBaptiste Daroussin 	case LIST_dash:
84561d06d6bSBaptiste Daroussin 	case LIST_enum:
84661d06d6bSBaptiste Daroussin 	case LIST_hyphen:
84761d06d6bSBaptiste Daroussin 	case LIST_hang:
84861d06d6bSBaptiste Daroussin 	case LIST_tag:
84961d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
85061d06d6bSBaptiste Daroussin 			p->tcol->rmargin = p->tcol->offset + width;
85161d06d6bSBaptiste Daroussin 		else
85261d06d6bSBaptiste Daroussin 			p->tcol->offset += width;
85361d06d6bSBaptiste Daroussin 		break;
85461d06d6bSBaptiste Daroussin 	case LIST_column:
85561d06d6bSBaptiste Daroussin 		assert(width);
85661d06d6bSBaptiste Daroussin 		p->tcol->rmargin = p->tcol->offset + width;
85761d06d6bSBaptiste Daroussin 		/*
85861d06d6bSBaptiste Daroussin 		 * XXX - this behaviour is not documented: the
85961d06d6bSBaptiste Daroussin 		 * right-most column is filled to the right margin.
86061d06d6bSBaptiste Daroussin 		 */
86161d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
86261d06d6bSBaptiste Daroussin 			break;
86361d06d6bSBaptiste Daroussin 		if (n->next == NULL && p->tcol->rmargin < p->maxrmargin)
86461d06d6bSBaptiste Daroussin 			p->tcol->rmargin = p->maxrmargin;
86561d06d6bSBaptiste Daroussin 		break;
86661d06d6bSBaptiste Daroussin 	default:
86761d06d6bSBaptiste Daroussin 		break;
86861d06d6bSBaptiste Daroussin 	}
86961d06d6bSBaptiste Daroussin 
87061d06d6bSBaptiste Daroussin 	/*
87161d06d6bSBaptiste Daroussin 	 * The dash, hyphen, bullet and enum lists all have a special
87261d06d6bSBaptiste Daroussin 	 * HEAD character (temporarily bold, in some cases).
87361d06d6bSBaptiste Daroussin 	 */
87461d06d6bSBaptiste Daroussin 
87561d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD)
87661d06d6bSBaptiste Daroussin 		switch (type) {
87761d06d6bSBaptiste Daroussin 		case LIST_bullet:
87861d06d6bSBaptiste Daroussin 			term_fontpush(p, TERMFONT_BOLD);
87961d06d6bSBaptiste Daroussin 			term_word(p, "\\[bu]");
88061d06d6bSBaptiste Daroussin 			term_fontpop(p);
88161d06d6bSBaptiste Daroussin 			break;
88261d06d6bSBaptiste Daroussin 		case LIST_dash:
88361d06d6bSBaptiste Daroussin 		case LIST_hyphen:
88461d06d6bSBaptiste Daroussin 			term_fontpush(p, TERMFONT_BOLD);
88561d06d6bSBaptiste Daroussin 			term_word(p, "-");
88661d06d6bSBaptiste Daroussin 			term_fontpop(p);
88761d06d6bSBaptiste Daroussin 			break;
88861d06d6bSBaptiste Daroussin 		case LIST_enum:
88961d06d6bSBaptiste Daroussin 			(pair->ppair->ppair->count)++;
89061d06d6bSBaptiste Daroussin 			(void)snprintf(buf, sizeof(buf), "%d.",
89161d06d6bSBaptiste Daroussin 			    pair->ppair->ppair->count);
89261d06d6bSBaptiste Daroussin 			term_word(p, buf);
89361d06d6bSBaptiste Daroussin 			break;
89461d06d6bSBaptiste Daroussin 		default:
89561d06d6bSBaptiste Daroussin 			break;
89661d06d6bSBaptiste Daroussin 		}
89761d06d6bSBaptiste Daroussin 
89861d06d6bSBaptiste Daroussin 	/*
89961d06d6bSBaptiste Daroussin 	 * If we're not going to process our children, indicate so here.
90061d06d6bSBaptiste Daroussin 	 */
90161d06d6bSBaptiste Daroussin 
90261d06d6bSBaptiste Daroussin 	switch (type) {
90361d06d6bSBaptiste Daroussin 	case LIST_bullet:
90461d06d6bSBaptiste Daroussin 	case LIST_item:
90561d06d6bSBaptiste Daroussin 	case LIST_dash:
90661d06d6bSBaptiste Daroussin 	case LIST_hyphen:
90761d06d6bSBaptiste Daroussin 	case LIST_enum:
90861d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
90961d06d6bSBaptiste Daroussin 			return 0;
91061d06d6bSBaptiste Daroussin 		break;
91161d06d6bSBaptiste Daroussin 	case LIST_column:
91261d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_HEAD)
91361d06d6bSBaptiste Daroussin 			return 0;
91461d06d6bSBaptiste Daroussin 		p->minbl = 0;
91561d06d6bSBaptiste Daroussin 		break;
91661d06d6bSBaptiste Daroussin 	default:
91761d06d6bSBaptiste Daroussin 		break;
91861d06d6bSBaptiste Daroussin 	}
91961d06d6bSBaptiste Daroussin 
92061d06d6bSBaptiste Daroussin 	return 1;
92161d06d6bSBaptiste Daroussin }
92261d06d6bSBaptiste Daroussin 
92361d06d6bSBaptiste Daroussin static void
92461d06d6bSBaptiste Daroussin termp_it_post(DECL_ARGS)
92561d06d6bSBaptiste Daroussin {
92661d06d6bSBaptiste Daroussin 	enum mdoc_list	   type;
92761d06d6bSBaptiste Daroussin 
92861d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK)
92961d06d6bSBaptiste Daroussin 		return;
93061d06d6bSBaptiste Daroussin 
93161d06d6bSBaptiste Daroussin 	type = n->parent->parent->parent->norm->Bl.type;
93261d06d6bSBaptiste Daroussin 
93361d06d6bSBaptiste Daroussin 	switch (type) {
93461d06d6bSBaptiste Daroussin 	case LIST_item:
93561d06d6bSBaptiste Daroussin 	case LIST_diag:
93661d06d6bSBaptiste Daroussin 	case LIST_inset:
93761d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_BODY)
93861d06d6bSBaptiste Daroussin 			term_newln(p);
93961d06d6bSBaptiste Daroussin 		break;
94061d06d6bSBaptiste Daroussin 	case LIST_column:
94161d06d6bSBaptiste Daroussin 		if (n->type == ROFFT_BODY)
94261d06d6bSBaptiste Daroussin 			term_flushln(p);
94361d06d6bSBaptiste Daroussin 		break;
94461d06d6bSBaptiste Daroussin 	default:
94561d06d6bSBaptiste Daroussin 		term_newln(p);
94661d06d6bSBaptiste Daroussin 		break;
94761d06d6bSBaptiste Daroussin 	}
94861d06d6bSBaptiste Daroussin 
94961d06d6bSBaptiste Daroussin 	/*
95061d06d6bSBaptiste Daroussin 	 * Now that our output is flushed, we can reset our tags.  Since
95161d06d6bSBaptiste Daroussin 	 * only `It' sets these flags, we're free to assume that nobody
95261d06d6bSBaptiste Daroussin 	 * has munged them in the meanwhile.
95361d06d6bSBaptiste Daroussin 	 */
95461d06d6bSBaptiste Daroussin 
95561d06d6bSBaptiste Daroussin 	p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND | TERMP_HANG);
95661d06d6bSBaptiste Daroussin 	p->trailspace = 0;
95761d06d6bSBaptiste Daroussin }
95861d06d6bSBaptiste Daroussin 
95961d06d6bSBaptiste Daroussin static int
96061d06d6bSBaptiste Daroussin termp_nm_pre(DECL_ARGS)
96161d06d6bSBaptiste Daroussin {
96261d06d6bSBaptiste Daroussin 	const char	*cp;
96361d06d6bSBaptiste Daroussin 
96461d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK) {
96561d06d6bSBaptiste Daroussin 		p->flags |= TERMP_PREKEEP;
96661d06d6bSBaptiste Daroussin 		return 1;
96761d06d6bSBaptiste Daroussin 	}
96861d06d6bSBaptiste Daroussin 
96961d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BODY) {
97061d06d6bSBaptiste Daroussin 		if (n->child == NULL)
97161d06d6bSBaptiste Daroussin 			return 0;
97261d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
97361d06d6bSBaptiste Daroussin 		cp = NULL;
97461d06d6bSBaptiste Daroussin 		if (n->prev->child != NULL)
97561d06d6bSBaptiste Daroussin 		    cp = n->prev->child->string;
97661d06d6bSBaptiste Daroussin 		if (cp == NULL)
97761d06d6bSBaptiste Daroussin 			cp = meta->name;
97861d06d6bSBaptiste Daroussin 		if (cp == NULL)
97961d06d6bSBaptiste Daroussin 			p->tcol->offset += term_len(p, 6);
98061d06d6bSBaptiste Daroussin 		else
98161d06d6bSBaptiste Daroussin 			p->tcol->offset += term_len(p, 1) +
98261d06d6bSBaptiste Daroussin 			    term_strlen(p, cp);
98361d06d6bSBaptiste Daroussin 		return 1;
98461d06d6bSBaptiste Daroussin 	}
98561d06d6bSBaptiste Daroussin 
98661d06d6bSBaptiste Daroussin 	if (n->child == NULL)
98761d06d6bSBaptiste Daroussin 		return 0;
98861d06d6bSBaptiste Daroussin 
98961d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD)
99061d06d6bSBaptiste Daroussin 		synopsis_pre(p, n->parent);
99161d06d6bSBaptiste Daroussin 
99261d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD &&
99361d06d6bSBaptiste Daroussin 	    n->next != NULL && n->next->child != NULL) {
99461d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE | TERMP_NOBREAK | TERMP_BRIND;
99561d06d6bSBaptiste Daroussin 		p->trailspace = 1;
99661d06d6bSBaptiste Daroussin 		p->tcol->rmargin = p->tcol->offset + term_len(p, 1);
99761d06d6bSBaptiste Daroussin 		if (n->child == NULL)
99861d06d6bSBaptiste Daroussin 			p->tcol->rmargin += term_strlen(p, meta->name);
99961d06d6bSBaptiste Daroussin 		else if (n->child->type == ROFFT_TEXT) {
100061d06d6bSBaptiste Daroussin 			p->tcol->rmargin += term_strlen(p, n->child->string);
100161d06d6bSBaptiste Daroussin 			if (n->child->next != NULL)
100261d06d6bSBaptiste Daroussin 				p->flags |= TERMP_HANG;
100361d06d6bSBaptiste Daroussin 		} else {
100461d06d6bSBaptiste Daroussin 			p->tcol->rmargin += term_len(p, 5);
100561d06d6bSBaptiste Daroussin 			p->flags |= TERMP_HANG;
100661d06d6bSBaptiste Daroussin 		}
100761d06d6bSBaptiste Daroussin 	}
1008*6d38604fSBaptiste Daroussin 	return termp_bold_pre(p, pair, meta, n);
100961d06d6bSBaptiste Daroussin }
101061d06d6bSBaptiste Daroussin 
101161d06d6bSBaptiste Daroussin static void
101261d06d6bSBaptiste Daroussin termp_nm_post(DECL_ARGS)
101361d06d6bSBaptiste Daroussin {
1014*6d38604fSBaptiste Daroussin 	switch (n->type) {
1015*6d38604fSBaptiste Daroussin 	case ROFFT_BLOCK:
101661d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1017*6d38604fSBaptiste Daroussin 		break;
1018*6d38604fSBaptiste Daroussin 	case ROFFT_HEAD:
1019*6d38604fSBaptiste Daroussin 		if (n->next == NULL || n->next->child == NULL)
1020*6d38604fSBaptiste Daroussin 			break;
102161d06d6bSBaptiste Daroussin 		term_flushln(p);
102261d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
102361d06d6bSBaptiste Daroussin 		p->trailspace = 0;
1024*6d38604fSBaptiste Daroussin 		break;
1025*6d38604fSBaptiste Daroussin 	case ROFFT_BODY:
1026*6d38604fSBaptiste Daroussin 		if (n->child != NULL)
102761d06d6bSBaptiste Daroussin 			term_flushln(p);
1028*6d38604fSBaptiste Daroussin 		break;
1029*6d38604fSBaptiste Daroussin 	default:
1030*6d38604fSBaptiste Daroussin 		break;
1031*6d38604fSBaptiste Daroussin 	}
103261d06d6bSBaptiste Daroussin }
103361d06d6bSBaptiste Daroussin 
103461d06d6bSBaptiste Daroussin static int
103561d06d6bSBaptiste Daroussin termp_fl_pre(DECL_ARGS)
103661d06d6bSBaptiste Daroussin {
1037*6d38604fSBaptiste Daroussin 	struct roff_node *nn;
103861d06d6bSBaptiste Daroussin 
103961d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_BOLD);
104061d06d6bSBaptiste Daroussin 	term_word(p, "\\-");
104161d06d6bSBaptiste Daroussin 
1042*6d38604fSBaptiste Daroussin 	if (n->child != NULL ||
1043*6d38604fSBaptiste Daroussin 	    ((nn = roff_node_next(n)) != NULL &&
1044*6d38604fSBaptiste Daroussin 	     nn->type != ROFFT_TEXT &&
1045*6d38604fSBaptiste Daroussin 	     (nn->flags & NODE_LINE) == 0))
104661d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
104761d06d6bSBaptiste Daroussin 
104861d06d6bSBaptiste Daroussin 	return 1;
104961d06d6bSBaptiste Daroussin }
105061d06d6bSBaptiste Daroussin 
105161d06d6bSBaptiste Daroussin static int
105261d06d6bSBaptiste Daroussin termp__a_pre(DECL_ARGS)
105361d06d6bSBaptiste Daroussin {
1054*6d38604fSBaptiste Daroussin 	struct roff_node *nn;
105561d06d6bSBaptiste Daroussin 
1056*6d38604fSBaptiste Daroussin 	if ((nn = roff_node_prev(n)) != NULL && nn->tok == MDOC__A &&
1057*6d38604fSBaptiste Daroussin 	    ((nn = roff_node_next(n)) == NULL || nn->tok != MDOC__A))
105861d06d6bSBaptiste Daroussin 		term_word(p, "and");
105961d06d6bSBaptiste Daroussin 
106061d06d6bSBaptiste Daroussin 	return 1;
106161d06d6bSBaptiste Daroussin }
106261d06d6bSBaptiste Daroussin 
106361d06d6bSBaptiste Daroussin static int
106461d06d6bSBaptiste Daroussin termp_an_pre(DECL_ARGS)
106561d06d6bSBaptiste Daroussin {
106661d06d6bSBaptiste Daroussin 
106761d06d6bSBaptiste Daroussin 	if (n->norm->An.auth == AUTH_split) {
106861d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_NOSPLIT;
106961d06d6bSBaptiste Daroussin 		p->flags |= TERMP_SPLIT;
107061d06d6bSBaptiste Daroussin 		return 0;
107161d06d6bSBaptiste Daroussin 	}
107261d06d6bSBaptiste Daroussin 	if (n->norm->An.auth == AUTH_nosplit) {
107361d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_SPLIT;
107461d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPLIT;
107561d06d6bSBaptiste Daroussin 		return 0;
107661d06d6bSBaptiste Daroussin 	}
107761d06d6bSBaptiste Daroussin 
107861d06d6bSBaptiste Daroussin 	if (p->flags & TERMP_SPLIT)
107961d06d6bSBaptiste Daroussin 		term_newln(p);
108061d06d6bSBaptiste Daroussin 
108161d06d6bSBaptiste Daroussin 	if (n->sec == SEC_AUTHORS && ! (p->flags & TERMP_NOSPLIT))
108261d06d6bSBaptiste Daroussin 		p->flags |= TERMP_SPLIT;
108361d06d6bSBaptiste Daroussin 
108461d06d6bSBaptiste Daroussin 	return 1;
108561d06d6bSBaptiste Daroussin }
108661d06d6bSBaptiste Daroussin 
108761d06d6bSBaptiste Daroussin static int
108861d06d6bSBaptiste Daroussin termp_ns_pre(DECL_ARGS)
108961d06d6bSBaptiste Daroussin {
109061d06d6bSBaptiste Daroussin 
109161d06d6bSBaptiste Daroussin 	if ( ! (NODE_LINE & n->flags))
109261d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
109361d06d6bSBaptiste Daroussin 	return 1;
109461d06d6bSBaptiste Daroussin }
109561d06d6bSBaptiste Daroussin 
109661d06d6bSBaptiste Daroussin static int
109761d06d6bSBaptiste Daroussin termp_rs_pre(DECL_ARGS)
109861d06d6bSBaptiste Daroussin {
109961d06d6bSBaptiste Daroussin 	if (SEC_SEE_ALSO != n->sec)
110061d06d6bSBaptiste Daroussin 		return 1;
1101*6d38604fSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK && roff_node_prev(n) != NULL)
110261d06d6bSBaptiste Daroussin 		term_vspace(p);
110361d06d6bSBaptiste Daroussin 	return 1;
110461d06d6bSBaptiste Daroussin }
110561d06d6bSBaptiste Daroussin 
110661d06d6bSBaptiste Daroussin static int
110761d06d6bSBaptiste Daroussin termp_ex_pre(DECL_ARGS)
110861d06d6bSBaptiste Daroussin {
110961d06d6bSBaptiste Daroussin 	term_newln(p);
111061d06d6bSBaptiste Daroussin 	return 1;
111161d06d6bSBaptiste Daroussin }
111261d06d6bSBaptiste Daroussin 
111361d06d6bSBaptiste Daroussin static int
111461d06d6bSBaptiste Daroussin termp_nd_pre(DECL_ARGS)
111561d06d6bSBaptiste Daroussin {
111661d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BODY)
111761d06d6bSBaptiste Daroussin 		term_word(p, "\\(en");
111861d06d6bSBaptiste Daroussin 	return 1;
111961d06d6bSBaptiste Daroussin }
112061d06d6bSBaptiste Daroussin 
112161d06d6bSBaptiste Daroussin static int
112261d06d6bSBaptiste Daroussin termp_bl_pre(DECL_ARGS)
112361d06d6bSBaptiste Daroussin {
1124*6d38604fSBaptiste Daroussin 	switch (n->type) {
1125*6d38604fSBaptiste Daroussin 	case ROFFT_BLOCK:
1126*6d38604fSBaptiste Daroussin 		term_newln(p);
1127*6d38604fSBaptiste Daroussin 		return 1;
1128*6d38604fSBaptiste Daroussin 	case ROFFT_HEAD:
1129*6d38604fSBaptiste Daroussin 		return 0;
1130*6d38604fSBaptiste Daroussin 	default:
1131*6d38604fSBaptiste Daroussin 		return 1;
1132*6d38604fSBaptiste Daroussin 	}
113361d06d6bSBaptiste Daroussin }
113461d06d6bSBaptiste Daroussin 
113561d06d6bSBaptiste Daroussin static void
113661d06d6bSBaptiste Daroussin termp_bl_post(DECL_ARGS)
113761d06d6bSBaptiste Daroussin {
113861d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BLOCK)
113961d06d6bSBaptiste Daroussin 		return;
114061d06d6bSBaptiste Daroussin 	term_newln(p);
114161d06d6bSBaptiste Daroussin 	if (n->tok != MDOC_Bl || n->norm->Bl.type != LIST_column)
114261d06d6bSBaptiste Daroussin 		return;
114361d06d6bSBaptiste Daroussin 	term_tab_set(p, NULL);
114461d06d6bSBaptiste Daroussin 	term_tab_set(p, "T");
114561d06d6bSBaptiste Daroussin 	term_tab_set(p, ".5i");
114661d06d6bSBaptiste Daroussin }
114761d06d6bSBaptiste Daroussin 
114861d06d6bSBaptiste Daroussin static int
114961d06d6bSBaptiste Daroussin termp_xr_pre(DECL_ARGS)
115061d06d6bSBaptiste Daroussin {
115161d06d6bSBaptiste Daroussin 	if (NULL == (n = n->child))
115261d06d6bSBaptiste Daroussin 		return 0;
115361d06d6bSBaptiste Daroussin 
115461d06d6bSBaptiste Daroussin 	assert(n->type == ROFFT_TEXT);
115561d06d6bSBaptiste Daroussin 	term_word(p, n->string);
115661d06d6bSBaptiste Daroussin 
115761d06d6bSBaptiste Daroussin 	if (NULL == (n = n->next))
115861d06d6bSBaptiste Daroussin 		return 0;
115961d06d6bSBaptiste Daroussin 
116061d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
116161d06d6bSBaptiste Daroussin 	term_word(p, "(");
116261d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
116361d06d6bSBaptiste Daroussin 
116461d06d6bSBaptiste Daroussin 	assert(n->type == ROFFT_TEXT);
116561d06d6bSBaptiste Daroussin 	term_word(p, n->string);
116661d06d6bSBaptiste Daroussin 
116761d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
116861d06d6bSBaptiste Daroussin 	term_word(p, ")");
116961d06d6bSBaptiste Daroussin 
117061d06d6bSBaptiste Daroussin 	return 0;
117161d06d6bSBaptiste Daroussin }
117261d06d6bSBaptiste Daroussin 
117361d06d6bSBaptiste Daroussin /*
117461d06d6bSBaptiste Daroussin  * This decides how to assert whitespace before any of the SYNOPSIS set
117561d06d6bSBaptiste Daroussin  * of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
117661d06d6bSBaptiste Daroussin  * macro combos).
117761d06d6bSBaptiste Daroussin  */
117861d06d6bSBaptiste Daroussin static void
1179*6d38604fSBaptiste Daroussin synopsis_pre(struct termp *p, struct roff_node *n)
118061d06d6bSBaptiste Daroussin {
1181*6d38604fSBaptiste Daroussin 	struct roff_node	*np;
1182*6d38604fSBaptiste Daroussin 
1183*6d38604fSBaptiste Daroussin 	if ((n->flags & NODE_SYNPRETTY) == 0 ||
1184*6d38604fSBaptiste Daroussin 	    (np = roff_node_prev(n)) == NULL)
118561d06d6bSBaptiste Daroussin 		return;
118661d06d6bSBaptiste Daroussin 
118761d06d6bSBaptiste Daroussin 	/*
118861d06d6bSBaptiste Daroussin 	 * If we're the second in a pair of like elements, emit our
118961d06d6bSBaptiste Daroussin 	 * newline and return.  UNLESS we're `Fo', `Fn', `Fn', in which
119061d06d6bSBaptiste Daroussin 	 * case we soldier on.
119161d06d6bSBaptiste Daroussin 	 */
1192*6d38604fSBaptiste Daroussin 	if (np->tok == n->tok &&
119361d06d6bSBaptiste Daroussin 	    MDOC_Ft != n->tok &&
119461d06d6bSBaptiste Daroussin 	    MDOC_Fo != n->tok &&
119561d06d6bSBaptiste Daroussin 	    MDOC_Fn != n->tok) {
119661d06d6bSBaptiste Daroussin 		term_newln(p);
119761d06d6bSBaptiste Daroussin 		return;
119861d06d6bSBaptiste Daroussin 	}
119961d06d6bSBaptiste Daroussin 
120061d06d6bSBaptiste Daroussin 	/*
120161d06d6bSBaptiste Daroussin 	 * If we're one of the SYNOPSIS set and non-like pair-wise after
120261d06d6bSBaptiste Daroussin 	 * another (or Fn/Fo, which we've let slip through) then assert
120361d06d6bSBaptiste Daroussin 	 * vertical space, else only newline and move on.
120461d06d6bSBaptiste Daroussin 	 */
1205*6d38604fSBaptiste Daroussin 	switch (np->tok) {
120661d06d6bSBaptiste Daroussin 	case MDOC_Fd:
120761d06d6bSBaptiste Daroussin 	case MDOC_Fn:
120861d06d6bSBaptiste Daroussin 	case MDOC_Fo:
120961d06d6bSBaptiste Daroussin 	case MDOC_In:
121061d06d6bSBaptiste Daroussin 	case MDOC_Vt:
121161d06d6bSBaptiste Daroussin 		term_vspace(p);
121261d06d6bSBaptiste Daroussin 		break;
121361d06d6bSBaptiste Daroussin 	case MDOC_Ft:
1214*6d38604fSBaptiste Daroussin 		if (n->tok != MDOC_Fn && n->tok != MDOC_Fo) {
121561d06d6bSBaptiste Daroussin 			term_vspace(p);
121661d06d6bSBaptiste Daroussin 			break;
121761d06d6bSBaptiste Daroussin 		}
121861d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
121961d06d6bSBaptiste Daroussin 	default:
122061d06d6bSBaptiste Daroussin 		term_newln(p);
122161d06d6bSBaptiste Daroussin 		break;
122261d06d6bSBaptiste Daroussin 	}
122361d06d6bSBaptiste Daroussin }
122461d06d6bSBaptiste Daroussin 
122561d06d6bSBaptiste Daroussin static int
122661d06d6bSBaptiste Daroussin termp_vt_pre(DECL_ARGS)
122761d06d6bSBaptiste Daroussin {
1228*6d38604fSBaptiste Daroussin 	switch (n->type) {
1229*6d38604fSBaptiste Daroussin 	case ROFFT_ELEM:
1230*6d38604fSBaptiste Daroussin 		return termp_ft_pre(p, pair, meta, n);
1231*6d38604fSBaptiste Daroussin 	case ROFFT_BLOCK:
123261d06d6bSBaptiste Daroussin 		synopsis_pre(p, n);
123361d06d6bSBaptiste Daroussin 		return 1;
1234*6d38604fSBaptiste Daroussin 	case ROFFT_HEAD:
123561d06d6bSBaptiste Daroussin 		return 0;
1236*6d38604fSBaptiste Daroussin 	default:
123761d06d6bSBaptiste Daroussin 		return termp_under_pre(p, pair, meta, n);
123861d06d6bSBaptiste Daroussin 	}
1239*6d38604fSBaptiste Daroussin }
124061d06d6bSBaptiste Daroussin 
124161d06d6bSBaptiste Daroussin static int
124261d06d6bSBaptiste Daroussin termp_bold_pre(DECL_ARGS)
124361d06d6bSBaptiste Daroussin {
124461d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_BOLD);
124561d06d6bSBaptiste Daroussin 	return 1;
124661d06d6bSBaptiste Daroussin }
124761d06d6bSBaptiste Daroussin 
124861d06d6bSBaptiste Daroussin static int
124961d06d6bSBaptiste Daroussin termp_fd_pre(DECL_ARGS)
125061d06d6bSBaptiste Daroussin {
125161d06d6bSBaptiste Daroussin 	synopsis_pre(p, n);
125261d06d6bSBaptiste Daroussin 	return termp_bold_pre(p, pair, meta, n);
125361d06d6bSBaptiste Daroussin }
125461d06d6bSBaptiste Daroussin 
125561d06d6bSBaptiste Daroussin static void
125661d06d6bSBaptiste Daroussin termp_fd_post(DECL_ARGS)
125761d06d6bSBaptiste Daroussin {
125861d06d6bSBaptiste Daroussin 	term_newln(p);
125961d06d6bSBaptiste Daroussin }
126061d06d6bSBaptiste Daroussin 
126161d06d6bSBaptiste Daroussin static int
126261d06d6bSBaptiste Daroussin termp_sh_pre(DECL_ARGS)
126361d06d6bSBaptiste Daroussin {
1264*6d38604fSBaptiste Daroussin 	struct roff_node	*np;
126561d06d6bSBaptiste Daroussin 
126661d06d6bSBaptiste Daroussin 	switch (n->type) {
126761d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
126861d06d6bSBaptiste Daroussin 		/*
126961d06d6bSBaptiste Daroussin 		 * Vertical space before sections, except
127061d06d6bSBaptiste Daroussin 		 * when the previous section was empty.
127161d06d6bSBaptiste Daroussin 		 */
1272*6d38604fSBaptiste Daroussin 		if ((np = roff_node_prev(n)) == NULL ||
1273*6d38604fSBaptiste Daroussin 		    np->tok != MDOC_Sh ||
1274*6d38604fSBaptiste Daroussin 		    (np->body != NULL && np->body->child != NULL))
127561d06d6bSBaptiste Daroussin 			term_vspace(p);
127661d06d6bSBaptiste Daroussin 		break;
127761d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
1278*6d38604fSBaptiste Daroussin 		return termp_bold_pre(p, pair, meta, n);
127961d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
128061d06d6bSBaptiste Daroussin 		p->tcol->offset = term_len(p, p->defindent);
128161d06d6bSBaptiste Daroussin 		term_tab_set(p, NULL);
128261d06d6bSBaptiste Daroussin 		term_tab_set(p, "T");
128361d06d6bSBaptiste Daroussin 		term_tab_set(p, ".5i");
1284*6d38604fSBaptiste Daroussin 		if (n->sec == SEC_AUTHORS)
128561d06d6bSBaptiste Daroussin 			p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
128661d06d6bSBaptiste Daroussin 		break;
128761d06d6bSBaptiste Daroussin 	default:
128861d06d6bSBaptiste Daroussin 		break;
128961d06d6bSBaptiste Daroussin 	}
129061d06d6bSBaptiste Daroussin 	return 1;
129161d06d6bSBaptiste Daroussin }
129261d06d6bSBaptiste Daroussin 
129361d06d6bSBaptiste Daroussin static void
129461d06d6bSBaptiste Daroussin termp_sh_post(DECL_ARGS)
129561d06d6bSBaptiste Daroussin {
129661d06d6bSBaptiste Daroussin 	switch (n->type) {
129761d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
129861d06d6bSBaptiste Daroussin 		term_newln(p);
129961d06d6bSBaptiste Daroussin 		break;
130061d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
130161d06d6bSBaptiste Daroussin 		term_newln(p);
130261d06d6bSBaptiste Daroussin 		p->tcol->offset = 0;
130361d06d6bSBaptiste Daroussin 		break;
130461d06d6bSBaptiste Daroussin 	default:
130561d06d6bSBaptiste Daroussin 		break;
130661d06d6bSBaptiste Daroussin 	}
130761d06d6bSBaptiste Daroussin }
130861d06d6bSBaptiste Daroussin 
130961d06d6bSBaptiste Daroussin static void
131061d06d6bSBaptiste Daroussin termp_lb_post(DECL_ARGS)
131161d06d6bSBaptiste Daroussin {
1312*6d38604fSBaptiste Daroussin 	if (n->sec == SEC_LIBRARY && n->flags & NODE_LINE)
131361d06d6bSBaptiste Daroussin 		term_newln(p);
131461d06d6bSBaptiste Daroussin }
131561d06d6bSBaptiste Daroussin 
131661d06d6bSBaptiste Daroussin static int
131761d06d6bSBaptiste Daroussin termp_d1_pre(DECL_ARGS)
131861d06d6bSBaptiste Daroussin {
131961d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BLOCK)
132061d06d6bSBaptiste Daroussin 		return 1;
132161d06d6bSBaptiste Daroussin 	term_newln(p);
132261d06d6bSBaptiste Daroussin 	p->tcol->offset += term_len(p, p->defindent + 1);
132361d06d6bSBaptiste Daroussin 	term_tab_set(p, NULL);
132461d06d6bSBaptiste Daroussin 	term_tab_set(p, "T");
132561d06d6bSBaptiste Daroussin 	term_tab_set(p, ".5i");
132661d06d6bSBaptiste Daroussin 	return 1;
132761d06d6bSBaptiste Daroussin }
132861d06d6bSBaptiste Daroussin 
132961d06d6bSBaptiste Daroussin static int
133061d06d6bSBaptiste Daroussin termp_ft_pre(DECL_ARGS)
133161d06d6bSBaptiste Daroussin {
133261d06d6bSBaptiste Daroussin 	synopsis_pre(p, n);
1333*6d38604fSBaptiste Daroussin 	return termp_under_pre(p, pair, meta, n);
133461d06d6bSBaptiste Daroussin }
133561d06d6bSBaptiste Daroussin 
133661d06d6bSBaptiste Daroussin static int
133761d06d6bSBaptiste Daroussin termp_fn_pre(DECL_ARGS)
133861d06d6bSBaptiste Daroussin {
133961d06d6bSBaptiste Daroussin 	size_t		 rmargin = 0;
134061d06d6bSBaptiste Daroussin 	int		 pretty;
134161d06d6bSBaptiste Daroussin 
134261d06d6bSBaptiste Daroussin 	synopsis_pre(p, n);
1343*6d38604fSBaptiste Daroussin 	pretty = n->flags & NODE_SYNPRETTY;
1344*6d38604fSBaptiste Daroussin 	if ((n = n->child) == NULL)
134561d06d6bSBaptiste Daroussin 		return 0;
134661d06d6bSBaptiste Daroussin 
134761d06d6bSBaptiste Daroussin 	if (pretty) {
134861d06d6bSBaptiste Daroussin 		rmargin = p->tcol->rmargin;
134961d06d6bSBaptiste Daroussin 		p->tcol->rmargin = p->tcol->offset + term_len(p, 4);
135061d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG;
135161d06d6bSBaptiste Daroussin 	}
135261d06d6bSBaptiste Daroussin 
135361d06d6bSBaptiste Daroussin 	assert(n->type == ROFFT_TEXT);
135461d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_BOLD);
135561d06d6bSBaptiste Daroussin 	term_word(p, n->string);
135661d06d6bSBaptiste Daroussin 	term_fontpop(p);
135761d06d6bSBaptiste Daroussin 
135861d06d6bSBaptiste Daroussin 	if (pretty) {
135961d06d6bSBaptiste Daroussin 		term_flushln(p);
136061d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
136161d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOPAD;
136261d06d6bSBaptiste Daroussin 		p->tcol->offset = p->tcol->rmargin;
136361d06d6bSBaptiste Daroussin 		p->tcol->rmargin = rmargin;
136461d06d6bSBaptiste Daroussin 	}
136561d06d6bSBaptiste Daroussin 
136661d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
136761d06d6bSBaptiste Daroussin 	term_word(p, "(");
136861d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
136961d06d6bSBaptiste Daroussin 
137061d06d6bSBaptiste Daroussin 	for (n = n->next; n; n = n->next) {
137161d06d6bSBaptiste Daroussin 		assert(n->type == ROFFT_TEXT);
137261d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_UNDER);
137361d06d6bSBaptiste Daroussin 		if (pretty)
137461d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NBRWORD;
137561d06d6bSBaptiste Daroussin 		term_word(p, n->string);
137661d06d6bSBaptiste Daroussin 		term_fontpop(p);
137761d06d6bSBaptiste Daroussin 
137861d06d6bSBaptiste Daroussin 		if (n->next) {
137961d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
138061d06d6bSBaptiste Daroussin 			term_word(p, ",");
138161d06d6bSBaptiste Daroussin 		}
138261d06d6bSBaptiste Daroussin 	}
138361d06d6bSBaptiste Daroussin 
138461d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
138561d06d6bSBaptiste Daroussin 	term_word(p, ")");
138661d06d6bSBaptiste Daroussin 
138761d06d6bSBaptiste Daroussin 	if (pretty) {
138861d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
138961d06d6bSBaptiste Daroussin 		term_word(p, ";");
139061d06d6bSBaptiste Daroussin 		term_flushln(p);
139161d06d6bSBaptiste Daroussin 	}
139261d06d6bSBaptiste Daroussin 	return 0;
139361d06d6bSBaptiste Daroussin }
139461d06d6bSBaptiste Daroussin 
139561d06d6bSBaptiste Daroussin static int
139661d06d6bSBaptiste Daroussin termp_fa_pre(DECL_ARGS)
139761d06d6bSBaptiste Daroussin {
139861d06d6bSBaptiste Daroussin 	const struct roff_node	*nn;
139961d06d6bSBaptiste Daroussin 
1400*6d38604fSBaptiste Daroussin 	if (n->parent->tok != MDOC_Fo)
1401*6d38604fSBaptiste Daroussin 		return termp_under_pre(p, pair, meta, n);
140261d06d6bSBaptiste Daroussin 
1403*6d38604fSBaptiste Daroussin 	for (nn = n->child; nn != NULL; nn = nn->next) {
140461d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_UNDER);
140561d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NBRWORD;
140661d06d6bSBaptiste Daroussin 		term_word(p, nn->string);
140761d06d6bSBaptiste Daroussin 		term_fontpop(p);
1408*6d38604fSBaptiste Daroussin 		if (nn->next != NULL) {
140961d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOSPACE;
141061d06d6bSBaptiste Daroussin 			term_word(p, ",");
141161d06d6bSBaptiste Daroussin 		}
141261d06d6bSBaptiste Daroussin 	}
1413*6d38604fSBaptiste Daroussin 	if (n->child != NULL &&
1414*6d38604fSBaptiste Daroussin 	    (nn = roff_node_next(n)) != NULL &&
1415*6d38604fSBaptiste Daroussin 	    nn->tok == MDOC_Fa) {
1416*6d38604fSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
1417*6d38604fSBaptiste Daroussin 		term_word(p, ",");
1418*6d38604fSBaptiste Daroussin 	}
141961d06d6bSBaptiste Daroussin 	return 0;
142061d06d6bSBaptiste Daroussin }
142161d06d6bSBaptiste Daroussin 
142261d06d6bSBaptiste Daroussin static int
142361d06d6bSBaptiste Daroussin termp_bd_pre(DECL_ARGS)
142461d06d6bSBaptiste Daroussin {
142561d06d6bSBaptiste Daroussin 	int			 offset;
142661d06d6bSBaptiste Daroussin 
142761d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BLOCK) {
142861d06d6bSBaptiste Daroussin 		print_bvspace(p, n, n);
142961d06d6bSBaptiste Daroussin 		return 1;
143061d06d6bSBaptiste Daroussin 	} else if (n->type == ROFFT_HEAD)
143161d06d6bSBaptiste Daroussin 		return 0;
143261d06d6bSBaptiste Daroussin 
143361d06d6bSBaptiste Daroussin 	/* Handle the -offset argument. */
143461d06d6bSBaptiste Daroussin 
143561d06d6bSBaptiste Daroussin 	if (n->norm->Bd.offs == NULL ||
143661d06d6bSBaptiste Daroussin 	    ! strcmp(n->norm->Bd.offs, "left"))
143761d06d6bSBaptiste Daroussin 		/* nothing */;
143861d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->norm->Bd.offs, "indent"))
143961d06d6bSBaptiste Daroussin 		p->tcol->offset += term_len(p, p->defindent + 1);
144061d06d6bSBaptiste Daroussin 	else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
144161d06d6bSBaptiste Daroussin 		p->tcol->offset += term_len(p, (p->defindent + 1) * 2);
144261d06d6bSBaptiste Daroussin 	else {
144361d06d6bSBaptiste Daroussin 		offset = a2width(p, n->norm->Bd.offs);
144461d06d6bSBaptiste Daroussin 		if (offset < 0 && (size_t)(-offset) > p->tcol->offset)
144561d06d6bSBaptiste Daroussin 			p->tcol->offset = 0;
144661d06d6bSBaptiste Daroussin 		else if (offset < SHRT_MAX)
144761d06d6bSBaptiste Daroussin 			p->tcol->offset += offset;
144861d06d6bSBaptiste Daroussin 	}
144961d06d6bSBaptiste Daroussin 
14507295610fSBaptiste Daroussin 	switch (n->norm->Bd.type) {
14517295610fSBaptiste Daroussin 	case DISP_literal:
145261d06d6bSBaptiste Daroussin 		term_tab_set(p, NULL);
145361d06d6bSBaptiste Daroussin 		term_tab_set(p, "T");
145461d06d6bSBaptiste Daroussin 		term_tab_set(p, "8n");
14557295610fSBaptiste Daroussin 		break;
14567295610fSBaptiste Daroussin 	case DISP_centered:
14577295610fSBaptiste Daroussin 		p->flags |= TERMP_CENTER;
14587295610fSBaptiste Daroussin 		break;
145961d06d6bSBaptiste Daroussin 	default:
146061d06d6bSBaptiste Daroussin 		break;
146161d06d6bSBaptiste Daroussin 	}
14627295610fSBaptiste Daroussin 	return 1;
146361d06d6bSBaptiste Daroussin }
146461d06d6bSBaptiste Daroussin 
146561d06d6bSBaptiste Daroussin static void
146661d06d6bSBaptiste Daroussin termp_bd_post(DECL_ARGS)
146761d06d6bSBaptiste Daroussin {
146861d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY)
146961d06d6bSBaptiste Daroussin 		return;
14707295610fSBaptiste Daroussin 	if (n->norm->Bd.type == DISP_unfilled ||
14717295610fSBaptiste Daroussin 	    n->norm->Bd.type == DISP_literal)
147261d06d6bSBaptiste Daroussin 		p->flags |= TERMP_BRNEVER;
147361d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
147461d06d6bSBaptiste Daroussin 	term_newln(p);
147561d06d6bSBaptiste Daroussin 	p->flags &= ~TERMP_BRNEVER;
14767295610fSBaptiste Daroussin 	if (n->norm->Bd.type == DISP_centered)
14777295610fSBaptiste Daroussin 		p->flags &= ~TERMP_CENTER;
147861d06d6bSBaptiste Daroussin }
147961d06d6bSBaptiste Daroussin 
148061d06d6bSBaptiste Daroussin static int
148161d06d6bSBaptiste Daroussin termp_xx_pre(DECL_ARGS)
148261d06d6bSBaptiste Daroussin {
148361d06d6bSBaptiste Daroussin 	if ((n->aux = p->flags & TERMP_PREKEEP) == 0)
148461d06d6bSBaptiste Daroussin 		p->flags |= TERMP_PREKEEP;
148561d06d6bSBaptiste Daroussin 	return 1;
148661d06d6bSBaptiste Daroussin }
148761d06d6bSBaptiste Daroussin 
148861d06d6bSBaptiste Daroussin static void
148961d06d6bSBaptiste Daroussin termp_xx_post(DECL_ARGS)
149061d06d6bSBaptiste Daroussin {
149161d06d6bSBaptiste Daroussin 	if (n->aux == 0)
149261d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
149361d06d6bSBaptiste Daroussin }
149461d06d6bSBaptiste Daroussin 
149561d06d6bSBaptiste Daroussin static void
149661d06d6bSBaptiste Daroussin termp_pf_post(DECL_ARGS)
149761d06d6bSBaptiste Daroussin {
1498*6d38604fSBaptiste Daroussin 	if (n->next != NULL && (n->next->flags & NODE_LINE) == 0)
149961d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
150061d06d6bSBaptiste Daroussin }
150161d06d6bSBaptiste Daroussin 
150261d06d6bSBaptiste Daroussin static int
150361d06d6bSBaptiste Daroussin termp_ss_pre(DECL_ARGS)
150461d06d6bSBaptiste Daroussin {
150561d06d6bSBaptiste Daroussin 	switch (n->type) {
150661d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
1507*6d38604fSBaptiste Daroussin 		if (roff_node_prev(n) == NULL)
150861d06d6bSBaptiste Daroussin 			term_newln(p);
1509*6d38604fSBaptiste Daroussin 		else
151061d06d6bSBaptiste Daroussin 			term_vspace(p);
151161d06d6bSBaptiste Daroussin 		break;
151261d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
151361d06d6bSBaptiste Daroussin 		p->tcol->offset = term_len(p, (p->defindent+1)/2);
1514*6d38604fSBaptiste Daroussin 		return termp_bold_pre(p, pair, meta, n);
151561d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
151661d06d6bSBaptiste Daroussin 		p->tcol->offset = term_len(p, p->defindent);
151761d06d6bSBaptiste Daroussin 		term_tab_set(p, NULL);
151861d06d6bSBaptiste Daroussin 		term_tab_set(p, "T");
151961d06d6bSBaptiste Daroussin 		term_tab_set(p, ".5i");
152061d06d6bSBaptiste Daroussin 		break;
152161d06d6bSBaptiste Daroussin 	default:
152261d06d6bSBaptiste Daroussin 		break;
152361d06d6bSBaptiste Daroussin 	}
152461d06d6bSBaptiste Daroussin 	return 1;
152561d06d6bSBaptiste Daroussin }
152661d06d6bSBaptiste Daroussin 
152761d06d6bSBaptiste Daroussin static void
152861d06d6bSBaptiste Daroussin termp_ss_post(DECL_ARGS)
152961d06d6bSBaptiste Daroussin {
153061d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_HEAD || n->type == ROFFT_BODY)
153161d06d6bSBaptiste Daroussin 		term_newln(p);
153261d06d6bSBaptiste Daroussin }
153361d06d6bSBaptiste Daroussin 
153461d06d6bSBaptiste Daroussin static int
153561d06d6bSBaptiste Daroussin termp_in_pre(DECL_ARGS)
153661d06d6bSBaptiste Daroussin {
153761d06d6bSBaptiste Daroussin 	synopsis_pre(p, n);
1538*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY && n->flags & NODE_LINE) {
153961d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_BOLD);
154061d06d6bSBaptiste Daroussin 		term_word(p, "#include");
154161d06d6bSBaptiste Daroussin 		term_word(p, "<");
154261d06d6bSBaptiste Daroussin 	} else {
154361d06d6bSBaptiste Daroussin 		term_word(p, "<");
154461d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_UNDER);
154561d06d6bSBaptiste Daroussin 	}
154661d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
154761d06d6bSBaptiste Daroussin 	return 1;
154861d06d6bSBaptiste Daroussin }
154961d06d6bSBaptiste Daroussin 
155061d06d6bSBaptiste Daroussin static void
155161d06d6bSBaptiste Daroussin termp_in_post(DECL_ARGS)
155261d06d6bSBaptiste Daroussin {
1553*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY)
155461d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_BOLD);
155561d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
155661d06d6bSBaptiste Daroussin 	term_word(p, ">");
1557*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY)
155861d06d6bSBaptiste Daroussin 		term_fontpop(p);
155961d06d6bSBaptiste Daroussin }
156061d06d6bSBaptiste Daroussin 
156161d06d6bSBaptiste Daroussin static int
156261d06d6bSBaptiste Daroussin termp_pp_pre(DECL_ARGS)
156361d06d6bSBaptiste Daroussin {
156461d06d6bSBaptiste Daroussin 	term_vspace(p);
1565*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_ID)
1566*6d38604fSBaptiste Daroussin 		term_tag_write(n, p->line);
156761d06d6bSBaptiste Daroussin 	return 0;
156861d06d6bSBaptiste Daroussin }
156961d06d6bSBaptiste Daroussin 
157061d06d6bSBaptiste Daroussin static int
157161d06d6bSBaptiste Daroussin termp_skip_pre(DECL_ARGS)
157261d06d6bSBaptiste Daroussin {
157361d06d6bSBaptiste Daroussin 	return 0;
157461d06d6bSBaptiste Daroussin }
157561d06d6bSBaptiste Daroussin 
157661d06d6bSBaptiste Daroussin static int
157761d06d6bSBaptiste Daroussin termp_quote_pre(DECL_ARGS)
157861d06d6bSBaptiste Daroussin {
157961d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM)
158061d06d6bSBaptiste Daroussin 		return 1;
158161d06d6bSBaptiste Daroussin 
158261d06d6bSBaptiste Daroussin 	switch (n->tok) {
158361d06d6bSBaptiste Daroussin 	case MDOC_Ao:
158461d06d6bSBaptiste Daroussin 	case MDOC_Aq:
158561d06d6bSBaptiste Daroussin 		term_word(p, n->child != NULL && n->child->next == NULL &&
158661d06d6bSBaptiste Daroussin 		    n->child->tok == MDOC_Mt ? "<" : "\\(la");
158761d06d6bSBaptiste Daroussin 		break;
158861d06d6bSBaptiste Daroussin 	case MDOC_Bro:
158961d06d6bSBaptiste Daroussin 	case MDOC_Brq:
159061d06d6bSBaptiste Daroussin 		term_word(p, "{");
159161d06d6bSBaptiste Daroussin 		break;
159261d06d6bSBaptiste Daroussin 	case MDOC_Oo:
159361d06d6bSBaptiste Daroussin 	case MDOC_Op:
159461d06d6bSBaptiste Daroussin 	case MDOC_Bo:
159561d06d6bSBaptiste Daroussin 	case MDOC_Bq:
159661d06d6bSBaptiste Daroussin 		term_word(p, "[");
159761d06d6bSBaptiste Daroussin 		break;
159861d06d6bSBaptiste Daroussin 	case MDOC__T:
159961d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
160061d06d6bSBaptiste Daroussin 	case MDOC_Do:
160161d06d6bSBaptiste Daroussin 	case MDOC_Dq:
160261d06d6bSBaptiste Daroussin 		term_word(p, "\\(lq");
160361d06d6bSBaptiste Daroussin 		break;
160461d06d6bSBaptiste Daroussin 	case MDOC_En:
160561d06d6bSBaptiste Daroussin 		if (NULL == n->norm->Es ||
160661d06d6bSBaptiste Daroussin 		    NULL == n->norm->Es->child)
160761d06d6bSBaptiste Daroussin 			return 1;
160861d06d6bSBaptiste Daroussin 		term_word(p, n->norm->Es->child->string);
160961d06d6bSBaptiste Daroussin 		break;
161061d06d6bSBaptiste Daroussin 	case MDOC_Po:
161161d06d6bSBaptiste Daroussin 	case MDOC_Pq:
161261d06d6bSBaptiste Daroussin 		term_word(p, "(");
161361d06d6bSBaptiste Daroussin 		break;
161461d06d6bSBaptiste Daroussin 	case MDOC_Qo:
161561d06d6bSBaptiste Daroussin 	case MDOC_Qq:
161661d06d6bSBaptiste Daroussin 		term_word(p, "\"");
161761d06d6bSBaptiste Daroussin 		break;
161861d06d6bSBaptiste Daroussin 	case MDOC_Ql:
161961d06d6bSBaptiste Daroussin 	case MDOC_So:
162061d06d6bSBaptiste Daroussin 	case MDOC_Sq:
162161d06d6bSBaptiste Daroussin 		term_word(p, "\\(oq");
162261d06d6bSBaptiste Daroussin 		break;
162361d06d6bSBaptiste Daroussin 	default:
162461d06d6bSBaptiste Daroussin 		abort();
162561d06d6bSBaptiste Daroussin 	}
162661d06d6bSBaptiste Daroussin 
162761d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
162861d06d6bSBaptiste Daroussin 	return 1;
162961d06d6bSBaptiste Daroussin }
163061d06d6bSBaptiste Daroussin 
163161d06d6bSBaptiste Daroussin static void
163261d06d6bSBaptiste Daroussin termp_quote_post(DECL_ARGS)
163361d06d6bSBaptiste Daroussin {
163461d06d6bSBaptiste Daroussin 
163561d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM)
163661d06d6bSBaptiste Daroussin 		return;
163761d06d6bSBaptiste Daroussin 
163861d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
163961d06d6bSBaptiste Daroussin 
164061d06d6bSBaptiste Daroussin 	switch (n->tok) {
164161d06d6bSBaptiste Daroussin 	case MDOC_Ao:
164261d06d6bSBaptiste Daroussin 	case MDOC_Aq:
164361d06d6bSBaptiste Daroussin 		term_word(p, n->child != NULL && n->child->next == NULL &&
164461d06d6bSBaptiste Daroussin 		    n->child->tok == MDOC_Mt ? ">" : "\\(ra");
164561d06d6bSBaptiste Daroussin 		break;
164661d06d6bSBaptiste Daroussin 	case MDOC_Bro:
164761d06d6bSBaptiste Daroussin 	case MDOC_Brq:
164861d06d6bSBaptiste Daroussin 		term_word(p, "}");
164961d06d6bSBaptiste Daroussin 		break;
165061d06d6bSBaptiste Daroussin 	case MDOC_Oo:
165161d06d6bSBaptiste Daroussin 	case MDOC_Op:
165261d06d6bSBaptiste Daroussin 	case MDOC_Bo:
165361d06d6bSBaptiste Daroussin 	case MDOC_Bq:
165461d06d6bSBaptiste Daroussin 		term_word(p, "]");
165561d06d6bSBaptiste Daroussin 		break;
165661d06d6bSBaptiste Daroussin 	case MDOC__T:
165761d06d6bSBaptiste Daroussin 		/* FALLTHROUGH */
165861d06d6bSBaptiste Daroussin 	case MDOC_Do:
165961d06d6bSBaptiste Daroussin 	case MDOC_Dq:
166061d06d6bSBaptiste Daroussin 		term_word(p, "\\(rq");
166161d06d6bSBaptiste Daroussin 		break;
166261d06d6bSBaptiste Daroussin 	case MDOC_En:
166361d06d6bSBaptiste Daroussin 		if (n->norm->Es == NULL ||
166461d06d6bSBaptiste Daroussin 		    n->norm->Es->child == NULL ||
166561d06d6bSBaptiste Daroussin 		    n->norm->Es->child->next == NULL)
166661d06d6bSBaptiste Daroussin 			p->flags &= ~TERMP_NOSPACE;
166761d06d6bSBaptiste Daroussin 		else
166861d06d6bSBaptiste Daroussin 			term_word(p, n->norm->Es->child->next->string);
166961d06d6bSBaptiste Daroussin 		break;
167061d06d6bSBaptiste Daroussin 	case MDOC_Po:
167161d06d6bSBaptiste Daroussin 	case MDOC_Pq:
167261d06d6bSBaptiste Daroussin 		term_word(p, ")");
167361d06d6bSBaptiste Daroussin 		break;
167461d06d6bSBaptiste Daroussin 	case MDOC_Qo:
167561d06d6bSBaptiste Daroussin 	case MDOC_Qq:
167661d06d6bSBaptiste Daroussin 		term_word(p, "\"");
167761d06d6bSBaptiste Daroussin 		break;
167861d06d6bSBaptiste Daroussin 	case MDOC_Ql:
167961d06d6bSBaptiste Daroussin 	case MDOC_So:
168061d06d6bSBaptiste Daroussin 	case MDOC_Sq:
168161d06d6bSBaptiste Daroussin 		term_word(p, "\\(cq");
168261d06d6bSBaptiste Daroussin 		break;
168361d06d6bSBaptiste Daroussin 	default:
168461d06d6bSBaptiste Daroussin 		abort();
168561d06d6bSBaptiste Daroussin 	}
168661d06d6bSBaptiste Daroussin }
168761d06d6bSBaptiste Daroussin 
168861d06d6bSBaptiste Daroussin static int
168961d06d6bSBaptiste Daroussin termp_eo_pre(DECL_ARGS)
169061d06d6bSBaptiste Daroussin {
169161d06d6bSBaptiste Daroussin 
169261d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY)
169361d06d6bSBaptiste Daroussin 		return 1;
169461d06d6bSBaptiste Daroussin 
169561d06d6bSBaptiste Daroussin 	if (n->end == ENDBODY_NOT &&
169661d06d6bSBaptiste Daroussin 	    n->parent->head->child == NULL &&
169761d06d6bSBaptiste Daroussin 	    n->child != NULL &&
169861d06d6bSBaptiste Daroussin 	    n->child->end != ENDBODY_NOT)
169961d06d6bSBaptiste Daroussin 		term_word(p, "\\&");
170061d06d6bSBaptiste Daroussin 	else if (n->end != ENDBODY_NOT ? n->child != NULL :
170161d06d6bSBaptiste Daroussin 	     n->parent->head->child != NULL && (n->child != NULL ||
170261d06d6bSBaptiste Daroussin 	     (n->parent->tail != NULL && n->parent->tail->child != NULL)))
170361d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
170461d06d6bSBaptiste Daroussin 
170561d06d6bSBaptiste Daroussin 	return 1;
170661d06d6bSBaptiste Daroussin }
170761d06d6bSBaptiste Daroussin 
170861d06d6bSBaptiste Daroussin static void
170961d06d6bSBaptiste Daroussin termp_eo_post(DECL_ARGS)
171061d06d6bSBaptiste Daroussin {
171161d06d6bSBaptiste Daroussin 	int	 body, tail;
171261d06d6bSBaptiste Daroussin 
171361d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY)
171461d06d6bSBaptiste Daroussin 		return;
171561d06d6bSBaptiste Daroussin 
171661d06d6bSBaptiste Daroussin 	if (n->end != ENDBODY_NOT) {
171761d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_NOSPACE;
171861d06d6bSBaptiste Daroussin 		return;
171961d06d6bSBaptiste Daroussin 	}
172061d06d6bSBaptiste Daroussin 
172161d06d6bSBaptiste Daroussin 	body = n->child != NULL || n->parent->head->child != NULL;
172261d06d6bSBaptiste Daroussin 	tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
172361d06d6bSBaptiste Daroussin 
172461d06d6bSBaptiste Daroussin 	if (body && tail)
172561d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
172661d06d6bSBaptiste Daroussin 	else if ( ! (body || tail))
172761d06d6bSBaptiste Daroussin 		term_word(p, "\\&");
172861d06d6bSBaptiste Daroussin 	else if ( ! tail)
172961d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_NOSPACE;
173061d06d6bSBaptiste Daroussin }
173161d06d6bSBaptiste Daroussin 
173261d06d6bSBaptiste Daroussin static int
173361d06d6bSBaptiste Daroussin termp_fo_pre(DECL_ARGS)
173461d06d6bSBaptiste Daroussin {
1735*6d38604fSBaptiste Daroussin 	size_t rmargin;
173661d06d6bSBaptiste Daroussin 
1737*6d38604fSBaptiste Daroussin 	switch (n->type) {
1738*6d38604fSBaptiste Daroussin 	case ROFFT_BLOCK:
173961d06d6bSBaptiste Daroussin 		synopsis_pre(p, n);
174061d06d6bSBaptiste Daroussin 		return 1;
1741*6d38604fSBaptiste Daroussin 	case ROFFT_BODY:
174261d06d6bSBaptiste Daroussin 		rmargin = p->tcol->rmargin;
1743*6d38604fSBaptiste Daroussin 		if (n->flags & NODE_SYNPRETTY) {
174461d06d6bSBaptiste Daroussin 			p->tcol->rmargin = p->tcol->offset + term_len(p, 4);
174561d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOBREAK | TERMP_BRIND |
174661d06d6bSBaptiste Daroussin 					TERMP_HANG;
174761d06d6bSBaptiste Daroussin 		}
174861d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
174961d06d6bSBaptiste Daroussin 		term_word(p, "(");
175061d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
1751*6d38604fSBaptiste Daroussin 		if (n->flags & NODE_SYNPRETTY) {
175261d06d6bSBaptiste Daroussin 			term_flushln(p);
175361d06d6bSBaptiste Daroussin 			p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND |
175461d06d6bSBaptiste Daroussin 					TERMP_HANG);
175561d06d6bSBaptiste Daroussin 			p->flags |= TERMP_NOPAD;
175661d06d6bSBaptiste Daroussin 			p->tcol->offset = p->tcol->rmargin;
175761d06d6bSBaptiste Daroussin 			p->tcol->rmargin = rmargin;
175861d06d6bSBaptiste Daroussin 		}
175961d06d6bSBaptiste Daroussin 		return 1;
1760*6d38604fSBaptiste Daroussin 	default:
1761*6d38604fSBaptiste Daroussin 		return termp_bold_pre(p, pair, meta, n);
176261d06d6bSBaptiste Daroussin 	}
176361d06d6bSBaptiste Daroussin }
176461d06d6bSBaptiste Daroussin 
176561d06d6bSBaptiste Daroussin static void
176661d06d6bSBaptiste Daroussin termp_fo_post(DECL_ARGS)
176761d06d6bSBaptiste Daroussin {
176861d06d6bSBaptiste Daroussin 	if (n->type != ROFFT_BODY)
176961d06d6bSBaptiste Daroussin 		return;
177061d06d6bSBaptiste Daroussin 
177161d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
177261d06d6bSBaptiste Daroussin 	term_word(p, ")");
177361d06d6bSBaptiste Daroussin 
1774*6d38604fSBaptiste Daroussin 	if (n->flags & NODE_SYNPRETTY) {
177561d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
177661d06d6bSBaptiste Daroussin 		term_word(p, ";");
177761d06d6bSBaptiste Daroussin 		term_flushln(p);
177861d06d6bSBaptiste Daroussin 	}
177961d06d6bSBaptiste Daroussin }
178061d06d6bSBaptiste Daroussin 
178161d06d6bSBaptiste Daroussin static int
178261d06d6bSBaptiste Daroussin termp_bf_pre(DECL_ARGS)
178361d06d6bSBaptiste Daroussin {
1784*6d38604fSBaptiste Daroussin 	switch (n->type) {
1785*6d38604fSBaptiste Daroussin 	case ROFFT_HEAD:
178661d06d6bSBaptiste Daroussin 		return 0;
1787*6d38604fSBaptiste Daroussin 	case ROFFT_BODY:
1788*6d38604fSBaptiste Daroussin 		break;
1789*6d38604fSBaptiste Daroussin 	default:
179061d06d6bSBaptiste Daroussin 		return 1;
1791*6d38604fSBaptiste Daroussin 	}
1792*6d38604fSBaptiste Daroussin 	switch (n->norm->Bf.font) {
1793*6d38604fSBaptiste Daroussin 	case FONT_Em:
1794*6d38604fSBaptiste Daroussin 		return termp_under_pre(p, pair, meta, n);
1795*6d38604fSBaptiste Daroussin 	case FONT_Sy:
1796*6d38604fSBaptiste Daroussin 		return termp_bold_pre(p, pair, meta, n);
1797*6d38604fSBaptiste Daroussin 	default:
1798*6d38604fSBaptiste Daroussin 		return termp_li_pre(p, pair, meta, n);
1799*6d38604fSBaptiste Daroussin 	}
180061d06d6bSBaptiste Daroussin }
180161d06d6bSBaptiste Daroussin 
180261d06d6bSBaptiste Daroussin static int
180361d06d6bSBaptiste Daroussin termp_sm_pre(DECL_ARGS)
180461d06d6bSBaptiste Daroussin {
1805*6d38604fSBaptiste Daroussin 	if (n->child == NULL)
180661d06d6bSBaptiste Daroussin 		p->flags ^= TERMP_NONOSPACE;
1807*6d38604fSBaptiste Daroussin 	else if (strcmp(n->child->string, "on") == 0)
180861d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_NONOSPACE;
180961d06d6bSBaptiste Daroussin 	else
181061d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NONOSPACE;
181161d06d6bSBaptiste Daroussin 
181261d06d6bSBaptiste Daroussin 	if (p->col && ! (TERMP_NONOSPACE & p->flags))
181361d06d6bSBaptiste Daroussin 		p->flags &= ~TERMP_NOSPACE;
181461d06d6bSBaptiste Daroussin 
181561d06d6bSBaptiste Daroussin 	return 0;
181661d06d6bSBaptiste Daroussin }
181761d06d6bSBaptiste Daroussin 
181861d06d6bSBaptiste Daroussin static int
181961d06d6bSBaptiste Daroussin termp_ap_pre(DECL_ARGS)
182061d06d6bSBaptiste Daroussin {
182161d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
182261d06d6bSBaptiste Daroussin 	term_word(p, "'");
182361d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
182461d06d6bSBaptiste Daroussin 	return 1;
182561d06d6bSBaptiste Daroussin }
182661d06d6bSBaptiste Daroussin 
182761d06d6bSBaptiste Daroussin static void
182861d06d6bSBaptiste Daroussin termp____post(DECL_ARGS)
182961d06d6bSBaptiste Daroussin {
1830*6d38604fSBaptiste Daroussin 	struct roff_node *nn;
183161d06d6bSBaptiste Daroussin 
183261d06d6bSBaptiste Daroussin 	/*
183361d06d6bSBaptiste Daroussin 	 * Handle lists of authors.  In general, print each followed by
183461d06d6bSBaptiste Daroussin 	 * a comma.  Don't print the comma if there are only two
183561d06d6bSBaptiste Daroussin 	 * authors.
183661d06d6bSBaptiste Daroussin 	 */
1837*6d38604fSBaptiste Daroussin 	if (n->tok == MDOC__A &&
1838*6d38604fSBaptiste Daroussin 	    (nn = roff_node_next(n)) != NULL && nn->tok == MDOC__A &&
1839*6d38604fSBaptiste Daroussin 	    ((nn = roff_node_next(nn)) == NULL || nn->tok != MDOC__A) &&
1840*6d38604fSBaptiste Daroussin 	    ((nn = roff_node_prev(n)) == NULL || nn->tok != MDOC__A))
184161d06d6bSBaptiste Daroussin 		return;
184261d06d6bSBaptiste Daroussin 
184361d06d6bSBaptiste Daroussin 	/* TODO: %U. */
184461d06d6bSBaptiste Daroussin 
1845*6d38604fSBaptiste Daroussin 	if (n->parent == NULL || n->parent->tok != MDOC_Rs)
184661d06d6bSBaptiste Daroussin 		return;
184761d06d6bSBaptiste Daroussin 
184861d06d6bSBaptiste Daroussin 	p->flags |= TERMP_NOSPACE;
1849*6d38604fSBaptiste Daroussin 	if (roff_node_next(n) == NULL) {
185061d06d6bSBaptiste Daroussin 		term_word(p, ".");
185161d06d6bSBaptiste Daroussin 		p->flags |= TERMP_SENTENCE;
185261d06d6bSBaptiste Daroussin 	} else
185361d06d6bSBaptiste Daroussin 		term_word(p, ",");
185461d06d6bSBaptiste Daroussin }
185561d06d6bSBaptiste Daroussin 
185661d06d6bSBaptiste Daroussin static int
185761d06d6bSBaptiste Daroussin termp_li_pre(DECL_ARGS)
185861d06d6bSBaptiste Daroussin {
185961d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_NONE);
186061d06d6bSBaptiste Daroussin 	return 1;
186161d06d6bSBaptiste Daroussin }
186261d06d6bSBaptiste Daroussin 
186361d06d6bSBaptiste Daroussin static int
186461d06d6bSBaptiste Daroussin termp_lk_pre(DECL_ARGS)
186561d06d6bSBaptiste Daroussin {
186661d06d6bSBaptiste Daroussin 	const struct roff_node *link, *descr, *punct;
186761d06d6bSBaptiste Daroussin 
186861d06d6bSBaptiste Daroussin 	if ((link = n->child) == NULL)
186961d06d6bSBaptiste Daroussin 		return 0;
187061d06d6bSBaptiste Daroussin 
187161d06d6bSBaptiste Daroussin 	/* Find beginning of trailing punctuation. */
187261d06d6bSBaptiste Daroussin 	punct = n->last;
187361d06d6bSBaptiste Daroussin 	while (punct != link && punct->flags & NODE_DELIMC)
187461d06d6bSBaptiste Daroussin 		punct = punct->prev;
187561d06d6bSBaptiste Daroussin 	punct = punct->next;
187661d06d6bSBaptiste Daroussin 
187761d06d6bSBaptiste Daroussin 	/* Link text. */
187861d06d6bSBaptiste Daroussin 	if ((descr = link->next) != NULL && descr != punct) {
187961d06d6bSBaptiste Daroussin 		term_fontpush(p, TERMFONT_UNDER);
188061d06d6bSBaptiste Daroussin 		while (descr != punct) {
188161d06d6bSBaptiste Daroussin 			if (descr->flags & (NODE_DELIMC | NODE_DELIMO))
188261d06d6bSBaptiste Daroussin 				p->flags |= TERMP_NOSPACE;
188361d06d6bSBaptiste Daroussin 			term_word(p, descr->string);
188461d06d6bSBaptiste Daroussin 			descr = descr->next;
188561d06d6bSBaptiste Daroussin 		}
188661d06d6bSBaptiste Daroussin 		term_fontpop(p);
188761d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
188861d06d6bSBaptiste Daroussin 		term_word(p, ":");
188961d06d6bSBaptiste Daroussin 	}
189061d06d6bSBaptiste Daroussin 
189161d06d6bSBaptiste Daroussin 	/* Link target. */
189261d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_BOLD);
189361d06d6bSBaptiste Daroussin 	term_word(p, link->string);
189461d06d6bSBaptiste Daroussin 	term_fontpop(p);
189561d06d6bSBaptiste Daroussin 
189661d06d6bSBaptiste Daroussin 	/* Trailing punctuation. */
189761d06d6bSBaptiste Daroussin 	while (punct != NULL) {
189861d06d6bSBaptiste Daroussin 		p->flags |= TERMP_NOSPACE;
189961d06d6bSBaptiste Daroussin 		term_word(p, punct->string);
190061d06d6bSBaptiste Daroussin 		punct = punct->next;
190161d06d6bSBaptiste Daroussin 	}
190261d06d6bSBaptiste Daroussin 	return 0;
190361d06d6bSBaptiste Daroussin }
190461d06d6bSBaptiste Daroussin 
190561d06d6bSBaptiste Daroussin static int
190661d06d6bSBaptiste Daroussin termp_bk_pre(DECL_ARGS)
190761d06d6bSBaptiste Daroussin {
190861d06d6bSBaptiste Daroussin 	switch (n->type) {
190961d06d6bSBaptiste Daroussin 	case ROFFT_BLOCK:
191061d06d6bSBaptiste Daroussin 		break;
191161d06d6bSBaptiste Daroussin 	case ROFFT_HEAD:
191261d06d6bSBaptiste Daroussin 		return 0;
191361d06d6bSBaptiste Daroussin 	case ROFFT_BODY:
191461d06d6bSBaptiste Daroussin 		if (n->parent->args != NULL || n->prev->child == NULL)
191561d06d6bSBaptiste Daroussin 			p->flags |= TERMP_PREKEEP;
191661d06d6bSBaptiste Daroussin 		break;
191761d06d6bSBaptiste Daroussin 	default:
191861d06d6bSBaptiste Daroussin 		abort();
191961d06d6bSBaptiste Daroussin 	}
192061d06d6bSBaptiste Daroussin 	return 1;
192161d06d6bSBaptiste Daroussin }
192261d06d6bSBaptiste Daroussin 
192361d06d6bSBaptiste Daroussin static void
192461d06d6bSBaptiste Daroussin termp_bk_post(DECL_ARGS)
192561d06d6bSBaptiste Daroussin {
192661d06d6bSBaptiste Daroussin 	if (n->type == ROFFT_BODY)
192761d06d6bSBaptiste Daroussin 		p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
192861d06d6bSBaptiste Daroussin }
192961d06d6bSBaptiste Daroussin 
1930*6d38604fSBaptiste Daroussin /*
1931*6d38604fSBaptiste Daroussin  * If we are in an `Rs' and there is a journal present,
1932*6d38604fSBaptiste Daroussin  * then quote us instead of underlining us (for disambiguation).
1933*6d38604fSBaptiste Daroussin  */
193461d06d6bSBaptiste Daroussin static void
193561d06d6bSBaptiste Daroussin termp__t_post(DECL_ARGS)
193661d06d6bSBaptiste Daroussin {
1937*6d38604fSBaptiste Daroussin 	if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
193861d06d6bSBaptiste Daroussin 	    n->parent->norm->Rs.quote_T)
193961d06d6bSBaptiste Daroussin 		termp_quote_post(p, pair, meta, n);
194061d06d6bSBaptiste Daroussin 	termp____post(p, pair, meta, n);
194161d06d6bSBaptiste Daroussin }
194261d06d6bSBaptiste Daroussin 
194361d06d6bSBaptiste Daroussin static int
194461d06d6bSBaptiste Daroussin termp__t_pre(DECL_ARGS)
194561d06d6bSBaptiste Daroussin {
1946*6d38604fSBaptiste Daroussin 	if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
194761d06d6bSBaptiste Daroussin 	    n->parent->norm->Rs.quote_T)
194861d06d6bSBaptiste Daroussin 		return termp_quote_pre(p, pair, meta, n);
1949*6d38604fSBaptiste Daroussin 	else
1950*6d38604fSBaptiste Daroussin 		return termp_under_pre(p, pair, meta, n);
195161d06d6bSBaptiste Daroussin }
195261d06d6bSBaptiste Daroussin 
195361d06d6bSBaptiste Daroussin static int
195461d06d6bSBaptiste Daroussin termp_under_pre(DECL_ARGS)
195561d06d6bSBaptiste Daroussin {
195661d06d6bSBaptiste Daroussin 	term_fontpush(p, TERMFONT_UNDER);
195761d06d6bSBaptiste Daroussin 	return 1;
195861d06d6bSBaptiste Daroussin }
195961d06d6bSBaptiste Daroussin 
196061d06d6bSBaptiste Daroussin static int
19617295610fSBaptiste Daroussin termp_abort_pre(DECL_ARGS)
19627295610fSBaptiste Daroussin {
19637295610fSBaptiste Daroussin 	abort();
19647295610fSBaptiste Daroussin }
1965