From c22c21c8728aa2cd2b8e093f5ee24da0a3776eed Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Sun, 16 Aug 2026 21:03:03 -0400 Subject: [PATCH] editor: add HandleEnd window-base regression test Cover the base-offset conversion in HandleEnd (the path that slices the full file content by the end-of-line offset), mirroring the tap-to-position regression test. --- internal/editor/cursor_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/internal/editor/cursor_test.go b/internal/editor/cursor_test.go index 993fe68..be30249 100644 --- a/internal/editor/cursor_test.go +++ b/internal/editor/cursor_test.go @@ -154,6 +154,39 @@ func TestTapToPosition_WindowBaseOffset(t *testing.T) { } } +// TestHandleEnd_WindowBaseOffset is a regression test for the window-relative +// GlyphLayout bug in HandleEnd. The layout covers only the visible window +// (base = IMEWindowStartByte), so its ByteOffsets are window-relative. +// HandleEnd converts the end-of-line position to an absolute file offset +// (base + window offset) before using it to index the full file content. +// Before the fix it used the window-relative offset, landing on the previous +// line's newline. +func TestHandleEnd_WindowBaseOffset(t *testing.T) { + lh := float64(EditorLineHeight()) + // File: line0 "AAAAAAAA\n" (bytes 0-8), line1 "BBBBBBBB\n" (bytes 9-17). + // Window starts at byte 9 (line 1). Window-relative offsets: B=0..7, \n=8. + gl := ui.GlyphLayout{LineHeight: EditorLineHeight()} + for i := 0; i < 9; i++ { + gl.ByteOffsets = append(gl.ByteOffsets, i) + gl.X = append(gl.X, ui.Dp(10+10*i)) + gl.Y = append(gl.Y, ui.Dp(lh)) // single visual line + gl.Advance = append(gl.Advance, 10) + } + TheState = NewState() + TheState.Editor.Buffer = "AAAAAAAA\nBBBBBBBB\n" + TheState.Editor.GlyphLayout = gl + TheState.Editor.IMEWindowStartByte = 9 + TheState.Editor.CursorPosition = 12 // line 1, 4th B (absolute) + + HandleEnd() + + // The end of line 1 is its newline at absolute byte 17. Before the fix the + // window-relative offset (8) indexed the previous line's newline (byte 8). + if TheState.Editor.CursorPosition != 17 { + t.Errorf("HandleEnd cursor = %d, want 17 (newline ending line 1); window-relative offset bug?", TheState.Editor.CursorPosition) + } +} + // TestTapToPosition_LargeFileScrolled is the end-to-end regression: with a // window-relative GlyphLayout and a deep scroll, a tap a few lines below the top // of the window must land on that window line, NOT be clamped to the last window