WinComm/forms/protocol.md
Scott Duensing ae2aef0119 Add remote forms system: DFM converter, server library, and client engine
Text-based protocol for serving Delphi-designed forms over serial.
dfm2form converts binary DFM (TPF0) to protocol commands on Linux.
formsrv loads .form files and sends/receives via pluggable transport.
formcli creates native Win 3.1 controls and routes events back to server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:35:54 -06:00

4.6 KiB

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 <formId> <width> <height> "<title>"

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"
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)

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

Opt-in events (require EVENT.BIND): DblClick, KeyDown, KeyUp, Enter, Exit, MouseDown, MouseUp, MouseMove.

Properties

Property Applies To Value Format
Caption Label, Button, CheckBox Quoted string
Text Edit, ComboBox, Memo Quoted string (\n for line breaks)
Items ListBox, ComboBox Quoted string (\n-delimited)
Checked CheckBox 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

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.