=================================================================== RCS file: /cvs/mandoc/mdoc_term.c,v retrieving revision 1.265 retrieving revision 1.286 diff -u -p -r1.265 -r1.286 --- mandoc/mdoc_term.c 2014/04/20 19:40:13 1.265 +++ mandoc/mdoc_term.c 2014/10/20 15:50:24 1.286 @@ -1,4 +1,4 @@ -/* $Id: mdoc_term.c,v 1.265 2014/04/20 19:40:13 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.286 2014/10/20 15:50:24 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze @@ -16,9 +16,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include @@ -30,6 +28,7 @@ #include #include "mandoc.h" +#include "mandoc_aux.h" #include "out.h" #include "term.h" #include "mdoc.h" @@ -66,7 +65,6 @@ static void synopsis_pre(struct termp *, static void termp____post(DECL_ARGS); static void termp__t_post(DECL_ARGS); -static void termp_an_post(DECL_ARGS); static void termp_bd_post(DECL_ARGS); static void termp_bk_post(DECL_ARGS); static void termp_bl_post(DECL_ARGS); @@ -94,6 +92,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_es_pre(DECL_ARGS); static int termp_ex_pre(DECL_ARGS); static int termp_fa_pre(DECL_ARGS); static int termp_fd_pre(DECL_ARGS); @@ -138,7 +137,7 @@ static const struct termact termacts[MDOC_MAX] = { { NULL, NULL }, /* El */ { termp_it_pre, termp_it_post }, /* It */ { termp_under_pre, NULL }, /* Ad */ - { termp_an_pre, termp_an_post }, /* An */ + { termp_an_pre, NULL }, /* An */ { termp_under_pre, NULL }, /* Ar */ { termp_cd_pre, NULL }, /* Cd */ { termp_bold_pre, NULL }, /* Cm */ @@ -157,7 +156,7 @@ static const struct termact termacts[MDOC_MAX] = { { termp_nd_pre, NULL }, /* Nd */ { termp_nm_pre, termp_nm_post }, /* Nm */ { termp_quote_pre, termp_quote_post }, /* Op */ - { NULL, NULL }, /* Ot */ + { termp_ft_pre, NULL }, /* Ot */ { termp_under_pre, NULL }, /* Pa */ { termp_rv_pre, NULL }, /* Rv */ { NULL, NULL }, /* St */ @@ -227,7 +226,7 @@ static const struct termact termacts[MDOC_MAX] = { { NULL, NULL }, /* Ek */ { termp_bt_pre, NULL }, /* Bt */ { NULL, NULL }, /* Hf */ - { NULL, NULL }, /* Fr */ + { termp_under_pre, NULL }, /* Fr */ { termp_ud_pre, NULL }, /* Ud */ { NULL, termp_lb_post }, /* Lb */ { termp_sp_pre, NULL }, /* Lp */ @@ -237,8 +236,8 @@ static const struct termact termacts[MDOC_MAX] = { { termp_quote_pre, termp_quote_post }, /* Bro */ { NULL, NULL }, /* Brc */ { NULL, termp____post }, /* %C */ - { NULL, NULL }, /* Es */ /* TODO */ - { NULL, NULL }, /* En */ /* TODO */ + { termp_es_pre, NULL }, /* Es */ + { termp_quote_pre, termp_quote_post }, /* En */ { termp_xx_pre, NULL }, /* Dx */ { NULL, termp____post }, /* %Q */ { termp_sp_pre, NULL }, /* br */ @@ -252,31 +251,44 @@ static const struct termact termacts[MDOC_MAX] = { void terminal_mdoc(void *arg, const struct mdoc *mdoc) { - const struct mdoc_node *n; const struct mdoc_meta *meta; + struct mdoc_node *n; struct termp *p; p = (struct termp *)arg; - if (0 == p->defindent) - p->defindent = 5; - p->overstep = 0; - p->maxrmargin = p->defrmargin; + p->rmargin = p->maxrmargin = p->defrmargin; p->tabwidth = term_len(p, 5); if (NULL == p->symtab) p->symtab = mchars_alloc(); - n = mdoc_node(mdoc); + n = mdoc_node(mdoc)->child; meta = mdoc_meta(mdoc); - term_begin(p, print_mdoc_head, print_mdoc_foot, meta); - - if (n->child) - print_mdoc_nodelist(p, NULL, meta, n->child); - - term_end(p); + 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); + term_newln(p); + break; + } + n = n->next; + } + } else { + if (p->defindent == 0) + p->defindent = 5; + term_begin(p, print_mdoc_head, print_mdoc_foot, meta); + if (n != NULL) { + if (n->tok != MDOC_Sh) + term_vspace(p); + print_mdoc_nodelist(p, NULL, meta, n); + } + term_end(p); + } } static void @@ -332,7 +344,11 @@ print_mdoc_node(DECL_ARGS) p->flags |= TERMP_NOSPACE; break; case MDOC_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: term_tbl(p, n->span); @@ -441,9 +457,9 @@ print_mdoc_foot(struct termp *p, const void *arg) static void print_mdoc_head(struct termp *p, const void *arg) { - char buf[BUFSIZ], title[BUFSIZ]; - size_t buflen, titlen; - const struct mdoc_meta *meta; + const struct mdoc_meta *meta; + char *volume, *title; + size_t vollen, titlen; meta = (const struct mdoc_meta *)arg; @@ -460,39 +476,37 @@ print_mdoc_head(struct termp *p, const void *arg) * switches on the manual section. */ - p->offset = 0; - p->rmargin = p->maxrmargin; - assert(meta->vol); - strlcpy(buf, meta->vol, BUFSIZ); - buflen = term_strlen(p, buf); + if (NULL == meta->arch) + volume = mandoc_strdup(meta->vol); + else + mandoc_asprintf(&volume, "%s (%s)", + meta->vol, meta->arch); + vollen = term_strlen(p, volume); - if (meta->arch) { - strlcat(buf, " (", BUFSIZ); - strlcat(buf, meta->arch, BUFSIZ); - strlcat(buf, ")", BUFSIZ); - } - - snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec); + if (NULL == meta->msec) + title = mandoc_strdup(meta->title); + else + mandoc_asprintf(&title, "%s(%s)", + meta->title, meta->msec); titlen = term_strlen(p, title); p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; p->trailspace = 1; p->offset = 0; - p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ? - (p->maxrmargin - - term_strlen(p, buf) + term_len(p, 1)) / 2 : - p->maxrmargin - buflen; + p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ? + (p->maxrmargin - vollen + term_len(p, 1)) / 2 : + p->maxrmargin - vollen; term_word(p, title); term_flushln(p); p->flags |= TERMP_NOSPACE; p->offset = p->rmargin; - p->rmargin = p->offset + buflen + titlen < p->maxrmargin ? + p->rmargin = p->offset + vollen + titlen < p->maxrmargin ? p->maxrmargin - titlen : p->maxrmargin; - term_word(p, buf); + term_word(p, volume); term_flushln(p); p->flags &= ~TERMP_NOBREAK; @@ -508,6 +522,8 @@ print_mdoc_head(struct termp *p, const void *arg) p->flags &= ~TERMP_NOSPACE; p->offset = 0; p->rmargin = p->maxrmargin; + free(title); + free(volume); } static size_t @@ -529,8 +545,10 @@ 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)) { SCALE_HS_INIT(&su, term_strlen(p, v)); + su.scale /= term_strlen(p, "0"); + } return(term_hspan(p, &su)); } @@ -548,8 +566,10 @@ a2offs(const struct termp *p, const char *v) return(term_len(p, p->defindent + 1)); else if (0 == strcmp(v, "indent-two")) return(term_len(p, (p->defindent + 1) * 2)); - else if ( ! a2roffsu(v, &su, SCALE_MAX)) + else if ( ! a2roffsu(v, &su, SCALE_MAX)) { SCALE_HS_INIT(&su, term_strlen(p, v)); + su.scale /= term_strlen(p, "0"); + } return(term_hspan(p, &su)); } @@ -746,7 +766,7 @@ termp_it_pre(DECL_ARGS) term_word(p, "\\ \\ "); break; case LIST_inset: - if (MDOC_BODY == n->type) + if (MDOC_BODY == n->type && n->parent->head->nchild) term_word(p, "\\ "); break; default: @@ -800,7 +820,8 @@ termp_it_pre(DECL_ARGS) * the "overstep" effect in term_flushln() and treat * this as a `-ohang' list instead. */ - if (n->next->child && + if (NULL != n->next && + NULL != n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) break; @@ -856,7 +877,9 @@ 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 && n->next->child && + if (MDOC_HEAD == n->type && + NULL != n->next && + NULL != n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) break; @@ -1021,7 +1044,8 @@ termp_nm_pre(DECL_ARGS) if (MDOC_HEAD == n->type) synopsis_pre(p, n->parent); - if (MDOC_HEAD == n->type && n->next->child) { + if (MDOC_HEAD == n->type && + 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); @@ -1049,7 +1073,8 @@ termp_nm_post(DECL_ARGS) if (MDOC_BLOCK == n->type) { p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP); - } else if (MDOC_HEAD == n->type && n->next->child) { + } else if (MDOC_HEAD == n->type && + NULL != n->next && NULL != n->next->child) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); p->trailspace = 0; @@ -1064,10 +1089,11 @@ termp_fl_pre(DECL_ARGS) term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\-"); - if (n->child) + if ( ! (n->nchild == 0 && + (n->next == NULL || + n->next->type == MDOC_TEXT || + n->next->flags & MDOC_LINE))) p->flags |= TERMP_NOSPACE; - else if (n->next && n->next->line == n->line) - p->flags |= TERMP_NOSPACE; return(1); } @@ -1087,56 +1113,29 @@ static int termp_an_pre(DECL_ARGS) { - if (NULL == n->child) - return(1); + if (n->norm->An.auth == AUTH_split) { + p->flags &= ~TERMP_NOSPLIT; + p->flags |= TERMP_SPLIT; + return(0); + } + if (n->norm->An.auth == AUTH_nosplit) { + p->flags &= ~TERMP_SPLIT; + p->flags |= TERMP_NOSPLIT; + return(0); + } - /* - * If not in the AUTHORS section, `An -split' will cause - * newlines to occur before the author name. If in the AUTHORS - * section, by default, the first `An' invocation is nosplit, - * then all subsequent ones, regardless of whether interspersed - * with other macros/text, are split. -split, in this case, - * will override the condition of the implied first -nosplit. - */ + if (n->child == NULL) + return(0); - if (n->sec == SEC_AUTHORS) { - if ( ! (TERMP_ANPREC & p->flags)) { - if (TERMP_SPLIT & p->flags) - term_newln(p); - return(1); - } - if (TERMP_NOSPLIT & p->flags) - return(1); + if (p->flags & TERMP_SPLIT) term_newln(p); - return(1); - } - if (TERMP_SPLIT & p->flags) - term_newln(p); + if (n->sec == SEC_AUTHORS && ! (p->flags & TERMP_NOSPLIT)) + p->flags |= TERMP_SPLIT; return(1); } -static void -termp_an_post(DECL_ARGS) -{ - - if (n->child) { - if (SEC_AUTHORS == n->sec) - p->flags |= TERMP_ANPREC; - return; - } - - if (AUTH_split == n->norm->An.auth) { - p->flags &= ~TERMP_NOSPLIT; - p->flags |= TERMP_SPLIT; - } else if (AUTH_nosplit == n->norm->An.auth) { - p->flags &= ~TERMP_SPLIT; - p->flags |= TERMP_NOSPLIT; - } - -} - static int termp_ns_pre(DECL_ARGS) { @@ -1163,33 +1162,42 @@ termp_rv_pre(DECL_ARGS) int nchild; term_newln(p); - term_word(p, "The"); nchild = n->nchild; - for (n = n->child; n; n = n->next) { - term_fontpush(p, TERMFONT_BOLD); - term_word(p, n->string); - term_fontpop(p); + if (nchild > 0) { + term_word(p, "The"); - p->flags |= TERMP_NOSPACE; - term_word(p, "()"); + for (n = n->child; n; n = n->next) { + term_fontpush(p, TERMFONT_BOLD); + term_word(p, n->string); + term_fontpop(p); - if (nchild > 2 && n->next) { p->flags |= TERMP_NOSPACE; - term_word(p, ","); + term_word(p, "()"); + + if (n->next == NULL) + continue; + + if (nchild > 2) { + p->flags |= TERMP_NOSPACE; + term_word(p, ","); + } + if (n->next->next == NULL) + term_word(p, "and"); } - if (n->next && NULL == n->next->next) - term_word(p, "and"); - } + if (nchild > 1) + term_word(p, "functions return"); + else + term_word(p, "function returns"); - if (nchild > 1) - term_word(p, "functions return"); - else - term_word(p, "function returns"); + term_word(p, "the value\\~0 if successful;"); + } else + term_word(p, "Upon successful completion," + " the value\\~0 is returned;"); - term_word(p, "the value 0 if successful; otherwise the " - "value -1 is returned and the global variable"); + term_word(p, "otherwise the value\\~\\-1 is returned" + " and the global variable"); term_fontpush(p, TERMFONT_UNDER); term_word(p, "errno"); @@ -1225,11 +1233,11 @@ termp_ex_pre(DECL_ARGS) } if (nchild > 1) - term_word(p, "utilities exit"); + term_word(p, "utilities exit\\~0"); else - term_word(p, "utility exits"); + term_word(p, "utility exits\\~0"); - term_word(p, "0 on success, and >0 if an error occurs."); + term_word(p, "on success, and\\~>0 if an error occurs."); p->flags |= TERMP_SENTENCE; return(0); @@ -1567,7 +1575,7 @@ termp_fa_pre(DECL_ARGS) static int termp_bd_pre(DECL_ARGS) { - size_t tabwidth, rm, rmax; + size_t tabwidth, lm, len, rm, rmax; struct mdoc_node *nn; if (MDOC_BLOCK == n->type) { @@ -1588,18 +1596,29 @@ termp_bd_pre(DECL_ARGS) */ if (DISP_literal != n->norm->Bd.type && - DISP_unfilled != n->norm->Bd.type) + DISP_unfilled != n->norm->Bd.type && + DISP_centered != n->norm->Bd.type) return(1); tabwidth = p->tabwidth; if (DISP_literal == n->norm->Bd.type) p->tabwidth = term_len(p, 8); + lm = p->offset; rm = p->rmargin; rmax = p->maxrmargin; p->rmargin = p->maxrmargin = TERM_MAXMARGIN; for (nn = n->child; nn; nn = nn->next) { + if (DISP_centered == n->norm->Bd.type) { + if (MDOC_TEXT == nn->type) { + len = term_strlen(p, nn->string); + p->offset = len >= rm ? 0 : + lm + len >= rm ? rm - len : + (lm + rm - len) / 2; + } else + p->offset = lm; + } print_mdoc_node(p, pair, meta, nn); /* * If the printed node flushes its own line, then we @@ -1746,6 +1765,9 @@ termp_ss_pre(DECL_ARGS) term_fontpush(p, TERMFONT_BOLD); p->offset = term_len(p, (p->defindent+1)/2); break; + case MDOC_BODY: + p->offset = term_len(p, p->defindent); + break; default: break; } @@ -1757,7 +1779,7 @@ static void termp_ss_post(DECL_ARGS) { - if (MDOC_HEAD == n->type) + if (n->type == MDOC_HEAD || n->type == MDOC_BODY) term_newln(p); } @@ -1829,6 +1851,13 @@ termp_sp_pre(DECL_ARGS) } static int +termp_es_pre(DECL_ARGS) +{ + + return(0); +} + +static int termp_quote_pre(DECL_ARGS) { @@ -1860,6 +1889,12 @@ termp_quote_pre(DECL_ARGS) case MDOC_Dq: term_word(p, "\\(lq"); break; + case MDOC_En: + if (NULL == n->norm->Es || + NULL == n->norm->Es->child) + return(1); + term_word(p, n->norm->Es->child->string); + break; case MDOC_Eo: break; case MDOC_Po: @@ -1897,7 +1932,8 @@ termp_quote_post(DECL_ARGS) if (MDOC_BODY != n->type && MDOC_ELEM != n->type) return; - p->flags |= TERMP_NOSPACE; + if (MDOC_En != n->tok) + p->flags |= TERMP_NOSPACE; switch (n->tok) { case MDOC_Ao: @@ -1924,6 +1960,14 @@ termp_quote_post(DECL_ARGS) case MDOC_Dq: 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; + term_word(p, n->norm->Es->child->next->string); + } + break; case MDOC_Eo: break; case MDOC_Po: @@ -2033,13 +2077,15 @@ static int termp_sm_pre(DECL_ARGS) { - assert(n->child && MDOC_TEXT == n->child->type); - if (0 == strcmp("on", n->child->string)) { - if (p->col) - p->flags &= ~TERMP_NOSPACE; + if (NULL == n->child) + p->flags ^= TERMP_NONOSPACE; + else if (0 == strcmp("on", n->child->string)) p->flags &= ~TERMP_NONOSPACE; - } else + else p->flags |= TERMP_NONOSPACE; + + if (p->col && ! (TERMP_NONOSPACE & p->flags)) + p->flags &= ~TERMP_NOSPACE; return(0); }