// formrt.h -- DVX BASIC form runtime // // Bridges BASIC programs to the DVX widget system. Control types // are resolved dynamically via WgtIfaceT interface descriptors // registered by .wgt DXE files. Properties and methods are // dispatched generically through descriptors. Events fire by // looking up ControlName_EventName in the compiled module's // procedure table and calling into the VM. #ifndef DVXBASIC_FORMRT_H #define DVXBASIC_FORMRT_H #include "../runtime/vm.h" #include "../runtime/values.h" #include "dvxApp.h" #include "dvxWgt.h" // ============================================================ // Forward declarations // ============================================================ typedef struct BasFormT BasFormT; typedef struct BasControlT BasControlT; // ============================================================ // Limits // ============================================================ #define BAS_MAX_CTRL_NAME 32 #define BAS_MAX_FRM_NESTING 16 // ============================================================ // Menu ID to name mapping for event dispatch // ============================================================ typedef struct { int32_t id; char name[BAS_MAX_CTRL_NAME]; BasControlT *proxy; // heap-allocated proxy for property access (widget=NULL, menuId stored) } BasMenuIdMapT; // ============================================================ // Control instance (a widget on a form) // ============================================================ #define BAS_MAX_TEXT_BUF 256 #define BAS_MAX_EVENT_OVERRIDES 16 // Event handler override (SetEvent) typedef struct { char eventName[BAS_MAX_CTRL_NAME]; // e.g. "Click" char handlerName[BAS_MAX_CTRL_NAME]; // e.g. "HandleOkClick" } BasEventOverrideT; typedef struct BasControlT { char name[BAS_MAX_CTRL_NAME]; // VB control name (e.g. "Command1") char typeName[BAS_MAX_CTRL_NAME]; // VB type name (e.g. "CommandButton") int32_t index; // control array index (-1 = not in array) WidgetT *widget; // the DVX widget BasFormT *form; // owning form const WgtIfaceT *iface; // interface descriptor (from .wgt) char textBuf[BAS_MAX_TEXT_BUF]; // persistent text for Caption/Text char dataSource[BAS_MAX_CTRL_NAME]; // name of Data control for binding char dataField[BAS_MAX_CTRL_NAME]; // column name for binding char helpTopic[BAS_MAX_CTRL_NAME]; // help topic ID for F1 int32_t menuId; // WM menu item ID (>0 for menu items, 0 for controls) BasEventOverrideT eventOverrides[BAS_MAX_EVENT_OVERRIDES]; int32_t eventOverrideCount; } BasControlT; // ============================================================ // Form instance (a DVX window with controls) // ============================================================ typedef struct BasFormT { char name[BAS_MAX_CTRL_NAME]; // form name (e.g. "Form1") WindowT *window; // DVX window WidgetT *root; // widget root (from wgtInitWindow) WidgetT *contentBox; // VBox/HBox for user controls AppContextT *ctx; // DVX app context BasControlT **controls; // stb_ds array of heap-allocated pointers BasVmT *vm; // VM for event dispatch BasModuleT *module; // compiled module (for SUB lookup) // Form-level properties (accumulated during .frm parsing) int32_t frmWidth; int32_t frmHeight; int32_t frmLeft; int32_t frmTop; bool frmResizable; bool frmHasResizable; // true if Resizable was explicitly set bool frmCentered; bool frmAutoSize; char frmLayout[32]; // "VBox", "HBox", or "WrapBox" char helpTopic[BAS_MAX_CTRL_NAME]; // form-level help topic // Per-form variable storage (allocated at load, freed at unload) BasValueT *formVars; int32_t formVarCount; // Menu ID to name mapping (for event dispatch) BasMenuIdMapT *menuIdMap; int32_t menuIdMapCount; // Synthetic control entry for the form itself, so that // FormName.Property works through the same getProp/setProp path. BasControlT formCtrl; } BasFormT; // ============================================================ // Form runtime context // ============================================================ // Cached .frm source for reload after unload typedef struct { char formName[BAS_MAX_CTRL_NAME]; char *frmSource; // malloc'd copy of .frm text int32_t frmSourceLen; } BasFrmCacheT; // Cached compiled form binary (for standalone apps) typedef struct { char formName[BAS_MAX_CTRL_NAME]; uint8_t *data; // malloc'd binary data int32_t dataLen; } BasCfmCacheT; typedef struct { AppContextT *ctx; // DVX app context BasVmT *vm; // shared VM instance BasModuleT *module; // compiled module BasFormT **forms; // stb_ds array of heap-allocated pointers BasFormT *currentForm; // form currently dispatching events char helpFile[256]; // project help file path (for F1) BasFrmCacheT *frmCache; // stb_ds array of cached .frm sources int32_t frmCacheCount; BasCfmCacheT *cfmCache; // stb_ds array of compiled form binaries int32_t cfmCacheCount; } BasFormRtT; // ============================================================ // API // ============================================================ // Initialize the form runtime with a DVX context and a compiled module. BasFormRtT *basFormRtCreate(AppContextT *ctx, BasVmT *vm, BasModuleT *module); // Load all cached forms (.frm text and compiled binaries) and show the // startup form. Called before bytecode execution begins. void basFormRtLoadAllForms(BasFormRtT *rt, const char *startupFormName); // VB-style event loop: pump DVX events until all forms are closed. // Called after bytecode halts to keep the app alive for event handlers. void basFormRtEventLoop(BasFormRtT *rt); // Simple non-debug execution: run bytecode in slices with dvxUpdate // between slices, then enter the event loop. Used by the standalone stub. void basFormRtRunSimple(BasFormRtT *rt); // Destroy the form runtime and all forms/controls. void basFormRtDestroy(BasFormRtT *rt); // Wire up the VM's UI callbacks to this form runtime. void basFormRtBindVm(BasFormRtT *rt); // ---- UI callback implementations (match BasUiCallbacksT) ---- BasValueT basFormRtGetProp(void *ctx, void *ctrlRef, const char *propName); void basFormRtSetProp(void *ctx, void *ctrlRef, const char *propName, BasValueT value); BasValueT basFormRtCallMethod(void *ctx, void *ctrlRef, const char *methodName, BasValueT *args, int32_t argc); void *basFormRtCreateCtrl(void *ctx, void *formRef, const char *typeName, const char *ctrlName); void *basFormRtFindCtrl(void *ctx, void *formRef, const char *ctrlName); void *basFormRtFindCtrlIdx(void *ctx, void *formRef, const char *ctrlName, int32_t index); void *basFormRtLoadForm(void *ctx, const char *formName); void basFormRtUnloadForm(void *ctx, void *formRef); void basFormRtShowForm(void *ctx, void *formRef, bool modal); void basFormRtHideForm(void *ctx, void *formRef); int32_t basFormRtMsgBox(void *ctx, const char *message, int32_t flags); // ---- Extern call callbacks (shared by IDE and stub) ---- void *basExternResolve(void *ctx, const char *libName, const char *funcName); BasValueT basExternCall(void *ctx, void *funcPtr, const char *libName, const char *funcName, BasValueT *args, int32_t argc, uint8_t retType); // ---- Form caching ---- // Register .frm source text for lazy loading when bytecode calls Load. void basFormRtRegisterFrm(BasFormRtT *rt, const char *formName, const char *source, int32_t sourceLen); // Register a compiled form binary for lazy loading when bytecode calls Load. void basFormRtRegisterCfm(BasFormRtT *rt, const char *formName, const uint8_t *data, int32_t dataLen); // ---- Widget creation ---- WidgetT *createWidget(const char *wgtTypeName, WidgetT *parent); // ---- Form window creation ---- WidgetT *basFormRtCreateContentBox(WidgetT *root, const char *layout); WindowT *basFormRtCreateFormWindow(AppContextT *ctx, const char *title, const char *layout, bool resizable, bool centered, bool autoSize, int32_t width, int32_t height, int32_t left, int32_t top, WidgetT **outRoot, WidgetT **outContentBox); // ---- Dynamic form/control API ---- void *basFormRtCreateForm(void *ctx, const char *formName, int32_t width, int32_t height); void *basFormRtCreateCtrlEx(void *ctx, void *formRef, const char *typeName, const char *ctrlName, void *parentRef); void basFormRtSetEvent(void *ctx, void *ctrlRef, const char *eventName, const char *handlerName); void basFormRtRemoveCtrl(void *ctx, void *formRef, const char *ctrlName); // ---- Event dispatch ---- bool basFormRtFireEvent(BasFormRtT *rt, BasFormT *form, const char *ctrlName, const char *eventName); bool basFormRtFireEventArgs(BasFormRtT *rt, BasFormT *form, const char *ctrlName, const char *eventName, const BasValueT *args, int32_t argCount); // ---- Form file loading ---- BasFormT *basFormRtLoadFrm(BasFormRtT *rt, const char *source, int32_t sourceLen); #endif // DVXBASIC_FORMRT_H