• src/syncterm/scripts/ui_checkbox.wren ui_checkbox_test.wren ui_form.wr

    From Deucе@VERT to Git commit to main/sbbs/master on Thursday, April 30, 2026 00:47:11
    https://gitlab.synchro.net/main/sbbs/-/commit/4aaa2f5b2a07e8bedb413778
    Added Files:
    src/syncterm/scripts/ui_checkbox.wren ui_checkbox_test.wren ui_form.wren ui_form_test.wren ui_menubar.wren ui_menubar_test.wren ui_radio.wren ui_radio_test.wren ui_spinbox.wren ui_spinbox_test.wren ui_statusbar.wren ui_statusbar_test.wren
    Modified Files:
    src/syncterm/Wren.adoc src/syncterm/scripts/syncterm.wren ui.wren ui_app.wren ui_demo.wren ui_draw.wren ui_draw_test.wren ui_pane.wren ui_popup_test.wren ui_style.wren ui_widget.wren wrentest.wren src/syncterm/wren_bind.c wren_bind_internal.h wren_bind_screen.c
    Log Message:
    SyncTERM: Wren UI form controls (Checkbox, Radio, Spin, Menu, Status, Form)

    Six new widgets:
    - Checkbox: single-row [X] Label toggle.
    - RadioGroup: vertical mutually-exclusive selector with cursor /
    selection split and a wrap= flag (Form turns wrap off so Up/Down
    escape the group at its edges).
    - SpinBox: numeric +/- with step / page / home-end keys.
    - StatusBar: bottom-row strip; text= or segments= [text, align].
    - MenuBar: horizontal command strip with Left/Right/hotkey/click
    activation; per-item callbacks, no nested submenus.
    - Form: Container that lays out (label, widget) field rows with
    optional OK / Cancel buttons.

    Layer-awareness gets a second axis: Widget.gatesActiveLayer (default
    false; Pane overrides true). An unfocused gating ancestor dims its
    whole subtree, so multi-pane layouts go inactive consistently
    instead of just along the chrome. Cursor highlight on RadioGroup
    only paints when the group itself has focus.

    Glyphs gained an auto-fallback: Glyphs[name] now probes the
    primary's first codepoint via the new foreign Codepage.encodes_(text)
    and promotes to the per-entry ASCII fallback if the primary isn't in
    CP437 (cell storage codepage). Resolutions are cached. Default
    glyphs cleaned to CP437-representable primaries throughout
    (radio.on •, check.on √, tag.on »).

    App.popStatus overlay now draws *below* the modal stack, so a
    dialog the user is interacting with isn't obscured by an indicator
    behind it.

    Painter.frameTitle pre-truncates the title before the cell-budgeted
    text() call so the trailing-space pad doesn't bleed extra
    characters past the right bracket.

    decode_utf8_first lifted out of wren_bind_screen.c's static scope
    and declared in wren_bind_internal.h — Codepage.encodes_ in
    wren_bind.c needs the same UTF-8 first-codepoint decode.

    Wren.adoc: subsections for the new widgets, an import update, the gatesActiveLayer + CP437-fallback notes, and the popStatus z-order
    note.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net