docs(reference): 06-ui — SIBO/Workabout MX programming reference
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user