1*95c635efSGarrett D'Amore /* $Id: man_term.c,v 1.127 2012/01/03 15:16:24 kristaps Exp $ */ 2*95c635efSGarrett D'Amore /* 3*95c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*95c635efSGarrett D'Amore * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org> 5*95c635efSGarrett D'Amore * 6*95c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 7*95c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 8*95c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 9*95c635efSGarrett D'Amore * 10*95c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*95c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*95c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*95c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*95c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*95c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*95c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*95c635efSGarrett D'Amore */ 18*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 19*95c635efSGarrett D'Amore #include "config.h" 20*95c635efSGarrett D'Amore #endif 21*95c635efSGarrett D'Amore 22*95c635efSGarrett D'Amore #include <sys/types.h> 23*95c635efSGarrett D'Amore 24*95c635efSGarrett D'Amore #include <assert.h> 25*95c635efSGarrett D'Amore #include <ctype.h> 26*95c635efSGarrett D'Amore #include <stdio.h> 27*95c635efSGarrett D'Amore #include <stdlib.h> 28*95c635efSGarrett D'Amore #include <string.h> 29*95c635efSGarrett D'Amore 30*95c635efSGarrett D'Amore #include "mandoc.h" 31*95c635efSGarrett D'Amore #include "out.h" 32*95c635efSGarrett D'Amore #include "man.h" 33*95c635efSGarrett D'Amore #include "term.h" 34*95c635efSGarrett D'Amore #include "main.h" 35*95c635efSGarrett D'Amore 36*95c635efSGarrett D'Amore #define MAXMARGINS 64 /* maximum number of indented scopes */ 37*95c635efSGarrett D'Amore 38*95c635efSGarrett D'Amore /* FIXME: have PD set the default vspace width. */ 39*95c635efSGarrett D'Amore 40*95c635efSGarrett D'Amore struct mtermp { 41*95c635efSGarrett D'Amore int fl; 42*95c635efSGarrett D'Amore #define MANT_LITERAL (1 << 0) 43*95c635efSGarrett D'Amore size_t lmargin[MAXMARGINS]; /* margins (incl. visible page) */ 44*95c635efSGarrett D'Amore int lmargincur; /* index of current margin */ 45*95c635efSGarrett D'Amore int lmarginsz; /* actual number of nested margins */ 46*95c635efSGarrett D'Amore size_t offset; /* default offset to visible page */ 47*95c635efSGarrett D'Amore }; 48*95c635efSGarrett D'Amore 49*95c635efSGarrett D'Amore #define DECL_ARGS struct termp *p, \ 50*95c635efSGarrett D'Amore struct mtermp *mt, \ 51*95c635efSGarrett D'Amore const struct man_node *n, \ 52*95c635efSGarrett D'Amore const struct man_meta *m 53*95c635efSGarrett D'Amore 54*95c635efSGarrett D'Amore struct termact { 55*95c635efSGarrett D'Amore int (*pre)(DECL_ARGS); 56*95c635efSGarrett D'Amore void (*post)(DECL_ARGS); 57*95c635efSGarrett D'Amore int flags; 58*95c635efSGarrett D'Amore #define MAN_NOTEXT (1 << 0) /* Never has text children. */ 59*95c635efSGarrett D'Amore }; 60*95c635efSGarrett D'Amore 61*95c635efSGarrett D'Amore static int a2width(const struct termp *, const char *); 62*95c635efSGarrett D'Amore static size_t a2height(const struct termp *, const char *); 63*95c635efSGarrett D'Amore 64*95c635efSGarrett D'Amore static void print_man_nodelist(DECL_ARGS); 65*95c635efSGarrett D'Amore static void print_man_node(DECL_ARGS); 66*95c635efSGarrett D'Amore static void print_man_head(struct termp *, const void *); 67*95c635efSGarrett D'Amore static void print_man_foot(struct termp *, const void *); 68*95c635efSGarrett D'Amore static void print_bvspace(struct termp *, 69*95c635efSGarrett D'Amore const struct man_node *); 70*95c635efSGarrett D'Amore 71*95c635efSGarrett D'Amore static int pre_B(DECL_ARGS); 72*95c635efSGarrett D'Amore static int pre_HP(DECL_ARGS); 73*95c635efSGarrett D'Amore static int pre_I(DECL_ARGS); 74*95c635efSGarrett D'Amore static int pre_IP(DECL_ARGS); 75*95c635efSGarrett D'Amore static int pre_OP(DECL_ARGS); 76*95c635efSGarrett D'Amore static int pre_PP(DECL_ARGS); 77*95c635efSGarrett D'Amore static int pre_RS(DECL_ARGS); 78*95c635efSGarrett D'Amore static int pre_SH(DECL_ARGS); 79*95c635efSGarrett D'Amore static int pre_SS(DECL_ARGS); 80*95c635efSGarrett D'Amore static int pre_TP(DECL_ARGS); 81*95c635efSGarrett D'Amore static int pre_alternate(DECL_ARGS); 82*95c635efSGarrett D'Amore static int pre_ft(DECL_ARGS); 83*95c635efSGarrett D'Amore static int pre_ign(DECL_ARGS); 84*95c635efSGarrett D'Amore static int pre_in(DECL_ARGS); 85*95c635efSGarrett D'Amore static int pre_literal(DECL_ARGS); 86*95c635efSGarrett D'Amore static int pre_sp(DECL_ARGS); 87*95c635efSGarrett D'Amore 88*95c635efSGarrett D'Amore static void post_IP(DECL_ARGS); 89*95c635efSGarrett D'Amore static void post_HP(DECL_ARGS); 90*95c635efSGarrett D'Amore static void post_RS(DECL_ARGS); 91*95c635efSGarrett D'Amore static void post_SH(DECL_ARGS); 92*95c635efSGarrett D'Amore static void post_SS(DECL_ARGS); 93*95c635efSGarrett D'Amore static void post_TP(DECL_ARGS); 94*95c635efSGarrett D'Amore 95*95c635efSGarrett D'Amore static const struct termact termacts[MAN_MAX] = { 96*95c635efSGarrett D'Amore { pre_sp, NULL, MAN_NOTEXT }, /* br */ 97*95c635efSGarrett D'Amore { NULL, NULL, 0 }, /* TH */ 98*95c635efSGarrett D'Amore { pre_SH, post_SH, 0 }, /* SH */ 99*95c635efSGarrett D'Amore { pre_SS, post_SS, 0 }, /* SS */ 100*95c635efSGarrett D'Amore { pre_TP, post_TP, 0 }, /* TP */ 101*95c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* LP */ 102*95c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* PP */ 103*95c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* P */ 104*95c635efSGarrett D'Amore { pre_IP, post_IP, 0 }, /* IP */ 105*95c635efSGarrett D'Amore { pre_HP, post_HP, 0 }, /* HP */ 106*95c635efSGarrett D'Amore { NULL, NULL, 0 }, /* SM */ 107*95c635efSGarrett D'Amore { pre_B, NULL, 0 }, /* SB */ 108*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* BI */ 109*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* IB */ 110*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* BR */ 111*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* RB */ 112*95c635efSGarrett D'Amore { NULL, NULL, 0 }, /* R */ 113*95c635efSGarrett D'Amore { pre_B, NULL, 0 }, /* B */ 114*95c635efSGarrett D'Amore { pre_I, NULL, 0 }, /* I */ 115*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* IR */ 116*95c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* RI */ 117*95c635efSGarrett D'Amore { pre_ign, NULL, MAN_NOTEXT }, /* na */ 118*95c635efSGarrett D'Amore { pre_sp, NULL, MAN_NOTEXT }, /* sp */ 119*95c635efSGarrett D'Amore { pre_literal, NULL, 0 }, /* nf */ 120*95c635efSGarrett D'Amore { pre_literal, NULL, 0 }, /* fi */ 121*95c635efSGarrett D'Amore { NULL, NULL, 0 }, /* RE */ 122*95c635efSGarrett D'Amore { pre_RS, post_RS, 0 }, /* RS */ 123*95c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* DT */ 124*95c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* UC */ 125*95c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* PD */ 126*95c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* AT */ 127*95c635efSGarrett D'Amore { pre_in, NULL, MAN_NOTEXT }, /* in */ 128*95c635efSGarrett D'Amore { pre_ft, NULL, MAN_NOTEXT }, /* ft */ 129*95c635efSGarrett D'Amore { pre_OP, NULL, 0 }, /* OP */ 130*95c635efSGarrett D'Amore }; 131*95c635efSGarrett D'Amore 132*95c635efSGarrett D'Amore 133*95c635efSGarrett D'Amore 134*95c635efSGarrett D'Amore void 135*95c635efSGarrett D'Amore terminal_man(void *arg, const struct man *man) 136*95c635efSGarrett D'Amore { 137*95c635efSGarrett D'Amore struct termp *p; 138*95c635efSGarrett D'Amore const struct man_node *n; 139*95c635efSGarrett D'Amore const struct man_meta *m; 140*95c635efSGarrett D'Amore struct mtermp mt; 141*95c635efSGarrett D'Amore 142*95c635efSGarrett D'Amore p = (struct termp *)arg; 143*95c635efSGarrett D'Amore 144*95c635efSGarrett D'Amore if (0 == p->defindent) 145*95c635efSGarrett D'Amore p->defindent = 7; 146*95c635efSGarrett D'Amore 147*95c635efSGarrett D'Amore p->overstep = 0; 148*95c635efSGarrett D'Amore p->maxrmargin = p->defrmargin; 149*95c635efSGarrett D'Amore p->tabwidth = term_len(p, 5); 150*95c635efSGarrett D'Amore 151*95c635efSGarrett D'Amore if (NULL == p->symtab) 152*95c635efSGarrett D'Amore p->symtab = mchars_alloc(); 153*95c635efSGarrett D'Amore 154*95c635efSGarrett D'Amore n = man_node(man); 155*95c635efSGarrett D'Amore m = man_meta(man); 156*95c635efSGarrett D'Amore 157*95c635efSGarrett D'Amore term_begin(p, print_man_head, print_man_foot, m); 158*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 159*95c635efSGarrett D'Amore 160*95c635efSGarrett D'Amore memset(&mt, 0, sizeof(struct mtermp)); 161*95c635efSGarrett D'Amore 162*95c635efSGarrett D'Amore mt.lmargin[mt.lmargincur] = term_len(p, p->defindent); 163*95c635efSGarrett D'Amore mt.offset = term_len(p, p->defindent); 164*95c635efSGarrett D'Amore 165*95c635efSGarrett D'Amore if (n->child) 166*95c635efSGarrett D'Amore print_man_nodelist(p, &mt, n->child, m); 167*95c635efSGarrett D'Amore 168*95c635efSGarrett D'Amore term_end(p); 169*95c635efSGarrett D'Amore } 170*95c635efSGarrett D'Amore 171*95c635efSGarrett D'Amore 172*95c635efSGarrett D'Amore static size_t 173*95c635efSGarrett D'Amore a2height(const struct termp *p, const char *cp) 174*95c635efSGarrett D'Amore { 175*95c635efSGarrett D'Amore struct roffsu su; 176*95c635efSGarrett D'Amore 177*95c635efSGarrett D'Amore if ( ! a2roffsu(cp, &su, SCALE_VS)) 178*95c635efSGarrett D'Amore SCALE_VS_INIT(&su, atoi(cp)); 179*95c635efSGarrett D'Amore 180*95c635efSGarrett D'Amore return(term_vspan(p, &su)); 181*95c635efSGarrett D'Amore } 182*95c635efSGarrett D'Amore 183*95c635efSGarrett D'Amore 184*95c635efSGarrett D'Amore static int 185*95c635efSGarrett D'Amore a2width(const struct termp *p, const char *cp) 186*95c635efSGarrett D'Amore { 187*95c635efSGarrett D'Amore struct roffsu su; 188*95c635efSGarrett D'Amore 189*95c635efSGarrett D'Amore if ( ! a2roffsu(cp, &su, SCALE_BU)) 190*95c635efSGarrett D'Amore return(-1); 191*95c635efSGarrett D'Amore 192*95c635efSGarrett D'Amore return((int)term_hspan(p, &su)); 193*95c635efSGarrett D'Amore } 194*95c635efSGarrett D'Amore 195*95c635efSGarrett D'Amore /* 196*95c635efSGarrett D'Amore * Printing leading vertical space before a block. 197*95c635efSGarrett D'Amore * This is used for the paragraph macros. 198*95c635efSGarrett D'Amore * The rules are pretty simple, since there's very little nesting going 199*95c635efSGarrett D'Amore * on here. Basically, if we're the first within another block (SS/SH), 200*95c635efSGarrett D'Amore * then don't emit vertical space. If we are (RS), then do. If not the 201*95c635efSGarrett D'Amore * first, print it. 202*95c635efSGarrett D'Amore */ 203*95c635efSGarrett D'Amore static void 204*95c635efSGarrett D'Amore print_bvspace(struct termp *p, const struct man_node *n) 205*95c635efSGarrett D'Amore { 206*95c635efSGarrett D'Amore 207*95c635efSGarrett D'Amore term_newln(p); 208*95c635efSGarrett D'Amore 209*95c635efSGarrett D'Amore if (n->body && n->body->child) 210*95c635efSGarrett D'Amore if (MAN_TBL == n->body->child->type) 211*95c635efSGarrett D'Amore return; 212*95c635efSGarrett D'Amore 213*95c635efSGarrett D'Amore if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) 214*95c635efSGarrett D'Amore if (NULL == n->prev) 215*95c635efSGarrett D'Amore return; 216*95c635efSGarrett D'Amore 217*95c635efSGarrett D'Amore term_vspace(p); 218*95c635efSGarrett D'Amore } 219*95c635efSGarrett D'Amore 220*95c635efSGarrett D'Amore /* ARGSUSED */ 221*95c635efSGarrett D'Amore static int 222*95c635efSGarrett D'Amore pre_ign(DECL_ARGS) 223*95c635efSGarrett D'Amore { 224*95c635efSGarrett D'Amore 225*95c635efSGarrett D'Amore return(0); 226*95c635efSGarrett D'Amore } 227*95c635efSGarrett D'Amore 228*95c635efSGarrett D'Amore 229*95c635efSGarrett D'Amore /* ARGSUSED */ 230*95c635efSGarrett D'Amore static int 231*95c635efSGarrett D'Amore pre_I(DECL_ARGS) 232*95c635efSGarrett D'Amore { 233*95c635efSGarrett D'Amore 234*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 235*95c635efSGarrett D'Amore return(1); 236*95c635efSGarrett D'Amore } 237*95c635efSGarrett D'Amore 238*95c635efSGarrett D'Amore 239*95c635efSGarrett D'Amore /* ARGSUSED */ 240*95c635efSGarrett D'Amore static int 241*95c635efSGarrett D'Amore pre_literal(DECL_ARGS) 242*95c635efSGarrett D'Amore { 243*95c635efSGarrett D'Amore 244*95c635efSGarrett D'Amore term_newln(p); 245*95c635efSGarrett D'Amore 246*95c635efSGarrett D'Amore if (MAN_nf == n->tok) 247*95c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 248*95c635efSGarrett D'Amore else 249*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 250*95c635efSGarrett D'Amore 251*95c635efSGarrett D'Amore /* 252*95c635efSGarrett D'Amore * Unlike .IP and .TP, .HP does not have a HEAD. 253*95c635efSGarrett D'Amore * So in case a second call to term_flushln() is needed, 254*95c635efSGarrett D'Amore * indentation has to be set up explicitly. 255*95c635efSGarrett D'Amore */ 256*95c635efSGarrett D'Amore if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) { 257*95c635efSGarrett D'Amore p->offset = p->rmargin; 258*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 259*95c635efSGarrett D'Amore p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE); 260*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 261*95c635efSGarrett D'Amore } 262*95c635efSGarrett D'Amore 263*95c635efSGarrett D'Amore return(0); 264*95c635efSGarrett D'Amore } 265*95c635efSGarrett D'Amore 266*95c635efSGarrett D'Amore /* ARGSUSED */ 267*95c635efSGarrett D'Amore static int 268*95c635efSGarrett D'Amore pre_alternate(DECL_ARGS) 269*95c635efSGarrett D'Amore { 270*95c635efSGarrett D'Amore enum termfont font[2]; 271*95c635efSGarrett D'Amore const struct man_node *nn; 272*95c635efSGarrett D'Amore int savelit, i; 273*95c635efSGarrett D'Amore 274*95c635efSGarrett D'Amore switch (n->tok) { 275*95c635efSGarrett D'Amore case (MAN_RB): 276*95c635efSGarrett D'Amore font[0] = TERMFONT_NONE; 277*95c635efSGarrett D'Amore font[1] = TERMFONT_BOLD; 278*95c635efSGarrett D'Amore break; 279*95c635efSGarrett D'Amore case (MAN_RI): 280*95c635efSGarrett D'Amore font[0] = TERMFONT_NONE; 281*95c635efSGarrett D'Amore font[1] = TERMFONT_UNDER; 282*95c635efSGarrett D'Amore break; 283*95c635efSGarrett D'Amore case (MAN_BR): 284*95c635efSGarrett D'Amore font[0] = TERMFONT_BOLD; 285*95c635efSGarrett D'Amore font[1] = TERMFONT_NONE; 286*95c635efSGarrett D'Amore break; 287*95c635efSGarrett D'Amore case (MAN_BI): 288*95c635efSGarrett D'Amore font[0] = TERMFONT_BOLD; 289*95c635efSGarrett D'Amore font[1] = TERMFONT_UNDER; 290*95c635efSGarrett D'Amore break; 291*95c635efSGarrett D'Amore case (MAN_IR): 292*95c635efSGarrett D'Amore font[0] = TERMFONT_UNDER; 293*95c635efSGarrett D'Amore font[1] = TERMFONT_NONE; 294*95c635efSGarrett D'Amore break; 295*95c635efSGarrett D'Amore case (MAN_IB): 296*95c635efSGarrett D'Amore font[0] = TERMFONT_UNDER; 297*95c635efSGarrett D'Amore font[1] = TERMFONT_BOLD; 298*95c635efSGarrett D'Amore break; 299*95c635efSGarrett D'Amore default: 300*95c635efSGarrett D'Amore abort(); 301*95c635efSGarrett D'Amore } 302*95c635efSGarrett D'Amore 303*95c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 304*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 305*95c635efSGarrett D'Amore 306*95c635efSGarrett D'Amore for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) { 307*95c635efSGarrett D'Amore term_fontrepl(p, font[i]); 308*95c635efSGarrett D'Amore if (savelit && NULL == nn->next) 309*95c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 310*95c635efSGarrett D'Amore print_man_node(p, mt, nn, m); 311*95c635efSGarrett D'Amore if (nn->next) 312*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 313*95c635efSGarrett D'Amore } 314*95c635efSGarrett D'Amore 315*95c635efSGarrett D'Amore return(0); 316*95c635efSGarrett D'Amore } 317*95c635efSGarrett D'Amore 318*95c635efSGarrett D'Amore /* ARGSUSED */ 319*95c635efSGarrett D'Amore static int 320*95c635efSGarrett D'Amore pre_B(DECL_ARGS) 321*95c635efSGarrett D'Amore { 322*95c635efSGarrett D'Amore 323*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 324*95c635efSGarrett D'Amore return(1); 325*95c635efSGarrett D'Amore } 326*95c635efSGarrett D'Amore 327*95c635efSGarrett D'Amore /* ARGSUSED */ 328*95c635efSGarrett D'Amore static int 329*95c635efSGarrett D'Amore pre_OP(DECL_ARGS) 330*95c635efSGarrett D'Amore { 331*95c635efSGarrett D'Amore 332*95c635efSGarrett D'Amore term_word(p, "["); 333*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 334*95c635efSGarrett D'Amore 335*95c635efSGarrett D'Amore if (NULL != (n = n->child)) { 336*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 337*95c635efSGarrett D'Amore term_word(p, n->string); 338*95c635efSGarrett D'Amore } 339*95c635efSGarrett D'Amore if (NULL != n && NULL != n->next) { 340*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 341*95c635efSGarrett D'Amore term_word(p, n->next->string); 342*95c635efSGarrett D'Amore } 343*95c635efSGarrett D'Amore 344*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 345*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 346*95c635efSGarrett D'Amore term_word(p, "]"); 347*95c635efSGarrett D'Amore return(0); 348*95c635efSGarrett D'Amore } 349*95c635efSGarrett D'Amore 350*95c635efSGarrett D'Amore /* ARGSUSED */ 351*95c635efSGarrett D'Amore static int 352*95c635efSGarrett D'Amore pre_ft(DECL_ARGS) 353*95c635efSGarrett D'Amore { 354*95c635efSGarrett D'Amore const char *cp; 355*95c635efSGarrett D'Amore 356*95c635efSGarrett D'Amore if (NULL == n->child) { 357*95c635efSGarrett D'Amore term_fontlast(p); 358*95c635efSGarrett D'Amore return(0); 359*95c635efSGarrett D'Amore } 360*95c635efSGarrett D'Amore 361*95c635efSGarrett D'Amore cp = n->child->string; 362*95c635efSGarrett D'Amore switch (*cp) { 363*95c635efSGarrett D'Amore case ('4'): 364*95c635efSGarrett D'Amore /* FALLTHROUGH */ 365*95c635efSGarrett D'Amore case ('3'): 366*95c635efSGarrett D'Amore /* FALLTHROUGH */ 367*95c635efSGarrett D'Amore case ('B'): 368*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 369*95c635efSGarrett D'Amore break; 370*95c635efSGarrett D'Amore case ('2'): 371*95c635efSGarrett D'Amore /* FALLTHROUGH */ 372*95c635efSGarrett D'Amore case ('I'): 373*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 374*95c635efSGarrett D'Amore break; 375*95c635efSGarrett D'Amore case ('P'): 376*95c635efSGarrett D'Amore term_fontlast(p); 377*95c635efSGarrett D'Amore break; 378*95c635efSGarrett D'Amore case ('1'): 379*95c635efSGarrett D'Amore /* FALLTHROUGH */ 380*95c635efSGarrett D'Amore case ('C'): 381*95c635efSGarrett D'Amore /* FALLTHROUGH */ 382*95c635efSGarrett D'Amore case ('R'): 383*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 384*95c635efSGarrett D'Amore break; 385*95c635efSGarrett D'Amore default: 386*95c635efSGarrett D'Amore break; 387*95c635efSGarrett D'Amore } 388*95c635efSGarrett D'Amore return(0); 389*95c635efSGarrett D'Amore } 390*95c635efSGarrett D'Amore 391*95c635efSGarrett D'Amore /* ARGSUSED */ 392*95c635efSGarrett D'Amore static int 393*95c635efSGarrett D'Amore pre_in(DECL_ARGS) 394*95c635efSGarrett D'Amore { 395*95c635efSGarrett D'Amore int len, less; 396*95c635efSGarrett D'Amore size_t v; 397*95c635efSGarrett D'Amore const char *cp; 398*95c635efSGarrett D'Amore 399*95c635efSGarrett D'Amore term_newln(p); 400*95c635efSGarrett D'Amore 401*95c635efSGarrett D'Amore if (NULL == n->child) { 402*95c635efSGarrett D'Amore p->offset = mt->offset; 403*95c635efSGarrett D'Amore return(0); 404*95c635efSGarrett D'Amore } 405*95c635efSGarrett D'Amore 406*95c635efSGarrett D'Amore cp = n->child->string; 407*95c635efSGarrett D'Amore less = 0; 408*95c635efSGarrett D'Amore 409*95c635efSGarrett D'Amore if ('-' == *cp) 410*95c635efSGarrett D'Amore less = -1; 411*95c635efSGarrett D'Amore else if ('+' == *cp) 412*95c635efSGarrett D'Amore less = 1; 413*95c635efSGarrett D'Amore else 414*95c635efSGarrett D'Amore cp--; 415*95c635efSGarrett D'Amore 416*95c635efSGarrett D'Amore if ((len = a2width(p, ++cp)) < 0) 417*95c635efSGarrett D'Amore return(0); 418*95c635efSGarrett D'Amore 419*95c635efSGarrett D'Amore v = (size_t)len; 420*95c635efSGarrett D'Amore 421*95c635efSGarrett D'Amore if (less < 0) 422*95c635efSGarrett D'Amore p->offset -= p->offset > v ? v : p->offset; 423*95c635efSGarrett D'Amore else if (less > 0) 424*95c635efSGarrett D'Amore p->offset += v; 425*95c635efSGarrett D'Amore else 426*95c635efSGarrett D'Amore p->offset = v; 427*95c635efSGarrett D'Amore 428*95c635efSGarrett D'Amore /* Don't let this creep beyond the right margin. */ 429*95c635efSGarrett D'Amore 430*95c635efSGarrett D'Amore if (p->offset > p->rmargin) 431*95c635efSGarrett D'Amore p->offset = p->rmargin; 432*95c635efSGarrett D'Amore 433*95c635efSGarrett D'Amore return(0); 434*95c635efSGarrett D'Amore } 435*95c635efSGarrett D'Amore 436*95c635efSGarrett D'Amore 437*95c635efSGarrett D'Amore /* ARGSUSED */ 438*95c635efSGarrett D'Amore static int 439*95c635efSGarrett D'Amore pre_sp(DECL_ARGS) 440*95c635efSGarrett D'Amore { 441*95c635efSGarrett D'Amore size_t i, len; 442*95c635efSGarrett D'Amore 443*95c635efSGarrett D'Amore if ((NULL == n->prev && n->parent)) { 444*95c635efSGarrett D'Amore if (MAN_SS == n->parent->tok) 445*95c635efSGarrett D'Amore return(0); 446*95c635efSGarrett D'Amore if (MAN_SH == n->parent->tok) 447*95c635efSGarrett D'Amore return(0); 448*95c635efSGarrett D'Amore } 449*95c635efSGarrett D'Amore 450*95c635efSGarrett D'Amore switch (n->tok) { 451*95c635efSGarrett D'Amore case (MAN_br): 452*95c635efSGarrett D'Amore len = 0; 453*95c635efSGarrett D'Amore break; 454*95c635efSGarrett D'Amore default: 455*95c635efSGarrett D'Amore len = n->child ? a2height(p, n->child->string) : 1; 456*95c635efSGarrett D'Amore break; 457*95c635efSGarrett D'Amore } 458*95c635efSGarrett D'Amore 459*95c635efSGarrett D'Amore if (0 == len) 460*95c635efSGarrett D'Amore term_newln(p); 461*95c635efSGarrett D'Amore for (i = 0; i < len; i++) 462*95c635efSGarrett D'Amore term_vspace(p); 463*95c635efSGarrett D'Amore 464*95c635efSGarrett D'Amore return(0); 465*95c635efSGarrett D'Amore } 466*95c635efSGarrett D'Amore 467*95c635efSGarrett D'Amore 468*95c635efSGarrett D'Amore /* ARGSUSED */ 469*95c635efSGarrett D'Amore static int 470*95c635efSGarrett D'Amore pre_HP(DECL_ARGS) 471*95c635efSGarrett D'Amore { 472*95c635efSGarrett D'Amore size_t len, one; 473*95c635efSGarrett D'Amore int ival; 474*95c635efSGarrett D'Amore const struct man_node *nn; 475*95c635efSGarrett D'Amore 476*95c635efSGarrett D'Amore switch (n->type) { 477*95c635efSGarrett D'Amore case (MAN_BLOCK): 478*95c635efSGarrett D'Amore print_bvspace(p, n); 479*95c635efSGarrett D'Amore return(1); 480*95c635efSGarrett D'Amore case (MAN_BODY): 481*95c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK; 482*95c635efSGarrett D'Amore p->flags |= TERMP_TWOSPACE; 483*95c635efSGarrett D'Amore break; 484*95c635efSGarrett D'Amore default: 485*95c635efSGarrett D'Amore return(0); 486*95c635efSGarrett D'Amore } 487*95c635efSGarrett D'Amore 488*95c635efSGarrett D'Amore len = mt->lmargin[mt->lmargincur]; 489*95c635efSGarrett D'Amore ival = -1; 490*95c635efSGarrett D'Amore 491*95c635efSGarrett D'Amore /* Calculate offset. */ 492*95c635efSGarrett D'Amore 493*95c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 494*95c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 495*95c635efSGarrett D'Amore len = (size_t)ival; 496*95c635efSGarrett D'Amore 497*95c635efSGarrett D'Amore one = term_len(p, 1); 498*95c635efSGarrett D'Amore if (len < one) 499*95c635efSGarrett D'Amore len = one; 500*95c635efSGarrett D'Amore 501*95c635efSGarrett D'Amore p->offset = mt->offset; 502*95c635efSGarrett D'Amore p->rmargin = mt->offset + len; 503*95c635efSGarrett D'Amore 504*95c635efSGarrett D'Amore if (ival >= 0) 505*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 506*95c635efSGarrett D'Amore 507*95c635efSGarrett D'Amore return(1); 508*95c635efSGarrett D'Amore } 509*95c635efSGarrett D'Amore 510*95c635efSGarrett D'Amore 511*95c635efSGarrett D'Amore /* ARGSUSED */ 512*95c635efSGarrett D'Amore static void 513*95c635efSGarrett D'Amore post_HP(DECL_ARGS) 514*95c635efSGarrett D'Amore { 515*95c635efSGarrett D'Amore 516*95c635efSGarrett D'Amore switch (n->type) { 517*95c635efSGarrett D'Amore case (MAN_BLOCK): 518*95c635efSGarrett D'Amore term_flushln(p); 519*95c635efSGarrett D'Amore break; 520*95c635efSGarrett D'Amore case (MAN_BODY): 521*95c635efSGarrett D'Amore term_flushln(p); 522*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 523*95c635efSGarrett D'Amore p->flags &= ~TERMP_TWOSPACE; 524*95c635efSGarrett D'Amore p->offset = mt->offset; 525*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 526*95c635efSGarrett D'Amore break; 527*95c635efSGarrett D'Amore default: 528*95c635efSGarrett D'Amore break; 529*95c635efSGarrett D'Amore } 530*95c635efSGarrett D'Amore } 531*95c635efSGarrett D'Amore 532*95c635efSGarrett D'Amore 533*95c635efSGarrett D'Amore /* ARGSUSED */ 534*95c635efSGarrett D'Amore static int 535*95c635efSGarrett D'Amore pre_PP(DECL_ARGS) 536*95c635efSGarrett D'Amore { 537*95c635efSGarrett D'Amore 538*95c635efSGarrett D'Amore switch (n->type) { 539*95c635efSGarrett D'Amore case (MAN_BLOCK): 540*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 541*95c635efSGarrett D'Amore print_bvspace(p, n); 542*95c635efSGarrett D'Amore break; 543*95c635efSGarrett D'Amore default: 544*95c635efSGarrett D'Amore p->offset = mt->offset; 545*95c635efSGarrett D'Amore break; 546*95c635efSGarrett D'Amore } 547*95c635efSGarrett D'Amore 548*95c635efSGarrett D'Amore return(MAN_HEAD != n->type); 549*95c635efSGarrett D'Amore } 550*95c635efSGarrett D'Amore 551*95c635efSGarrett D'Amore 552*95c635efSGarrett D'Amore /* ARGSUSED */ 553*95c635efSGarrett D'Amore static int 554*95c635efSGarrett D'Amore pre_IP(DECL_ARGS) 555*95c635efSGarrett D'Amore { 556*95c635efSGarrett D'Amore const struct man_node *nn; 557*95c635efSGarrett D'Amore size_t len; 558*95c635efSGarrett D'Amore int savelit, ival; 559*95c635efSGarrett D'Amore 560*95c635efSGarrett D'Amore switch (n->type) { 561*95c635efSGarrett D'Amore case (MAN_BODY): 562*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 563*95c635efSGarrett D'Amore break; 564*95c635efSGarrett D'Amore case (MAN_HEAD): 565*95c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK; 566*95c635efSGarrett D'Amore break; 567*95c635efSGarrett D'Amore case (MAN_BLOCK): 568*95c635efSGarrett D'Amore print_bvspace(p, n); 569*95c635efSGarrett D'Amore /* FALLTHROUGH */ 570*95c635efSGarrett D'Amore default: 571*95c635efSGarrett D'Amore return(1); 572*95c635efSGarrett D'Amore } 573*95c635efSGarrett D'Amore 574*95c635efSGarrett D'Amore len = mt->lmargin[mt->lmargincur]; 575*95c635efSGarrett D'Amore ival = -1; 576*95c635efSGarrett D'Amore 577*95c635efSGarrett D'Amore /* Calculate the offset from the optional second argument. */ 578*95c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 579*95c635efSGarrett D'Amore if (NULL != (nn = nn->next)) 580*95c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 581*95c635efSGarrett D'Amore len = (size_t)ival; 582*95c635efSGarrett D'Amore 583*95c635efSGarrett D'Amore switch (n->type) { 584*95c635efSGarrett D'Amore case (MAN_HEAD): 585*95c635efSGarrett D'Amore /* Handle zero-width lengths. */ 586*95c635efSGarrett D'Amore if (0 == len) 587*95c635efSGarrett D'Amore len = term_len(p, 1); 588*95c635efSGarrett D'Amore 589*95c635efSGarrett D'Amore p->offset = mt->offset; 590*95c635efSGarrett D'Amore p->rmargin = mt->offset + len; 591*95c635efSGarrett D'Amore if (ival < 0) 592*95c635efSGarrett D'Amore break; 593*95c635efSGarrett D'Amore 594*95c635efSGarrett D'Amore /* Set the saved left-margin. */ 595*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 596*95c635efSGarrett D'Amore 597*95c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 598*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 599*95c635efSGarrett D'Amore 600*95c635efSGarrett D'Amore if (n->child) 601*95c635efSGarrett D'Amore print_man_node(p, mt, n->child, m); 602*95c635efSGarrett D'Amore 603*95c635efSGarrett D'Amore if (savelit) 604*95c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 605*95c635efSGarrett D'Amore 606*95c635efSGarrett D'Amore return(0); 607*95c635efSGarrett D'Amore case (MAN_BODY): 608*95c635efSGarrett D'Amore p->offset = mt->offset + len; 609*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 610*95c635efSGarrett D'Amore break; 611*95c635efSGarrett D'Amore default: 612*95c635efSGarrett D'Amore break; 613*95c635efSGarrett D'Amore } 614*95c635efSGarrett D'Amore 615*95c635efSGarrett D'Amore return(1); 616*95c635efSGarrett D'Amore } 617*95c635efSGarrett D'Amore 618*95c635efSGarrett D'Amore 619*95c635efSGarrett D'Amore /* ARGSUSED */ 620*95c635efSGarrett D'Amore static void 621*95c635efSGarrett D'Amore post_IP(DECL_ARGS) 622*95c635efSGarrett D'Amore { 623*95c635efSGarrett D'Amore 624*95c635efSGarrett D'Amore switch (n->type) { 625*95c635efSGarrett D'Amore case (MAN_HEAD): 626*95c635efSGarrett D'Amore term_flushln(p); 627*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 628*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 629*95c635efSGarrett D'Amore break; 630*95c635efSGarrett D'Amore case (MAN_BODY): 631*95c635efSGarrett D'Amore term_newln(p); 632*95c635efSGarrett D'Amore break; 633*95c635efSGarrett D'Amore default: 634*95c635efSGarrett D'Amore break; 635*95c635efSGarrett D'Amore } 636*95c635efSGarrett D'Amore } 637*95c635efSGarrett D'Amore 638*95c635efSGarrett D'Amore 639*95c635efSGarrett D'Amore /* ARGSUSED */ 640*95c635efSGarrett D'Amore static int 641*95c635efSGarrett D'Amore pre_TP(DECL_ARGS) 642*95c635efSGarrett D'Amore { 643*95c635efSGarrett D'Amore const struct man_node *nn; 644*95c635efSGarrett D'Amore size_t len; 645*95c635efSGarrett D'Amore int savelit, ival; 646*95c635efSGarrett D'Amore 647*95c635efSGarrett D'Amore switch (n->type) { 648*95c635efSGarrett D'Amore case (MAN_HEAD): 649*95c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK; 650*95c635efSGarrett D'Amore break; 651*95c635efSGarrett D'Amore case (MAN_BODY): 652*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 653*95c635efSGarrett D'Amore break; 654*95c635efSGarrett D'Amore case (MAN_BLOCK): 655*95c635efSGarrett D'Amore print_bvspace(p, n); 656*95c635efSGarrett D'Amore /* FALLTHROUGH */ 657*95c635efSGarrett D'Amore default: 658*95c635efSGarrett D'Amore return(1); 659*95c635efSGarrett D'Amore } 660*95c635efSGarrett D'Amore 661*95c635efSGarrett D'Amore len = (size_t)mt->lmargin[mt->lmargincur]; 662*95c635efSGarrett D'Amore ival = -1; 663*95c635efSGarrett D'Amore 664*95c635efSGarrett D'Amore /* Calculate offset. */ 665*95c635efSGarrett D'Amore 666*95c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 667*95c635efSGarrett D'Amore if (nn->string && nn->parent->line == nn->line) 668*95c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 669*95c635efSGarrett D'Amore len = (size_t)ival; 670*95c635efSGarrett D'Amore 671*95c635efSGarrett D'Amore switch (n->type) { 672*95c635efSGarrett D'Amore case (MAN_HEAD): 673*95c635efSGarrett D'Amore /* Handle zero-length properly. */ 674*95c635efSGarrett D'Amore if (0 == len) 675*95c635efSGarrett D'Amore len = term_len(p, 1); 676*95c635efSGarrett D'Amore 677*95c635efSGarrett D'Amore p->offset = mt->offset; 678*95c635efSGarrett D'Amore p->rmargin = mt->offset + len; 679*95c635efSGarrett D'Amore 680*95c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 681*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 682*95c635efSGarrett D'Amore 683*95c635efSGarrett D'Amore /* Don't print same-line elements. */ 684*95c635efSGarrett D'Amore for (nn = n->child; nn; nn = nn->next) 685*95c635efSGarrett D'Amore if (nn->line > n->line) 686*95c635efSGarrett D'Amore print_man_node(p, mt, nn, m); 687*95c635efSGarrett D'Amore 688*95c635efSGarrett D'Amore if (savelit) 689*95c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 690*95c635efSGarrett D'Amore if (ival >= 0) 691*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 692*95c635efSGarrett D'Amore 693*95c635efSGarrett D'Amore return(0); 694*95c635efSGarrett D'Amore case (MAN_BODY): 695*95c635efSGarrett D'Amore p->offset = mt->offset + len; 696*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 697*95c635efSGarrett D'Amore break; 698*95c635efSGarrett D'Amore default: 699*95c635efSGarrett D'Amore break; 700*95c635efSGarrett D'Amore } 701*95c635efSGarrett D'Amore 702*95c635efSGarrett D'Amore return(1); 703*95c635efSGarrett D'Amore } 704*95c635efSGarrett D'Amore 705*95c635efSGarrett D'Amore 706*95c635efSGarrett D'Amore /* ARGSUSED */ 707*95c635efSGarrett D'Amore static void 708*95c635efSGarrett D'Amore post_TP(DECL_ARGS) 709*95c635efSGarrett D'Amore { 710*95c635efSGarrett D'Amore 711*95c635efSGarrett D'Amore switch (n->type) { 712*95c635efSGarrett D'Amore case (MAN_HEAD): 713*95c635efSGarrett D'Amore term_flushln(p); 714*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 715*95c635efSGarrett D'Amore p->flags &= ~TERMP_TWOSPACE; 716*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 717*95c635efSGarrett D'Amore break; 718*95c635efSGarrett D'Amore case (MAN_BODY): 719*95c635efSGarrett D'Amore term_newln(p); 720*95c635efSGarrett D'Amore break; 721*95c635efSGarrett D'Amore default: 722*95c635efSGarrett D'Amore break; 723*95c635efSGarrett D'Amore } 724*95c635efSGarrett D'Amore } 725*95c635efSGarrett D'Amore 726*95c635efSGarrett D'Amore 727*95c635efSGarrett D'Amore /* ARGSUSED */ 728*95c635efSGarrett D'Amore static int 729*95c635efSGarrett D'Amore pre_SS(DECL_ARGS) 730*95c635efSGarrett D'Amore { 731*95c635efSGarrett D'Amore 732*95c635efSGarrett D'Amore switch (n->type) { 733*95c635efSGarrett D'Amore case (MAN_BLOCK): 734*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 735*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 736*95c635efSGarrett D'Amore mt->offset = term_len(p, p->defindent); 737*95c635efSGarrett D'Amore /* If following a prior empty `SS', no vspace. */ 738*95c635efSGarrett D'Amore if (n->prev && MAN_SS == n->prev->tok) 739*95c635efSGarrett D'Amore if (NULL == n->prev->body->child) 740*95c635efSGarrett D'Amore break; 741*95c635efSGarrett D'Amore if (NULL == n->prev) 742*95c635efSGarrett D'Amore break; 743*95c635efSGarrett D'Amore term_vspace(p); 744*95c635efSGarrett D'Amore break; 745*95c635efSGarrett D'Amore case (MAN_HEAD): 746*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 747*95c635efSGarrett D'Amore p->offset = term_len(p, p->defindent/2); 748*95c635efSGarrett D'Amore break; 749*95c635efSGarrett D'Amore case (MAN_BODY): 750*95c635efSGarrett D'Amore p->offset = mt->offset; 751*95c635efSGarrett D'Amore break; 752*95c635efSGarrett D'Amore default: 753*95c635efSGarrett D'Amore break; 754*95c635efSGarrett D'Amore } 755*95c635efSGarrett D'Amore 756*95c635efSGarrett D'Amore return(1); 757*95c635efSGarrett D'Amore } 758*95c635efSGarrett D'Amore 759*95c635efSGarrett D'Amore 760*95c635efSGarrett D'Amore /* ARGSUSED */ 761*95c635efSGarrett D'Amore static void 762*95c635efSGarrett D'Amore post_SS(DECL_ARGS) 763*95c635efSGarrett D'Amore { 764*95c635efSGarrett D'Amore 765*95c635efSGarrett D'Amore switch (n->type) { 766*95c635efSGarrett D'Amore case (MAN_HEAD): 767*95c635efSGarrett D'Amore term_newln(p); 768*95c635efSGarrett D'Amore break; 769*95c635efSGarrett D'Amore case (MAN_BODY): 770*95c635efSGarrett D'Amore term_newln(p); 771*95c635efSGarrett D'Amore break; 772*95c635efSGarrett D'Amore default: 773*95c635efSGarrett D'Amore break; 774*95c635efSGarrett D'Amore } 775*95c635efSGarrett D'Amore } 776*95c635efSGarrett D'Amore 777*95c635efSGarrett D'Amore 778*95c635efSGarrett D'Amore /* ARGSUSED */ 779*95c635efSGarrett D'Amore static int 780*95c635efSGarrett D'Amore pre_SH(DECL_ARGS) 781*95c635efSGarrett D'Amore { 782*95c635efSGarrett D'Amore 783*95c635efSGarrett D'Amore switch (n->type) { 784*95c635efSGarrett D'Amore case (MAN_BLOCK): 785*95c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 786*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 787*95c635efSGarrett D'Amore mt->offset = term_len(p, p->defindent); 788*95c635efSGarrett D'Amore /* If following a prior empty `SH', no vspace. */ 789*95c635efSGarrett D'Amore if (n->prev && MAN_SH == n->prev->tok) 790*95c635efSGarrett D'Amore if (NULL == n->prev->body->child) 791*95c635efSGarrett D'Amore break; 792*95c635efSGarrett D'Amore /* If the first macro, no vspae. */ 793*95c635efSGarrett D'Amore if (NULL == n->prev) 794*95c635efSGarrett D'Amore break; 795*95c635efSGarrett D'Amore term_vspace(p); 796*95c635efSGarrett D'Amore break; 797*95c635efSGarrett D'Amore case (MAN_HEAD): 798*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 799*95c635efSGarrett D'Amore p->offset = 0; 800*95c635efSGarrett D'Amore break; 801*95c635efSGarrett D'Amore case (MAN_BODY): 802*95c635efSGarrett D'Amore p->offset = mt->offset; 803*95c635efSGarrett D'Amore break; 804*95c635efSGarrett D'Amore default: 805*95c635efSGarrett D'Amore break; 806*95c635efSGarrett D'Amore } 807*95c635efSGarrett D'Amore 808*95c635efSGarrett D'Amore return(1); 809*95c635efSGarrett D'Amore } 810*95c635efSGarrett D'Amore 811*95c635efSGarrett D'Amore 812*95c635efSGarrett D'Amore /* ARGSUSED */ 813*95c635efSGarrett D'Amore static void 814*95c635efSGarrett D'Amore post_SH(DECL_ARGS) 815*95c635efSGarrett D'Amore { 816*95c635efSGarrett D'Amore 817*95c635efSGarrett D'Amore switch (n->type) { 818*95c635efSGarrett D'Amore case (MAN_HEAD): 819*95c635efSGarrett D'Amore term_newln(p); 820*95c635efSGarrett D'Amore break; 821*95c635efSGarrett D'Amore case (MAN_BODY): 822*95c635efSGarrett D'Amore term_newln(p); 823*95c635efSGarrett D'Amore break; 824*95c635efSGarrett D'Amore default: 825*95c635efSGarrett D'Amore break; 826*95c635efSGarrett D'Amore } 827*95c635efSGarrett D'Amore } 828*95c635efSGarrett D'Amore 829*95c635efSGarrett D'Amore /* ARGSUSED */ 830*95c635efSGarrett D'Amore static int 831*95c635efSGarrett D'Amore pre_RS(DECL_ARGS) 832*95c635efSGarrett D'Amore { 833*95c635efSGarrett D'Amore int ival; 834*95c635efSGarrett D'Amore size_t sz; 835*95c635efSGarrett D'Amore 836*95c635efSGarrett D'Amore switch (n->type) { 837*95c635efSGarrett D'Amore case (MAN_BLOCK): 838*95c635efSGarrett D'Amore term_newln(p); 839*95c635efSGarrett D'Amore return(1); 840*95c635efSGarrett D'Amore case (MAN_HEAD): 841*95c635efSGarrett D'Amore return(0); 842*95c635efSGarrett D'Amore default: 843*95c635efSGarrett D'Amore break; 844*95c635efSGarrett D'Amore } 845*95c635efSGarrett D'Amore 846*95c635efSGarrett D'Amore sz = term_len(p, p->defindent); 847*95c635efSGarrett D'Amore 848*95c635efSGarrett D'Amore if (NULL != (n = n->parent->head->child)) 849*95c635efSGarrett D'Amore if ((ival = a2width(p, n->string)) >= 0) 850*95c635efSGarrett D'Amore sz = (size_t)ival; 851*95c635efSGarrett D'Amore 852*95c635efSGarrett D'Amore mt->offset += sz; 853*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 854*95c635efSGarrett D'Amore p->offset = mt->offset < p->rmargin ? mt->offset : p->rmargin; 855*95c635efSGarrett D'Amore 856*95c635efSGarrett D'Amore if (++mt->lmarginsz < MAXMARGINS) 857*95c635efSGarrett D'Amore mt->lmargincur = mt->lmarginsz; 858*95c635efSGarrett D'Amore 859*95c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = mt->lmargin[mt->lmargincur - 1]; 860*95c635efSGarrett D'Amore return(1); 861*95c635efSGarrett D'Amore } 862*95c635efSGarrett D'Amore 863*95c635efSGarrett D'Amore /* ARGSUSED */ 864*95c635efSGarrett D'Amore static void 865*95c635efSGarrett D'Amore post_RS(DECL_ARGS) 866*95c635efSGarrett D'Amore { 867*95c635efSGarrett D'Amore int ival; 868*95c635efSGarrett D'Amore size_t sz; 869*95c635efSGarrett D'Amore 870*95c635efSGarrett D'Amore switch (n->type) { 871*95c635efSGarrett D'Amore case (MAN_BLOCK): 872*95c635efSGarrett D'Amore return; 873*95c635efSGarrett D'Amore case (MAN_HEAD): 874*95c635efSGarrett D'Amore return; 875*95c635efSGarrett D'Amore default: 876*95c635efSGarrett D'Amore term_newln(p); 877*95c635efSGarrett D'Amore break; 878*95c635efSGarrett D'Amore } 879*95c635efSGarrett D'Amore 880*95c635efSGarrett D'Amore sz = term_len(p, p->defindent); 881*95c635efSGarrett D'Amore 882*95c635efSGarrett D'Amore if (NULL != (n = n->parent->head->child)) 883*95c635efSGarrett D'Amore if ((ival = a2width(p, n->string)) >= 0) 884*95c635efSGarrett D'Amore sz = (size_t)ival; 885*95c635efSGarrett D'Amore 886*95c635efSGarrett D'Amore mt->offset = mt->offset < sz ? 0 : mt->offset - sz; 887*95c635efSGarrett D'Amore p->offset = mt->offset; 888*95c635efSGarrett D'Amore 889*95c635efSGarrett D'Amore if (--mt->lmarginsz < MAXMARGINS) 890*95c635efSGarrett D'Amore mt->lmargincur = mt->lmarginsz; 891*95c635efSGarrett D'Amore } 892*95c635efSGarrett D'Amore 893*95c635efSGarrett D'Amore static void 894*95c635efSGarrett D'Amore print_man_node(DECL_ARGS) 895*95c635efSGarrett D'Amore { 896*95c635efSGarrett D'Amore size_t rm, rmax; 897*95c635efSGarrett D'Amore int c; 898*95c635efSGarrett D'Amore 899*95c635efSGarrett D'Amore switch (n->type) { 900*95c635efSGarrett D'Amore case(MAN_TEXT): 901*95c635efSGarrett D'Amore /* 902*95c635efSGarrett D'Amore * If we have a blank line, output a vertical space. 903*95c635efSGarrett D'Amore * If we have a space as the first character, break 904*95c635efSGarrett D'Amore * before printing the line's data. 905*95c635efSGarrett D'Amore */ 906*95c635efSGarrett D'Amore if ('\0' == *n->string) { 907*95c635efSGarrett D'Amore term_vspace(p); 908*95c635efSGarrett D'Amore return; 909*95c635efSGarrett D'Amore } else if (' ' == *n->string && MAN_LINE & n->flags) 910*95c635efSGarrett D'Amore term_newln(p); 911*95c635efSGarrett D'Amore 912*95c635efSGarrett D'Amore term_word(p, n->string); 913*95c635efSGarrett D'Amore 914*95c635efSGarrett D'Amore /* 915*95c635efSGarrett D'Amore * If we're in a literal context, make sure that words 916*95c635efSGarrett D'Amore * togehter on the same line stay together. This is a 917*95c635efSGarrett D'Amore * POST-printing call, so we check the NEXT word. Since 918*95c635efSGarrett D'Amore * -man doesn't have nested macros, we don't need to be 919*95c635efSGarrett D'Amore * more specific than this. 920*95c635efSGarrett D'Amore */ 921*95c635efSGarrett D'Amore if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) && 922*95c635efSGarrett D'Amore (NULL == n->next || 923*95c635efSGarrett D'Amore n->next->line > n->line)) { 924*95c635efSGarrett D'Amore rm = p->rmargin; 925*95c635efSGarrett D'Amore rmax = p->maxrmargin; 926*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin = TERM_MAXMARGIN; 927*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 928*95c635efSGarrett D'Amore term_flushln(p); 929*95c635efSGarrett D'Amore p->rmargin = rm; 930*95c635efSGarrett D'Amore p->maxrmargin = rmax; 931*95c635efSGarrett D'Amore } 932*95c635efSGarrett D'Amore 933*95c635efSGarrett D'Amore if (MAN_EOS & n->flags) 934*95c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE; 935*95c635efSGarrett D'Amore return; 936*95c635efSGarrett D'Amore case (MAN_EQN): 937*95c635efSGarrett D'Amore term_eqn(p, n->eqn); 938*95c635efSGarrett D'Amore return; 939*95c635efSGarrett D'Amore case (MAN_TBL): 940*95c635efSGarrett D'Amore /* 941*95c635efSGarrett D'Amore * Tables are preceded by a newline. Then process a 942*95c635efSGarrett D'Amore * table line, which will cause line termination, 943*95c635efSGarrett D'Amore */ 944*95c635efSGarrett D'Amore if (TBL_SPAN_FIRST & n->span->flags) 945*95c635efSGarrett D'Amore term_newln(p); 946*95c635efSGarrett D'Amore term_tbl(p, n->span); 947*95c635efSGarrett D'Amore return; 948*95c635efSGarrett D'Amore default: 949*95c635efSGarrett D'Amore break; 950*95c635efSGarrett D'Amore } 951*95c635efSGarrett D'Amore 952*95c635efSGarrett D'Amore if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) 953*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 954*95c635efSGarrett D'Amore 955*95c635efSGarrett D'Amore c = 1; 956*95c635efSGarrett D'Amore if (termacts[n->tok].pre) 957*95c635efSGarrett D'Amore c = (*termacts[n->tok].pre)(p, mt, n, m); 958*95c635efSGarrett D'Amore 959*95c635efSGarrett D'Amore if (c && n->child) 960*95c635efSGarrett D'Amore print_man_nodelist(p, mt, n->child, m); 961*95c635efSGarrett D'Amore 962*95c635efSGarrett D'Amore if (termacts[n->tok].post) 963*95c635efSGarrett D'Amore (*termacts[n->tok].post)(p, mt, n, m); 964*95c635efSGarrett D'Amore if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) 965*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 966*95c635efSGarrett D'Amore 967*95c635efSGarrett D'Amore if (MAN_EOS & n->flags) 968*95c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE; 969*95c635efSGarrett D'Amore } 970*95c635efSGarrett D'Amore 971*95c635efSGarrett D'Amore 972*95c635efSGarrett D'Amore static void 973*95c635efSGarrett D'Amore print_man_nodelist(DECL_ARGS) 974*95c635efSGarrett D'Amore { 975*95c635efSGarrett D'Amore 976*95c635efSGarrett D'Amore print_man_node(p, mt, n, m); 977*95c635efSGarrett D'Amore if ( ! n->next) 978*95c635efSGarrett D'Amore return; 979*95c635efSGarrett D'Amore print_man_nodelist(p, mt, n->next, m); 980*95c635efSGarrett D'Amore } 981*95c635efSGarrett D'Amore 982*95c635efSGarrett D'Amore 983*95c635efSGarrett D'Amore static void 984*95c635efSGarrett D'Amore print_man_foot(struct termp *p, const void *arg) 985*95c635efSGarrett D'Amore { 986*95c635efSGarrett D'Amore char title[BUFSIZ]; 987*95c635efSGarrett D'Amore size_t datelen; 988*95c635efSGarrett D'Amore const struct man_meta *meta; 989*95c635efSGarrett D'Amore 990*95c635efSGarrett D'Amore meta = (const struct man_meta *)arg; 991*95c635efSGarrett D'Amore assert(meta->title); 992*95c635efSGarrett D'Amore assert(meta->msec); 993*95c635efSGarrett D'Amore assert(meta->date); 994*95c635efSGarrett D'Amore 995*95c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 996*95c635efSGarrett D'Amore 997*95c635efSGarrett D'Amore term_vspace(p); 998*95c635efSGarrett D'Amore 999*95c635efSGarrett D'Amore /* 1000*95c635efSGarrett D'Amore * Temporary, undocumented option to imitate mdoc(7) output. 1001*95c635efSGarrett D'Amore * In the bottom right corner, use the source instead of 1002*95c635efSGarrett D'Amore * the title. 1003*95c635efSGarrett D'Amore */ 1004*95c635efSGarrett D'Amore 1005*95c635efSGarrett D'Amore if ( ! p->mdocstyle) { 1006*95c635efSGarrett D'Amore term_vspace(p); 1007*95c635efSGarrett D'Amore term_vspace(p); 1008*95c635efSGarrett D'Amore snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec); 1009*95c635efSGarrett D'Amore } else if (meta->source) { 1010*95c635efSGarrett D'Amore strlcpy(title, meta->source, BUFSIZ); 1011*95c635efSGarrett D'Amore } else { 1012*95c635efSGarrett D'Amore title[0] = '\0'; 1013*95c635efSGarrett D'Amore } 1014*95c635efSGarrett D'Amore datelen = term_strlen(p, meta->date); 1015*95c635efSGarrett D'Amore 1016*95c635efSGarrett D'Amore /* Bottom left corner: manual source. */ 1017*95c635efSGarrett D'Amore 1018*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; 1019*95c635efSGarrett D'Amore p->offset = 0; 1020*95c635efSGarrett D'Amore p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2; 1021*95c635efSGarrett D'Amore 1022*95c635efSGarrett D'Amore if (meta->source) 1023*95c635efSGarrett D'Amore term_word(p, meta->source); 1024*95c635efSGarrett D'Amore term_flushln(p); 1025*95c635efSGarrett D'Amore 1026*95c635efSGarrett D'Amore /* At the bottom in the middle: manual date. */ 1027*95c635efSGarrett D'Amore 1028*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 1029*95c635efSGarrett D'Amore p->offset = p->rmargin; 1030*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin - term_strlen(p, title); 1031*95c635efSGarrett D'Amore if (p->offset + datelen >= p->rmargin) 1032*95c635efSGarrett D'Amore p->rmargin = p->offset + datelen; 1033*95c635efSGarrett D'Amore 1034*95c635efSGarrett D'Amore term_word(p, meta->date); 1035*95c635efSGarrett D'Amore term_flushln(p); 1036*95c635efSGarrett D'Amore 1037*95c635efSGarrett D'Amore /* Bottom right corner: manual title and section. */ 1038*95c635efSGarrett D'Amore 1039*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 1040*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 1041*95c635efSGarrett D'Amore p->offset = p->rmargin; 1042*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 1043*95c635efSGarrett D'Amore 1044*95c635efSGarrett D'Amore term_word(p, title); 1045*95c635efSGarrett D'Amore term_flushln(p); 1046*95c635efSGarrett D'Amore } 1047*95c635efSGarrett D'Amore 1048*95c635efSGarrett D'Amore 1049*95c635efSGarrett D'Amore static void 1050*95c635efSGarrett D'Amore print_man_head(struct termp *p, const void *arg) 1051*95c635efSGarrett D'Amore { 1052*95c635efSGarrett D'Amore char buf[BUFSIZ], title[BUFSIZ]; 1053*95c635efSGarrett D'Amore size_t buflen, titlen; 1054*95c635efSGarrett D'Amore const struct man_meta *m; 1055*95c635efSGarrett D'Amore 1056*95c635efSGarrett D'Amore m = (const struct man_meta *)arg; 1057*95c635efSGarrett D'Amore assert(m->title); 1058*95c635efSGarrett D'Amore assert(m->msec); 1059*95c635efSGarrett D'Amore 1060*95c635efSGarrett D'Amore if (m->vol) 1061*95c635efSGarrett D'Amore strlcpy(buf, m->vol, BUFSIZ); 1062*95c635efSGarrett D'Amore else 1063*95c635efSGarrett D'Amore buf[0] = '\0'; 1064*95c635efSGarrett D'Amore buflen = term_strlen(p, buf); 1065*95c635efSGarrett D'Amore 1066*95c635efSGarrett D'Amore /* Top left corner: manual title and section. */ 1067*95c635efSGarrett D'Amore 1068*95c635efSGarrett D'Amore snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec); 1069*95c635efSGarrett D'Amore titlen = term_strlen(p, title); 1070*95c635efSGarrett D'Amore 1071*95c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; 1072*95c635efSGarrett D'Amore p->offset = 0; 1073*95c635efSGarrett D'Amore p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ? 1074*95c635efSGarrett D'Amore (p->maxrmargin - 1075*95c635efSGarrett D'Amore term_strlen(p, buf) + term_len(p, 1)) / 2 : 1076*95c635efSGarrett D'Amore p->maxrmargin - buflen; 1077*95c635efSGarrett D'Amore 1078*95c635efSGarrett D'Amore term_word(p, title); 1079*95c635efSGarrett D'Amore term_flushln(p); 1080*95c635efSGarrett D'Amore 1081*95c635efSGarrett D'Amore /* At the top in the middle: manual volume. */ 1082*95c635efSGarrett D'Amore 1083*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 1084*95c635efSGarrett D'Amore p->offset = p->rmargin; 1085*95c635efSGarrett D'Amore p->rmargin = p->offset + buflen + titlen < p->maxrmargin ? 1086*95c635efSGarrett D'Amore p->maxrmargin - titlen : p->maxrmargin; 1087*95c635efSGarrett D'Amore 1088*95c635efSGarrett D'Amore term_word(p, buf); 1089*95c635efSGarrett D'Amore term_flushln(p); 1090*95c635efSGarrett D'Amore 1091*95c635efSGarrett D'Amore /* Top right corner: title and section, again. */ 1092*95c635efSGarrett D'Amore 1093*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 1094*95c635efSGarrett D'Amore if (p->rmargin + titlen <= p->maxrmargin) { 1095*95c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 1096*95c635efSGarrett D'Amore p->offset = p->rmargin; 1097*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 1098*95c635efSGarrett D'Amore term_word(p, title); 1099*95c635efSGarrett D'Amore term_flushln(p); 1100*95c635efSGarrett D'Amore } 1101*95c635efSGarrett D'Amore 1102*95c635efSGarrett D'Amore p->flags &= ~TERMP_NOSPACE; 1103*95c635efSGarrett D'Amore p->offset = 0; 1104*95c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 1105*95c635efSGarrett D'Amore 1106*95c635efSGarrett D'Amore /* 1107*95c635efSGarrett D'Amore * Groff prints three blank lines before the content. 1108*95c635efSGarrett D'Amore * Do the same, except in the temporary, undocumented 1109*95c635efSGarrett D'Amore * mode imitating mdoc(7) output. 1110*95c635efSGarrett D'Amore */ 1111*95c635efSGarrett D'Amore 1112*95c635efSGarrett D'Amore term_vspace(p); 1113*95c635efSGarrett D'Amore if ( ! p->mdocstyle) { 1114*95c635efSGarrett D'Amore term_vspace(p); 1115*95c635efSGarrett D'Amore term_vspace(p); 1116*95c635efSGarrett D'Amore } 1117*95c635efSGarrett D'Amore } 1118