=================================================================== RCS file: /cvs/mandoc/term.c,v retrieving revision 1.185 retrieving revision 1.196 diff -u -p -r1.185 -r1.196 --- mandoc/term.c 2011/04/29 22:18:12 1.185 +++ mandoc/term.c 2011/05/20 15:44:55 1.196 @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.185 2011/04/29 22:18:12 kristaps Exp $ */ +/* $Id: term.c,v 1.196 2011/05/20 15:44:55 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -33,13 +33,11 @@ #include "term.h" #include "main.h" -static void spec(struct termp *, const char *, size_t); -static void res(struct termp *, const char *, size_t); -static void bufferc(struct termp *, char); -static void adjbuf(struct termp *p, size_t); -static void encode(struct termp *, const char *, size_t); +static void adjbuf(struct termp *p, int); +static void bufferc(struct termp *, char); +static void encode(struct termp *, const char *, size_t); +static void encode1(struct termp *, int); - void term_free(struct termp *p) { @@ -72,18 +70,6 @@ term_end(struct termp *p) (*p->end)(p); } - -struct termp * -term_alloc(enum termenc enc) -{ - struct termp *p; - - p = mandoc_calloc(1, sizeof(struct termp)); - p->enc = enc; - return(p); -} - - /* * 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 @@ -155,12 +141,12 @@ term_flushln(struct termp *p) vis = vend = 0; i = 0; - while (i < (int)p->col) { + while (i < p->col) { /* * Handle literal tab characters: collapse all * subsequent tabs into a single huge set of spaces. */ - while (i < (int)p->col && '\t' == p->buf[i]) { + while (i < p->col && '\t' == p->buf[i]) { vend = (vis / p->tabwidth + 1) * p->tabwidth; vbl += vend - vis; vis = vend; @@ -174,7 +160,7 @@ term_flushln(struct termp *p) * space is printed according to regular spacing rules). */ - for (j = i, jhy = 0; j < (int)p->col; j++) { + for (j = i, jhy = 0; j < p->col; j++) { if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j]) break; @@ -217,7 +203,7 @@ term_flushln(struct termp *p) } /* Write out the [remaining] word. */ - for ( ; i < (int)p->col; i++) { + for ( ; i < p->col; i++) { if (vend > bp && jhy > 0 && i > jhy) break; if ('\t' == p->buf[i]) @@ -344,44 +330,6 @@ term_vspace(struct termp *p) (*p->endline)(p); } - -static void -numbered(struct termp *p, const char *word, size_t len) -{ - const char *rhs; - - rhs = mchars_num2char(word, len); - if (rhs) - encode(p, rhs, 1); -} - - -static void -spec(struct termp *p, const char *word, size_t len) -{ - const char *rhs; - size_t sz; - - rhs = mchars_spec2str(p->symtab, word, len, &sz); - if (rhs) - encode(p, rhs, sz); - else if (1 == len) - encode(p, word, len); -} - - -static void -res(struct termp *p, const char *word, size_t len) -{ - const char *rhs; - size_t sz; - - rhs = mchars_res2str(p->symtab, word, len, &sz); - if (rhs) - encode(p, rhs, sz); -} - - void term_fontlast(struct termp *p) { @@ -446,7 +394,6 @@ term_fontpop(struct termp *p) p->fonti--; } - /* * Handle pwords, partial words, which may be either a single word or a * phrase that cannot be broken down (such as a literal string). This @@ -455,8 +402,9 @@ term_fontpop(struct termp *p) void term_word(struct termp *p, const char *word) { - const char *seq; - int sz; + const char *seq, *cp; + char c; + int sz, uc; size_t ssz; enum mandoc_esc esc; @@ -491,15 +439,50 @@ term_word(struct termp *p, const char *word) if (ESCAPE_ERROR == esc) break; + if (TERMENC_ASCII != p->enc) + switch (esc) { + case (ESCAPE_UNICODE): + uc = mchars_num2uc(seq + 1, sz - 1); + if ('\0' == uc) + break; + encode1(p, uc); + continue; + case (ESCAPE_PREDEF): + uc = mchars_res2cp(p->symtab, seq, sz); + if (uc <= 0) + break; + encode1(p, uc); + continue; + case (ESCAPE_SPECIAL): + uc = mchars_spec2cp(p->symtab, seq, sz); + if (uc <= 0) + break; + encode1(p, uc); + continue; + default: + break; + } + switch (esc) { + case (ESCAPE_UNICODE): + encode1(p, '?'); + break; case (ESCAPE_NUMBERED): - numbered(p, seq, sz); + c = mchars_num2char(seq, sz); + if ('\0' != c) + encode(p, &c, 1); break; case (ESCAPE_PREDEF): - res(p, seq, sz); + cp = mchars_res2str(p->symtab, seq, sz, &ssz); + if (NULL != cp) + encode(p, cp, ssz); break; case (ESCAPE_SPECIAL): - spec(p, seq, sz); + cp = mchars_spec2str(p->symtab, seq, sz, &ssz); + if (NULL != cp) + encode(p, cp, ssz); + else if (1 == ssz) + encode(p, seq, sz); break; case (ESCAPE_FONTBOLD): term_fontrepl(p, TERMFONT_BOLD); @@ -507,6 +490,8 @@ term_word(struct termp *p, const char *word) case (ESCAPE_FONTITALIC): term_fontrepl(p, TERMFONT_UNDER); break; + case (ESCAPE_FONT): + /* FALLTHROUGH */ case (ESCAPE_FONTROMAN): term_fontrepl(p, TERMFONT_NONE); break; @@ -523,9 +508,8 @@ term_word(struct termp *p, const char *word) } } - static void -adjbuf(struct termp *p, size_t sz) +adjbuf(struct termp *p, int sz) { if (0 == p->maxcols) @@ -533,10 +517,10 @@ adjbuf(struct termp *p, size_t sz) while (sz >= p->maxcols) p->maxcols <<= 2; - p->buf = mandoc_realloc(p->buf, p->maxcols); + p->buf = mandoc_realloc + (p->buf, sizeof(int) * (size_t)p->maxcols); } - static void bufferc(struct termp *p, char c) { @@ -544,16 +528,45 @@ bufferc(struct termp *p, char c) if (p->col + 1 >= p->maxcols) adjbuf(p, p->col + 1); - p->buf[(int)p->col++] = c; + p->buf[p->col++] = c; } +/* + * See encode(). + * Do this for a single (probably unicode) value. + * Does not check for non-decorated glyphs. + */ +static void +encode1(struct termp *p, int c) +{ + enum termfont f; + if (p->col + 4 >= p->maxcols) + adjbuf(p, p->col + 4); + + f = term_fonttop(p); + + if (TERMFONT_NONE == f) { + p->buf[p->col++] = c; + return; + } else if (TERMFONT_UNDER == f) { + p->buf[p->col++] = '_'; + } else + p->buf[p->col++] = c; + + p->buf[p->col++] = 8; + p->buf[p->col++] = c; +} + static void encode(struct termp *p, const char *word, size_t sz) { enum termfont f; - int i; + int i, len; + /* LINTED */ + len = sz; + /* * Encode and buffer a string of characters. If the current * font mode is unset, buffer directly, else encode then buffer @@ -561,35 +574,34 @@ encode(struct termp *p, const char *word, size_t sz) */ if (TERMFONT_NONE == (f = term_fonttop(p))) { - if (p->col + sz >= p->maxcols) - adjbuf(p, p->col + sz); - memcpy(&p->buf[(int)p->col], word, sz); - p->col += sz; + if (p->col + len >= p->maxcols) + adjbuf(p, p->col + len); + for (i = 0; i < len; i++) + p->buf[p->col++] = word[i]; return; } /* Pre-buffer, assuming worst-case. */ - if (p->col + 1 + (sz * 3) >= p->maxcols) - adjbuf(p, p->col + 1 + (sz * 3)); + if (p->col + 1 + (len * 3) >= p->maxcols) + adjbuf(p, p->col + 1 + (len * 3)); - for (i = 0; i < (int)sz; i++) { - if ( ! isgraph((u_char)word[i])) { - p->buf[(int)p->col++] = word[i]; + for (i = 0; i < len; i++) { + if ( ! isgraph((unsigned char)word[i])) { + p->buf[p->col++] = word[i]; continue; } if (TERMFONT_UNDER == f) - p->buf[(int)p->col++] = '_'; + p->buf[p->col++] = '_'; else - p->buf[(int)p->col++] = word[i]; + p->buf[p->col++] = word[i]; - p->buf[(int)p->col++] = 8; - p->buf[(int)p->col++] = word[i]; + p->buf[p->col++] = 8; + p->buf[p->col++] = word[i]; } } - size_t term_len(const struct termp *p, size_t sz) { @@ -602,9 +614,10 @@ size_t term_strlen(const struct termp *p, const char *cp) { size_t sz, rsz, i; - int ssz; - enum mandoc_esc esc; + int ssz, c; const char *seq, *rhs; + enum mandoc_esc esc; + static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' }; /* * Account for escaped sequences within string length @@ -613,15 +626,57 @@ term_strlen(const struct termp *p, const char *cp) */ sz = 0; - while ('\0' != *cp) + while ('\0' != *cp) { + rsz = strcspn(cp, rej); + for (i = 0; i < rsz; i++) + sz += (*p->width)(p, *cp++); + + c = 0; switch (*cp) { case ('\\'): - ++cp; + cp++; esc = mandoc_escape(&cp, &seq, &ssz); if (ESCAPE_ERROR == esc) return(sz); + if (TERMENC_ASCII != p->enc) + switch (esc) { + case (ESCAPE_UNICODE): + c = mchars_num2uc + (seq + 1, ssz - 1); + if ('\0' == c) + break; + sz += (*p->width)(p, c); + continue; + case (ESCAPE_PREDEF): + c = mchars_res2cp + (p->symtab, seq, ssz); + if (c <= 0) + break; + sz += (*p->width)(p, c); + continue; + case (ESCAPE_SPECIAL): + c = mchars_spec2cp + (p->symtab, seq, ssz); + if (c <= 0) + break; + sz += (*p->width)(p, c); + continue; + default: + break; + } + + rhs = NULL; + switch (esc) { + case (ESCAPE_UNICODE): + sz += (*p->width)(p, '?'); + break; + case (ESCAPE_NUMBERED): + c = mchars_num2char(seq, ssz); + if ('\0' != c) + sz += (*p->width)(p, c); + break; case (ESCAPE_PREDEF): rhs = mchars_res2str (p->symtab, seq, ssz, &rsz); @@ -637,7 +692,6 @@ term_strlen(const struct termp *p, const char *cp) rsz = ssz; break; default: - rhs = NULL; break; } @@ -656,14 +710,13 @@ term_strlen(const struct termp *p, const char *cp) cp++; break; default: - sz += (*p->width)(p, *cp++); break; } + } return(sz); } - /* ARGSUSED */ size_t term_vspan(const struct termp *p, const struct roffsu *su) @@ -699,7 +752,6 @@ term_vspan(const struct termp *p, const struct roffsu return(/* LINTED */(size_t) r); } - size_t term_hspan(const struct termp *p, const struct roffsu *su)