# Remote Forms Protocol ## Overview Text-based protocol for remote GUI. A C server on Linux sends form/control commands over a transport layer; a Delphi 1.0 client on Windows 3.1 creates native controls and sends user events back. ## Message Format - One command per message. - Transport delivers whole messages (today: newline-delimited over serial). - Strings are double-quoted with escapes: `\"` `\\` `\n` `\r` `\t`. - Bare tokens (IDs, numbers, type names) are whitespace-delimited. - IDs are positive integers assigned by the server. ## Server → Client Commands ### FORM.CREATE FORM.CREATE "" Create a new form with the given dimensions and title. The form is not shown until FORM.SHOW is sent. ### FORM.SHOW FORM.SHOW <formId> ### FORM.HIDE FORM.HIDE <formId> ### FORM.DESTROY FORM.DESTROY <formId> Free the form and all its controls. ### CTRL.CREATE CTRL.CREATE <formId> <ctrlId> <type> <left> <top> <width> <height> [Key="val" ...] Create a control on the specified form. Inline key/value properties are applied immediately after creation. See Control Types and Properties below. ### CTRL.SET CTRL.SET <formId> <ctrlId> Key="val" [Key="val" ...] Update one or more properties on an existing control. ### EVENT.BIND EVENT.BIND <formId> <ctrlId> <eventName> Wire an opt-in event handler. Auto-wired events do not need explicit binding. ### EVENT.UNBIND EVENT.UNBIND <formId> <ctrlId> <eventName> Remove an event handler. ## Client → Server Events EVENT <formId> <ctrlId> <eventName> [<data>] Event data varies by event type: | Event | Data | |-----------|-------------------------------| | Click | (none) | | DblClick | (none) | | Change | `"new text"` or `<position>` (ScrollBar) | | Select | `<index> "selected text"` | | KeyDown | `<vkCode>` | | KeyUp | `<vkCode>` | | MouseDown | `<x> <y> <button>` | | MouseUp | `<x> <y> <button>` | | MouseMove | `<x> <y> <button>` | | Enter | (none) | | Exit | (none) | | Close | (none) | | Notify | (none) | ## Control Types | Type | Delphi Class | Auto-wired Events | |-------------|--------------|-------------------| | Label | TLabel | (none) | | Edit | TEdit | Change | | Button | TButton | Click | | CheckBox | TCheckBox | Click | | ListBox | TListBox | Select | | ComboBox | TComboBox | Select, Change | | Memo | TMemo | Change | | Image | TImage | (none) | | GroupBox | TGroupBox | (none) | | RadioButton | TRadioButton | Click | | Panel | TPanel | (none) | | ScrollBar | TScrollBar | Change | | MediaPlayer | TMediaPlayer | (none) | GroupBox and Panel are cosmetic containers (flat parent model — no child containment in the protocol). RadioButtons are all in one group per form. Opt-in events (require EVENT.BIND): Click (Image, GroupBox, Panel), Notify (MediaPlayer), DblClick, KeyDown, KeyUp, Enter, Exit, MouseDown, MouseUp, MouseMove. ## Properties | Property | Applies To | Value Format | |-------------|---------------------------------------------|-------------------------------------------| | Caption | Label, Button, CheckBox, GroupBox, RadioButton, Panel | Quoted string | | Text | Edit, ComboBox, Memo | Quoted string (`\n` for line breaks) | | Items | ListBox, ComboBox | Quoted string (`\n`-delimited) | | Checked | CheckBox, RadioButton | 0 or 1 | | Enabled | All | 0 or 1 | | Visible | All | 0 or 1 | | MaxLength | Edit | Integer | | ReadOnly | Edit, Memo | 0 or 1 | | ScrollBars | Memo | 0-3 (ssNone..ssBoth) | | ItemIndex | ListBox, ComboBox | Integer (-1 = none) | | TabOrder | All windowed controls | Integer | | Stretch | Image | 0 or 1 | | Center | Image | 0 or 1 | | Transparent | Image | 0 or 1 | | Picture | Image | Quoted string (filename, BMP only) | | BevelOuter | Panel | 0-2 (bvNone, bvLowered, bvRaised) | | BevelInner | Panel | 0-2 (bvNone, bvLowered, bvRaised) | | BorderStyle | Panel | 0-1 (bsNone, bsSingle) | | Kind | ScrollBar | 0-1 (sbHorizontal, sbVertical) | | Min | ScrollBar | Integer | | Max | ScrollBar | Integer | | Position | ScrollBar | Integer | | LargeChange | ScrollBar | Integer | | SmallChange | ScrollBar | Integer | | FileName | MediaPlayer | Quoted string (media file path) | | DeviceType | MediaPlayer | Quoted string (e.g., `dtWaveAudio`) | | AutoOpen | MediaPlayer | 0 or 1 | | Command | MediaPlayer | Quoted string (pseudo-property, see below)| File path properties (Picture, FileName) are resolved relative to the client's `BasePath` setting. Subdirectories are allowed (e.g., `Picture="images\logo.bmp"` with `BasePath=C:\MYAPP` resolves to `C:\MYAPP\images\logo.bmp`). Command is a pseudo-property that triggers a method call on the MediaPlayer rather than setting a value. Valid commands: `Open`, `Play`, `Stop`, `Close`, `Pause`, `Resume`, `Rewind`, `Next`, `Previous`. ## String Encoding - Strings in the protocol are always double-quoted. - Escape sequences: `\"` (literal quote), `\\` (literal backslash), `\n` (newline), `\r` (carriage return), `\t` (tab). - Multi-line values (Memo text, ListBox items) use `\n` within a single quoted string. ## Transport Layer The protocol is transport-agnostic. Messages are delivered via: ``` int ReadMessage(char *buf, int maxLen); // returns bytes read, 0 = none void WriteMessage(const char *buf); // sends complete message ``` Current transport: newline-delimited serial (messages terminated by CR+LF). The transport handles framing; protocol layer never sees delimiters.