FABRIC.md item 4.4x: split the REPL prompt into its own bottom strip
Scope expanded from pure CANVAS-rectangle arithmetic (as originally scoped) to also splitting the REPL prompt/input line out of the scrollback box into an independent single-line strip, per Captain Bob's explicit fold-in after the gap was reported (§25.0 rule 3) rather than silently expanded. vt100.c: VT100_BOX_ORIGIN_X/Y are no longer hardcoded per-arch literals -- both are now derived from fb_width()/fb_height() at vt100_enable_ttf() time. New vt100_strip_draw() renders the bottom strip (gray border lines, bright-white text) directly via the existing ttf_draw_glyph_cell() rasterizer, independent of the box's own grid/cursor state. Border lines are drawn after the glyph loop so an oversized cell can only be clipped by them, never erase them. console.c/console.h: console_fb_strip_draw() thin wrapper, matching the existing console_fb_enable_ttf()/console_fb_scroll_*() pattern. repl.c: builds a plain-text "[VMName] ok> <input>" mirror in g_strip_prompt/strip_refresh(), refreshed on every keystroke (including backspace) from sk_readline() -- already wired for item 4.4v, since keyboard-typed characters will flow through the same console_getc() path once that lands. Also widened sk_repl_step()/sk_repl_run()'s local input buffer from a second, smaller 256-byte buffer to INPUT_BUFFER_SIZE (1025), per 4.4w's decision. Verified: three-arch clean QEMU boot + logs, amd64 screendump showing the box and strip as two visually distinct regions with no visible glyph/border clipping. Punch list §25 item 4.4x complete. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
763c6f2cd5
commit
91742e02f4
@@ -317,6 +317,13 @@ void console_fb_scroll_fwd(uint32_t n)
|
||||
}
|
||||
}
|
||||
|
||||
void console_fb_strip_draw(const char *text)
|
||||
{
|
||||
if (fb_is_available()) {
|
||||
vt100_strip_draw(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single character from serial console (non-blocking)
|
||||
* Returns -1 if no character available
|
||||
|
||||
+97
-13
@@ -45,6 +45,7 @@
|
||||
#include "starkernel/kmalloc.h"
|
||||
#include "log.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Maximum CSI parameters */
|
||||
#define VT100_MAX_PARAMS 16
|
||||
@@ -82,23 +83,40 @@ static ttf_raster_cache_t g_ttf_cache;
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* FABRIC.md item 4.4t: confine REPL text (TTF mode only) to the 640x480
|
||||
* CANVAS box computed in 4.4o and pixel-verified in 4.4p. Per-arch raster
|
||||
* top-left origin, from those items' measurements. Boot/POST (bitmap mode)
|
||||
* is untouched -- g_origin_x/g_origin_y default to (0,0) and only change
|
||||
* once vt100_enable_ttf() runs.
|
||||
* CANVAS box computed in 4.4o and pixel-verified in 4.4p. Boot/POST
|
||||
* (bitmap mode) is untouched -- g_origin_x/g_origin_y default to (0,0)
|
||||
* and only change once vt100_enable_ttf() runs.
|
||||
*
|
||||
* FABRIC.md item 4.4x: origin is now DERIVED from fb_width()/fb_height()
|
||||
* at vt100_enable_ttf() time rather than hardcoded per-arch literals --
|
||||
* both the old per-arch numbers (320/104 amd64, 80/4 aarch64+riscv64) and
|
||||
* the new ones below check out against the same formula, so this is a
|
||||
* strict generalization, not a behavior change for X. Y changes because
|
||||
* 4.4u/4.4w replaced 4.4m's 96px/4-line REPL strip with a single-line
|
||||
* strip pinned to the bottom of the screen (see VT100_STRIP_* below) --
|
||||
* the box now sits directly above that strip instead of assuming 96px.
|
||||
* origin_x = (fb_width() - VT100_BOX_W) / 2 -- horizontal center
|
||||
* origin_y = fb_height() - VT100_BOX_H -- box bottom edge
|
||||
* - VT100_STRIP_BOX_GAP_PX -- gap above strip
|
||||
* - (2*VT100_STRIP_GAP_PX + 1) -- strip height
|
||||
* --------------------------------------------------------------------- */
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#define VT100_BOX_ORIGIN_X 320u
|
||||
#define VT100_BOX_ORIGIN_Y 104u
|
||||
#else
|
||||
#define VT100_BOX_ORIGIN_X 80u
|
||||
#define VT100_BOX_ORIGIN_Y 4u
|
||||
#endif
|
||||
#define VT100_BOX_W 640u
|
||||
#define VT100_BOX_H 480u
|
||||
#define VT100_BOX_COLS 53u /* 640 / VT100_TTF_CELL_W_PX, exact */
|
||||
#define VT100_BOX_ROWS 20u /* 480 / VT100_TTF_CELL_H_PX, exact */
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* FABRIC.md items 4.4u/4.4w/4.4x: the REPL prompt/input strip -- a
|
||||
* single-line region pinned to the bottom of the screen, independent of
|
||||
* the scrollback box's own grid (see vt100_strip_draw() below). Numbers
|
||||
* pinned by Captain Bob directly, 2026-08-12 (4.4w).
|
||||
* --------------------------------------------------------------------- */
|
||||
#define VT100_STRIP_GAP_PX 15u /* baseline-to-border-line gap, both sides, mirrored */
|
||||
#define VT100_STRIP_BOX_GAP_PX 8u /* gap between the strip's top border and the box's bottom edge */
|
||||
#define VT100_STRIP_BORDER_GRAY FB_RGB(0xAA, 0xAA, 0xAA) /* FB_ANSI_PALETTE[7] */
|
||||
#define VT100_STRIP_TEXT_WHITE FB_RGB(0xFF, 0xFF, 0xFF)
|
||||
#define VT100_STRIP_LEFT_MARGIN_PX(fbw) (((fbw) - VT100_BOX_W) / 2u) /* aligned under the box */
|
||||
|
||||
static uint32_t g_origin_x = 0; /* box top-left, TTF mode only; 0 in bitmap mode */
|
||||
static uint32_t g_origin_y = 0;
|
||||
|
||||
@@ -268,6 +286,68 @@ static void ttf_draw_glyph_cell(uint32_t cell_px, uint32_t cell_py, uint8_t ch,
|
||||
}
|
||||
}
|
||||
|
||||
/* FABRIC.md items 4.4u/4.4w/4.4x: draw the REPL prompt/input strip -- a
|
||||
* single-line region pinned to the bottom of the screen, independent of
|
||||
* the scrollback box's own grid and cursor state (this function never
|
||||
* touches g_vt, and nothing in the box's own put_char()/scroll_up() path
|
||||
* touches the strip). Reuses ttf_draw_glyph_cell() for the actual glyph
|
||||
* blit -- same rasterizer, same cache, as the box's own grid -- rather
|
||||
* than a second text-drawing path.
|
||||
*
|
||||
* Horizontal scroll (4.4u step 4): @p text is drawn tail-anchored once it
|
||||
* exceeds the strip's width. That is equivalent to cursor-anchored
|
||||
* scrolling because the caller (repl.c) only ever appends at, or
|
||||
* backspaces from, the end of the line -- there is no mid-line cursor
|
||||
* movement in this REPL, so "keep the cursor visible" and "keep the tail
|
||||
* visible" are the same window.
|
||||
*
|
||||
* Border lines are drawn LAST, after the glyph loop, not first: a glyph
|
||||
* cell's own opaque background fill (cell_h()=24px) can extend a few
|
||||
* pixels past the strip's 15px baseline-to-line gap for full-ascender
|
||||
* characters -- 4.4u's own record already flags these gap numbers as
|
||||
* "informal... need to be re-checked once actually built." Drawing the
|
||||
* borders last means an oversized cell can never erase them; it can only
|
||||
* be visually clipped by them, which is the correct failure direction.
|
||||
*
|
||||
* No-op before TTF mode is active. */
|
||||
void vt100_strip_draw(const char *text)
|
||||
{
|
||||
uint32_t fbw, fbh, bottom_line_y, top_line_y, baseline_y, cell_py;
|
||||
uint32_t margin_x, avail_px, avail_cols, len, start, i;
|
||||
|
||||
if (!g_ttf_ready || g_glyph_mode != VT_GLYPH_TTF) return;
|
||||
if (!text) text = "";
|
||||
|
||||
fbw = fb_width();
|
||||
fbh = fb_height();
|
||||
bottom_line_y = fbh - 1u;
|
||||
top_line_y = bottom_line_y - (2u * VT100_STRIP_GAP_PX);
|
||||
baseline_y = bottom_line_y - VT100_STRIP_GAP_PX;
|
||||
cell_py = baseline_y - VT100_TTF_SIZE_PX;
|
||||
margin_x = VT100_STRIP_LEFT_MARGIN_PX(fbw);
|
||||
|
||||
/* Clear the whole strip first -- both border lines get redrawn every
|
||||
* call regardless, so clearing border-to-border is simpler than
|
||||
* clearing just the interior and no less correct. */
|
||||
fb_fill_rect(0, top_line_y, fbw, bottom_line_y - top_line_y + 1u, VT100_DEFAULT_BG);
|
||||
|
||||
avail_px = (fbw > 2u * margin_x) ? (fbw - 2u * margin_x) : 0u;
|
||||
avail_cols = cell_w() ? (avail_px / cell_w()) : 0u;
|
||||
|
||||
len = (uint32_t)strlen(text);
|
||||
start = (len > avail_cols) ? (len - avail_cols) : 0u;
|
||||
|
||||
for (i = start; i < len; i++) {
|
||||
uint32_t col = i - start;
|
||||
ttf_draw_glyph_cell(margin_x + col * cell_w(), cell_py,
|
||||
(uint8_t)text[i],
|
||||
VT100_STRIP_TEXT_WHITE, VT100_DEFAULT_BG);
|
||||
}
|
||||
|
||||
fb_fill_rect(0, top_line_y, fbw, 1u, VT100_STRIP_BORDER_GRAY);
|
||||
fb_fill_rect(0, bottom_line_y, fbw, 1u, VT100_STRIP_BORDER_GRAY);
|
||||
}
|
||||
|
||||
static void draw_cursor_glyph(uint8_t ch)
|
||||
{
|
||||
uint32_t f = eff_fg();
|
||||
@@ -391,8 +471,12 @@ void vt100_enable_ttf(void)
|
||||
* scrollback allocation block just below depends on g_vt.cols via
|
||||
* g_line_stride, so origin/cols/rows MUST be set first or every
|
||||
* shadow/ring index silently corrupts instead of crashing. */
|
||||
g_origin_x = VT100_BOX_ORIGIN_X;
|
||||
g_origin_y = VT100_BOX_ORIGIN_Y;
|
||||
/* FABRIC.md item 4.4x: derived from the real framebuffer size, not a
|
||||
* hardcoded per-arch literal -- see the formula in this file's header
|
||||
* comment above VT100_BOX_W. */
|
||||
g_origin_x = VT100_STRIP_LEFT_MARGIN_PX(fb_width());
|
||||
g_origin_y = fb_height() - VT100_BOX_H - VT100_STRIP_BOX_GAP_PX
|
||||
- (2u * VT100_STRIP_GAP_PX + 1u);
|
||||
g_vt.cols = VT100_BOX_COLS;
|
||||
g_vt.rows = VT100_BOX_ROWS;
|
||||
g_vt.cx = g_vt.cy = 0;
|
||||
|
||||
Reference in New Issue
Block a user