-/* $Id: term.c,v 1.168 2010/08/20 23:22:09 schwarze Exp $ */
+/* $Id: term.c,v 1.171 2010/09/15 14:36:16 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
p = calloc(1, sizeof(struct termp));
if (NULL == p) {
perror(NULL);
- exit(MANDOCLEVEL_SYSERR);
+ exit((int)MANDOCLEVEL_SYSERR);
}
p->enc = enc;
* Handle literal tab characters: collapse all
* subsequent tabs into a single huge set of spaces.
*/
- for (j = i; j < (int)p->col; j++) {
- if ('\t' != p->buf[j])
- break;
+ while (i < (int)p->col && '\t' == p->buf[i]) {
vend = (vis / p->tabwidth + 1) * p->tabwidth;
vbl += vend - vis;
vis = vend;
+ i++;
}
/*
*/
/* LINTED */
- for (jhy = 0; j < (int)p->col; j++) {
+ for (j = i, jhy = 0; j < (int)p->col; j++) {
if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j])
break;
p->overstep = 0;
}
- /*
- * Skip leading tabs, they were handled above.
- */
- while (i < (int)p->col && '\t' == p->buf[i])
- i++;
-
/* Write out the [remaining] word. */
for ( ; i < (int)p->col; i++) {
if (vend > bp && jhy > 0 && i > jhy)
term_word(struct termp *p, const char *word)
{
const char *sv, *seq;
- int sz;
size_t ssz;
enum roffdeco deco;
continue;
seq = ++word;
- sz = a2roffdeco(&deco, &seq, &ssz);
+ word += a2roffdeco(&deco, &seq, &ssz);
switch (deco) {
case (DECO_RESERVED):
break;
}
- word += sz;
if (DECO_NOSPACE == deco && '\0' == *word)
p->flags |= TERMP_NOSPACE;
}
p->buf = realloc(p->buf, p->maxcols);
if (NULL == p->buf) {
perror(NULL);
- exit(MANDOCLEVEL_SYSERR);
+ exit((int)MANDOCLEVEL_SYSERR);
}
}
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);
}