-
Notifications
You must be signed in to change notification settings - Fork 83
Description
Description
When repeatedly writing escape-heavy output (SGR sequences, 256-color, truecolor) to the terminal followed by scrolling, new rows can display stale cell data from previously used page memory. This manifests as content from old rows appearing horizontally merged into current rows.
Root cause
In Screen.zig, cursorDownScroll() only clears new row cells when the cursor has a non-default background color (bg_color != .none). When programs reset attributes with ESC[0m (which sets bg_color = .none), pages.grow() extends existing pages by appending rows whose cell memory still contains data from previously erased rows. These stale cells are never cleared and become visible on lines that aren't fully overwritten (e.g., empty lines from bare \r\n sequences with default cursor style).
Symptoms
- Content from previous rows appears merged horizontally into current rows
- Bug is transient — self-corrects on the next write to that row
- Bug is periodic — frequency depends on column width (e.g., ~every 11 writes at cols=160)
- Affects all column widths at different frequencies
Reproduction
- Create a terminal (any reasonable size, e.g. 160x39)
- Repeatedly write escape-heavy output containing SGR color sequences followed by
ESC[0mresets - After enough repetitions to trigger
pages.grow(), inspect viewport rows - Some rows will contain horizontally concatenated content from two different terminal lines
Expected behavior
New rows created during scrolling should always have clean/empty cells regardless of cursor style.
Fix
Draft PR with fix and regression tests: #134