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