Skip to content

Module — Platform Interface

The platform interface is the hard boundary between core determinism and OS-specific behavior.

Boundary rules

  • Core includes only src/platform/zr_platform.h (OS-header-free)
  • OS headers live only in src/platform/posix/ and src/platform/win32/
  • No #ifdef in core for platform differences

API surface

Defined in src/platform/zr_platform.h.

Lifecycle

Function Description
plat_create(out, cfg) Create platform instance
plat_destroy(plat) Destroy platform instance

Raw mode

Function Description
plat_enter_raw(plat) Enter raw mode (idempotent)
plat_leave_raw(plat) Leave raw mode (idempotent)

Raw mode enables unbuffered input and disables terminal echo/line editing.

Capabilities and size

Function Description
plat_get_size(plat, out) Get terminal dimensions (cols, rows)
plat_get_caps(plat, out) Get detected capabilities

I/O

Function Description
plat_read_input(plat, buf, cap) Read available input bytes (non-blocking)
plat_read_input_timed(plat, buf, cap, timeout_ms) Bounded wait + read for startup probing
plat_write_output(plat, bytes, len) Write output bytes to terminal

Wait/wake

Function Returns Description
plat_wait(plat, timeout_ms) 1=ready, 0=timeout, <0=error Block until input ready or timeout
plat_wake(plat) ZR_OK or error Wake blocked wait (thread-safe)

plat_wake is the only function callable from non-engine threads.

Detection helpers

Function Description
plat_supports_terminal_queries(plat) Returns 1 when probe queries are valid for this backend mode
plat_is_dumb_terminal(plat) Returns 1 when backend/session is a non-interactive dumb terminal mode
plat_guess_terminal_id(plat, out_id) Environment-based fallback identity hint when XTVERSION is unavailable

Time

Function Description
plat_now_ms() Monotonic time in milliseconds

Output capabilities

plat_get_caps() reports terminal/backend capabilities that affect output emission:

  • plat_caps_t.color_mode — detected color mode (16 / 256 / RGB). Backends use conservative detection and clamp any wrapper requested_color_mode to avoid emitting higher-color SGR forms than the terminal/backend can handle.
  • plat_caps_t.sgr_attrs_supported — bitmask of supported style attrs (bold/italic/underline/reverse/dim/strike/overline/blink) applied by the diff renderer before SGR emission.
  • plat_caps_t.supports_scroll_region — safe to use DECSTBM + SU/SD for scroll optimizations
  • plat_caps_t.supports_sync_update — safe to wrap presents in DEC private mode ?2026 (synchronized updates)
  • plat_caps_t.supports_cursor_shape — safe to emit DECSCUSR (ESC[Ps q) for cursor shape/blink control
  • plat_caps_t.supports_focus_events — safe to enable xterm focus in/out reports (CSI I / CSI O via ?1004h)
  • plat_caps_t.supports_output_wait_writable — backend supports plat_wait_output_writable() for bounded output pacing
  • plat_caps_t.supports_underline_styles — safe to emit underline variants (SGR 4:n)
  • plat_caps_t.supports_colored_underlines — safe to emit underline color/reset (SGR 58 / 59)
  • plat_caps_t.supports_hyperlinks — safe to emit OSC 8 hyperlinks

Backends also support environment overrides for manual capability control in non-standard terminals/CI harnesses:

  • ZIREAEL_CAP_MOUSE
  • ZIREAEL_CAP_BRACKETED_PASTE
  • ZIREAEL_CAP_OSC52
  • ZIREAEL_CAP_SYNC_UPDATE
  • ZIREAEL_CAP_SCROLL_REGION
  • ZIREAEL_CAP_CURSOR_SHAPE
  • ZIREAEL_CAP_FOCUS_EVENTS
  • ZIREAEL_CAP_UNDERLINE_STYLES
  • ZIREAEL_CAP_COLORED_UNDERLINES
  • ZIREAEL_CAP_HYPERLINKS
  • ZIREAEL_CAP_SGR_ATTRS_MASK (u32, accepts decimal or 0x... hex)

Boolean overrides accept: 1/0, true/false, yes/no, on/off.

Output backpressure hook

To support optional frame pacing, the platform interface exposes an output-writability wait:

  • plat_wait_output_writable(plat_t* plat, int32_t timeout_ms):
  • returns ZR_OK when output is writable within timeout_ms
  • returns ZR_ERR_LIMIT on timeout
  • returns ZR_ERR_UNSUPPORTED when the backend cannot support writability waits
  • returns ZR_ERR_PLATFORM on OS failures

Backend constraints

POSIX

  • Process-wide SIGWINCH handler with a bounded wake-fd registry
  • Multiple concurrent plat_create instances are supported
  • Registry capacity is bounded (currently 32 concurrent wake fds)
  • Uses self-pipe for signal-safe wake
  • Preserves one SIGWINCH wake via overflow marker when a wake pipe is saturated
  • Chains to any previously installed SIGWINCH handler
  • Restores the prior handler when the final POSIX platform instance is destroyed
  • Default create path is unchanged: non-TTY stdio falls back to /dev/tty and fails with ZR_ERR_PLATFORM when no TTY is available
  • ZIREAEL_POSIX_PIPE_MODE=1 is an explicit opt-in for non-TTY stdio: skip /dev/tty fallback, treat plat_enter_raw/plat_leave_raw as no-op success (no termios calls), and report deterministic size 80x24
  • plat_write_output: suppresses SIGPIPE termination and returns ZR_ERR_PLATFORM on broken-pipe/EPIPE failures
  • plat_wait_output_writable: uses poll(POLLOUT) on stdout fd

Windows

  • Uses ConPTY or native console API
  • Multiple engines may be creatable but contend for console
  • Treat as single-engine unless you fully control console ownership
  • Key input text is translated to UTF-8 bytes before core parsing
  • plat_wait_output_writable: best-effort; returns ZR_ERR_UNSUPPORTED if not feasible

Implementation files

  • src/platform/zr_platform.h — OS-header-free interface
  • src/platform/posix/zr_plat_posix.c — POSIX backend
  • src/platform/win32/zr_plat_win32.c — Windows backend