A simple, high performance text editor.
On device: scroll far down a wrapped file, relaunch, and the app lands further DOWN than where the user left off — the deeper the scroll, the further off. Root cause: the persisted Scroll is a pixel offset in VISUAL-line space. Restoring maps it through the WrapIndex (scrollDecompose -> LineForVisual), but on relaunch every count is the estimate (1) until the line is shaped, and shaping covers the visible window only — the lines ABOVE the restored viewport are never shaped. With all-ones counts LineForVisual maps the offset 1:1, landing a logical line deeper by every wrapped continuation above the viewport, and the state is stable (the under-counted lines never re-enter the window), so it never self-corrects. The snapshot now persists wrap-independent coordinates: the logical line at the viewport top (derived with the same mapping the layout uses, against the current index, so it is exactly the shown line) plus the sub-line remainder. The restore re-derives the offset as line*lh + sub, which maps to the saved line under any wrap state (all-ones or populated). The raw Dp offset is kept for pre-line-coordinate session files (loadSession defaults the missing key to -1; BeginRestore rejects the ambiguous zero value: a genuine line-0 snapshot always has Scroll < lh). TestRestore_ScrollSurvivesWrapState reproduces it: 150 lines recorded as wrapped x3, viewport at logical line 200 (visual 500); a relaunch with a fresh WrapIndex must land the window on line 200. Fails pre-fix (window at line 254, i.e. deeper) and passes with the fix. Docs: spec §2.4 (line-based scroll persist + current save policy), architecture §6.7 (why the offset is unrestorable by re-mapping). |
||
|---|---|---|
| .qwen | ||
| cmd/pad | ||
| doc | ||
| internal | ||
| scripts | ||
| .DS_Store | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||