Skip to content

fix(addon-serialize): restore the cursor after a full row without a relative move - #6205

Open
Tongering wants to merge 1 commit into
xtermjs:masterfrom
Tongering:fix/addon-serialize-cursor-pending-wrap
Open

Tongering wants to merge 1 commit into
xtermjs:masterfrom
Tongering:fix/addon-serialize-cursor-pending-wrap

Conversation

@Tongering

Copy link
Copy Markdown

Fixes #6165.

Problem

SerializeAddon restores the cursor with a relative move computed as
realCursorCol - _lastCursorCol. When the serialized stream ends on a full row, the
replayed cursor sits in the pending-wrap sentinel column (cursorX === cols), and
_lastCursorCol is cols as well. A relative CSI n D issued from that state collapses
the sentinel first and then moves, so the cursor lands one column short and all following
output shifts left.

Measured on master: with cursorX === cols, CSI 1 D lands on column 8, while
CSI 10 G lands on column 9.

Minimal repro (also added as a unit test):

cursor after writing XY
source [9, 0] ABCDEFGHIX / Y
restored (before) [8, 0] ABCDEFGHXY / (empty)

Fix

When the tracked column is at or past cols, the column is set with CSI <col+1> G
instead of a relative move.

Why not clamp _lastCursorCol

I first tried clamping the tracked column to cols - 1. That is worse: it discards the
sentinel entirely, so the restored terminal has no pending wrap and the next character
wraps to the following row instead of overwriting the last cell.

Verification

  • the new unit test fails on master and passes with the fix
  • npm run test-unit -- addons/addon-serialize/out-esbuild/SerializeAddon.test.js → 45 passing
  • npm run test-unit → all green
  • npm run lint → Found 0 warnings and 0 errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serialize addon restores a cursor one column left after a full-row write

1 participant