1*260e9a87SYuri Pankov /* $Id: mdoc_term.c,v 1.313 2015/03/06 15:48:52 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*260e9a87SYuri Pankov * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
5698f87a4SGarrett D'Amore * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
695c635efSGarrett D'Amore *
795c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
895c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
995c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies.
1095c635efSGarrett D'Amore *
1195c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1295c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1395c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1495c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1595c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1695c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1795c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1895c635efSGarrett D'Amore */
1995c635efSGarrett D'Amore #include "config.h"
2095c635efSGarrett D'Amore
2195c635efSGarrett D'Amore #include <sys/types.h>
2295c635efSGarrett D'Amore
2395c635efSGarrett D'Amore #include <assert.h>
2495c635efSGarrett D'Amore #include <ctype.h>
25*260e9a87SYuri Pankov #include <limits.h>
2695c635efSGarrett D'Amore #include <stdint.h>
2795c635efSGarrett D'Amore #include <stdio.h>
2895c635efSGarrett D'Amore #include <stdlib.h>
2995c635efSGarrett D'Amore #include <string.h>
3095c635efSGarrett D'Amore
3195c635efSGarrett D'Amore #include "mandoc.h"
32*260e9a87SYuri Pankov #include "mandoc_aux.h"
3395c635efSGarrett D'Amore #include "out.h"
3495c635efSGarrett D'Amore #include "term.h"
3595c635efSGarrett D'Amore #include "mdoc.h"
3695c635efSGarrett D'Amore #include "main.h"
3795c635efSGarrett D'Amore
3895c635efSGarrett D'Amore struct termpair {
3995c635efSGarrett D'Amore struct termpair *ppair;
4095c635efSGarrett D'Amore int count;
4195c635efSGarrett D'Amore };
4295c635efSGarrett D'Amore
4395c635efSGarrett D'Amore #define DECL_ARGS struct termp *p, \
4495c635efSGarrett D'Amore struct termpair *pair, \
45698f87a4SGarrett D'Amore const struct mdoc_meta *meta, \
46698f87a4SGarrett D'Amore struct mdoc_node *n
4795c635efSGarrett D'Amore
4895c635efSGarrett D'Amore struct termact {
4995c635efSGarrett D'Amore int (*pre)(DECL_ARGS);
5095c635efSGarrett D'Amore void (*post)(DECL_ARGS);
5195c635efSGarrett D'Amore };
5295c635efSGarrett D'Amore
53*260e9a87SYuri Pankov static int a2width(const struct termp *, const char *);
5495c635efSGarrett D'Amore
5595c635efSGarrett D'Amore static void print_bvspace(struct termp *,
5695c635efSGarrett D'Amore const struct mdoc_node *,
5795c635efSGarrett D'Amore const struct mdoc_node *);
5895c635efSGarrett D'Amore static void print_mdoc_node(DECL_ARGS);
5995c635efSGarrett D'Amore static void print_mdoc_nodelist(DECL_ARGS);
6095c635efSGarrett D'Amore static void print_mdoc_head(struct termp *, const void *);
6195c635efSGarrett D'Amore static void print_mdoc_foot(struct termp *, const void *);
6295c635efSGarrett D'Amore static void synopsis_pre(struct termp *,
6395c635efSGarrett D'Amore const struct mdoc_node *);
6495c635efSGarrett D'Amore
6595c635efSGarrett D'Amore static void termp____post(DECL_ARGS);
6695c635efSGarrett D'Amore static void termp__t_post(DECL_ARGS);
6795c635efSGarrett D'Amore static void termp_bd_post(DECL_ARGS);
6895c635efSGarrett D'Amore static void termp_bk_post(DECL_ARGS);
6995c635efSGarrett D'Amore static void termp_bl_post(DECL_ARGS);
70*260e9a87SYuri Pankov static void termp_eo_post(DECL_ARGS);
71698f87a4SGarrett D'Amore static void termp_fd_post(DECL_ARGS);
7295c635efSGarrett D'Amore static void termp_fo_post(DECL_ARGS);
7395c635efSGarrett D'Amore static void termp_in_post(DECL_ARGS);
7495c635efSGarrett D'Amore static void termp_it_post(DECL_ARGS);
7595c635efSGarrett D'Amore static void termp_lb_post(DECL_ARGS);
7695c635efSGarrett D'Amore static void termp_nm_post(DECL_ARGS);
7795c635efSGarrett D'Amore static void termp_pf_post(DECL_ARGS);
7895c635efSGarrett D'Amore static void termp_quote_post(DECL_ARGS);
7995c635efSGarrett D'Amore static void termp_sh_post(DECL_ARGS);
8095c635efSGarrett D'Amore static void termp_ss_post(DECL_ARGS);
8195c635efSGarrett D'Amore
8295c635efSGarrett D'Amore static int termp__a_pre(DECL_ARGS);
8395c635efSGarrett D'Amore static int termp__t_pre(DECL_ARGS);
8495c635efSGarrett D'Amore static int termp_an_pre(DECL_ARGS);
8595c635efSGarrett D'Amore static int termp_ap_pre(DECL_ARGS);
8695c635efSGarrett D'Amore static int termp_bd_pre(DECL_ARGS);
8795c635efSGarrett D'Amore static int termp_bf_pre(DECL_ARGS);
8895c635efSGarrett D'Amore static int termp_bk_pre(DECL_ARGS);
8995c635efSGarrett D'Amore static int termp_bl_pre(DECL_ARGS);
9095c635efSGarrett D'Amore static int termp_bold_pre(DECL_ARGS);
9195c635efSGarrett D'Amore static int termp_bt_pre(DECL_ARGS);
9295c635efSGarrett D'Amore static int termp_bx_pre(DECL_ARGS);
9395c635efSGarrett D'Amore static int termp_cd_pre(DECL_ARGS);
9495c635efSGarrett D'Amore static int termp_d1_pre(DECL_ARGS);
95*260e9a87SYuri Pankov static int termp_eo_pre(DECL_ARGS);
9695c635efSGarrett D'Amore static int termp_ex_pre(DECL_ARGS);
9795c635efSGarrett D'Amore static int termp_fa_pre(DECL_ARGS);
9895c635efSGarrett D'Amore static int termp_fd_pre(DECL_ARGS);
9995c635efSGarrett D'Amore static int termp_fl_pre(DECL_ARGS);
10095c635efSGarrett D'Amore static int termp_fn_pre(DECL_ARGS);
10195c635efSGarrett D'Amore static int termp_fo_pre(DECL_ARGS);
10295c635efSGarrett D'Amore static int termp_ft_pre(DECL_ARGS);
10395c635efSGarrett D'Amore static int termp_in_pre(DECL_ARGS);
10495c635efSGarrett D'Amore static int termp_it_pre(DECL_ARGS);
10595c635efSGarrett D'Amore static int termp_li_pre(DECL_ARGS);
106*260e9a87SYuri Pankov static int termp_ll_pre(DECL_ARGS);
10795c635efSGarrett D'Amore static int termp_lk_pre(DECL_ARGS);
10895c635efSGarrett D'Amore static int termp_nd_pre(DECL_ARGS);
10995c635efSGarrett D'Amore static int termp_nm_pre(DECL_ARGS);
11095c635efSGarrett D'Amore static int termp_ns_pre(DECL_ARGS);
11195c635efSGarrett D'Amore static int termp_quote_pre(DECL_ARGS);
11295c635efSGarrett D'Amore static int termp_rs_pre(DECL_ARGS);
11395c635efSGarrett D'Amore static int termp_rv_pre(DECL_ARGS);
11495c635efSGarrett D'Amore static int termp_sh_pre(DECL_ARGS);
115*260e9a87SYuri Pankov static int termp_skip_pre(DECL_ARGS);
11695c635efSGarrett D'Amore static int termp_sm_pre(DECL_ARGS);
11795c635efSGarrett D'Amore static int termp_sp_pre(DECL_ARGS);
11895c635efSGarrett D'Amore static int termp_ss_pre(DECL_ARGS);
11995c635efSGarrett D'Amore static int termp_under_pre(DECL_ARGS);
12095c635efSGarrett D'Amore static int termp_ud_pre(DECL_ARGS);
12195c635efSGarrett D'Amore static int termp_vt_pre(DECL_ARGS);
12295c635efSGarrett D'Amore static int termp_xr_pre(DECL_ARGS);
12395c635efSGarrett D'Amore static int termp_xx_pre(DECL_ARGS);
12495c635efSGarrett D'Amore
12595c635efSGarrett D'Amore static const struct termact termacts[MDOC_MAX] = {
12695c635efSGarrett D'Amore { termp_ap_pre, NULL }, /* Ap */
12795c635efSGarrett D'Amore { NULL, NULL }, /* Dd */
12895c635efSGarrett D'Amore { NULL, NULL }, /* Dt */
12995c635efSGarrett D'Amore { NULL, NULL }, /* Os */
13095c635efSGarrett D'Amore { termp_sh_pre, termp_sh_post }, /* Sh */
13195c635efSGarrett D'Amore { termp_ss_pre, termp_ss_post }, /* Ss */
13295c635efSGarrett D'Amore { termp_sp_pre, NULL }, /* Pp */
133698f87a4SGarrett D'Amore { termp_d1_pre, termp_bl_post }, /* D1 */
134698f87a4SGarrett D'Amore { termp_d1_pre, termp_bl_post }, /* Dl */
13595c635efSGarrett D'Amore { termp_bd_pre, termp_bd_post }, /* Bd */
13695c635efSGarrett D'Amore { NULL, NULL }, /* Ed */
13795c635efSGarrett D'Amore { termp_bl_pre, termp_bl_post }, /* Bl */
13895c635efSGarrett D'Amore { NULL, NULL }, /* El */
13995c635efSGarrett D'Amore { termp_it_pre, termp_it_post }, /* It */
14095c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Ad */
141*260e9a87SYuri Pankov { termp_an_pre, NULL }, /* An */
14295c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Ar */
14395c635efSGarrett D'Amore { termp_cd_pre, NULL }, /* Cd */
14495c635efSGarrett D'Amore { termp_bold_pre, NULL }, /* Cm */
14595c635efSGarrett D'Amore { NULL, NULL }, /* Dv */
14695c635efSGarrett D'Amore { NULL, NULL }, /* Er */
14795c635efSGarrett D'Amore { NULL, NULL }, /* Ev */
14895c635efSGarrett D'Amore { termp_ex_pre, NULL }, /* Ex */
14995c635efSGarrett D'Amore { termp_fa_pre, NULL }, /* Fa */
150698f87a4SGarrett D'Amore { termp_fd_pre, termp_fd_post }, /* Fd */
15195c635efSGarrett D'Amore { termp_fl_pre, NULL }, /* Fl */
15295c635efSGarrett D'Amore { termp_fn_pre, NULL }, /* Fn */
15395c635efSGarrett D'Amore { termp_ft_pre, NULL }, /* Ft */
15495c635efSGarrett D'Amore { termp_bold_pre, NULL }, /* Ic */
15595c635efSGarrett D'Amore { termp_in_pre, termp_in_post }, /* In */
15695c635efSGarrett D'Amore { termp_li_pre, NULL }, /* Li */
15795c635efSGarrett D'Amore { termp_nd_pre, NULL }, /* Nd */
15895c635efSGarrett D'Amore { termp_nm_pre, termp_nm_post }, /* Nm */
15995c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Op */
160*260e9a87SYuri Pankov { termp_ft_pre, NULL }, /* Ot */
16195c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Pa */
16295c635efSGarrett D'Amore { termp_rv_pre, NULL }, /* Rv */
16395c635efSGarrett D'Amore { NULL, NULL }, /* St */
16495c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Va */
16595c635efSGarrett D'Amore { termp_vt_pre, NULL }, /* Vt */
16695c635efSGarrett D'Amore { termp_xr_pre, NULL }, /* Xr */
16795c635efSGarrett D'Amore { termp__a_pre, termp____post }, /* %A */
16895c635efSGarrett D'Amore { termp_under_pre, termp____post }, /* %B */
16995c635efSGarrett D'Amore { NULL, termp____post }, /* %D */
17095c635efSGarrett D'Amore { termp_under_pre, termp____post }, /* %I */
17195c635efSGarrett D'Amore { termp_under_pre, termp____post }, /* %J */
17295c635efSGarrett D'Amore { NULL, termp____post }, /* %N */
17395c635efSGarrett D'Amore { NULL, termp____post }, /* %O */
17495c635efSGarrett D'Amore { NULL, termp____post }, /* %P */
17595c635efSGarrett D'Amore { NULL, termp____post }, /* %R */
17695c635efSGarrett D'Amore { termp__t_pre, termp__t_post }, /* %T */
17795c635efSGarrett D'Amore { NULL, termp____post }, /* %V */
17895c635efSGarrett D'Amore { NULL, NULL }, /* Ac */
17995c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Ao */
18095c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Aq */
18195c635efSGarrett D'Amore { NULL, NULL }, /* At */
18295c635efSGarrett D'Amore { NULL, NULL }, /* Bc */
18395c635efSGarrett D'Amore { termp_bf_pre, NULL }, /* Bf */
18495c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Bo */
18595c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Bq */
18695c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Bsx */
18795c635efSGarrett D'Amore { termp_bx_pre, NULL }, /* Bx */
188*260e9a87SYuri Pankov { termp_skip_pre, NULL }, /* Db */
18995c635efSGarrett D'Amore { NULL, NULL }, /* Dc */
19095c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Do */
19195c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Dq */
19295c635efSGarrett D'Amore { NULL, NULL }, /* Ec */ /* FIXME: no space */
19395c635efSGarrett D'Amore { NULL, NULL }, /* Ef */
19495c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Em */
195*260e9a87SYuri Pankov { termp_eo_pre, termp_eo_post }, /* Eo */
19695c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Fx */
19795c635efSGarrett D'Amore { termp_bold_pre, NULL }, /* Ms */
198*260e9a87SYuri Pankov { termp_li_pre, NULL }, /* No */
19995c635efSGarrett D'Amore { termp_ns_pre, NULL }, /* Ns */
20095c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Nx */
20195c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Ox */
20295c635efSGarrett D'Amore { NULL, NULL }, /* Pc */
203698f87a4SGarrett D'Amore { NULL, termp_pf_post }, /* Pf */
20495c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Po */
20595c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Pq */
20695c635efSGarrett D'Amore { NULL, NULL }, /* Qc */
20795c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Ql */
20895c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Qo */
20995c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Qq */
21095c635efSGarrett D'Amore { NULL, NULL }, /* Re */
21195c635efSGarrett D'Amore { termp_rs_pre, NULL }, /* Rs */
21295c635efSGarrett D'Amore { NULL, NULL }, /* Sc */
21395c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* So */
21495c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Sq */
21595c635efSGarrett D'Amore { termp_sm_pre, NULL }, /* Sm */
21695c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Sx */
21795c635efSGarrett D'Amore { termp_bold_pre, NULL }, /* Sy */
21895c635efSGarrett D'Amore { NULL, NULL }, /* Tn */
21995c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Ux */
22095c635efSGarrett D'Amore { NULL, NULL }, /* Xc */
22195c635efSGarrett D'Amore { NULL, NULL }, /* Xo */
22295c635efSGarrett D'Amore { termp_fo_pre, termp_fo_post }, /* Fo */
22395c635efSGarrett D'Amore { NULL, NULL }, /* Fc */
22495c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Oo */
22595c635efSGarrett D'Amore { NULL, NULL }, /* Oc */
22695c635efSGarrett D'Amore { termp_bk_pre, termp_bk_post }, /* Bk */
22795c635efSGarrett D'Amore { NULL, NULL }, /* Ek */
22895c635efSGarrett D'Amore { termp_bt_pre, NULL }, /* Bt */
22995c635efSGarrett D'Amore { NULL, NULL }, /* Hf */
230*260e9a87SYuri Pankov { termp_under_pre, NULL }, /* Fr */
23195c635efSGarrett D'Amore { termp_ud_pre, NULL }, /* Ud */
23295c635efSGarrett D'Amore { NULL, termp_lb_post }, /* Lb */
23395c635efSGarrett D'Amore { termp_sp_pre, NULL }, /* Lp */
23495c635efSGarrett D'Amore { termp_lk_pre, NULL }, /* Lk */
23595c635efSGarrett D'Amore { termp_under_pre, NULL }, /* Mt */
23695c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Brq */
23795c635efSGarrett D'Amore { termp_quote_pre, termp_quote_post }, /* Bro */
23895c635efSGarrett D'Amore { NULL, NULL }, /* Brc */
23995c635efSGarrett D'Amore { NULL, termp____post }, /* %C */
240*260e9a87SYuri Pankov { termp_skip_pre, NULL }, /* Es */
241*260e9a87SYuri Pankov { termp_quote_pre, termp_quote_post }, /* En */
24295c635efSGarrett D'Amore { termp_xx_pre, NULL }, /* Dx */
24395c635efSGarrett D'Amore { NULL, termp____post }, /* %Q */
24495c635efSGarrett D'Amore { termp_sp_pre, NULL }, /* br */
24595c635efSGarrett D'Amore { termp_sp_pre, NULL }, /* sp */
246698f87a4SGarrett D'Amore { NULL, termp____post }, /* %U */
24795c635efSGarrett D'Amore { NULL, NULL }, /* Ta */
248*260e9a87SYuri Pankov { termp_ll_pre, NULL }, /* ll */
24995c635efSGarrett D'Amore };
25095c635efSGarrett D'Amore
25195c635efSGarrett D'Amore
25295c635efSGarrett D'Amore void
terminal_mdoc(void * arg,const struct mdoc * mdoc)25395c635efSGarrett D'Amore terminal_mdoc(void *arg, const struct mdoc *mdoc)
25495c635efSGarrett D'Amore {
255698f87a4SGarrett D'Amore const struct mdoc_meta *meta;
256*260e9a87SYuri Pankov struct mdoc_node *n;
25795c635efSGarrett D'Amore struct termp *p;
25895c635efSGarrett D'Amore
25995c635efSGarrett D'Amore p = (struct termp *)arg;
26095c635efSGarrett D'Amore
26195c635efSGarrett D'Amore p->overstep = 0;
262*260e9a87SYuri Pankov p->rmargin = p->maxrmargin = p->defrmargin;
26395c635efSGarrett D'Amore p->tabwidth = term_len(p, 5);
26495c635efSGarrett D'Amore
265*260e9a87SYuri Pankov n = mdoc_node(mdoc)->child;
266698f87a4SGarrett D'Amore meta = mdoc_meta(mdoc);
26795c635efSGarrett D'Amore
268*260e9a87SYuri Pankov if (p->synopsisonly) {
269*260e9a87SYuri Pankov while (n != NULL) {
270*260e9a87SYuri Pankov if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
271*260e9a87SYuri Pankov if (n->child->next->child != NULL)
272*260e9a87SYuri Pankov print_mdoc_nodelist(p, NULL,
273*260e9a87SYuri Pankov meta, n->child->next->child);
274*260e9a87SYuri Pankov term_newln(p);
275*260e9a87SYuri Pankov break;
276*260e9a87SYuri Pankov }
277*260e9a87SYuri Pankov n = n->next;
278*260e9a87SYuri Pankov }
279*260e9a87SYuri Pankov } else {
280*260e9a87SYuri Pankov if (p->defindent == 0)
281*260e9a87SYuri Pankov p->defindent = 5;
282698f87a4SGarrett D'Amore term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
283*260e9a87SYuri Pankov if (n != NULL) {
284*260e9a87SYuri Pankov if (n->tok != MDOC_Sh)
285*260e9a87SYuri Pankov term_vspace(p);
286*260e9a87SYuri Pankov print_mdoc_nodelist(p, NULL, meta, n);
287*260e9a87SYuri Pankov }
28895c635efSGarrett D'Amore term_end(p);
28995c635efSGarrett D'Amore }
290*260e9a87SYuri Pankov }
29195c635efSGarrett D'Amore
29295c635efSGarrett D'Amore static void
print_mdoc_nodelist(DECL_ARGS)29395c635efSGarrett D'Amore print_mdoc_nodelist(DECL_ARGS)
29495c635efSGarrett D'Amore {
29595c635efSGarrett D'Amore
296*260e9a87SYuri Pankov while (n != NULL) {
297698f87a4SGarrett D'Amore print_mdoc_node(p, pair, meta, n);
298*260e9a87SYuri Pankov n = n->next;
299*260e9a87SYuri Pankov }
30095c635efSGarrett D'Amore }
30195c635efSGarrett D'Amore
30295c635efSGarrett D'Amore static void
print_mdoc_node(DECL_ARGS)30395c635efSGarrett D'Amore print_mdoc_node(DECL_ARGS)
30495c635efSGarrett D'Amore {
30595c635efSGarrett D'Amore int chld;
30695c635efSGarrett D'Amore struct termpair npair;
30795c635efSGarrett D'Amore size_t offset, rmargin;
30895c635efSGarrett D'Amore
30995c635efSGarrett D'Amore chld = 1;
31095c635efSGarrett D'Amore offset = p->offset;
31195c635efSGarrett D'Amore rmargin = p->rmargin;
312*260e9a87SYuri Pankov n->flags &= ~MDOC_ENDED;
313*260e9a87SYuri Pankov n->prev_font = p->fonti;
31495c635efSGarrett D'Amore
31595c635efSGarrett D'Amore memset(&npair, 0, sizeof(struct termpair));
31695c635efSGarrett D'Amore npair.ppair = pair;
31795c635efSGarrett D'Amore
31895c635efSGarrett D'Amore /*
31995c635efSGarrett D'Amore * Keeps only work until the end of a line. If a keep was
32095c635efSGarrett D'Amore * invoked in a prior line, revert it to PREKEEP.
32195c635efSGarrett D'Amore */
32295c635efSGarrett D'Amore
323*260e9a87SYuri Pankov if (p->flags & TERMP_KEEP && n->flags & MDOC_LINE) {
32495c635efSGarrett D'Amore p->flags &= ~TERMP_KEEP;
32595c635efSGarrett D'Amore p->flags |= TERMP_PREKEEP;
32695c635efSGarrett D'Amore }
32795c635efSGarrett D'Amore
32895c635efSGarrett D'Amore /*
32995c635efSGarrett D'Amore * After the keep flags have been set up, we may now
33095c635efSGarrett D'Amore * produce output. Note that some pre-handlers do so.
33195c635efSGarrett D'Amore */
33295c635efSGarrett D'Amore
33395c635efSGarrett D'Amore switch (n->type) {
334*260e9a87SYuri Pankov case MDOC_TEXT:
33595c635efSGarrett D'Amore if (' ' == *n->string && MDOC_LINE & n->flags)
33695c635efSGarrett D'Amore term_newln(p);
33795c635efSGarrett D'Amore if (MDOC_DELIMC & n->flags)
33895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
33995c635efSGarrett D'Amore term_word(p, n->string);
34095c635efSGarrett D'Amore if (MDOC_DELIMO & n->flags)
34195c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
34295c635efSGarrett D'Amore break;
343*260e9a87SYuri Pankov case MDOC_EQN:
344*260e9a87SYuri Pankov if ( ! (n->flags & MDOC_LINE))
345*260e9a87SYuri Pankov p->flags |= TERMP_NOSPACE;
34695c635efSGarrett D'Amore term_eqn(p, n->eqn);
347*260e9a87SYuri Pankov if (n->next != NULL && ! (n->next->flags & MDOC_LINE))
348*260e9a87SYuri Pankov p->flags |= TERMP_NOSPACE;
34995c635efSGarrett D'Amore break;
350*260e9a87SYuri Pankov case MDOC_TBL:
351*260e9a87SYuri Pankov if (p->tbl.cols == NULL)
352*260e9a87SYuri Pankov term_newln(p);
35395c635efSGarrett D'Amore term_tbl(p, n->span);
35495c635efSGarrett D'Amore break;
35595c635efSGarrett D'Amore default:
356*260e9a87SYuri Pankov if (termacts[n->tok].pre &&
357*260e9a87SYuri Pankov (n->end == ENDBODY_NOT || n->nchild))
35895c635efSGarrett D'Amore chld = (*termacts[n->tok].pre)
359698f87a4SGarrett D'Amore (p, &npair, meta, n);
36095c635efSGarrett D'Amore break;
36195c635efSGarrett D'Amore }
36295c635efSGarrett D'Amore
36395c635efSGarrett D'Amore if (chld && n->child)
364698f87a4SGarrett D'Amore print_mdoc_nodelist(p, &npair, meta, n->child);
36595c635efSGarrett D'Amore
366698f87a4SGarrett D'Amore term_fontpopq(p,
367*260e9a87SYuri Pankov (ENDBODY_NOT == n->end ? n : n->body)->prev_font);
36895c635efSGarrett D'Amore
36995c635efSGarrett D'Amore switch (n->type) {
370*260e9a87SYuri Pankov case MDOC_TEXT:
37195c635efSGarrett D'Amore break;
372*260e9a87SYuri Pankov case MDOC_TBL:
37395c635efSGarrett D'Amore break;
374*260e9a87SYuri Pankov case MDOC_EQN:
37595c635efSGarrett D'Amore break;
37695c635efSGarrett D'Amore default:
37795c635efSGarrett D'Amore if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
37895c635efSGarrett D'Amore break;
379698f87a4SGarrett D'Amore (void)(*termacts[n->tok].post)(p, &npair, meta, n);
38095c635efSGarrett D'Amore
38195c635efSGarrett D'Amore /*
38295c635efSGarrett D'Amore * Explicit end tokens not only call the post
38395c635efSGarrett D'Amore * handler, but also tell the respective block
38495c635efSGarrett D'Amore * that it must not call the post handler again.
38595c635efSGarrett D'Amore */
38695c635efSGarrett D'Amore if (ENDBODY_NOT != n->end)
387*260e9a87SYuri Pankov n->body->flags |= MDOC_ENDED;
38895c635efSGarrett D'Amore
38995c635efSGarrett D'Amore /*
39095c635efSGarrett D'Amore * End of line terminating an implicit block
39195c635efSGarrett D'Amore * while an explicit block is still open.
39295c635efSGarrett D'Amore * Continue the explicit block without spacing.
39395c635efSGarrett D'Amore */
39495c635efSGarrett D'Amore if (ENDBODY_NOSPACE == n->end)
39595c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
39695c635efSGarrett D'Amore break;
39795c635efSGarrett D'Amore }
39895c635efSGarrett D'Amore
39995c635efSGarrett D'Amore if (MDOC_EOS & n->flags)
40095c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
40195c635efSGarrett D'Amore
402*260e9a87SYuri Pankov if (MDOC_ll != n->tok) {
40395c635efSGarrett D'Amore p->offset = offset;
40495c635efSGarrett D'Amore p->rmargin = rmargin;
40595c635efSGarrett D'Amore }
406*260e9a87SYuri Pankov }
40795c635efSGarrett D'Amore
40895c635efSGarrett D'Amore static void
print_mdoc_foot(struct termp * p,const void * arg)40995c635efSGarrett D'Amore print_mdoc_foot(struct termp *p, const void *arg)
41095c635efSGarrett D'Amore {
411698f87a4SGarrett D'Amore const struct mdoc_meta *meta;
412*260e9a87SYuri Pankov size_t sz;
41395c635efSGarrett D'Amore
414698f87a4SGarrett D'Amore meta = (const struct mdoc_meta *)arg;
41595c635efSGarrett D'Amore
41695c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE);
41795c635efSGarrett D'Amore
41895c635efSGarrett D'Amore /*
41995c635efSGarrett D'Amore * Output the footer in new-groff style, that is, three columns
42095c635efSGarrett D'Amore * with the middle being the manual date and flanking columns
42195c635efSGarrett D'Amore * being the operating system:
42295c635efSGarrett D'Amore *
42395c635efSGarrett D'Amore * SYSTEM DATE SYSTEM
42495c635efSGarrett D'Amore */
42595c635efSGarrett D'Amore
42695c635efSGarrett D'Amore term_vspace(p);
42795c635efSGarrett D'Amore
42895c635efSGarrett D'Amore p->offset = 0;
429*260e9a87SYuri Pankov sz = term_strlen(p, meta->date);
430*260e9a87SYuri Pankov p->rmargin = p->maxrmargin > sz ?
431*260e9a87SYuri Pankov (p->maxrmargin + term_len(p, 1) - sz) / 2 : 0;
432698f87a4SGarrett D'Amore p->trailspace = 1;
43395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
43495c635efSGarrett D'Amore
435698f87a4SGarrett D'Amore term_word(p, meta->os);
43695c635efSGarrett D'Amore term_flushln(p);
43795c635efSGarrett D'Amore
43895c635efSGarrett D'Amore p->offset = p->rmargin;
439*260e9a87SYuri Pankov sz = term_strlen(p, meta->os);
440*260e9a87SYuri Pankov p->rmargin = p->maxrmargin > sz ? p->maxrmargin - sz : 0;
44195c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
44295c635efSGarrett D'Amore
443698f87a4SGarrett D'Amore term_word(p, meta->date);
44495c635efSGarrett D'Amore term_flushln(p);
44595c635efSGarrett D'Amore
44695c635efSGarrett D'Amore p->offset = p->rmargin;
44795c635efSGarrett D'Amore p->rmargin = p->maxrmargin;
448698f87a4SGarrett D'Amore p->trailspace = 0;
44995c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK;
45095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
45195c635efSGarrett D'Amore
452698f87a4SGarrett D'Amore term_word(p, meta->os);
45395c635efSGarrett D'Amore term_flushln(p);
45495c635efSGarrett D'Amore
45595c635efSGarrett D'Amore p->offset = 0;
45695c635efSGarrett D'Amore p->rmargin = p->maxrmargin;
45795c635efSGarrett D'Amore p->flags = 0;
45895c635efSGarrett D'Amore }
45995c635efSGarrett D'Amore
46095c635efSGarrett D'Amore static void
print_mdoc_head(struct termp * p,const void * arg)46195c635efSGarrett D'Amore print_mdoc_head(struct termp *p, const void *arg)
46295c635efSGarrett D'Amore {
463698f87a4SGarrett D'Amore const struct mdoc_meta *meta;
464*260e9a87SYuri Pankov char *volume, *title;
465*260e9a87SYuri Pankov size_t vollen, titlen;
46695c635efSGarrett D'Amore
467698f87a4SGarrett D'Amore meta = (const struct mdoc_meta *)arg;
46895c635efSGarrett D'Amore
46995c635efSGarrett D'Amore /*
47095c635efSGarrett D'Amore * The header is strange. It has three components, which are
47195c635efSGarrett D'Amore * really two with the first duplicated. It goes like this:
47295c635efSGarrett D'Amore *
47395c635efSGarrett D'Amore * IDENTIFIER TITLE IDENTIFIER
47495c635efSGarrett D'Amore *
47595c635efSGarrett D'Amore * The IDENTIFIER is NAME(SECTION), which is the command-name
47695c635efSGarrett D'Amore * (if given, or "unknown" if not) followed by the manual page
47795c635efSGarrett D'Amore * section. These are given in `Dt'. The TITLE is a free-form
47895c635efSGarrett D'Amore * string depending on the manual volume. If not specified, it
47995c635efSGarrett D'Amore * switches on the manual section.
48095c635efSGarrett D'Amore */
48195c635efSGarrett D'Amore
482698f87a4SGarrett D'Amore assert(meta->vol);
483*260e9a87SYuri Pankov if (NULL == meta->arch)
484*260e9a87SYuri Pankov volume = mandoc_strdup(meta->vol);
485*260e9a87SYuri Pankov else
486*260e9a87SYuri Pankov mandoc_asprintf(&volume, "%s (%s)",
487*260e9a87SYuri Pankov meta->vol, meta->arch);
488*260e9a87SYuri Pankov vollen = term_strlen(p, volume);
48995c635efSGarrett D'Amore
490*260e9a87SYuri Pankov if (NULL == meta->msec)
491*260e9a87SYuri Pankov title = mandoc_strdup(meta->title);
492*260e9a87SYuri Pankov else
493*260e9a87SYuri Pankov mandoc_asprintf(&title, "%s(%s)",
494*260e9a87SYuri Pankov meta->title, meta->msec);
49595c635efSGarrett D'Amore titlen = term_strlen(p, title);
49695c635efSGarrett D'Amore
49795c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
498698f87a4SGarrett D'Amore p->trailspace = 1;
49995c635efSGarrett D'Amore p->offset = 0;
500*260e9a87SYuri Pankov p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
501*260e9a87SYuri Pankov (p->maxrmargin - vollen + term_len(p, 1)) / 2 :
502*260e9a87SYuri Pankov vollen < p->maxrmargin ? p->maxrmargin - vollen : 0;
50395c635efSGarrett D'Amore
50495c635efSGarrett D'Amore term_word(p, title);
50595c635efSGarrett D'Amore term_flushln(p);
50695c635efSGarrett D'Amore
50795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
50895c635efSGarrett D'Amore p->offset = p->rmargin;
509*260e9a87SYuri Pankov p->rmargin = p->offset + vollen + titlen < p->maxrmargin ?
51095c635efSGarrett D'Amore p->maxrmargin - titlen : p->maxrmargin;
51195c635efSGarrett D'Amore
512*260e9a87SYuri Pankov term_word(p, volume);
51395c635efSGarrett D'Amore term_flushln(p);
51495c635efSGarrett D'Amore
51595c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK;
516698f87a4SGarrett D'Amore p->trailspace = 0;
51795c635efSGarrett D'Amore if (p->rmargin + titlen <= p->maxrmargin) {
51895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
51995c635efSGarrett D'Amore p->offset = p->rmargin;
52095c635efSGarrett D'Amore p->rmargin = p->maxrmargin;
52195c635efSGarrett D'Amore term_word(p, title);
52295c635efSGarrett D'Amore term_flushln(p);
52395c635efSGarrett D'Amore }
52495c635efSGarrett D'Amore
52595c635efSGarrett D'Amore p->flags &= ~TERMP_NOSPACE;
52695c635efSGarrett D'Amore p->offset = 0;
52795c635efSGarrett D'Amore p->rmargin = p->maxrmargin;
528*260e9a87SYuri Pankov free(title);
529*260e9a87SYuri Pankov free(volume);
53095c635efSGarrett D'Amore }
53195c635efSGarrett D'Amore
532*260e9a87SYuri Pankov static int
a2width(const struct termp * p,const char * v)53395c635efSGarrett D'Amore a2width(const struct termp *p, const char *v)
53495c635efSGarrett D'Amore {
53595c635efSGarrett D'Amore struct roffsu su;
53695c635efSGarrett D'Amore
537*260e9a87SYuri Pankov if (a2roffsu(v, &su, SCALE_MAX) < 2) {
53895c635efSGarrett D'Amore SCALE_HS_INIT(&su, term_strlen(p, v));
539*260e9a87SYuri Pankov su.scale /= term_strlen(p, "0");
540*260e9a87SYuri Pankov }
54195c635efSGarrett D'Amore return(term_hspan(p, &su));
54295c635efSGarrett D'Amore }
54395c635efSGarrett D'Amore
54495c635efSGarrett D'Amore /*
54595c635efSGarrett D'Amore * Determine how much space to print out before block elements of `It'
54695c635efSGarrett D'Amore * (and thus `Bl') and `Bd'. And then go ahead and print that space,
54795c635efSGarrett D'Amore * too.
54895c635efSGarrett D'Amore */
54995c635efSGarrett D'Amore static void
print_bvspace(struct termp * p,const struct mdoc_node * bl,const struct mdoc_node * n)55095c635efSGarrett D'Amore print_bvspace(struct termp *p,
55195c635efSGarrett D'Amore const struct mdoc_node *bl,
55295c635efSGarrett D'Amore const struct mdoc_node *n)
55395c635efSGarrett D'Amore {
55495c635efSGarrett D'Amore const struct mdoc_node *nn;
55595c635efSGarrett D'Amore
55695c635efSGarrett D'Amore assert(n);
55795c635efSGarrett D'Amore
55895c635efSGarrett D'Amore term_newln(p);
55995c635efSGarrett D'Amore
56095c635efSGarrett D'Amore if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
56195c635efSGarrett D'Amore return;
56295c635efSGarrett D'Amore if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
56395c635efSGarrett D'Amore return;
56495c635efSGarrett D'Amore
56595c635efSGarrett D'Amore /* Do not vspace directly after Ss/Sh. */
56695c635efSGarrett D'Amore
567*260e9a87SYuri Pankov nn = n;
568*260e9a87SYuri Pankov while (nn->prev == NULL) {
569*260e9a87SYuri Pankov do {
570*260e9a87SYuri Pankov nn = nn->parent;
571*260e9a87SYuri Pankov if (nn->type == MDOC_ROOT)
57295c635efSGarrett D'Amore return;
573*260e9a87SYuri Pankov } while (nn->type != MDOC_BLOCK);
574*260e9a87SYuri Pankov if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
57595c635efSGarrett D'Amore return;
576*260e9a87SYuri Pankov if (nn->tok == MDOC_It &&
577*260e9a87SYuri Pankov nn->parent->parent->norm->Bl.type != LIST_item)
57895c635efSGarrett D'Amore break;
57995c635efSGarrett D'Amore }
58095c635efSGarrett D'Amore
58195c635efSGarrett D'Amore /* A `-column' does not assert vspace within the list. */
58295c635efSGarrett D'Amore
58395c635efSGarrett D'Amore if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
58495c635efSGarrett D'Amore if (n->prev && MDOC_It == n->prev->tok)
58595c635efSGarrett D'Amore return;
58695c635efSGarrett D'Amore
58795c635efSGarrett D'Amore /* A `-diag' without body does not vspace. */
58895c635efSGarrett D'Amore
58995c635efSGarrett D'Amore if (MDOC_Bl == bl->tok && LIST_diag == bl->norm->Bl.type)
59095c635efSGarrett D'Amore if (n->prev && MDOC_It == n->prev->tok) {
59195c635efSGarrett D'Amore assert(n->prev->body);
59295c635efSGarrett D'Amore if (NULL == n->prev->body->child)
59395c635efSGarrett D'Amore return;
59495c635efSGarrett D'Amore }
59595c635efSGarrett D'Amore
59695c635efSGarrett D'Amore term_vspace(p);
59795c635efSGarrett D'Amore }
59895c635efSGarrett D'Amore
59995c635efSGarrett D'Amore
600*260e9a87SYuri Pankov static int
termp_ll_pre(DECL_ARGS)601*260e9a87SYuri Pankov termp_ll_pre(DECL_ARGS)
602*260e9a87SYuri Pankov {
603*260e9a87SYuri Pankov
604*260e9a87SYuri Pankov term_setwidth(p, n->nchild ? n->child->string : NULL);
605*260e9a87SYuri Pankov return(0);
606*260e9a87SYuri Pankov }
607*260e9a87SYuri Pankov
60895c635efSGarrett D'Amore static int
termp_it_pre(DECL_ARGS)60995c635efSGarrett D'Amore termp_it_pre(DECL_ARGS)
61095c635efSGarrett D'Amore {
611*260e9a87SYuri Pankov char buf[24];
61295c635efSGarrett D'Amore const struct mdoc_node *bl, *nn;
613*260e9a87SYuri Pankov size_t ncols, dcol;
614*260e9a87SYuri Pankov int i, offset, width;
61595c635efSGarrett D'Amore enum mdoc_list type;
61695c635efSGarrett D'Amore
61795c635efSGarrett D'Amore if (MDOC_BLOCK == n->type) {
61895c635efSGarrett D'Amore print_bvspace(p, n->parent->parent, n);
61995c635efSGarrett D'Amore return(1);
62095c635efSGarrett D'Amore }
62195c635efSGarrett D'Amore
62295c635efSGarrett D'Amore bl = n->parent->parent->parent;
62395c635efSGarrett D'Amore type = bl->norm->Bl.type;
62495c635efSGarrett D'Amore
62595c635efSGarrett D'Amore /*
626*260e9a87SYuri Pankov * Defaults for specific list types.
627*260e9a87SYuri Pankov */
628*260e9a87SYuri Pankov
629*260e9a87SYuri Pankov switch (type) {
630*260e9a87SYuri Pankov case LIST_bullet:
631*260e9a87SYuri Pankov /* FALLTHROUGH */
632*260e9a87SYuri Pankov case LIST_dash:
633*260e9a87SYuri Pankov /* FALLTHROUGH */
634*260e9a87SYuri Pankov case LIST_hyphen:
635*260e9a87SYuri Pankov /* FALLTHROUGH */
636*260e9a87SYuri Pankov case LIST_enum:
637*260e9a87SYuri Pankov width = term_len(p, 2);
638*260e9a87SYuri Pankov break;
639*260e9a87SYuri Pankov case LIST_hang:
640*260e9a87SYuri Pankov width = term_len(p, 8);
641*260e9a87SYuri Pankov break;
642*260e9a87SYuri Pankov case LIST_column:
643*260e9a87SYuri Pankov /* FALLTHROUGH */
644*260e9a87SYuri Pankov case LIST_tag:
645*260e9a87SYuri Pankov width = term_len(p, 10);
646*260e9a87SYuri Pankov break;
647*260e9a87SYuri Pankov default:
648*260e9a87SYuri Pankov width = 0;
649*260e9a87SYuri Pankov break;
650*260e9a87SYuri Pankov }
651*260e9a87SYuri Pankov offset = 0;
652*260e9a87SYuri Pankov
653*260e9a87SYuri Pankov /*
65495c635efSGarrett D'Amore * First calculate width and offset. This is pretty easy unless
65595c635efSGarrett D'Amore * we're a -column list, in which case all prior columns must
65695c635efSGarrett D'Amore * be accounted for.
65795c635efSGarrett D'Amore */
65895c635efSGarrett D'Amore
659*260e9a87SYuri Pankov if (bl->norm->Bl.offs != NULL) {
660*260e9a87SYuri Pankov offset = a2width(p, bl->norm->Bl.offs);
661*260e9a87SYuri Pankov if (offset < 0 && (size_t)(-offset) > p->offset)
662*260e9a87SYuri Pankov offset = -p->offset;
663*260e9a87SYuri Pankov else if (offset > SHRT_MAX)
664*260e9a87SYuri Pankov offset = 0;
665*260e9a87SYuri Pankov }
66695c635efSGarrett D'Amore
66795c635efSGarrett D'Amore switch (type) {
668*260e9a87SYuri Pankov case LIST_column:
66995c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
67095c635efSGarrett D'Amore break;
67195c635efSGarrett D'Amore
67295c635efSGarrett D'Amore /*
67395c635efSGarrett D'Amore * Imitate groff's column handling:
67495c635efSGarrett D'Amore * - For each earlier column, add its width.
67595c635efSGarrett D'Amore * - For less than 5 columns, add four more blanks per
67695c635efSGarrett D'Amore * column.
67795c635efSGarrett D'Amore * - For exactly 5 columns, add three more blank per
67895c635efSGarrett D'Amore * column.
67995c635efSGarrett D'Amore * - For more than 5 columns, add only one column.
68095c635efSGarrett D'Amore */
68195c635efSGarrett D'Amore ncols = bl->norm->Bl.ncols;
68295c635efSGarrett D'Amore dcol = ncols < 5 ? term_len(p, 4) :
68395c635efSGarrett D'Amore ncols == 5 ? term_len(p, 3) : term_len(p, 1);
68495c635efSGarrett D'Amore
68595c635efSGarrett D'Amore /*
68695c635efSGarrett D'Amore * Calculate the offset by applying all prior MDOC_BODY,
68795c635efSGarrett D'Amore * so we stop at the MDOC_HEAD (NULL == nn->prev).
68895c635efSGarrett D'Amore */
68995c635efSGarrett D'Amore
69095c635efSGarrett D'Amore for (i = 0, nn = n->prev;
69195c635efSGarrett D'Amore nn->prev && i < (int)ncols;
69295c635efSGarrett D'Amore nn = nn->prev, i++)
693*260e9a87SYuri Pankov offset += dcol + a2width(p,
694*260e9a87SYuri Pankov bl->norm->Bl.cols[i]);
69595c635efSGarrett D'Amore
69695c635efSGarrett D'Amore /*
69795c635efSGarrett D'Amore * When exceeding the declared number of columns, leave
69895c635efSGarrett D'Amore * the remaining widths at 0. This will later be
69995c635efSGarrett D'Amore * adjusted to the default width of 10, or, for the last
70095c635efSGarrett D'Amore * column, stretched to the right margin.
70195c635efSGarrett D'Amore */
70295c635efSGarrett D'Amore if (i >= (int)ncols)
70395c635efSGarrett D'Amore break;
70495c635efSGarrett D'Amore
70595c635efSGarrett D'Amore /*
70695c635efSGarrett D'Amore * Use the declared column widths, extended as explained
70795c635efSGarrett D'Amore * in the preceding paragraph.
70895c635efSGarrett D'Amore */
70995c635efSGarrett D'Amore width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
71095c635efSGarrett D'Amore break;
71195c635efSGarrett D'Amore default:
71295c635efSGarrett D'Amore if (NULL == bl->norm->Bl.width)
71395c635efSGarrett D'Amore break;
71495c635efSGarrett D'Amore
71595c635efSGarrett D'Amore /*
71695c635efSGarrett D'Amore * Note: buffer the width by 2, which is groff's magic
71795c635efSGarrett D'Amore * number for buffering single arguments. See the above
71895c635efSGarrett D'Amore * handling for column for how this changes.
71995c635efSGarrett D'Amore */
72095c635efSGarrett D'Amore width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
721*260e9a87SYuri Pankov if (width < 0 && (size_t)(-width) > p->offset)
722*260e9a87SYuri Pankov width = -p->offset;
723*260e9a87SYuri Pankov else if (width > SHRT_MAX)
724*260e9a87SYuri Pankov width = 0;
72595c635efSGarrett D'Amore break;
72695c635efSGarrett D'Amore }
72795c635efSGarrett D'Amore
72895c635efSGarrett D'Amore /*
72995c635efSGarrett D'Amore * Whitespace control. Inset bodies need an initial space,
73095c635efSGarrett D'Amore * while diagonal bodies need two.
73195c635efSGarrett D'Amore */
73295c635efSGarrett D'Amore
73395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
73495c635efSGarrett D'Amore
73595c635efSGarrett D'Amore switch (type) {
736*260e9a87SYuri Pankov case LIST_diag:
73795c635efSGarrett D'Amore if (MDOC_BODY == n->type)
73895c635efSGarrett D'Amore term_word(p, "\\ \\ ");
73995c635efSGarrett D'Amore break;
740*260e9a87SYuri Pankov case LIST_inset:
741*260e9a87SYuri Pankov if (MDOC_BODY == n->type && n->parent->head->nchild)
74295c635efSGarrett D'Amore term_word(p, "\\ ");
74395c635efSGarrett D'Amore break;
74495c635efSGarrett D'Amore default:
74595c635efSGarrett D'Amore break;
74695c635efSGarrett D'Amore }
74795c635efSGarrett D'Amore
74895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
74995c635efSGarrett D'Amore
75095c635efSGarrett D'Amore switch (type) {
751*260e9a87SYuri Pankov case LIST_diag:
75295c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
75395c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
75495c635efSGarrett D'Amore break;
75595c635efSGarrett D'Amore default:
75695c635efSGarrett D'Amore break;
75795c635efSGarrett D'Amore }
75895c635efSGarrett D'Amore
75995c635efSGarrett D'Amore /*
76095c635efSGarrett D'Amore * Pad and break control. This is the tricky part. These flags
76195c635efSGarrett D'Amore * are documented in term_flushln() in term.c. Note that we're
76295c635efSGarrett D'Amore * going to unset all of these flags in termp_it_post() when we
76395c635efSGarrett D'Amore * exit.
76495c635efSGarrett D'Amore */
76595c635efSGarrett D'Amore
76695c635efSGarrett D'Amore switch (type) {
767*260e9a87SYuri Pankov case LIST_enum:
768698f87a4SGarrett D'Amore /*
769698f87a4SGarrett D'Amore * Weird special case.
770*260e9a87SYuri Pankov * Some very narrow lists actually hang.
771698f87a4SGarrett D'Amore */
772*260e9a87SYuri Pankov /* FALLTHROUGH */
773*260e9a87SYuri Pankov case LIST_bullet:
774*260e9a87SYuri Pankov /* FALLTHROUGH */
775*260e9a87SYuri Pankov case LIST_dash:
776*260e9a87SYuri Pankov /* FALLTHROUGH */
777*260e9a87SYuri Pankov case LIST_hyphen:
778*260e9a87SYuri Pankov if (width <= (int)term_len(p, 2))
779698f87a4SGarrett D'Amore p->flags |= TERMP_HANG;
780698f87a4SGarrett D'Amore if (MDOC_HEAD != n->type)
781698f87a4SGarrett D'Amore break;
78295c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK;
783698f87a4SGarrett D'Amore p->trailspace = 1;
78495c635efSGarrett D'Amore break;
785*260e9a87SYuri Pankov case LIST_hang:
786698f87a4SGarrett D'Amore if (MDOC_HEAD != n->type)
78795c635efSGarrett D'Amore break;
78895c635efSGarrett D'Amore
78995c635efSGarrett D'Amore /*
79095c635efSGarrett D'Amore * This is ugly. If `-hang' is specified and the body
79195c635efSGarrett D'Amore * is a `Bl' or `Bd', then we want basically to nullify
79295c635efSGarrett D'Amore * the "overstep" effect in term_flushln() and treat
79395c635efSGarrett D'Amore * this as a `-ohang' list instead.
79495c635efSGarrett D'Amore */
795*260e9a87SYuri Pankov if (NULL != n->next &&
796*260e9a87SYuri Pankov NULL != n->next->child &&
79795c635efSGarrett D'Amore (MDOC_Bl == n->next->child->tok ||
79895c635efSGarrett D'Amore MDOC_Bd == n->next->child->tok))
799698f87a4SGarrett D'Amore break;
800698f87a4SGarrett D'Amore
801*260e9a87SYuri Pankov p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG;
802698f87a4SGarrett D'Amore p->trailspace = 1;
80395c635efSGarrett D'Amore break;
804*260e9a87SYuri Pankov case LIST_tag:
80595c635efSGarrett D'Amore if (MDOC_HEAD != n->type)
80695c635efSGarrett D'Amore break;
807698f87a4SGarrett D'Amore
808*260e9a87SYuri Pankov p->flags |= TERMP_NOBREAK | TERMP_BRIND;
809698f87a4SGarrett D'Amore p->trailspace = 2;
810698f87a4SGarrett D'Amore
81195c635efSGarrett D'Amore if (NULL == n->next || NULL == n->next->child)
81295c635efSGarrett D'Amore p->flags |= TERMP_DANGLE;
81395c635efSGarrett D'Amore break;
814*260e9a87SYuri Pankov case LIST_column:
81595c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
81695c635efSGarrett D'Amore break;
81795c635efSGarrett D'Amore
818698f87a4SGarrett D'Amore if (NULL == n->next) {
81995c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK;
820698f87a4SGarrett D'Amore p->trailspace = 0;
821698f87a4SGarrett D'Amore } else {
82295c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK;
823698f87a4SGarrett D'Amore p->trailspace = 1;
824698f87a4SGarrett D'Amore }
82595c635efSGarrett D'Amore
82695c635efSGarrett D'Amore break;
827*260e9a87SYuri Pankov case LIST_diag:
828698f87a4SGarrett D'Amore if (MDOC_HEAD != n->type)
829698f87a4SGarrett D'Amore break;
830*260e9a87SYuri Pankov p->flags |= TERMP_NOBREAK | TERMP_BRIND;
831698f87a4SGarrett D'Amore p->trailspace = 1;
83295c635efSGarrett D'Amore break;
83395c635efSGarrett D'Amore default:
83495c635efSGarrett D'Amore break;
83595c635efSGarrett D'Amore }
83695c635efSGarrett D'Amore
83795c635efSGarrett D'Amore /*
83895c635efSGarrett D'Amore * Margin control. Set-head-width lists have their right
83995c635efSGarrett D'Amore * margins shortened. The body for these lists has the offset
84095c635efSGarrett D'Amore * necessarily lengthened. Everybody gets the offset.
84195c635efSGarrett D'Amore */
84295c635efSGarrett D'Amore
84395c635efSGarrett D'Amore p->offset += offset;
84495c635efSGarrett D'Amore
84595c635efSGarrett D'Amore switch (type) {
846*260e9a87SYuri Pankov case LIST_hang:
84795c635efSGarrett D'Amore /*
84895c635efSGarrett D'Amore * Same stipulation as above, regarding `-hang'. We
84995c635efSGarrett D'Amore * don't want to recalculate rmargin and offsets when
85095c635efSGarrett D'Amore * using `Bd' or `Bl' within `-hang' overstep lists.
85195c635efSGarrett D'Amore */
852*260e9a87SYuri Pankov if (MDOC_HEAD == n->type &&
853*260e9a87SYuri Pankov NULL != n->next &&
854*260e9a87SYuri Pankov NULL != n->next->child &&
85595c635efSGarrett D'Amore (MDOC_Bl == n->next->child->tok ||
85695c635efSGarrett D'Amore MDOC_Bd == n->next->child->tok))
85795c635efSGarrett D'Amore break;
85895c635efSGarrett D'Amore /* FALLTHROUGH */
859*260e9a87SYuri Pankov case LIST_bullet:
86095c635efSGarrett D'Amore /* FALLTHROUGH */
861*260e9a87SYuri Pankov case LIST_dash:
86295c635efSGarrett D'Amore /* FALLTHROUGH */
863*260e9a87SYuri Pankov case LIST_enum:
86495c635efSGarrett D'Amore /* FALLTHROUGH */
865*260e9a87SYuri Pankov case LIST_hyphen:
86695c635efSGarrett D'Amore /* FALLTHROUGH */
867*260e9a87SYuri Pankov case LIST_tag:
86895c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
86995c635efSGarrett D'Amore p->rmargin = p->offset + width;
87095c635efSGarrett D'Amore else
87195c635efSGarrett D'Amore p->offset += width;
87295c635efSGarrett D'Amore break;
873*260e9a87SYuri Pankov case LIST_column:
87495c635efSGarrett D'Amore assert(width);
87595c635efSGarrett D'Amore p->rmargin = p->offset + width;
87695c635efSGarrett D'Amore /*
87795c635efSGarrett D'Amore * XXX - this behaviour is not documented: the
87895c635efSGarrett D'Amore * right-most column is filled to the right margin.
87995c635efSGarrett D'Amore */
88095c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
88195c635efSGarrett D'Amore break;
88295c635efSGarrett D'Amore if (NULL == n->next && p->rmargin < p->maxrmargin)
88395c635efSGarrett D'Amore p->rmargin = p->maxrmargin;
88495c635efSGarrett D'Amore break;
88595c635efSGarrett D'Amore default:
88695c635efSGarrett D'Amore break;
88795c635efSGarrett D'Amore }
88895c635efSGarrett D'Amore
88995c635efSGarrett D'Amore /*
89095c635efSGarrett D'Amore * The dash, hyphen, bullet and enum lists all have a special
89195c635efSGarrett D'Amore * HEAD character (temporarily bold, in some cases).
89295c635efSGarrett D'Amore */
89395c635efSGarrett D'Amore
89495c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
89595c635efSGarrett D'Amore switch (type) {
896*260e9a87SYuri Pankov case LIST_bullet:
89795c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
89895c635efSGarrett D'Amore term_word(p, "\\[bu]");
89995c635efSGarrett D'Amore term_fontpop(p);
90095c635efSGarrett D'Amore break;
901*260e9a87SYuri Pankov case LIST_dash:
90295c635efSGarrett D'Amore /* FALLTHROUGH */
903*260e9a87SYuri Pankov case LIST_hyphen:
90495c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
90595c635efSGarrett D'Amore term_word(p, "\\(hy");
90695c635efSGarrett D'Amore term_fontpop(p);
90795c635efSGarrett D'Amore break;
908*260e9a87SYuri Pankov case LIST_enum:
90995c635efSGarrett D'Amore (pair->ppair->ppair->count)++;
910*260e9a87SYuri Pankov (void)snprintf(buf, sizeof(buf), "%d.",
91195c635efSGarrett D'Amore pair->ppair->ppair->count);
91295c635efSGarrett D'Amore term_word(p, buf);
91395c635efSGarrett D'Amore break;
91495c635efSGarrett D'Amore default:
91595c635efSGarrett D'Amore break;
91695c635efSGarrett D'Amore }
91795c635efSGarrett D'Amore
91895c635efSGarrett D'Amore /*
91995c635efSGarrett D'Amore * If we're not going to process our children, indicate so here.
92095c635efSGarrett D'Amore */
92195c635efSGarrett D'Amore
92295c635efSGarrett D'Amore switch (type) {
923*260e9a87SYuri Pankov case LIST_bullet:
92495c635efSGarrett D'Amore /* FALLTHROUGH */
925*260e9a87SYuri Pankov case LIST_item:
92695c635efSGarrett D'Amore /* FALLTHROUGH */
927*260e9a87SYuri Pankov case LIST_dash:
92895c635efSGarrett D'Amore /* FALLTHROUGH */
929*260e9a87SYuri Pankov case LIST_hyphen:
93095c635efSGarrett D'Amore /* FALLTHROUGH */
931*260e9a87SYuri Pankov case LIST_enum:
93295c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
93395c635efSGarrett D'Amore return(0);
93495c635efSGarrett D'Amore break;
935*260e9a87SYuri Pankov case LIST_column:
93695c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
93795c635efSGarrett D'Amore return(0);
93895c635efSGarrett D'Amore break;
93995c635efSGarrett D'Amore default:
94095c635efSGarrett D'Amore break;
94195c635efSGarrett D'Amore }
94295c635efSGarrett D'Amore
94395c635efSGarrett D'Amore return(1);
94495c635efSGarrett D'Amore }
94595c635efSGarrett D'Amore
94695c635efSGarrett D'Amore static void
termp_it_post(DECL_ARGS)94795c635efSGarrett D'Amore termp_it_post(DECL_ARGS)
94895c635efSGarrett D'Amore {
94995c635efSGarrett D'Amore enum mdoc_list type;
95095c635efSGarrett D'Amore
95195c635efSGarrett D'Amore if (MDOC_BLOCK == n->type)
95295c635efSGarrett D'Amore return;
95395c635efSGarrett D'Amore
95495c635efSGarrett D'Amore type = n->parent->parent->parent->norm->Bl.type;
95595c635efSGarrett D'Amore
95695c635efSGarrett D'Amore switch (type) {
957*260e9a87SYuri Pankov case LIST_item:
95895c635efSGarrett D'Amore /* FALLTHROUGH */
959*260e9a87SYuri Pankov case LIST_diag:
96095c635efSGarrett D'Amore /* FALLTHROUGH */
961*260e9a87SYuri Pankov case LIST_inset:
96295c635efSGarrett D'Amore if (MDOC_BODY == n->type)
96395c635efSGarrett D'Amore term_newln(p);
96495c635efSGarrett D'Amore break;
965*260e9a87SYuri Pankov case LIST_column:
96695c635efSGarrett D'Amore if (MDOC_BODY == n->type)
96795c635efSGarrett D'Amore term_flushln(p);
96895c635efSGarrett D'Amore break;
96995c635efSGarrett D'Amore default:
97095c635efSGarrett D'Amore term_newln(p);
97195c635efSGarrett D'Amore break;
97295c635efSGarrett D'Amore }
97395c635efSGarrett D'Amore
97495c635efSGarrett D'Amore /*
97595c635efSGarrett D'Amore * Now that our output is flushed, we can reset our tags. Since
97695c635efSGarrett D'Amore * only `It' sets these flags, we're free to assume that nobody
97795c635efSGarrett D'Amore * has munged them in the meanwhile.
97895c635efSGarrett D'Amore */
97995c635efSGarrett D'Amore
980*260e9a87SYuri Pankov p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND |
981*260e9a87SYuri Pankov TERMP_DANGLE | TERMP_HANG);
982698f87a4SGarrett D'Amore p->trailspace = 0;
98395c635efSGarrett D'Amore }
98495c635efSGarrett D'Amore
98595c635efSGarrett D'Amore static int
termp_nm_pre(DECL_ARGS)98695c635efSGarrett D'Amore termp_nm_pre(DECL_ARGS)
98795c635efSGarrett D'Amore {
988*260e9a87SYuri Pankov const char *cp;
98995c635efSGarrett D'Amore
990698f87a4SGarrett D'Amore if (MDOC_BLOCK == n->type) {
991698f87a4SGarrett D'Amore p->flags |= TERMP_PREKEEP;
99295c635efSGarrett D'Amore return(1);
993698f87a4SGarrett D'Amore }
99495c635efSGarrett D'Amore
99595c635efSGarrett D'Amore if (MDOC_BODY == n->type) {
99695c635efSGarrett D'Amore if (NULL == n->child)
99795c635efSGarrett D'Amore return(0);
99895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
999*260e9a87SYuri Pankov cp = NULL;
1000*260e9a87SYuri Pankov if (n->prev->child != NULL)
1001*260e9a87SYuri Pankov cp = n->prev->child->string;
1002*260e9a87SYuri Pankov if (cp == NULL)
1003*260e9a87SYuri Pankov cp = meta->name;
1004*260e9a87SYuri Pankov if (cp == NULL)
1005*260e9a87SYuri Pankov p->offset += term_len(p, 6);
1006*260e9a87SYuri Pankov else
1007*260e9a87SYuri Pankov p->offset += term_len(p, 1) + term_strlen(p, cp);
100895c635efSGarrett D'Amore return(1);
100995c635efSGarrett D'Amore }
101095c635efSGarrett D'Amore
1011698f87a4SGarrett D'Amore if (NULL == n->child && NULL == meta->name)
101295c635efSGarrett D'Amore return(0);
101395c635efSGarrett D'Amore
101495c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
101595c635efSGarrett D'Amore synopsis_pre(p, n->parent);
101695c635efSGarrett D'Amore
1017*260e9a87SYuri Pankov if (MDOC_HEAD == n->type &&
1018*260e9a87SYuri Pankov NULL != n->next && NULL != n->next->child) {
1019*260e9a87SYuri Pankov p->flags |= TERMP_NOSPACE | TERMP_NOBREAK | TERMP_BRIND;
1020698f87a4SGarrett D'Amore p->trailspace = 1;
102195c635efSGarrett D'Amore p->rmargin = p->offset + term_len(p, 1);
102295c635efSGarrett D'Amore if (NULL == n->child) {
1023698f87a4SGarrett D'Amore p->rmargin += term_strlen(p, meta->name);
102495c635efSGarrett D'Amore } else if (MDOC_TEXT == n->child->type) {
102595c635efSGarrett D'Amore p->rmargin += term_strlen(p, n->child->string);
102695c635efSGarrett D'Amore if (n->child->next)
102795c635efSGarrett D'Amore p->flags |= TERMP_HANG;
102895c635efSGarrett D'Amore } else {
102995c635efSGarrett D'Amore p->rmargin += term_len(p, 5);
103095c635efSGarrett D'Amore p->flags |= TERMP_HANG;
103195c635efSGarrett D'Amore }
103295c635efSGarrett D'Amore }
103395c635efSGarrett D'Amore
103495c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
103595c635efSGarrett D'Amore if (NULL == n->child)
1036698f87a4SGarrett D'Amore term_word(p, meta->name);
103795c635efSGarrett D'Amore return(1);
103895c635efSGarrett D'Amore }
103995c635efSGarrett D'Amore
104095c635efSGarrett D'Amore static void
termp_nm_post(DECL_ARGS)104195c635efSGarrett D'Amore termp_nm_post(DECL_ARGS)
104295c635efSGarrett D'Amore {
104395c635efSGarrett D'Amore
1044698f87a4SGarrett D'Amore if (MDOC_BLOCK == n->type) {
1045698f87a4SGarrett D'Amore p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1046*260e9a87SYuri Pankov } else if (MDOC_HEAD == n->type &&
1047*260e9a87SYuri Pankov NULL != n->next && NULL != n->next->child) {
104895c635efSGarrett D'Amore term_flushln(p);
1049*260e9a87SYuri Pankov p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
1050698f87a4SGarrett D'Amore p->trailspace = 0;
105195c635efSGarrett D'Amore } else if (MDOC_BODY == n->type && n->child)
105295c635efSGarrett D'Amore term_flushln(p);
105395c635efSGarrett D'Amore }
105495c635efSGarrett D'Amore
105595c635efSGarrett D'Amore static int
termp_fl_pre(DECL_ARGS)105695c635efSGarrett D'Amore termp_fl_pre(DECL_ARGS)
105795c635efSGarrett D'Amore {
105895c635efSGarrett D'Amore
105995c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
106095c635efSGarrett D'Amore term_word(p, "\\-");
106195c635efSGarrett D'Amore
1062*260e9a87SYuri Pankov if ( ! (n->nchild == 0 &&
1063*260e9a87SYuri Pankov (n->next == NULL ||
1064*260e9a87SYuri Pankov n->next->type == MDOC_TEXT ||
1065*260e9a87SYuri Pankov n->next->flags & MDOC_LINE)))
106695c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
106795c635efSGarrett D'Amore
106895c635efSGarrett D'Amore return(1);
106995c635efSGarrett D'Amore }
107095c635efSGarrett D'Amore
107195c635efSGarrett D'Amore static int
termp__a_pre(DECL_ARGS)107295c635efSGarrett D'Amore termp__a_pre(DECL_ARGS)
107395c635efSGarrett D'Amore {
107495c635efSGarrett D'Amore
107595c635efSGarrett D'Amore if (n->prev && MDOC__A == n->prev->tok)
107695c635efSGarrett D'Amore if (NULL == n->next || MDOC__A != n->next->tok)
107795c635efSGarrett D'Amore term_word(p, "and");
107895c635efSGarrett D'Amore
107995c635efSGarrett D'Amore return(1);
108095c635efSGarrett D'Amore }
108195c635efSGarrett D'Amore
108295c635efSGarrett D'Amore static int
termp_an_pre(DECL_ARGS)108395c635efSGarrett D'Amore termp_an_pre(DECL_ARGS)
108495c635efSGarrett D'Amore {
108595c635efSGarrett D'Amore
1086*260e9a87SYuri Pankov if (n->norm->An.auth == AUTH_split) {
108795c635efSGarrett D'Amore p->flags &= ~TERMP_NOSPLIT;
108895c635efSGarrett D'Amore p->flags |= TERMP_SPLIT;
1089*260e9a87SYuri Pankov return(0);
1090*260e9a87SYuri Pankov }
1091*260e9a87SYuri Pankov if (n->norm->An.auth == AUTH_nosplit) {
109295c635efSGarrett D'Amore p->flags &= ~TERMP_SPLIT;
109395c635efSGarrett D'Amore p->flags |= TERMP_NOSPLIT;
1094*260e9a87SYuri Pankov return(0);
109595c635efSGarrett D'Amore }
109695c635efSGarrett D'Amore
1097*260e9a87SYuri Pankov if (p->flags & TERMP_SPLIT)
1098*260e9a87SYuri Pankov term_newln(p);
1099*260e9a87SYuri Pankov
1100*260e9a87SYuri Pankov if (n->sec == SEC_AUTHORS && ! (p->flags & TERMP_NOSPLIT))
1101*260e9a87SYuri Pankov p->flags |= TERMP_SPLIT;
1102*260e9a87SYuri Pankov
1103*260e9a87SYuri Pankov return(1);
110495c635efSGarrett D'Amore }
110595c635efSGarrett D'Amore
110695c635efSGarrett D'Amore static int
termp_ns_pre(DECL_ARGS)110795c635efSGarrett D'Amore termp_ns_pre(DECL_ARGS)
110895c635efSGarrett D'Amore {
110995c635efSGarrett D'Amore
111095c635efSGarrett D'Amore if ( ! (MDOC_LINE & n->flags))
111195c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
111295c635efSGarrett D'Amore return(1);
111395c635efSGarrett D'Amore }
111495c635efSGarrett D'Amore
111595c635efSGarrett D'Amore static int
termp_rs_pre(DECL_ARGS)111695c635efSGarrett D'Amore termp_rs_pre(DECL_ARGS)
111795c635efSGarrett D'Amore {
111895c635efSGarrett D'Amore
111995c635efSGarrett D'Amore if (SEC_SEE_ALSO != n->sec)
112095c635efSGarrett D'Amore return(1);
112195c635efSGarrett D'Amore if (MDOC_BLOCK == n->type && n->prev)
112295c635efSGarrett D'Amore term_vspace(p);
112395c635efSGarrett D'Amore return(1);
112495c635efSGarrett D'Amore }
112595c635efSGarrett D'Amore
112695c635efSGarrett D'Amore static int
termp_rv_pre(DECL_ARGS)112795c635efSGarrett D'Amore termp_rv_pre(DECL_ARGS)
112895c635efSGarrett D'Amore {
112995c635efSGarrett D'Amore int nchild;
113095c635efSGarrett D'Amore
113195c635efSGarrett D'Amore term_newln(p);
113295c635efSGarrett D'Amore
113395c635efSGarrett D'Amore nchild = n->nchild;
1134*260e9a87SYuri Pankov if (nchild > 0) {
1135*260e9a87SYuri Pankov term_word(p, "The");
1136*260e9a87SYuri Pankov
113795c635efSGarrett D'Amore for (n = n->child; n; n = n->next) {
113895c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
113995c635efSGarrett D'Amore term_word(p, n->string);
114095c635efSGarrett D'Amore term_fontpop(p);
114195c635efSGarrett D'Amore
114295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
114395c635efSGarrett D'Amore term_word(p, "()");
114495c635efSGarrett D'Amore
1145*260e9a87SYuri Pankov if (n->next == NULL)
1146*260e9a87SYuri Pankov continue;
1147*260e9a87SYuri Pankov
1148*260e9a87SYuri Pankov if (nchild > 2) {
114995c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
115095c635efSGarrett D'Amore term_word(p, ",");
115195c635efSGarrett D'Amore }
1152*260e9a87SYuri Pankov if (n->next->next == NULL)
115395c635efSGarrett D'Amore term_word(p, "and");
115495c635efSGarrett D'Amore }
115595c635efSGarrett D'Amore
115695c635efSGarrett D'Amore if (nchild > 1)
115795c635efSGarrett D'Amore term_word(p, "functions return");
115895c635efSGarrett D'Amore else
115995c635efSGarrett D'Amore term_word(p, "function returns");
116095c635efSGarrett D'Amore
1161*260e9a87SYuri Pankov term_word(p, "the value\\~0 if successful;");
1162*260e9a87SYuri Pankov } else
1163*260e9a87SYuri Pankov term_word(p, "Upon successful completion,"
1164*260e9a87SYuri Pankov " the value\\~0 is returned;");
1165*260e9a87SYuri Pankov
1166*260e9a87SYuri Pankov term_word(p, "otherwise the value\\~\\-1 is returned"
1167*260e9a87SYuri Pankov " and the global variable");
116895c635efSGarrett D'Amore
116995c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
117095c635efSGarrett D'Amore term_word(p, "errno");
117195c635efSGarrett D'Amore term_fontpop(p);
117295c635efSGarrett D'Amore
117395c635efSGarrett D'Amore term_word(p, "is set to indicate the error.");
117495c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
117595c635efSGarrett D'Amore
117695c635efSGarrett D'Amore return(0);
117795c635efSGarrett D'Amore }
117895c635efSGarrett D'Amore
117995c635efSGarrett D'Amore static int
termp_ex_pre(DECL_ARGS)118095c635efSGarrett D'Amore termp_ex_pre(DECL_ARGS)
118195c635efSGarrett D'Amore {
118295c635efSGarrett D'Amore int nchild;
118395c635efSGarrett D'Amore
118495c635efSGarrett D'Amore term_newln(p);
118595c635efSGarrett D'Amore term_word(p, "The");
118695c635efSGarrett D'Amore
118795c635efSGarrett D'Amore nchild = n->nchild;
118895c635efSGarrett D'Amore for (n = n->child; n; n = n->next) {
118995c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
119095c635efSGarrett D'Amore term_word(p, n->string);
119195c635efSGarrett D'Amore term_fontpop(p);
119295c635efSGarrett D'Amore
119395c635efSGarrett D'Amore if (nchild > 2 && n->next) {
119495c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
119595c635efSGarrett D'Amore term_word(p, ",");
119695c635efSGarrett D'Amore }
119795c635efSGarrett D'Amore
119895c635efSGarrett D'Amore if (n->next && NULL == n->next->next)
119995c635efSGarrett D'Amore term_word(p, "and");
120095c635efSGarrett D'Amore }
120195c635efSGarrett D'Amore
120295c635efSGarrett D'Amore if (nchild > 1)
1203*260e9a87SYuri Pankov term_word(p, "utilities exit\\~0");
120495c635efSGarrett D'Amore else
1205*260e9a87SYuri Pankov term_word(p, "utility exits\\~0");
120695c635efSGarrett D'Amore
1207*260e9a87SYuri Pankov term_word(p, "on success, and\\~>0 if an error occurs.");
120895c635efSGarrett D'Amore
120995c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
121095c635efSGarrett D'Amore return(0);
121195c635efSGarrett D'Amore }
121295c635efSGarrett D'Amore
121395c635efSGarrett D'Amore static int
termp_nd_pre(DECL_ARGS)121495c635efSGarrett D'Amore termp_nd_pre(DECL_ARGS)
121595c635efSGarrett D'Amore {
121695c635efSGarrett D'Amore
1217*260e9a87SYuri Pankov if (n->type == MDOC_BODY)
121895c635efSGarrett D'Amore term_word(p, "\\(en");
121995c635efSGarrett D'Amore return(1);
122095c635efSGarrett D'Amore }
122195c635efSGarrett D'Amore
122295c635efSGarrett D'Amore static int
termp_bl_pre(DECL_ARGS)122395c635efSGarrett D'Amore termp_bl_pre(DECL_ARGS)
122495c635efSGarrett D'Amore {
122595c635efSGarrett D'Amore
122695c635efSGarrett D'Amore return(MDOC_HEAD != n->type);
122795c635efSGarrett D'Amore }
122895c635efSGarrett D'Amore
122995c635efSGarrett D'Amore static void
termp_bl_post(DECL_ARGS)123095c635efSGarrett D'Amore termp_bl_post(DECL_ARGS)
123195c635efSGarrett D'Amore {
123295c635efSGarrett D'Amore
123395c635efSGarrett D'Amore if (MDOC_BLOCK == n->type)
123495c635efSGarrett D'Amore term_newln(p);
123595c635efSGarrett D'Amore }
123695c635efSGarrett D'Amore
123795c635efSGarrett D'Amore static int
termp_xr_pre(DECL_ARGS)123895c635efSGarrett D'Amore termp_xr_pre(DECL_ARGS)
123995c635efSGarrett D'Amore {
124095c635efSGarrett D'Amore
124195c635efSGarrett D'Amore if (NULL == (n = n->child))
124295c635efSGarrett D'Amore return(0);
124395c635efSGarrett D'Amore
124495c635efSGarrett D'Amore assert(MDOC_TEXT == n->type);
124595c635efSGarrett D'Amore term_word(p, n->string);
124695c635efSGarrett D'Amore
124795c635efSGarrett D'Amore if (NULL == (n = n->next))
124895c635efSGarrett D'Amore return(0);
124995c635efSGarrett D'Amore
125095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
125195c635efSGarrett D'Amore term_word(p, "(");
125295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
125395c635efSGarrett D'Amore
125495c635efSGarrett D'Amore assert(MDOC_TEXT == n->type);
125595c635efSGarrett D'Amore term_word(p, n->string);
125695c635efSGarrett D'Amore
125795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
125895c635efSGarrett D'Amore term_word(p, ")");
125995c635efSGarrett D'Amore
126095c635efSGarrett D'Amore return(0);
126195c635efSGarrett D'Amore }
126295c635efSGarrett D'Amore
126395c635efSGarrett D'Amore /*
126495c635efSGarrett D'Amore * This decides how to assert whitespace before any of the SYNOPSIS set
126595c635efSGarrett D'Amore * of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
126695c635efSGarrett D'Amore * macro combos).
126795c635efSGarrett D'Amore */
126895c635efSGarrett D'Amore static void
synopsis_pre(struct termp * p,const struct mdoc_node * n)126995c635efSGarrett D'Amore synopsis_pre(struct termp *p, const struct mdoc_node *n)
127095c635efSGarrett D'Amore {
127195c635efSGarrett D'Amore /*
127295c635efSGarrett D'Amore * Obviously, if we're not in a SYNOPSIS or no prior macros
127395c635efSGarrett D'Amore * exist, do nothing.
127495c635efSGarrett D'Amore */
127595c635efSGarrett D'Amore if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
127695c635efSGarrett D'Amore return;
127795c635efSGarrett D'Amore
127895c635efSGarrett D'Amore /*
127995c635efSGarrett D'Amore * If we're the second in a pair of like elements, emit our
128095c635efSGarrett D'Amore * newline and return. UNLESS we're `Fo', `Fn', `Fn', in which
128195c635efSGarrett D'Amore * case we soldier on.
128295c635efSGarrett D'Amore */
128395c635efSGarrett D'Amore if (n->prev->tok == n->tok &&
128495c635efSGarrett D'Amore MDOC_Ft != n->tok &&
128595c635efSGarrett D'Amore MDOC_Fo != n->tok &&
128695c635efSGarrett D'Amore MDOC_Fn != n->tok) {
128795c635efSGarrett D'Amore term_newln(p);
128895c635efSGarrett D'Amore return;
128995c635efSGarrett D'Amore }
129095c635efSGarrett D'Amore
129195c635efSGarrett D'Amore /*
129295c635efSGarrett D'Amore * If we're one of the SYNOPSIS set and non-like pair-wise after
129395c635efSGarrett D'Amore * another (or Fn/Fo, which we've let slip through) then assert
129495c635efSGarrett D'Amore * vertical space, else only newline and move on.
129595c635efSGarrett D'Amore */
129695c635efSGarrett D'Amore switch (n->prev->tok) {
1297*260e9a87SYuri Pankov case MDOC_Fd:
129895c635efSGarrett D'Amore /* FALLTHROUGH */
1299*260e9a87SYuri Pankov case MDOC_Fn:
130095c635efSGarrett D'Amore /* FALLTHROUGH */
1301*260e9a87SYuri Pankov case MDOC_Fo:
130295c635efSGarrett D'Amore /* FALLTHROUGH */
1303*260e9a87SYuri Pankov case MDOC_In:
130495c635efSGarrett D'Amore /* FALLTHROUGH */
1305*260e9a87SYuri Pankov case MDOC_Vt:
130695c635efSGarrett D'Amore term_vspace(p);
130795c635efSGarrett D'Amore break;
1308*260e9a87SYuri Pankov case MDOC_Ft:
130995c635efSGarrett D'Amore if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
131095c635efSGarrett D'Amore term_vspace(p);
131195c635efSGarrett D'Amore break;
131295c635efSGarrett D'Amore }
131395c635efSGarrett D'Amore /* FALLTHROUGH */
131495c635efSGarrett D'Amore default:
131595c635efSGarrett D'Amore term_newln(p);
131695c635efSGarrett D'Amore break;
131795c635efSGarrett D'Amore }
131895c635efSGarrett D'Amore }
131995c635efSGarrett D'Amore
132095c635efSGarrett D'Amore static int
termp_vt_pre(DECL_ARGS)132195c635efSGarrett D'Amore termp_vt_pre(DECL_ARGS)
132295c635efSGarrett D'Amore {
132395c635efSGarrett D'Amore
132495c635efSGarrett D'Amore if (MDOC_ELEM == n->type) {
132595c635efSGarrett D'Amore synopsis_pre(p, n);
1326698f87a4SGarrett D'Amore return(termp_under_pre(p, pair, meta, n));
132795c635efSGarrett D'Amore } else if (MDOC_BLOCK == n->type) {
132895c635efSGarrett D'Amore synopsis_pre(p, n);
132995c635efSGarrett D'Amore return(1);
133095c635efSGarrett D'Amore } else if (MDOC_HEAD == n->type)
133195c635efSGarrett D'Amore return(0);
133295c635efSGarrett D'Amore
1333698f87a4SGarrett D'Amore return(termp_under_pre(p, pair, meta, n));
133495c635efSGarrett D'Amore }
133595c635efSGarrett D'Amore
133695c635efSGarrett D'Amore static int
termp_bold_pre(DECL_ARGS)133795c635efSGarrett D'Amore termp_bold_pre(DECL_ARGS)
133895c635efSGarrett D'Amore {
133995c635efSGarrett D'Amore
134095c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
134195c635efSGarrett D'Amore return(1);
134295c635efSGarrett D'Amore }
134395c635efSGarrett D'Amore
134495c635efSGarrett D'Amore static int
termp_fd_pre(DECL_ARGS)134595c635efSGarrett D'Amore termp_fd_pre(DECL_ARGS)
134695c635efSGarrett D'Amore {
134795c635efSGarrett D'Amore
134895c635efSGarrett D'Amore synopsis_pre(p, n);
1349698f87a4SGarrett D'Amore return(termp_bold_pre(p, pair, meta, n));
1350698f87a4SGarrett D'Amore }
1351698f87a4SGarrett D'Amore
1352698f87a4SGarrett D'Amore static void
termp_fd_post(DECL_ARGS)1353698f87a4SGarrett D'Amore termp_fd_post(DECL_ARGS)
1354698f87a4SGarrett D'Amore {
1355698f87a4SGarrett D'Amore
1356698f87a4SGarrett D'Amore term_newln(p);
135795c635efSGarrett D'Amore }
135895c635efSGarrett D'Amore
135995c635efSGarrett D'Amore static int
termp_sh_pre(DECL_ARGS)136095c635efSGarrett D'Amore termp_sh_pre(DECL_ARGS)
136195c635efSGarrett D'Amore {
136295c635efSGarrett D'Amore
136395c635efSGarrett D'Amore switch (n->type) {
1364*260e9a87SYuri Pankov case MDOC_BLOCK:
1365*260e9a87SYuri Pankov /*
1366*260e9a87SYuri Pankov * Vertical space before sections, except
1367*260e9a87SYuri Pankov * when the previous section was empty.
1368*260e9a87SYuri Pankov */
1369*260e9a87SYuri Pankov if (n->prev == NULL ||
1370*260e9a87SYuri Pankov MDOC_Sh != n->prev->tok ||
1371*260e9a87SYuri Pankov (n->prev->body != NULL &&
1372*260e9a87SYuri Pankov n->prev->body->child != NULL))
137395c635efSGarrett D'Amore term_vspace(p);
137495c635efSGarrett D'Amore break;
1375*260e9a87SYuri Pankov case MDOC_HEAD:
137695c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
137795c635efSGarrett D'Amore break;
1378*260e9a87SYuri Pankov case MDOC_BODY:
137995c635efSGarrett D'Amore p->offset = term_len(p, p->defindent);
1380698f87a4SGarrett D'Amore if (SEC_AUTHORS == n->sec)
1381698f87a4SGarrett D'Amore p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
138295c635efSGarrett D'Amore break;
138395c635efSGarrett D'Amore default:
138495c635efSGarrett D'Amore break;
138595c635efSGarrett D'Amore }
138695c635efSGarrett D'Amore return(1);
138795c635efSGarrett D'Amore }
138895c635efSGarrett D'Amore
138995c635efSGarrett D'Amore static void
termp_sh_post(DECL_ARGS)139095c635efSGarrett D'Amore termp_sh_post(DECL_ARGS)
139195c635efSGarrett D'Amore {
139295c635efSGarrett D'Amore
139395c635efSGarrett D'Amore switch (n->type) {
1394*260e9a87SYuri Pankov case MDOC_HEAD:
139595c635efSGarrett D'Amore term_newln(p);
139695c635efSGarrett D'Amore break;
1397*260e9a87SYuri Pankov case MDOC_BODY:
139895c635efSGarrett D'Amore term_newln(p);
139995c635efSGarrett D'Amore p->offset = 0;
140095c635efSGarrett D'Amore break;
140195c635efSGarrett D'Amore default:
140295c635efSGarrett D'Amore break;
140395c635efSGarrett D'Amore }
140495c635efSGarrett D'Amore }
140595c635efSGarrett D'Amore
140695c635efSGarrett D'Amore static int
termp_bt_pre(DECL_ARGS)140795c635efSGarrett D'Amore termp_bt_pre(DECL_ARGS)
140895c635efSGarrett D'Amore {
140995c635efSGarrett D'Amore
141095c635efSGarrett D'Amore term_word(p, "is currently in beta test.");
141195c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
141295c635efSGarrett D'Amore return(0);
141395c635efSGarrett D'Amore }
141495c635efSGarrett D'Amore
141595c635efSGarrett D'Amore static void
termp_lb_post(DECL_ARGS)141695c635efSGarrett D'Amore termp_lb_post(DECL_ARGS)
141795c635efSGarrett D'Amore {
141895c635efSGarrett D'Amore
141995c635efSGarrett D'Amore if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags)
142095c635efSGarrett D'Amore term_newln(p);
142195c635efSGarrett D'Amore }
142295c635efSGarrett D'Amore
142395c635efSGarrett D'Amore static int
termp_ud_pre(DECL_ARGS)142495c635efSGarrett D'Amore termp_ud_pre(DECL_ARGS)
142595c635efSGarrett D'Amore {
142695c635efSGarrett D'Amore
142795c635efSGarrett D'Amore term_word(p, "currently under development.");
142895c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
142995c635efSGarrett D'Amore return(0);
143095c635efSGarrett D'Amore }
143195c635efSGarrett D'Amore
143295c635efSGarrett D'Amore static int
termp_d1_pre(DECL_ARGS)143395c635efSGarrett D'Amore termp_d1_pre(DECL_ARGS)
143495c635efSGarrett D'Amore {
143595c635efSGarrett D'Amore
143695c635efSGarrett D'Amore if (MDOC_BLOCK != n->type)
143795c635efSGarrett D'Amore return(1);
143895c635efSGarrett D'Amore term_newln(p);
143995c635efSGarrett D'Amore p->offset += term_len(p, p->defindent + 1);
144095c635efSGarrett D'Amore return(1);
144195c635efSGarrett D'Amore }
144295c635efSGarrett D'Amore
144395c635efSGarrett D'Amore static int
termp_ft_pre(DECL_ARGS)144495c635efSGarrett D'Amore termp_ft_pre(DECL_ARGS)
144595c635efSGarrett D'Amore {
144695c635efSGarrett D'Amore
144795c635efSGarrett D'Amore /* NB: MDOC_LINE does not effect this! */
144895c635efSGarrett D'Amore synopsis_pre(p, n);
144995c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
145095c635efSGarrett D'Amore return(1);
145195c635efSGarrett D'Amore }
145295c635efSGarrett D'Amore
145395c635efSGarrett D'Amore static int
termp_fn_pre(DECL_ARGS)145495c635efSGarrett D'Amore termp_fn_pre(DECL_ARGS)
145595c635efSGarrett D'Amore {
1456698f87a4SGarrett D'Amore size_t rmargin = 0;
145795c635efSGarrett D'Amore int pretty;
145895c635efSGarrett D'Amore
145995c635efSGarrett D'Amore pretty = MDOC_SYNPRETTY & n->flags;
146095c635efSGarrett D'Amore
146195c635efSGarrett D'Amore synopsis_pre(p, n);
146295c635efSGarrett D'Amore
146395c635efSGarrett D'Amore if (NULL == (n = n->child))
146495c635efSGarrett D'Amore return(0);
146595c635efSGarrett D'Amore
1466698f87a4SGarrett D'Amore if (pretty) {
1467698f87a4SGarrett D'Amore rmargin = p->rmargin;
1468698f87a4SGarrett D'Amore p->rmargin = p->offset + term_len(p, 4);
1469*260e9a87SYuri Pankov p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG;
1470698f87a4SGarrett D'Amore }
1471698f87a4SGarrett D'Amore
147295c635efSGarrett D'Amore assert(MDOC_TEXT == n->type);
147395c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
147495c635efSGarrett D'Amore term_word(p, n->string);
147595c635efSGarrett D'Amore term_fontpop(p);
147695c635efSGarrett D'Amore
1477698f87a4SGarrett D'Amore if (pretty) {
1478698f87a4SGarrett D'Amore term_flushln(p);
1479*260e9a87SYuri Pankov p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
1480698f87a4SGarrett D'Amore p->offset = p->rmargin;
1481698f87a4SGarrett D'Amore p->rmargin = rmargin;
1482698f87a4SGarrett D'Amore }
1483698f87a4SGarrett D'Amore
148495c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
148595c635efSGarrett D'Amore term_word(p, "(");
148695c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
148795c635efSGarrett D'Amore
148895c635efSGarrett D'Amore for (n = n->next; n; n = n->next) {
148995c635efSGarrett D'Amore assert(MDOC_TEXT == n->type);
149095c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
1491698f87a4SGarrett D'Amore if (pretty)
1492698f87a4SGarrett D'Amore p->flags |= TERMP_NBRWORD;
149395c635efSGarrett D'Amore term_word(p, n->string);
149495c635efSGarrett D'Amore term_fontpop(p);
149595c635efSGarrett D'Amore
149695c635efSGarrett D'Amore if (n->next) {
149795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
149895c635efSGarrett D'Amore term_word(p, ",");
149995c635efSGarrett D'Amore }
150095c635efSGarrett D'Amore }
150195c635efSGarrett D'Amore
150295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
150395c635efSGarrett D'Amore term_word(p, ")");
150495c635efSGarrett D'Amore
150595c635efSGarrett D'Amore if (pretty) {
150695c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
150795c635efSGarrett D'Amore term_word(p, ";");
1508698f87a4SGarrett D'Amore term_flushln(p);
150995c635efSGarrett D'Amore }
151095c635efSGarrett D'Amore
151195c635efSGarrett D'Amore return(0);
151295c635efSGarrett D'Amore }
151395c635efSGarrett D'Amore
151495c635efSGarrett D'Amore static int
termp_fa_pre(DECL_ARGS)151595c635efSGarrett D'Amore termp_fa_pre(DECL_ARGS)
151695c635efSGarrett D'Amore {
151795c635efSGarrett D'Amore const struct mdoc_node *nn;
151895c635efSGarrett D'Amore
151995c635efSGarrett D'Amore if (n->parent->tok != MDOC_Fo) {
152095c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
152195c635efSGarrett D'Amore return(1);
152295c635efSGarrett D'Amore }
152395c635efSGarrett D'Amore
152495c635efSGarrett D'Amore for (nn = n->child; nn; nn = nn->next) {
152595c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
1526698f87a4SGarrett D'Amore p->flags |= TERMP_NBRWORD;
152795c635efSGarrett D'Amore term_word(p, nn->string);
152895c635efSGarrett D'Amore term_fontpop(p);
152995c635efSGarrett D'Amore
1530698f87a4SGarrett D'Amore if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
153195c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
153295c635efSGarrett D'Amore term_word(p, ",");
153395c635efSGarrett D'Amore }
153495c635efSGarrett D'Amore }
153595c635efSGarrett D'Amore
153695c635efSGarrett D'Amore return(0);
153795c635efSGarrett D'Amore }
153895c635efSGarrett D'Amore
153995c635efSGarrett D'Amore static int
termp_bd_pre(DECL_ARGS)154095c635efSGarrett D'Amore termp_bd_pre(DECL_ARGS)
154195c635efSGarrett D'Amore {
1542*260e9a87SYuri Pankov size_t tabwidth, lm, len, rm, rmax;
1543698f87a4SGarrett D'Amore struct mdoc_node *nn;
1544*260e9a87SYuri Pankov int offset;
154595c635efSGarrett D'Amore
154695c635efSGarrett D'Amore if (MDOC_BLOCK == n->type) {
154795c635efSGarrett D'Amore print_bvspace(p, n, n);
154895c635efSGarrett D'Amore return(1);
154995c635efSGarrett D'Amore } else if (MDOC_HEAD == n->type)
155095c635efSGarrett D'Amore return(0);
155195c635efSGarrett D'Amore
1552*260e9a87SYuri Pankov /* Handle the -offset argument. */
1553*260e9a87SYuri Pankov
1554*260e9a87SYuri Pankov if (n->norm->Bd.offs == NULL ||
1555*260e9a87SYuri Pankov ! strcmp(n->norm->Bd.offs, "left"))
1556*260e9a87SYuri Pankov /* nothing */;
1557*260e9a87SYuri Pankov else if ( ! strcmp(n->norm->Bd.offs, "indent"))
1558*260e9a87SYuri Pankov p->offset += term_len(p, p->defindent + 1);
1559*260e9a87SYuri Pankov else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
1560*260e9a87SYuri Pankov p->offset += term_len(p, (p->defindent + 1) * 2);
1561*260e9a87SYuri Pankov else {
1562*260e9a87SYuri Pankov offset = a2width(p, n->norm->Bd.offs);
1563*260e9a87SYuri Pankov if (offset < 0 && (size_t)(-offset) > p->offset)
1564*260e9a87SYuri Pankov p->offset = 0;
1565*260e9a87SYuri Pankov else if (offset < SHRT_MAX)
1566*260e9a87SYuri Pankov p->offset += offset;
1567*260e9a87SYuri Pankov }
156895c635efSGarrett D'Amore
156995c635efSGarrett D'Amore /*
157095c635efSGarrett D'Amore * If -ragged or -filled are specified, the block does nothing
157195c635efSGarrett D'Amore * but change the indentation. If -unfilled or -literal are
157295c635efSGarrett D'Amore * specified, text is printed exactly as entered in the display:
157395c635efSGarrett D'Amore * for macro lines, a newline is appended to the line. Blank
157495c635efSGarrett D'Amore * lines are allowed.
157595c635efSGarrett D'Amore */
157695c635efSGarrett D'Amore
157795c635efSGarrett D'Amore if (DISP_literal != n->norm->Bd.type &&
1578*260e9a87SYuri Pankov DISP_unfilled != n->norm->Bd.type &&
1579*260e9a87SYuri Pankov DISP_centered != n->norm->Bd.type)
158095c635efSGarrett D'Amore return(1);
158195c635efSGarrett D'Amore
158295c635efSGarrett D'Amore tabwidth = p->tabwidth;
158395c635efSGarrett D'Amore if (DISP_literal == n->norm->Bd.type)
158495c635efSGarrett D'Amore p->tabwidth = term_len(p, 8);
158595c635efSGarrett D'Amore
1586*260e9a87SYuri Pankov lm = p->offset;
158795c635efSGarrett D'Amore rm = p->rmargin;
158895c635efSGarrett D'Amore rmax = p->maxrmargin;
158995c635efSGarrett D'Amore p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
159095c635efSGarrett D'Amore
159195c635efSGarrett D'Amore for (nn = n->child; nn; nn = nn->next) {
1592*260e9a87SYuri Pankov if (DISP_centered == n->norm->Bd.type) {
1593*260e9a87SYuri Pankov if (MDOC_TEXT == nn->type) {
1594*260e9a87SYuri Pankov len = term_strlen(p, nn->string);
1595*260e9a87SYuri Pankov p->offset = len >= rm ? 0 :
1596*260e9a87SYuri Pankov lm + len >= rm ? rm - len :
1597*260e9a87SYuri Pankov (lm + rm - len) / 2;
1598*260e9a87SYuri Pankov } else
1599*260e9a87SYuri Pankov p->offset = lm;
1600*260e9a87SYuri Pankov }
1601698f87a4SGarrett D'Amore print_mdoc_node(p, pair, meta, nn);
160295c635efSGarrett D'Amore /*
160395c635efSGarrett D'Amore * If the printed node flushes its own line, then we
160495c635efSGarrett D'Amore * needn't do it here as well. This is hacky, but the
160595c635efSGarrett D'Amore * notion of selective eoln whitespace is pretty dumb
160695c635efSGarrett D'Amore * anyway, so don't sweat it.
160795c635efSGarrett D'Amore */
160895c635efSGarrett D'Amore switch (nn->tok) {
1609*260e9a87SYuri Pankov case MDOC_Sm:
161095c635efSGarrett D'Amore /* FALLTHROUGH */
1611*260e9a87SYuri Pankov case MDOC_br:
161295c635efSGarrett D'Amore /* FALLTHROUGH */
1613*260e9a87SYuri Pankov case MDOC_sp:
161495c635efSGarrett D'Amore /* FALLTHROUGH */
1615*260e9a87SYuri Pankov case MDOC_Bl:
161695c635efSGarrett D'Amore /* FALLTHROUGH */
1617*260e9a87SYuri Pankov case MDOC_D1:
161895c635efSGarrett D'Amore /* FALLTHROUGH */
1619*260e9a87SYuri Pankov case MDOC_Dl:
162095c635efSGarrett D'Amore /* FALLTHROUGH */
1621*260e9a87SYuri Pankov case MDOC_Lp:
162295c635efSGarrett D'Amore /* FALLTHROUGH */
1623*260e9a87SYuri Pankov case MDOC_Pp:
162495c635efSGarrett D'Amore continue;
162595c635efSGarrett D'Amore default:
162695c635efSGarrett D'Amore break;
162795c635efSGarrett D'Amore }
1628*260e9a87SYuri Pankov if (p->flags & TERMP_NONEWLINE ||
1629*260e9a87SYuri Pankov (nn->next && ! (nn->next->flags & MDOC_LINE)))
163095c635efSGarrett D'Amore continue;
163195c635efSGarrett D'Amore term_flushln(p);
163295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
163395c635efSGarrett D'Amore }
163495c635efSGarrett D'Amore
163595c635efSGarrett D'Amore p->tabwidth = tabwidth;
163695c635efSGarrett D'Amore p->rmargin = rm;
163795c635efSGarrett D'Amore p->maxrmargin = rmax;
163895c635efSGarrett D'Amore return(0);
163995c635efSGarrett D'Amore }
164095c635efSGarrett D'Amore
164195c635efSGarrett D'Amore static void
termp_bd_post(DECL_ARGS)164295c635efSGarrett D'Amore termp_bd_post(DECL_ARGS)
164395c635efSGarrett D'Amore {
164495c635efSGarrett D'Amore size_t rm, rmax;
164595c635efSGarrett D'Amore
164695c635efSGarrett D'Amore if (MDOC_BODY != n->type)
164795c635efSGarrett D'Amore return;
164895c635efSGarrett D'Amore
164995c635efSGarrett D'Amore rm = p->rmargin;
165095c635efSGarrett D'Amore rmax = p->maxrmargin;
165195c635efSGarrett D'Amore
165295c635efSGarrett D'Amore if (DISP_literal == n->norm->Bd.type ||
165395c635efSGarrett D'Amore DISP_unfilled == n->norm->Bd.type)
165495c635efSGarrett D'Amore p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
165595c635efSGarrett D'Amore
165695c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
165795c635efSGarrett D'Amore term_newln(p);
165895c635efSGarrett D'Amore
165995c635efSGarrett D'Amore p->rmargin = rm;
166095c635efSGarrett D'Amore p->maxrmargin = rmax;
166195c635efSGarrett D'Amore }
166295c635efSGarrett D'Amore
166395c635efSGarrett D'Amore static int
termp_bx_pre(DECL_ARGS)166495c635efSGarrett D'Amore termp_bx_pre(DECL_ARGS)
166595c635efSGarrett D'Amore {
166695c635efSGarrett D'Amore
166795c635efSGarrett D'Amore if (NULL != (n = n->child)) {
166895c635efSGarrett D'Amore term_word(p, n->string);
166995c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
167095c635efSGarrett D'Amore term_word(p, "BSD");
167195c635efSGarrett D'Amore } else {
167295c635efSGarrett D'Amore term_word(p, "BSD");
167395c635efSGarrett D'Amore return(0);
167495c635efSGarrett D'Amore }
167595c635efSGarrett D'Amore
167695c635efSGarrett D'Amore if (NULL != (n = n->next)) {
167795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
167895c635efSGarrett D'Amore term_word(p, "-");
167995c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
168095c635efSGarrett D'Amore term_word(p, n->string);
168195c635efSGarrett D'Amore }
168295c635efSGarrett D'Amore
168395c635efSGarrett D'Amore return(0);
168495c635efSGarrett D'Amore }
168595c635efSGarrett D'Amore
168695c635efSGarrett D'Amore static int
termp_xx_pre(DECL_ARGS)168795c635efSGarrett D'Amore termp_xx_pre(DECL_ARGS)
168895c635efSGarrett D'Amore {
168995c635efSGarrett D'Amore const char *pp;
169095c635efSGarrett D'Amore int flags;
169195c635efSGarrett D'Amore
169295c635efSGarrett D'Amore pp = NULL;
169395c635efSGarrett D'Amore switch (n->tok) {
1694*260e9a87SYuri Pankov case MDOC_Bsx:
169595c635efSGarrett D'Amore pp = "BSD/OS";
169695c635efSGarrett D'Amore break;
1697*260e9a87SYuri Pankov case MDOC_Dx:
169895c635efSGarrett D'Amore pp = "DragonFly";
169995c635efSGarrett D'Amore break;
1700*260e9a87SYuri Pankov case MDOC_Fx:
170195c635efSGarrett D'Amore pp = "FreeBSD";
170295c635efSGarrett D'Amore break;
1703*260e9a87SYuri Pankov case MDOC_Nx:
170495c635efSGarrett D'Amore pp = "NetBSD";
170595c635efSGarrett D'Amore break;
1706*260e9a87SYuri Pankov case MDOC_Ox:
170795c635efSGarrett D'Amore pp = "OpenBSD";
170895c635efSGarrett D'Amore break;
1709*260e9a87SYuri Pankov case MDOC_Ux:
171095c635efSGarrett D'Amore pp = "UNIX";
171195c635efSGarrett D'Amore break;
171295c635efSGarrett D'Amore default:
1713698f87a4SGarrett D'Amore abort();
1714698f87a4SGarrett D'Amore /* NOTREACHED */
171595c635efSGarrett D'Amore }
171695c635efSGarrett D'Amore
171795c635efSGarrett D'Amore term_word(p, pp);
171895c635efSGarrett D'Amore if (n->child) {
171995c635efSGarrett D'Amore flags = p->flags;
172095c635efSGarrett D'Amore p->flags |= TERMP_KEEP;
172195c635efSGarrett D'Amore term_word(p, n->child->string);
172295c635efSGarrett D'Amore p->flags = flags;
172395c635efSGarrett D'Amore }
172495c635efSGarrett D'Amore return(0);
172595c635efSGarrett D'Amore }
172695c635efSGarrett D'Amore
172795c635efSGarrett D'Amore static void
termp_pf_post(DECL_ARGS)172895c635efSGarrett D'Amore termp_pf_post(DECL_ARGS)
172995c635efSGarrett D'Amore {
173095c635efSGarrett D'Amore
1731*260e9a87SYuri Pankov if ( ! (n->next == NULL || n->next->flags & MDOC_LINE))
173295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
173395c635efSGarrett D'Amore }
173495c635efSGarrett D'Amore
173595c635efSGarrett D'Amore static int
termp_ss_pre(DECL_ARGS)173695c635efSGarrett D'Amore termp_ss_pre(DECL_ARGS)
173795c635efSGarrett D'Amore {
173895c635efSGarrett D'Amore
173995c635efSGarrett D'Amore switch (n->type) {
1740*260e9a87SYuri Pankov case MDOC_BLOCK:
174195c635efSGarrett D'Amore term_newln(p);
174295c635efSGarrett D'Amore if (n->prev)
174395c635efSGarrett D'Amore term_vspace(p);
174495c635efSGarrett D'Amore break;
1745*260e9a87SYuri Pankov case MDOC_HEAD:
174695c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
174795c635efSGarrett D'Amore p->offset = term_len(p, (p->defindent+1)/2);
174895c635efSGarrett D'Amore break;
1749*260e9a87SYuri Pankov case MDOC_BODY:
1750*260e9a87SYuri Pankov p->offset = term_len(p, p->defindent);
1751*260e9a87SYuri Pankov break;
175295c635efSGarrett D'Amore default:
175395c635efSGarrett D'Amore break;
175495c635efSGarrett D'Amore }
175595c635efSGarrett D'Amore
175695c635efSGarrett D'Amore return(1);
175795c635efSGarrett D'Amore }
175895c635efSGarrett D'Amore
175995c635efSGarrett D'Amore static void
termp_ss_post(DECL_ARGS)176095c635efSGarrett D'Amore termp_ss_post(DECL_ARGS)
176195c635efSGarrett D'Amore {
176295c635efSGarrett D'Amore
1763*260e9a87SYuri Pankov if (n->type == MDOC_HEAD || n->type == MDOC_BODY)
176495c635efSGarrett D'Amore term_newln(p);
176595c635efSGarrett D'Amore }
176695c635efSGarrett D'Amore
176795c635efSGarrett D'Amore static int
termp_cd_pre(DECL_ARGS)176895c635efSGarrett D'Amore termp_cd_pre(DECL_ARGS)
176995c635efSGarrett D'Amore {
177095c635efSGarrett D'Amore
177195c635efSGarrett D'Amore synopsis_pre(p, n);
177295c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
177395c635efSGarrett D'Amore return(1);
177495c635efSGarrett D'Amore }
177595c635efSGarrett D'Amore
177695c635efSGarrett D'Amore static int
termp_in_pre(DECL_ARGS)177795c635efSGarrett D'Amore termp_in_pre(DECL_ARGS)
177895c635efSGarrett D'Amore {
177995c635efSGarrett D'Amore
178095c635efSGarrett D'Amore synopsis_pre(p, n);
178195c635efSGarrett D'Amore
178295c635efSGarrett D'Amore if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags) {
178395c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
178495c635efSGarrett D'Amore term_word(p, "#include");
178595c635efSGarrett D'Amore term_word(p, "<");
178695c635efSGarrett D'Amore } else {
178795c635efSGarrett D'Amore term_word(p, "<");
178895c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
178995c635efSGarrett D'Amore }
179095c635efSGarrett D'Amore
179195c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
179295c635efSGarrett D'Amore return(1);
179395c635efSGarrett D'Amore }
179495c635efSGarrett D'Amore
179595c635efSGarrett D'Amore static void
termp_in_post(DECL_ARGS)179695c635efSGarrett D'Amore termp_in_post(DECL_ARGS)
179795c635efSGarrett D'Amore {
179895c635efSGarrett D'Amore
179995c635efSGarrett D'Amore if (MDOC_SYNPRETTY & n->flags)
180095c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
180195c635efSGarrett D'Amore
180295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
180395c635efSGarrett D'Amore term_word(p, ">");
180495c635efSGarrett D'Amore
180595c635efSGarrett D'Amore if (MDOC_SYNPRETTY & n->flags)
180695c635efSGarrett D'Amore term_fontpop(p);
180795c635efSGarrett D'Amore }
180895c635efSGarrett D'Amore
180995c635efSGarrett D'Amore static int
termp_sp_pre(DECL_ARGS)181095c635efSGarrett D'Amore termp_sp_pre(DECL_ARGS)
181195c635efSGarrett D'Amore {
1812*260e9a87SYuri Pankov struct roffsu su;
1813*260e9a87SYuri Pankov int i, len;
181495c635efSGarrett D'Amore
181595c635efSGarrett D'Amore switch (n->tok) {
1816*260e9a87SYuri Pankov case MDOC_sp:
1817*260e9a87SYuri Pankov if (n->child) {
1818*260e9a87SYuri Pankov if ( ! a2roffsu(n->child->string, &su, SCALE_VS))
1819*260e9a87SYuri Pankov su.scale = 1.0;
1820*260e9a87SYuri Pankov len = term_vspan(p, &su);
1821*260e9a87SYuri Pankov } else
1822*260e9a87SYuri Pankov len = 1;
182395c635efSGarrett D'Amore break;
1824*260e9a87SYuri Pankov case MDOC_br:
182595c635efSGarrett D'Amore len = 0;
182695c635efSGarrett D'Amore break;
182795c635efSGarrett D'Amore default:
182895c635efSGarrett D'Amore len = 1;
182995c635efSGarrett D'Amore break;
183095c635efSGarrett D'Amore }
183195c635efSGarrett D'Amore
183295c635efSGarrett D'Amore if (0 == len)
183395c635efSGarrett D'Amore term_newln(p);
1834*260e9a87SYuri Pankov else if (len < 0)
1835*260e9a87SYuri Pankov p->skipvsp -= len;
1836*260e9a87SYuri Pankov else
183795c635efSGarrett D'Amore for (i = 0; i < len; i++)
183895c635efSGarrett D'Amore term_vspace(p);
183995c635efSGarrett D'Amore
184095c635efSGarrett D'Amore return(0);
184195c635efSGarrett D'Amore }
184295c635efSGarrett D'Amore
1843*260e9a87SYuri Pankov static int
termp_skip_pre(DECL_ARGS)1844*260e9a87SYuri Pankov termp_skip_pre(DECL_ARGS)
1845*260e9a87SYuri Pankov {
184695c635efSGarrett D'Amore
1847*260e9a87SYuri Pankov return(0);
1848*260e9a87SYuri Pankov }
1849*260e9a87SYuri Pankov
185095c635efSGarrett D'Amore static int
termp_quote_pre(DECL_ARGS)185195c635efSGarrett D'Amore termp_quote_pre(DECL_ARGS)
185295c635efSGarrett D'Amore {
185395c635efSGarrett D'Amore
185495c635efSGarrett D'Amore if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
185595c635efSGarrett D'Amore return(1);
185695c635efSGarrett D'Amore
185795c635efSGarrett D'Amore switch (n->tok) {
1858*260e9a87SYuri Pankov case MDOC_Ao:
185995c635efSGarrett D'Amore /* FALLTHROUGH */
1860*260e9a87SYuri Pankov case MDOC_Aq:
1861*260e9a87SYuri Pankov term_word(p, n->nchild == 1 &&
1862*260e9a87SYuri Pankov n->child->tok == MDOC_Mt ? "<" : "\\(la");
186395c635efSGarrett D'Amore break;
1864*260e9a87SYuri Pankov case MDOC_Bro:
186595c635efSGarrett D'Amore /* FALLTHROUGH */
1866*260e9a87SYuri Pankov case MDOC_Brq:
186795c635efSGarrett D'Amore term_word(p, "{");
186895c635efSGarrett D'Amore break;
1869*260e9a87SYuri Pankov case MDOC_Oo:
187095c635efSGarrett D'Amore /* FALLTHROUGH */
1871*260e9a87SYuri Pankov case MDOC_Op:
187295c635efSGarrett D'Amore /* FALLTHROUGH */
1873*260e9a87SYuri Pankov case MDOC_Bo:
187495c635efSGarrett D'Amore /* FALLTHROUGH */
1875*260e9a87SYuri Pankov case MDOC_Bq:
187695c635efSGarrett D'Amore term_word(p, "[");
187795c635efSGarrett D'Amore break;
1878*260e9a87SYuri Pankov case MDOC_Do:
187995c635efSGarrett D'Amore /* FALLTHROUGH */
1880*260e9a87SYuri Pankov case MDOC_Dq:
1881*260e9a87SYuri Pankov term_word(p, "\\(Lq");
188295c635efSGarrett D'Amore break;
1883*260e9a87SYuri Pankov case MDOC_En:
1884*260e9a87SYuri Pankov if (NULL == n->norm->Es ||
1885*260e9a87SYuri Pankov NULL == n->norm->Es->child)
1886*260e9a87SYuri Pankov return(1);
1887*260e9a87SYuri Pankov term_word(p, n->norm->Es->child->string);
188895c635efSGarrett D'Amore break;
1889*260e9a87SYuri Pankov case MDOC_Po:
189095c635efSGarrett D'Amore /* FALLTHROUGH */
1891*260e9a87SYuri Pankov case MDOC_Pq:
189295c635efSGarrett D'Amore term_word(p, "(");
189395c635efSGarrett D'Amore break;
1894*260e9a87SYuri Pankov case MDOC__T:
189595c635efSGarrett D'Amore /* FALLTHROUGH */
1896*260e9a87SYuri Pankov case MDOC_Qo:
189795c635efSGarrett D'Amore /* FALLTHROUGH */
1898*260e9a87SYuri Pankov case MDOC_Qq:
189995c635efSGarrett D'Amore term_word(p, "\"");
190095c635efSGarrett D'Amore break;
1901*260e9a87SYuri Pankov case MDOC_Ql:
190295c635efSGarrett D'Amore /* FALLTHROUGH */
1903*260e9a87SYuri Pankov case MDOC_So:
190495c635efSGarrett D'Amore /* FALLTHROUGH */
1905*260e9a87SYuri Pankov case MDOC_Sq:
1906698f87a4SGarrett D'Amore term_word(p, "\\(oq");
190795c635efSGarrett D'Amore break;
190895c635efSGarrett D'Amore default:
190995c635efSGarrett D'Amore abort();
191095c635efSGarrett D'Amore /* NOTREACHED */
191195c635efSGarrett D'Amore }
191295c635efSGarrett D'Amore
191395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
191495c635efSGarrett D'Amore return(1);
191595c635efSGarrett D'Amore }
191695c635efSGarrett D'Amore
191795c635efSGarrett D'Amore static void
termp_quote_post(DECL_ARGS)191895c635efSGarrett D'Amore termp_quote_post(DECL_ARGS)
191995c635efSGarrett D'Amore {
192095c635efSGarrett D'Amore
1921*260e9a87SYuri Pankov if (n->type != MDOC_BODY && n->type != MDOC_ELEM)
192295c635efSGarrett D'Amore return;
192395c635efSGarrett D'Amore
192495c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
192595c635efSGarrett D'Amore
192695c635efSGarrett D'Amore switch (n->tok) {
1927*260e9a87SYuri Pankov case MDOC_Ao:
192895c635efSGarrett D'Amore /* FALLTHROUGH */
1929*260e9a87SYuri Pankov case MDOC_Aq:
1930*260e9a87SYuri Pankov term_word(p, n->nchild == 1 &&
1931*260e9a87SYuri Pankov n->child->tok == MDOC_Mt ? ">" : "\\(ra");
193295c635efSGarrett D'Amore break;
1933*260e9a87SYuri Pankov case MDOC_Bro:
193495c635efSGarrett D'Amore /* FALLTHROUGH */
1935*260e9a87SYuri Pankov case MDOC_Brq:
193695c635efSGarrett D'Amore term_word(p, "}");
193795c635efSGarrett D'Amore break;
1938*260e9a87SYuri Pankov case MDOC_Oo:
193995c635efSGarrett D'Amore /* FALLTHROUGH */
1940*260e9a87SYuri Pankov case MDOC_Op:
194195c635efSGarrett D'Amore /* FALLTHROUGH */
1942*260e9a87SYuri Pankov case MDOC_Bo:
194395c635efSGarrett D'Amore /* FALLTHROUGH */
1944*260e9a87SYuri Pankov case MDOC_Bq:
194595c635efSGarrett D'Amore term_word(p, "]");
194695c635efSGarrett D'Amore break;
1947*260e9a87SYuri Pankov case MDOC_Do:
194895c635efSGarrett D'Amore /* FALLTHROUGH */
1949*260e9a87SYuri Pankov case MDOC_Dq:
1950*260e9a87SYuri Pankov term_word(p, "\\(Rq");
195195c635efSGarrett D'Amore break;
1952*260e9a87SYuri Pankov case MDOC_En:
1953*260e9a87SYuri Pankov if (n->norm->Es == NULL ||
1954*260e9a87SYuri Pankov n->norm->Es->child == NULL ||
1955*260e9a87SYuri Pankov n->norm->Es->child->next == NULL)
1956*260e9a87SYuri Pankov p->flags &= ~TERMP_NOSPACE;
1957*260e9a87SYuri Pankov else
1958*260e9a87SYuri Pankov term_word(p, n->norm->Es->child->next->string);
195995c635efSGarrett D'Amore break;
1960*260e9a87SYuri Pankov case MDOC_Po:
196195c635efSGarrett D'Amore /* FALLTHROUGH */
1962*260e9a87SYuri Pankov case MDOC_Pq:
196395c635efSGarrett D'Amore term_word(p, ")");
196495c635efSGarrett D'Amore break;
1965*260e9a87SYuri Pankov case MDOC__T:
196695c635efSGarrett D'Amore /* FALLTHROUGH */
1967*260e9a87SYuri Pankov case MDOC_Qo:
196895c635efSGarrett D'Amore /* FALLTHROUGH */
1969*260e9a87SYuri Pankov case MDOC_Qq:
197095c635efSGarrett D'Amore term_word(p, "\"");
197195c635efSGarrett D'Amore break;
1972*260e9a87SYuri Pankov case MDOC_Ql:
197395c635efSGarrett D'Amore /* FALLTHROUGH */
1974*260e9a87SYuri Pankov case MDOC_So:
197595c635efSGarrett D'Amore /* FALLTHROUGH */
1976*260e9a87SYuri Pankov case MDOC_Sq:
1977698f87a4SGarrett D'Amore term_word(p, "\\(cq");
197895c635efSGarrett D'Amore break;
197995c635efSGarrett D'Amore default:
198095c635efSGarrett D'Amore abort();
198195c635efSGarrett D'Amore /* NOTREACHED */
198295c635efSGarrett D'Amore }
198395c635efSGarrett D'Amore }
198495c635efSGarrett D'Amore
1985*260e9a87SYuri Pankov static int
termp_eo_pre(DECL_ARGS)1986*260e9a87SYuri Pankov termp_eo_pre(DECL_ARGS)
1987*260e9a87SYuri Pankov {
198895c635efSGarrett D'Amore
1989*260e9a87SYuri Pankov if (n->type != MDOC_BODY)
1990*260e9a87SYuri Pankov return(1);
1991*260e9a87SYuri Pankov
1992*260e9a87SYuri Pankov if (n->end == ENDBODY_NOT &&
1993*260e9a87SYuri Pankov n->parent->head->child == NULL &&
1994*260e9a87SYuri Pankov n->child != NULL &&
1995*260e9a87SYuri Pankov n->child->end != ENDBODY_NOT)
1996*260e9a87SYuri Pankov term_word(p, "\\&");
1997*260e9a87SYuri Pankov else if (n->end != ENDBODY_NOT ? n->child != NULL :
1998*260e9a87SYuri Pankov n->parent->head->child != NULL && (n->child != NULL ||
1999*260e9a87SYuri Pankov (n->parent->tail != NULL && n->parent->tail->child != NULL)))
2000*260e9a87SYuri Pankov p->flags |= TERMP_NOSPACE;
2001*260e9a87SYuri Pankov
2002*260e9a87SYuri Pankov return(1);
2003*260e9a87SYuri Pankov }
2004*260e9a87SYuri Pankov
2005*260e9a87SYuri Pankov static void
termp_eo_post(DECL_ARGS)2006*260e9a87SYuri Pankov termp_eo_post(DECL_ARGS)
2007*260e9a87SYuri Pankov {
2008*260e9a87SYuri Pankov int body, tail;
2009*260e9a87SYuri Pankov
2010*260e9a87SYuri Pankov if (n->type != MDOC_BODY)
2011*260e9a87SYuri Pankov return;
2012*260e9a87SYuri Pankov
2013*260e9a87SYuri Pankov if (n->end != ENDBODY_NOT) {
2014*260e9a87SYuri Pankov p->flags &= ~TERMP_NOSPACE;
2015*260e9a87SYuri Pankov return;
2016*260e9a87SYuri Pankov }
2017*260e9a87SYuri Pankov
2018*260e9a87SYuri Pankov body = n->child != NULL || n->parent->head->child != NULL;
2019*260e9a87SYuri Pankov tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
2020*260e9a87SYuri Pankov
2021*260e9a87SYuri Pankov if (body && tail)
2022*260e9a87SYuri Pankov p->flags |= TERMP_NOSPACE;
2023*260e9a87SYuri Pankov else if ( ! (body || tail))
2024*260e9a87SYuri Pankov term_word(p, "\\&");
2025*260e9a87SYuri Pankov else if ( ! tail)
2026*260e9a87SYuri Pankov p->flags &= ~TERMP_NOSPACE;
2027*260e9a87SYuri Pankov }
2028*260e9a87SYuri Pankov
202995c635efSGarrett D'Amore static int
termp_fo_pre(DECL_ARGS)203095c635efSGarrett D'Amore termp_fo_pre(DECL_ARGS)
203195c635efSGarrett D'Amore {
2032698f87a4SGarrett D'Amore size_t rmargin = 0;
2033698f87a4SGarrett D'Amore int pretty;
2034698f87a4SGarrett D'Amore
2035698f87a4SGarrett D'Amore pretty = MDOC_SYNPRETTY & n->flags;
203695c635efSGarrett D'Amore
203795c635efSGarrett D'Amore if (MDOC_BLOCK == n->type) {
203895c635efSGarrett D'Amore synopsis_pre(p, n);
203995c635efSGarrett D'Amore return(1);
204095c635efSGarrett D'Amore } else if (MDOC_BODY == n->type) {
2041698f87a4SGarrett D'Amore if (pretty) {
2042698f87a4SGarrett D'Amore rmargin = p->rmargin;
2043698f87a4SGarrett D'Amore p->rmargin = p->offset + term_len(p, 4);
2044*260e9a87SYuri Pankov p->flags |= TERMP_NOBREAK | TERMP_BRIND |
2045*260e9a87SYuri Pankov TERMP_HANG;
2046698f87a4SGarrett D'Amore }
204795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
204895c635efSGarrett D'Amore term_word(p, "(");
204995c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
2050698f87a4SGarrett D'Amore if (pretty) {
2051698f87a4SGarrett D'Amore term_flushln(p);
2052*260e9a87SYuri Pankov p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND |
2053*260e9a87SYuri Pankov TERMP_HANG);
2054698f87a4SGarrett D'Amore p->offset = p->rmargin;
2055698f87a4SGarrett D'Amore p->rmargin = rmargin;
2056698f87a4SGarrett D'Amore }
205795c635efSGarrett D'Amore return(1);
205895c635efSGarrett D'Amore }
205995c635efSGarrett D'Amore
206095c635efSGarrett D'Amore if (NULL == n->child)
206195c635efSGarrett D'Amore return(0);
206295c635efSGarrett D'Amore
206395c635efSGarrett D'Amore /* XXX: we drop non-initial arguments as per groff. */
206495c635efSGarrett D'Amore
206595c635efSGarrett D'Amore assert(n->child->string);
206695c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
206795c635efSGarrett D'Amore term_word(p, n->child->string);
206895c635efSGarrett D'Amore return(0);
206995c635efSGarrett D'Amore }
207095c635efSGarrett D'Amore
207195c635efSGarrett D'Amore static void
termp_fo_post(DECL_ARGS)207295c635efSGarrett D'Amore termp_fo_post(DECL_ARGS)
207395c635efSGarrett D'Amore {
207495c635efSGarrett D'Amore
207595c635efSGarrett D'Amore if (MDOC_BODY != n->type)
207695c635efSGarrett D'Amore return;
207795c635efSGarrett D'Amore
207895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
207995c635efSGarrett D'Amore term_word(p, ")");
208095c635efSGarrett D'Amore
208195c635efSGarrett D'Amore if (MDOC_SYNPRETTY & n->flags) {
208295c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
208395c635efSGarrett D'Amore term_word(p, ";");
2084698f87a4SGarrett D'Amore term_flushln(p);
208595c635efSGarrett D'Amore }
208695c635efSGarrett D'Amore }
208795c635efSGarrett D'Amore
208895c635efSGarrett D'Amore static int
termp_bf_pre(DECL_ARGS)208995c635efSGarrett D'Amore termp_bf_pre(DECL_ARGS)
209095c635efSGarrett D'Amore {
209195c635efSGarrett D'Amore
209295c635efSGarrett D'Amore if (MDOC_HEAD == n->type)
209395c635efSGarrett D'Amore return(0);
2094698f87a4SGarrett D'Amore else if (MDOC_BODY != n->type)
209595c635efSGarrett D'Amore return(1);
209695c635efSGarrett D'Amore
209795c635efSGarrett D'Amore if (FONT_Em == n->norm->Bf.font)
209895c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
209995c635efSGarrett D'Amore else if (FONT_Sy == n->norm->Bf.font)
210095c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
210195c635efSGarrett D'Amore else
210295c635efSGarrett D'Amore term_fontpush(p, TERMFONT_NONE);
210395c635efSGarrett D'Amore
210495c635efSGarrett D'Amore return(1);
210595c635efSGarrett D'Amore }
210695c635efSGarrett D'Amore
210795c635efSGarrett D'Amore static int
termp_sm_pre(DECL_ARGS)210895c635efSGarrett D'Amore termp_sm_pre(DECL_ARGS)
210995c635efSGarrett D'Amore {
211095c635efSGarrett D'Amore
2111*260e9a87SYuri Pankov if (NULL == n->child)
2112*260e9a87SYuri Pankov p->flags ^= TERMP_NONOSPACE;
2113*260e9a87SYuri Pankov else if (0 == strcmp("on", n->child->string))
211495c635efSGarrett D'Amore p->flags &= ~TERMP_NONOSPACE;
2115*260e9a87SYuri Pankov else
211695c635efSGarrett D'Amore p->flags |= TERMP_NONOSPACE;
211795c635efSGarrett D'Amore
2118*260e9a87SYuri Pankov if (p->col && ! (TERMP_NONOSPACE & p->flags))
2119*260e9a87SYuri Pankov p->flags &= ~TERMP_NOSPACE;
2120*260e9a87SYuri Pankov
212195c635efSGarrett D'Amore return(0);
212295c635efSGarrett D'Amore }
212395c635efSGarrett D'Amore
212495c635efSGarrett D'Amore static int
termp_ap_pre(DECL_ARGS)212595c635efSGarrett D'Amore termp_ap_pre(DECL_ARGS)
212695c635efSGarrett D'Amore {
212795c635efSGarrett D'Amore
212895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
212995c635efSGarrett D'Amore term_word(p, "'");
213095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
213195c635efSGarrett D'Amore return(1);
213295c635efSGarrett D'Amore }
213395c635efSGarrett D'Amore
213495c635efSGarrett D'Amore static void
termp____post(DECL_ARGS)213595c635efSGarrett D'Amore termp____post(DECL_ARGS)
213695c635efSGarrett D'Amore {
213795c635efSGarrett D'Amore
213895c635efSGarrett D'Amore /*
213995c635efSGarrett D'Amore * Handle lists of authors. In general, print each followed by
214095c635efSGarrett D'Amore * a comma. Don't print the comma if there are only two
214195c635efSGarrett D'Amore * authors.
214295c635efSGarrett D'Amore */
214395c635efSGarrett D'Amore if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
214495c635efSGarrett D'Amore if (NULL == n->next->next || MDOC__A != n->next->next->tok)
214595c635efSGarrett D'Amore if (NULL == n->prev || MDOC__A != n->prev->tok)
214695c635efSGarrett D'Amore return;
214795c635efSGarrett D'Amore
214895c635efSGarrett D'Amore /* TODO: %U. */
214995c635efSGarrett D'Amore
215095c635efSGarrett D'Amore if (NULL == n->parent || MDOC_Rs != n->parent->tok)
215195c635efSGarrett D'Amore return;
215295c635efSGarrett D'Amore
215395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
215495c635efSGarrett D'Amore if (NULL == n->next) {
215595c635efSGarrett D'Amore term_word(p, ".");
215695c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE;
215795c635efSGarrett D'Amore } else
215895c635efSGarrett D'Amore term_word(p, ",");
215995c635efSGarrett D'Amore }
216095c635efSGarrett D'Amore
216195c635efSGarrett D'Amore static int
termp_li_pre(DECL_ARGS)216295c635efSGarrett D'Amore termp_li_pre(DECL_ARGS)
216395c635efSGarrett D'Amore {
216495c635efSGarrett D'Amore
216595c635efSGarrett D'Amore term_fontpush(p, TERMFONT_NONE);
216695c635efSGarrett D'Amore return(1);
216795c635efSGarrett D'Amore }
216895c635efSGarrett D'Amore
216995c635efSGarrett D'Amore static int
termp_lk_pre(DECL_ARGS)217095c635efSGarrett D'Amore termp_lk_pre(DECL_ARGS)
217195c635efSGarrett D'Amore {
2172698f87a4SGarrett D'Amore const struct mdoc_node *link, *descr;
217395c635efSGarrett D'Amore
2174698f87a4SGarrett D'Amore if (NULL == (link = n->child))
2175698f87a4SGarrett D'Amore return(0);
2176698f87a4SGarrett D'Amore
2177698f87a4SGarrett D'Amore if (NULL != (descr = link->next)) {
217895c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
2179698f87a4SGarrett D'Amore while (NULL != descr) {
2180698f87a4SGarrett D'Amore term_word(p, descr->string);
2181698f87a4SGarrett D'Amore descr = descr->next;
2182698f87a4SGarrett D'Amore }
218395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE;
218495c635efSGarrett D'Amore term_word(p, ":");
2185698f87a4SGarrett D'Amore term_fontpop(p);
2186698f87a4SGarrett D'Amore }
218795c635efSGarrett D'Amore
218895c635efSGarrett D'Amore term_fontpush(p, TERMFONT_BOLD);
2189698f87a4SGarrett D'Amore term_word(p, link->string);
219095c635efSGarrett D'Amore term_fontpop(p);
219195c635efSGarrett D'Amore
219295c635efSGarrett D'Amore return(0);
219395c635efSGarrett D'Amore }
219495c635efSGarrett D'Amore
219595c635efSGarrett D'Amore static int
termp_bk_pre(DECL_ARGS)219695c635efSGarrett D'Amore termp_bk_pre(DECL_ARGS)
219795c635efSGarrett D'Amore {
219895c635efSGarrett D'Amore
219995c635efSGarrett D'Amore switch (n->type) {
2200*260e9a87SYuri Pankov case MDOC_BLOCK:
220195c635efSGarrett D'Amore break;
2202*260e9a87SYuri Pankov case MDOC_HEAD:
220395c635efSGarrett D'Amore return(0);
2204*260e9a87SYuri Pankov case MDOC_BODY:
220595c635efSGarrett D'Amore if (n->parent->args || 0 == n->prev->nchild)
220695c635efSGarrett D'Amore p->flags |= TERMP_PREKEEP;
220795c635efSGarrett D'Amore break;
220895c635efSGarrett D'Amore default:
220995c635efSGarrett D'Amore abort();
221095c635efSGarrett D'Amore /* NOTREACHED */
221195c635efSGarrett D'Amore }
221295c635efSGarrett D'Amore
221395c635efSGarrett D'Amore return(1);
221495c635efSGarrett D'Amore }
221595c635efSGarrett D'Amore
221695c635efSGarrett D'Amore static void
termp_bk_post(DECL_ARGS)221795c635efSGarrett D'Amore termp_bk_post(DECL_ARGS)
221895c635efSGarrett D'Amore {
221995c635efSGarrett D'Amore
222095c635efSGarrett D'Amore if (MDOC_BODY == n->type)
222195c635efSGarrett D'Amore p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
222295c635efSGarrett D'Amore }
222395c635efSGarrett D'Amore
222495c635efSGarrett D'Amore static void
termp__t_post(DECL_ARGS)222595c635efSGarrett D'Amore termp__t_post(DECL_ARGS)
222695c635efSGarrett D'Amore {
222795c635efSGarrett D'Amore
222895c635efSGarrett D'Amore /*
222995c635efSGarrett D'Amore * If we're in an `Rs' and there's a journal present, then quote
223095c635efSGarrett D'Amore * us instead of underlining us (for disambiguation).
223195c635efSGarrett D'Amore */
223295c635efSGarrett D'Amore if (n->parent && MDOC_Rs == n->parent->tok &&
223395c635efSGarrett D'Amore n->parent->norm->Rs.quote_T)
2234698f87a4SGarrett D'Amore termp_quote_post(p, pair, meta, n);
223595c635efSGarrett D'Amore
2236698f87a4SGarrett D'Amore termp____post(p, pair, meta, n);
223795c635efSGarrett D'Amore }
223895c635efSGarrett D'Amore
223995c635efSGarrett D'Amore static int
termp__t_pre(DECL_ARGS)224095c635efSGarrett D'Amore termp__t_pre(DECL_ARGS)
224195c635efSGarrett D'Amore {
224295c635efSGarrett D'Amore
224395c635efSGarrett D'Amore /*
224495c635efSGarrett D'Amore * If we're in an `Rs' and there's a journal present, then quote
224595c635efSGarrett D'Amore * us instead of underlining us (for disambiguation).
224695c635efSGarrett D'Amore */
224795c635efSGarrett D'Amore if (n->parent && MDOC_Rs == n->parent->tok &&
224895c635efSGarrett D'Amore n->parent->norm->Rs.quote_T)
2249698f87a4SGarrett D'Amore return(termp_quote_pre(p, pair, meta, n));
225095c635efSGarrett D'Amore
225195c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
225295c635efSGarrett D'Amore return(1);
225395c635efSGarrett D'Amore }
225495c635efSGarrett D'Amore
225595c635efSGarrett D'Amore static int
termp_under_pre(DECL_ARGS)225695c635efSGarrett D'Amore termp_under_pre(DECL_ARGS)
225795c635efSGarrett D'Amore {
225895c635efSGarrett D'Amore
225995c635efSGarrett D'Amore term_fontpush(p, TERMFONT_UNDER);
226095c635efSGarrett D'Amore return(1);
226195c635efSGarrett D'Amore }
2262