=================================================================== RCS file: /cvs/mandoc/mdoc_term.c,v retrieving revision 1.297 retrieving revision 1.322 diff -u -p -r1.297 -r1.322 --- mandoc/mdoc_term.c 2014/11/28 16:54:23 1.297 +++ mandoc/mdoc_term.c 2015/07/25 14:18:04 1.322 @@ -1,16 +1,16 @@ -/* $Id: mdoc_term.c,v 1.297 2014/11/28 16:54:23 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.322 2015/07/25 14:18:04 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze + * Copyright (c) 2010, 2012-2015 Ingo Schwarze * Copyright (c) 2013 Franco Fichtner * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -22,16 +22,19 @@ #include #include +#include #include #include #include #include -#include "mandoc.h" #include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" #include "out.h" #include "term.h" -#include "mdoc.h" +#include "tag.h" #include "main.h" struct termpair { @@ -41,32 +44,32 @@ struct termpair { #define DECL_ARGS struct termp *p, \ struct termpair *pair, \ - const struct mdoc_meta *meta, \ - struct mdoc_node *n + const struct roff_meta *meta, \ + struct roff_node *n struct termact { int (*pre)(DECL_ARGS); void (*post)(DECL_ARGS); }; -static size_t a2width(const struct termp *, const char *); -static size_t a2height(const struct termp *, const char *); +static int a2width(const struct termp *, const char *); static void print_bvspace(struct termp *, - const struct mdoc_node *, - const struct mdoc_node *); + const struct roff_node *, + const struct roff_node *); static void print_mdoc_node(DECL_ARGS); static void print_mdoc_nodelist(DECL_ARGS); -static void print_mdoc_head(struct termp *, const void *); -static void print_mdoc_foot(struct termp *, const void *); +static void print_mdoc_head(struct termp *, const struct roff_meta *); +static void print_mdoc_foot(struct termp *, const struct roff_meta *); static void synopsis_pre(struct termp *, - const struct mdoc_node *); + const struct roff_node *); static void termp____post(DECL_ARGS); static void termp__t_post(DECL_ARGS); static void termp_bd_post(DECL_ARGS); static void termp_bk_post(DECL_ARGS); static void termp_bl_post(DECL_ARGS); +static void termp_eo_post(DECL_ARGS); static void termp_fd_post(DECL_ARGS); static void termp_fo_post(DECL_ARGS); static void termp_in_post(DECL_ARGS); @@ -91,6 +94,7 @@ static int termp_bt_pre(DECL_ARGS); static int termp_bx_pre(DECL_ARGS); static int termp_cd_pre(DECL_ARGS); static int termp_d1_pre(DECL_ARGS); +static int termp_eo_pre(DECL_ARGS); static int termp_ex_pre(DECL_ARGS); static int termp_fa_pre(DECL_ARGS); static int termp_fd_pre(DECL_ARGS); @@ -114,6 +118,7 @@ static int termp_skip_pre(DECL_ARGS); static int termp_sm_pre(DECL_ARGS); static int termp_sp_pre(DECL_ARGS); static int termp_ss_pre(DECL_ARGS); +static int termp_tag_pre(DECL_ARGS); static int termp_under_pre(DECL_ARGS); static int termp_ud_pre(DECL_ARGS); static int termp_vt_pre(DECL_ARGS); @@ -142,7 +147,7 @@ static const struct termact termacts[MDOC_MAX] = { { termp_bold_pre, NULL }, /* Cm */ { NULL, NULL }, /* Dv */ { NULL, NULL }, /* Er */ - { NULL, NULL }, /* Ev */ + { termp_tag_pre, NULL }, /* Ev */ { termp_ex_pre, NULL }, /* Ex */ { termp_fa_pre, NULL }, /* Fa */ { termp_fd_pre, termp_fd_post }, /* Fd */ @@ -190,7 +195,7 @@ static const struct termact termacts[MDOC_MAX] = { { NULL, NULL }, /* Ec */ /* FIXME: no space */ { NULL, NULL }, /* Ef */ { termp_under_pre, NULL }, /* Em */ - { termp_quote_pre, termp_quote_post }, /* Eo */ + { termp_eo_pre, termp_eo_post }, /* Eo */ { termp_xx_pre, NULL }, /* Fx */ { termp_bold_pre, NULL }, /* Ms */ { termp_li_pre, NULL }, /* No */ @@ -246,29 +251,27 @@ static const struct termact termacts[MDOC_MAX] = { { termp_ll_pre, NULL }, /* ll */ }; +static int fn_prio; void -terminal_mdoc(void *arg, const struct mdoc *mdoc) +terminal_mdoc(void *arg, const struct roff_man *mdoc) { - const struct mdoc_meta *meta; - struct mdoc_node *n; + struct roff_node *n; struct termp *p; p = (struct termp *)arg; - p->overstep = 0; p->rmargin = p->maxrmargin = p->defrmargin; p->tabwidth = term_len(p, 5); - n = mdoc_node(mdoc)->child; - meta = mdoc_meta(mdoc); - + n = mdoc->first->child; if (p->synopsisonly) { while (n != NULL) { if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) { if (n->child->next->child != NULL) print_mdoc_nodelist(p, NULL, - meta, n->child->next->child); + &mdoc->meta, + n->child->next->child); term_newln(p); break; } @@ -277,11 +280,12 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc) } else { if (p->defindent == 0) p->defindent = 5; - term_begin(p, print_mdoc_head, print_mdoc_foot, meta); + term_begin(p, print_mdoc_head, print_mdoc_foot, + &mdoc->meta); if (n != NULL) { if (n->tok != MDOC_Sh) term_vspace(p); - print_mdoc_nodelist(p, NULL, meta, n); + print_mdoc_nodelist(p, NULL, &mdoc->meta, n); } term_end(p); } @@ -291,9 +295,10 @@ static void print_mdoc_nodelist(DECL_ARGS) { - print_mdoc_node(p, pair, meta, n); - if (n->next) - print_mdoc_nodelist(p, pair, meta, n->next); + while (n != NULL) { + print_mdoc_node(p, pair, meta, n); + n = n->next; + } } static void @@ -306,7 +311,8 @@ print_mdoc_node(DECL_ARGS) chld = 1; offset = p->offset; rmargin = p->rmargin; - n->prev_font = term_fontq(p); + n->flags &= ~MDOC_ENDED; + n->prev_font = p->fonti; memset(&npair, 0, sizeof(struct termpair)); npair.ppair = pair; @@ -316,12 +322,9 @@ print_mdoc_node(DECL_ARGS) * invoked in a prior line, revert it to PREKEEP. */ - if (TERMP_KEEP & p->flags) { - if (n->prev ? (n->prev->lastline != n->line) : - (n->parent && n->parent->line != n->line)) { - p->flags &= ~TERMP_KEEP; - p->flags |= TERMP_PREKEEP; - } + if (p->flags & TERMP_KEEP && n->flags & MDOC_LINE) { + p->flags &= ~TERMP_KEEP; + p->flags |= TERMP_PREKEEP; } /* @@ -330,7 +333,7 @@ print_mdoc_node(DECL_ARGS) */ switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: if (' ' == *n->string && MDOC_LINE & n->flags) term_newln(p); if (MDOC_DELIMC & n->flags) @@ -339,14 +342,16 @@ print_mdoc_node(DECL_ARGS) if (MDOC_DELIMO & n->flags) p->flags |= TERMP_NOSPACE; break; - case MDOC_EQN: + case ROFFT_EQN: if ( ! (n->flags & MDOC_LINE)) p->flags |= TERMP_NOSPACE; term_eqn(p, n->eqn); if (n->next != NULL && ! (n->next->flags & MDOC_LINE)) p->flags |= TERMP_NOSPACE; break; - case MDOC_TBL: + case ROFFT_TBL: + if (p->tbl.cols == NULL) + term_newln(p); term_tbl(p, n->span); break; default: @@ -361,14 +366,14 @@ print_mdoc_node(DECL_ARGS) print_mdoc_nodelist(p, &npair, meta, n->child); term_fontpopq(p, - (ENDBODY_NOT == n->end ? n : n->pending)->prev_font); + (ENDBODY_NOT == n->end ? n : n->body)->prev_font); switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: break; - case MDOC_TBL: + case ROFFT_TBL: break; - case MDOC_EQN: + case ROFFT_EQN: break; default: if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags) @@ -381,7 +386,7 @@ print_mdoc_node(DECL_ARGS) * that it must not call the post handler again. */ if (ENDBODY_NOT != n->end) - n->pending->flags |= MDOC_ENDED; + n->body->flags |= MDOC_ENDED; /* * End of line terminating an implicit block @@ -403,13 +408,10 @@ print_mdoc_node(DECL_ARGS) } static void -print_mdoc_foot(struct termp *p, const void *arg) +print_mdoc_foot(struct termp *p, const struct roff_meta *meta) { - const struct mdoc_meta *meta; size_t sz; - meta = (const struct mdoc_meta *)arg; - term_fontrepl(p, TERMFONT_NONE); /* @@ -455,14 +457,11 @@ print_mdoc_foot(struct termp *p, const void *arg) } static void -print_mdoc_head(struct termp *p, const void *arg) +print_mdoc_head(struct termp *p, const struct roff_meta *meta) { - const struct mdoc_meta *meta; char *volume, *title; size_t vollen, titlen; - meta = (const struct mdoc_meta *)arg; - /* * The header is strange. It has three components, which are * really two with the first duplicated. It goes like this: @@ -526,31 +525,16 @@ print_mdoc_head(struct termp *p, const void *arg) free(volume); } -static size_t -a2height(const struct termp *p, const char *v) -{ - struct roffsu su; - - - assert(v); - if ( ! a2roffsu(v, &su, SCALE_VS)) - SCALE_VS_INIT(&su, atoi(v)); - - return(term_vspan(p, &su)); -} - -static size_t +static int a2width(const struct termp *p, const char *v) { struct roffsu su; - assert(v); - if ( ! a2roffsu(v, &su, SCALE_MAX)) { + if (a2roffsu(v, &su, SCALE_MAX) < 2) { SCALE_HS_INIT(&su, term_strlen(p, v)); su.scale /= term_strlen(p, "0"); } - - return(term_hspan(p, &su)); + return(term_hspan(p, &su) / 24); } /* @@ -560,10 +544,10 @@ a2width(const struct termp *p, const char *v) */ static void print_bvspace(struct termp *p, - const struct mdoc_node *bl, - const struct mdoc_node *n) + const struct roff_node *bl, + const struct roff_node *n) { - const struct mdoc_node *nn; + const struct roff_node *nn; assert(n); @@ -580,9 +564,9 @@ print_bvspace(struct termp *p, while (nn->prev == NULL) { do { nn = nn->parent; - if (nn->type == MDOC_ROOT) + if (nn->type == ROFFT_ROOT) return; - } while (nn->type != MDOC_BLOCK); + } while (nn->type != ROFFT_BLOCK); if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss) return; if (nn->tok == MDOC_It && @@ -620,13 +604,13 @@ termp_ll_pre(DECL_ARGS) static int termp_it_pre(DECL_ARGS) { - const struct mdoc_node *bl, *nn; char buf[24]; - int i; - size_t width, offset, ncols, dcol; + const struct roff_node *bl, *nn; + size_t ncols, dcol; + int i, offset, width; enum mdoc_list type; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { print_bvspace(p, n->parent->parent, n); return(1); } @@ -635,19 +619,50 @@ termp_it_pre(DECL_ARGS) type = bl->norm->Bl.type; /* + * Defaults for specific list types. + */ + + switch (type) { + case LIST_bullet: + /* FALLTHROUGH */ + case LIST_dash: + /* FALLTHROUGH */ + case LIST_hyphen: + /* FALLTHROUGH */ + case LIST_enum: + width = term_len(p, 2); + break; + case LIST_hang: + width = term_len(p, 8); + break; + case LIST_column: + /* FALLTHROUGH */ + case LIST_tag: + width = term_len(p, 10); + break; + default: + width = 0; + break; + } + offset = 0; + + /* * First calculate width and offset. This is pretty easy unless * we're a -column list, in which case all prior columns must * be accounted for. */ - width = offset = 0; - - if (bl->norm->Bl.offs) + if (bl->norm->Bl.offs != NULL) { offset = a2width(p, bl->norm->Bl.offs); + if (offset < 0 && (size_t)(-offset) > p->offset) + offset = -p->offset; + else if (offset > SHRT_MAX) + offset = 0; + } switch (type) { case LIST_column: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; /* @@ -664,8 +679,8 @@ termp_it_pre(DECL_ARGS) ncols == 5 ? term_len(p, 3) : term_len(p, 1); /* - * Calculate the offset by applying all prior MDOC_BODY, - * so we stop at the MDOC_HEAD (NULL == nn->prev). + * Calculate the offset by applying all prior ROFFT_BODY, + * so we stop at the ROFFT_HEAD (nn->prev == NULL). */ for (i = 0, nn = n->prev; @@ -698,43 +713,15 @@ termp_it_pre(DECL_ARGS) * number for buffering single arguments. See the above * handling for column for how this changes. */ - assert(bl->norm->Bl.width); width = a2width(p, bl->norm->Bl.width) + term_len(p, 2); + if (width < 0 && (size_t)(-width) > p->offset) + width = -p->offset; + else if (width > SHRT_MAX) + width = 0; break; } /* - * List-type can override the width in the case of fixed-head - * values (bullet, dash/hyphen, enum). Tags need a non-zero - * offset. - */ - - switch (type) { - case LIST_bullet: - /* FALLTHROUGH */ - case LIST_dash: - /* FALLTHROUGH */ - case LIST_hyphen: - /* FALLTHROUGH */ - case LIST_enum: - if (width < term_len(p, 2)) - width = term_len(p, 2); - break; - case LIST_hang: - if (0 == width) - width = term_len(p, 8); - break; - case LIST_column: - /* FALLTHROUGH */ - case LIST_tag: - if (0 == width) - width = term_len(p, 10); - break; - default: - break; - } - - /* * Whitespace control. Inset bodies need an initial space, * while diagonal bodies need two. */ @@ -743,11 +730,11 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_diag: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_word(p, "\\ \\ "); break; case LIST_inset: - if (MDOC_BODY == n->type && n->parent->head->nchild) + if (n->type == ROFFT_BODY && n->parent->head->nchild) term_word(p, "\\ "); break; default: @@ -758,7 +745,7 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_diag: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) term_fontpush(p, TERMFONT_BOLD); break; default: @@ -776,23 +763,23 @@ termp_it_pre(DECL_ARGS) case LIST_enum: /* * Weird special case. - * Very narrow enum lists actually hang. + * Some very narrow lists actually hang. */ - if (width == term_len(p, 2)) - p->flags |= TERMP_HANG; /* FALLTHROUGH */ case LIST_bullet: /* FALLTHROUGH */ case LIST_dash: /* FALLTHROUGH */ case LIST_hyphen: - if (MDOC_HEAD != n->type) + if (width <= (int)term_len(p, 2)) + p->flags |= TERMP_HANG; + if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK; p->trailspace = 1; break; case LIST_hang: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; /* @@ -811,7 +798,7 @@ termp_it_pre(DECL_ARGS) p->trailspace = 1; break; case LIST_tag: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK | TERMP_BRIND; @@ -821,7 +808,7 @@ termp_it_pre(DECL_ARGS) p->flags |= TERMP_DANGLE; break; case LIST_column: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; if (NULL == n->next) { @@ -834,7 +821,7 @@ termp_it_pre(DECL_ARGS) break; case LIST_diag: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 1; @@ -858,7 +845,7 @@ termp_it_pre(DECL_ARGS) * don't want to recalculate rmargin and offsets when * using `Bd' or `Bl' within `-hang' overstep lists. */ - if (MDOC_HEAD == n->type && + if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child && (MDOC_Bl == n->next->child->tok || @@ -874,8 +861,7 @@ termp_it_pre(DECL_ARGS) case LIST_hyphen: /* FALLTHROUGH */ case LIST_tag: - assert(width); - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) p->rmargin = p->offset + width; else p->offset += width; @@ -887,7 +873,7 @@ termp_it_pre(DECL_ARGS) * XXX - this behaviour is not documented: the * right-most column is filled to the right margin. */ - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; if (NULL == n->next && p->rmargin < p->maxrmargin) p->rmargin = p->maxrmargin; @@ -901,7 +887,7 @@ termp_it_pre(DECL_ARGS) * HEAD character (temporarily bold, in some cases). */ - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) switch (type) { case LIST_bullet: term_fontpush(p, TERMFONT_BOLD); @@ -939,11 +925,11 @@ termp_it_pre(DECL_ARGS) case LIST_hyphen: /* FALLTHROUGH */ case LIST_enum: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) return(0); break; case LIST_column: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) return(0); break; default: @@ -958,7 +944,7 @@ termp_it_post(DECL_ARGS) { enum mdoc_list type; - if (MDOC_BLOCK == n->type) + if (n->type == ROFFT_BLOCK) return; type = n->parent->parent->parent->norm->Bl.type; @@ -969,11 +955,11 @@ termp_it_post(DECL_ARGS) case LIST_diag: /* FALLTHROUGH */ case LIST_inset: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_newln(p); break; case LIST_column: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_flushln(p); break; default: @@ -997,12 +983,12 @@ termp_nm_pre(DECL_ARGS) { const char *cp; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { p->flags |= TERMP_PREKEEP; return(1); } - if (MDOC_BODY == n->type) { + if (n->type == ROFFT_BODY) { if (NULL == n->child) return(0); p->flags |= TERMP_NOSPACE; @@ -1021,17 +1007,17 @@ termp_nm_pre(DECL_ARGS) if (NULL == n->child && NULL == meta->name) return(0); - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) synopsis_pre(p, n->parent); - if (MDOC_HEAD == n->type && + if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child) { p->flags |= TERMP_NOSPACE | TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 1; p->rmargin = p->offset + term_len(p, 1); if (NULL == n->child) { p->rmargin += term_strlen(p, meta->name); - } else if (MDOC_TEXT == n->child->type) { + } else if (n->child->type == ROFFT_TEXT) { p->rmargin += term_strlen(p, n->child->string); if (n->child->next) p->flags |= TERMP_HANG; @@ -1051,14 +1037,14 @@ static void termp_nm_post(DECL_ARGS) { - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP); - } else if (MDOC_HEAD == n->type && + } else if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); p->trailspace = 0; - } else if (MDOC_BODY == n->type && n->child) + } else if (n->type == ROFFT_BODY && n->child != NULL) term_flushln(p); } @@ -1066,12 +1052,13 @@ static int termp_fl_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\-"); if ( ! (n->nchild == 0 && (n->next == NULL || - n->next->type == MDOC_TEXT || + n->next->type == ROFFT_TEXT || n->next->flags & MDOC_LINE))) p->flags |= TERMP_NOSPACE; @@ -1104,9 +1091,6 @@ termp_an_pre(DECL_ARGS) return(0); } - if (n->child == NULL) - return(0); - if (p->flags & TERMP_SPLIT) term_newln(p); @@ -1131,7 +1115,7 @@ termp_rs_pre(DECL_ARGS) if (SEC_SEE_ALSO != n->sec) return(1); - if (MDOC_BLOCK == n->type && n->prev) + if (n->type == ROFFT_BLOCK && n->prev != NULL) term_vspace(p); return(1); } @@ -1227,7 +1211,7 @@ static int termp_nd_pre(DECL_ARGS) { - if (n->type == MDOC_BODY) + if (n->type == ROFFT_BODY) term_word(p, "\\(en"); return(1); } @@ -1236,14 +1220,14 @@ static int termp_bl_pre(DECL_ARGS) { - return(MDOC_HEAD != n->type); + return(n->type != ROFFT_HEAD); } static void termp_bl_post(DECL_ARGS) { - if (MDOC_BLOCK == n->type) + if (n->type == ROFFT_BLOCK) term_newln(p); } @@ -1254,7 +1238,7 @@ termp_xr_pre(DECL_ARGS) if (NULL == (n = n->child)) return(0); - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_word(p, n->string); if (NULL == (n = n->next)) @@ -1264,7 +1248,7 @@ termp_xr_pre(DECL_ARGS) term_word(p, "("); p->flags |= TERMP_NOSPACE; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_word(p, n->string); p->flags |= TERMP_NOSPACE; @@ -1279,7 +1263,7 @@ termp_xr_pre(DECL_ARGS) * macro combos). */ static void -synopsis_pre(struct termp *p, const struct mdoc_node *n) +synopsis_pre(struct termp *p, const struct roff_node *n) { /* * Obviously, if we're not in a SYNOPSIS or no prior macros @@ -1334,13 +1318,13 @@ static int termp_vt_pre(DECL_ARGS) { - if (MDOC_ELEM == n->type) { + if (n->type == ROFFT_ELEM) { synopsis_pre(p, n); return(termp_under_pre(p, pair, meta, n)); - } else if (MDOC_BLOCK == n->type) { + } else if (n->type == ROFFT_BLOCK) { synopsis_pre(p, n); return(1); - } else if (MDOC_HEAD == n->type) + } else if (n->type == ROFFT_HEAD) return(0); return(termp_under_pre(p, pair, meta, n)); @@ -1350,6 +1334,7 @@ static int termp_bold_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); return(1); } @@ -1374,24 +1359,32 @@ termp_sh_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: /* * Vertical space before sections, except * when the previous section was empty. */ if (n->prev == NULL || - MDOC_Sh != n->prev->tok || + n->prev->tok != MDOC_Sh || (n->prev->body != NULL && n->prev->body->child != NULL)) term_vspace(p); break; - case MDOC_HEAD: + case ROFFT_HEAD: term_fontpush(p, TERMFONT_BOLD); break; - case MDOC_BODY: + case ROFFT_BODY: p->offset = term_len(p, p->defindent); - if (SEC_AUTHORS == n->sec) + switch (n->sec) { + case SEC_DESCRIPTION: + fn_prio = 0; + break; + case SEC_AUTHORS: p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT); + break; + default: + break; + } break; default: break; @@ -1404,10 +1397,10 @@ termp_sh_post(DECL_ARGS) { switch (n->type) { - case MDOC_HEAD: + case ROFFT_HEAD: term_newln(p); break; - case MDOC_BODY: + case ROFFT_BODY: term_newln(p); p->offset = 0; break; @@ -1446,7 +1439,7 @@ static int termp_d1_pre(DECL_ARGS) { - if (MDOC_BLOCK != n->type) + if (n->type != ROFFT_BLOCK) return(1); term_newln(p); p->offset += term_len(p, p->defindent + 1); @@ -1482,11 +1475,16 @@ termp_fn_pre(DECL_ARGS) p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG; } - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); + if (n->sec == SEC_DESCRIPTION) { + if ( ! tag_get(n->string, 0, ++fn_prio)) + tag_put(n->string, 0, fn_prio, p->line); + } + if (pretty) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); @@ -1499,7 +1497,7 @@ termp_fn_pre(DECL_ARGS) p->flags |= TERMP_NOSPACE; for (n = n->next; n; n = n->next) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_UNDER); if (pretty) p->flags |= TERMP_NBRWORD; @@ -1527,7 +1525,7 @@ termp_fn_pre(DECL_ARGS) static int termp_fa_pre(DECL_ARGS) { - const struct mdoc_node *nn; + const struct roff_node *nn; if (n->parent->tok != MDOC_Fo) { term_fontpush(p, TERMFONT_UNDER); @@ -1553,12 +1551,13 @@ static int termp_bd_pre(DECL_ARGS) { size_t tabwidth, lm, len, rm, rmax; - struct mdoc_node *nn; + struct roff_node *nn; + int offset; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { print_bvspace(p, n, n); return(1); - } else if (MDOC_HEAD == n->type) + } else if (n->type == ROFFT_HEAD) return(0); /* Handle the -offset argument. */ @@ -1570,8 +1569,13 @@ termp_bd_pre(DECL_ARGS) p->offset += term_len(p, p->defindent + 1); else if ( ! strcmp(n->norm->Bd.offs, "indent-two")) p->offset += term_len(p, (p->defindent + 1) * 2); - else - p->offset += a2width(p, n->norm->Bd.offs); + else { + offset = a2width(p, n->norm->Bd.offs); + if (offset < 0 && (size_t)(-offset) > p->offset) + p->offset = 0; + else if (offset < SHRT_MAX) + p->offset += offset; + } /* * If -ragged or -filled are specified, the block does nothing @@ -1597,7 +1601,7 @@ termp_bd_pre(DECL_ARGS) for (nn = n->child; nn; nn = nn->next) { if (DISP_centered == n->norm->Bd.type) { - if (MDOC_TEXT == nn->type) { + if (nn->type == ROFFT_TEXT) { len = term_strlen(p, nn->string); p->offset = len >= rm ? 0 : lm + len >= rm ? rm - len : @@ -1632,7 +1636,8 @@ termp_bd_pre(DECL_ARGS) default: break; } - if (nn->next && nn->next->line == nn->line) + if (p->flags & TERMP_NONEWLINE || + (nn->next && ! (nn->next->flags & MDOC_LINE))) continue; term_flushln(p); p->flags |= TERMP_NOSPACE; @@ -1649,7 +1654,7 @@ termp_bd_post(DECL_ARGS) { size_t rm, rmax; - if (MDOC_BODY != n->type) + if (n->type != ROFFT_BODY) return; rm = p->rmargin; @@ -1734,7 +1739,8 @@ static void termp_pf_post(DECL_ARGS) { - p->flags |= TERMP_NOSPACE; + if ( ! (n->next == NULL || n->next->flags & MDOC_LINE)) + p->flags |= TERMP_NOSPACE; } static int @@ -1742,16 +1748,16 @@ termp_ss_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: term_newln(p); if (n->prev) term_vspace(p); break; - case MDOC_HEAD: + case ROFFT_HEAD: term_fontpush(p, TERMFONT_BOLD); p->offset = term_len(p, (p->defindent+1)/2); break; - case MDOC_BODY: + case ROFFT_BODY: p->offset = term_len(p, p->defindent); break; default: @@ -1765,7 +1771,7 @@ static void termp_ss_post(DECL_ARGS) { - if (n->type == MDOC_HEAD || n->type == MDOC_BODY) + if (n->type == ROFFT_HEAD || n->type == ROFFT_BODY) term_newln(p); } @@ -1814,24 +1820,34 @@ termp_in_post(DECL_ARGS) static int termp_sp_pre(DECL_ARGS) { - size_t i, len; + struct roffsu su; + int i, len; switch (n->tok) { case MDOC_sp: - len = n->child ? a2height(p, n->child->string) : 1; + if (n->child) { + if ( ! a2roffsu(n->child->string, &su, SCALE_VS)) + su.scale = 1.0; + len = term_vspan(p, &su); + } else + len = 1; break; case MDOC_br: len = 0; break; default: len = 1; + fn_prio = 0; break; } if (0 == len) term_newln(p); - for (i = 0; i < len; i++) - term_vspace(p); + else if (len < 0) + p->skipvsp -= len; + else + for (i = 0; i < len; i++) + term_vspace(p); return(0); } @@ -1847,15 +1863,15 @@ static int termp_quote_pre(DECL_ARGS) { - if (MDOC_BODY != n->type && MDOC_ELEM != n->type) + if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) return(1); switch (n->tok) { case MDOC_Ao: /* FALLTHROUGH */ case MDOC_Aq: - term_word(p, n->parent->prev != NULL && - n->parent->prev->tok == MDOC_An ? "<" : "\\(la"); + term_word(p, n->nchild == 1 && + n->child->tok == MDOC_Mt ? "<" : "\\(la"); break; case MDOC_Bro: /* FALLTHROUGH */ @@ -1874,7 +1890,7 @@ termp_quote_pre(DECL_ARGS) case MDOC_Do: /* FALLTHROUGH */ case MDOC_Dq: - term_word(p, "\\(lq"); + term_word(p, "\\(Lq"); break; case MDOC_En: if (NULL == n->norm->Es || @@ -1882,8 +1898,6 @@ termp_quote_pre(DECL_ARGS) return(1); term_word(p, n->norm->Es->child->string); break; - case MDOC_Eo: - break; case MDOC_Po: /* FALLTHROUGH */ case MDOC_Pq: @@ -1916,19 +1930,17 @@ static void termp_quote_post(DECL_ARGS) { - if (n->type != MDOC_BODY && n->type != MDOC_ELEM) + if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) return; - if ( ! (n->tok == MDOC_En || - (n->tok == MDOC_Eo && n->end == ENDBODY_SPACE))) - p->flags |= TERMP_NOSPACE; + p->flags |= TERMP_NOSPACE; switch (n->tok) { case MDOC_Ao: /* FALLTHROUGH */ case MDOC_Aq: - term_word(p, n->parent->prev != NULL && - n->parent->prev->tok == MDOC_An ? ">" : "\\(ra"); + term_word(p, n->nchild == 1 && + n->child->tok == MDOC_Mt ? ">" : "\\(ra"); break; case MDOC_Bro: /* FALLTHROUGH */ @@ -1947,18 +1959,16 @@ termp_quote_post(DECL_ARGS) case MDOC_Do: /* FALLTHROUGH */ case MDOC_Dq: - term_word(p, "\\(rq"); + term_word(p, "\\(Rq"); break; case MDOC_En: - if (NULL != n->norm->Es && - NULL != n->norm->Es->child && - NULL != n->norm->Es->child->next) { - p->flags |= TERMP_NOSPACE; + if (n->norm->Es == NULL || + n->norm->Es->child == NULL || + n->norm->Es->child->next == NULL) + p->flags &= ~TERMP_NOSPACE; + else term_word(p, n->norm->Es->child->next->string); - } break; - case MDOC_Eo: - break; case MDOC_Po: /* FALLTHROUGH */ case MDOC_Pq: @@ -1985,6 +1995,50 @@ termp_quote_post(DECL_ARGS) } static int +termp_eo_pre(DECL_ARGS) +{ + + if (n->type != ROFFT_BODY) + return(1); + + if (n->end == ENDBODY_NOT && + n->parent->head->child == NULL && + n->child != NULL && + n->child->end != ENDBODY_NOT) + term_word(p, "\\&"); + else if (n->end != ENDBODY_NOT ? n->child != NULL : + n->parent->head->child != NULL && (n->child != NULL || + (n->parent->tail != NULL && n->parent->tail->child != NULL))) + p->flags |= TERMP_NOSPACE; + + return(1); +} + +static void +termp_eo_post(DECL_ARGS) +{ + int body, tail; + + if (n->type != ROFFT_BODY) + return; + + if (n->end != ENDBODY_NOT) { + p->flags &= ~TERMP_NOSPACE; + return; + } + + body = n->child != NULL || n->parent->head->child != NULL; + tail = n->parent->tail != NULL && n->parent->tail->child != NULL; + + if (body && tail) + p->flags |= TERMP_NOSPACE; + else if ( ! (body || tail)) + term_word(p, "\\&"); + else if ( ! tail) + p->flags &= ~TERMP_NOSPACE; +} + +static int termp_fo_pre(DECL_ARGS) { size_t rmargin = 0; @@ -1992,10 +2046,10 @@ termp_fo_pre(DECL_ARGS) pretty = MDOC_SYNPRETTY & n->flags; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { synopsis_pre(p, n); return(1); - } else if (MDOC_BODY == n->type) { + } else if (n->type == ROFFT_BODY) { if (pretty) { rmargin = p->rmargin; p->rmargin = p->offset + term_len(p, 4); @@ -2030,7 +2084,7 @@ static void termp_fo_post(DECL_ARGS) { - if (MDOC_BODY != n->type) + if (n->type != ROFFT_BODY) return; p->flags |= TERMP_NOSPACE; @@ -2047,9 +2101,9 @@ static int termp_bf_pre(DECL_ARGS) { - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) return(0); - else if (MDOC_BODY != n->type) + else if (n->type != ROFFT_BODY) return(1); if (FONT_Em == n->norm->Bf.font) @@ -2127,7 +2181,7 @@ termp_li_pre(DECL_ARGS) static int termp_lk_pre(DECL_ARGS) { - const struct mdoc_node *link, *descr; + const struct roff_node *link, *descr; if (NULL == (link = n->child)) return(0); @@ -2155,11 +2209,11 @@ termp_bk_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: break; - case MDOC_HEAD: + case ROFFT_HEAD: return(0); - case MDOC_BODY: + case ROFFT_BODY: if (n->parent->args || 0 == n->prev->nchild) p->flags |= TERMP_PREKEEP; break; @@ -2175,7 +2229,7 @@ static void termp_bk_post(DECL_ARGS) { - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP); } @@ -2215,5 +2269,21 @@ termp_under_pre(DECL_ARGS) { term_fontpush(p, TERMFONT_UNDER); + return(1); +} + +static int +termp_tag_pre(DECL_ARGS) +{ + + if (n->child != NULL && + n->child->type == ROFFT_TEXT && + n->prev == NULL && + (n->parent->tok == MDOC_It || + (n->parent->tok == MDOC_Xo && + n->parent->parent->prev == NULL && + n->parent->parent->parent->tok == MDOC_It)) && + ! tag_get(n->child->string, 0, 1)) + tag_put(n->child->string, 0, 1, p->line); return(1); }