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
@@ -5951,16 +5951,72 @@ document and committing that amendment as its own item.*
|
||||
> words: "as long as there's enough space above and below so it looks right." Not
|
||||
> reopened as a fresh pixel negotiation; the second mockup pass's numbers stand.
|
||||
|
||||
- [ ] **4.4x — Redo 4.4n's CANVAS rectangle for the real (single-line) REPL-strip height.**
|
||||
- [x] **4.4x — Redo 4.4n's CANVAS rectangle for the real (single-line) REPL-strip height, AND
|
||||
split the REPL prompt/input line out of the scrollback box into its own bottom strip.**
|
||||
4.4n's existing CANVAS math assumed 4.4m's 96px/4-line REPL strip; 4.4u replaced that with a
|
||||
single-line strip (4.4w's gap values, once pinned, give the real height — order-of-magnitude
|
||||
20-40px, not 96px). Pure arithmetic against already-decided numbers, not a new design
|
||||
question, but CANVAS's top-left/width/height must be recomputed before any drawing code
|
||||
reads them. Depends on 4.4w (gap values pinned first).
|
||||
*Done when:* a new CANVAS rectangle (top-left, width, height) is computed and recorded per
|
||||
architecture, explicitly superseding 4.4n's numbers the way 4.4n itself is referenced from
|
||||
4.4u as historical record, not edited in place.
|
||||
*Refs:* §27.8, 4.4n, 4.4u, 4.4w.
|
||||
20-40px, not 96px). Depends on 4.4w (gap values pinned first).
|
||||
|
||||
**Scope expanded 2026-08-12, folded in by Captain Bob directly.** Originally scoped as pure
|
||||
arithmetic (recompute the box rectangle, no code). Found while starting this item: today the
|
||||
REPL prompt (`ok>`, cursor, typed input) prints through the exact same `console_puts()` →
|
||||
vt100-grid path as everything else, confined to the box by 4.4t — there is no separate
|
||||
bottom strip in the code at all, so 4.4u's design (box above, independent single-line strip
|
||||
below, separated by the 8px gap) does not exist yet even though the geometry math assumes it
|
||||
does. Reported per §25.0 rule 3 rather than silently expanded; Bob's answer was to fold the
|
||||
split into this item rather than open a new one, since the split is what makes the recomputed
|
||||
geometry meaningful in the first place.
|
||||
*Done when:* `VT100_BOX_ORIGIN_Y` (and confirmation that `_ORIGIN_X`/`_W`/`_H` are unchanged)
|
||||
is recomputed and recorded per architecture below; the REPL prompt/cursor/input line renders
|
||||
in its own single-line strip pinned to the bottom of the screen (row 0 = `fb_height()-1`,
|
||||
gray border lines per 4.4u/4.4w, bright-white text) independent of the scrollback box's own
|
||||
grid; scrollback output continues to render only inside the box. Three-arch QEMU boot + logs
|
||||
per CLAUDE.md; amd64 screendump showing both regions distinctly.
|
||||
*Refs:* §27.8, 4.4n, 4.4u, 4.4w, 4.4t.
|
||||
|
||||
> **DONE 2026-08-12.** `VT100_BOX_ORIGIN_X`/`_ORIGIN_Y` are no longer hardcoded per-arch
|
||||
> literals — both are now derived at `vt100_enable_ttf()` time from `fb_width()`/
|
||||
> `fb_height()` (`vt100.c`):
|
||||
> ```
|
||||
> origin_x = (fb_width() - VT100_BOX_W) / 2
|
||||
> origin_y = fb_height() - VT100_BOX_H - VT100_STRIP_BOX_GAP_PX(8) - (2*VT100_STRIP_GAP_PX(15) + 1)
|
||||
> ```
|
||||
> Confirmed the old per-arch `_ORIGIN_X`/`_W`/`_H` values fall out of the same formula
|
||||
> unchanged (only Y moves, since only the strip height changed): amd64 origin=(320,281)
|
||||
> [was (320,104)], aarch64/riscv64 origin=(80,81) [was (80,4)], both against the same
|
||||
> 800×600/1280×800 resolutions 4.4l already confirmed.
|
||||
>
|
||||
> **The strip split is real, not just geometry.** New `vt100_strip_draw()` (`vt100.c`) draws
|
||||
> the bottom strip directly via the existing `ttf_draw_glyph_cell()` rasterizer (no second
|
||||
> text-drawing path), independent of the box's own grid/cursor. `console_fb_strip_draw()`
|
||||
> (`console.c`/`console.h`) is the thin wrapper, matching the existing
|
||||
> `console_fb_enable_ttf()`/`console_fb_scroll_*()` pattern. `repl.c` builds a plain-text
|
||||
> (no ANSI) `"[VMName] ok> <input>"` mirror in `g_strip_prompt`/`strip_refresh()`, refreshed
|
||||
> on every keystroke from `sk_readline()` (including backspace) — this also means it's
|
||||
> already wired for 4.4v: once the keyboard bridge lands, typed characters flow through the
|
||||
> same `console_getc()` → `sk_readline()` path and the strip updates for free, no further
|
||||
> changes needed here.
|
||||
>
|
||||
> **Also fixed, found while wiring this:** `sk_repl_step()`/`sk_repl_run()`'s local
|
||||
> `char input[256]` was a second, smaller buffer than `INPUT_BUFFER_SIZE`=1025 — the actual
|
||||
> gap 4.4w's decision (full 1025-char buffer, not a smaller practical limit) needed closed.
|
||||
> Widened both to `INPUT_BUFFER_SIZE`.
|
||||
>
|
||||
> **Border-line ordering deliberate:** `vt100_strip_draw()` draws the two gray border lines
|
||||
> *after* the glyph loop, not before — a glyph cell's own opaque background fill (24px tall)
|
||||
> can extend a few pixels past the 15px baseline-to-line gap for full-ascender characters,
|
||||
> and drawing borders last means an oversized cell can only be visually clipped by them, never
|
||||
> erase them. Screendump-verified below: no visible clipping at this font size in practice.
|
||||
>
|
||||
> Three-arch QEMU boot + logs: clean (`logs/20260812-144724/amd64`,
|
||||
> `logs/20260812-144811/aarch64`, `logs/20260812-144922/riscv64`). amd64 screendump
|
||||
> (`logs/screendump-4.4x/amd64-strip.png`) confirms both regions distinctly: scrollback box
|
||||
> with boot/POST history near the top, bottom strip with gray borders and
|
||||
> `[Hera] ok>` in white, clearly separated. aarch64/riscv64 screendump attempted but the
|
||||
> manual ISO build used for it didn't reproduce the Makefile's exact boot chain (unrelated to
|
||||
> this item's code) — not blocking, since the formula is resolution-derived and already
|
||||
> verified correct by direct calculation against both known resolutions, and the real
|
||||
> acceptance boot (via `make qemu`, not a manual screendump) passed clean on all three.
|
||||
|
||||
- [x] **4.4y — Decide the toggle meta-key.** Design-only, no code. 4.4u step 8 left this open —
|
||||
candidates floated were TAB and Ctrl+TAB, Bob explicitly deferred choosing ("we'll figure out
|
||||
|
||||
@@ -90,6 +90,14 @@ void console_fb_enable_ttf(void);
|
||||
void console_fb_scroll_back(uint32_t n);
|
||||
void console_fb_scroll_fwd(uint32_t n);
|
||||
|
||||
/**
|
||||
* FABRIC.md items 4.4u/4.4w/4.4x: thin wrapper over vt100_strip_draw() --
|
||||
* see that function's doc comment for the full contract (the REPL
|
||||
* prompt/input strip, independent of the scrollback box). No-op if the
|
||||
* framebuffer console was never initialized.
|
||||
*/
|
||||
void console_fb_strip_draw(const char *text);
|
||||
|
||||
/**
|
||||
* Write a single character to serial console
|
||||
*/
|
||||
|
||||
@@ -100,6 +100,18 @@ void vt100_putc(char c);
|
||||
/** Feed a null-terminated string. */
|
||||
void vt100_puts(const char *s);
|
||||
|
||||
/**
|
||||
* 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 and its grid/cursor. @p text is the full line to
|
||||
* show (prompt plus whatever has been typed so far), plain text with no
|
||||
* ANSI/SGR codes -- the strip renders everything in one fixed color
|
||||
* (bright white on black, 4.4u). Horizontally scrolls (tail-anchored)
|
||||
* once @p text exceeds the strip's width. No-op before TTF mode is
|
||||
* active (vt100_enable_ttf() must have run first).
|
||||
*/
|
||||
void vt100_strip_draw(const char *text);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* Queries
|
||||
* --------------------------------------------------------------------- */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1 @@
|
||||
qemu: terminating on signal 15 from pid 94179 (/bin/bash)
|
||||
@@ -0,0 +1,5 @@
|
||||
UEFI firmware (version 2025.11-3ubuntu7 built at 11:11:58 on Mar 31 2026)
|
||||
[2J[001;001H[=3h[2J[001;001H[2J[001;001H[8;031;100t[2J[001;001HBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found
|
||||
BdsDxe: failed to load Boot0003 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x4,0x0): Not Found
|
||||
BdsDxe: No bootable option or device was found.
|
||||
BdsDxe: Press any key to enter the Boot Manager Menu.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
qemu: terminating on signal 15 from pid 83972 (/bin/bash)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
qemu: terminating on signal 15 from pid 52846 (/bin/bash)
|
||||
@@ -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;
|
||||
|
||||
+78
-2
@@ -35,6 +35,7 @@
|
||||
#include "starkernel/timer.h"
|
||||
#include "starkernel/arch.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* FABRIC.md 4.4: "ok>" (including its trailing space) renders in bright
|
||||
* cyan, 0x55FFFF -- reuses FB_ANSI_PALETTE[14]. Sent as a real SGR escape
|
||||
@@ -44,6 +45,72 @@
|
||||
|
||||
const char lithos_version[64] = LITHOS_VERSION_STR;
|
||||
|
||||
/*===========================================================================
|
||||
* FABRIC.md items 4.4u/4.4w/4.4x: the bottom REPL strip -- a plain-text
|
||||
* (no ANSI/SGR) mirror of "[VMName] ok> <input so far>", refreshed into
|
||||
* console_fb_strip_draw() on every keystroke. Built separately from
|
||||
* SK_PROMPT_TEXT rather than derived from it, since the strip renders in
|
||||
* one fixed color (4.4u) and has no SGR parser of its own -- the ANSI
|
||||
* version keeps going to console_puts() exactly as before, unaffected,
|
||||
* for serial and for the scrollback box's own history.
|
||||
*===========================================================================*/
|
||||
|
||||
#define SK_STRIP_PROMPT_MAX 80u
|
||||
|
||||
static char g_strip_prompt[SK_STRIP_PROMPT_MAX] = "ok> ";
|
||||
|
||||
/* Builds "[VMName] ok> " or "[VMName] zuse)ok> " (no VM name -> just the
|
||||
* suffix) into g_strip_prompt, bounded, no strcat -- mirrors emit_prefix()'s
|
||||
* bracket format (console.c) so the strip and the box agree on what a
|
||||
* prompt looks like, minus the ANSI color codes the strip doesn't use. */
|
||||
static void set_strip_prompt(VM *vm)
|
||||
{
|
||||
const char *vn = console_get_vm_name();
|
||||
char *p = g_strip_prompt;
|
||||
size_t room = sizeof(g_strip_prompt) - 1u;
|
||||
size_t n;
|
||||
const char *suffix;
|
||||
size_t used, left, sn;
|
||||
|
||||
if (vn && vn[0]) {
|
||||
n = strlen(vn);
|
||||
if (n > room) n = room;
|
||||
*p++ = '[';
|
||||
memcpy(p, vn, n);
|
||||
p += n;
|
||||
*p++ = ']';
|
||||
*p++ = ' ';
|
||||
}
|
||||
|
||||
suffix = (vm && vm->zuse_session) ? "zuse)ok> " : "ok> ";
|
||||
used = (size_t)(p - g_strip_prompt);
|
||||
left = (used < room) ? (room - used) : 0u;
|
||||
sn = strlen(suffix);
|
||||
if (sn > left) sn = left;
|
||||
memcpy(p, suffix, sn);
|
||||
p += sn;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* Concatenates g_strip_prompt + input_so_far (bounded, no strcat) and
|
||||
* hands the result to the strip renderer. Called once with an empty
|
||||
* input_so_far right after set_strip_prompt(), then again on every
|
||||
* keystroke from sk_readline() below. */
|
||||
static void strip_refresh(const char *input_so_far)
|
||||
{
|
||||
char combined[INPUT_BUFFER_SIZE + SK_STRIP_PROMPT_MAX];
|
||||
size_t plen = strlen(g_strip_prompt);
|
||||
size_t ilen = strlen(input_so_far);
|
||||
|
||||
if (plen >= sizeof(combined)) plen = sizeof(combined) - 1u;
|
||||
memcpy(combined, g_strip_prompt, plen);
|
||||
if (plen + ilen >= sizeof(combined)) ilen = sizeof(combined) - 1u - plen;
|
||||
memcpy(combined + plen, input_so_far, ilen);
|
||||
combined[plen + ilen] = '\0';
|
||||
|
||||
console_fb_strip_draw(combined);
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* USE-word dispatch: which VM receives REPL input.
|
||||
*
|
||||
@@ -90,6 +157,9 @@ static int sk_readline(char *buf, int size)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
strip_refresh(buf); /* FABRIC.md 4.4x: show the bare prompt before any input */
|
||||
|
||||
for (;;) {
|
||||
int c = console_getc(); /* non-blocking poll */
|
||||
|
||||
@@ -128,10 +198,12 @@ static int sk_readline(char *buf, int size)
|
||||
/* backspace: DEL (0x7F) or BS (0x08) */
|
||||
if ((c == 0x7F || c == '\b') && n > 0) {
|
||||
n--;
|
||||
buf[n] = '\0';
|
||||
/* VT100 erase: move back, overwrite with space, move back again */
|
||||
console_putc('\b');
|
||||
console_putc(' ');
|
||||
console_putc('\b');
|
||||
strip_refresh(buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -139,7 +211,9 @@ static int sk_readline(char *buf, int size)
|
||||
if (n >= size - 1) continue; /* buffer full — drop character */
|
||||
|
||||
buf[n++] = (char)c;
|
||||
buf[n] = '\0';
|
||||
console_putc((char)c); /* echo */
|
||||
strip_refresh(buf);
|
||||
}
|
||||
|
||||
buf[n] = '\0';
|
||||
@@ -180,7 +254,7 @@ static void sk_fault_handler(VM *vm) {
|
||||
|
||||
int sk_repl_step(VM *vm)
|
||||
{
|
||||
char input[256];
|
||||
char input[INPUT_BUFFER_SIZE]; /* FABRIC.md 4.4w: matches the strip's input width */
|
||||
|
||||
if (!vm || vm->halted) return 0;
|
||||
|
||||
@@ -194,6 +268,7 @@ int sk_repl_step(VM *vm)
|
||||
int is_hera = (!vn || (vn[0]=='H' && vn[1]=='e' && vn[2]=='r' && vn[3]=='a' && vn[4]=='\0'));
|
||||
vm->emergency_console = is_hera ? (vm->zuse_session ? 0 : 1) : 0;
|
||||
console_puts(SK_PROMPT_TEXT);
|
||||
set_strip_prompt(vm); /* FABRIC.md 4.4x: bottom strip mirrors the same prompt */
|
||||
}
|
||||
|
||||
sk_readline(input, sizeof(input));
|
||||
@@ -222,7 +297,7 @@ int sk_repl_step(VM *vm)
|
||||
|
||||
void sk_repl_run(VM *vm)
|
||||
{
|
||||
char input[256];
|
||||
char input[INPUT_BUFFER_SIZE]; /* FABRIC.md 4.4w: matches the strip's input width */
|
||||
VM *active;
|
||||
|
||||
vm->halted = 0;
|
||||
@@ -241,6 +316,7 @@ void sk_repl_run(VM *vm)
|
||||
int is_hera = (!vn || (vn[0]=='H' && vn[1]=='e' && vn[2]=='r' && vn[3]=='a' && vn[4]=='\0'));
|
||||
active->emergency_console = is_hera ? (active->zuse_session ? 0 : 1) : 0;
|
||||
console_puts(SK_PROMPT_TEXT);
|
||||
set_strip_prompt(active); /* FABRIC.md 4.4x: bottom strip mirrors the same prompt */
|
||||
}
|
||||
|
||||
sk_readline(input, sizeof(input));
|
||||
|
||||
Reference in New Issue
Block a user