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);
|
basSymTabEnterFormScope(&p->sym, formName);
|
||||||
|
|
||||||
// Emit a forward JMP that will skip form init code (patched at ENDFORM).
|
// Emit a forward JMP to skip over form init code. All module-level
|
||||||
// If no init code is emitted, the JMP is patched to jump to right here (noop).
|
// 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);
|
basEmit8(&p->cg, OP_JMP);
|
||||||
p->formInitJmpAddr = basCodePos(&p->cg);
|
p->formInitJmpAddr = basCodePos(&p->cg);
|
||||||
basEmit16(&p->cg, 0); // placeholder — patched at ENDFORM
|
basEmit16(&p->cg, 0); // placeholder — patched at ENDFORM
|
||||||
|
|
@ -2017,24 +2019,14 @@ static void parseEndForm(BasParserT *p) {
|
||||||
|
|
||||||
int32_t varCount = basSymTabLeaveFormScope(&p->sym);
|
int32_t varCount = basSymTabLeaveFormScope(&p->sym);
|
||||||
|
|
||||||
// Determine if any form init code was emitted
|
// Close the form init block: add OP_RET and patch the JMP
|
||||||
int32_t initStart = p->formInitCodeStart;
|
basEmit8(&p->cg, OP_RET);
|
||||||
int32_t initAddr = -1;
|
int32_t initAddr = p->formInitCodeStart;
|
||||||
int32_t initLen = 0;
|
int32_t initLen = basCodePos(&p->cg) - p->formInitCodeStart;
|
||||||
int32_t curPos = basCodePos(&p->cg);
|
|
||||||
|
|
||||||
if (curPos > initStart) {
|
// Patch the JMP to skip over the entire init block
|
||||||
// Init code was emitted — add OP_RET to end the init block
|
int16_t offset = (int16_t)(basCodePos(&p->cg) - (p->formInitJmpAddr + 2));
|
||||||
basEmit8(&p->cg, OP_RET);
|
basPatch16(&p->cg, p->formInitJmpAddr, offset);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
p->formInitJmpAddr = -1;
|
p->formInitJmpAddr = -1;
|
||||||
p->formInitCodeStart = -1;
|
p->formInitCodeStart = -1;
|
||||||
|
|
|
||||||
|
|
@ -552,8 +552,7 @@ void basFormRtHideForm(void *ctx, void *formRef) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form->window->visible = false;
|
dvxHideWindow(rt->ctx, form->window);
|
||||||
dvxInvalidateWindow(rt->ctx, form->window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -724,8 +723,18 @@ BasFormT *basFormRtLoadFrm(BasFormRtT *rt, const char *source, int32_t sourceLen
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "VERSION x.xx" -- skip version declaration
|
// "VERSION DVX x.xx" (native) or "VERSION x.xx" (VB import)
|
||||||
if (strncasecmp(trimmed, "VERSION ", 8) == 0) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1076,7 +1085,7 @@ void basFormRtShowForm(void *ctx, void *formRef, bool modal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form->window->visible = true;
|
dvxShowWindow(rt->ctx, form->window);
|
||||||
dvxRaiseWindow(rt->ctx, form->window);
|
dvxRaiseWindow(rt->ctx, form->window);
|
||||||
|
|
||||||
if (form->frmAutoSize) {
|
if (form->frmAutoSize) {
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,22 @@ bool dsgnLoadFrm(DsgnStateT *ds, const char *source, int32_t sourceLen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncasecmp(trimmed, "VERSION ", 8) == 0) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1014,7 +1030,7 @@ int32_t dsgnSaveFrm(const DsgnStateT *ds, char *buf, int32_t bufSize) {
|
||||||
|
|
||||||
int32_t pos = 0;
|
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, "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, " Caption = \"%s\"\n", ds->form->caption);
|
||||||
pos += snprintf(buf + pos, bufSize - pos, " Layout = %s\n", ds->form->layout);
|
pos += snprintf(buf + pos, bufSize - pos, " Layout = %s\n", ds->form->layout);
|
||||||
|
|
|
||||||
|
|
@ -902,9 +902,8 @@ static void compileAndRun(void) {
|
||||||
|
|
||||||
clearOutput();
|
clearOutput();
|
||||||
setStatus("Compiling...");
|
setStatus("Compiling...");
|
||||||
|
dvxSetBusy(sAc, true);
|
||||||
// Force a display update so the status is visible
|
dvxUpdate(sAc);
|
||||||
dvxInvalidateWindow(sAc, sWin);
|
|
||||||
|
|
||||||
// Build source: either concatenate project files or use editor contents
|
// Build source: either concatenate project files or use editor contents
|
||||||
char *concatBuf = NULL;
|
char *concatBuf = NULL;
|
||||||
|
|
@ -921,6 +920,7 @@ static void compileAndRun(void) {
|
||||||
|
|
||||||
if (!concatBuf) {
|
if (!concatBuf) {
|
||||||
setStatus("Out of memory.");
|
setStatus("Out of memory.");
|
||||||
|
dvxSetBusy(sAc, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1076,6 +1076,8 @@ static void compileAndRun(void) {
|
||||||
arrput(sProject.sourceMap, mapEntry);
|
arrput(sProject.sourceMap, mapEntry);
|
||||||
sProject.sourceMapCount = (int32_t)arrlen(sProject.sourceMap);
|
sProject.sourceMapCount = (int32_t)arrlen(sProject.sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dvxUpdate(sAc);
|
||||||
}
|
}
|
||||||
|
|
||||||
concatBuf[pos] = '\0';
|
concatBuf[pos] = '\0';
|
||||||
|
|
@ -1099,6 +1101,7 @@ static void compileAndRun(void) {
|
||||||
if (!parser) {
|
if (!parser) {
|
||||||
free(concatBuf);
|
free(concatBuf);
|
||||||
setStatus("Out of memory.");
|
setStatus("Out of memory.");
|
||||||
|
dvxSetBusy(sAc, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1125,6 +1128,7 @@ static void compileAndRun(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus("Compilation failed.");
|
setStatus("Compilation failed.");
|
||||||
|
dvxSetBusy(sAc, false);
|
||||||
basParserFree(parser);
|
basParserFree(parser);
|
||||||
free(parser);
|
free(parser);
|
||||||
free(concatBuf);
|
free(concatBuf);
|
||||||
|
|
@ -1139,9 +1143,12 @@ static void compileAndRun(void) {
|
||||||
|
|
||||||
if (!mod) {
|
if (!mod) {
|
||||||
setStatus("Failed to build module.");
|
setStatus("Failed to build module.");
|
||||||
|
dvxSetBusy(sAc, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dvxSetBusy(sAc, false);
|
||||||
|
|
||||||
// Cache the compiled module for Ctrl+F5
|
// Cache the compiled module for Ctrl+F5
|
||||||
if (sCachedModule) {
|
if (sCachedModule) {
|
||||||
basModuleFree(sCachedModule);
|
basModuleFree(sCachedModule);
|
||||||
|
|
@ -1187,11 +1194,11 @@ static void runModule(BasModuleT *mod) {
|
||||||
bool hadCodeWin = sCodeWin && sCodeWin->visible;
|
bool hadCodeWin = sCodeWin && sCodeWin->visible;
|
||||||
bool hadPrjWin = sProjectWin && sProjectWin->visible;
|
bool hadPrjWin = sProjectWin && sProjectWin->visible;
|
||||||
|
|
||||||
if (sFormWin) { sFormWin->visible = false; dvxInvalidateWindow(sAc, sFormWin); }
|
if (sFormWin) { dvxHideWindow(sAc, sFormWin); }
|
||||||
if (sToolboxWin) { sToolboxWin->visible = false; dvxInvalidateWindow(sAc, sToolboxWin); }
|
if (sToolboxWin) { dvxHideWindow(sAc, sToolboxWin); }
|
||||||
if (sPropsWin) { sPropsWin->visible = false; dvxInvalidateWindow(sAc, sPropsWin); }
|
if (sPropsWin) { dvxHideWindow(sAc, sPropsWin); }
|
||||||
if (sCodeWin) { sCodeWin->visible = false; dvxInvalidateWindow(sAc, sCodeWin); }
|
if (sCodeWin) { dvxHideWindow(sAc, sCodeWin); }
|
||||||
if (sProjectWin) { sProjectWin->visible = false; dvxInvalidateWindow(sAc, sProjectWin); }
|
if (sProjectWin) { dvxHideWindow(sAc, sProjectWin); }
|
||||||
|
|
||||||
// Create VM
|
// Create VM
|
||||||
BasVmT *vm = basVmCreate();
|
BasVmT *vm = basVmCreate();
|
||||||
|
|
@ -1291,11 +1298,11 @@ static void runModule(BasModuleT *mod) {
|
||||||
basVmDestroy(vm);
|
basVmDestroy(vm);
|
||||||
|
|
||||||
// Restore IDE windows
|
// Restore IDE windows
|
||||||
if (hadFormWin && sFormWin) { sFormWin->visible = true; dvxInvalidateWindow(sAc, sFormWin); }
|
if (hadFormWin && sFormWin) { dvxShowWindow(sAc, sFormWin); }
|
||||||
if (hadToolbox && sToolboxWin) { sToolboxWin->visible = true; dvxInvalidateWindow(sAc, sToolboxWin); }
|
if (hadToolbox && sToolboxWin) { dvxShowWindow(sAc, sToolboxWin); }
|
||||||
if (hadProps && sPropsWin) { sPropsWin->visible = true; dvxInvalidateWindow(sAc, sPropsWin); }
|
if (hadProps && sPropsWin) { dvxShowWindow(sAc, sPropsWin); }
|
||||||
if (hadCodeWin && sCodeWin) { sCodeWin->visible = true; dvxInvalidateWindow(sAc, sCodeWin); }
|
if (hadCodeWin && sCodeWin) { dvxShowWindow(sAc, sCodeWin); }
|
||||||
if (hadPrjWin && sProjectWin) { sProjectWin->visible = true; dvxInvalidateWindow(sAc, sProjectWin); }
|
if (hadPrjWin && sProjectWin) { dvxShowWindow(sAc, sProjectWin); }
|
||||||
|
|
||||||
// Repaint to clear destroyed runtime forms and restore designer
|
// Repaint to clear destroyed runtime forms and restore designer
|
||||||
dvxUpdate(sAc);
|
dvxUpdate(sAc);
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ static void onTreeReorder(WidgetT *w);
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
static void onPrpClose(WindowT *win) {
|
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) {
|
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
|
// 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.
|
// Mark the entire window content area as dirty.
|
||||||
void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);
|
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)
|
// Minimize a window (show as icon at bottom of screen)
|
||||||
void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);
|
void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue