# 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), or `<itemIndex>` (RadioGroup) | | DblClick | (none) | | Change | `"new text"`, `<position>` (ScrollBar), or `<index>` (TabSet, TabbedNotebook) | | 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) | | SelectCell| `<col> <row>` | | SetEditText| `<col> <row> "text"` | ## 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) | | MainMenu | TMainMenu | (none) | | PopupMenu | TPopupMenu | (none) | | MenuItem | TMenuItem | Click | | RadioGroup | TRadioGroup | Click | | BitBtn | TBitBtn | Click | | SpeedButton | TSpeedButton | Click | | TabSet | TTabSet | Change | | Notebook | TNotebook | (none) | | TabbedNotebook | TTabbedNotebook | Change | | MaskEdit | TMaskEdit | Change | | Outline | TOutline | (none) | | Bevel | TBevel | (none) | | Header | THeader | (none) | | ScrollBox | TScrollBox | (none) | | StringGrid | TStringGrid | SelectCell | MainMenu and PopupMenu use `0 0 0 0` geometry (non-visual). MenuItem uses `0 0 0 0` geometry and requires a `Parent` property to specify its parent menu or menu item. One MainMenu per form (auto-attached). PopupMenu is associated with any control via the `PopupMenu` property. 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), SetEditText (StringGrid), DblClick, KeyDown, KeyUp, Enter, Exit, MouseDown, MouseUp, MouseMove. Menu and RadioGroup components do not support opt-in events. ## Properties ### Common Properties | Property | Applies To | Format | |-----------|--------------|-------------------------------| | Enabled | All | 0 or 1 | | Visible | All | 0 or 1 | | TabOrder | All windowed | Integer | | PopupMenu | Any TControl | Integer (ctrlId of PopupMenu) | ### Label, Button, GroupBox | Property | Format | |----------|---------------| | Caption | Quoted string | ### Edit | Property | Format | |-----------|---------------| | Text | Quoted string | | MaxLength | Integer | | ReadOnly | 0 or 1 | ### CheckBox, RadioButton | Property | Format | |----------|---------------| | Caption | Quoted string | | Checked | 0 or 1 | ### ListBox | Property | Format | |-----------|--------------------------------| | Items | Quoted string (`\n`-delimited) | | ItemIndex | Integer (-1 = none) | ### ComboBox | Property | Format | |-----------|--------------------------------| | Text | Quoted string | | Items | Quoted string (`\n`-delimited) | | ItemIndex | Integer (-1 = none) | ### Memo | Property | Format | |------------|--------------------------------------| | Text | Quoted string (`\n` for line breaks) | | ReadOnly | 0 or 1 | | ScrollBars | 0-3 (ssNone..ssBoth) | ### Image | Property | Format | |-------------|------------------------------------| | Picture | Quoted string (filename, BMP only) | | Stretch | 0 or 1 | | Center | 0 or 1 | | Transparent | 0 or 1 | File path resolved relative to client's `BasePath` setting. ### Panel | Property | Format | |-------------|------------------------------------| | Caption | Quoted string | | BevelOuter | 0-2 (bvNone, bvLowered, bvRaised) | | BevelInner | 0-2 (bvNone, bvLowered, bvRaised) | | BorderStyle | 0-1 (bsNone, bsSingle) | ### ScrollBar | Property | Format | |-------------|-----------------------------------| | Kind | 0 (sbHorizontal), 1 (sbVertical) | | Min | Integer | | Max | Integer | | Position | Integer | | LargeChange | Integer | | SmallChange | Integer | ### MediaPlayer | Property | Format | |------------|-------------------------------------| | FileName | Quoted string (media file path) | | DeviceType | Quoted string (e.g., `dtWaveAudio`) | | AutoOpen | 0 or 1 | | Command | Quoted string (pseudo-property) | File path resolved relative to client's `BasePath` setting. Command triggers a method call rather than setting a value. Valid commands: `Open`, `Play`, `Stop`, `Close`, `Pause`, `Resume`, `Rewind`, `Next`, `Previous`. ### MainMenu, PopupMenu No type-specific properties. One MainMenu per form (auto-attached). PopupMenu is associated with controls via the common `PopupMenu` property. ### MenuItem | Property | Format | |----------|--------------------------------------| | Caption | Quoted string | | Parent | Integer (ctrlId of parent menu/item) | | Checked | 0 or 1 | | ShortCut | Integer (Delphi ShortCut value) | ### RadioGroup | Property | Format | |-----------|--------------------------------| | Caption | Quoted string | | Items | Quoted string (`\n`-delimited) | | ItemIndex | Integer (-1 = none) | | Columns | Integer | ### BitBtn | Property | Format | |-----------|----------------------------------| | Caption | Quoted string | | Kind | 0-10 (bkCustom..bkAll) | | Layout | 0-3 (blGlyphLeft..blGlyphBottom) | | NumGlyphs | Integer (1-4) | ### SpeedButton | Property | Format | |------------|----------------------------------| | Caption | Quoted string | | Layout | 0-3 (blGlyphLeft..blGlyphBottom) | | NumGlyphs | Integer (1-4) | | GroupIndex | Integer (0 = no group) | | Down | 0 or 1 | | AllowAllUp | 0 or 1 | ### TabSet, Notebook, TabbedNotebook | Property | Format | |-----------|--------------------------------| | Items | Quoted string (`\n`-delimited) | | ItemIndex | Integer (-1 = none) | ### MaskEdit | Property | Format | |-----------|---------------| | Text | Quoted string | | MaxLength | Integer | | EditMask | Quoted string | ### Outline | Property | Format | |--------------|---------------------------------| | Items | Quoted string (`\n`-delimited) | | OutlineStyle | 0-6 (osText..osTreePictureText) | ### Bevel | Property | Format | |----------|----------------------------| | Shape | 0-5 (bsBox..bsRightLine) | | Style | 0-1 (bsLowered, bsRaised) | ### Header | Property | Format | |----------|--------------------------------| | Items | Quoted string (`\n`-delimited) | ### ScrollBox No type-specific properties. ### StringGrid | Property | Format | |------------------|---------------------------------------------------------| | ColCount | Integer (default 5) | | RowCount | Integer (default 5) | | FixedCols | Integer (default 1) | | FixedRows | Integer (default 1) | | DefaultColWidth | Integer (pixels) | | DefaultRowHeight | Integer (pixels) | | Options | Integer (bitmask, see below) | | Cells | Quoted string (tab-delimited cols, `\n`-delimited rows) | | Cell | Quoted string (`col,row,value`) | Options is an integer bitmask of TGridOption values: | Bit | Value | Option | |-----|--------|---------------------| | 0 | 0x0001 | goFixedVertLine | | 1 | 0x0002 | goFixedHorzLine | | 2 | 0x0004 | goVertLine | | 3 | 0x0008 | goHorzLine | | 4 | 0x0010 | goRangeSelect | | 5 | 0x0020 | goDrawFocusSelected | | 6 | 0x0040 | goRowSizing | | 7 | 0x0080 | goColSizing | | 8 | 0x0100 | goRowMoving | | 9 | 0x0200 | goColMoving | | 10 | 0x0400 | goEditing | | 11 | 0x0800 | goTabs | | 12 | 0x1000 | goThumbTracking | Cells is a bulk-load property: columns are tab-delimited, rows are `\n`-delimited. Cell is an individual update: `"col,row,value"`. ## 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.