summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2010-09-21 22:33:42 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2010-09-21 22:33:42 +0000
commit7e083e7d1f3ed272a595c2fcf389689e668c0d5c (patch)
treed878c12e2679c5a15152fef9ee6f726f1016897e
parent9c69d1cb16a4cae16118eb197819c5f1a966c613 (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.c6
-rw-r--r--usr.bin/mandoc/term.c54
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);
}