Replace form store with stream-from-disk and dynamic form IDs
Form IDs were baked into .form files at conversion time, preventing a form from being displayed more than once. dfm2form now writes a placeholder ID (0), and formServerSendForm streams the file directly from disk, assigning a unique ID on the fly via rewriteFormId. This eliminates formServerLoadFile, the in-memory form store, and the -i flag from dfm2form. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
38125a51a1
commit
17394e4f5d
4 changed files with 164 additions and 256 deletions
|
|
@ -46,39 +46,37 @@ part of a Delphi 1.0 project on Windows.
|
|||
## DFM Converter
|
||||
|
||||
`dfm2form` reads Delphi 1.0 binary DFM files (TPF0 format) and outputs
|
||||
`.form` files containing protocol commands.
|
||||
`.form` files containing protocol commands. The form ID in the output
|
||||
is a placeholder (`0`); the server assigns a dynamic ID when it streams
|
||||
the file to the client.
|
||||
|
||||
```
|
||||
dfm2form [-i <formId>] <input.dfm> [output.form]
|
||||
dfm2form <input.dfm> [output.form]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `-i <formId>` — Set the form ID (default: 1). Each form needs a
|
||||
unique ID when serving multiple forms.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```
|
||||
dfm2form login.dfm # output to stdout
|
||||
dfm2form login.dfm login.form # output to file
|
||||
dfm2form -i 2 settings.dfm settings.form
|
||||
```
|
||||
|
||||
**Output** is a sequence of protocol commands:
|
||||
|
||||
```
|
||||
FORM.CREATE 1 400 300 "Login"
|
||||
CTRL.CREATE 1 1 Label 20 20 100 17 Caption="Username:"
|
||||
CTRL.CREATE 1 2 Edit 120 18 200 21 Text="" MaxLength=32 TabOrder=0
|
||||
CTRL.CREATE 1 3 Label 20 52 100 17 Caption="Password:"
|
||||
CTRL.CREATE 1 4 Edit 120 50 200 21 Text="" MaxLength=32 TabOrder=1
|
||||
CTRL.CREATE 1 5 Button 245 90 75 25 Caption="OK" TabOrder=2
|
||||
CTRL.CREATE 1 6 Button 160 90 75 25 Caption="Cancel" TabOrder=3
|
||||
EVENT.BIND 1 5 Enter
|
||||
FORM.SHOW 1
|
||||
FORM.CREATE 0 400 300 "Login"
|
||||
CTRL.CREATE 0 1 Label 20 20 100 17 Caption="Username:"
|
||||
CTRL.CREATE 0 2 Edit 120 18 200 21 Text="" MaxLength=32 TabOrder=0
|
||||
CTRL.CREATE 0 3 Label 20 52 100 17 Caption="Password:"
|
||||
CTRL.CREATE 0 4 Edit 120 50 200 21 Text="" MaxLength=32 TabOrder=1
|
||||
CTRL.CREATE 0 5 Button 245 90 75 25 Caption="OK" TabOrder=2
|
||||
CTRL.CREATE 0 6 Button 160 90 75 25 Caption="Cancel" TabOrder=3
|
||||
EVENT.BIND 0 5 Enter
|
||||
FORM.SHOW 0
|
||||
```
|
||||
|
||||
The placeholder `0` IDs are replaced at runtime by `formServerSendForm`.
|
||||
|
||||
The converter maps Delphi class names to protocol control types,
|
||||
extracts geometry and properties, and emits `EVENT.BIND` for any
|
||||
event handler assignments in the DFM that are not auto-wired (see
|
||||
|
|
@ -86,9 +84,9 @@ Events below). Unknown control classes are skipped with a warning.
|
|||
|
||||
## Server Library (C)
|
||||
|
||||
The server loads `.form` files and sends their commands to a remote
|
||||
client through a pluggable transport interface. It also receives
|
||||
events from the client and dispatches them to a callback.
|
||||
The server streams `.form` files from disk to a remote client through
|
||||
a pluggable transport interface, assigning dynamic form IDs. It also
|
||||
receives events from the client and dispatches them to a callback.
|
||||
|
||||
### Transport Interface
|
||||
|
||||
|
|
@ -117,17 +115,15 @@ typedef struct {
|
|||
FormServerT *formServerCreate(FormTransportT *transport);
|
||||
void formServerDestroy(FormServerT *server);
|
||||
|
||||
// Load a .form file. Returns the form ID, or -1 on error.
|
||||
int32_t formServerLoadFile(FormServerT *server, const char *path);
|
||||
|
||||
// Send all commands for a loaded form to the client.
|
||||
void formServerSendForm(FormServerT *server, int32_t formId);
|
||||
// Stream a .form file to the client, assigning a dynamic form ID.
|
||||
// Returns the assigned form ID, or -1 on error.
|
||||
int32_t formServerSendForm(FormServerT *server, const char *path);
|
||||
|
||||
// Form visibility
|
||||
void formServerShowForm(FormServerT *server, int32_t formId);
|
||||
void formServerHideForm(FormServerT *server, int32_t formId);
|
||||
|
||||
// Destroy a form (sends FORM.DESTROY and removes from store)
|
||||
// Destroy a form on the client.
|
||||
void formServerDestroyForm(FormServerT *server, int32_t formId);
|
||||
|
||||
// Update a control property
|
||||
|
|
@ -188,8 +184,7 @@ int main(void)
|
|||
|
||||
formServerSetEventCallback(server, onEvent, server);
|
||||
|
||||
int32_t formId = formServerLoadFile(server, "login.form");
|
||||
formServerSendForm(server, formId);
|
||||
int32_t formId = formServerSendForm(server, "login.form");
|
||||
|
||||
// Main loop
|
||||
while (running) {
|
||||
|
|
@ -540,8 +535,6 @@ any protocol or application code.
|
|||
| Limit | Value |
|
||||
|---------------------------|-------|
|
||||
| Max message length | 4096 bytes |
|
||||
| Max forms (server) | 64 |
|
||||
| Max lines per .form file | 1024 |
|
||||
| Max controls per form | 256 |
|
||||
| Form ID range | 1-65535 (stored in high word of Tag) |
|
||||
| Control ID range | 1-65535 (stored in low word of Tag) |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// dfm2form.c - Convert Delphi 1.0 binary DFM (TPF0) to .form protocol text
|
||||
//
|
||||
// Usage: dfm2form [-i <formId>] <input.dfm> [output.form]
|
||||
// Usage: dfm2form <input.dfm> [output.form]
|
||||
//
|
||||
// Reads a binary DFM file, extracts the form and control definitions,
|
||||
// and outputs protocol commands (FORM.CREATE, CTRL.CREATE, EVENT.BIND,
|
||||
|
|
@ -864,8 +864,7 @@ static void emitForm(FILE *out, int32_t formId, DfmFormT *form)
|
|||
|
||||
static void usage(const char *progName)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-i <formId>] <input.dfm> [output.form]\n", progName);
|
||||
fprintf(stderr, " -i <formId> Set form ID (default: 1)\n");
|
||||
fprintf(stderr, "Usage: %s <input.dfm> [output.form]\n", progName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -876,23 +875,13 @@ static void usage(const char *progName)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int32_t formId = 1;
|
||||
const char *inputPath = NULL;
|
||||
const char *inputPath = NULL;
|
||||
const char *outputPath = NULL;
|
||||
|
||||
// Parse arguments
|
||||
int32_t i = 1;
|
||||
while (i < argc) {
|
||||
if (strcmp(argv[i], "-i") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
formId = atoi(argv[++i]);
|
||||
if (formId <= 0) {
|
||||
fprintf(stderr, "Error: form ID must be positive\n");
|
||||
exit(1);
|
||||
}
|
||||
} else if (argv[i][0] == '-') {
|
||||
if (argv[i][0] == '-') {
|
||||
usage(argv[0]);
|
||||
} else if (inputPath == NULL) {
|
||||
inputPath = argv[i];
|
||||
|
|
@ -965,7 +954,7 @@ int main(int argc, char *argv[])
|
|||
fout = stdout;
|
||||
}
|
||||
|
||||
emitForm(fout, formId, &form);
|
||||
emitForm(fout, 0, &form);
|
||||
|
||||
if (fout != stdout) {
|
||||
fclose(fout);
|
||||
|
|
|
|||
331
forms/formsrv.c
331
forms/formsrv.c
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "formsrv.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -13,26 +14,17 @@
|
|||
// Constants
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define MAX_FORMS 64
|
||||
#define MAX_LINES 1024
|
||||
#define MAX_MSG_LEN 4096
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
int32_t formId;
|
||||
char *lines[MAX_LINES];
|
||||
int32_t lineCount;
|
||||
} FormDataT;
|
||||
|
||||
struct FormServerS {
|
||||
FormTransportT *transport;
|
||||
EventCallbackT eventCallback;
|
||||
void *eventUserData;
|
||||
FormDataT forms[MAX_FORMS];
|
||||
int32_t formCount;
|
||||
int32_t nextFormId;
|
||||
char msgBuf[MAX_MSG_LEN];
|
||||
};
|
||||
|
||||
|
|
@ -40,66 +32,16 @@ struct FormServerS {
|
|||
// Prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static FormDataT *findForm(FormServerT *server, int32_t formId);
|
||||
static void freeFormData(FormDataT *fd);
|
||||
static int32_t parseFormId(const char *line);
|
||||
static void sendCommand(FormServerT *server, const char *fmt, ...);
|
||||
static bool skipSpaces(const char **p);
|
||||
static bool parseToken(const char **p, char *buf, int32_t bufSize);
|
||||
static bool parseToken(const char **p, char *buf, int32_t bufSize);
|
||||
static void rewriteFormId(char *line, int32_t lineSize, int32_t formId);
|
||||
static void sendCommand(FormServerT *server, const char *fmt, ...);
|
||||
static bool skipSpaces(const char **p);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Internal helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static FormDataT *findForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
for (int32_t i = 0; i < server->formCount; i++) {
|
||||
if (server->forms[i].formId == formId) {
|
||||
return &server->forms[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void freeFormData(FormDataT *fd)
|
||||
{
|
||||
for (int32_t i = 0; i < fd->lineCount; i++) {
|
||||
free(fd->lines[i]);
|
||||
fd->lines[i] = NULL;
|
||||
}
|
||||
fd->lineCount = 0;
|
||||
fd->formId = 0;
|
||||
}
|
||||
|
||||
|
||||
static int32_t parseFormId(const char *line)
|
||||
{
|
||||
// Skip command prefix (e.g., "FORM.CREATE "), then read first integer
|
||||
const char *p = line;
|
||||
// Skip non-space command name
|
||||
while (*p && *p != ' ') {
|
||||
p++;
|
||||
}
|
||||
// Skip space
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
// Parse integer
|
||||
return (int32_t)atoi(p);
|
||||
}
|
||||
|
||||
|
||||
static bool skipSpaces(const char **p)
|
||||
{
|
||||
while (**p == ' ' || **p == '\t') {
|
||||
(*p)++;
|
||||
}
|
||||
return **p != '\0';
|
||||
}
|
||||
|
||||
|
||||
static bool parseToken(const char **p, char *buf, int32_t bufSize)
|
||||
{
|
||||
skipSpaces(p);
|
||||
|
|
@ -152,7 +94,49 @@ static bool parseToken(const char **p, char *buf, int32_t bufSize)
|
|||
}
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
static void rewriteFormId(char *line, int32_t lineSize, int32_t formId)
|
||||
{
|
||||
// Protocol lines have the form: COMMAND <formId> <rest...>
|
||||
// Skip command prefix (non-space chars)
|
||||
char *p = line;
|
||||
while (*p && *p != ' ') {
|
||||
p++;
|
||||
}
|
||||
// Skip spaces
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
|
||||
// p now points at the placeholder ID token ("0")
|
||||
// Find the end of this token
|
||||
char *idStart = p;
|
||||
while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') {
|
||||
p++;
|
||||
}
|
||||
char *idEnd = p;
|
||||
|
||||
// Format the new ID
|
||||
char idBuf[16];
|
||||
int32_t idLen = snprintf(idBuf, sizeof(idBuf), "%d", formId);
|
||||
|
||||
int32_t oldLen = (int32_t)(idEnd - idStart);
|
||||
int32_t shift = idLen - oldLen;
|
||||
|
||||
// Check that the rewritten line still fits
|
||||
int32_t curLen = (int32_t)strlen(line);
|
||||
if (curLen + shift >= lineSize - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shift the remainder of the line
|
||||
if (shift != 0) {
|
||||
memmove(idStart + idLen, idEnd, strlen(idEnd) + 1);
|
||||
}
|
||||
|
||||
// Write the new ID (no NUL — the memmove already placed the rest)
|
||||
memcpy(idStart, idBuf, idLen);
|
||||
}
|
||||
|
||||
|
||||
static void sendCommand(FormServerT *server, const char *fmt, ...)
|
||||
{
|
||||
|
|
@ -167,17 +151,34 @@ static void sendCommand(FormServerT *server, const char *fmt, ...)
|
|||
}
|
||||
|
||||
|
||||
static bool skipSpaces(const char **p)
|
||||
{
|
||||
while (**p == ' ' || **p == '\t') {
|
||||
(*p)++;
|
||||
}
|
||||
return **p != '\0';
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void formServerBindEvent(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *eventName)
|
||||
{
|
||||
sendCommand(server, "EVENT.BIND %d %d %s", formId, ctrlId, eventName);
|
||||
}
|
||||
|
||||
|
||||
FormServerT *formServerCreate(FormTransportT *transport)
|
||||
{
|
||||
FormServerT *server = (FormServerT *)calloc(1, sizeof(FormServerT));
|
||||
if (server == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
server->transport = transport;
|
||||
server->transport = transport;
|
||||
server->nextFormId = 1;
|
||||
return server;
|
||||
}
|
||||
|
||||
|
|
@ -187,151 +188,19 @@ void formServerDestroy(FormServerT *server)
|
|||
if (server == NULL) {
|
||||
return;
|
||||
}
|
||||
for (int32_t i = 0; i < server->formCount; i++) {
|
||||
freeFormData(&server->forms[i]);
|
||||
}
|
||||
free(server);
|
||||
}
|
||||
|
||||
|
||||
int32_t formServerLoadFile(FormServerT *server, const char *path)
|
||||
{
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "formsrv: cannot open '%s': %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (server->formCount >= MAX_FORMS) {
|
||||
fprintf(stderr, "formsrv: too many forms (max %d)\n", MAX_FORMS);
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FormDataT *fd = &server->forms[server->formCount];
|
||||
memset(fd, 0, sizeof(FormDataT));
|
||||
|
||||
char lineBuf[MAX_MSG_LEN];
|
||||
int32_t formId = -1;
|
||||
|
||||
while (fgets(lineBuf, sizeof(lineBuf), f) != NULL) {
|
||||
// Strip trailing newline
|
||||
int32_t len = (int32_t)strlen(lineBuf);
|
||||
while (len > 0 && (lineBuf[len - 1] == '\n' || lineBuf[len - 1] == '\r')) {
|
||||
lineBuf[--len] = '\0';
|
||||
}
|
||||
|
||||
// Skip empty lines
|
||||
if (len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd->lineCount >= MAX_LINES) {
|
||||
fprintf(stderr, "formsrv: too many lines in '%s' (max %d)\n", path, MAX_LINES);
|
||||
freeFormData(fd);
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd->lines[fd->lineCount] = strdup(lineBuf);
|
||||
if (fd->lines[fd->lineCount] == NULL) {
|
||||
fprintf(stderr, "formsrv: out of memory\n");
|
||||
freeFormData(fd);
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
fd->lineCount++;
|
||||
|
||||
// Extract form ID from first FORM.CREATE line
|
||||
if (formId == -1 && strncmp(lineBuf, "FORM.CREATE ", 12) == 0) {
|
||||
formId = parseFormId(lineBuf);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (formId <= 0) {
|
||||
fprintf(stderr, "formsrv: no FORM.CREATE found in '%s'\n", path);
|
||||
freeFormData(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd->formId = formId;
|
||||
server->formCount++;
|
||||
return formId;
|
||||
}
|
||||
|
||||
|
||||
void formServerSendForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
FormDataT *fd = findForm(server, formId);
|
||||
if (fd == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < fd->lineCount; i++) {
|
||||
server->transport->writeMessage(fd->lines[i], server->transport->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void formServerShowForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
sendCommand(server, "FORM.SHOW %d", formId);
|
||||
}
|
||||
|
||||
|
||||
void formServerHideForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
sendCommand(server, "FORM.HIDE %d", formId);
|
||||
}
|
||||
|
||||
|
||||
void formServerDestroyForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
sendCommand(server, "FORM.DESTROY %d", formId);
|
||||
|
||||
// Remove from form store
|
||||
for (int32_t i = 0; i < server->formCount; i++) {
|
||||
if (server->forms[i].formId == formId) {
|
||||
freeFormData(&server->forms[i]);
|
||||
// Shift remaining forms down
|
||||
for (int32_t j = i; j < server->formCount - 1; j++) {
|
||||
server->forms[j] = server->forms[j + 1];
|
||||
}
|
||||
server->formCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void formServerSetProp(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *prop, const char *value)
|
||||
void formServerHideForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
sendCommand(server, "CTRL.SET %d %d %s=%s", formId, ctrlId, prop, value);
|
||||
}
|
||||
|
||||
|
||||
void formServerBindEvent(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *eventName)
|
||||
{
|
||||
sendCommand(server, "EVENT.BIND %d %d %s", formId, ctrlId, eventName);
|
||||
}
|
||||
|
||||
|
||||
void formServerUnbindEvent(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *eventName)
|
||||
{
|
||||
sendCommand(server, "EVENT.UNBIND %d %d %s", formId, ctrlId, eventName);
|
||||
}
|
||||
|
||||
|
||||
void formServerSetEventCallback(FormServerT *server, EventCallbackT cb,
|
||||
void *userData)
|
||||
{
|
||||
server->eventCallback = cb;
|
||||
server->eventUserData = userData;
|
||||
sendCommand(server, "FORM.HIDE %d", formId);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -348,7 +217,7 @@ bool formServerPollEvent(FormServerT *server)
|
|||
|
||||
// Parse: EVENT <formId> <ctrlId> <eventName> [<data>]
|
||||
const char *p = server->msgBuf;
|
||||
char token[256];
|
||||
char token[256];
|
||||
|
||||
if (!parseToken(&p, token, sizeof(token))) {
|
||||
return false;
|
||||
|
|
@ -386,3 +255,63 @@ bool formServerPollEvent(FormServerT *server)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t formServerSendForm(FormServerT *server, const char *path)
|
||||
{
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "formsrv: cannot open '%s': %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t formId = server->nextFormId++;
|
||||
char lineBuf[MAX_MSG_LEN];
|
||||
|
||||
while (fgets(lineBuf, sizeof(lineBuf), f) != NULL) {
|
||||
// Strip trailing newline
|
||||
int32_t len = (int32_t)strlen(lineBuf);
|
||||
while (len > 0 && (lineBuf[len - 1] == '\n' || lineBuf[len - 1] == '\r')) {
|
||||
lineBuf[--len] = '\0';
|
||||
}
|
||||
|
||||
// Skip empty lines
|
||||
if (len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rewriteFormId(lineBuf, sizeof(lineBuf), formId);
|
||||
server->transport->writeMessage(lineBuf, server->transport->ctx);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return formId;
|
||||
}
|
||||
|
||||
|
||||
void formServerSetEventCallback(FormServerT *server, EventCallbackT cb,
|
||||
void *userData)
|
||||
{
|
||||
server->eventCallback = cb;
|
||||
server->eventUserData = userData;
|
||||
}
|
||||
|
||||
|
||||
void formServerSetProp(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *prop, const char *value)
|
||||
{
|
||||
sendCommand(server, "CTRL.SET %d %d %s=%s", formId, ctrlId, prop, value);
|
||||
}
|
||||
|
||||
|
||||
void formServerShowForm(FormServerT *server, int32_t formId)
|
||||
{
|
||||
sendCommand(server, "FORM.SHOW %d", formId);
|
||||
}
|
||||
|
||||
|
||||
void formServerUnbindEvent(FormServerT *server, int32_t formId, int32_t ctrlId,
|
||||
const char *eventName)
|
||||
{
|
||||
sendCommand(server, "EVENT.UNBIND %d %d %s", formId, ctrlId, eventName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// formsrv.h - Remote forms server library
|
||||
//
|
||||
// Loads .form files (protocol command sequences) and sends them to a
|
||||
// remote client via a transport interface. Receives EVENT messages
|
||||
// from the client and dispatches them to a callback.
|
||||
// Streams .form files from disk to a remote client via a transport
|
||||
// interface, assigning dynamic form IDs. Receives EVENT messages from
|
||||
// the client and dispatches them to a callback.
|
||||
|
||||
#ifndef FORMSRV_H
|
||||
#define FORMSRV_H
|
||||
|
|
@ -48,12 +48,9 @@ typedef struct FormServerS FormServerT;
|
|||
FormServerT *formServerCreate(FormTransportT *transport);
|
||||
void formServerDestroy(FormServerT *server);
|
||||
|
||||
// Load a .form file into the server's form store. Returns the form ID
|
||||
// parsed from the first FORM.CREATE line, or -1 on error.
|
||||
int32_t formServerLoadFile(FormServerT *server, const char *path);
|
||||
|
||||
// Send all commands for a loaded form to the client.
|
||||
void formServerSendForm(FormServerT *server, int32_t formId);
|
||||
// Stream a .form file to the client, assigning a dynamic form ID.
|
||||
// Returns the assigned form ID, or -1 on error.
|
||||
int32_t formServerSendForm(FormServerT *server, const char *path);
|
||||
|
||||
// Send FORM.SHOW / FORM.HIDE / FORM.DESTROY commands.
|
||||
void formServerShowForm(FormServerT *server, int32_t formId);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue