diff --git a/docs/reference/06-ui.md b/docs/reference/06-ui.md new file mode 100644 index 0000000..5a7c4aa --- /dev/null +++ b/docs/reference/06-ui.md @@ -0,0 +1,480 @@ +# Psion SIBO / Workabout MX — User-Interface Programming + +**The Window Server and the Console** + +Reference notes drawn from the SIBO 'C' SDK *Window Server Reference* (v2.30, +March 1999) and the *PLIB Reference* (console functions). Everything below is +sourced from those two manuals; section/line references are given as +`[wserv]` and `[plib]`. Anything not backed by the manuals is explicitly +flagged as **reverse-engineered** or **uncertain**. + +> **Machine-type note.** The manuals cover the HC, MC, S3, S3a and Workabout. +> The **Workabout** is reported by the window server as machine type +> `WS_TYPE_S3C` (i.e. it shares the "Series 3c" identity), and in +> compatibility mode its `version_id` is `WS_TYPE_S3C | WS_VERSION_4` +> `[wserv 7288-7291]`. The manuals do **not** name a "Workabout MX" +> variant; MX-specific behaviour (notably the barcode scan key, below) is +> **not documented** and is marked as reverse-engineered where it appears. + +--- + +## 1. The Window Server model + +The window server is a **system process** that provides shared access to the +screen and the keyboard (and a pointing device, where one exists) `[plib +1295-1296]`. Application processes talk to it as **clients** through the +**WLIB** library — a thin C shell over ROM-based code reached by software +interrupts `[plib 1338-1339]`. + +### 1.1 Clients, foreground and background + +- Of all the clients, exactly **one is the foreground client**; all others are + background clients. The **foreground client is the one that receives + keyboard input** `[wserv 1906-1910]`. +- On the small-screen machines (HC, S3, S3a, Workabout) the windows of + background clients are **not visible at all**; only the foreground client's + windows are shown, in front `[wserv 1918-1921]`. +- On the **MC** (large screen) windows of several clients can be visible at + once, and a client can *attach* to another `[wserv 1330-1333]`. +- The server keeps clients in a **front-to-back task order**: position 0 is the + foreground; position 1 is the frontmost background task, and so on `[wserv + 1968-1971]`. +- A client can move itself or another client between foreground and background + with `wClientPosition` `[wserv 1983-1984]`. + +### 1.2 The shared screen and keyboard + +Drawing goes into a **hierarchical system of overlapping windows**; all drawing +is clipped to visible areas, and the server issues **redraw events** telling a +client which areas need repainting `[plib 1318-1323]`. Keyboard input is routed +to the foreground client, except for keys the server processes itself (task +switch, pause) or keys a client has **captured** with `wCaptureKey` so that it +receives them whether foreground or not `[wserv 1911-1915, 6283-6293]`. + +### 1.3 Connecting + +A process must connect before using the server, via `wConnect` (or a wrapper +such as `wStartup`) `[wserv 1371-1372]`. + +```c +VOID wConnect(WSERV_SPEC *pwserv_spec, VOID *pnws_handle, UINT flags); +``` + +`[wserv 7182-7183]` + +- `flags` combines: `W_CONNECT_AT_BACK` (connect as background; default is + foreground), `W_CONNECT_USER_FLAG`, `W_CONNECT_SYSTEM_MODAL`, + `W_CONNECT_PRIORITY` (enable the server's process-priority handling), + `W_CONNECT_DISABLE_LEAVES` (return negative error numbers instead of calling + `p_leave`) `[wserv 7187-7203]`. +- `pnws_handle` is the handle the server puts into events **not** directed at a + window (e.g. key events) `[wserv 7206-7207]`. +- `pwserv_spec` points to a `WSERV_SPEC` the client must keep for the life of + the connection. `wConnect` fills its `CONNECT_INFO conn` sub-struct with + useful data — screen size (`pixels`), pixel geometry, `set_is_dark`, + `version_id` (machine type + server version), and the default + `system_font_handle` `[wserv 7210-7251]`. + +**Connection tests / helpers.** After connecting, the reserved static +`wClientData` is non-zero (zero if not connected) `[wserv 1882-1894]`. The +`WSERV_SPEC` address is also recorded in the reserved static `wserv_channel`, +which general-purpose code can read for screen size etc. `[wserv 7294-7303]`. + +**Two startup paths (see also §5 on the console):** + +- **PLIB startup module:** call `wStartup`, which connects, creates and + initialises a backed-up window covering the whole screen, and creates a + permanent graphics context on it — ready to draw `[wserv 1496-1519]`. The + created window's ID is in the global `wMainWid` `[wserv 1609]`. +- **CLIB startup module:** the startup automatically opens the console device + `con:`, which on the HC/S3/S3a/Workabout **is itself a window-server + connection** — so the process is already a client. Connecting again with + `wConnect`/`wStartup` panics the process (panic 100) `[wserv 1387-1396, + 1757]`. The console channel is in the static `winHandle` `[wserv 1399-1403]`. + +### 1.4 Windows (briefly) + +- Create with `wCreateWindow` (returns a window ID); the window is dormant and + invisible until **initialised** with `wInitialiseWindowTree`, which activates + the window and all descendants `[wserv 3141-3167]`. +- Destroy a tree with `wCloseWindowTree`; destroying a window more than once is + **not** treated as an error `[wserv 3185-3202]`. +- Windows can be **backed-up** by bitmaps: drawing is mirrored to a backup + bitmap and the server redraws automatically, so the client largely avoids + redraw handling `[wserv 1270-1273, plib 1334-1335]`. +- Redraw/mouse events are directed at a window by the **handle** the client + supplied at `wCreateWindow` (commonly the address of a client structure) + `[wserv 1944-1946]`. + +--- + +## 2. The event system + +For each client the server maintains a **queue of events** reporting user input +and other state changes: key presses, foreground/background changes, redraw +events, and (on pointer machines) mouse events `[wserv 1926-1937]`. Key and +mouse events are time-stamped in system ticks (1 tick = 1/32 s) for e.g. +double-click detection `[wserv 1939-1941, 14331-14333]`. + +### 2.1 Fetching events + +```c +VOID wGetEventWait (WS_EV *event); /* block until an event */ +VOID wGetEvent (WS_EV *event); /* async, no wait */ +VOID wGetEventSpecial(WS_EV *event, UINT flags); /* async + event filter */ +VOID wGetEventUpdate (UINT flags); /* change the filter */ +``` + +`[wserv 14302-14432]` + +- **`wGetEventWait`** returns only when an event is available; on an empty queue + it waits indefinitely `[wserv 1949-1951]`. +- **`wGetEvent`** is the asynchronous version, for clients that also service + non-server sources (serial input, timers). It sets `event->type = + E_FILE_PENDING` immediately; when an event arrives the server fills `event` + and signals the client's I/O semaphore. **Only one may be outstanding** — a + second pending `wGetEvent` panics the process `[wserv 14363-14378]`. +- **`wGetEventSpecial`** (window server **version 4** only) is `wGetEvent` plus + a `flags` filter selecting which events to deliver. Only one call to + `wGetEvent`/`wGetEventSpecial` may be outstanding at a time `[wserv + 14381-14393]`. Filter flags (OR-able) `[wserv 14396-14416]`: + - `WE_KEY` — key and task-key events + - `WE_REDRAW` — `WM_REDRAW` + - `WE_STATUS` — `WM_FOREGROUND`, `WM_BACKGROUND`, `WM_ON` + - `WE_MOUSE` — mouse and rubber-band events + - `WE_OTHERS` — everything else + - `WE_NORMAL` — all of the above (`wGetEventSpecial(..., WE_NORMAL)` == + `wGetEvent`) + - `WE_ESC` — only meaningful when `WE_KEY` is *not* set: on ESC the keyboard + buffer is discarded and a `WM_ESCAPE` event is delivered. +- **`wGetEventUpdate`** (v4) replaces the filter of an outstanding + `wGetEvent`/`wGetEventSpecial`; a no-op if none is outstanding `[wserv + 14419-14432]`. + +> **Async discipline.** Fully process one server event before requesting the +> next. Because the server runs at higher priority than clients, an async +> request can complete while you are handling some *other* source. Never +> destroy a window directly in response to a non-server event — instead call +> `wCancelGetEvent`, which delivers a **`WM_CANCELLED`** at the **highest +> priority** (overtaking all queued but not-yet-delivered events), and do the +> destruction when that arrives `[wserv 3227-3252]`. + +### 2.2 The event structure + +```c +typedef struct { + WORD type; /* positive event type, WM_xxxx */ + UWORD handle; /* target window, or the wConnect handle */ + UWORD time; /* low word of tick count (key/mouse) */ + WS_EVENT_UNION p; /* type-dependent payload */ +} WS_EV; + +typedef union { + UWORD uword; + UBYTE *dpoint; + P_RECT rect; /* WM_REDRAW rectangle */ + WMSG_KEY key; /* WM_KEY */ + WMSG_MOUSE mouse; /* WM_MOUSE / rubber band */ + WMSG_RUBBER rubber; + WMSG_CAPS caps; /* WM_KEYBOARD_STATE_CHANGE */ +} WS_EVENT_UNION; +``` + +`[wserv 14311-14350]` + +- `handle`: for window-directed events (`WM_REDRAW`, `WM_MOUSE`) it is the + handle given to `wCreateWindow`; for non-window events (`WM_KEY`, + `WM_FOREGROUND`) it is the handle given to `wConnect` `[wserv 14326-14329]`. + +The key payload: + +```c +typedef struct { + UWORD keycode; /* code of the key pressed */ + UBYTE modifiers; /* shift/ctrl/psion/caps/num-lock */ + UBYTE count; /* auto-repeat accumulation */ +} WMSG_KEY; +``` + +`[wserv 14456-14465]` + +- `modifiers` bit flags: `W_SHIFT_MODIFIER` (0x02), `W_CTRL_MODIFIER` (0x04), + `W_PSION_MODIFIER` (0x08), `W_CAPS_MODIFIER` (0x10), + `W_NUM_LOCK_MODIFIER` (0x20, MC only) `[wserv 14481-14499]`. +- `count` is 1 for a single press; it exceeds 1 only when the client cannot + keep up with auto-repeat. The manual's advice is to **ignore the repeat + count** `[wserv 14466-14476, 6263-6280]`. +- `keycode`: printable SIBO characters (code page 850-like) fall in + `0x20`–`0xFF` excluding `0x7F`. The **PSION** shift typically adds `0x200` + (`W_SPECIAL_KEY`). "Special" keys carry codes `< 0x20`, `0x7F`, or `> 0xFF` + `[wserv 14501-14541]`. Named special codes include `W_KEY_TAB` (0x09), + `W_KEY_DELETE_LEFT` (0x08), `W_KEY_DELETE_RIGHT` (0x7F), `W_KEY_RETURN` + (0x0D), `W_KEY_ESCAPE` (0x1B), `W_KEY_UP/DOWN/RIGHT/LEFT` (0x100–0x103), + `W_KEY_PAGE_UP/DOWN` (0x104/0x105), `W_KEY_HOME/END` (0x106/0x107), + `W_KEY_TASK` (0x108), `W_KEY_MENU` (0x122), `W_KEY_HELP` (0x123), + `W_KEY_ON` (0x2002), `W_KEY_OFF` (0x2003), etc. `[wserv 14547-14852]`. + +### 2.3 Event types + +Common event types (`WS_EV event;` assumed) `[wserv 14441-15048]`: + +| Event | Meaning | Payload | +|-------|---------|---------| +| **`WM_KEY`** | A key was pressed. The full description is in `event.p.key` (keycode, modifiers, count). Delivered to the foreground client (or a capturer). `[wserv 14449-14476, 6249-6250]` | `p.key` | +| **`WM_REDRAW`** | Sent when the client's queue is empty and one or more windows has an update region. `event.p.rect` is a rectangular block of pixels needing redraw. Lowest priority except for `WM_USER_MSG`. `[wserv 14855-14865]` | `p.rect` | +| **`WM_BACKGROUND`** | The foreground client has just gone to background. Usually nothing to do, but suspend real-time/animated activity until foreground returns. Only `type` set. `[wserv 14868-14878]` | — | +| **`WM_FOREGROUND`** | A background client has just become foreground. Only `type` set. `[wserv 14881-14887]` | — | +| **`WM_CANCELLED`** | Sent in response to `wCancelGetEvent`; delivered at highest priority. Only `type` set. `[wserv 14890-14897, 3250-3252]` | — | +| **`WM_USER_MSG`** | Sent in response to `wUserMsg`. **Lowest priority of all** — useful as an "the server has nothing more to send" marker. Only `type` set. `[wserv 14909-14916]` | — | +| **`WM_ON`** | Machine switched on (server v3.5+). Delivered to the foreground client if it called `wInformOn`; in v4, to any client (fore or back) that called `wInformOnAll(TRUE)`. Prompts a display refresh. Only `type` set. `[wserv 14919-14937]` | — | +| **`WM_COMMAND`** | Another client sent a command via `wSendCommand` (server v3.5). Prompts the receiver to call `wGetCommand` for the data (up to 127 bytes). Only `type` set. `[wserv 14940-14947, 1128-1129]` | — | +| **`WM_TASK_KEY`** | Sent to the **application-key handler** (the shell) when an application key is pressed with no process of that application present, or a PSION-shifted application key is pressed. S3/S3a/Workabout only. The app-key index (0–15) is in `event.p.key.keycode`. `[wserv 14963-14975]` | `p.key.keycode` | +| **`WM_ESCAPE`** | (v4) Delivered when ESC is pressed *and* the client selected events with `wGetEventSpecial` including `WE_ESC`/`WM_ESCAPE` but **excluding** key events; the keyboard buffer is discarded. `[wserv 14999-15015]` | — | +| **`WM_TASK_UPDATE`** | Sent to the shell (when foreground) whenever *any* process terminates. S3/S3a/Workabout and HC v3.5+. Only `type` set. `[wserv 14950-14960]` | — | +| **`WM_DATE_CHANGED`** | (v4) Date changed (reset, or past midnight). Sent to a foreground S3a/Workabout app not in S3 compatibility mode; background apps get it on next foreground; delivered at next power-on if off. `[wserv 14978-14993]` | — | +| **`WM_KEYBOARD_STATE_CHANGE`** | Sent only to the shell when numlock/capslock changes; new state in `event.p.caps.modifiers`. (MC generates it for the caps-lock key.) `[wserv 15065-15069, 14734-14735]` | `p.caps` | + +**Mouse / pointer events** (only on machines with a pointing device, e.g. the +MC) `[wserv 15076-15187]`: + +| Event | Meaning | +|-------|---------| +| **`WM_MOUSE`** | State change on the digitiser. `event.p.mouse` is a `WMSG_MOUSE { UBYTE event; UBYTE state; P_POINT pos; }`. `event.p.mouse.event` is `WM_MOUSE_MOVE` (filtered out by default), `WM_MOUSE_PRESS`, or `WM_MOUSE_RELEASE`; `state` carries `W_MOUSE_DOWN`, `W_MOUSE_OUTSIDE`, and the shift modifiers. `[wserv 15083-15129]` | +| **`WM_RUBBER_BAND_INIT`** | Special `WM_MOUSE` variant sent when a press occurs in a window flagged `W_WIN_RUBBER_BAND_CAPTURE`. `[wserv 15146-15154]` | +| **`WM_RUBBER`** | Sent on completion of a rubber-band interaction. `[wserv 15160-15166]` | +| **`WM_ACTIVE`** | Sent to a window that set `W_WIN_INACTIVE` when a `WM_MOUSE_PRESS` lands on it or a descendant (in place of the `WM_MOUSE`); the client typically re-activates the tree by clearing `W_WIN_INACTIVE`. Only `type` set. `[wserv 15169-15186]` | + +Large-screen (MC) events also include `WM_DEICONISE`, `WM_ATTACHED`, +`WM_DETACHED` for the multi-task attach/iconise model `[wserv 15017-15062]`. + +### 2.4 Event priority + +Event delivery is **prioritised**, not strictly FIFO: + +- `WM_CANCELLED` is delivered at the **highest** priority, overtaking anything + queued but not yet delivered `[wserv 3250-3252]`. +- `WM_REDRAW` is **lower** than user input and foreground/background events; + the only type lower than `WM_REDRAW` is `WM_USER_MSG` `[wserv 14865, + 3126-3127]`. +- `WM_USER_MSG` has the **lowest** priority of all `[wserv 14912-14913]`. +- Between windows there is a further **two-level redraw priority**: windows are + low by default; `W_WIN_PRIORITY` (on `wCreateWindow`/`wSetWindow`) promotes a + window's redraws ahead of the rest `[wserv 3130-3131]`. + +### 2.5 The barcode scan key — **reverse-engineered (Workabout MX)** + +> **Not in the manuals.** The *Window Server Reference* documents no barcode / +> scanner / laser trigger key, and defines no keycode near 368. On barcode- +> equipped Workabout / Workabout MX hardware the **scan (trigger) key is +> observed to arrive as an ordinary `WM_KEY` event with keycode 368** +> (`0x170`). This is **reverse-engineered field knowledge, not documented +> behaviour** — treat the exact value and delivery path as version/hardware +> dependent and confirm on the target unit. Because it surfaces as a normal +> key event, it can be handled in the ordinary `WM_KEY` path (and, like other +> keys, potentially captured with `wCaptureKey`). + +--- + +## 3. Drawing and text output primitives + +All drawing targets a **drawable** selected by the **current graphics context +(GC)** `[wserv 5504, 5526]`. + +### 3.1 Graphics contexts + +- Create a **permanent** GC on a window/bitmap with `gCreateGC` / + `gCreateGC0` (the latter with default values) `[wserv 304-305, 1438]`. Select + the current GC with `gSetGC` / `gSetGC0` `[wserv 311-312, 2993]`. +- **Temporary** GCs are used during redraws (see below) and are freed + automatically by `wEndRedraw` `[wserv 3037-3050]`. +- `wStartup` conveniently makes a permanent GC on its full-screen window + `[wserv 1502-1505]`. + +### 3.2 Graphics primitives + +- Lines / shapes / borders / fills: `gDrawLine`, `gBorderRect`, `gBorder`, + `gBorder2Rect`/`gBorder2` (shadowed, v4), `gFillPattern`, `gInvObloid` + `[wserv 315-326, 1296, 919-957]`. +- Bitmaps: `gCopyBit` (copy a bitmap to a window) and the bitmap-file family + (`gInitBit`, `gGetBit`, `gLoadBit`, `gPeekBit`, `gSaveBit`) `[wserv 354, + 829-1021]`. +- The server also draws buttons (`wDrawButton`, `wDrawButton2`), sprites + (`wCreateSprite`/`wSetSprite`) and scaled objects (`gDrawObject`) `[wserv + 926-969, 1168, 1203]`. + +### 3.3 Text output + +Text is drawn through the current GC (font ID, style, transfer mode) `[wserv +5526-5536]`: + +- `gPrintText` — draw text from a pixel position `[wserv 5508, 1439]` +- `gPrintClipText` — clipped to a given width `[wserv 5510]` +- `gPrintBoxText` — left/right/centred in a box; commonly used for + **flicker-free** redraw `[wserv 5512-5513, 2961]` +- `gXPrintText` — with embellishment `[wserv 5515]` +- `gShadowText` — shadowed (v4) `[wserv 5517]` + +Font styles combine `G_STY_NORMAL`, `G_STY_BOLD`, `G_STY_UNDERLINE`, +`G_STY_INVERSE`, `G_STY_DOUBLE`, `G_STY_MONO`, `G_STY_ITALIC` `[wserv +5539-5557]`. Layout helpers: `gTextWidth`, `gTextCount`, `wGetWidthTable` +`[wserv 5492-5497]`. + +### 3.4 Redraw handling + +On a `WM_REDRAW`, the normal response is to **validate** the update region and +draw it `[wserv 10248-10256]`. Bracket the drawing with a `wBeginRedraw` +variant and `wEndRedraw`; `wBeginRedraw` both signals "this is a redraw" and +**validates** the given rectangle `[wserv 3005-3007]`. There are six +`wBeginRedraw*` variants covering partial vs whole window and +independent/temporary GC combinations `[wserv 3020-3050]`. Related: validate +without redrawing (`wValidateRect`, `wValidateWin`) and force redraws by +invalidating (`wInvalidateRect`, `wInvalidateWin`) `[wserv 270-274, 2901]`. +Backed-up windows largely avoid this cycle because the server repaints from the +backup bitmap `[wserv 1270-1273]`. + +Minimal MC (non-backed-up) redraw loop `[wserv 1589-1608]`: + +```c +wStartup(); +do { + wGetEventWait(&event); + if (event.type == WM_REDRAW) { + wBeginRedrawWin(wMainWid); + gPrintText(10, 20, "Hello world!", 12); + wEndRedraw(); + } +} while (event.type != WM_KEY); +``` + +--- + +## 4. Error handling (server calls) + +By default a failing server function calls `p_leave` with the negative error +number; `wDisableLeaves(TRUE)` (or `W_CONNECT_DISABLE_LEAVES` at connect time) +makes it **return** the error instead `[wserv 1629-1641]`. Many drawing calls +are **blind** (queued client-side, no acknowledgement); on failure the server +discards further blind ops until a non-blind call reports the error. Force the +issue with `wCheckPoint` (flush + signal) or `wFlush` (flush only); after an +error, `wCleanUp` releases dangling resources `[wserv 1653-1703]`. Client-side +buffering means a panic can lag the offending call — insert `wFlush`/ +`wCheckPoint` when hunting one down `[wserv 1791-1793]`. + +--- + +## 5. The console layer — `CON:` and the PLIB console functions + +The console is the **lightweight text-UI path**. PLIB contains only *primitive* +console functions — typed-line input (with simple backspace editing) and +mono-spaced line output — while the `con:` device driver adds row/column +positioning and mono-spaced character printing `[plib 1299-1301]`. They are +explicitly "for quick-and-dirty applications... not suitable for constructing +quality user interfaces" `[plib 8580-8581]`. + +### 5.1 Relationship to the window server + +Both the PLIB console functions and `con:` **ultimately call the window +server** for input and drawing — but expose only a fraction of its capability +`[plib 1310-1315]`. How `con:` is implemented differs by machine `[wserv +1319-1323]`: + +- **HC / S3 / S3a / Workabout:** `con:` is implemented by **connecting + directly to the window server** — opening `con:` makes the process a window- + server client. Opening it also creates and initialises a **backed-up** + console window (no redraw handling needed) `[wserv 1319-1320, 1387-1407]`. + The console window's ID can be fetched with the `P_FINQ` I/O function + (`CONSOLE_INFO.window_handle`), letting a CLIB program create its own GC on + that window and draw with WLIB `[wserv 1410-1453]`. +- **MC:** `con:` is implemented by a **separate `SYS$CONS` display process** + that keeps a character map and redraws its own window (with title/menu bars). + Here it is `SYS$CONS`, not the application, that is the window-server client; + the application cannot use the console window, and `P_FINQ` is **not** + supported. On the MC the recommendation is the **PLIB startup module + + `wStartup`** `[wserv 1305-1322, 1539-1615]`. + +The two startup modules therefore differ: the **CLIB** startup auto-opens +`con:` (backing `printf`, `gets`, `cprintf`, `cgets`) `[wserv 1387-1389]`; the +**PLIB** startup does not, and you call `wStartup` yourself `[wserv 1496-1497]`. +Auto-opening can be suppressed in CLIB by defining `p_xwind` `[wserv +1457-1490]`. + +### 5.2 The PLIB console functions + +Output (open `con:` automatically on first use) `[plib 8584-8595, 8700-8737]`: + +```c +VOID p_putch(UINT c); /* write one character */ +VOID p_puts (TEXT *str); /* write string + newline */ +VOID p_printf(TEXT *fstr, ...); /* formatted line + newline */ +VOID p_print (TEXT *fstr, ...); /* formatted, no trailing newline */ +``` + +- `p_printf` uses an internal buffer of `P_MAXSYSIO` (258) bytes; output is + limited to `P_MAXSYSIO - 2` (256) bytes per call. Format is that of `p_atob` + `[plib 8720-8726]`. +- `p_print` moves no line; embed `\r` (start of line) and `\n` (down a line) + yourself `[plib 8732-8737]`. + +Input `[plib 8597-8599, 8740-8770]`: + +```c +INT p_getch(VOID); /* wait for a key, return its code */ +INT p_gets (TEXT *str); /* read a line (backspace edit) */ +INT p_getl (TEXT *pmt, TEXT *str, INT len); /* prompt, then read a line */ +``` + +- `p_getch` waits for a key and returns its character code (no echo) `[plib + 8740-8743]`. +- `p_gets` reads up to `P_MAXSYSIO-1` characters, Enter-terminated, and NUL- + terminates at `str` (needs `P_MAXSYSIO` bytes there); returns the length + `[plib 8746-8756]`. +- `p_getl` writes the prompt `pmt`, then reads up to `len` characters + (Enter-terminated, needs `len+1` bytes); returns the length `[plib + 8759-8770]`. + +Canonical smallest program `[plib 1020-1021]`: + +```c +p_printf("Hello world"); +p_getch(); +``` + +### 5.3 Console configuration statics + +Set these **before the first console call** `[plib 8612-8694]`: + +- `winHandle` (`GLREF_D VOID *`) holds the open console channel; open a file or + `TTY:` into it first to **redirect** `p_putch` / `p_print` / `p_printf`. Do + **not** use `p_getch` / `p_gets` / `p_getl` when redirected `[plib + 8615-8628]`. +- `_DefScreenRect` (`P_RECT`, top-left `(0,0)`, bottom-right = columns × rows) + changes the console window size `[plib 8629-8665]`. +- `_DefScreenMode` (`INT`) selects the mode: `0` native (default, currently + single-pixel non-compatibility on all SIBO machines), `1` compatibility, `2` + non-compatibility with grey, `3` compatibility with grey. Irrelevant values + are ignored `[plib 8668-8694]`. + +--- + +## 6. Higher UI libraries (pointer only) + +For full applications — menus, dialogs, forms — SIBO provides **higher-level UI +libraries layered on the window server** (commonly referred to as **HWIM**, +**FORM** and **OLIB**). **These are separate libraries and are not documented +in the *Window Server Reference* or *PLIB Reference*** covered here; the two +manuals mention menus and dialog boxes only as *windows the server draws/clips* +(e.g. `[wserv 2395, 10646-10647]`), not as an API. Use those libraries' own +references for real application UIs; the material above is the **foundation** +they sit on. *(Library names are noted as a pointer only and are not sourced +from these two manuals.)* + +--- + +### Source key + +- `[wserv N]` — *Window Server Reference* v2.30, line N of the supplied text. +- `[plib N]` — *PLIB Reference* (console functions), line N of the supplied + text. +- Items marked **reverse-engineered** / **uncertain** are **not** in either + manual (notably the code-368 barcode scan key and the higher UI library + names).