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