- Package: clayterm
- Version: v0.6.0 (reproduced on
main @ d75fb4b)
- Runtime: Deno 2.x
- OS: platform-independent (WASM); reproduced on macOS
Describe the bug
When a glyph is floated onto the trailing column of an already-placed wide character, the overwrite is swallowed and the wide char is left dangling. On a 12x1 buffer, 你好 places 你 across cols 0-1 and 好 across cols 2-3; floating X onto col 1 (the trailing column of 你) emits \x1b[1;1H你\x1b[1;3H好... with no X anywhere. In a real terminal 你 then paints over both columns and fully hides the intended overlay. Overwriting a wide char's lead column already renders correctly, since the back buffer resets to spaces each frame; only the trailing-column case is broken.
To Reproduce
Render 你好 on a 12x1 buffer, then float X at col 1. The grid expects " X好 " but gets "你 好 ", and the byte stream contains no X.
Expected behavior
The orphaned lead column collapses to a space and the overlay glyph is actually emitted, so 你好 with X at col 1 renders " X好". Total row advance width is unchanged. Rows with no overlapping writes on wide chars stay byte-for-byte identical, and the cleanup only activates on a detected partial overwrite.
Additional Information
Failing test case on nm/repro/wide-char-overlay (test · diff).
The cell buffer has no continuation-cell marker (src/cell.h:8-12), so a trailing column is an unbacked implicit skip rather than an addressable placeholder. The fix likely lives in present_cups (src/clayterm.c:166), which advances x += wcwidth(...) past the trailing column (L185-201) and so never revisits or repairs it when overwritten this frame; present_lines (src/clayterm.c:213) has the same skip in line mode (L229-244), and setcell (src/clayterm.c:70) writes one cell without clearing the orphaned lead.
main@ d75fb4b)Describe the bug
When a glyph is floated onto the trailing column of an already-placed wide character, the overwrite is swallowed and the wide char is left dangling. On a 12x1 buffer,
你好places 你 across cols 0-1 and 好 across cols 2-3; floatingXonto col 1 (the trailing column of 你) emits\x1b[1;1H你\x1b[1;3H好...with noXanywhere. In a real terminal 你 then paints over both columns and fully hides the intended overlay. Overwriting a wide char's lead column already renders correctly, since the back buffer resets to spaces each frame; only the trailing-column case is broken.To Reproduce
Render
你好on a 12x1 buffer, then floatXat col 1. The grid expects" X好 "but gets"你 好 ", and the byte stream contains noX.Expected behavior
The orphaned lead column collapses to a space and the overlay glyph is actually emitted, so
你好withXat col 1 renders" X好". Total row advance width is unchanged. Rows with no overlapping writes on wide chars stay byte-for-byte identical, and the cleanup only activates on a detected partial overwrite.Additional Information
Failing test case on
nm/repro/wide-char-overlay(test · diff).The cell buffer has no continuation-cell marker (
src/cell.h:8-12), so a trailing column is an unbacked implicit skip rather than an addressable placeholder. The fix likely lives inpresent_cups(src/clayterm.c:166), which advancesx += wcwidth(...)past the trailing column (L185-201) and so never revisits or repairs it when overwritten this frame;present_lines(src/clayterm.c:213) has the same skip in line mode (L229-244), andsetcell(src/clayterm.c:70) writes one cell without clearing the orphaned lead.