• src/syncterm/scripts/auto/connected/sftp_browser.wrensrc/syncterm/scri

    From Deucе@VERT to Git commit to main/sbbs/master on Fri May 1 09:47:56 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/79b77e1e01d974b65af40834
    Added Files:
    src/syncterm/scripts/auto/connected/sftp_browser.wren
    Modified Files:
    src/syncterm/scripts/syncterm.wren ui_app.wren ui_popup.wren src/syncterm/wren_bind.c wren_bind_sftp.c wren_bind_sftp.h
    Log Message:
    SyncTERM: Wren SFTP browser

    New scripts/auto/connected/sftp_browser.wren replaces the C-side
    sftp_browser.c for read-only navigation of an SFTP session. Bound
    to Alt-S; spawns a child fiber whose App owns the screen (CTerm
    suspended while modal).

    Display:
    - Each row shows size, mtime, an optional `+` marker (when the
    server's fattr advertises a non-empty descs@syncterm.net
    extension), and a label. Directories use lname when the
    server provides one; files keep their bare filename and put
    lname into a bottom description bar inside the pane.
    - F2 fetches the long description via the descs request and
    displays it preformatted (block-centred, no per-line centring).
    - Esc / [X] dismiss; F1 / [?] show help; Enter descends into
    directories; .. ascends. Files don't transfer yet — that
    lands with the Wren queue replacement.

    C-side wiring (wren_bind_sftp.[ch], wren_bind.c):
    - struct wren_sftp_entry gains has_long_desc; build_sftp_entry
    populates it from sftp_fattr_get_ext_by_type(de->attrs,
    SFTP_EXT_NAME_DESCS).
    - SFTPEntry foreign class gains hasLongDesc accessor.

    ui_app.wren:
    - dispatchMouse_ now hands an unclaimed button-1 drag-start back
    to the C-side selector (Input.unget(me) + Input.mousedrag()),
    so the standard SyncTERM rectangle / line-copy UI works while
    a Wren App is up.

    ui_popup.wren:
    - New splitHardLines_ helper splits on CR/LF/CRLF without
    word-wrapping. longestHardLine_ now counts codepoints rather
    than bytes so multi-byte UTF-8 (e.g. box-drawing) doesn't
    inflate the popup width measurement.
    - Popup gains a `preformatted` mode and Alert.showPreformatted:
    splits only on hard breaks (no word-wrap, no mid-codepoint
    splits) and left-aligns all lines at one block-column so the
    block is centred while each line keeps its relative shape.
    centeredBounds_ takes a preformatted flag for consistent row
    counting between sizing and painting.

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

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