1*698f87a4SGarrett D'Amore /* $Id: man_term.c,v 1.139 2013/12/22 23:34:13 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 3*698f87a4SGarrett D'Amore * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> 4*698f87a4SGarrett D'Amore * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org> 595c635efSGarrett D'Amore * 695c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 795c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 895c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 995c635efSGarrett D'Amore * 1095c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1195c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1295c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1395c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1495c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1595c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1695c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1795c635efSGarrett D'Amore */ 1895c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 1995c635efSGarrett D'Amore #include "config.h" 2095c635efSGarrett D'Amore #endif 2195c635efSGarrett D'Amore 2295c635efSGarrett D'Amore #include <sys/types.h> 2395c635efSGarrett D'Amore 2495c635efSGarrett D'Amore #include <assert.h> 2595c635efSGarrett D'Amore #include <ctype.h> 2695c635efSGarrett D'Amore #include <stdio.h> 2795c635efSGarrett D'Amore #include <stdlib.h> 2895c635efSGarrett D'Amore #include <string.h> 2995c635efSGarrett D'Amore 3095c635efSGarrett D'Amore #include "mandoc.h" 3195c635efSGarrett D'Amore #include "out.h" 3295c635efSGarrett D'Amore #include "man.h" 3395c635efSGarrett D'Amore #include "term.h" 3495c635efSGarrett D'Amore #include "main.h" 3595c635efSGarrett D'Amore 3695c635efSGarrett D'Amore #define MAXMARGINS 64 /* maximum number of indented scopes */ 3795c635efSGarrett D'Amore 3895c635efSGarrett D'Amore struct mtermp { 3995c635efSGarrett D'Amore int fl; 4095c635efSGarrett D'Amore #define MANT_LITERAL (1 << 0) 4195c635efSGarrett D'Amore size_t lmargin[MAXMARGINS]; /* margins (incl. visible page) */ 4295c635efSGarrett D'Amore int lmargincur; /* index of current margin */ 4395c635efSGarrett D'Amore int lmarginsz; /* actual number of nested margins */ 4495c635efSGarrett D'Amore size_t offset; /* default offset to visible page */ 45*698f87a4SGarrett D'Amore int pardist; /* vert. space before par., unit: [v] */ 4695c635efSGarrett D'Amore }; 4795c635efSGarrett D'Amore 4895c635efSGarrett D'Amore #define DECL_ARGS struct termp *p, \ 4995c635efSGarrett D'Amore struct mtermp *mt, \ 5095c635efSGarrett D'Amore const struct man_node *n, \ 51*698f87a4SGarrett D'Amore const struct man_meta *meta 5295c635efSGarrett D'Amore 5395c635efSGarrett D'Amore struct termact { 5495c635efSGarrett D'Amore int (*pre)(DECL_ARGS); 5595c635efSGarrett D'Amore void (*post)(DECL_ARGS); 5695c635efSGarrett D'Amore int flags; 5795c635efSGarrett D'Amore #define MAN_NOTEXT (1 << 0) /* Never has text children. */ 5895c635efSGarrett D'Amore }; 5995c635efSGarrett D'Amore 6095c635efSGarrett D'Amore static int a2width(const struct termp *, const char *); 6195c635efSGarrett D'Amore static size_t a2height(const struct termp *, const char *); 6295c635efSGarrett D'Amore 6395c635efSGarrett D'Amore static void print_man_nodelist(DECL_ARGS); 6495c635efSGarrett D'Amore static void print_man_node(DECL_ARGS); 6595c635efSGarrett D'Amore static void print_man_head(struct termp *, const void *); 6695c635efSGarrett D'Amore static void print_man_foot(struct termp *, const void *); 6795c635efSGarrett D'Amore static void print_bvspace(struct termp *, 68*698f87a4SGarrett D'Amore const struct man_node *, int); 6995c635efSGarrett D'Amore 7095c635efSGarrett D'Amore static int pre_B(DECL_ARGS); 7195c635efSGarrett D'Amore static int pre_HP(DECL_ARGS); 7295c635efSGarrett D'Amore static int pre_I(DECL_ARGS); 7395c635efSGarrett D'Amore static int pre_IP(DECL_ARGS); 7495c635efSGarrett D'Amore static int pre_OP(DECL_ARGS); 75*698f87a4SGarrett D'Amore static int pre_PD(DECL_ARGS); 7695c635efSGarrett D'Amore static int pre_PP(DECL_ARGS); 7795c635efSGarrett D'Amore static int pre_RS(DECL_ARGS); 7895c635efSGarrett D'Amore static int pre_SH(DECL_ARGS); 7995c635efSGarrett D'Amore static int pre_SS(DECL_ARGS); 8095c635efSGarrett D'Amore static int pre_TP(DECL_ARGS); 81*698f87a4SGarrett D'Amore static int pre_UR(DECL_ARGS); 8295c635efSGarrett D'Amore static int pre_alternate(DECL_ARGS); 8395c635efSGarrett D'Amore static int pre_ft(DECL_ARGS); 8495c635efSGarrett D'Amore static int pre_ign(DECL_ARGS); 8595c635efSGarrett D'Amore static int pre_in(DECL_ARGS); 8695c635efSGarrett D'Amore static int pre_literal(DECL_ARGS); 8795c635efSGarrett D'Amore static int pre_sp(DECL_ARGS); 8895c635efSGarrett D'Amore 8995c635efSGarrett D'Amore static void post_IP(DECL_ARGS); 9095c635efSGarrett D'Amore static void post_HP(DECL_ARGS); 9195c635efSGarrett D'Amore static void post_RS(DECL_ARGS); 9295c635efSGarrett D'Amore static void post_SH(DECL_ARGS); 9395c635efSGarrett D'Amore static void post_SS(DECL_ARGS); 9495c635efSGarrett D'Amore static void post_TP(DECL_ARGS); 95*698f87a4SGarrett D'Amore static void post_UR(DECL_ARGS); 9695c635efSGarrett D'Amore 9795c635efSGarrett D'Amore static const struct termact termacts[MAN_MAX] = { 9895c635efSGarrett D'Amore { pre_sp, NULL, MAN_NOTEXT }, /* br */ 9995c635efSGarrett D'Amore { NULL, NULL, 0 }, /* TH */ 10095c635efSGarrett D'Amore { pre_SH, post_SH, 0 }, /* SH */ 10195c635efSGarrett D'Amore { pre_SS, post_SS, 0 }, /* SS */ 10295c635efSGarrett D'Amore { pre_TP, post_TP, 0 }, /* TP */ 10395c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* LP */ 10495c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* PP */ 10595c635efSGarrett D'Amore { pre_PP, NULL, 0 }, /* P */ 10695c635efSGarrett D'Amore { pre_IP, post_IP, 0 }, /* IP */ 10795c635efSGarrett D'Amore { pre_HP, post_HP, 0 }, /* HP */ 10895c635efSGarrett D'Amore { NULL, NULL, 0 }, /* SM */ 10995c635efSGarrett D'Amore { pre_B, NULL, 0 }, /* SB */ 11095c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* BI */ 11195c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* IB */ 11295c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* BR */ 11395c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* RB */ 11495c635efSGarrett D'Amore { NULL, NULL, 0 }, /* R */ 11595c635efSGarrett D'Amore { pre_B, NULL, 0 }, /* B */ 11695c635efSGarrett D'Amore { pre_I, NULL, 0 }, /* I */ 11795c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* IR */ 11895c635efSGarrett D'Amore { pre_alternate, NULL, 0 }, /* RI */ 11995c635efSGarrett D'Amore { pre_ign, NULL, MAN_NOTEXT }, /* na */ 12095c635efSGarrett D'Amore { pre_sp, NULL, MAN_NOTEXT }, /* sp */ 12195c635efSGarrett D'Amore { pre_literal, NULL, 0 }, /* nf */ 12295c635efSGarrett D'Amore { pre_literal, NULL, 0 }, /* fi */ 12395c635efSGarrett D'Amore { NULL, NULL, 0 }, /* RE */ 12495c635efSGarrett D'Amore { pre_RS, post_RS, 0 }, /* RS */ 12595c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* DT */ 12695c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* UC */ 127*698f87a4SGarrett D'Amore { pre_PD, NULL, MAN_NOTEXT }, /* PD */ 12895c635efSGarrett D'Amore { pre_ign, NULL, 0 }, /* AT */ 12995c635efSGarrett D'Amore { pre_in, NULL, MAN_NOTEXT }, /* in */ 13095c635efSGarrett D'Amore { pre_ft, NULL, MAN_NOTEXT }, /* ft */ 13195c635efSGarrett D'Amore { pre_OP, NULL, 0 }, /* OP */ 132*698f87a4SGarrett D'Amore { pre_literal, NULL, 0 }, /* EX */ 133*698f87a4SGarrett D'Amore { pre_literal, NULL, 0 }, /* EE */ 134*698f87a4SGarrett D'Amore { pre_UR, post_UR, 0 }, /* UR */ 135*698f87a4SGarrett D'Amore { NULL, NULL, 0 }, /* UE */ 13695c635efSGarrett D'Amore }; 13795c635efSGarrett D'Amore 13895c635efSGarrett D'Amore 13995c635efSGarrett D'Amore 14095c635efSGarrett D'Amore void 14195c635efSGarrett D'Amore terminal_man(void *arg, const struct man *man) 14295c635efSGarrett D'Amore { 14395c635efSGarrett D'Amore struct termp *p; 14495c635efSGarrett D'Amore const struct man_node *n; 145*698f87a4SGarrett D'Amore const struct man_meta *meta; 14695c635efSGarrett D'Amore struct mtermp mt; 14795c635efSGarrett D'Amore 14895c635efSGarrett D'Amore p = (struct termp *)arg; 14995c635efSGarrett D'Amore 15095c635efSGarrett D'Amore if (0 == p->defindent) 15195c635efSGarrett D'Amore p->defindent = 7; 15295c635efSGarrett D'Amore 15395c635efSGarrett D'Amore p->overstep = 0; 15495c635efSGarrett D'Amore p->maxrmargin = p->defrmargin; 15595c635efSGarrett D'Amore p->tabwidth = term_len(p, 5); 15695c635efSGarrett D'Amore 15795c635efSGarrett D'Amore if (NULL == p->symtab) 15895c635efSGarrett D'Amore p->symtab = mchars_alloc(); 15995c635efSGarrett D'Amore 16095c635efSGarrett D'Amore n = man_node(man); 161*698f87a4SGarrett D'Amore meta = man_meta(man); 16295c635efSGarrett D'Amore 163*698f87a4SGarrett D'Amore term_begin(p, print_man_head, print_man_foot, meta); 16495c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 16595c635efSGarrett D'Amore 16695c635efSGarrett D'Amore memset(&mt, 0, sizeof(struct mtermp)); 16795c635efSGarrett D'Amore 16895c635efSGarrett D'Amore mt.lmargin[mt.lmargincur] = term_len(p, p->defindent); 16995c635efSGarrett D'Amore mt.offset = term_len(p, p->defindent); 170*698f87a4SGarrett D'Amore mt.pardist = 1; 17195c635efSGarrett D'Amore 17295c635efSGarrett D'Amore if (n->child) 173*698f87a4SGarrett D'Amore print_man_nodelist(p, &mt, n->child, meta); 17495c635efSGarrett D'Amore 17595c635efSGarrett D'Amore term_end(p); 17695c635efSGarrett D'Amore } 17795c635efSGarrett D'Amore 17895c635efSGarrett D'Amore 17995c635efSGarrett D'Amore static size_t 18095c635efSGarrett D'Amore a2height(const struct termp *p, const char *cp) 18195c635efSGarrett D'Amore { 18295c635efSGarrett D'Amore struct roffsu su; 18395c635efSGarrett D'Amore 18495c635efSGarrett D'Amore if ( ! a2roffsu(cp, &su, SCALE_VS)) 18595c635efSGarrett D'Amore SCALE_VS_INIT(&su, atoi(cp)); 18695c635efSGarrett D'Amore 18795c635efSGarrett D'Amore return(term_vspan(p, &su)); 18895c635efSGarrett D'Amore } 18995c635efSGarrett D'Amore 19095c635efSGarrett D'Amore 19195c635efSGarrett D'Amore static int 19295c635efSGarrett D'Amore a2width(const struct termp *p, const char *cp) 19395c635efSGarrett D'Amore { 19495c635efSGarrett D'Amore struct roffsu su; 19595c635efSGarrett D'Amore 19695c635efSGarrett D'Amore if ( ! a2roffsu(cp, &su, SCALE_BU)) 19795c635efSGarrett D'Amore return(-1); 19895c635efSGarrett D'Amore 19995c635efSGarrett D'Amore return((int)term_hspan(p, &su)); 20095c635efSGarrett D'Amore } 20195c635efSGarrett D'Amore 20295c635efSGarrett D'Amore /* 20395c635efSGarrett D'Amore * Printing leading vertical space before a block. 20495c635efSGarrett D'Amore * This is used for the paragraph macros. 20595c635efSGarrett D'Amore * The rules are pretty simple, since there's very little nesting going 20695c635efSGarrett D'Amore * on here. Basically, if we're the first within another block (SS/SH), 20795c635efSGarrett D'Amore * then don't emit vertical space. If we are (RS), then do. If not the 20895c635efSGarrett D'Amore * first, print it. 20995c635efSGarrett D'Amore */ 21095c635efSGarrett D'Amore static void 211*698f87a4SGarrett D'Amore print_bvspace(struct termp *p, const struct man_node *n, int pardist) 21295c635efSGarrett D'Amore { 213*698f87a4SGarrett D'Amore int i; 21495c635efSGarrett D'Amore 21595c635efSGarrett D'Amore term_newln(p); 21695c635efSGarrett D'Amore 21795c635efSGarrett D'Amore if (n->body && n->body->child) 21895c635efSGarrett D'Amore if (MAN_TBL == n->body->child->type) 21995c635efSGarrett D'Amore return; 22095c635efSGarrett D'Amore 22195c635efSGarrett D'Amore if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) 22295c635efSGarrett D'Amore if (NULL == n->prev) 22395c635efSGarrett D'Amore return; 22495c635efSGarrett D'Amore 225*698f87a4SGarrett D'Amore for (i = 0; i < pardist; i++) 22695c635efSGarrett D'Amore term_vspace(p); 22795c635efSGarrett D'Amore } 22895c635efSGarrett D'Amore 22995c635efSGarrett D'Amore /* ARGSUSED */ 23095c635efSGarrett D'Amore static int 23195c635efSGarrett D'Amore pre_ign(DECL_ARGS) 23295c635efSGarrett D'Amore { 23395c635efSGarrett D'Amore 23495c635efSGarrett D'Amore return(0); 23595c635efSGarrett D'Amore } 23695c635efSGarrett D'Amore 23795c635efSGarrett D'Amore 23895c635efSGarrett D'Amore /* ARGSUSED */ 23995c635efSGarrett D'Amore static int 24095c635efSGarrett D'Amore pre_I(DECL_ARGS) 24195c635efSGarrett D'Amore { 24295c635efSGarrett D'Amore 24395c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 24495c635efSGarrett D'Amore return(1); 24595c635efSGarrett D'Amore } 24695c635efSGarrett D'Amore 24795c635efSGarrett D'Amore 24895c635efSGarrett D'Amore /* ARGSUSED */ 24995c635efSGarrett D'Amore static int 25095c635efSGarrett D'Amore pre_literal(DECL_ARGS) 25195c635efSGarrett D'Amore { 25295c635efSGarrett D'Amore 25395c635efSGarrett D'Amore term_newln(p); 25495c635efSGarrett D'Amore 255*698f87a4SGarrett D'Amore if (MAN_nf == n->tok || MAN_EX == n->tok) 25695c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 25795c635efSGarrett D'Amore else 25895c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 25995c635efSGarrett D'Amore 26095c635efSGarrett D'Amore /* 26195c635efSGarrett D'Amore * Unlike .IP and .TP, .HP does not have a HEAD. 26295c635efSGarrett D'Amore * So in case a second call to term_flushln() is needed, 26395c635efSGarrett D'Amore * indentation has to be set up explicitly. 26495c635efSGarrett D'Amore */ 26595c635efSGarrett D'Amore if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) { 26695c635efSGarrett D'Amore p->offset = p->rmargin; 26795c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 268*698f87a4SGarrett D'Amore p->trailspace = 0; 269*698f87a4SGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 27095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 27195c635efSGarrett D'Amore } 27295c635efSGarrett D'Amore 27395c635efSGarrett D'Amore return(0); 27495c635efSGarrett D'Amore } 27595c635efSGarrett D'Amore 27695c635efSGarrett D'Amore /* ARGSUSED */ 27795c635efSGarrett D'Amore static int 278*698f87a4SGarrett D'Amore pre_PD(DECL_ARGS) 279*698f87a4SGarrett D'Amore { 280*698f87a4SGarrett D'Amore 281*698f87a4SGarrett D'Amore n = n->child; 282*698f87a4SGarrett D'Amore if (0 == n) { 283*698f87a4SGarrett D'Amore mt->pardist = 1; 284*698f87a4SGarrett D'Amore return(0); 285*698f87a4SGarrett D'Amore } 286*698f87a4SGarrett D'Amore assert(MAN_TEXT == n->type); 287*698f87a4SGarrett D'Amore mt->pardist = atoi(n->string); 288*698f87a4SGarrett D'Amore return(0); 289*698f87a4SGarrett D'Amore } 290*698f87a4SGarrett D'Amore 291*698f87a4SGarrett D'Amore /* ARGSUSED */ 292*698f87a4SGarrett D'Amore static int 29395c635efSGarrett D'Amore pre_alternate(DECL_ARGS) 29495c635efSGarrett D'Amore { 29595c635efSGarrett D'Amore enum termfont font[2]; 29695c635efSGarrett D'Amore const struct man_node *nn; 29795c635efSGarrett D'Amore int savelit, i; 29895c635efSGarrett D'Amore 29995c635efSGarrett D'Amore switch (n->tok) { 30095c635efSGarrett D'Amore case (MAN_RB): 30195c635efSGarrett D'Amore font[0] = TERMFONT_NONE; 30295c635efSGarrett D'Amore font[1] = TERMFONT_BOLD; 30395c635efSGarrett D'Amore break; 30495c635efSGarrett D'Amore case (MAN_RI): 30595c635efSGarrett D'Amore font[0] = TERMFONT_NONE; 30695c635efSGarrett D'Amore font[1] = TERMFONT_UNDER; 30795c635efSGarrett D'Amore break; 30895c635efSGarrett D'Amore case (MAN_BR): 30995c635efSGarrett D'Amore font[0] = TERMFONT_BOLD; 31095c635efSGarrett D'Amore font[1] = TERMFONT_NONE; 31195c635efSGarrett D'Amore break; 31295c635efSGarrett D'Amore case (MAN_BI): 31395c635efSGarrett D'Amore font[0] = TERMFONT_BOLD; 31495c635efSGarrett D'Amore font[1] = TERMFONT_UNDER; 31595c635efSGarrett D'Amore break; 31695c635efSGarrett D'Amore case (MAN_IR): 31795c635efSGarrett D'Amore font[0] = TERMFONT_UNDER; 31895c635efSGarrett D'Amore font[1] = TERMFONT_NONE; 31995c635efSGarrett D'Amore break; 32095c635efSGarrett D'Amore case (MAN_IB): 32195c635efSGarrett D'Amore font[0] = TERMFONT_UNDER; 32295c635efSGarrett D'Amore font[1] = TERMFONT_BOLD; 32395c635efSGarrett D'Amore break; 32495c635efSGarrett D'Amore default: 32595c635efSGarrett D'Amore abort(); 32695c635efSGarrett D'Amore } 32795c635efSGarrett D'Amore 32895c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 32995c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 33095c635efSGarrett D'Amore 33195c635efSGarrett D'Amore for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) { 33295c635efSGarrett D'Amore term_fontrepl(p, font[i]); 33395c635efSGarrett D'Amore if (savelit && NULL == nn->next) 33495c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 335*698f87a4SGarrett D'Amore print_man_node(p, mt, nn, meta); 33695c635efSGarrett D'Amore if (nn->next) 33795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 33895c635efSGarrett D'Amore } 33995c635efSGarrett D'Amore 34095c635efSGarrett D'Amore return(0); 34195c635efSGarrett D'Amore } 34295c635efSGarrett D'Amore 34395c635efSGarrett D'Amore /* ARGSUSED */ 34495c635efSGarrett D'Amore static int 34595c635efSGarrett D'Amore pre_B(DECL_ARGS) 34695c635efSGarrett D'Amore { 34795c635efSGarrett D'Amore 34895c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 34995c635efSGarrett D'Amore return(1); 35095c635efSGarrett D'Amore } 35195c635efSGarrett D'Amore 35295c635efSGarrett D'Amore /* ARGSUSED */ 35395c635efSGarrett D'Amore static int 35495c635efSGarrett D'Amore pre_OP(DECL_ARGS) 35595c635efSGarrett D'Amore { 35695c635efSGarrett D'Amore 35795c635efSGarrett D'Amore term_word(p, "["); 35895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 35995c635efSGarrett D'Amore 36095c635efSGarrett D'Amore if (NULL != (n = n->child)) { 36195c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 36295c635efSGarrett D'Amore term_word(p, n->string); 36395c635efSGarrett D'Amore } 36495c635efSGarrett D'Amore if (NULL != n && NULL != n->next) { 36595c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 36695c635efSGarrett D'Amore term_word(p, n->next->string); 36795c635efSGarrett D'Amore } 36895c635efSGarrett D'Amore 36995c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 37095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 37195c635efSGarrett D'Amore term_word(p, "]"); 37295c635efSGarrett D'Amore return(0); 37395c635efSGarrett D'Amore } 37495c635efSGarrett D'Amore 37595c635efSGarrett D'Amore /* ARGSUSED */ 37695c635efSGarrett D'Amore static int 37795c635efSGarrett D'Amore pre_ft(DECL_ARGS) 37895c635efSGarrett D'Amore { 37995c635efSGarrett D'Amore const char *cp; 38095c635efSGarrett D'Amore 38195c635efSGarrett D'Amore if (NULL == n->child) { 38295c635efSGarrett D'Amore term_fontlast(p); 38395c635efSGarrett D'Amore return(0); 38495c635efSGarrett D'Amore } 38595c635efSGarrett D'Amore 38695c635efSGarrett D'Amore cp = n->child->string; 38795c635efSGarrett D'Amore switch (*cp) { 38895c635efSGarrett D'Amore case ('4'): 38995c635efSGarrett D'Amore /* FALLTHROUGH */ 39095c635efSGarrett D'Amore case ('3'): 39195c635efSGarrett D'Amore /* FALLTHROUGH */ 39295c635efSGarrett D'Amore case ('B'): 39395c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 39495c635efSGarrett D'Amore break; 39595c635efSGarrett D'Amore case ('2'): 39695c635efSGarrett D'Amore /* FALLTHROUGH */ 39795c635efSGarrett D'Amore case ('I'): 39895c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_UNDER); 39995c635efSGarrett D'Amore break; 40095c635efSGarrett D'Amore case ('P'): 40195c635efSGarrett D'Amore term_fontlast(p); 40295c635efSGarrett D'Amore break; 40395c635efSGarrett D'Amore case ('1'): 40495c635efSGarrett D'Amore /* FALLTHROUGH */ 40595c635efSGarrett D'Amore case ('C'): 40695c635efSGarrett D'Amore /* FALLTHROUGH */ 40795c635efSGarrett D'Amore case ('R'): 40895c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 40995c635efSGarrett D'Amore break; 41095c635efSGarrett D'Amore default: 41195c635efSGarrett D'Amore break; 41295c635efSGarrett D'Amore } 41395c635efSGarrett D'Amore return(0); 41495c635efSGarrett D'Amore } 41595c635efSGarrett D'Amore 41695c635efSGarrett D'Amore /* ARGSUSED */ 41795c635efSGarrett D'Amore static int 41895c635efSGarrett D'Amore pre_in(DECL_ARGS) 41995c635efSGarrett D'Amore { 42095c635efSGarrett D'Amore int len, less; 42195c635efSGarrett D'Amore size_t v; 42295c635efSGarrett D'Amore const char *cp; 42395c635efSGarrett D'Amore 42495c635efSGarrett D'Amore term_newln(p); 42595c635efSGarrett D'Amore 42695c635efSGarrett D'Amore if (NULL == n->child) { 42795c635efSGarrett D'Amore p->offset = mt->offset; 42895c635efSGarrett D'Amore return(0); 42995c635efSGarrett D'Amore } 43095c635efSGarrett D'Amore 43195c635efSGarrett D'Amore cp = n->child->string; 43295c635efSGarrett D'Amore less = 0; 43395c635efSGarrett D'Amore 43495c635efSGarrett D'Amore if ('-' == *cp) 43595c635efSGarrett D'Amore less = -1; 43695c635efSGarrett D'Amore else if ('+' == *cp) 43795c635efSGarrett D'Amore less = 1; 43895c635efSGarrett D'Amore else 43995c635efSGarrett D'Amore cp--; 44095c635efSGarrett D'Amore 44195c635efSGarrett D'Amore if ((len = a2width(p, ++cp)) < 0) 44295c635efSGarrett D'Amore return(0); 44395c635efSGarrett D'Amore 44495c635efSGarrett D'Amore v = (size_t)len; 44595c635efSGarrett D'Amore 44695c635efSGarrett D'Amore if (less < 0) 44795c635efSGarrett D'Amore p->offset -= p->offset > v ? v : p->offset; 44895c635efSGarrett D'Amore else if (less > 0) 44995c635efSGarrett D'Amore p->offset += v; 45095c635efSGarrett D'Amore else 45195c635efSGarrett D'Amore p->offset = v; 45295c635efSGarrett D'Amore 45395c635efSGarrett D'Amore /* Don't let this creep beyond the right margin. */ 45495c635efSGarrett D'Amore 45595c635efSGarrett D'Amore if (p->offset > p->rmargin) 45695c635efSGarrett D'Amore p->offset = p->rmargin; 45795c635efSGarrett D'Amore 45895c635efSGarrett D'Amore return(0); 45995c635efSGarrett D'Amore } 46095c635efSGarrett D'Amore 46195c635efSGarrett D'Amore 46295c635efSGarrett D'Amore /* ARGSUSED */ 46395c635efSGarrett D'Amore static int 46495c635efSGarrett D'Amore pre_sp(DECL_ARGS) 46595c635efSGarrett D'Amore { 466*698f87a4SGarrett D'Amore char *s; 46795c635efSGarrett D'Amore size_t i, len; 468*698f87a4SGarrett D'Amore int neg; 46995c635efSGarrett D'Amore 47095c635efSGarrett D'Amore if ((NULL == n->prev && n->parent)) { 471*698f87a4SGarrett D'Amore switch (n->parent->tok) { 472*698f87a4SGarrett D'Amore case (MAN_SH): 473*698f87a4SGarrett D'Amore /* FALLTHROUGH */ 474*698f87a4SGarrett D'Amore case (MAN_SS): 475*698f87a4SGarrett D'Amore /* FALLTHROUGH */ 476*698f87a4SGarrett D'Amore case (MAN_PP): 477*698f87a4SGarrett D'Amore /* FALLTHROUGH */ 478*698f87a4SGarrett D'Amore case (MAN_LP): 479*698f87a4SGarrett D'Amore /* FALLTHROUGH */ 480*698f87a4SGarrett D'Amore case (MAN_P): 481*698f87a4SGarrett D'Amore /* FALLTHROUGH */ 48295c635efSGarrett D'Amore return(0); 483*698f87a4SGarrett D'Amore default: 484*698f87a4SGarrett D'Amore break; 485*698f87a4SGarrett D'Amore } 48695c635efSGarrett D'Amore } 48795c635efSGarrett D'Amore 488*698f87a4SGarrett D'Amore neg = 0; 48995c635efSGarrett D'Amore switch (n->tok) { 49095c635efSGarrett D'Amore case (MAN_br): 49195c635efSGarrett D'Amore len = 0; 49295c635efSGarrett D'Amore break; 49395c635efSGarrett D'Amore default: 494*698f87a4SGarrett D'Amore if (NULL == n->child) { 495*698f87a4SGarrett D'Amore len = 1; 496*698f87a4SGarrett D'Amore break; 497*698f87a4SGarrett D'Amore } 498*698f87a4SGarrett D'Amore s = n->child->string; 499*698f87a4SGarrett D'Amore if ('-' == *s) { 500*698f87a4SGarrett D'Amore neg = 1; 501*698f87a4SGarrett D'Amore s++; 502*698f87a4SGarrett D'Amore } 503*698f87a4SGarrett D'Amore len = a2height(p, s); 50495c635efSGarrett D'Amore break; 50595c635efSGarrett D'Amore } 50695c635efSGarrett D'Amore 50795c635efSGarrett D'Amore if (0 == len) 50895c635efSGarrett D'Amore term_newln(p); 509*698f87a4SGarrett D'Amore else if (neg) 510*698f87a4SGarrett D'Amore p->skipvsp += len; 511*698f87a4SGarrett D'Amore else 51295c635efSGarrett D'Amore for (i = 0; i < len; i++) 51395c635efSGarrett D'Amore term_vspace(p); 51495c635efSGarrett D'Amore 51595c635efSGarrett D'Amore return(0); 51695c635efSGarrett D'Amore } 51795c635efSGarrett D'Amore 51895c635efSGarrett D'Amore 51995c635efSGarrett D'Amore /* ARGSUSED */ 52095c635efSGarrett D'Amore static int 52195c635efSGarrett D'Amore pre_HP(DECL_ARGS) 52295c635efSGarrett D'Amore { 52395c635efSGarrett D'Amore size_t len, one; 52495c635efSGarrett D'Amore int ival; 52595c635efSGarrett D'Amore const struct man_node *nn; 52695c635efSGarrett D'Amore 52795c635efSGarrett D'Amore switch (n->type) { 52895c635efSGarrett D'Amore case (MAN_BLOCK): 529*698f87a4SGarrett D'Amore print_bvspace(p, n, mt->pardist); 53095c635efSGarrett D'Amore return(1); 53195c635efSGarrett D'Amore case (MAN_BODY): 53295c635efSGarrett D'Amore break; 53395c635efSGarrett D'Amore default: 53495c635efSGarrett D'Amore return(0); 53595c635efSGarrett D'Amore } 53695c635efSGarrett D'Amore 537*698f87a4SGarrett D'Amore if ( ! (MANT_LITERAL & mt->fl)) { 538*698f87a4SGarrett D'Amore p->flags |= TERMP_NOBREAK; 539*698f87a4SGarrett D'Amore p->trailspace = 2; 540*698f87a4SGarrett D'Amore } 541*698f87a4SGarrett D'Amore 54295c635efSGarrett D'Amore len = mt->lmargin[mt->lmargincur]; 54395c635efSGarrett D'Amore ival = -1; 54495c635efSGarrett D'Amore 54595c635efSGarrett D'Amore /* Calculate offset. */ 54695c635efSGarrett D'Amore 54795c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 54895c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 54995c635efSGarrett D'Amore len = (size_t)ival; 55095c635efSGarrett D'Amore 55195c635efSGarrett D'Amore one = term_len(p, 1); 55295c635efSGarrett D'Amore if (len < one) 55395c635efSGarrett D'Amore len = one; 55495c635efSGarrett D'Amore 55595c635efSGarrett D'Amore p->offset = mt->offset; 55695c635efSGarrett D'Amore p->rmargin = mt->offset + len; 55795c635efSGarrett D'Amore 55895c635efSGarrett D'Amore if (ival >= 0) 55995c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 56095c635efSGarrett D'Amore 56195c635efSGarrett D'Amore return(1); 56295c635efSGarrett D'Amore } 56395c635efSGarrett D'Amore 56495c635efSGarrett D'Amore 56595c635efSGarrett D'Amore /* ARGSUSED */ 56695c635efSGarrett D'Amore static void 56795c635efSGarrett D'Amore post_HP(DECL_ARGS) 56895c635efSGarrett D'Amore { 56995c635efSGarrett D'Amore 57095c635efSGarrett D'Amore switch (n->type) { 57195c635efSGarrett D'Amore case (MAN_BODY): 572*698f87a4SGarrett D'Amore term_newln(p); 57395c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 574*698f87a4SGarrett D'Amore p->trailspace = 0; 57595c635efSGarrett D'Amore p->offset = mt->offset; 57695c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 57795c635efSGarrett D'Amore break; 57895c635efSGarrett D'Amore default: 57995c635efSGarrett D'Amore break; 58095c635efSGarrett D'Amore } 58195c635efSGarrett D'Amore } 58295c635efSGarrett D'Amore 58395c635efSGarrett D'Amore 58495c635efSGarrett D'Amore /* ARGSUSED */ 58595c635efSGarrett D'Amore static int 58695c635efSGarrett D'Amore pre_PP(DECL_ARGS) 58795c635efSGarrett D'Amore { 58895c635efSGarrett D'Amore 58995c635efSGarrett D'Amore switch (n->type) { 59095c635efSGarrett D'Amore case (MAN_BLOCK): 59195c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 592*698f87a4SGarrett D'Amore print_bvspace(p, n, mt->pardist); 59395c635efSGarrett D'Amore break; 59495c635efSGarrett D'Amore default: 59595c635efSGarrett D'Amore p->offset = mt->offset; 59695c635efSGarrett D'Amore break; 59795c635efSGarrett D'Amore } 59895c635efSGarrett D'Amore 59995c635efSGarrett D'Amore return(MAN_HEAD != n->type); 60095c635efSGarrett D'Amore } 60195c635efSGarrett D'Amore 60295c635efSGarrett D'Amore 60395c635efSGarrett D'Amore /* ARGSUSED */ 60495c635efSGarrett D'Amore static int 60595c635efSGarrett D'Amore pre_IP(DECL_ARGS) 60695c635efSGarrett D'Amore { 60795c635efSGarrett D'Amore const struct man_node *nn; 60895c635efSGarrett D'Amore size_t len; 60995c635efSGarrett D'Amore int savelit, ival; 61095c635efSGarrett D'Amore 61195c635efSGarrett D'Amore switch (n->type) { 61295c635efSGarrett D'Amore case (MAN_BODY): 61395c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 61495c635efSGarrett D'Amore break; 61595c635efSGarrett D'Amore case (MAN_HEAD): 61695c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK; 617*698f87a4SGarrett D'Amore p->trailspace = 1; 61895c635efSGarrett D'Amore break; 61995c635efSGarrett D'Amore case (MAN_BLOCK): 620*698f87a4SGarrett D'Amore print_bvspace(p, n, mt->pardist); 62195c635efSGarrett D'Amore /* FALLTHROUGH */ 62295c635efSGarrett D'Amore default: 62395c635efSGarrett D'Amore return(1); 62495c635efSGarrett D'Amore } 62595c635efSGarrett D'Amore 62695c635efSGarrett D'Amore len = mt->lmargin[mt->lmargincur]; 62795c635efSGarrett D'Amore ival = -1; 62895c635efSGarrett D'Amore 62995c635efSGarrett D'Amore /* Calculate the offset from the optional second argument. */ 63095c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 63195c635efSGarrett D'Amore if (NULL != (nn = nn->next)) 63295c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 63395c635efSGarrett D'Amore len = (size_t)ival; 63495c635efSGarrett D'Amore 63595c635efSGarrett D'Amore switch (n->type) { 63695c635efSGarrett D'Amore case (MAN_HEAD): 63795c635efSGarrett D'Amore /* Handle zero-width lengths. */ 63895c635efSGarrett D'Amore if (0 == len) 63995c635efSGarrett D'Amore len = term_len(p, 1); 64095c635efSGarrett D'Amore 64195c635efSGarrett D'Amore p->offset = mt->offset; 64295c635efSGarrett D'Amore p->rmargin = mt->offset + len; 64395c635efSGarrett D'Amore if (ival < 0) 64495c635efSGarrett D'Amore break; 64595c635efSGarrett D'Amore 64695c635efSGarrett D'Amore /* Set the saved left-margin. */ 64795c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 64895c635efSGarrett D'Amore 64995c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 65095c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 65195c635efSGarrett D'Amore 65295c635efSGarrett D'Amore if (n->child) 653*698f87a4SGarrett D'Amore print_man_node(p, mt, n->child, meta); 65495c635efSGarrett D'Amore 65595c635efSGarrett D'Amore if (savelit) 65695c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 65795c635efSGarrett D'Amore 65895c635efSGarrett D'Amore return(0); 65995c635efSGarrett D'Amore case (MAN_BODY): 66095c635efSGarrett D'Amore p->offset = mt->offset + len; 66195c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 66295c635efSGarrett D'Amore break; 66395c635efSGarrett D'Amore default: 66495c635efSGarrett D'Amore break; 66595c635efSGarrett D'Amore } 66695c635efSGarrett D'Amore 66795c635efSGarrett D'Amore return(1); 66895c635efSGarrett D'Amore } 66995c635efSGarrett D'Amore 67095c635efSGarrett D'Amore 67195c635efSGarrett D'Amore /* ARGSUSED */ 67295c635efSGarrett D'Amore static void 67395c635efSGarrett D'Amore post_IP(DECL_ARGS) 67495c635efSGarrett D'Amore { 67595c635efSGarrett D'Amore 67695c635efSGarrett D'Amore switch (n->type) { 67795c635efSGarrett D'Amore case (MAN_HEAD): 67895c635efSGarrett D'Amore term_flushln(p); 67995c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 680*698f87a4SGarrett D'Amore p->trailspace = 0; 68195c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 68295c635efSGarrett D'Amore break; 68395c635efSGarrett D'Amore case (MAN_BODY): 68495c635efSGarrett D'Amore term_newln(p); 685*698f87a4SGarrett D'Amore p->offset = mt->offset; 68695c635efSGarrett D'Amore break; 68795c635efSGarrett D'Amore default: 68895c635efSGarrett D'Amore break; 68995c635efSGarrett D'Amore } 69095c635efSGarrett D'Amore } 69195c635efSGarrett D'Amore 69295c635efSGarrett D'Amore 69395c635efSGarrett D'Amore /* ARGSUSED */ 69495c635efSGarrett D'Amore static int 69595c635efSGarrett D'Amore pre_TP(DECL_ARGS) 69695c635efSGarrett D'Amore { 69795c635efSGarrett D'Amore const struct man_node *nn; 69895c635efSGarrett D'Amore size_t len; 69995c635efSGarrett D'Amore int savelit, ival; 70095c635efSGarrett D'Amore 70195c635efSGarrett D'Amore switch (n->type) { 70295c635efSGarrett D'Amore case (MAN_HEAD): 70395c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK; 704*698f87a4SGarrett D'Amore p->trailspace = 1; 70595c635efSGarrett D'Amore break; 70695c635efSGarrett D'Amore case (MAN_BODY): 70795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 70895c635efSGarrett D'Amore break; 70995c635efSGarrett D'Amore case (MAN_BLOCK): 710*698f87a4SGarrett D'Amore print_bvspace(p, n, mt->pardist); 71195c635efSGarrett D'Amore /* FALLTHROUGH */ 71295c635efSGarrett D'Amore default: 71395c635efSGarrett D'Amore return(1); 71495c635efSGarrett D'Amore } 71595c635efSGarrett D'Amore 71695c635efSGarrett D'Amore len = (size_t)mt->lmargin[mt->lmargincur]; 71795c635efSGarrett D'Amore ival = -1; 71895c635efSGarrett D'Amore 71995c635efSGarrett D'Amore /* Calculate offset. */ 72095c635efSGarrett D'Amore 72195c635efSGarrett D'Amore if (NULL != (nn = n->parent->head->child)) 72295c635efSGarrett D'Amore if (nn->string && nn->parent->line == nn->line) 72395c635efSGarrett D'Amore if ((ival = a2width(p, nn->string)) >= 0) 72495c635efSGarrett D'Amore len = (size_t)ival; 72595c635efSGarrett D'Amore 72695c635efSGarrett D'Amore switch (n->type) { 72795c635efSGarrett D'Amore case (MAN_HEAD): 72895c635efSGarrett D'Amore /* Handle zero-length properly. */ 72995c635efSGarrett D'Amore if (0 == len) 73095c635efSGarrett D'Amore len = term_len(p, 1); 73195c635efSGarrett D'Amore 73295c635efSGarrett D'Amore p->offset = mt->offset; 73395c635efSGarrett D'Amore p->rmargin = mt->offset + len; 73495c635efSGarrett D'Amore 73595c635efSGarrett D'Amore savelit = MANT_LITERAL & mt->fl; 73695c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 73795c635efSGarrett D'Amore 73895c635efSGarrett D'Amore /* Don't print same-line elements. */ 73995c635efSGarrett D'Amore for (nn = n->child; nn; nn = nn->next) 74095c635efSGarrett D'Amore if (nn->line > n->line) 741*698f87a4SGarrett D'Amore print_man_node(p, mt, nn, meta); 74295c635efSGarrett D'Amore 74395c635efSGarrett D'Amore if (savelit) 74495c635efSGarrett D'Amore mt->fl |= MANT_LITERAL; 74595c635efSGarrett D'Amore if (ival >= 0) 74695c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = (size_t)ival; 74795c635efSGarrett D'Amore 74895c635efSGarrett D'Amore return(0); 74995c635efSGarrett D'Amore case (MAN_BODY): 75095c635efSGarrett D'Amore p->offset = mt->offset + len; 75195c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 752*698f87a4SGarrett D'Amore p->trailspace = 0; 753*698f87a4SGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 75495c635efSGarrett D'Amore break; 75595c635efSGarrett D'Amore default: 75695c635efSGarrett D'Amore break; 75795c635efSGarrett D'Amore } 75895c635efSGarrett D'Amore 75995c635efSGarrett D'Amore return(1); 76095c635efSGarrett D'Amore } 76195c635efSGarrett D'Amore 76295c635efSGarrett D'Amore 76395c635efSGarrett D'Amore /* ARGSUSED */ 76495c635efSGarrett D'Amore static void 76595c635efSGarrett D'Amore post_TP(DECL_ARGS) 76695c635efSGarrett D'Amore { 76795c635efSGarrett D'Amore 76895c635efSGarrett D'Amore switch (n->type) { 76995c635efSGarrett D'Amore case (MAN_HEAD): 77095c635efSGarrett D'Amore term_flushln(p); 77195c635efSGarrett D'Amore break; 77295c635efSGarrett D'Amore case (MAN_BODY): 77395c635efSGarrett D'Amore term_newln(p); 774*698f87a4SGarrett D'Amore p->offset = mt->offset; 77595c635efSGarrett D'Amore break; 77695c635efSGarrett D'Amore default: 77795c635efSGarrett D'Amore break; 77895c635efSGarrett D'Amore } 77995c635efSGarrett D'Amore } 78095c635efSGarrett D'Amore 78195c635efSGarrett D'Amore 78295c635efSGarrett D'Amore /* ARGSUSED */ 78395c635efSGarrett D'Amore static int 78495c635efSGarrett D'Amore pre_SS(DECL_ARGS) 78595c635efSGarrett D'Amore { 786*698f87a4SGarrett D'Amore int i; 78795c635efSGarrett D'Amore 78895c635efSGarrett D'Amore switch (n->type) { 78995c635efSGarrett D'Amore case (MAN_BLOCK): 79095c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 79195c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 79295c635efSGarrett D'Amore mt->offset = term_len(p, p->defindent); 79395c635efSGarrett D'Amore /* If following a prior empty `SS', no vspace. */ 79495c635efSGarrett D'Amore if (n->prev && MAN_SS == n->prev->tok) 79595c635efSGarrett D'Amore if (NULL == n->prev->body->child) 79695c635efSGarrett D'Amore break; 79795c635efSGarrett D'Amore if (NULL == n->prev) 79895c635efSGarrett D'Amore break; 799*698f87a4SGarrett D'Amore for (i = 0; i < mt->pardist; i++) 80095c635efSGarrett D'Amore term_vspace(p); 80195c635efSGarrett D'Amore break; 80295c635efSGarrett D'Amore case (MAN_HEAD): 80395c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 804*698f87a4SGarrett D'Amore p->offset = term_len(p, 3); 80595c635efSGarrett D'Amore break; 80695c635efSGarrett D'Amore case (MAN_BODY): 80795c635efSGarrett D'Amore p->offset = mt->offset; 80895c635efSGarrett D'Amore break; 80995c635efSGarrett D'Amore default: 81095c635efSGarrett D'Amore break; 81195c635efSGarrett D'Amore } 81295c635efSGarrett D'Amore 81395c635efSGarrett D'Amore return(1); 81495c635efSGarrett D'Amore } 81595c635efSGarrett D'Amore 81695c635efSGarrett D'Amore 81795c635efSGarrett D'Amore /* ARGSUSED */ 81895c635efSGarrett D'Amore static void 81995c635efSGarrett D'Amore post_SS(DECL_ARGS) 82095c635efSGarrett D'Amore { 82195c635efSGarrett D'Amore 82295c635efSGarrett D'Amore switch (n->type) { 82395c635efSGarrett D'Amore case (MAN_HEAD): 82495c635efSGarrett D'Amore term_newln(p); 82595c635efSGarrett D'Amore break; 82695c635efSGarrett D'Amore case (MAN_BODY): 82795c635efSGarrett D'Amore term_newln(p); 82895c635efSGarrett D'Amore break; 82995c635efSGarrett D'Amore default: 83095c635efSGarrett D'Amore break; 83195c635efSGarrett D'Amore } 83295c635efSGarrett D'Amore } 83395c635efSGarrett D'Amore 83495c635efSGarrett D'Amore 83595c635efSGarrett D'Amore /* ARGSUSED */ 83695c635efSGarrett D'Amore static int 83795c635efSGarrett D'Amore pre_SH(DECL_ARGS) 83895c635efSGarrett D'Amore { 839*698f87a4SGarrett D'Amore int i; 84095c635efSGarrett D'Amore 84195c635efSGarrett D'Amore switch (n->type) { 84295c635efSGarrett D'Amore case (MAN_BLOCK): 84395c635efSGarrett D'Amore mt->fl &= ~MANT_LITERAL; 84495c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); 84595c635efSGarrett D'Amore mt->offset = term_len(p, p->defindent); 84695c635efSGarrett D'Amore /* If following a prior empty `SH', no vspace. */ 84795c635efSGarrett D'Amore if (n->prev && MAN_SH == n->prev->tok) 84895c635efSGarrett D'Amore if (NULL == n->prev->body->child) 84995c635efSGarrett D'Amore break; 85095c635efSGarrett D'Amore /* If the first macro, no vspae. */ 85195c635efSGarrett D'Amore if (NULL == n->prev) 85295c635efSGarrett D'Amore break; 853*698f87a4SGarrett D'Amore for (i = 0; i < mt->pardist; i++) 85495c635efSGarrett D'Amore term_vspace(p); 85595c635efSGarrett D'Amore break; 85695c635efSGarrett D'Amore case (MAN_HEAD): 85795c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_BOLD); 85895c635efSGarrett D'Amore p->offset = 0; 85995c635efSGarrett D'Amore break; 86095c635efSGarrett D'Amore case (MAN_BODY): 86195c635efSGarrett D'Amore p->offset = mt->offset; 86295c635efSGarrett D'Amore break; 86395c635efSGarrett D'Amore default: 86495c635efSGarrett D'Amore break; 86595c635efSGarrett D'Amore } 86695c635efSGarrett D'Amore 86795c635efSGarrett D'Amore return(1); 86895c635efSGarrett D'Amore } 86995c635efSGarrett D'Amore 87095c635efSGarrett D'Amore 87195c635efSGarrett D'Amore /* ARGSUSED */ 87295c635efSGarrett D'Amore static void 87395c635efSGarrett D'Amore post_SH(DECL_ARGS) 87495c635efSGarrett D'Amore { 87595c635efSGarrett D'Amore 87695c635efSGarrett D'Amore switch (n->type) { 87795c635efSGarrett D'Amore case (MAN_HEAD): 87895c635efSGarrett D'Amore term_newln(p); 87995c635efSGarrett D'Amore break; 88095c635efSGarrett D'Amore case (MAN_BODY): 88195c635efSGarrett D'Amore term_newln(p); 88295c635efSGarrett D'Amore break; 88395c635efSGarrett D'Amore default: 88495c635efSGarrett D'Amore break; 88595c635efSGarrett D'Amore } 88695c635efSGarrett D'Amore } 88795c635efSGarrett D'Amore 88895c635efSGarrett D'Amore /* ARGSUSED */ 88995c635efSGarrett D'Amore static int 89095c635efSGarrett D'Amore pre_RS(DECL_ARGS) 89195c635efSGarrett D'Amore { 89295c635efSGarrett D'Amore int ival; 89395c635efSGarrett D'Amore size_t sz; 89495c635efSGarrett D'Amore 89595c635efSGarrett D'Amore switch (n->type) { 89695c635efSGarrett D'Amore case (MAN_BLOCK): 89795c635efSGarrett D'Amore term_newln(p); 89895c635efSGarrett D'Amore return(1); 89995c635efSGarrett D'Amore case (MAN_HEAD): 90095c635efSGarrett D'Amore return(0); 90195c635efSGarrett D'Amore default: 90295c635efSGarrett D'Amore break; 90395c635efSGarrett D'Amore } 90495c635efSGarrett D'Amore 90595c635efSGarrett D'Amore sz = term_len(p, p->defindent); 90695c635efSGarrett D'Amore 90795c635efSGarrett D'Amore if (NULL != (n = n->parent->head->child)) 90895c635efSGarrett D'Amore if ((ival = a2width(p, n->string)) >= 0) 90995c635efSGarrett D'Amore sz = (size_t)ival; 91095c635efSGarrett D'Amore 91195c635efSGarrett D'Amore mt->offset += sz; 91295c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 91395c635efSGarrett D'Amore p->offset = mt->offset < p->rmargin ? mt->offset : p->rmargin; 91495c635efSGarrett D'Amore 91595c635efSGarrett D'Amore if (++mt->lmarginsz < MAXMARGINS) 91695c635efSGarrett D'Amore mt->lmargincur = mt->lmarginsz; 91795c635efSGarrett D'Amore 91895c635efSGarrett D'Amore mt->lmargin[mt->lmargincur] = mt->lmargin[mt->lmargincur - 1]; 91995c635efSGarrett D'Amore return(1); 92095c635efSGarrett D'Amore } 92195c635efSGarrett D'Amore 92295c635efSGarrett D'Amore /* ARGSUSED */ 92395c635efSGarrett D'Amore static void 92495c635efSGarrett D'Amore post_RS(DECL_ARGS) 92595c635efSGarrett D'Amore { 92695c635efSGarrett D'Amore int ival; 92795c635efSGarrett D'Amore size_t sz; 92895c635efSGarrett D'Amore 92995c635efSGarrett D'Amore switch (n->type) { 93095c635efSGarrett D'Amore case (MAN_BLOCK): 93195c635efSGarrett D'Amore return; 93295c635efSGarrett D'Amore case (MAN_HEAD): 93395c635efSGarrett D'Amore return; 93495c635efSGarrett D'Amore default: 93595c635efSGarrett D'Amore term_newln(p); 93695c635efSGarrett D'Amore break; 93795c635efSGarrett D'Amore } 93895c635efSGarrett D'Amore 93995c635efSGarrett D'Amore sz = term_len(p, p->defindent); 94095c635efSGarrett D'Amore 94195c635efSGarrett D'Amore if (NULL != (n = n->parent->head->child)) 94295c635efSGarrett D'Amore if ((ival = a2width(p, n->string)) >= 0) 94395c635efSGarrett D'Amore sz = (size_t)ival; 94495c635efSGarrett D'Amore 94595c635efSGarrett D'Amore mt->offset = mt->offset < sz ? 0 : mt->offset - sz; 94695c635efSGarrett D'Amore p->offset = mt->offset; 94795c635efSGarrett D'Amore 94895c635efSGarrett D'Amore if (--mt->lmarginsz < MAXMARGINS) 94995c635efSGarrett D'Amore mt->lmargincur = mt->lmarginsz; 95095c635efSGarrett D'Amore } 95195c635efSGarrett D'Amore 952*698f87a4SGarrett D'Amore /* ARGSUSED */ 953*698f87a4SGarrett D'Amore static int 954*698f87a4SGarrett D'Amore pre_UR(DECL_ARGS) 955*698f87a4SGarrett D'Amore { 956*698f87a4SGarrett D'Amore 957*698f87a4SGarrett D'Amore return (MAN_HEAD != n->type); 958*698f87a4SGarrett D'Amore } 959*698f87a4SGarrett D'Amore 960*698f87a4SGarrett D'Amore /* ARGSUSED */ 961*698f87a4SGarrett D'Amore static void 962*698f87a4SGarrett D'Amore post_UR(DECL_ARGS) 963*698f87a4SGarrett D'Amore { 964*698f87a4SGarrett D'Amore 965*698f87a4SGarrett D'Amore if (MAN_BLOCK != n->type) 966*698f87a4SGarrett D'Amore return; 967*698f87a4SGarrett D'Amore 968*698f87a4SGarrett D'Amore term_word(p, "<"); 969*698f87a4SGarrett D'Amore p->flags |= TERMP_NOSPACE; 970*698f87a4SGarrett D'Amore 971*698f87a4SGarrett D'Amore if (NULL != n->child->child) 972*698f87a4SGarrett D'Amore print_man_node(p, mt, n->child->child, meta); 973*698f87a4SGarrett D'Amore 974*698f87a4SGarrett D'Amore p->flags |= TERMP_NOSPACE; 975*698f87a4SGarrett D'Amore term_word(p, ">"); 976*698f87a4SGarrett D'Amore } 977*698f87a4SGarrett D'Amore 97895c635efSGarrett D'Amore static void 97995c635efSGarrett D'Amore print_man_node(DECL_ARGS) 98095c635efSGarrett D'Amore { 98195c635efSGarrett D'Amore size_t rm, rmax; 98295c635efSGarrett D'Amore int c; 98395c635efSGarrett D'Amore 98495c635efSGarrett D'Amore switch (n->type) { 98595c635efSGarrett D'Amore case(MAN_TEXT): 98695c635efSGarrett D'Amore /* 98795c635efSGarrett D'Amore * If we have a blank line, output a vertical space. 98895c635efSGarrett D'Amore * If we have a space as the first character, break 98995c635efSGarrett D'Amore * before printing the line's data. 99095c635efSGarrett D'Amore */ 99195c635efSGarrett D'Amore if ('\0' == *n->string) { 99295c635efSGarrett D'Amore term_vspace(p); 99395c635efSGarrett D'Amore return; 99495c635efSGarrett D'Amore } else if (' ' == *n->string && MAN_LINE & n->flags) 99595c635efSGarrett D'Amore term_newln(p); 99695c635efSGarrett D'Amore 99795c635efSGarrett D'Amore term_word(p, n->string); 998*698f87a4SGarrett D'Amore goto out; 99995c635efSGarrett D'Amore 100095c635efSGarrett D'Amore case (MAN_EQN): 100195c635efSGarrett D'Amore term_eqn(p, n->eqn); 100295c635efSGarrett D'Amore return; 100395c635efSGarrett D'Amore case (MAN_TBL): 100495c635efSGarrett D'Amore /* 100595c635efSGarrett D'Amore * Tables are preceded by a newline. Then process a 100695c635efSGarrett D'Amore * table line, which will cause line termination, 100795c635efSGarrett D'Amore */ 100895c635efSGarrett D'Amore if (TBL_SPAN_FIRST & n->span->flags) 100995c635efSGarrett D'Amore term_newln(p); 101095c635efSGarrett D'Amore term_tbl(p, n->span); 101195c635efSGarrett D'Amore return; 101295c635efSGarrett D'Amore default: 101395c635efSGarrett D'Amore break; 101495c635efSGarrett D'Amore } 101595c635efSGarrett D'Amore 101695c635efSGarrett D'Amore if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) 101795c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 101895c635efSGarrett D'Amore 101995c635efSGarrett D'Amore c = 1; 102095c635efSGarrett D'Amore if (termacts[n->tok].pre) 1021*698f87a4SGarrett D'Amore c = (*termacts[n->tok].pre)(p, mt, n, meta); 102295c635efSGarrett D'Amore 102395c635efSGarrett D'Amore if (c && n->child) 1024*698f87a4SGarrett D'Amore print_man_nodelist(p, mt, n->child, meta); 102595c635efSGarrett D'Amore 102695c635efSGarrett D'Amore if (termacts[n->tok].post) 1027*698f87a4SGarrett D'Amore (*termacts[n->tok].post)(p, mt, n, meta); 102895c635efSGarrett D'Amore if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) 102995c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 103095c635efSGarrett D'Amore 1031*698f87a4SGarrett D'Amore out: 1032*698f87a4SGarrett D'Amore /* 1033*698f87a4SGarrett D'Amore * If we're in a literal context, make sure that words 1034*698f87a4SGarrett D'Amore * together on the same line stay together. This is a 1035*698f87a4SGarrett D'Amore * POST-printing call, so we check the NEXT word. Since 1036*698f87a4SGarrett D'Amore * -man doesn't have nested macros, we don't need to be 1037*698f87a4SGarrett D'Amore * more specific than this. 1038*698f87a4SGarrett D'Amore */ 1039*698f87a4SGarrett D'Amore if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) && 1040*698f87a4SGarrett D'Amore (NULL == n->next || n->next->line > n->line)) { 1041*698f87a4SGarrett D'Amore rm = p->rmargin; 1042*698f87a4SGarrett D'Amore rmax = p->maxrmargin; 1043*698f87a4SGarrett D'Amore p->rmargin = p->maxrmargin = TERM_MAXMARGIN; 1044*698f87a4SGarrett D'Amore p->flags |= TERMP_NOSPACE; 1045*698f87a4SGarrett D'Amore if (NULL != n->string && '\0' != *n->string) 1046*698f87a4SGarrett D'Amore term_flushln(p); 1047*698f87a4SGarrett D'Amore else 1048*698f87a4SGarrett D'Amore term_newln(p); 1049*698f87a4SGarrett D'Amore if (rm < rmax && n->parent->tok == MAN_HP) { 1050*698f87a4SGarrett D'Amore p->offset = rm; 1051*698f87a4SGarrett D'Amore p->rmargin = rmax; 1052*698f87a4SGarrett D'Amore } else 1053*698f87a4SGarrett D'Amore p->rmargin = rm; 1054*698f87a4SGarrett D'Amore p->maxrmargin = rmax; 1055*698f87a4SGarrett D'Amore } 105695c635efSGarrett D'Amore if (MAN_EOS & n->flags) 105795c635efSGarrett D'Amore p->flags |= TERMP_SENTENCE; 105895c635efSGarrett D'Amore } 105995c635efSGarrett D'Amore 106095c635efSGarrett D'Amore 106195c635efSGarrett D'Amore static void 106295c635efSGarrett D'Amore print_man_nodelist(DECL_ARGS) 106395c635efSGarrett D'Amore { 106495c635efSGarrett D'Amore 1065*698f87a4SGarrett D'Amore print_man_node(p, mt, n, meta); 106695c635efSGarrett D'Amore if ( ! n->next) 106795c635efSGarrett D'Amore return; 1068*698f87a4SGarrett D'Amore print_man_nodelist(p, mt, n->next, meta); 106995c635efSGarrett D'Amore } 107095c635efSGarrett D'Amore 107195c635efSGarrett D'Amore 107295c635efSGarrett D'Amore static void 107395c635efSGarrett D'Amore print_man_foot(struct termp *p, const void *arg) 107495c635efSGarrett D'Amore { 107595c635efSGarrett D'Amore char title[BUFSIZ]; 107695c635efSGarrett D'Amore size_t datelen; 107795c635efSGarrett D'Amore const struct man_meta *meta; 107895c635efSGarrett D'Amore 107995c635efSGarrett D'Amore meta = (const struct man_meta *)arg; 108095c635efSGarrett D'Amore assert(meta->title); 108195c635efSGarrett D'Amore assert(meta->msec); 108295c635efSGarrett D'Amore assert(meta->date); 108395c635efSGarrett D'Amore 108495c635efSGarrett D'Amore term_fontrepl(p, TERMFONT_NONE); 108595c635efSGarrett D'Amore 108695c635efSGarrett D'Amore term_vspace(p); 108795c635efSGarrett D'Amore 108895c635efSGarrett D'Amore /* 108995c635efSGarrett D'Amore * Temporary, undocumented option to imitate mdoc(7) output. 109095c635efSGarrett D'Amore * In the bottom right corner, use the source instead of 109195c635efSGarrett D'Amore * the title. 109295c635efSGarrett D'Amore */ 109395c635efSGarrett D'Amore 109495c635efSGarrett D'Amore if ( ! p->mdocstyle) { 109595c635efSGarrett D'Amore term_vspace(p); 109695c635efSGarrett D'Amore term_vspace(p); 109795c635efSGarrett D'Amore snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec); 109895c635efSGarrett D'Amore } else if (meta->source) { 109995c635efSGarrett D'Amore strlcpy(title, meta->source, BUFSIZ); 110095c635efSGarrett D'Amore } else { 110195c635efSGarrett D'Amore title[0] = '\0'; 110295c635efSGarrett D'Amore } 110395c635efSGarrett D'Amore datelen = term_strlen(p, meta->date); 110495c635efSGarrett D'Amore 110595c635efSGarrett D'Amore /* Bottom left corner: manual source. */ 110695c635efSGarrett D'Amore 110795c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; 1108*698f87a4SGarrett D'Amore p->trailspace = 1; 110995c635efSGarrett D'Amore p->offset = 0; 111095c635efSGarrett D'Amore p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2; 111195c635efSGarrett D'Amore 111295c635efSGarrett D'Amore if (meta->source) 111395c635efSGarrett D'Amore term_word(p, meta->source); 111495c635efSGarrett D'Amore term_flushln(p); 111595c635efSGarrett D'Amore 111695c635efSGarrett D'Amore /* At the bottom in the middle: manual date. */ 111795c635efSGarrett D'Amore 111895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 111995c635efSGarrett D'Amore p->offset = p->rmargin; 112095c635efSGarrett D'Amore p->rmargin = p->maxrmargin - term_strlen(p, title); 112195c635efSGarrett D'Amore if (p->offset + datelen >= p->rmargin) 112295c635efSGarrett D'Amore p->rmargin = p->offset + datelen; 112395c635efSGarrett D'Amore 112495c635efSGarrett D'Amore term_word(p, meta->date); 112595c635efSGarrett D'Amore term_flushln(p); 112695c635efSGarrett D'Amore 112795c635efSGarrett D'Amore /* Bottom right corner: manual title and section. */ 112895c635efSGarrett D'Amore 112995c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 113095c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 1131*698f87a4SGarrett D'Amore p->trailspace = 0; 113295c635efSGarrett D'Amore p->offset = p->rmargin; 113395c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 113495c635efSGarrett D'Amore 113595c635efSGarrett D'Amore term_word(p, title); 113695c635efSGarrett D'Amore term_flushln(p); 113795c635efSGarrett D'Amore } 113895c635efSGarrett D'Amore 113995c635efSGarrett D'Amore 114095c635efSGarrett D'Amore static void 114195c635efSGarrett D'Amore print_man_head(struct termp *p, const void *arg) 114295c635efSGarrett D'Amore { 114395c635efSGarrett D'Amore char buf[BUFSIZ], title[BUFSIZ]; 114495c635efSGarrett D'Amore size_t buflen, titlen; 1145*698f87a4SGarrett D'Amore const struct man_meta *meta; 114695c635efSGarrett D'Amore 1147*698f87a4SGarrett D'Amore meta = (const struct man_meta *)arg; 1148*698f87a4SGarrett D'Amore assert(meta->title); 1149*698f87a4SGarrett D'Amore assert(meta->msec); 115095c635efSGarrett D'Amore 1151*698f87a4SGarrett D'Amore if (meta->vol) 1152*698f87a4SGarrett D'Amore strlcpy(buf, meta->vol, BUFSIZ); 115395c635efSGarrett D'Amore else 115495c635efSGarrett D'Amore buf[0] = '\0'; 115595c635efSGarrett D'Amore buflen = term_strlen(p, buf); 115695c635efSGarrett D'Amore 115795c635efSGarrett D'Amore /* Top left corner: manual title and section. */ 115895c635efSGarrett D'Amore 1159*698f87a4SGarrett D'Amore snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec); 116095c635efSGarrett D'Amore titlen = term_strlen(p, title); 116195c635efSGarrett D'Amore 116295c635efSGarrett D'Amore p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; 1163*698f87a4SGarrett D'Amore p->trailspace = 1; 116495c635efSGarrett D'Amore p->offset = 0; 116595c635efSGarrett D'Amore p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ? 116695c635efSGarrett D'Amore (p->maxrmargin - 116795c635efSGarrett D'Amore term_strlen(p, buf) + term_len(p, 1)) / 2 : 116895c635efSGarrett D'Amore p->maxrmargin - buflen; 116995c635efSGarrett D'Amore 117095c635efSGarrett D'Amore term_word(p, title); 117195c635efSGarrett D'Amore term_flushln(p); 117295c635efSGarrett D'Amore 117395c635efSGarrett D'Amore /* At the top in the middle: manual volume. */ 117495c635efSGarrett D'Amore 117595c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 117695c635efSGarrett D'Amore p->offset = p->rmargin; 117795c635efSGarrett D'Amore p->rmargin = p->offset + buflen + titlen < p->maxrmargin ? 117895c635efSGarrett D'Amore p->maxrmargin - titlen : p->maxrmargin; 117995c635efSGarrett D'Amore 118095c635efSGarrett D'Amore term_word(p, buf); 118195c635efSGarrett D'Amore term_flushln(p); 118295c635efSGarrett D'Amore 118395c635efSGarrett D'Amore /* Top right corner: title and section, again. */ 118495c635efSGarrett D'Amore 118595c635efSGarrett D'Amore p->flags &= ~TERMP_NOBREAK; 1186*698f87a4SGarrett D'Amore p->trailspace = 0; 118795c635efSGarrett D'Amore if (p->rmargin + titlen <= p->maxrmargin) { 118895c635efSGarrett D'Amore p->flags |= TERMP_NOSPACE; 118995c635efSGarrett D'Amore p->offset = p->rmargin; 119095c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 119195c635efSGarrett D'Amore term_word(p, title); 119295c635efSGarrett D'Amore term_flushln(p); 119395c635efSGarrett D'Amore } 119495c635efSGarrett D'Amore 119595c635efSGarrett D'Amore p->flags &= ~TERMP_NOSPACE; 119695c635efSGarrett D'Amore p->offset = 0; 119795c635efSGarrett D'Amore p->rmargin = p->maxrmargin; 119895c635efSGarrett D'Amore 119995c635efSGarrett D'Amore /* 120095c635efSGarrett D'Amore * Groff prints three blank lines before the content. 120195c635efSGarrett D'Amore * Do the same, except in the temporary, undocumented 120295c635efSGarrett D'Amore * mode imitating mdoc(7) output. 120395c635efSGarrett D'Amore */ 120495c635efSGarrett D'Amore 120595c635efSGarrett D'Amore term_vspace(p); 120695c635efSGarrett D'Amore if ( ! p->mdocstyle) { 120795c635efSGarrett D'Amore term_vspace(p); 120895c635efSGarrett D'Amore term_vspace(p); 120995c635efSGarrett D'Amore } 121095c635efSGarrett D'Amore } 1211