diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-09-21 22:33:42 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-09-21 22:33:42 +0000 |
commit | 7e083e7d1f3ed272a595c2fcf389689e668c0d5c (patch) | |
tree | d878c12e2679c5a15152fef9ee6f726f1016897e | |
parent | 9c69d1cb16a4cae16118eb197819c5f1a966c613 (diff) |
When calculating string lengths, resolve escape sequences and use
their actual lengths. Will improve vertical alignment in some
uncommon situations, for example when escape sequences occur in
list or column width strings or in .Nm block arguments in the SYNOPSIS.
From kristaps@.
-rw-r--r-- | usr.bin/mandoc/man_term.c | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/term.c | 54 |
2 files changed, 50 insertions, 10 deletions
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c index 9c3389d9b1f..074c3b7d257 100644 --- a/usr.bin/mandoc/man_term.c +++ b/usr.bin/mandoc/man_term.c @@ -1,4 +1,4 @@ -/* $Id: man_term.c,v 1.45 2010/07/25 18:05:54 schwarze Exp $ */ +/* $Id: man_term.c,v 1.46 2010/09/21 22:33:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -912,6 +912,10 @@ print_man_foot(struct termp *p, const void *arg) p->rmargin = p->maxrmargin - term_strlen(p, buf); p->offset = 0; + /* term_strlen() can return zero. */ + if (p->rmargin == p->maxrmargin) + p->rmargin--; + if (meta->source) term_word(p, meta->source); if (meta->source) diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index 4f307967d9b..c0a8918184a 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.49 2010/08/20 23:34:00 schwarze Exp $ */ +/* $Id: term.c,v 1.50 2010/09/21 22:33:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org> @@ -79,7 +79,7 @@ term_alloc(enum termenc enc) p = calloc(1, sizeof(struct termp)); if (NULL == p) { perror(NULL); - exit(MANDOCLEVEL_SYSERR); + exit((int)MANDOCLEVEL_SYSERR); } p->enc = enc; @@ -454,7 +454,6 @@ void term_word(struct termp *p, const char *word) { const char *sv, *seq; - int sz; size_t ssz; enum roffdeco deco; @@ -511,7 +510,7 @@ term_word(struct termp *p, const char *word) continue; seq = ++word; - sz = a2roffdeco(&deco, &seq, &ssz); + word += a2roffdeco(&deco, &seq, &ssz); switch (deco) { case (DECO_RESERVED): @@ -538,7 +537,6 @@ term_word(struct termp *p, const char *word) break; } - word += sz; if (DECO_NOSPACE == deco && '\0' == *word) p->flags |= TERMP_NOSPACE; } @@ -572,7 +570,7 @@ adjbuf(struct termp *p, size_t sz) p->buf = realloc(p->buf, p->maxcols); if (NULL == p->buf) { perror(NULL); - exit(MANDOCLEVEL_SYSERR); + exit((int)MANDOCLEVEL_SYSERR); } } @@ -641,10 +639,48 @@ term_len(const struct termp *p, size_t sz) size_t term_strlen(const struct termp *p, const char *cp) { - size_t sz; + size_t sz, ssz, rsz, i; + enum roffdeco d; + const char *seq, *rhs; - for (sz = 0; *cp; cp++) - sz += (*p->width)(p, *cp); + for (sz = 0; '\0' != *cp; ) + /* + * Account for escaped sequences within string length + * calculations. This follows the logic in term_word() + * as we must calculate the width of produced strings. + */ + if ('\\' == *cp) { + seq = ++cp; + cp += a2roffdeco(&d, &seq, &ssz); + + switch (d) { + case (DECO_RESERVED): + rhs = chars_res2str + (p->symtab, seq, ssz, &rsz); + break; + case (DECO_SPECIAL): + /* FALLTHROUGH */ + case (DECO_SSPECIAL): + rhs = chars_spec2str + (p->symtab, seq, ssz, &rsz); + + /* Allow for one-char escapes. */ + if (DECO_SSPECIAL != d || rhs) + break; + + rhs = seq; + rsz = ssz; + break; + default: + rhs = NULL; + break; + } + + if (rhs) + for (i = 0; i < rsz; i++) + sz += (*p->width)(p, *rhs++); + } else + sz += (*p->width)(p, *cp++); return(sz); } |