-/* $Id: term.c,v 1.161 2010/07/16 22:33:30 kristaps Exp $ */
+/* $Id: term.c,v 1.169 2010/08/20 23:34:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
#include "term.h"
#include "main.h"
-static void spec(struct termp *, const char *, size_t);
+static void spec(struct termp *, enum roffdeco,
+ const char *, size_t);
static void res(struct termp *, const char *, size_t);
-static void buffera(struct termp *, const char *, size_t);
static void bufferc(struct termp *, char);
static void adjbuf(struct termp *p, size_t);
static void encode(struct termp *, const char *, size_t);
p = calloc(1, sizeof(struct termp));
if (NULL == p) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(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)
if ('\t' == p->buf[i])
break;
if (' ' == p->buf[i]) {
- while (' ' == p->buf[i]) {
- vbl += (*p->width)(p, p->buf[i]);
+ j = i;
+ while (' ' == p->buf[i])
i++;
- }
+ vbl += (i - j) * (*p->width)(p, ' ');
break;
}
if (ASCII_NBRSP == p->buf[i]) {
vis = vend;
}
+ /*
+ * If there was trailing white space, it was not printed;
+ * so reset the cursor position accordingly.
+ */
+ vis -= vbl;
+
p->col = 0;
p->overstep = 0;
static void
-spec(struct termp *p, const char *word, size_t len)
+spec(struct termp *p, enum roffdeco d, const char *word, size_t len)
{
const char *rhs;
size_t sz;
rhs = chars_spec2str(p->symtab, word, len, &sz);
if (rhs)
encode(p, rhs, sz);
+ else if (DECO_SSPECIAL == d)
+ encode(p, word, len);
}
if ( ! (p->flags & TERMP_NONOSPACE))
p->flags &= ~TERMP_NOSPACE;
+ else
+ p->flags |= TERMP_NOSPACE;
p->flags &= ~TERMP_SENTENCE;
- /* FIXME: use strcspn. */
-
while (*word) {
- if ('\\' != *word) {
- encode(p, word, 1);
- word++;
+ if ((ssz = strcspn(word, "\\")) > 0)
+ encode(p, word, ssz);
+
+ word += ssz;
+ if ('\\' != *word)
continue;
- }
seq = ++word;
sz = a2roffdeco(&deco, &seq, &ssz);
res(p, seq, ssz);
break;
case (DECO_SPECIAL):
- spec(p, seq, ssz);
+ /* FALLTHROUGH */
+ case (DECO_SSPECIAL):
+ spec(p, deco, seq, ssz);
break;
case (DECO_BOLD):
term_fontrepl(p, TERMFONT_BOLD);
* Note that we don't process the pipe: the parser sees it as
* punctuation, but we don't in terms of typography.
*/
- if (sv[0] && 0 == sv[1])
+ if (sv[0] && '\0' == sv[1])
switch (sv[0]) {
case('('):
/* FALLTHROUGH */
p->buf = realloc(p->buf, p->maxcols);
if (NULL == p->buf) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(MANDOCLEVEL_SYSERR);
}
}
-static void
-buffera(struct termp *p, const char *word, size_t sz)
-{
-
- if (p->col + sz >= p->maxcols)
- adjbuf(p, p->col + sz);
-
- memcpy(&p->buf[(int)p->col], word, sz);
- p->col += sz;
-}
-
-
static void
bufferc(struct termp *p, char c)
{
*/
if (TERMFONT_NONE == (f = term_fonttop(p))) {
- buffera(p, word, sz);
+ if (p->col + sz >= p->maxcols)
+ adjbuf(p, p->col + sz);
+ memcpy(&p->buf[(int)p->col], word, sz);
+ p->col += sz;
return;
}
+ /* Pre-buffer, assuming worst-case. */
+
+ if (p->col + 1 + (sz * 3) >= p->maxcols)
+ adjbuf(p, p->col + 1 + (sz * 3));
+
for (i = 0; i < (int)sz; i++) {
if ( ! isgraph((u_char)word[i])) {
- bufferc(p, word[i]);
+ p->buf[(int)p->col++] = word[i];
continue;
}
if (TERMFONT_UNDER == f)
- bufferc(p, '_');
+ p->buf[(int)p->col++] = '_';
else
- bufferc(p, word[i]);
+ p->buf[(int)p->col++] = word[i];
- bufferc(p, 8);
- bufferc(p, word[i]);
+ p->buf[(int)p->col++] = 8;
+ p->buf[(int)p->col++] = word[i];
}
}