=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.244 retrieving revision 1.250 diff -u -p -r1.244 -r1.250 --- mandoc/term.c 2015/01/31 00:12:41 1.244 +++ mandoc/term.c 2015/09/21 13:25:00 1.250 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.244 2015/01/31 00:12:41 schwarze Exp $ */ +/* $Id: term.c,v 1.250 2015/09/21 13:25:00 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -49,7 +49,7 @@ term_free(struct termp *p) void term_begin(struct termp *p, term_margin head, - term_margin foot, const void *arg) + term_margin foot, const struct roff_meta *arg) { p->headf = head; @@ -78,6 +78,8 @@ term_end(struct termp *p) * the next column. However, if less than p->trailspace blanks, * which can be 0, 1, or 2, remain to the right margin, the line * will be broken. + * - TERMP_BRTRSP: Consider trailing whitespace significant + * when deciding whether the chunk fits or not. * - TERMP_BRIND: If the chunk does not fit and the output line has * to be broken, start the next line at the right margin instead * of at the offset. Used together with TERMP_NOBREAK for the tags @@ -265,6 +267,7 @@ term_flushln(struct termp *p) p->col = 0; p->overstep = 0; + p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE); if ( ! (TERMP_NOBREAK & p->flags)) { p->viscol = 0; @@ -290,6 +293,10 @@ term_flushln(struct termp *p) } else if (TERMP_DANGLE & p->flags) return; + /* Trailing whitespace is significant in some columns. */ + if (vis && vbl && (TERMP_BRTRSP & p->flags)) + vis += vbl; + /* If the column was overrun, break the line. */ if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) { (*p->endline)(p); @@ -413,14 +420,10 @@ term_word(struct termp *p, const char *word) p->flags |= TERMP_NOSPACE; p->flags &= ~(TERMP_SENTENCE | TERMP_NONEWLINE); + p->skipvsp = 0; while ('\0' != *word) { if ('\\' != *word) { - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - word++; - continue; - } if (TERMP_NBRWORD & p->flags) { if (' ' == *word) { encode(p, nbrsp, 1); @@ -479,13 +482,13 @@ term_word(struct termp *p, const char *word) term_fontlast(p); continue; case ESCAPE_NOSPACE: - if (TERMP_SKIPCHAR & p->flags) - p->flags &= ~TERMP_SKIPCHAR; - else if ('\0' == *word) + if (p->flags & TERMP_BACKAFTER) + p->flags &= ~TERMP_BACKAFTER; + else if (*word == '\0') p->flags |= (TERMP_NOSPACE | TERMP_NONEWLINE); continue; case ESCAPE_SKIPCHAR: - p->flags |= TERMP_SKIPCHAR; + p->flags |= TERMP_BACKAFTER; continue; case ESCAPE_OVERSTRIKE: cp = seq + sz; @@ -495,9 +498,17 @@ term_word(struct termp *p, const char *word) continue; } encode1(p, *seq++); - if (seq < cp) - encode(p, "\b", 1); + if (seq < cp) { + if (p->flags & TERMP_BACKBEFORE) + p->flags |= TERMP_BACKAFTER; + else + p->flags |= TERMP_BACKBEFORE; + } } + /* Trim trailing backspace/blank pair. */ + if (p->col > 2 && p->buf[p->col - 1] == ' ') + p->col -= 2; + continue; default: continue; } @@ -552,16 +563,19 @@ encode1(struct termp *p, int c) { enum termfont f; - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - return; - } + if (p->col + 7 >= p->maxcols) + adjbuf(p, p->col + 7); - if (p->col + 6 >= p->maxcols) - adjbuf(p, p->col + 6); + f = (c == ASCII_HYPH || isgraph(c)) ? + p->fontq[p->fonti] : TERMFONT_NONE; - f = p->fontq[p->fonti]; - + if (p->flags & TERMP_BACKBEFORE) { + if (p->buf[p->col - 1] == ' ') + p->col--; + else + p->buf[p->col++] = 8; + p->flags &= ~TERMP_BACKBEFORE; + } if (TERMFONT_UNDER == f || TERMFONT_BI == f) { p->buf[p->col++] = '_'; p->buf[p->col++] = 8; @@ -574,6 +588,10 @@ encode1(struct termp *p, int c) p->buf[p->col++] = 8; } p->buf[p->col++] = c; + if (p->flags & TERMP_BACKAFTER) { + p->flags |= TERMP_BACKBEFORE; + p->flags &= ~TERMP_BACKAFTER; + } } static void @@ -581,30 +599,9 @@ encode(struct termp *p, const char *word, size_t sz) { size_t i; - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - return; - } + if (p->col + 2 + (sz * 5) >= p->maxcols) + adjbuf(p, p->col + 2 + (sz * 5)); - /* - * Encode and buffer a string of characters. If the current - * font mode is unset, buffer directly, else encode then buffer - * character by character. - */ - - if (p->fontq[p->fonti] == TERMFONT_NONE) { - if (p->col + sz >= p->maxcols) - adjbuf(p, p->col + sz); - for (i = 0; i < sz; i++) - p->buf[p->col++] = word[i]; - return; - } - - /* Pre-buffer, assuming worst-case. */ - - if (p->col + 1 + (sz * 5) >= p->maxcols) - adjbuf(p, p->col + 1 + (sz * 5)); - for (i = 0; i < sz; i++) { if (ASCII_HYPH == word[i] || isgraph((unsigned char)word[i])) @@ -618,8 +615,7 @@ void term_setwidth(struct termp *p, const char *wstr) { struct roffsu su; - size_t width; - int iop; + int iop, width; iop = 0; width = 0; @@ -830,11 +826,12 @@ term_vspan(const struct termp *p, const struct roffsu return(ri < 66 ? ri : 1); } +/* + * Convert a scaling width to basic units, rounding down. + */ int term_hspan(const struct termp *p, const struct roffsu *su) { - double v; - v = (*p->hspan)(p, su); - return(v > 0.0 ? v + 0.0005 : v - 0.0005); + return((*p->hspan)(p, su)); }