=================================================================== RCS file: /cvs/mandoc/Attic/mdocterm.c,v retrieving revision 1.16 retrieving revision 1.24 diff -u -p -r1.16 -r1.24 --- mandoc/Attic/mdocterm.c 2009/02/27 08:20:15 1.16 +++ mandoc/Attic/mdocterm.c 2009/03/02 12:09:32 1.24 @@ -1,4 +1,4 @@ -/* $Id: mdocterm.c,v 1.16 2009/02/27 08:20:15 kristaps Exp $ */ +/* $Id: mdocterm.c,v 1.24 2009/03/02 12:09:32 kristaps Exp $ */ /* * Copyright (c) 2008 Kristaps Dzonsons * @@ -16,6 +16,8 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include + #include #include #include @@ -36,6 +38,7 @@ #define TERMSYM_LARROW "<-" #define TERMSYM_RARROW "->" #define TERMSYM_UARROW "^" +#define TERMSYM_DARROW "v" #define TERMSYM_LSQUOTE "`" #define TERMSYM_RSQUOTE "\'" #define TERMSYM_SQUOTE "\'" @@ -52,7 +55,8 @@ #define TERMSYM_GRAVE "`" #define TERMSYM_PI "pi" #define TERMSYM_PLUSMINUS "+=" -#define TERMSYM_INFINITY "infinity" +#define TERMSYM_INF "oo" +#define TERMSYM_INF2 "infinity" #define TERMSYM_NAN "NaN" #define TERMSYM_BAR "|" #define TERMSYM_BULLET "o" @@ -81,6 +85,7 @@ static void footer(struct termp *, static void pword(struct termp *, const char *, size_t); static void pescape(struct termp *, const char *, size_t *, size_t); +static void pgraph(struct termp *, char); static void nescape(struct termp *, const char *, size_t); static void chara(struct termp *, char); @@ -108,7 +113,7 @@ main(int argc, char *argv[]) if (NULL == (mdoc = mmain_mdoc(p))) mmain_exit(p, 1); - termp.maxrmargin = 80; /* XXX */ + termp.maxrmargin = 78; /* XXX */ termp.rmargin = termp.maxrmargin; termp.maxcols = 1024; termp.offset = termp.col = 0; @@ -169,9 +174,10 @@ flushln(struct termp *p) for (i = 0; i < p->col; i++) { /* * Count up visible word characters. Control sequences - * (starting with the CSI) aren't counted. + * (starting with the CSI) aren't counted. A space + * generates a non-printing word, which is valid (the + * space is printed according to regular spacing rules). */ - assert( ! xisspace(p->buf[i])); /* LINTED */ for (j = i, vsz = 0; j < p->col; j++) { @@ -183,27 +189,35 @@ flushln(struct termp *p) } else vsz++; } - assert(vsz > 0); /* + * If we're breaking normally... + * * If a word is too long and we're within a line, put it * on the next line. Puke if we're being asked to write * something that will exceed the right margin (i.e., - * from a fresh line or when we're not allowed to break - * the line with TERMP_NOBREAK). + * from a fresh line). + * + * If we're not breaking... + * + * Don't let the visible size exceed the full right + * margin. */ - /* FIXME: allow selective right-margin breaking. */ - - if (vis && vis + vsz > maxvis) { - if (p->flags & TERMP_NOBREAK) + if ( ! (TERMP_NOBREAK & p->flags)) { + if (vis && vis + vsz > maxvis) { + putchar('\n'); + for (j = 0; j < p->offset; j++) + putchar(' '); + vis = 0; + } else if (vis + vsz > maxvis) errx(1, "word breaks right margin"); + } else if (vis + vsz > p->maxrmargin - p->offset) { putchar('\n'); - for (j = 0; j < p->offset; j++) + for (j = 0; j < p->rmargin; j++) putchar(' '); - vis = 0; - } else if (vis + vsz > maxvis) - errx(1, "word breaks right margin"); + vis = p->rmargin; + } /* * Write out the word and a trailing space. Omit the @@ -222,15 +236,22 @@ flushln(struct termp *p) } } + if ((TERMP_NOBREAK & p->flags) && vis >= maxvis) { + putchar('\n'); + for (i = 0; i < p->rmargin; i++) + putchar(' '); + p->col = 0; + return; + } + /* * If we're not to right-marginalise it (newline), then instead * pad to the right margin and stay off. */ if (p->flags & TERMP_NOBREAK) { - if ( ! (p->flags & TERMP_NORPAD)) - for ( ; vis < maxvis; vis++) - putchar(' '); + for ( ; vis < maxvis; vis++) + putchar(' '); } else putchar('\n'); @@ -338,50 +359,70 @@ nescape(struct termp *p, const char *word, size_t len) stringa(p, TERMSYM_RBRACK); else if ('l' == word[0] && 'B' == word[1]) stringa(p, TERMSYM_LBRACK); + else if ('l' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_LDQUOTE); + else if ('r' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_RDQUOTE); + else if ('o' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_LSQUOTE); + else if ('a' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_RSQUOTE); else if ('<' == word[0] && '-' == word[1]) stringa(p, TERMSYM_LARROW); else if ('-' == word[0] && '>' == word[1]) stringa(p, TERMSYM_RARROW); - else if ('l' == word[0] && 'q' == word[1]) - stringa(p, TERMSYM_DQUOTE); - else if ('r' == word[0] && 'q' == word[1]) - stringa(p, TERMSYM_DQUOTE); else if ('b' == word[0] && 'u' == word[1]) stringa(p, TERMSYM_BULLET); - else if ('L' == word[0] && 'e' == word[1]) - stringa(p, TERMSYM_LE); else if ('<' == word[0] && '=' == word[1]) stringa(p, TERMSYM_LE); - else if ('G' == word[0] && 'e' == word[1]) - stringa(p, TERMSYM_GE); else if ('>' == word[0] && '=' == word[1]) stringa(p, TERMSYM_GE); - else if ('R' == word[0] && 'q' == word[1]) - stringa(p, TERMSYM_RDQUOTE); - else if ('L' == word[0] && 'q' == word[1]) - stringa(p, TERMSYM_LDQUOTE); + else if ('=' == word[0] && '=' == word[1]) + stringa(p, TERMSYM_EQ); + else if ('+' == word[0] && '-' == word[1]) + stringa(p, TERMSYM_PLUSMINUS); else if ('u' == word[0] && 'a' == word[1]) stringa(p, TERMSYM_UARROW); + else if ('d' == word[0] && 'a' == word[1]) + stringa(p, TERMSYM_DARROW); else if ('a' == word[0] && 'a' == word[1]) stringa(p, TERMSYM_ACUTE); else if ('g' == word[0] && 'a' == word[1]) stringa(p, TERMSYM_GRAVE); - else if ('P' == word[0] && 'i' == word[1]) - stringa(p, TERMSYM_PI); - else if ('N' == word[0] && 'e' == word[1]) + else if ('!' == word[0] && '=' == word[1]) stringa(p, TERMSYM_NEQ); - else if ('L' == word[0] && 't' == word[1]) - stringa(p, TERMSYM_LT); + else if ('i' == word[0] && 'f' == word[1]) + stringa(p, TERMSYM_INF); + else if ('n' == word[0] && 'a' == word[1]) + stringa(p, TERMSYM_NAN); + else if ('b' == word[0] && 'a' == word[1]) + stringa(p, TERMSYM_BAR); + + /* Deprecated forms. */ + else if ('B' == word[0] && 'a' == word[1]) + stringa(p, TERMSYM_BAR); + else if ('I' == word[0] && 'f' == word[1]) + stringa(p, TERMSYM_INF2); + else if ('G' == word[0] && 'e' == word[1]) + stringa(p, TERMSYM_GE); else if ('G' == word[0] && 't' == word[1]) stringa(p, TERMSYM_GT); - else if ('P' == word[0] && 'm' == word[1]) - stringa(p, TERMSYM_PLUSMINUS); - else if ('I' == word[0] && 'f' == word[1]) - stringa(p, TERMSYM_INFINITY); + else if ('L' == word[0] && 'e' == word[1]) + stringa(p, TERMSYM_LE); + else if ('L' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_LDQUOTE); + else if ('L' == word[0] && 't' == word[1]) + stringa(p, TERMSYM_LT); else if ('N' == word[0] && 'a' == word[1]) stringa(p, TERMSYM_NAN); - else if ('B' == word[0] && 'a' == word[1]) - stringa(p, TERMSYM_BAR); + else if ('N' == word[0] && 'e' == word[1]) + stringa(p, TERMSYM_NEQ); + else if ('P' == word[0] && 'i' == word[1]) + stringa(p, TERMSYM_PI); + else if ('P' == word[0] && 'm' == word[1]) + stringa(p, TERMSYM_PLUSMINUS); + else if ('R' == word[0] && 'q' == word[1]) + stringa(p, TERMSYM_RDQUOTE); break; default: break; @@ -390,6 +431,26 @@ nescape(struct termp *p, const char *word, size_t len) static void +pgraph(struct termp *p, char byte) +{ + int i; + + switch (byte) { + case (' '): + chara(p, ' '); + break; + case ('\t'): + for (i = 0; i < INDENT; i++) + chara(p, ' '); + break; + default: + warnx("unknown non-graphing character"); + break; + } +} + + +static void pescape(struct termp *p, const char *word, size_t *i, size_t len) { size_t j; @@ -441,6 +502,10 @@ pescape(struct termp *p, const char *word, size_t *i, /* FALLTHROUGH */ case ('.'): chara(p, word[*i]); + break; + case ('e'): + chara(p, '\\'); + break; default: break; } @@ -460,8 +525,6 @@ pword(struct termp *p, const char *word, size_t len) { size_t i; - /*assert(len > 0);*/ /* Can be, if literal. */ - /* * Handle pwords, partial words, which may be either a single * word or a phrase that cannot be broken down (such as a @@ -490,6 +553,10 @@ pword(struct termp *p, const char *word, size_t len) pescape(p, word, &i, len); continue; } + if ( ! isgraph((int)word[i])) { + pgraph(p, word[i]); + continue; + } chara(p, word[i]); } @@ -530,7 +597,14 @@ word(struct termp *p, const char *word) if ( ! xisspace(word[i])) { j++; continue; + } + + /* Escaped spaces don't delimit... */ + if (i > 0 && xisspace(word[i]) && '\\' == word[i - 1]) { + j++; + continue; } + if (0 == j) continue; assert(i >= j); @@ -652,15 +726,21 @@ footer(struct termp *p, const struct mdoc_meta *meta) static void header(struct termp *p, const struct mdoc_meta *meta) { - char *buf, *title, *bufp; + char *buf, *title, *bufp, *vbuf; const char *pp; + struct utsname uts; + p->rmargin = p->maxrmargin; + p->offset = 0; + if (NULL == (buf = malloc(p->rmargin))) err(1, "malloc"); if (NULL == (title = malloc(p->rmargin))) err(1, "malloc"); + if (NULL == (vbuf = malloc(p->rmargin))) + err(1, "malloc"); - if (NULL == (pp = mdoc_vol2a(meta->vol))) + if (NULL == (pp = mdoc_vol2a(meta->vol))) { switch (meta->msec) { case (MSEC_1): /* FALLTHROUGH */ @@ -685,12 +765,21 @@ header(struct termp *p, const struct mdoc_meta *meta) pp = mdoc_vol2a(VOL_KM); break; default: - /* FIXME: capitalise. */ - if (NULL == (pp = mdoc_msec2a(meta->msec))) - pp = mdoc_msec2a(MSEC_local); break; } + } + vbuf[0] = 0; + if (pp) { + if (-1 == uname(&uts)) + err(1, "uname"); + (void)strlcat(vbuf, uts.sysname, p->rmargin); + (void)strlcat(vbuf, " ", p->rmargin); + } else if (NULL == (pp = mdoc_msec2a(meta->msec))) + pp = mdoc_msec2a(MSEC_local); + + (void)strlcat(vbuf, pp, p->rmargin); + /* * The header is strange. It has three components, which are * really two with the first duplicated. It goes like this: @@ -706,9 +795,9 @@ header(struct termp *p, const struct mdoc_meta *meta) if (mdoc_arch2a(meta->arch)) (void)snprintf(buf, p->rmargin, "%s (%s)", - pp, mdoc_arch2a(meta->arch)); + vbuf, mdoc_arch2a(meta->arch)); else - (void)strlcpy(buf, pp, p->rmargin); + (void)strlcpy(buf, vbuf, p->rmargin); pp = mdoc_msec2a(meta->msec); @@ -745,5 +834,6 @@ header(struct termp *p, const struct mdoc_meta *meta) p->flags &= ~TERMP_NOSPACE; free(title); + free(vbuf); free(buf); }