What
The line editor was byte-oriented end to end, so multibyte UTF-8 (accented Latin, CJK, emoji) was broken three ways:
- Input: bytes ≥ 0x80 fell through the key-dispatch
elsearm and were dropped — you couldn't even typecafé. - Cursor: Left/Right moved one byte, landing inside a codepoint.
- Deletion: backspace/deleteChar removed one byte → dangling continuation byte (corrupt text); cursor reposition counted bytes not display columns, over-shooting past multibyte chars.
Adds UTF-8 helpers (isUtf8Continuation, utf8SeqLen, prevCodepointLen, curCodepointLen) and:
insertUtf8(lead)assembles a full codepoint (reading continuation bytes) and inserts it atomically; wired via a0xC2...0xF4dispatch arm.moveCursorLeft/Rightstep one whole codepoint.backspace/deleteCharremove the whole codepoint at/before the cursor.- insert/backspace/delete reposition the cursor by display columns (one per codepoint), not bytes.
ASCII is unchanged (every helper returns 1 for ASCII bytes).
Verification
zig buildclean (exit 0).- PTY: typing
echo caféprintscafé; one Backspace →caf; withecho Xé, Left+Left thenA→AXé; ASCII regressionecho abXcd→ mid-line backspace →aXcdstill works.
Scope: byte-vs-codepoint correctness. Wide-character (CJK/emoji width-2) column alignment — treating one codepoint as two columns — is a separate follow-up; this treats one codepoint as one column, correct for accented Latin and the common cases.