# 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).
