1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 03:22:48 -05:00

Fix behaviour of backspace in a 1-column terminal.

This is the first bug found as a direct result of writing that
terminal test program - I added some tests for things I expected to
work already, and some of them didn't, proving immediately that it was
a good idea!

If the terminal is one column wide, and you've printed a
character (hence, set the wrapnext flag), what should backspace do?
Surely it should behave like any other backspace with wrapnext set,
i.e. clear the wrapnext flag, returning the cursor's _logical_
position to the location of the most recently printed character. But
in fact it was anti-wrapping to the previous line, because I'd got the
cases in the wrong order in the if-else chain that forms the backspace
handler. So the handler for 'we're in column 0, wrapping time' was
coming before 'wrapnext is set, just clear it'.

Now wrapnext is checked _first_, before checking anything at all. Any
time we can just clear that, we should.
This commit is contained in:
Simon Tatham
2023-03-05 10:01:36 +00:00
parent 9ba742ad9f
commit 069f7c8b21
2 changed files with 55 additions and 3 deletions

View File

@ -326,6 +326,57 @@ static void test_wrap(Mock *mk)
IEQUAL(mk->term->curs.x, 78);
IEQUAL(mk->term->curs.y, 0);
IEQUAL(mk->term->wrapnext, 0);
/*
* Now test the special cases that arise when the terminal is only
* one column wide!
*/
reset(mk);
term_size(mk->term, 24, 1, 0);
mk->term->curs.x = 0;
mk->term->curs.y = 0;
mk->term->wrap = true;
/* Printing a single-width character takes us into wrapnext immediately */
term_datapl(mk->term, PTRLEN_LITERAL("a"));
IEQUAL(mk->term->curs.x, 0);
IEQUAL(mk->term->curs.y, 0);
IEQUAL(mk->term->wrapnext, 1);
IEQUAL(get_lineattr(mk->term, 0), 0);
IEQUAL(get_termchar(mk->term, 0, 0).chr, CSET_ASCII | 'a');
/* Printing a second one wraps, and takes us _back_ to wrapnext */
term_datapl(mk->term, PTRLEN_LITERAL("b"));
IEQUAL(mk->term->curs.x, 0);
IEQUAL(mk->term->curs.y, 1);
IEQUAL(mk->term->wrapnext, 1);
IEQUAL(get_lineattr(mk->term, 0), LATTR_WRAPPED);
IEQUAL(get_termchar(mk->term, 0, 0).chr, CSET_ASCII | 'a');
IEQUAL(get_termchar(mk->term, 0, 1).chr, CSET_ASCII | 'b');
/* Backspacing once clears the wrapnext flag, putting us on the b */
term_datapl(mk->term, PTRLEN_LITERAL("\b"));
IEQUAL(mk->term->curs.x, 0);
IEQUAL(mk->term->curs.y, 1);
IEQUAL(mk->term->wrapnext, 0);
/* Backspacing again returns to the previous line, putting us on the a */
term_datapl(mk->term, PTRLEN_LITERAL("\b"));
IEQUAL(mk->term->curs.x, 0);
IEQUAL(mk->term->curs.y, 0);
IEQUAL(mk->term->wrapnext, 0);
/* And now try with a double-width character */
reset(mk);
term_size(mk->term, 24, 1, 0);
mk->term->curs.x = 0;
mk->term->curs.y = 0;
mk->term->wrap = true;
/* DW character won't fit at all, so it transforms into U+FFFD
* REPLACEMENT CHARACTER and then behaves like a SW char */
term_datapl(mk->term, PTRLEN_LITERAL("\xEA\xB0\x80"));
IEQUAL(mk->term->curs.x, 0);
IEQUAL(mk->term->curs.y, 0);
IEQUAL(mk->term->wrapnext, 1);
IEQUAL(get_lineattr(mk->term, 0), 0);
IEQUAL(get_termchar(mk->term, 0, 0).chr, 0xFFFD);
}
int main(void)