diff options
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | man_term.c | 4 | ||||
-rw-r--r-- | term.c | 48 |
3 files changed, 46 insertions, 11 deletions
@@ -172,11 +172,6 @@ Several areas can be cleaned up to make mandoc even faster. These are * structural issues ************************************************************************ -- rendering frontend code can calculate widths only for plain strings, - not for strings containing escape sequences. For example, this - hinders calculation of the indent required for .Nm \&[ in text(1). - comments from kristaps@ Wed, 21 Jul 2010 23:26:08 +0200 - - another example of the same problem: .Bl -tag -width "\eD{format}XX" -compact in OpenBSD ksh(1) gives the wrong width @@ -916,6 +916,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) @@ -458,7 +458,6 @@ void term_word(struct termp *p, const char *word) { const char *sv, *seq; - int sz; size_t ssz; enum roffdeco deco; @@ -515,7 +514,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): @@ -542,7 +541,6 @@ term_word(struct termp *p, const char *word) break; } - word += sz; if (DECO_NOSPACE == deco && '\0' == *word) p->flags |= TERMP_NOSPACE; } @@ -645,10 +643,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); } |