FABRIC-2.md §I.9 follow-on: blinking | cursor instead of static block
Build / build-riscv64-img (push) Canceled after 0s
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s

Captain Bob asked for the framebuffer cursor to render as a blinking
vertical bar rather than the previous static solid-block glyph.

vt100_draw_cursor() (hal/vt100.c) now fills a thin bar (cell_w()/8, min
1px, full cell height) at the cursor's left edge instead of the whole
cell -- an I-beam shape. vt100_erase_cursor() is unchanged (clearing the
whole cell already safely covers the narrower bar).

Blinking is new in repl.c: sk_console_readline()'s idle branch toggles the
cursor on/off every SK_CURSOR_BLINK_INTERVAL (50 ticks, 500ms at 100Hz)
via alternating console_fb_draw_cursor()/console_fb_erase_cursor() calls,
independent of the heartbeat/idle-beat mechanism the §I.9 fix just touched
(deliberately not reused, to avoid recoupling to that path). Runs
regardless of n, so it blinks whether sitting at a bare prompt or paused
mid-edit. Every deterministic draw site (initial prompt, prompt reanchor,
backspace, character echo) now goes through a new helper, sk_cursor_show(),
which resets the blink cycle to "on" and redraws -- typing always shows a
solid cursor, never mid-blink.

Verified via the mandatory foreground 3-arch QEMU acceptance boot: amd64
(logs/20260905-021054, extensive live interactive typing including
multi-line : / ; word definitions and error cases, prompts stayed
correctly attached throughout), aarch64 (logs/20260905-021551), riscv64
(logs/20260905-022324) -- all three reached (zuse) ok> and shut down
cleanly via BYE.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
Robert Allan James
2026-09-05 02:24:51 -04:00
co-authored by Claude Sonnet 5
parent 8edb95b65d
commit 70dc8beba4
11 changed files with 27059 additions and 15 deletions
+14 -10
View File
@@ -354,20 +354,24 @@ static void draw_cursor_glyph(uint8_t ch)
}
}
/* Solid block cursor at the current position (g_vt.cx, g_vt.cy). Not
* blinking -- a static indicator, simplest thing that actually shows
* where typed input lands, callable as often as the caller likes since
* it is idempotent (always draws the same thing at the current position).
* A character typed at this position naturally overwrites it --
* draw_cursor_glyph() always fills the whole cell with bg before drawing
* a glyph -- but *leaving* this position without drawing a character
* (Enter/newline) does not, which is what vt100_erase_cursor() below is
* for. No-op outside TTF mode or graphics mode (4.4ab's
/* Thin vertical-bar ("I-beam") cursor at the current position (g_vt.cx,
* g_vt.cy) -- 2026-09-05, replaces the earlier solid block glyph per
* request. Idempotent (always draws the same bar at the current
* position), so callable as often as the caller likes; blinking (repl.c,
* sk_console_readline()'s idle loop) is layered on top by alternating
* calls to this and vt100_erase_cursor() on a timer, not by anything in
* here. A character typed at this position naturally overwrites the bar
* -- draw_cursor_glyph() always fills the whole cell with bg before
* drawing a glyph -- but *leaving* this position without drawing a
* character (Enter/newline) does not, which is what vt100_erase_cursor()
* below is for. No-op outside TTF mode or graphics mode (4.4ab's
* g_terminal_visible), matching every other draw call in this file. */
void vt100_draw_cursor(void)
{
if (!g_terminal_visible || g_glyph_mode != VT_GLYPH_TTF) return;
fb_fill_rect(px_of(g_vt.cx), py_of(g_vt.cy), cell_w(), cell_h(), eff_fg());
uint32_t bar_w = cell_w() / 8u;
if (bar_w < 1u) bar_w = 1u;
fb_fill_rect(px_of(g_vt.cx), py_of(g_vt.cy), bar_w, cell_h(), eff_fg());
}
/* Erases whatever vt100_draw_cursor() last drew at the current position,