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