=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.263 retrieving revision 1.265 diff -u -p -r1.263 -r1.265 --- mandoc/term.c 2017/06/04 18:50:35 1.263 +++ mandoc/term.c 2017/06/07 02:14:09 1.265 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.263 2017/06/04 18:50:35 schwarze Exp $ */ +/* $Id: term.c,v 1.265 2017/06/07 02:14:09 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010-2017 Ingo Schwarze @@ -36,6 +36,7 @@ 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); +static void endline(struct termp *); void @@ -116,13 +117,13 @@ term_flushln(struct termp *p) vis = vend = 0; i = 0; - while (i < p->col) { + while (i < p->lastcol) { /* * Handle literal tab characters: collapse all * subsequent tabs into a single huge set of spaces. */ ntab = 0; - while (i < p->col && p->buf[i] == '\t') { + while (i < p->lastcol && p->buf[i] == '\t') { vend = term_tab_next(vis); vbl += vend - vis; vis = vend; @@ -137,7 +138,7 @@ term_flushln(struct termp *p) * space is printed according to regular spacing rules). */ - for (j = i, jhy = 0; j < p->col; j++) { + for (j = i, jhy = 0; j < p->lastcol; j++) { if (' ' == p->buf[j] || '\t' == p->buf[j]) break; @@ -169,10 +170,10 @@ term_flushln(struct termp *p) * Find out whether we would exceed the right margin. * If so, break to the next line. */ - if (vend > bp && 0 == jhy && vis > 0) { + if (vend > bp && 0 == jhy && vis > 0 && + (p->flags & TERMP_BRNEVER) == 0) { vend -= vis; - (*p->endline)(p); - p->viscol = 0; + endline(p); /* Use pending tabs on the new line. */ @@ -192,14 +193,14 @@ term_flushln(struct termp *p) } /* Write out the [remaining] word. */ - for ( ; i < p->col; i++) { + for ( ; i < p->lastcol; i++) { if (vend > bp && jhy > 0 && i > jhy) break; if ('\t' == p->buf[i]) break; if (' ' == p->buf[i]) { j = i; - while (i < p->col && ' ' == p->buf[i]) + while (i < p->lastcol && ' ' == p->buf[i]) i++; dv = (i - j) * (*p->width)(p, ' '); vbl += dv; @@ -242,34 +243,40 @@ term_flushln(struct termp *p) else vis = 0; - p->col = 0; + p->col = p->lastcol = 0; + p->minbl = p->trailspace; p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE | TERMP_NOPAD); - if ( ! (TERMP_NOBREAK & p->flags)) { - p->viscol = 0; - p->minbl = 0; - (*p->endline)(p); - return; - } - - if (TERMP_HANG & p->flags) { - p->minbl = p->trailspace; - 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); - p->viscol = 0; - p->minbl = 0; - } else - p->minbl = p->trailspace; + if ((p->flags & TERMP_NOBREAK) == 0 || + ((p->flags & TERMP_HANG) == 0 && + vis + p->trailspace * (*p->width)(p, ' ') > maxvis)) + endline(p); } +static void +endline(struct termp *p) +{ + if ((p->flags & (TERMP_NEWMC | TERMP_ENDMC)) == TERMP_ENDMC) { + p->mc = NULL; + p->flags &= ~TERMP_ENDMC; + } + if (p->mc != NULL) { + if (p->viscol && p->maxrmargin >= p->viscol) + (*p->advance)(p, p->maxrmargin - p->viscol + 1); + p->flags |= TERMP_NOBUF | TERMP_NOSPACE; + term_word(p, p->mc); + p->flags &= ~(TERMP_NOBUF | TERMP_NEWMC); + } + p->viscol = 0; + p->minbl = 0; + (*p->endline)(p); +} + /* * A newline only breaks an existing line; it won't assert vertical * space. All data in the output buffer is flushed prior to the newline @@ -280,7 +287,7 @@ term_newln(struct termp *p) { p->flags |= TERMP_NOSPACE; - if (p->col || p->viscol) + if (p->lastcol || p->viscol) term_flushln(p); } @@ -296,6 +303,7 @@ term_vspace(struct termp *p) term_newln(p); p->viscol = 0; + p->minbl = 0; if (0 < p->skipvsp) p->skipvsp--; else @@ -370,25 +378,25 @@ term_word(struct termp *p, const char *word) size_t csz, lsz, ssz; enum mandoc_esc esc; - if ( ! (TERMP_NOSPACE & p->flags)) { - if ( ! (TERMP_KEEP & p->flags)) { - bufferc(p, ' '); - if (TERMP_SENTENCE & p->flags) + if ((p->flags & TERMP_NOBUF) == 0) { + if ((p->flags & TERMP_NOSPACE) == 0) { + if ((p->flags & TERMP_KEEP) == 0) { bufferc(p, ' '); - } else - bufferc(p, ASCII_NBRSP); + if (p->flags & TERMP_SENTENCE) + bufferc(p, ' '); + } else + bufferc(p, ASCII_NBRSP); + } + if (p->flags & TERMP_PREKEEP) + p->flags |= TERMP_KEEP; + if (p->flags & TERMP_NONOSPACE) + p->flags |= TERMP_NOSPACE; + else + p->flags &= ~TERMP_NOSPACE; + p->flags &= ~(TERMP_SENTENCE | TERMP_NONEWLINE); + p->skipvsp = 0; } - if (TERMP_PREKEEP & p->flags) - p->flags |= TERMP_KEEP; - if ( ! (p->flags & TERMP_NONOSPACE)) - p->flags &= ~TERMP_NOSPACE; - else - p->flags |= TERMP_NOSPACE; - - p->flags &= ~(TERMP_SENTENCE | TERMP_NONEWLINE); - p->skipvsp = 0; - while ('\0' != *word) { if ('\\' != *word) { if (TERMP_NBRWORD & p->flags) { @@ -548,10 +556,12 @@ term_word(struct termp *p, const char *word) } } /* Trim trailing backspace/blank pair. */ - if (p->col > 2 && - (p->buf[p->col - 1] == ' ' || - p->buf[p->col - 1] == '\t')) - p->col -= 2; + if (p->lastcol > 2 && + (p->buf[p->lastcol - 1] == ' ' || + p->buf[p->lastcol - 1] == '\t')) + p->lastcol -= 2; + if (p->col > p->lastcol) + p->col = p->lastcol; continue; default: continue; @@ -590,11 +600,16 @@ adjbuf(struct termp *p, size_t sz) static void bufferc(struct termp *p, char c) { - + if (p->flags & TERMP_NOBUF) { + (*p->letter)(p, c); + return; + } if (p->col + 1 >= p->maxcols) adjbuf(p, p->col + 1); - - p->buf[p->col++] = c; + if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP)) + p->buf[p->col] = c; + if (p->lastcol < ++p->col) + p->lastcol = p->col; } /* @@ -607,6 +622,11 @@ encode1(struct termp *p, int c) { enum termfont f; + if (p->flags & TERMP_NOBUF) { + (*p->letter)(p, c); + return; + } + if (p->col + 7 >= p->maxcols) adjbuf(p, p->col + 7); @@ -631,7 +651,10 @@ encode1(struct termp *p, int c) p->buf[p->col++] = c; p->buf[p->col++] = 8; } - p->buf[p->col++] = c; + if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP)) + p->buf[p->col] = c; + if (p->lastcol < ++p->col) + p->lastcol = p->col; if (p->flags & TERMP_BACKAFTER) { p->flags |= TERMP_BACKBEFORE; p->flags &= ~TERMP_BACKAFTER; @@ -643,6 +666,12 @@ encode(struct termp *p, const char *word, size_t sz) { size_t i; + if (p->flags & TERMP_NOBUF) { + for (i = 0; i < sz; i++) + (*p->letter)(p, word[i]); + return; + } + if (p->col + 2 + (sz * 5) >= p->maxcols) adjbuf(p, p->col + 2 + (sz * 5)); @@ -651,7 +680,10 @@ encode(struct termp *p, const char *word, size_t sz) isgraph((unsigned char)word[i])) encode1(p, word[i]); else { - p->buf[p->col++] = word[i]; + if (p->lastcol <= p->col || + (word[i] != ' ' && word[i] != ASCII_NBRSP)) + p->buf[p->col] = word[i]; + p->col++; /* * Postpone the effect of \z while handling @@ -665,6 +697,8 @@ encode(struct termp *p, const char *word, size_t sz) } } } + if (p->lastcol < p->col) + p->lastcol = p->col; } void