=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.111 retrieving revision 1.123 diff -u -p -r1.111 -r1.123 --- mandoc/term.c 2009/10/26 07:18:23 1.111 +++ mandoc/term.c 2009/11/06 10:31:32 1.123 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.111 2009/10/26 07:18:23 kristaps Exp $ */ +/* $Id: term.c,v 1.123 2009/11/06 10:31:32 kristaps Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -15,10 +15,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include -#include +#include #include #include #include +#include #include "chars.h" #include "out.h" @@ -76,9 +77,11 @@ term_alloc(enum termenc enc) { struct termp *p; - if (NULL == (p = malloc(sizeof(struct termp)))) - return(NULL); - bzero(p, sizeof(struct termp)); + p = calloc(1, sizeof(struct termp)); + if (NULL == p) { + perror(NULL); + exit(EXIT_FAILURE); + } p->maxrmargin = 78; p->enc = enc; return(p); @@ -119,36 +122,44 @@ term_alloc(enum termenc enc) * If TERMP_NOBREAK is specified and the line overruns the right * margin, it will break and pad-right to the right margin after * writing. If maxrmargin is violated, it will break and continue - * writing from the right-margin, which will lead to the above - * scenario upon exit. - * - * Otherwise, the line will break at the right margin. Extremely long - * lines will cause the system to emit a warning (TODO: hyphenate, if - * possible). + * writing from the right-margin, which will lead to the above scenario + * upon exit. Otherwise, the line will break at the right margin. */ void term_flushln(struct termp *p) { - int i, j; - size_t vbl, vsz, vis, maxvis, mmax, bp; + int i; /* current input position in p->buf */ + size_t vis; /* current visual position on output */ + size_t vbl; /* number of blanks to prepend to output */ + size_t vsz; /* visual characters to write to output */ + size_t bp; /* visual right border position */ + int j; /* temporary loop index */ + size_t maxvis, mmax; static int overstep = 0; /* * 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. */ assert(p->offset < p->rmargin); - assert((int)(p->rmargin - p->offset) - overstep > 0); - maxvis = /* LINTED */ - p->rmargin - p->offset - overstep; - mmax = /* LINTED */ - p->maxrmargin - p->offset - overstep; + maxvis = (int)(p->rmargin - p->offset) - overstep < 0 ? + /* LINTED */ + 0 : p->rmargin - p->offset - overstep; + mmax = (int)(p->maxrmargin - p->offset) - overstep < 0 ? + /* LINTED */ + 0 : p->maxrmargin - p->offset - overstep; bp = TERMP_NOBREAK & p->flags ? mmax : maxvis; + + /* + * FIXME: if bp is zero, we still output the first word before + * breaking the line. + */ + vis = 0; /* @@ -204,7 +215,8 @@ term_flushln(struct termp *p) vis = 0; } /* Remove the overstep width. */ - bp += overstep; + bp += (int)/* LINTED */ + overstep; overstep = 0; } else { for (j = 0; j < (int)vbl; j++) @@ -218,7 +230,12 @@ term_flushln(struct termp *p) for ( ; i < (int)p->col; i++) { if (' ' == p->buf[i]) break; - putchar(p->buf[i]); + + /* The unit sep. is a non-breaking space. */ + if (31 == p->buf[i]) + putchar(' '); + else + putchar(p->buf[i]); } vis += vsz; } @@ -357,21 +374,21 @@ do_reserved(struct termp *p, const char *word, size_t static void do_escaped(struct termp *p, const char **word) { - int j, type; + int j, type, sv, t, lim; const char *wp; wp = *word; type = 1; - if (0 == *(++wp)) { + if ('\0' == *(++wp)) { *word = wp; return; } if ('(' == *wp) { wp++; - if (0 == *wp || 0 == *(wp + 1)) { - *word = 0 == *wp ? wp : wp + 1; + if ('\0' == *wp || '\0' == *(wp + 1)) { + *word = '\0' == *wp ? wp : wp + 1; return; } @@ -380,7 +397,7 @@ do_escaped(struct termp *p, const char **word) return; } else if ('*' == *wp) { - if (0 == *(++wp)) { + if ('\0' == *(++wp)) { *word = wp; return; } @@ -388,8 +405,8 @@ do_escaped(struct termp *p, const char **word) switch (*wp) { case ('('): wp++; - if (0 == *wp || 0 == *(wp + 1)) { - *word = 0 == *wp ? wp : wp + 1; + if ('\0' == *wp || '\0' == *(wp + 1)) { + *word = '\0' == *wp ? wp : wp + 1; return; } @@ -404,24 +421,115 @@ do_escaped(struct termp *p, const char **word) *word = wp; return; } - + + } else if ('s' == *wp) { + /* This closely follows mandoc_special(). */ + if ('\0' == *(++wp)) { + *word = wp; + return; + } + + t = 0; + lim = 1; + + if (*wp == '\'') { + lim = 0; + t = 1; + ++wp; + } else if (*wp == '[') { + lim = 0; + t = 2; + ++wp; + } else if (*wp == '(') { + lim = 2; + t = 3; + ++wp; + } + + if (*wp == '+' || *wp == '-') + ++wp; + + if (*wp == '\'') { + if (t) { + *word = wp; + return; + } + lim = 0; + t = 1; + ++wp; + } else if (*wp == '[') { + if (t) { + *word = wp; + return; + } + lim = 0; + t = 2; + ++wp; + } else if (*wp == '(') { + if (t) { + *word = wp; + return; + } + lim = 2; + t = 3; + ++wp; + } + + if ( ! isdigit((u_char)*wp)) { + *word = --wp; + return; + } + + for (j = 0; isdigit((u_char)*wp); j++) { + if (lim && j >= lim) + break; + ++wp; + } + + if (t && t < 3) { + if (1 == t && *wp != '\'') { + *word = --wp; + return; + } + if (2 == t && *wp != ']') { + *word = --wp; + return; + } + ++wp; + } + *word = --wp; + return; + } else if ('f' == *wp) { - if (0 == *(++wp)) { + if ('\0' == *(++wp)) { *word = wp; return; } switch (*wp) { + case ('3'): + /* FALLTHROUGH */ case ('B'): - p->bold++; + p->metamask = p->metafont; + p->metafont |= METAF_BOLD; break; + case ('2'): + /* FALLTHROUGH */ case ('I'): - p->under++; + p->metamask = p->metafont; + p->metafont |= METAF_UNDER; break; case ('P'): + sv = p->metamask; + p->metamask = p->metafont; + p->metafont = sv; + break; + case ('1'): /* FALLTHROUGH */ case ('R'): - p->bold = p->under = 0; + p->metamask = p->metafont; + p->metafont &= ~METAF_UNDER; + p->metafont &= ~METAF_BOLD; break; default: break; @@ -440,7 +548,7 @@ do_escaped(struct termp *p, const char **word) for (j = 0; *wp && ']' != *wp; wp++, j++) /* Loop... */ ; - if (0 == *wp) { + if ('\0' == *wp) { *word = wp; return; } @@ -465,7 +573,7 @@ term_word(struct termp *p, const char *word) sv = word; - if (word[0] && 0 == word[1]) + if (word[0] && '\0' == word[1]) switch (word[0]) { case('.'): /* FALLTHROUGH */ @@ -533,8 +641,10 @@ buffer(struct termp *p, char c) p->maxcols = 256; s = p->maxcols * 2; p->buf = realloc(p->buf, s); - if (NULL == p->buf) - err(1, "realloc"); /* FIXME: shouldn't be here! */ + if (NULL == p->buf) { + perror(NULL); + exit(EXIT_FAILURE); + } p->maxcols = s; } p->buf[(int)(p->col)++] = c; @@ -545,12 +655,12 @@ static void encode(struct termp *p, char c) { - if (' ' != c) { - if (p->under) { + if (isgraph((u_char)c)) { + if (p->under || METAF_UNDER & p->metafont) { buffer(p, '_'); buffer(p, 8); } - if (p->bold) { + if (p->bold || METAF_BOLD & p->metafont) { buffer(p, c); buffer(p, 8); }