1. The combination \z\h is a no-op whatever the argument may be.
In the past, the \z only affected the first space character generated
by the \h, which was wrong.
2. For the conbination \zX\h with a positive argument, the first
space resulting from the \h is not printed but consumed by the \z.
3. For the combination \zX\h with a negative argument, application
of the \z needs to be completed before the \h can be started.
In the past, if this combination occurred at the beginning of an
output line, the \h backed up to the beginning of the line and
after that, the \z attempted to back up even further, triggering
an assertion.
Bugs found during an audit of assignments to termp->col that i
started after the bugfix tbl_term.c rev. 1.65. The assertion
triggered by bug 3 was *not* yet found by afl(1).
-# $OpenBSD: Makefile,v 1.18 2022/04/13 13:11:33 schwarze Exp $
+# $OpenBSD: Makefile,v 1.19 2022/04/27 13:30:19 schwarze Exp $
-REGRESS_TARGETS = one two multi B bs_man bs_mdoc c c_man E1 e f h l O1 o p w z
+REGRESS_TARGETS = one two multi
+REGRESS_TARGETS += B bs_man bs_mdoc c c_man E1 e f h hneg l O1 o p w z
REGRESS_TARGETS += ignore invalid unsupp
HTML_TARGETS = f
LINT_TARGETS = B h l O1 w ignore invalid unsupp
+# mandoc defect:
+# - \h with a negative argument replaces output characters
+# instead of overstriking them
+
+SKIP_GROFF = hneg
+
.include <bsd.regress.mk>
--- /dev/null
+.\" $OpenBSD: hneg.in,v 1.1 2022/04/27 13:30:19 schwarze Exp $
+.Dd $Mdocdate: April 27 2022 $
+.Dt ESC-HNEG 1
+.Os
+.Sh NAME
+.Nm esc-hneg
+.Nd the roff escape h sequence with a negative argument
+.Sh DESCRIPTION
+simple: >abc\h'-3'd<
+.br
+after z escape: >ab\zc\h'-2'd<
--- /dev/null
+ESC-HNEG(1) General Commands Manual ESC-HNEG(1)
+
+N\bNA\bAM\bME\bE
+ e\bes\bsc\bc-\b-h\bhn\bne\beg\bg - the roff escape h sequence with a negative argument
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+ simple: >d<c
+ after z escape: >d<c
+
+OpenBSD April 27, 2022 OpenBSD
-.\" $OpenBSD: z.in,v 1.3 2017/07/04 14:53:27 schwarze Exp $
-.Dd $Mdocdate: July 4 2017 $
+.\" $OpenBSD: z.in,v 1.4 2022/04/27 13:30:19 schwarze Exp $
+.Dd $Mdocdate: April 27 2022 $
.Dt ESC-Z 1
.Os
.Sh NAME
.br
single z with overstrike: >\z\o'ab'c<
.br
+single z with h escape: >\z\h'3'm\z\h'-3'<
+.br
+single z with char and h with positive argument: >\za\h'3'b<
+.br
+single z with char and h with zero argument: >\za\h'0'b<
+.br
single z near the end of the line: >\z<
.br
double z: >\z\zx<
single z with font escape: >x\bx\bb\bbo\bol\bld\bd<
single z with nospace escape: > new line<
single z with overstrike: >a\bb\bc<
+ single z with h escape: >m<
+ single z with char and h with positive argument: >a b<
+ single z with char and h with zero argument: >a\bb<
single z near the end of the line: ><
double z: >x\b<
-OpenBSD July 4, 2017 OpenBSD
+OpenBSD April 27, 2022 OpenBSD
-/* $OpenBSD: term.c,v 1.145 2022/01/10 17:59:45 schwarze Exp $ */
+/* $OpenBSD: term.c,v 1.146 2022/04/27 13:30:19 schwarze Exp $ */
/*
* Copyright (c) 2010-2022 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
encode(p, "utf8", 4);
continue;
case ESCAPE_HORIZ:
+ if (p->flags & TERMP_BACKAFTER) {
+ p->flags &= ~TERMP_BACKAFTER;
+ continue;
+ }
if (*seq == '|') {
seq++;
uc = -p->col;
if (a2roffsu(seq, &su, SCALE_EM) == NULL)
continue;
uc += term_hen(p, &su);
- if (uc > 0) {
+ if (uc >= 0) {
while (uc > 0) {
- bufferc(p, ASCII_NBRSP);
uc -= term_len(p, 1);
+ if (p->flags & TERMP_BACKBEFORE)
+ p->flags &= ~TERMP_BACKBEFORE;
+ else
+ bufferc(p, ASCII_NBRSP);
}
- } else if (p->col > (size_t)(-uc)) {
+ continue;
+ }
+ if (p->flags & TERMP_BACKBEFORE) {
+ p->flags &= ~TERMP_BACKBEFORE;
+ assert(p->col > 0);
+ p->col--;
+ }
+ if (p->col >= (size_t)(-uc)) {
p->col += uc;
} else {
uc += p->col;