- The theme/font request globals (gThemeChange*, gFont*Request,
gFontChangePending, gCurrentFont*, gFontDialogRequested): only Qt
read them.
- The font-picker-toggle command: it only set gFontDialogRequested, so
it did nothing in kge or kte.
- The terminal :font and :font-size recorded requests nothing read and
answered "Font requested"; they now say fonts are not available in
the terminal.
- kte::DisplayColumns, added for Qt's drawing and now unused.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ImGui measured every span, highlight and the cursor from column 0 of the
line (and rescanned the line for each column conversion), which is
quadratic in line length on minified files. Columns now come from one
table per line and pixel offsets from the nearest position already
measured. Output is pixel-identical to before (compared under Xvfb, with
syntax colouring, tabs, UTF-8 and search highlights).
kte::kTabWidth replaces the literal 8s, and Qt's 4: Qt expanded tabs to
4 columns while the command layer scrolled by 8, misplacing the cursor
and horizontal scroll on lines with tabs. MeasureChar and
DisplayColumns (TermWidth.h) are the command layer's column model, now
shared, and Qt draws by it instead of one column per byte, which
shifted everything after a multi-byte character.
Qt also:
- drew operators in the dark-mode background colour, so they vanished;
- computed the editor's column count three ways (different glyph,
padding and status-row accounting) from painting, and positioned text
with a rounded cell width, so the cursor drifted off the glyphs on long
lines. One TextLayout now serves painting, resizing, font changes and
wheel scrolling, with a fractional cell width; runs are drawn only
where visible;
- drew each non-ASCII character at its cell, since a fallback-font glyph
wider than a cell pushed the rest of the run out of place.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
- C0 controls and DEL were passed to ncurses, which acted on them: a
carriage return moved to column 0 and the line padding then erased
the text, so every line of a CRLF file drew blank, and a backspace
ate the previous character. They are now drawn in caret notation
(^M, ^H, ^?) and counted as two cells. C1 controls (and stray bytes
0x80-0x9F, which decode to them; U+009B is CSI) are drawn as '?'.
- The width rule lives in TermWidth.h and is shared by the renderer's
drawing loop, its cursor placement and the command layer's
horizontal scrolling and mouse mapping, which also disagreed on NUL
and invalid bytes.
- GUI config: columns/rows must be 1..1000 and the font size a finite
4..200 (TOML 'size = inf' and huge values were accepted, leading to
UB in float-to-int conversion and int overflow downstream).
Verified in tmux: a CRLF file now shows 'first line^M' where the
baseline showed a blank line.
Audit findings B9 (and the CR/BS case from the follow-up review).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB