Skip to content

Stale cell data visible on new rows after scrolling with default cursor style #138

@darrinm

Description

@darrinm

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

  1. Create a terminal (any reasonable size, e.g. 160x39)
  2. Repeatedly write escape-heavy output containing SGR color sequences followed by ESC[0m resets
  3. After enough repetitions to trigger pages.grow(), inspect viewport rows
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions