Summary
When a line has both a breakpoint AND an active LSP diagnostic, the TUI rasteriser overwrites column 0 of the gutter with the diagnostic dot, hiding the breakpoint indicator. GTK shows both at slightly different x positions.
Repro
- Set a breakpoint on a line that also has an LSP error/warning.
- Compare TUI vs GTK in the same file.
Expected
Both indicators visible in both backends — either side-by-side (GTK behaviour) or with one consistently winning across both backends.
Actual
- GTK — both visible. BP
● from gutter_text paints at rect.x + 3.0; diagnostic arc paints at rect.x + 3.0 + dot_r (centered circle), slightly offset, both readable.
- TUI — diagnostic dot wins.
quadraui::tui::draw_editor paints the BP character (from gutter_text[0]) at area.x, then the diagnostic loop calls set_cell(buf, area.x, ...) which fully overwrites the cell.
Origin
Pre-existing behaviour, predates #276. The Stage 1 lift ported it verbatim from render_impl::render_window. Code path in quadraui/src/tui/editor.rs::draw_editor:
```rust
// Gutter loop paints BP at column 0 from gutter_text...
set_cell(buf, gx, screen_y, ch, fg, line_bg);
// ...then diagnostic icon overwrites column 0:
if let Some(severity) = editor.diagnostic_gutter.get(&line.line_idx) {
set_cell(buf, area.x, screen_y, '●', diag_color, line_bg);
}
```
The line above this comment was the verbatim port note // Diagnostic gutter icon (overwrite leftmost gutter char) — the comment confirms the overwrite was intentional in the original, but it wasn't aware of the BP-column case.
Fix direction
Two options:
- TUI: shift diagnostic dot to its own column (preferred — matches GTK). When `editor.has_breakpoints` is true, paint the diagnostic dot at `area.x + bp_column_width` (skipping the BP column) so both are visible.
- TUI: keep current overwrite but only when `!has_breakpoints`. Less code, but keeps the divergence in cases where there's no BP column.
Option 1 is cleaner and produces cross-backend visual parity.
Surface affected
`quadraui/src/tui/editor.rs` (the diagnostic gutter icon block, ~line 159).
Why now
Surfaced during smoke testing for #276 (Phase C Stage 1).
Summary
When a line has both a breakpoint AND an active LSP diagnostic, the TUI rasteriser overwrites column 0 of the gutter with the diagnostic dot, hiding the breakpoint indicator. GTK shows both at slightly different x positions.
Repro
Expected
Both indicators visible in both backends — either side-by-side (GTK behaviour) or with one consistently winning across both backends.
Actual
●fromgutter_textpaints atrect.x + 3.0; diagnostic arc paints atrect.x + 3.0 + dot_r(centered circle), slightly offset, both readable.quadraui::tui::draw_editorpaints the BP character (fromgutter_text[0]) atarea.x, then the diagnostic loop callsset_cell(buf, area.x, ...)which fully overwrites the cell.Origin
Pre-existing behaviour, predates #276. The Stage 1 lift ported it verbatim from
render_impl::render_window. Code path inquadraui/src/tui/editor.rs::draw_editor:```rust
// Gutter loop paints BP at column 0 from gutter_text...
set_cell(buf, gx, screen_y, ch, fg, line_bg);
// ...then diagnostic icon overwrites column 0:
if let Some(severity) = editor.diagnostic_gutter.get(&line.line_idx) {
set_cell(buf, area.x, screen_y, '●', diag_color, line_bg);
}
```
The line above this comment was the verbatim port note
// Diagnostic gutter icon (overwrite leftmost gutter char)— the comment confirms the overwrite was intentional in the original, but it wasn't aware of the BP-column case.Fix direction
Two options:
Option 1 is cleaner and produces cross-backend visual parity.
Surface affected
`quadraui/src/tui/editor.rs` (the diagnostic gutter icon block, ~line 159).
Why now
Surfaced during smoke testing for #276 (Phase C Stage 1).