=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.128 retrieving revision 1.135 diff -u -p -r1.128 -r1.135 --- mandoc/term.c 2010/01/01 17:14:30 1.128 +++ mandoc/term.c 2010/05/16 01:35:37 1.135 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.128 2010/01/01 17:14:30 kristaps Exp $ */ +/* $Id: term.c,v 1.135 2010/05/16 01:35:37 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -34,7 +34,7 @@ #include "mdoc.h" #include "main.h" -static struct termp *term_alloc(enum termenc); +static struct termp *term_alloc(enum termenc, size_t); static void term_free(struct termp *); static void spec(struct termp *, const char *, size_t); static void res(struct termp *, const char *, size_t); @@ -45,10 +45,10 @@ static void encode(struct termp *, const char *, si void * -ascii_alloc(void) +ascii_alloc(size_t width) { - return(term_alloc(TERMENC_ASCII)); + return(term_alloc(TERMENC_ASCII, width)); } @@ -74,7 +74,7 @@ term_free(struct termp *p) static struct termp * -term_alloc(enum termenc enc) +term_alloc(enum termenc enc, size_t width) { struct termp *p; @@ -83,8 +83,11 @@ term_alloc(enum termenc enc) perror(NULL); exit(EXIT_FAILURE); } - p->maxrmargin = 78; p->enc = enc; + /* Enforce some lower boundary. */ + if (width < 60) + width = 60; + p->defrmargin = width - 2; return(p); } @@ -93,13 +96,11 @@ term_alloc(enum termenc enc) * Flush a line of text. A "line" is loosely defined as being something * that should be followed by a newline, regardless of whether it's * broken apart by newlines getting there. A line can also be a - * fragment of a columnar list. + * fragment of a columnar list (`Bl -tag' or `Bl -column'), which does + * not have a trailing newline. * - * Specifically, a line is whatever's in p->buf of length p->col, which - * is zeroed after this function returns. + * The following flags may be specified: * - * The usage of termp:flags is as follows: - * * - TERMP_NOLPAD: when beginning to write the line, don't left-pad the * offset value. This is useful when doing columnar lists where the * prior column has right-padded. @@ -136,7 +137,6 @@ term_flushln(struct termp *p) 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. @@ -147,12 +147,12 @@ term_flushln(struct termp *p) assert(p->offset < p->rmargin); - maxvis = (int)(p->rmargin - p->offset) - overstep < 0 ? + maxvis = (int)(p->rmargin - p->offset) - p->overstep < 0 ? /* LINTED */ - 0 : p->rmargin - p->offset - overstep; - mmax = (int)(p->maxrmargin - p->offset) - overstep < 0 ? + 0 : p->rmargin - p->offset - p->overstep; + mmax = (int)(p->maxrmargin - p->offset) - p->overstep < 0 ? /* LINTED */ - 0 : p->maxrmargin - p->offset - overstep; + 0 : p->maxrmargin - p->offset - p->overstep; bp = TERMP_NOBREAK & p->flags ? mmax : maxvis; @@ -186,7 +186,7 @@ term_flushln(struct termp *p) for (j = i, vsz = 0; j < (int)p->col; j++) { if (j && ' ' == p->buf[j]) break; - else if (8 == p->buf[j]) + if (8 == p->buf[j]) vsz--; else vsz++; @@ -197,13 +197,15 @@ term_flushln(struct termp *p) * beginning of a line, one between words -- but do not * actually write them yet. */ + vbl = (size_t)(0 == vis ? 0 : 1); /* * Find out whether we would exceed the right margin. - * If so, break to the next line. (TODO: hyphenate) - * Otherwise, write the chosen number of blanks now. + * If so, break to the next line. Otherwise, write the chosen + * number of blanks. */ + if (vis && vis + vbl + vsz > bp) { putchar('\n'); if (TERMP_NOBREAK & p->flags) { @@ -215,34 +217,32 @@ term_flushln(struct termp *p) putchar(' '); vis = 0; } - /* Remove the overstep width. */ + + /* Remove the p->overstep width. */ + bp += (int)/* LINTED */ - overstep; - overstep = 0; + p->overstep; + p->overstep = 0; } else { for (j = 0; j < (int)vbl; j++) putchar(' '); vis += vbl; } - /* - * Finally, write out the word. - */ - for ( ; i < (int)p->col; i++) { + /* Write out the [remaining] word. */ + for ( ; i < (int)p->col; i++) if (' ' == p->buf[i]) break; - - /* The unit sep. is a non-breaking space. */ - if (31 == p->buf[i]) + else if (ASCII_NBRSP == p->buf[i]) putchar(' '); else putchar(p->buf[i]); - } + vis += vsz; } p->col = 0; - overstep = 0; + p->overstep = 0; if ( ! (TERMP_NOBREAK & p->flags)) { putchar('\n'); @@ -251,7 +251,7 @@ term_flushln(struct termp *p) if (TERMP_HANG & p->flags) { /* We need one blank after the tag. */ - overstep = /* LINTED */ + p->overstep = /* LINTED */ vis - maxvis + 1; /* @@ -264,12 +264,12 @@ term_flushln(struct termp *p) * move it one step LEFT and flag the rest of the line * to be longer. */ - if (overstep >= -1) { - assert((int)maxvis + overstep >= 0); + if (p->overstep >= -1) { + assert((int)maxvis + p->overstep >= 0); /* LINTED */ - maxvis += overstep; + maxvis += p->overstep; } else - overstep = 0; + p->overstep = 0; } else if (TERMP_DANGLE & p->flags) return; @@ -442,8 +442,6 @@ term_word(struct termp *p, const char *word) case(')'): /* FALLTHROUGH */ case(']'): - /* FALLTHROUGH */ - case('}'): if ( ! (TERMP_IGNDELIM & p->flags)) p->flags |= TERMP_NOSPACE; break; @@ -451,12 +449,17 @@ term_word(struct termp *p, const char *word) break; } - if ( ! (TERMP_NOSPACE & p->flags)) + if ( ! (TERMP_NOSPACE & p->flags)) { bufferc(p, ' '); + if (TERMP_SENTENCE & p->flags) + bufferc(p, ' '); + } if ( ! (p->flags & TERMP_NONOSPACE)) p->flags &= ~TERMP_NOSPACE; + p->flags &= ~TERMP_SENTENCE; + /* FIXME: use strcspn. */ while (*word) { @@ -497,13 +500,15 @@ term_word(struct termp *p, const char *word) p->flags |= TERMP_NOSPACE; } + /* + * Note that we don't process the pipe: the parser sees it as + * punctuation, but we don't in terms of typography. + */ if (sv[0] && 0 == sv[1]) switch (sv[0]) { case('('): /* FALLTHROUGH */ case('['): - /* FALLTHROUGH */ - case('{'): p->flags |= TERMP_NOSPACE; break; default: