aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/term_ps.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-10-27 20:41:58 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-10-27 20:41:58 +0000
commit47d687861577577fa527223c4f420c3b647be931 (patch)
tree669bae5092e4211112710f87514fbbaea782abfc /term_ps.c
parent581ec294b3151ee015247639a62753ba3748aa44 (diff)
downloadmandoc-47d687861577577fa527223c4f420c3b647be931.tar.gz
mandoc-47d687861577577fa527223c4f420c3b647be931.tar.zst
mandoc-47d687861577577fa527223c4f420c3b647be931.zip
Support overstriking by backspace in PostScript and PDF output.
Of course, this is only a minor improvement; it would be much better to support non-ASCII characters in these output modes, but that would require major changes that i'm not going to work on right now. The main reason for doing this is that it allows to get ASCII output closer to groff.
Diffstat (limited to 'term_ps.c')
-rw-r--r--term_ps.c78
1 files changed, 62 insertions, 16 deletions
diff --git a/term_ps.c b/term_ps.c
index e1803038..e27c8119 100644
--- a/term_ps.c
+++ b/term_ps.c
@@ -1,4 +1,4 @@
-/* $Id: term_ps.c,v 1.66 2014/08/28 01:37:12 schwarze Exp $ */
+/* $Id: term_ps.c,v 1.67 2014/10/27 20:41:58 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -59,12 +59,13 @@ struct termp_ps {
#define PS_INLINE (1 << 0) /* we're in a word */
#define PS_MARGINS (1 << 1) /* we're in the margins */
#define PS_NEWPAGE (1 << 2) /* new page, no words yet */
+#define PS_BACKSP (1 << 3) /* last character was backspace */
size_t pscol; /* visible column (AFM units) */
size_t psrow; /* visible row (AFM units) */
char *psmarg; /* margin buf */
size_t psmargsz; /* margin buf size */
size_t psmargcur; /* cur index in margin buf */
- char last; /* character buffer */
+ char last; /* last non-backspace seen */
enum termfont lastf; /* last set font */
enum termfont nextf; /* building next font here */
size_t scale; /* font scaling factor */
@@ -1047,7 +1048,7 @@ ps_fclose(struct termp *p)
*/
if (p->ps->last != '\0') {
- assert(p->ps->last != 8);
+ assert( ! (p->ps->flags & PS_BACKSP));
if (p->ps->nextf != p->ps->lastf) {
ps_pclose(p);
ps_setfont(p, p->ps->nextf);
@@ -1066,25 +1067,30 @@ ps_fclose(struct termp *p)
static void
ps_letter(struct termp *p, int arg)
{
+ size_t savecol;
char c;
c = arg >= 128 || arg <= 0 ? '?' : arg;
/*
- * When receiving an initial character, merely buffer it,
- * because a backspace might follow to specify formatting.
- * When receiving a backspace, use the buffered character
- * to build the font instruction and clear the buffer.
- * Only when there are two non-backspace characters in a row,
- * activate the font built so far and print the first of them;
- * the second, again, merely gets buffered.
- * The final character will get printed from ps_fclose().
+ * When receiving a backspace, merely flag it.
+ * We don't know yet whether it is
+ * a font instruction or an overstrike.
*/
- if (c == 8) {
+ if (c == '\b') {
assert(p->ps->last != '\0');
- assert(p->ps->last != 8);
- if ('_' == p->ps->last) {
+ assert( ! (p->ps->flags & PS_BACKSP));
+ p->ps->flags |= PS_BACKSP;
+ return;
+ }
+
+ /*
+ * Decode font instructions.
+ */
+
+ if (p->ps->flags & PS_BACKSP) {
+ if (p->ps->last == '_') {
switch (p->ps->nextf) {
case TERMFONT_BI:
break;
@@ -1094,7 +1100,11 @@ ps_letter(struct termp *p, int arg)
default:
p->ps->nextf = TERMFONT_UNDER;
}
- } else {
+ p->ps->last = c;
+ p->ps->flags &= ~PS_BACKSP;
+ return;
+ }
+ if (p->ps->last == c) {
switch (p->ps->nextf) {
case TERMFONT_BI:
break;
@@ -1104,8 +1114,26 @@ ps_letter(struct termp *p, int arg)
default:
p->ps->nextf = TERMFONT_BOLD;
}
+ p->ps->flags &= ~PS_BACKSP;
+ return;
}
- } else if (p->ps->last != '\0' && p->ps->last != 8) {
+
+ /*
+ * This is not a font instruction, but rather
+ * the next character. Prepare for overstrike.
+ */
+
+ savecol = p->ps->pscol;
+ } else
+ savecol = SIZE_MAX;
+
+ /*
+ * We found the next character, so the font instructions
+ * for the previous one are complete.
+ * Use them and print it.
+ */
+
+ if (p->ps->last != '\0') {
if (p->ps->nextf != p->ps->lastf) {
ps_pclose(p);
ps_setfont(p, p->ps->nextf);
@@ -1113,7 +1141,25 @@ ps_letter(struct termp *p, int arg)
p->ps->nextf = TERMFONT_NONE;
ps_pletter(p, p->ps->last);
}
+
+ /*
+ * Do not print the current character yet because font
+ * instructions might follow; only remember it.
+ * For the first character, nothing else is done.
+ * The final character will get printed from ps_fclose().
+ */
+
p->ps->last = c;
+
+ /*
+ * For an overstrike, back up to the previous position.
+ */
+
+ if (savecol != SIZE_MAX) {
+ ps_pclose(p);
+ p->ps->pscol = savecol;
+ p->ps->flags &= ~PS_BACKSP;
+ }
}
static void