diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2018-08-25 16:53:38 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2018-08-25 16:53:38 +0000 |
commit | 4a586872ce6f32a40dd13b7fa93c56b7a3ef52d8 (patch) | |
tree | 32b9ab81d75bbad8884825043d06315cd8adc911 /roff.c | |
parent | 870322bd99e8a445ec84289025691baf9352ce27 (diff) | |
download | mandoc-4a586872ce6f32a40dd13b7fa93c56b7a3ef52d8.tar.gz mandoc-4a586872ce6f32a40dd13b7fa93c56b7a3ef52d8.tar.zst mandoc-4a586872ce6f32a40dd13b7fa93c56b7a3ef52d8.zip |
Rudimentary implementation of the roff(7) .char (output glyph
definition) request, used for example by groff_hdtbl(7).
This simplistic implementation may interact incorrectly
with the .tr (input character translation) request.
But come on, you are not only using .char *and* .tr, but you do so
with respect to the same character in the same manual page?
Diffstat (limited to 'roff.c')
-rw-r--r-- | roff.c | 75 |
1 files changed, 73 insertions, 2 deletions
@@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.340 2018/08/24 23:12:33 schwarze Exp $ */ +/* $Id: roff.c,v 1.341 2018/08/25 16:53:39 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org> @@ -176,6 +176,7 @@ static int roff_br(ROFF_ARGS); static int roff_cblock(ROFF_ARGS); static int roff_cc(ROFF_ARGS); static int roff_ccond(struct roff *, int, int); +static int roff_char(ROFF_ARGS); static int roff_cond(ROFF_ARGS); static int roff_cond_text(ROFF_ARGS); static int roff_cond_sub(ROFF_ARGS); @@ -397,7 +398,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_insec, NULL, NULL, 0 }, /* cf */ { roff_line_ignore, NULL, NULL, 0 }, /* cflags */ { roff_line_ignore, NULL, NULL, 0 }, /* ch */ - { roff_unsupp, NULL, NULL, 0 }, /* char */ + { roff_char, NULL, NULL, 0 }, /* char */ { roff_unsupp, NULL, NULL, 0 }, /* chop */ { roff_line_ignore, NULL, NULL, 0 }, /* class */ { roff_insec, NULL, NULL, 0 }, /* close */ @@ -3322,6 +3323,76 @@ roff_cc(ROFF_ARGS) } static int +roff_char(ROFF_ARGS) +{ + const char *p, *kp, *vp; + size_t ksz, vsz; + int font; + + /* Parse the character to be replaced. */ + + kp = buf->buf + pos; + p = kp + 1; + if (*kp == '\0' || (*kp == '\\' && + mandoc_escape(&p, NULL, NULL) != ESCAPE_SPECIAL) || + (*p != ' ' && *p != '\0')) { + mandoc_vmsg(MANDOCERR_CHAR_ARG, r->parse, + ln, pos, "char %s", kp); + return ROFF_IGN; + } + ksz = p - kp; + while (*p == ' ') + p++; + + /* + * If the replacement string contains a font escape sequence, + * we have to restore the font at the end. + */ + + vp = p; + vsz = strlen(p); + font = 0; + while (*p != '\0') { + if (*p++ != '\\') + continue; + switch (mandoc_escape(&p, NULL, NULL)) { + case ESCAPE_FONT: + case ESCAPE_FONTROMAN: + case ESCAPE_FONTITALIC: + case ESCAPE_FONTBOLD: + case ESCAPE_FONTBI: + case ESCAPE_FONTPREV: + font++; + break; + default: + break; + } + } + if (font > 1) + mandoc_msg(MANDOCERR_CHAR_FONT, r->parse, + ln, vp - buf->buf, vp); + + /* + * Approximate the effect of .char using the .tr tables. + * XXX In groff, .char and .tr interact differently. + */ + + if (ksz == 1) { + if (r->xtab == NULL) + r->xtab = mandoc_calloc(128, sizeof(*r->xtab)); + assert((unsigned int)*kp < 128); + free(r->xtab[(int)*kp].p); + r->xtab[(int)*kp].sz = mandoc_asprintf(&r->xtab[(int)*kp].p, + "%s%s", vp, font ? "\fP" : ""); + } else { + roff_setstrn(&r->xmbtab, kp, ksz, vp, vsz, 0); + if (font) + roff_setstrn(&r->xmbtab, kp, ksz, "\\fP", 3, 1); + } + return ROFF_IGN; +} + +static int roff_ec(ROFF_ARGS) { const char *p; |