=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.137 retrieving revision 1.141 diff -u -p -r1.137 -r1.141 --- mandoc/term.c 2010/05/17 22:11:42 1.137 +++ mandoc/term.c 2010/06/07 10:52:44 1.141 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.137 2010/05/17 22:11:42 kristaps Exp $ */ +/* $Id: term.c,v 1.141 2010/06/07 10:52:44 kristaps Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,7 @@ #include "mdoc.h" #include "main.h" -static struct termp *term_alloc(enum termenc, size_t); +static struct termp *term_alloc(char *, enum termenc); static void term_free(struct termp *); static void spec(struct termp *, const char *, size_t); static void res(struct termp *, const char *, size_t); @@ -46,10 +47,10 @@ static void encode(struct termp *, const char *, si void * -ascii_alloc(size_t width) +ascii_alloc(char *outopts) { - return(term_alloc(TERMENC_ASCII, width)); + return(term_alloc(outopts, TERMENC_ASCII)); } @@ -75,16 +76,35 @@ term_free(struct termp *p) static struct termp * -term_alloc(enum termenc enc, size_t width) +term_alloc(char *outopts, enum termenc enc) { - struct termp *p; + struct termp *p; + const char *toks[2]; + char *v; + size_t width; + toks[0] = "width"; + toks[1] = NULL; + p = calloc(1, sizeof(struct termp)); if (NULL == p) { perror(NULL); exit(EXIT_FAILURE); } + + p->tabwidth = 5; p->enc = enc; + width = 80; + + while (outopts && *outopts) + switch (getsubopt(&outopts, UNCONST(toks), &v)) { + case (0): + width = atoi(v); + break; + default: + break; + } + /* Enforce some lower boundary. */ if (width < 60) width = 60; @@ -137,6 +157,7 @@ term_flushln(struct termp *p) size_t vend; /* end of word visual position on output */ size_t bp; /* visual right border position */ int j; /* temporary loop index */ + int jhy; /* last hyphen before line overflow */ size_t maxvis, mmax; /* @@ -171,6 +192,17 @@ term_flushln(struct termp *p) while (i < (int)p->col) { /* + * Handle literal tab characters. + */ + for (j = i; j < (int)p->col; j++) { + if ('\t' != p->buf[j]) + break; + vend = (vis/p->tabwidth+1)*p->tabwidth; + vbl += vend - vis; + vis = vend; + } + + /* * Count up visible word characters. Control sequences * (starting with the CSI) aren't counted. A space * generates a non-printing word, which is valid (the @@ -178,27 +210,32 @@ term_flushln(struct termp *p) */ /* LINTED */ - for (j = i; j < (int)p->col; j++) { - if (j && ' ' == p->buf[j]) + for (jhy = 0; j < (int)p->col; j++) { + if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j]) break; - if (8 == p->buf[j]) - vend--; - else + if (8 != p->buf[j]) { + if (vend > vis && vend < bp && + ASCII_HYPH == p->buf[j]) + jhy = j; vend++; + } else + vend--; } /* * Find out whether we would exceed the right margin. * If so, break to the next line. */ - if (vend > bp && vis > 0) { + if (vend > bp && 0 == jhy && vis > 0) { vend -= vis; putchar('\n'); if (TERMP_NOBREAK & p->flags) { + p->viscol = p->rmargin; for (j = 0; j < (int)p->rmargin; j++) putchar(' '); vend += p->rmargin - p->offset; } else { + p->viscol = 0; vbl = p->offset; } @@ -209,8 +246,18 @@ term_flushln(struct termp *p) p->overstep = 0; } + /* + * Skip leading tabs, they were handled above. + */ + while (i < (int)p->col && '\t' == p->buf[i]) + i++; + /* Write out the [remaining] word. */ for ( ; i < (int)p->col; i++) { + if (vend > bp && jhy > 0 && i > jhy) + break; + if ('\t' == p->buf[i]) + break; if (' ' == p->buf[i]) { while (' ' == p->buf[i]) { vbl++; @@ -231,9 +278,16 @@ term_flushln(struct termp *p) if (vbl) { for (j = 0; j < (int)vbl; j++) putchar(' '); + p->viscol += vbl; vbl = 0; } - putchar(p->buf[i]); + + if (ASCII_HYPH == p->buf[i]) + putchar('-'); + else + putchar(p->buf[i]); + + p->viscol += 1; } vend += vbl; vis = vend; @@ -243,6 +297,7 @@ term_flushln(struct termp *p) p->overstep = 0; if ( ! (TERMP_NOBREAK & p->flags)) { + p->viscol = 0; putchar('\n'); return; } @@ -274,11 +329,13 @@ term_flushln(struct termp *p) /* Right-pad. */ if (maxvis > vis + /* LINTED */ - ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) + ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) { + p->viscol += maxvis - vis; for ( ; vis < maxvis; vis++) putchar(' '); - else { /* ...or newline break. */ + } else { /* ...or newline break. */ putchar('\n'); + p->viscol = p->rmargin; for (i = 0; i < (int)p->rmargin; i++) putchar(' '); } @@ -295,7 +352,7 @@ term_newln(struct termp *p) { p->flags |= TERMP_NOSPACE; - if (0 == p->col) { + if (0 == p->col && 0 == p->viscol) { p->flags &= ~TERMP_NOLPAD; return; } @@ -315,6 +372,7 @@ term_vspace(struct termp *p) { term_newln(p); + p->viscol = 0; putchar('\n'); }