Erase what the text layer drew: three GUI bugs, one cause
The sink painted glyphs on top of whatever was already on the renderer and
never erased anything, and the host deliberately does not clear the frame so a
DRAW survives. The grid was always correct; the screen kept the previous
frame. That surfaced as three separate-looking faults:
- a backspaced character stayed on screen, including across a line wrap
- a scroll left the old rows behind, "papered over with garbage"
- the editing cursor smeared an underscore along every column it passed
through, which read as an underline under the text being typed
render() now fills each row it is about to draw, and each row that has emptied
since it last drew, with the background first. Row by row rather than one
clear over the whole area: the text layer is authoritative over the rows it
occupies and leaves every other pixel alone, so a picture behind the text
loses only the strips the text uses instead of all of it.
echo_line() also truncates rows that hold nothing but the spaces its own erase
pass wrote, which is what backspacing back across a wrap leaves behind. A row
of spaces is text as far as render() is concerned, so it would have been
repainted forever and kept erasing whatever was under it.
The cursor glyph is removed outright, as asked. The smearing was the erase bug
rather than the cursor, so one could come back and behave -- a block would
read better than an underscore.
Four pixel-level tests, because grid assertions could never have caught any of
this. Each was checked by reverting the fix and watching it fail; two of them
were vacuous when first written and are noted as such where they are fixed.
The real-keyboard test also now rubs out a character and scrolls forty lines.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,8 +108,37 @@ if ! await "lower" 15; then
|
||||
fail "lower case did not survive the keyboard: composed text is not reaching the editor"
|
||||
fi
|
||||
|
||||
# Backspace, end to end and through what it produces rather than what it draws.
|
||||
# Typing PRINX, rubbing out the X and finishing the word only runs if backspace
|
||||
# actually removed a character from the line buffer -- otherwise this is a
|
||||
# syntax error. Reported as "the backspace key does not clear the character
|
||||
# underneath it".
|
||||
type_line '30 PRINX'$'\b''T "BS OK"'
|
||||
type_line 'RUN'
|
||||
if ! await "BS OK" 15; then
|
||||
echo "--- what the driver actually wrote ---"
|
||||
tr -d '\r' < "${OUT}" 2>/dev/null | sed -n '1,30p'
|
||||
fail "backspace did not remove a character: the line reached the parser unedited"
|
||||
fi
|
||||
|
||||
# More lines than the window has rows, so the text has to scroll. Checked
|
||||
# through stdout, which proves the interpreter kept running across the scroll;
|
||||
# that the *screen* scrolls correctly is asserted at pixel level in
|
||||
# tests/akgl_frontend.c, which can read the render target back and this cannot.
|
||||
type_line '40 FOR I# = 1 TO 40'
|
||||
type_line '50 PRINT "SCROLL"'
|
||||
type_line '60 NEXT I#'
|
||||
type_line 'RUN 40'
|
||||
if ! await "SCROLL" 20; then
|
||||
echo "--- what the driver actually wrote ---"
|
||||
tr -d '\r' < "${OUT}" 2>/dev/null | sed -n '1,30p'
|
||||
fail "a program long enough to scroll the window produced nothing"
|
||||
fi
|
||||
COUNT="$(tr -d '\r' < "${OUT}" | grep -c '^SCROLL$')"
|
||||
[ "${COUNT}" -eq 40 ] || fail "expected 40 scrolled lines, got ${COUNT}"
|
||||
|
||||
type_line 'QUIT'
|
||||
await "" 1 >/dev/null 2>&1 || true
|
||||
|
||||
echo "PASS: typed at a real focused window and the interpreter ran it"
|
||||
echo "PASS: typed at a real focused window; backspace, scrolling and RUN all worked"
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user