New form scope bug fixing.
This commit is contained in:
parent
bf5bf9bb1d
commit
e36d4b9cec
8 changed files with 97 additions and 39 deletions
|
|
@ -1993,8 +1993,10 @@ static void parseBeginForm(BasParserT *p) {
|
|||
|
||||
basSymTabEnterFormScope(&p->sym, formName);
|
||||
|
||||
// Emit a forward JMP that will skip form init code (patched at ENDFORM).
|
||||
// If no init code is emitted, the JMP is patched to jump to right here (noop).
|
||||
// Emit a forward JMP to skip over form init code. All module-level
|
||||
// bytecode inside the form scope (array DIMs, UDT init, executable
|
||||
// statements, JMPs over SUB bodies) goes into the init block that
|
||||
// runs at form load time, not at program startup.
|
||||
basEmit8(&p->cg, OP_JMP);
|
||||
p->formInitJmpAddr = basCodePos(&p->cg);
|
||||
basEmit16(&p->cg, 0); // placeholder — patched at ENDFORM
|
||||
|
|
@ -2017,24 +2019,14 @@ static void parseEndForm(BasParserT *p) {
|
|||
|
||||
int32_t varCount = basSymTabLeaveFormScope(&p->sym);
|
||||
|
||||
// Determine if any form init code was emitted
|
||||
int32_t initStart = p->formInitCodeStart;
|
||||
int32_t initAddr = -1;
|
||||
int32_t initLen = 0;
|
||||
int32_t curPos = basCodePos(&p->cg);
|
||||
// Close the form init block: add OP_RET and patch the JMP
|
||||
basEmit8(&p->cg, OP_RET);
|
||||
int32_t initAddr = p->formInitCodeStart;
|
||||
int32_t initLen = basCodePos(&p->cg) - p->formInitCodeStart;
|
||||
|
||||
if (curPos > initStart) {
|
||||
// Init code was emitted — add OP_RET to end the init block
|
||||
basEmit8(&p->cg, OP_RET);
|
||||
initAddr = initStart;
|
||||
initLen = basCodePos(&p->cg) - initStart;
|
||||
}
|
||||
|
||||
// Patch the JMP to skip over init code (land here)
|
||||
if (p->formInitJmpAddr >= 0) {
|
||||
int16_t offset = (int16_t)(basCodePos(&p->cg) - (p->formInitJmpAddr + 2));
|
||||
basPatch16(&p->cg, p->formInitJmpAddr, offset);
|
||||
}
|
||||
// Patch the JMP to skip over the entire init block
|
||||
int16_t offset = (int16_t)(basCodePos(&p->cg) - (p->formInitJmpAddr + 2));
|
||||
basPatch16(&p->cg, p->formInitJmpAddr, offset);
|
||||
|
||||
p->formInitJmpAddr = -1;
|
||||
p->formInitCodeStart = -1;
|
||||
|
|
|
|||
|
|
@ -552,8 +552,7 @@ void basFormRtHideForm(void *ctx, void *formRef) {
|
|||
return;
|
||||
}
|
||||
|
||||
form->window->visible = false;
|
||||
dvxInvalidateWindow(rt->ctx, form->window);
|
||||
dvxHideWindow(rt->ctx, form->window);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -724,8 +723,18 @@ BasFormT *basFormRtLoadFrm(BasFormRtT *rt, const char *source, int32_t sourceLen
|
|||
continue;
|
||||
}
|
||||
|
||||
// "VERSION x.xx" -- skip version declaration
|
||||
// "VERSION DVX x.xx" (native) or "VERSION x.xx" (VB import)
|
||||
if (strncasecmp(trimmed, "VERSION ", 8) == 0) {
|
||||
const char *ver = trimmed + 8;
|
||||
|
||||
if (strncasecmp(ver, "DVX ", 4) != 0) {
|
||||
double vbVer = atof(ver);
|
||||
|
||||
if (vbVer > 2.0) {
|
||||
return NULL; // VB4+ form, not compatible
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1076,7 +1085,7 @@ void basFormRtShowForm(void *ctx, void *formRef, bool modal) {
|
|||
return;
|
||||
}
|
||||
|
||||
form->window->visible = true;
|
||||
dvxShowWindow(rt->ctx, form->window);
|
||||
dvxRaiseWindow(rt->ctx, form->window);
|
||||
|
||||
if (form->frmAutoSize) {
|
||||
|
|
|
|||
|
|
@ -401,6 +401,22 @@ bool dsgnLoadFrm(DsgnStateT *ds, const char *source, int32_t sourceLen) {
|
|||
}
|
||||
|
||||
if (strncasecmp(trimmed, "VERSION ", 8) == 0) {
|
||||
// Accept "VERSION DVX x.xx" (native) and "VERSION x.xx" (VB import).
|
||||
// Reject VB forms with version > 1.xx (VB4+/VB6 use features we
|
||||
// don't support like OLE controls and binary properties).
|
||||
const char *ver = trimmed + 8;
|
||||
|
||||
if (strncasecmp(ver, "DVX ", 4) == 0) {
|
||||
// Native DVX BASIC form — always accepted
|
||||
} else {
|
||||
// VB form — check version number
|
||||
double vbVer = atof(ver);
|
||||
|
||||
if (vbVer > 2.0) {
|
||||
return false; // VB4+ form, not compatible
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1014,7 +1030,7 @@ int32_t dsgnSaveFrm(const DsgnStateT *ds, char *buf, int32_t bufSize) {
|
|||
|
||||
int32_t pos = 0;
|
||||
|
||||
pos += snprintf(buf + pos, bufSize - pos, "VERSION 1.00\n");
|
||||
pos += snprintf(buf + pos, bufSize - pos, "VERSION DVX 1.00\n");
|
||||
pos += snprintf(buf + pos, bufSize - pos, "Begin Form %s\n", ds->form->name);
|
||||
pos += snprintf(buf + pos, bufSize - pos, " Caption = \"%s\"\n", ds->form->caption);
|
||||
pos += snprintf(buf + pos, bufSize - pos, " Layout = %s\n", ds->form->layout);
|
||||
|
|
|
|||
|
|
@ -902,9 +902,8 @@ static void compileAndRun(void) {
|
|||
|
||||
clearOutput();
|
||||
setStatus("Compiling...");
|
||||
|
||||
// Force a display update so the status is visible
|
||||
dvxInvalidateWindow(sAc, sWin);
|
||||
dvxSetBusy(sAc, true);
|
||||
dvxUpdate(sAc);
|
||||
|
||||
// Build source: either concatenate project files or use editor contents
|
||||
char *concatBuf = NULL;
|
||||
|
|
@ -921,6 +920,7 @@ static void compileAndRun(void) {
|
|||
|
||||
if (!concatBuf) {
|
||||
setStatus("Out of memory.");
|
||||
dvxSetBusy(sAc, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1076,6 +1076,8 @@ static void compileAndRun(void) {
|
|||
arrput(sProject.sourceMap, mapEntry);
|
||||
sProject.sourceMapCount = (int32_t)arrlen(sProject.sourceMap);
|
||||
}
|
||||
|
||||
dvxUpdate(sAc);
|
||||
}
|
||||
|
||||
concatBuf[pos] = '\0';
|
||||
|
|
@ -1099,6 +1101,7 @@ static void compileAndRun(void) {
|
|||
if (!parser) {
|
||||
free(concatBuf);
|
||||
setStatus("Out of memory.");
|
||||
dvxSetBusy(sAc, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1125,6 +1128,7 @@ static void compileAndRun(void) {
|
|||
}
|
||||
|
||||
setStatus("Compilation failed.");
|
||||
dvxSetBusy(sAc, false);
|
||||
basParserFree(parser);
|
||||
free(parser);
|
||||
free(concatBuf);
|
||||
|
|
@ -1139,9 +1143,12 @@ static void compileAndRun(void) {
|
|||
|
||||
if (!mod) {
|
||||
setStatus("Failed to build module.");
|
||||
dvxSetBusy(sAc, false);
|
||||
return;
|
||||
}
|
||||
|
||||
dvxSetBusy(sAc, false);
|
||||
|
||||
// Cache the compiled module for Ctrl+F5
|
||||
if (sCachedModule) {
|
||||
basModuleFree(sCachedModule);
|
||||
|
|
@ -1187,11 +1194,11 @@ static void runModule(BasModuleT *mod) {
|
|||
bool hadCodeWin = sCodeWin && sCodeWin->visible;
|
||||
bool hadPrjWin = sProjectWin && sProjectWin->visible;
|
||||
|
||||
if (sFormWin) { sFormWin->visible = false; dvxInvalidateWindow(sAc, sFormWin); }
|
||||
if (sToolboxWin) { sToolboxWin->visible = false; dvxInvalidateWindow(sAc, sToolboxWin); }
|
||||
if (sPropsWin) { sPropsWin->visible = false; dvxInvalidateWindow(sAc, sPropsWin); }
|
||||
if (sCodeWin) { sCodeWin->visible = false; dvxInvalidateWindow(sAc, sCodeWin); }
|
||||
if (sProjectWin) { sProjectWin->visible = false; dvxInvalidateWindow(sAc, sProjectWin); }
|
||||
if (sFormWin) { dvxHideWindow(sAc, sFormWin); }
|
||||
if (sToolboxWin) { dvxHideWindow(sAc, sToolboxWin); }
|
||||
if (sPropsWin) { dvxHideWindow(sAc, sPropsWin); }
|
||||
if (sCodeWin) { dvxHideWindow(sAc, sCodeWin); }
|
||||
if (sProjectWin) { dvxHideWindow(sAc, sProjectWin); }
|
||||
|
||||
// Create VM
|
||||
BasVmT *vm = basVmCreate();
|
||||
|
|
@ -1291,11 +1298,11 @@ static void runModule(BasModuleT *mod) {
|
|||
basVmDestroy(vm);
|
||||
|
||||
// Restore IDE windows
|
||||
if (hadFormWin && sFormWin) { sFormWin->visible = true; dvxInvalidateWindow(sAc, sFormWin); }
|
||||
if (hadToolbox && sToolboxWin) { sToolboxWin->visible = true; dvxInvalidateWindow(sAc, sToolboxWin); }
|
||||
if (hadProps && sPropsWin) { sPropsWin->visible = true; dvxInvalidateWindow(sAc, sPropsWin); }
|
||||
if (hadCodeWin && sCodeWin) { sCodeWin->visible = true; dvxInvalidateWindow(sAc, sCodeWin); }
|
||||
if (hadPrjWin && sProjectWin) { sProjectWin->visible = true; dvxInvalidateWindow(sAc, sProjectWin); }
|
||||
if (hadFormWin && sFormWin) { dvxShowWindow(sAc, sFormWin); }
|
||||
if (hadToolbox && sToolboxWin) { dvxShowWindow(sAc, sToolboxWin); }
|
||||
if (hadProps && sPropsWin) { dvxShowWindow(sAc, sPropsWin); }
|
||||
if (hadCodeWin && sCodeWin) { dvxShowWindow(sAc, sCodeWin); }
|
||||
if (hadPrjWin && sProjectWin) { dvxShowWindow(sAc, sProjectWin); }
|
||||
|
||||
// Repaint to clear destroyed runtime forms and restore designer
|
||||
dvxUpdate(sAc);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static void onTreeReorder(WidgetT *w);
|
|||
// ============================================================
|
||||
|
||||
static void onPrpClose(WindowT *win) {
|
||||
win->visible = false;
|
||||
dvxHideWindow(sPrpCtx, win);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void onToolClick(WidgetT *w) {
|
|||
|
||||
|
||||
static void onTbxClose(WindowT *win) {
|
||||
win->visible = false;
|
||||
dvxHideWindow(sDs->ctx, win);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3925,6 +3925,34 @@ WindowT *dvxCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w,
|
|||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// dvxHideWindow
|
||||
// ============================================================
|
||||
|
||||
void dvxHideWindow(AppContextT *ctx, WindowT *win) {
|
||||
if (!win || !win->visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyListAdd(&ctx->dirty, win->x, win->y, win->w, win->h);
|
||||
win->visible = false;
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// dvxShowWindow
|
||||
// ============================================================
|
||||
|
||||
void dvxShowWindow(AppContextT *ctx, WindowT *win) {
|
||||
if (!win || win->visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
win->visible = true;
|
||||
dvxInvalidateWindow(ctx, win);
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// dvxDestroyWindow
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -223,6 +223,12 @@ void dvxInvalidateRect(AppContextT *ctx, WindowT *win, int32_t x, int32_t y, int
|
|||
// Mark the entire window content area as dirty.
|
||||
void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);
|
||||
|
||||
// Hide a window without destroying it (marks exposed region dirty).
|
||||
void dvxHideWindow(AppContextT *ctx, WindowT *win);
|
||||
|
||||
// Show a previously hidden window (marks region dirty for repaint).
|
||||
void dvxShowWindow(AppContextT *ctx, WindowT *win);
|
||||
|
||||
// Minimize a window (show as icon at bottom of screen)
|
||||
void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue