=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.209 retrieving revision 1.213 diff -u -p -r1.209 -r1.213 --- mandoc/term.c 2013/08/08 20:07:47 1.209 +++ mandoc/term.c 2013/12/24 23:04:36 1.213 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.209 2013/08/08 20:07:47 schwarze Exp $ */ +/* $Id: term.c,v 1.213 2013/12/24 23:04:36 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze @@ -34,7 +34,7 @@ #include "main.h" static size_t cond_width(const struct termp *, int, int *); -static void adjbuf(struct termp *p, int); +static void adjbuf(struct termp *p, size_t); static void bufferc(struct termp *, char); static void encode(struct termp *, const char *, size_t); static void encode1(struct termp *, int); @@ -83,10 +83,9 @@ term_end(struct termp *p) * - TERMP_NOBREAK: this is the most important and is used when making * columns. In short: don't print a newline and instead expect the * next call to do the padding up to the start of the next column. + * p->trailspace may be set to 0, 1, or 2, depending on how many + * space characters are required at the end of the column. * - * - TERMP_TWOSPACE: make sure there is room for at least two space - * characters of padding. Otherwise, rather break the line. - * * - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and * the line is overrun, and don't pad-right if it's underrun. * @@ -105,15 +104,15 @@ term_end(struct termp *p) void term_flushln(struct termp *p) { - int i; /* current input position in p->buf */ + size_t i; /* current input position in p->buf */ int ntab; /* number of tabs to prepend */ size_t vis; /* current visual position on output */ size_t vbl; /* number of blanks to prepend to output */ size_t vend; /* end of word visual position on output */ size_t bp; /* visual right border position */ size_t dv; /* temporary for visual pos calculations */ - int j; /* temporary loop index for p->buf */ - int jhy; /* last hyph before overflow w/r/t j */ + size_t j; /* temporary loop index for p->buf */ + size_t jhy; /* last hyph before overflow w/r/t j */ size_t maxvis; /* output position of visible boundary */ size_t mmax; /* used in calculating bp */ @@ -121,7 +120,12 @@ term_flushln(struct termp *p) * First, establish the maximum columns of "visible" content. * This is usually the difference between the right-margin and * an indentation, but can be, for tagged lists or columns, a - * small set of values. + * small set of values. + * + * The following unsigned-signed subtractions look strange, + * but they are actually correct. If the int p->overstep + * is negative, it gets sign extended. Subtracting that + * very large size_t effectively adds a small number to dv. */ assert (p->rmargin >= p->offset); dv = p->rmargin - p->offset; @@ -200,7 +204,11 @@ term_flushln(struct termp *p) if (0 < ntab) vbl += ntab * p->tabwidth; - /* Remove the p->overstep width. */ + /* + * Remove the p->overstep width. + * Again, if p->overstep is negative, + * sign extension does the right thing. + */ bp += (size_t)p->overstep; p->overstep = 0; @@ -216,7 +224,7 @@ term_flushln(struct termp *p) j = i; while (' ' == p->buf[i]) i++; - dv = (size_t)(i - j) * (*p->width)(p, ' '); + dv = (i - j) * (*p->width)(p, ' '); vbl += dv; vend += dv; break; @@ -269,15 +277,17 @@ term_flushln(struct termp *p) } if (TERMP_HANG & p->flags) { - /* We need one blank after the tag. */ - p->overstep = (int)(vis - maxvis + (*p->width)(p, ' ')); + p->overstep = (int)(vis - maxvis + + p->trailspace * (*p->width)(p, ' ')); /* * If we have overstepped the margin, temporarily move * it to the right and flag the rest of the line to be * shorter. + * If there is a request to keep the columns together, + * allow negative overstep when the column is not full. */ - if (p->overstep < 0) + if (p->trailspace && p->overstep < 0) p->overstep = 0; return; @@ -285,8 +295,7 @@ term_flushln(struct termp *p) return; /* If the column was overrun, break the line. */ - if (maxvis <= vis + - ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) { + if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) { (*p->endline)(p); p->viscol = 0; } @@ -420,7 +429,7 @@ term_word(struct termp *p, const char *word) else p->flags |= TERMP_NOSPACE; - p->flags &= ~(TERMP_SENTENCE | TERMP_IGNDELIM); + p->flags &= ~TERMP_SENTENCE; while ('\0' != *word) { if ('\\' != *word) { @@ -507,7 +516,7 @@ term_word(struct termp *p, const char *word) } static void -adjbuf(struct termp *p, int sz) +adjbuf(struct termp *p, size_t sz) { if (0 == p->maxcols) @@ -515,8 +524,7 @@ adjbuf(struct termp *p, int sz) while (sz >= p->maxcols) p->maxcols <<= 2; - p->buf = mandoc_realloc - (p->buf, sizeof(int) * (size_t)p->maxcols); + p->buf = mandoc_realloc(p->buf, sizeof(int) * p->maxcols); } static void @@ -566,16 +574,13 @@ encode1(struct termp *p, int c) static void encode(struct termp *p, const char *word, size_t sz) { - int i, len; + size_t i; if (TERMP_SKIPCHAR & p->flags) { p->flags &= ~TERMP_SKIPCHAR; return; } - /* LINTED */ - len = sz; - /* * Encode and buffer a string of characters. If the current * font mode is unset, buffer directly, else encode then buffer @@ -583,19 +588,19 @@ encode(struct termp *p, const char *word, size_t sz) */ if (TERMFONT_NONE == term_fonttop(p)) { - if (p->col + len >= p->maxcols) - adjbuf(p, p->col + len); - for (i = 0; i < len; i++) + 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 + (len * 5) >= p->maxcols) - adjbuf(p, p->col + 1 + (len * 5)); + if (p->col + 1 + (sz * 5) >= p->maxcols) + adjbuf(p, p->col + 1 + (sz * 5)); - for (i = 0; i < len; i++) { + for (i = 0; i < sz; i++) { if (ASCII_HYPH == word[i] || isgraph((unsigned char)word[i])) encode1(p, word[i]);