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