summaryrefslogtreecommitdiffstats
path: root/term.c
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2010-09-15 14:36:16 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2010-09-15 14:36:16 +0000
commitd314ff3f89a95ea238e50cfcbb6a6fc3848c56d2 (patch)
tree4d46e52e2868bfea5dec3c6f38ef479898448a47 /term.c
parentea02c27746628977c16bd9f8665b1ceed267c88f (diff)
downloadmandoc-d314ff3f89a95ea238e50cfcbb6a6fc3848c56d2.tar.gz
Allow string lengths to account for escapes. Now all calls to calculate
column width in -Tascii, -Tpdf, and -Tps will account for "more real" string lengths. Example: .Bl -tag -width \s[+123424]foo .It bar baz .El The size escape will be correctly tossed. .Bl -tag -width \(aqbar .It \(aqbar baz .El The \(aq will be correctly handled.
Diffstat (limited to 'term.c')
-rw-r--r--term.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/term.c b/term.c
index 1e0f0d33..afd809e7 100644
--- a/term.c
+++ b/term.c
@@ -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);
}