grid: a row-local shift moves one row of a multi-row OSC 66 block #24

Closed
opened 2026-10-04 17:50:20 +09:00 by natsukium · 0 comments
Owner

ICH, DCH and the IRM insert shift only the cursor row. An OSC 66 character with s>=2 spans several rows, so a shift on one of them moves that row of the block and leaves the others where they were. The block's cells then no longer line up under its primary: sized_block_at finds the primary but the footprint it computes covers the wrong cells, and the renderer draws a torn glyph.

Repro (3×10): \e]66;s=2;A\a\e[1;1H\e[@ moves the top row of A's 2×2 block right by one and leaves the bottom row in place.

The cut at a shift's boundaries is handled (#12: a block a boundary crosses is erased whole). What remains is an uncut multi-row block inside the shifted span. kitty erases every multi-line multicell character intersecting a row-local shift (nuke_multiline_char_intersecting_with in screen_insert_characters / screen_delete_characters); the same rule here would be: before a row-local shift, clear every sized block with rows > 1 that intersects [cur, edge) on that row. DECIC/DECDC and SL/SR shift every row of the region and move such a block whole unless the region's top or bottom cuts it, which is the same vertical-seam question for scroll regions.

ICH, DCH and the IRM insert shift only the cursor row. An OSC 66 character with `s>=2` spans several rows, so a shift on one of them moves that row of the block and leaves the others where they were. The block's cells then no longer line up under its primary: `sized_block_at` finds the primary but the footprint it computes covers the wrong cells, and the renderer draws a torn glyph. Repro (3×10): `\e]66;s=2;A\a\e[1;1H\e[@` moves the top row of A's 2×2 block right by one and leaves the bottom row in place. The cut at a shift's boundaries is handled (#12: a block a boundary crosses is erased whole). What remains is an *uncut* multi-row block inside the shifted span. kitty erases every multi-line multicell character intersecting a row-local shift (`nuke_multiline_char_intersecting_with` in `screen_insert_characters` / `screen_delete_characters`); the same rule here would be: before a row-local shift, clear every sized block with `rows > 1` that intersects `[cur, edge)` on that row. DECIC/DECDC and SL/SR shift every row of the region and move such a block whole unless the region's top or bottom cuts it, which is the same vertical-seam question for scroll regions.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis#24
No description provided.