=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.152 retrieving revision 1.164 diff -u -p -r1.152 -r1.164 --- mandoc/term.c 2010/06/28 09:48:44 1.152 +++ mandoc/term.c 2010/07/25 22:56:47 1.164 @@ -1,6 +1,7 @@ -/* $Id: term.c,v 1.152 2010/06/28 09:48:44 kristaps Exp $ */ +/* $Id: term.c,v 1.164 2010/07/25 22:56:47 kristaps Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons + * Copyright (c) 2010 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -33,7 +34,8 @@ #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); @@ -161,21 +163,17 @@ term_flushln(struct termp *p) */ vbl = p->flags & TERMP_NOLPAD ? 0 : p->offset; - /* - * FIXME: if bp is zero, we still output the first word before - * breaking the line. - */ - vis = vend = i = 0; - while (i < (int)p->col) { + while (i < (int)p->col) { /* - * Handle literal tab characters. + * 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; - vend = (vis/p->tabwidth+1)*p->tabwidth; + vend = (vis / p->tabwidth + 1) * p->tabwidth; vbl += vend - vis; vis = vend; } @@ -191,13 +189,21 @@ term_flushln(struct termp *p) for (jhy = 0; j < (int)p->col; j++) { if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j]) break; - if (8 != p->buf[j]) { - if (vend > vis && vend < bp && - ASCII_HYPH == p->buf[j]) - jhy = j; - vend++; - } else - vend--; + + /* Back over the the last printed character. */ + if (8 == p->buf[j]) { + assert(j); + vend -= (*p->width)(p, p->buf[j - 1]); + continue; + } + + /* Regular word. */ + /* Break at the hyphen point if we overrun. */ + if (vend > vis && vend < bp && + ASCII_HYPH == p->buf[j]) + jhy = j; + + vend += (*p->width)(p, p->buf[j]); } /* @@ -236,14 +242,14 @@ term_flushln(struct termp *p) if ('\t' == p->buf[i]) break; if (' ' == p->buf[i]) { - while (' ' == p->buf[i]) { - vbl++; + j = i; + while (' ' == p->buf[i]) i++; - } + vbl += (i - j) * (*p->width)(p, ' '); break; } if (ASCII_NBRSP == p->buf[i]) { - vbl++; + vbl += (*p->width)(p, ' '); continue; } @@ -258,12 +264,13 @@ term_flushln(struct termp *p) vbl = 0; } - if (ASCII_HYPH == p->buf[i]) + if (ASCII_HYPH == p->buf[i]) { (*p->letter)(p, '-'); - else + p->viscol += (*p->width)(p, '-'); + } else { (*p->letter)(p, p->buf[i]); - - p->viscol += 1; + p->viscol += (*p->width)(p, p->buf[i]); + } } vend += vbl; vis = vend; @@ -281,7 +288,7 @@ term_flushln(struct termp *p) if (TERMP_HANG & p->flags) { /* We need one blank after the tag. */ p->overstep = /* LINTED */ - vis - maxvis + 1; + vis - maxvis + (*p->width)(p, ' '); /* * Behave exactly the same way as groff: @@ -305,7 +312,8 @@ term_flushln(struct termp *p) /* Right-pad. */ if (maxvis > vis + /* LINTED */ - ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) { + ((TERMP_TWOSPACE & p->flags) ? + (*p->width)(p, ' ') : 0)) { p->viscol += maxvis - vis; (*p->advance)(p, maxvis - vis); vis += (maxvis - vis); @@ -353,14 +361,16 @@ term_vspace(struct termp *p) 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_a2ascii(p->symtab, word, len, &sz); + rhs = chars_spec2str(p->symtab, word, len, &sz); if (rhs) encode(p, rhs, sz); + else if (DECO_SSPECIAL == d) + encode(p, word, len); } @@ -370,7 +380,7 @@ res(struct termp *p, const char *word, size_t len) const char *rhs; size_t sz; - rhs = chars_a2res(p->symtab, word, len, &sz); + rhs = chars_res2str(p->symtab, word, len, &sz); if (rhs) encode(p, rhs, sz); } @@ -496,14 +506,13 @@ term_word(struct termp *p, const char *word) 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); @@ -513,7 +522,9 @@ term_word(struct termp *p, const char *word) 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); @@ -540,7 +551,7 @@ term_word(struct termp *p, const char *word) * 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 */ @@ -647,6 +658,7 @@ term_strlen(const struct termp *p, const char *cp) } +/* ARGSUSED */ size_t term_vspan(const struct termp *p, const struct roffsu *su) { @@ -686,39 +698,11 @@ term_vspan(const struct termp *p, const struct roffsu size_t term_hspan(const struct termp *p, const struct roffsu *su) { - double r; + double v; - /* XXX: CM, IN, and PT are approximations. */ - - switch (su->unit) { - case (SCALE_CM): - r = 4 * su->scale; - break; - case (SCALE_IN): - /* XXX: this is an approximation. */ - r = 10 * su->scale; - break; - case (SCALE_PC): - r = (10 * su->scale) / 6; - break; - case (SCALE_PT): - r = (10 * su->scale) / 72; - break; - case (SCALE_MM): - r = su->scale / 1000; /* FIXME: double-check. */ - break; - case (SCALE_VS): - r = su->scale * 2 - 1; /* FIXME: double-check. */ - break; - default: - r = su->scale; - break; - } - - if (r < 0.0) - r = 0.0; - return((size_t)/* LINTED */ - r); + v = ((*p->hspan)(p, su)); + if (v < 0.0) + v = 0.0; + return((size_t) /* LINTED */ + v); } - -