diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2012-05-31 22:29:13 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2012-05-31 22:29:13 +0000 |
commit | 151c919ed8cc3ed826972bf9834c86d322c8ea2a (patch) | |
tree | 88cd0e892637ff83ebf37f93c1e552f8572604bb /term.c | |
parent | a72385d7db78c4b91054f655c790402b70f79571 (diff) | |
download | mandoc-151c919ed8cc3ed826972bf9834c86d322c8ea2a.tar.gz |
Implement the roff \z escape sequence, intended to output the next
character without advancing the cursor position; implement it to
simply skip the next character, as it will usually be overwritten.
With this change, the pod2man(1) preamble user-defined string \*:,
intended to render as a diaeresis or umlaut diacritic above the
preceding character, is rendered in a slightly less ugly way,
though still not correctly. It was rendered as "z.." and is now
rendered as ".".
Given that the definition of \*: uses elaborate manual \h positioning,
there is little chance for mandoc(1) to ever render it correctly,
but at least we can refrain from printing out a spurious "z", and
we can make the \z do something semi-reasonable for easier cases.
"just commit" kristaps@
Diffstat (limited to 'term.c')
-rw-r--r-- | term.c | 66 |
1 files changed, 53 insertions, 13 deletions
@@ -33,6 +33,7 @@ #include "term.h" #include "main.h" +static size_t cond_width(const struct termp *, int, int *); static void adjbuf(struct termp *p, int); static void bufferc(struct termp *, char); static void encode(struct termp *, const char *, size_t); @@ -419,12 +420,17 @@ term_word(struct termp *p, const char *word) p->flags &= ~(TERMP_SENTENCE | TERMP_IGNDELIM); while ('\0' != *word) { - if ((ssz = strcspn(word, "\\")) > 0) + if ('\\' != *word) { + if (TERMP_SKIPCHAR & p->flags) { + p->flags &= ~TERMP_SKIPCHAR; + word++; + continue; + } + ssz = strcspn(word, "\\"); encode(p, word, ssz); - - word += (int)ssz; - if ('\\' != *word) + word += (int)ssz; continue; + } word++; esc = mandoc_escape(&word, &seq, &sz); @@ -480,9 +486,14 @@ term_word(struct termp *p, const char *word) term_fontlast(p); break; case (ESCAPE_NOSPACE): - if ('\0' == *word) + if (TERMP_SKIPCHAR & p->flags) + p->flags &= ~TERMP_SKIPCHAR; + else if ('\0' == *word) p->flags |= TERMP_NOSPACE; break; + case (ESCAPE_SKIPCHAR): + p->flags |= TERMP_SKIPCHAR; + break; default: break; } @@ -522,6 +533,11 @@ encode1(struct termp *p, int c) { enum termfont f; + if (TERMP_SKIPCHAR & p->flags) { + p->flags &= ~TERMP_SKIPCHAR; + return; + } + if (p->col + 4 >= p->maxcols) adjbuf(p, p->col + 4); @@ -545,6 +561,11 @@ encode(struct termp *p, const char *word, size_t sz) enum termfont f; int i, len; + if (TERMP_SKIPCHAR & p->flags) { + p->flags &= ~TERMP_SKIPCHAR; + return; + } + /* LINTED */ len = sz; @@ -593,12 +614,22 @@ term_len(const struct termp *p, size_t sz) return((*p->width)(p, ' ') * sz); } +static size_t +cond_width(const struct termp *p, int c, int *skip) +{ + + if (*skip) { + (*skip) = 0; + return(0); + } else + return((*p->width)(p, c)); +} size_t term_strlen(const struct termp *p, const char *cp) { size_t sz, rsz, i; - int ssz, c; + int ssz, skip, c; const char *seq, *rhs; enum mandoc_esc esc; static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' }; @@ -610,10 +641,11 @@ term_strlen(const struct termp *p, const char *cp) */ sz = 0; + skip = 0; while ('\0' != *cp) { rsz = strcspn(cp, rej); for (i = 0; i < rsz; i++) - sz += (*p->width)(p, *cp++); + sz += cond_width(p, *cp++, &skip); c = 0; switch (*cp) { @@ -630,14 +662,14 @@ term_strlen(const struct termp *p, const char *cp) (seq + 1, ssz - 1); if ('\0' == c) break; - sz += (*p->width)(p, c); + sz += cond_width(p, c, &skip); continue; case (ESCAPE_SPECIAL): c = mchars_spec2cp (p->symtab, seq, ssz); if (c <= 0) break; - sz += (*p->width)(p, c); + sz += cond_width(p, c, &skip); continue; default: break; @@ -647,12 +679,12 @@ term_strlen(const struct termp *p, const char *cp) switch (esc) { case (ESCAPE_UNICODE): - sz += (*p->width)(p, '?'); + sz += cond_width(p, '?', &skip); break; case (ESCAPE_NUMBERED): c = mchars_num2char(seq, ssz); if ('\0' != c) - sz += (*p->width)(p, c); + sz += cond_width(p, c, &skip); break; case (ESCAPE_SPECIAL): rhs = mchars_spec2str @@ -664,6 +696,9 @@ term_strlen(const struct termp *p, const char *cp) rhs = seq; rsz = ssz; break; + case (ESCAPE_SKIPCHAR): + skip = 1; + break; default: break; } @@ -671,15 +706,20 @@ term_strlen(const struct termp *p, const char *cp) if (NULL == rhs) break; + if (skip) { + skip = 0; + break; + } + for (i = 0; i < rsz; i++) sz += (*p->width)(p, *rhs++); break; case (ASCII_NBRSP): - sz += (*p->width)(p, ' '); + sz += cond_width(p, ' ', &skip); cp++; break; case (ASCII_HYPH): - sz += (*p->width)(p, '-'); + sz += cond_width(p, '-', &skip); cp++; break; default: |