From 744bd191070c54bae77902d667dafb3d5f42d3f8 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Wed, 18 Aug 2021 00:21:03 -0300 Subject: [PATCH 1/7] Fixes race condition between vWatch and _CONSOLETITLE It was a love triangle with _WindowHandle in the end, it's complicated. --- internal/c/libqb.cpp | 18 +++++++++--------- internal/support/vwatch/vwatch.bm | 10 ++++++---- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/internal/c/libqb.cpp b/internal/c/libqb.cpp index 55363f1c5..72371dfb2 100644 --- a/internal/c/libqb.cpp +++ b/internal/c/libqb.cpp @@ -26203,15 +26203,15 @@ void sub_put2(int32 i,int64 offset,void *element,int32 passed){ int32 func__screenhide(){return -screen_hide;} void sub__consoletitle(qbs* s){ - if (new_error) return; - static qbs *sz=NULL; if (!sz) sz=qbs_new(0,0); - static qbs *cz=NULL; if (!cz){cz=qbs_new(1,0); cz->chr[0]=0;} - qbs_set(sz,qbs_add(s,cz)); - if (console){ if (console_active){ - #ifdef QB64_WINDOWS - SetConsoleTitle((char*)sz->chr); - #endif - }} + #ifdef QB64_WINDOWS + char *title; + title = (char *)malloc(s->len + 1); + title[s->len] = '\0'; //add NULL terminator + memcpy(title, s->chr, s->len); + if (console){ if (console_active){ + SetConsoleTitle(title); + }} + #endif } diff --git a/internal/support/vwatch/vwatch.bm b/internal/support/vwatch/vwatch.bm index b1e4e4538..326f21d7d 100644 --- a/internal/support/vwatch/vwatch.bm +++ b/internal/support/vwatch/vwatch.bm @@ -97,10 +97,12 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) LOOP END IF - IF vw_hwndsent = 0 AND _WINDOWHANDLE > 0 THEN - vw_hwndsent = -1 - vw_cmd$ = "hwnd:" + _MK$(_OFFSET, _WINDOWHANDLE) - GOSUB SendCommand + IF vw_hwndsent = 0 THEN + IF _WINDOWHANDLE > 0 THEN + vw_hwndsent = -1 + vw_cmd$ = "hwnd:" + _MK$(_OFFSET, _WINDOWHANDLE) + GOSUB SendCommand + END IF END IF IF vwatch_linenumber = 0 THEN From e791ca2001967c05cc878e88e2ce92f0166b56f1 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Wed, 18 Aug 2021 00:26:06 -0300 Subject: [PATCH 2/7] Ensures _ConsoleTitle has time to do its thing. --- internal/c/libqb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/c/libqb.cpp b/internal/c/libqb.cpp index 72371dfb2..33d073e9d 100644 --- a/internal/c/libqb.cpp +++ b/internal/c/libqb.cpp @@ -26210,6 +26210,7 @@ void sub_put2(int32 i,int64 offset,void *element,int32 passed){ memcpy(title, s->chr, s->len); if (console){ if (console_active){ SetConsoleTitle(title); + Sleep(40); }} #endif } From e311e2ee35c52d228eadb4d9a2aa6b6616278d15 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 19 Aug 2021 01:05:47 -0300 Subject: [PATCH 3/7] Optimizes $Debug internal protocol. Less back-and-forth of commands to get variable data. Moves processing/address fetching almost entirely to `vwatch.bm`. --- internal/support/vwatch/vwatch.bm | 108 ++++++++++++++++++++++++------ source/ide/ide_methods.bas | 70 +++---------------- 2 files changed, 95 insertions(+), 83 deletions(-) diff --git a/internal/support/vwatch/vwatch.bm b/internal/support/vwatch/vwatch.bm index 326f21d7d..4b895e357 100644 --- a/internal/support/vwatch/vwatch.bm +++ b/internal/support/vwatch/vwatch.bm @@ -6,10 +6,12 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) STATIC AS _BYTE vw_pauseMode, vw_stepOver, vw_bypass, vw_setNextLine, vw_hwndsent STATIC AS _OFFSET vw_idehwnd STATIC vw_buffer$ - DIM AS LONG vw_i, vw_tempIndex, vw_localIndex, vw_varSize, vw_sequence, vw_cmdsize + DIM AS LONG vw_i, vw_tempIndex, vw_localIndex, vw_varSize, vw_cmdsize DIM AS _OFFSET vw_address DIM AS _MEM vw_m, vw_m2 - DIM vw_start!, vw_temp$, vw_cmd$, vw_value$, vw_k&, vw_buf$, vw_scope$ + DIM AS _BYTE vw_isarray + DIM vw_start!, vw_temp$, vw_cmd$, vw_value$, vw_k&, vw_buf$, vw_scope$, vw_varType$ + DIM vw_dummy%& DECLARE LIBRARY SUB vwatch_stoptimers ALIAS stop_timers @@ -250,26 +252,22 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) CASE "call stack" 'send call stack history GOSUB SendCallStack - CASE "get address" + CASE "get global var", "get local var" vw_tempIndex = CVL(LEFT$(vw_value$, 4)) - vw_arrayIndex = CVL(MID$(vw_value$, 5, 4)) - vw_sequence = CVI(MID$(vw_value$, 9, 2)) - vw_varSize = CVL(MID$(vw_value$, 11, 4)) - vw_address = _CV(_OFFSET, MID$(vw_value$, 15, LEN(vw_address))) - vw_buf$ = SPACE$(vw_varSize) - vw_m = _MEM(vw_address, vw_varSize) - vw_m2 = _MEM(_OFFSET(vw_buf$), vw_varSize) - _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET - vw_cmd$ = "address read:" + MKL$(vw_tempIndex) + MKL$(vw_arrayIndex) + MKI$(vw_sequence) + _MK$(_OFFSET, vw_address) + vw_buf$ - GOSUB SendCommand - CASE "get global address", "get local address" - vw_tempIndex = CVL(LEFT$(vw_value$, 4)) - vw_localIndex = CVL(MID$(vw_value$, 5, 4)) - vw_arrayIndex = CVL(MID$(vw_value$, 9, 4)) - vw_sequence = CVI(MID$(vw_value$, 13, 2)) - vw_varSize = CVL(MID$(vw_value$, 15, 4)) - vw_scope$ = MID$(vw_value$, 19) - IF vw_cmd$ = "get global address" THEN + vw_isarray = _CV(_BYTE, MID$(vw_value$, 5, 1)) + vw_localIndex = CVL(MID$(vw_value$, 6, 4)) + vw_arrayIndex = CVL(MID$(vw_value$, 10, 4)) + vw_varSize = CVL(MID$(vw_value$, 14, 4)) + vw_i = CVI(MID$(vw_value$, 18, 2)) + IF vw_i THEN + vw_scope$ = MID$(vw_value$, 20, vw_i) + vw_i = CVI(MID$(vw_value$, 20 + vw_i, 2)) + vw_varType$ = RIGHT$(vw_value$, vw_i) + ELSE + vw_i = CVI(MID$(vw_value$, 20, 2)) + vw_varType$ = RIGHT$(vw_value$, vw_i) + END IF + IF vw_cmd$ = "get global var" THEN vw_address = _OFFSET(globalVariables) + LEN(vw_address) * vw_localIndex ELSE IF vw_scope$ = LEFT$(vwatch_stack(vwatch_sublevel), INSTR(vwatch_stack(vwatch_sublevel), ",") - 1) THEN @@ -281,12 +279,78 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) vw_address = _MEMGET(vw_m, vw_address, _OFFSET) 'first resolve pass vw_address = _MEMGET(vw_m, vw_address, _OFFSET) 'second resolve pass + IF vw_isarray THEN + 'get the address of where this array is stored + vw_buf$ = SPACE$(LEN(vw_dummy%&)) + vw_m = _MEM(vw_address, LEN(vw_dummy%&)) + vw_m2 = _MEM(_OFFSET(vw_buf$), LEN(vw_dummy%&)) + _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET + + IF LEN(vw_dummy%&) = 8 THEN + vw_address = _CV(_INTEGER64, vw_buf$) 'Pointer to data + ELSE + vw_address = _CV(LONG, vw_buf$) 'Pointer to data + END IF + 'vw_address now points to the actual data + + 'find the required element for this array + IF INSTR(vw_varType$, "STRING *") THEN + vw_varSize = VAL(MID$(vw_varType$, _INSTRREV(vw_varType$, " ") + 1)) + ELSEIF INSTR(vw_varType$, "STRING") THEN + vw_varSize = LEN(vw_dummy%&) + END IF + + 'this is where we calculate the actual element position in memory + vw_address = vw_address + ((vw_arrayIndex - 1) * vw_varSize) + END IF + 'vw_address now points to the actual data vw_buf$ = SPACE$(vw_varSize) vw_m = _MEM(vw_address, vw_varSize) vw_m2 = _MEM(_OFFSET(vw_buf$), vw_varSize) _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET - vw_cmd$ = "address read:" + MKL$(vw_tempIndex) + MKL$(vw_arrayIndex) + MKI$(vw_sequence) + _MK$(_OFFSET, vw_address) + vw_buf$ + + IF INSTR(vw_varType$, "STRING *") > 0 AND vw_isarray <> 0 THEN + 'actual data already fetched; nothing else to do + ELSEIF INSTR(vw_varType$, "STRING") THEN + IF vw_isarray THEN + 'First pass + vw_varSize = LEN(vw_dummy%&) + vw_buf$ = SPACE$(vw_varSize) + vw_m = _MEM(vw_address, vw_varSize) + vw_m2 = _MEM(_OFFSET(vw_buf$), vw_varSize) + _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET + + IF LEN(vw_dummy%&) = 8 THEN + vw_address = _CV(_INTEGER64, vw_buf$) 'Pointer to data + ELSE + vw_address = _CV(LONG, vw_buf$) 'Pointer to data + END IF + + 'Second pass + vw_varSize = LEN(vw_dummy%&) + LEN(vw_varSize) + vw_buf$ = SPACE$(vw_varSize) + vw_m = _MEM(vw_address, vw_varSize) + vw_m2 = _MEM(_OFFSET(vw_buf$), vw_varSize) + _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET + END IF + + 'vw_buf$ now contains a pointer to the string data + 'as well as the number of bytes we have to read + IF LEN(vw_dummy%&) = 8 THEN + vw_address = _CV(_INTEGER64, LEFT$(vw_buf$, 8)) 'Pointer to data + vw_varSize = CVL(MID$(vw_buf$, 9)) + ELSE + vw_address = _CV(LONG, LEFT$(vw_buf$, 4)) 'Pointer to data + vw_varSize = CVL(MID$(vw_buf$, 5)) + END IF + vw_buf$ = SPACE$(vw_varSize) + vw_m = _MEM(vw_address, vw_varSize) + vw_m2 = _MEM(_OFFSET(vw_buf$), vw_varSize) + _MEMCOPY vw_m, vw_m.OFFSET, vw_m.SIZE TO vw_m2, vw_m2.OFFSET + END IF + + vw_cmd$ = "address read:" + MKL$(vw_tempIndex) + MKL$(vw_arrayIndex) + vw_buf$ GOSUB SendCommand CASE "set global address", "set local address" vw_localIndex = CVL(LEFT$(vw_value$, 4)) diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index 86fae07d6..798577208 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -7384,14 +7384,13 @@ SUB DebugMode temp$ = MID$(temp$, 9) cmd$ = "" IF LEN(usedVariableList(tempIndex&).subfunc) = 0 THEN - cmd$ = "get global address:" + cmd$ = "get global var:" ELSE - cmd$ = "get local address:" + cmd$ = "get local var:" END IF GOSUB GetVarSize - IF usedVariableList(tempIndex&).isarray THEN varSize& = LEN(dummy%&) IF LEN(cmd$) THEN - cmd$ = cmd$ + MKL$(tempIndex&) + MKL$(usedVariableList(tempIndex&).localIndex) + MKL$(tempArrayIndex&) + MKI$(1) + MKL$(varSize&) + usedVariableList(tempIndex&).subfunc + cmd$ = cmd$ + MKL$(tempIndex&) + _MK$(_BYTE, usedVariableList(tempIndex&).isarray) + MKL$(usedVariableList(tempIndex&).localIndex) + MKL$(tempArrayIndex&) + MKL$(varSize&) + MKI$(LEN(usedVariableList(tempIndex&).subfunc)) + usedVariableList(tempIndex&).subfunc + MKI$(LEN(usedVariableList(tempIndex&).varType)) + usedVariableList(tempIndex&).varType GOSUB SendCommand END IF LOOP @@ -7401,44 +7400,8 @@ SUB DebugMode CASE "address read" tempIndex& = CVL(LEFT$(value$, 4)) tempArrayIndex& = CVL(MID$(value$, 5, 4)) - sequence% = CVI(MID$(value$, 9, 2)) - address%& = _CV(_OFFSET, MID$(value$, 11, LEN(address%&))) - recvData$ = MID$(value$, 11 + LEN(address%&)) + recvData$ = MID$(value$, 9) GOSUB GetVarSize - IF usedVariableList(tempIndex&).isarray THEN - SELECT CASE sequence% - CASE 1 'received array's address; request tempArrayIndex& - IF LEN(dummy%&) = 8 THEN - address%& = _CV(_INTEGER64, LEFT$(recvData$, 8)) 'Pointer to data - ELSE - address%& = _CV(LONG, LEFT$(recvData$, 4)) 'Pointer to data - END IF - - IF INSTR(usedVariableList(tempIndex&).varType, "STRING *") THEN - varType$ = usedVariableList(tempIndex&).varType - varSize& = VAL(MID$(varType$, _INSTRREV(varType$, " ") + 1)) - ELSEIF varType$ = "STRING" THEN - varSize& = LEN(dummy%&) - END IF - address%& = address%& + ((tempArrayIndex& - 1) * varSize&) - cmd$ = "get address:" + MKL$(tempIndex&) + MKL$(tempArrayIndex&) + MKI$(2) + MKL$(varSize&) + _MK$(_OFFSET, address%&) - GOSUB SendCommand - GOTO vwatch_sequence_done - CASE 2 'actual string data received or variable-length address - IF INSTR(usedVariableList(tempIndex&).varType, "STRING *") THEN - GOTO storeReceivedData - ELSEIF varType$ = "STRING" THEN - varSize& = LEN(dummy%&) + LEN(dummy&) - cmd$ = "get address:" + MKL$(tempIndex&) + MKL$(tempArrayIndex&) + MKI$(3) + MKL$(varSize&) + recvData$ - GOSUB SendCommand - GOTO vwatch_sequence_done - END IF - CASE 3 'got an address and the length of this string array index - GOTO requestActualStringData - CASE 4 'variable-length string data finally received - GOTO storeReceivedData - END SELECT - END IF SELECT CASE varType$ CASE "_BYTE", "BYTE": recvData$ = STR$(_CV(_BYTE, recvData$)) CASE "_UNSIGNED _BYTE", "UNSIGNED BYTE": recvData$ = STR$(_CV(_UNSIGNED _BYTE, recvData$)) @@ -7453,32 +7416,17 @@ SUB DebugMode CASE "_FLOAT", "FLOAT": recvData$ = STR$(_CV(_FLOAT, recvData$)) CASE "_OFFSET", "OFFSET": recvData$ = STR$(_CV(_OFFSET, recvData$)) CASE "_UNSIGNED _OFFSET", "UNSIGNED OFFSET": recvData$ = STR$(_CV(_UNSIGNED _OFFSET, recvData$)) - CASE "STRING" - IF sequence% = 1 THEN - requestActualStringData: - IF LEN(dummy%&) = 8 THEN - address%& = _CV(_INTEGER64, LEFT$(recvData$, 8)) 'Pointer to data - strLength& = CVL(MID$(recvData$, 9)) - ELSE - address%& = _CV(LONG, LEFT$(recvData$, 4)) 'Pointer to data - strLength& = CVL(MID$(recvData$, 5)) - END IF - - sequence% = sequence% + 1 - cmd$ = "get address:" + MKL$(tempIndex&) + MKL$(tempArrayIndex&) + MKI$(sequence%) + MKL$(strLength&) + _MK$(_OFFSET, address%&) - GOSUB SendCommand - GOTO vwatch_sequence_done - END IF + 'CASE "STRING": 'no conversion required END SELECT - storeReceivedData: IF usedVariableList(tempIndex&).isarray THEN seqIndex& = INSTR(usedVariableList(tempIndex&).indexes, MKL$(tempArrayIndex&)) - storageSlot& = CVL(MID$(usedVariableList(tempIndex&).storage, seqIndex&, 4)) - vWatchArrayReceivedData$(storageSlot&) = recvData$ + IF seqIndex& <= LEN(usedVariableList(tempIndex&).mostRecentValue) - 3 THEN + storageSlot& = CVL(MID$(usedVariableList(tempIndex&).mostRecentValue, seqIndex&, 4)) + vWatchArrayReceivedData$(storageSlot&) = recvData$ + END IF ELSE usedVariableList(tempIndex&).mostRecentValue = recvData$ END IF - vwatch_sequence_done: IF PauseMode THEN GOSUB UpdateDisplay CASE "current sub" currentSub$ = value$ From 34950c80eacff829627a673068252728eafb1fea Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 19 Aug 2021 01:09:18 -0300 Subject: [PATCH 4/7] Visual tweaks to dialogs. Show received array data in Watch List box. --- source/ide/ide_methods.bas | 70 ++++++++++++++++++++++++++++++++------ source/qb64.bas | 3 +- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index 798577208..d33739b1d 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -7653,8 +7653,10 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl IF usedVariableList(tempIndex&).subfunc = currentScope$ OR usedVariableList(tempIndex&).subfunc = "" THEN IF usedVariableList(tempIndex&).isarray THEN seqIndex& = INSTR(usedVariableList(tempIndex&).indexes, MKL$(tempArrayIndex&)) - storageSlot& = CVL(MID$(usedVariableList(tempIndex&).storage, seqIndex&, 4)) - tempValue$ = vWatchArrayReceivedData$(storageSlot&) + IF seqIndex& <= LEN(usedVariableList(tempIndex&).mostRecentValue) - 3 THEN + storageSlot& = CVL(MID$(usedVariableList(tempIndex&).mostRecentValue, seqIndex&, 4)) + tempValue$ = vWatchArrayReceivedData$(storageSlot&) + END IF ELSE tempValue$ = usedVariableList(tempIndex&).mostRecentValue END IF @@ -7766,7 +7768,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF dialogHeight < 9 THEN dialogHeight = 9 dialogWidth = 6 + maxModuleNameLen + maxVarLen + maxTypeLen - IF IdeDebugMode > 0 THEN dialogWidth = dialogWidth + 200 'make room for "= values" + IF IdeDebugMode > 0 THEN dialogWidth = dialogWidth + 100 'make room for "= values" IF dialogWidth < 60 THEN dialogWidth = 60 IF dialogWidth > idewx - 8 THEN dialogWidth = idewx - 8 @@ -7954,6 +7956,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) longestVarName = 0 nextvWatchArraySlot = 0 FOR y = 1 TO totalVariablesCreated + usedVariableList(y).mostRecentValue = "" IF usedVariableList(y).watch THEN thisLen = LEN(usedVariableList(y).name) IF usedVariableList(y).isarray THEN @@ -7973,7 +7976,7 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) WHILE nextvWatchArraySlot > UBOUND(vWatchArrayReceivedData$) REDIM _PRESERVE vWatchArrayReceivedData$(1 TO UBOUND(vWatchArrayReceivedData$) + 999) WEND - usedVariableList(y).storage = usedVariableList(y).storage + MKL$(nextvWatchArraySlot) + usedVariableList(y).mostRecentValue = usedVariableList(y).mostRecentValue + MKL$(nextvWatchArraySlot) vWatchArrayReceivedData$(nextvWatchArraySlot) = "" temp$ = MID$(temp$, 5) LOOP @@ -7982,6 +7985,12 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) END IF END IF NEXT + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF @@ -8022,6 +8031,9 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) temp$ = parseRange$(v$) usedVariableList(varDlgList(y).index).indexes = temp$ temp$ = formatRange$(temp$) + IF usedVariableList(varDlgList(y).index).watchRange <> temp$ THEN + usedVariableList(x).mostRecentValue = "" + END IF usedVariableList(varDlgList(y).index).watchRange = temp$ ELSE usedVariableList(varDlgList(y).index).indexes = "" @@ -8232,12 +8244,24 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) END IF l$ = l$ + text$ + l3$ - IF totalVisibleVariables = 1 THEN doubleClickThreshold = LEN(l$) - 1 + IF totalVisibleVariables = 1 THEN doubleClickThreshold = LEN(l$) - 3 IF IdeDebugMode > 0 THEN IF usedVariableList(x).subfunc = currentScope$ OR usedVariableList(x).subfunc = "" THEN IF usedVariableList(x).watch THEN - l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + StrReplace$(usedVariableList(x).mostRecentValue, CHR$(0), " ") + IF usedVariableList(x).isarray THEN + temp$ = usedVariableList(x).mostRecentValue + IF LEN(temp$) THEN l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + "{" + DO WHILE LEN(temp$) + storageSlot& = CVL(LEFT$(temp$, 4)) + temp$ = MID$(temp$, 5) + l$ = l$ + StrReplace$(vWatchArrayReceivedData$(storageSlot&), CHR$(0), " ") + IF LEN(temp$) THEN l$ = l$ + "," + LOOP + IF LEN(usedVariableList(x).mostRecentValue) THEN l$ = l$ + "}" + ELSE + l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + StrReplace$(usedVariableList(x).mostRecentValue, CHR$(0), " ") + END IF END IF ELSE l$ = l$ + " " @@ -8760,10 +8784,12 @@ FUNCTION idecallstackbox idecentercurrentline ideselect = 0 - DO - GetInput - _LIMIT 100 - LOOP UNTIL mRELEASE + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF END IF @@ -10366,12 +10392,24 @@ FUNCTION ideinputbox$(title$, caption$, initialvalue$, validinput$, boxwidth, ma END IF IF K$ = CHR$(27) OR (focus = 3 AND info <> 0) THEN + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF IF K$ = CHR$(13) OR (focus = 2 AND info <> 0) THEN ideinputbox$ = idetxt(o(1).txt) ok = -1 + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF 'end of custom controls @@ -12040,6 +12078,12 @@ FUNCTION idesubs$ IF K$ = CHR$(27) OR (focus = 5 AND info <> 0) THEN idesubs$ = "C" GOSUB SaveSortSettings + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF @@ -12057,6 +12101,12 @@ FUNCTION idesubs$ idesx = 1 GOSUB SaveSortSettings + IF mousedown THEN + DO + GetInput + _LIMIT 100 + LOOP UNTIL mRELEASE + END IF EXIT FUNCTION END IF diff --git a/source/qb64.bas b/source/qb64.bas index aab0ae441..84d408512 100644 --- a/source/qb64.bas +++ b/source/qb64.bas @@ -112,7 +112,7 @@ TYPE usedVarList AS LONG id, linenumber, includeLevel, includedLine, scope, localIndex AS _BYTE used, watch, isarray AS STRING name, cname, varType, includedFile, subfunc, mostRecentValue - AS STRING watchRange, indexes, elements, storage 'for Arrays and UDTs + AS STRING watchRange, indexes, elements 'for Arrays and UDTs AS _OFFSET baseAddress END TYPE @@ -25955,7 +25955,6 @@ SUB manageVariableList (__name$, __cname$, localIndex AS LONG, action AS _BYTE) usedVariableList(i).used = 0 usedVariableList(i).watch = 0 usedVariableList(i).mostRecentValue = "" - usedVariableList(i).storage = "" usedVariableList(i).linenumber = linenumber usedVariableList(i).includeLevel = inclevel IF inclevel > 0 THEN From 087c32063129a42da0c006ebd01a4be65e8bef73 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 19 Aug 2021 01:20:52 -0300 Subject: [PATCH 5/7] Encloses string data within quotation marks (Watch List dialog). --- source/ide/ide_methods.bas | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index d33739b1d..f96524456 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -8249,18 +8249,24 @@ FUNCTION idevariablewatchbox$(currentScope$, filter$, selectVar, returnAction) IF IdeDebugMode > 0 THEN IF usedVariableList(x).subfunc = currentScope$ OR usedVariableList(x).subfunc = "" THEN IF usedVariableList(x).watch THEN + isString = (INSTR(usedVariableList(x).varType, "STRING *") > 0 OR usedVariableList(x).varType = "STRING") IF usedVariableList(x).isarray THEN temp$ = usedVariableList(x).mostRecentValue IF LEN(temp$) THEN l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + "{" DO WHILE LEN(temp$) storageSlot& = CVL(LEFT$(temp$, 4)) temp$ = MID$(temp$, 5) + IF isString THEN l$ = l$ + CHR$(34) l$ = l$ + StrReplace$(vWatchArrayReceivedData$(storageSlot&), CHR$(0), " ") + IF isString THEN l$ = l$ + CHR$(34) IF LEN(temp$) THEN l$ = l$ + "," LOOP IF LEN(usedVariableList(x).mostRecentValue) THEN l$ = l$ + "}" ELSE - l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + StrReplace$(usedVariableList(x).mostRecentValue, CHR$(0), " ") + l$ = l$ + " = " + CHR$(16) + CHR$(variableNameColor) + IF isString THEN l$ = l$ + CHR$(34) + l$ = l$ + StrReplace$(usedVariableList(x).mostRecentValue, CHR$(0), " ") + IF isString THEN l$ = l$ + CHR$(34) END IF END IF ELSE From d29a6657ccd46fe688b590d4892edbd94887ebc7 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 19 Aug 2021 01:28:33 -0300 Subject: [PATCH 6/7] Encloses string data within quotation marks (Watch Panel). --- source/ide/ide_methods.bas | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/ide/ide_methods.bas b/source/ide/ide_methods.bas index f96524456..34ddbf172 100644 --- a/source/ide/ide_methods.bas +++ b/source/ide/ide_methods.bas @@ -7651,6 +7651,7 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl END IF item$ = thisName$ + SPACE$(longestVarName - LEN(thisName$)) + " = " IF usedVariableList(tempIndex&).subfunc = currentScope$ OR usedVariableList(tempIndex&).subfunc = "" THEN + isString = (INSTR(usedVariableList(tempIndex&).varType, "STRING *") > 0 OR usedVariableList(tempIndex&).varType = "STRING") IF usedVariableList(tempIndex&).isarray THEN seqIndex& = INSTR(usedVariableList(tempIndex&).indexes, MKL$(tempArrayIndex&)) IF seqIndex& <= LEN(usedVariableList(tempIndex&).mostRecentValue) - 3 THEN @@ -7661,7 +7662,11 @@ SUB showvWatchPanel (this AS vWatchPanelType, currentScope$, totalVisibleVariabl tempValue$ = usedVariableList(tempIndex&).mostRecentValue END IF - item$ = item$ + tempValue$ + IF isString THEN + item$ = item$ + CHR$(34) + tempValue$ + CHR$(34) + ELSE + item$ = item$ + tempValue$ + END IF COLOR fg ELSE item$ = item$ + "" From 9aa166e4debd8e639e39cb366320dce686fd8fa7 Mon Sep 17 00:00:00 2001 From: FellippeHeitor Date: Thu, 19 Aug 2021 19:10:51 -0300 Subject: [PATCH 7/7] Checks for array's lbound and ubound before fetching data. --- internal/c/qbx.cpp | 8 ++++++++ internal/support/vwatch/vwatch.bm | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/internal/c/qbx.cpp b/internal/c/qbx.cpp index 055b79d88..fba71478f 100755 --- a/internal/c/qbx.cpp +++ b/internal/c/qbx.cpp @@ -941,6 +941,14 @@ inline int16 func_abs(int16 d){return abs(d);} inline int32 func_abs(int32 d){return abs(d);} inline int64 func_abs(int64 d){return llabs(d);} +ptrszint check_lbound(ptrszint *array) { + return func_lbound((ptrszint*)(*array),1,1); +} + +ptrszint check_ubound(ptrszint *array) { + return func_ubound((ptrszint*)(*array),1,1); +} + inline ptrszint array_check(uptrszint index,uptrszint limit){ //nb. forces signed index into an unsigned variable for quicker comparison if (index vw_ubound THEN + GOTO cmdProcessingDone + END IF + + 'get the address of where this array's data is stored vw_buf$ = SPACE$(LEN(vw_dummy%&)) vw_m = _MEM(vw_address, LEN(vw_dummy%&)) vw_m2 = _MEM(_OFFSET(vw_buf$), LEN(vw_dummy%&)) @@ -301,7 +310,7 @@ SUB vwatch (globalVariables AS _OFFSET, localVariables AS _OFFSET) END IF 'this is where we calculate the actual element position in memory - vw_address = vw_address + ((vw_arrayIndex - 1) * vw_varSize) + vw_address = vw_address + ((vw_arrayIndex - vw_lbound) * vw_varSize) END IF 'vw_address now points to the actual data