=================================================================== RCS file: /cvs/mandoc/mdoc_term.c,v retrieving revision 1.295 retrieving revision 1.304 diff -u -p -r1.295 -r1.304 --- mandoc/mdoc_term.c 2014/11/27 22:27:56 1.295 +++ mandoc/mdoc_term.c 2015/01/30 22:04:44 1.304 @@ -1,7 +1,7 @@ -/* $Id: mdoc_term.c,v 1.295 2014/11/27 22:27:56 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.304 2015/01/30 22:04:44 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 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -49,8 +50,7 @@ struct termact { 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 *, @@ -291,9 +291,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 @@ -526,30 +527,15 @@ 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)); } @@ -620,10 +606,10 @@ 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 mdoc_node *bl, *nn; + size_t ncols, dcol; + int i, offset, width; enum mdoc_list type; if (MDOC_BLOCK == n->type) { @@ -635,15 +621,46 @@ 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: @@ -698,43 +715,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. */ @@ -776,16 +765,16 @@ 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 (width <= (int)term_len(p, 2)) + p->flags |= TERMP_HANG; if (MDOC_HEAD != n->type) break; p->flags |= TERMP_NOBREAK; @@ -874,7 +863,6 @@ termp_it_pre(DECL_ARGS) case LIST_hyphen: /* FALLTHROUGH */ case LIST_tag: - assert(width); if (MDOC_HEAD == n->type) p->rmargin = p->offset + width; else @@ -995,6 +983,7 @@ termp_it_post(DECL_ARGS) static int termp_nm_pre(DECL_ARGS) { + const char *cp; if (MDOC_BLOCK == n->type) { p->flags |= TERMP_PREKEEP; @@ -1005,12 +994,15 @@ termp_nm_pre(DECL_ARGS) if (NULL == n->child) return(0); p->flags |= TERMP_NOSPACE; - p->offset += term_len(p, 1) + - (NULL == n->prev->child ? - term_strlen(p, meta->name) : - MDOC_TEXT == n->prev->child->type ? - term_strlen(p, n->prev->child->string) : - term_len(p, 5)); + cp = NULL; + if (n->prev->child != NULL) + cp = n->prev->child->string; + if (cp == NULL) + cp = meta->name; + if (cp == NULL) + p->offset += term_len(p, 6); + else + p->offset += term_len(p, 1) + term_strlen(p, cp); return(1); } @@ -1223,14 +1215,8 @@ static int termp_nd_pre(DECL_ARGS) { - if (MDOC_BODY != n->type) - return(1); - -#if defined(__OpenBSD__) || defined(__linux__) - term_word(p, "\\(en"); -#else - term_word(p, "\\(em"); -#endif + if (n->type == MDOC_BODY) + term_word(p, "\\(en"); return(1); } @@ -1556,6 +1542,7 @@ termp_bd_pre(DECL_ARGS) { size_t tabwidth, lm, len, rm, rmax; struct mdoc_node *nn; + int offset; if (MDOC_BLOCK == n->type) { print_bvspace(p, n, n); @@ -1572,8 +1559,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 @@ -1634,7 +1626,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; @@ -1736,7 +1729,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 @@ -1816,11 +1810,17 @@ termp_in_post(DECL_ARGS) static int termp_sp_pre(DECL_ARGS) { + struct roffsu su; size_t 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; @@ -1856,8 +1856,8 @@ termp_quote_pre(DECL_ARGS) 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 */ @@ -1929,8 +1929,8 @@ termp_quote_post(DECL_ARGS) 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 */