=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.211 retrieving revision 1.220 diff -u -p -r1.211 -r1.220 --- mandoc/term.c 2013/12/22 23:34:13 1.211 +++ mandoc/term.c 2014/04/05 21:18:19 1.220 @@ -1,7 +1,7 @@ -/* $Id: term.c,v 1.211 2013/12/22 23:34:13 schwarze Exp $ */ +/* $Id: term.c,v 1.220 2014/04/05 21:18:19 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze + * Copyright (c) 2010-2014 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 @@ -23,12 +23,12 @@ #include #include -#include #include #include #include #include "mandoc.h" +#include "mandoc_aux.h" #include "out.h" #include "term.h" #include "main.h" @@ -120,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; @@ -174,9 +179,17 @@ term_flushln(struct termp *p) /* Regular word. */ /* Break at the hyphen point if we overrun. */ if (vend > vis && vend < bp && - ASCII_HYPH == p->buf[j]) + (ASCII_HYPH == p->buf[j] || + ASCII_BREAK == p->buf[j])) jhy = j; + /* + * Hyphenation now decided, put back a real + * hyphen such that we get the correct width. + */ + if (ASCII_HYPH == p->buf[j]) + p->buf[j] = '-'; + vend += (*p->width)(p, p->buf[j]); } @@ -199,7 +212,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; @@ -224,6 +241,8 @@ term_flushln(struct termp *p) vbl += (*p->width)(p, ' '); continue; } + if (ASCII_BREAK == p->buf[i]) + continue; /* * Now we definitely know there will be @@ -236,12 +255,6 @@ term_flushln(struct termp *p) vbl = 0; } - if (ASCII_HYPH == p->buf[i]) { - (*p->letter)(p, '-'); - p->viscol += (*p->width)(p, '-'); - continue; - } - (*p->letter)(p, p->buf[i]); if (8 == p->buf[i]) p->viscol -= (*p->width)(p, p->buf[i-1]); @@ -275,8 +288,10 @@ term_flushln(struct termp *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; @@ -396,6 +411,7 @@ term_fontpop(struct termp *p) void term_word(struct termp *p, const char *word) { + const char nbrsp[2] = { ASCII_NBRSP, 0 }; const char *seq, *cp; char c; int sz, uc; @@ -418,7 +434,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) { @@ -427,7 +443,15 @@ term_word(struct termp *p, const char *word) word++; continue; } - ssz = strcspn(word, "\\"); + if (TERMP_NBRWORD & p->flags) { + if (' ' == *word) { + encode(p, nbrsp, 1); + word++; + continue; + } + ssz = strcspn(word, "\\ "); + } else + ssz = strcspn(word, "\\"); encode(p, word, ssz); word += (int)ssz; continue; @@ -502,6 +526,7 @@ term_word(struct termp *p, const char *word) break; } } + p->flags &= ~TERMP_NBRWORD; } static void @@ -598,6 +623,36 @@ encode(struct termp *p, const char *word, size_t sz) } } +void +term_setwidth(struct termp *p, const char *wstr) +{ + struct roffsu su; + size_t width; + int iop; + + iop = 0; + width = 0; + if (NULL != wstr) { + switch (*wstr) { + case ('+'): + iop = 1; + wstr++; + break; + case ('-'): + iop = -1; + wstr++; + break; + default: + break; + } + if (a2roffsu(wstr, &su, SCALE_MAX)) + width = term_hspan(p, &su); + else + iop = 0; + } + (*p->setwidth)(p, iop, width); +} + size_t term_len(const struct termp *p, size_t sz) { @@ -623,7 +678,8 @@ term_strlen(const struct termp *p, const char *cp) int ssz, skip, c; const char *seq, *rhs; enum mandoc_esc esc; - static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' }; + static const char rej[] = { '\\', ASCII_NBRSP, ASCII_HYPH, + ASCII_BREAK, '\0' }; /* * Account for escaped sequences within string length @@ -638,7 +694,6 @@ term_strlen(const struct termp *p, const char *cp) for (i = 0; i < rsz; i++) sz += cond_width(p, *cp++, &skip); - c = 0; switch (*cp) { case ('\\'): cp++; @@ -712,6 +767,8 @@ term_strlen(const struct termp *p, const char *cp) case (ASCII_HYPH): sz += cond_width(p, '-', &skip); cp++; + /* FALLTHROUGH */ + case (ASCII_BREAK): break; default: break;