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/andsrc/platform/win32/ - No
#ifdefin 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 wrapperrequested_color_modeto 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 optimizationsplat_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 controlplat_caps_t.supports_focus_events— safe to enable xterm focus in/out reports (CSI I/CSI Ovia?1004h)plat_caps_t.supports_output_wait_writable— backend supportsplat_wait_output_writable()for bounded output pacingplat_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_MOUSEZIREAEL_CAP_BRACKETED_PASTEZIREAEL_CAP_OSC52ZIREAEL_CAP_SYNC_UPDATEZIREAEL_CAP_SCROLL_REGIONZIREAEL_CAP_CURSOR_SHAPEZIREAEL_CAP_FOCUS_EVENTSZIREAEL_CAP_UNDERLINE_STYLESZIREAEL_CAP_COLORED_UNDERLINESZIREAEL_CAP_HYPERLINKSZIREAEL_CAP_SGR_ATTRS_MASK(u32, accepts decimal or0x...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_OKwhen output is writable withintimeout_ms - returns
ZR_ERR_LIMITon timeout - returns
ZR_ERR_UNSUPPORTEDwhen the backend cannot support writability waits - returns
ZR_ERR_PLATFORMon OS failures
Backend constraints¶
POSIX¶
- Process-wide SIGWINCH handler with a bounded wake-fd registry
- Multiple concurrent
plat_createinstances 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
SIGWINCHhandler - Restores the prior handler when the final POSIX platform instance is destroyed
- Default create path is unchanged: non-TTY stdio falls back to
/dev/ttyand fails withZR_ERR_PLATFORMwhen no TTY is available ZIREAEL_POSIX_PIPE_MODE=1is an explicit opt-in for non-TTY stdio: skip/dev/ttyfallback, treatplat_enter_raw/plat_leave_rawas no-op success (no termios calls), and report deterministic size80x24plat_write_output: suppresses SIGPIPE termination and returnsZR_ERR_PLATFORMon broken-pipe/EPIPE failuresplat_wait_output_writable: usespoll(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; returnsZR_ERR_UNSUPPORTEDif not feasible
Implementation files¶
src/platform/zr_platform.h— OS-header-free interfacesrc/platform/posix/zr_plat_posix.c— POSIX backendsrc/platform/win32/zr_plat_win32.c— Windows backend