Skip to content

Commit

Permalink
Merge v2.0.19
Browse files Browse the repository at this point in the history
  • Loading branch information
thqby committed Feb 6, 2025
2 parents 08cd24b + 8243f09 commit 6be86e6
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 31 deletions.
23 changes: 17 additions & 6 deletions source/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,26 @@ Line *Debugger::FindFirstLineForBreakpoint(int file_index, UINT line_no)
// Set Line::mBreakpoint for all executable lines that share the line's number,
// such as an expression and any fat arrow function's it contains, or all param
// default initializers in e.g. `Fn(a:=[], b:={}) {`.
void SetBreakpointForLineGroup(Line *line, Breakpoint *bp)
void Debugger::SetBreakpointForLineGroup(Line *line, Breakpoint *bp)
{
auto line_no = line->mLineNumber;
auto file_no = line->mFileIndex;
do {
if (line->mActionType != ACT_BLOCK_BEGIN) // Skip the block-begin implied by any fat-arrow.
line->mBreakpoint = bp;
line = line->mNextLine;
} while (line && line->mLineNumber == line_no && line->mFileIndex == file_no);
line->mBreakpoint = bp;
for (int i = 0; i < g_script->mFuncs.mCount; ++i)
{
ASSERT(dynamic_cast<UserFunc*>(g_script->mFuncs.mItem[i]));
auto &func = *(UserFunc *)g_script->mFuncs.mItem[i];
auto fl = func.mJumpToLine;
// Fat arrow functions are either removed from the main line list or come after the
// line which contains them, in which case our caller would have found the latter.
if (fl->mLineNumber == line_no && fl->mFileIndex == file_no && func.mIsFuncExpression)
fl->mBreakpoint = bp;
// After the script loads, a function's parameter default initializers precede mJumpToLine.
for (fl = fl->mPrevLine
; fl->mLineNumber == line_no && fl->mFileIndex == file_no && fl->mActionType == ACT_EXPRESSION
; fl = fl->mPrevLine)
fl->mBreakpoint = bp;
}
}


Expand Down
3 changes: 1 addition & 2 deletions source/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class Debugger
int WriteBreakpointXml(Breakpoint *aBreakpoint, Line *aLine);
int WriteExceptionBreakpointXml();
Line *FindFirstLineForBreakpoint(int file_index, UINT line_no);
void SetBreakpointForLineGroup(Line *line, Breakpoint *bp);

void AppendPropertyName(CStringA &aNameBuf, size_t aParentNameLength, const char *aName);
void AppendStringKey(CStringA &aNameBuf, size_t aParentNameLength, const char *aKey);
Expand Down Expand Up @@ -474,8 +475,6 @@ class Debugger
constexpr auto SCRIPT_STACK_BUF_SIZE = 2048; // Character limit for Error().Stack and stack traces generated by the error dialog.

void GetScriptStack(LPTSTR aBuf, int aBufSize, DbgStack::Entry *aTop = nullptr);
bool LineIsFatArrowBlock(Line *line);
void SetBreakpointForLineGroup(Line *line, Breakpoint *bp);


#endif
Expand Down
16 changes: 9 additions & 7 deletions source/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,15 +643,13 @@ LRESULT LowLevelCommon(const HHOOK aHook, int aCode, WPARAM wParam, LPARAM lPara
HotkeyIDType hotkey_id_temp; // For informal/temp storage of the ID-without-flags.

bool fire_with_no_suppress = false; // Set default.
bool down_performed_action, was_down_before_up;
bool was_down_before_up = false;
bool down_performed_action = this_key.down_performed_action; // Save prior to reset.
// Reset this in preparation for the next call to this procedure that involves this key:
this_key.down_performed_action = false; // Reset this for both key-up and key-repeat.
if (aKeyUp)
{
// Save prior to reset. These var's should only be used further below in conjunction with aKeyUp
// being TRUE. Otherwise, their values will be unreliable (refer to some other key, probably).
was_down_before_up = this_key.is_down;
down_performed_action = this_key.down_performed_action; // Save prior to reset below.
// Reset these values in preparation for the next call to this procedure that involves this key:
this_key.down_performed_action = false;
was_down_before_up = this_key.is_down; // Save prior to reset.
if (this_key.hotkey_to_fire_upon_release != HOTKEY_ID_INVALID)
{
hotkey_id_with_flags = this_key.hotkey_to_fire_upon_release;
Expand Down Expand Up @@ -891,6 +889,9 @@ LRESULT LowLevelCommon(const HHOOK aHook, int aCode, WPARAM wParam, LPARAM lPara
// script such as the following would send two M's for +b, one upon down and one upon up:
// +b::Send, M
// b & z::return
// Although the final suppress/allow determination could be based on hotkey_down_was_suppressed,
// the entry condition must be based on down_performed_action, otherwise the issue described above
// would occur for non-suppressed versions of those hotkeys.
// I don't remember exactly what the "pPrefixKey != &this_key" check is for below, but it is kept
// to minimize the chance of breaking other things:
bool fell_through_from_case2 = false; // Set default.
Expand Down Expand Up @@ -4436,6 +4437,7 @@ void ResetKeyTypeState(key_type &key)
key.it_put_alt_down = false;
key.it_put_shift_down = false;
key.down_performed_action = false;
key.hotkey_down_was_suppressed = false;
key.was_just_used = 0;
key.hotkey_to_fire_upon_release = HOTKEY_ID_INVALID;
// ABOVE line was added in v1.0.48.03 to fix various ways in which the hook didn't receive the key-down
Expand Down
9 changes: 7 additions & 2 deletions source/keyboard_mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,8 @@ void SendKeys(LPCTSTR aKeys, SendRawModes aSendRaw, SendModes aSendModeOrig, HWN
// Put any modifiers in sModifiersLR_remapped back into effect, as if they were physically down.
mods_down_physically |= sModifiersLR_remapped;

modLR_type mods_current = GetModifierLRState();

// Restore the state of the modifiers to be those the user is physically holding down right now.
// Any modifiers that are logically "persistent", as detected upon entrance to this function
// (e.g. due to something such as a prior "Send, {LWinDown}"), are also pushed down if they're not already.
Expand All @@ -897,7 +899,10 @@ void SendKeys(LPCTSTR aKeys, SendRawModes aSendRaw, SendModes aSendModeOrig, HWN
// user resumes typing.
// v1.0.42.04: Now that SendKey() is lazy about releasing Ctrl and/or Shift (but not Win/Alt),
// the section below also releases Ctrl/Shift if appropriate. See SendKey() for more details.
mods_to_set = persistent_modifiers_for_this_SendKeys; // Set default.
// Fix for v2.0.19: Filter the default value to just the modifiers which are currently in effect.
// If any "persistent" modifiers aren't down now, they were likely released by something external
// during the Send, and to avoid stuck modifiers, they should not be pushed back down.
mods_to_set = persistent_modifiers_for_this_SendKeys & mods_current; // Set default.
if (sInBlindMode) // This section is not needed for the array-sending modes because they exploit uninterruptibility to perform a more reliable restoration.
{
// For selective {Blind!#^+}, restore any modifiers that were automatically released at the
Expand Down Expand Up @@ -959,7 +964,7 @@ void SendKeys(LPCTSTR aKeys, SendRawModes aSendRaw, SendModes aSendModeOrig, HWN
// which in turn causes the Shift key to stick down. If non-zero, the Shift key is currently "up"
// but should be "released" anyway, since the system will inject Shift-down either before the next
// keyboard event or after the Numpad key is released. Find "fake shift" for more details.
SetModifierLRState(mods_to_set, GetModifierLRState() | g_modifiersLR_numpad_mask, aTargetWindow, true, true); // It also does DoKeyDelay(g->PressDuration).
SetModifierLRState(mods_to_set, mods_current | g_modifiersLR_numpad_mask, aTargetWindow, true, true); // It also does DoKeyDelay(g->PressDuration).
} // End of non-array Send.

// For peace of mind and because that's how it was tested originally, the following is done
Expand Down
56 changes: 44 additions & 12 deletions source/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5846,9 +5846,11 @@ ResultType Script::AddLine(ActionTypeType aActionType, LPTSTR aArg[], int aArgc,
case ACT_FINALLY:
bool expected = false;
Line *parent = mPendingRelatedLine;
if (parent->mActionType == ACT_BLOCK_BEGIN) // For mPendingRelatedLine, this means an entire block preceding this line.
parent = parent->mParentLine;
for (;; parent = parent->mParentLine)
{
if (!parent)
if (!parent || parent->mActionType == ACT_BLOCK_BEGIN) // If parent is a block-begin, it would be enclosing this line.
return line.LineUnexpectedError();
enum_act parent_act = (enum_act)parent->mActionType;
switch (aActionType)
Expand Down Expand Up @@ -8430,13 +8432,32 @@ Line *Script::PreparseCommands(Line *aStartingLine)
// all skip an initial ACT_BLOCK_BEGIN (to avoid an extra ExecUntil call),
// which would result in executing the function's body instead of skipping it.
Line *body = line->mNextLine;
block_begin = parent->mNextLine; // In case there are multiple fat arrow functions on one line.
Line *after_body = parent->mRelatedLine;
Line *body_end = after_body->mPrevLine; // In case body is multiple lines (such as a nested IF or LOOP).
// Swap the statement body and fat arrow functions around to make it work:
parent ->mNextLine = body , body ->mPrevLine = parent;
body_end ->mNextLine = block_begin, block_begin->mPrevLine = body_end;
line ->mNextLine = after_body , after_body ->mPrevLine = line;
// Remove the fat arrow functions to allow the correct body to execute.
parent->mNextLine = body, body->mPrevLine = parent;
// If this wasn't unset, an error dialog would walk upward to find a previous line,
// then step forward and fail to find the original target line. Instead, it will
// display from the function's block-begin downward, usually including the expression
// which contains the function. Must not change line->mNextLine or line itself because
// they are still needed by the current and next iteration of this loop.
block_begin->mPrevLine = nullptr;
// An alternative approach used in v2.0.17 & .18 was to move the function's body,
// but identifying the right place to move it was deceptively complicated:
// if cond
// ; BAD: executed by IF
// f(A()=>)
// ; OK for A
// else
// ; BAD: executed by ELSE
// if f(B()=>)
// ; BAD: executed by IF
// body
// ; OK? Difficult to locate because mRelatedLine points us to the very end of the ladder.
// else ...
// This was intended to group the lines together so that the debugger can iterate
// over them efficiently, but as demonstrated above, they can't always be kept in a
// continuguous sequence. Instead, the debugger now iterates over the function list.
// If ever we do shuffle lines around again, be sure that the loop here is redesigned
// to finish preparsing this current "line" and continue iterating correctly.
}
else if (parent && parent->mActionType != ACT_BLOCK_BEGIN)
{
Expand Down Expand Up @@ -10590,7 +10611,10 @@ void Line::Free(bool aSkipFatArrowBlockBreakpoint, bool aOnlyBreakpoint)
line->mActionType == ACT_BLOCK_BEGIN && line->mAttribute && line->mNextLine &&
mLineNumber == line->mNextLine->mLineNumber && mFileIndex == line->mNextLine->mFileIndex)
return;
SetBreakpointForLineGroup(line, nullptr);
do {
line->mBreakpoint = nullptr;
line = line->mNextLine;
} while (line && line->mLineNumber == mLineNumber && line->mFileIndex == mFileIndex);
delete bp;
}
#endif
Expand Down Expand Up @@ -11204,9 +11228,17 @@ ResultType Line::ExecUntil(ExecUntilMode aMode, ResultToken *aResultToken, Line
}
if (!g.ThrownToken && line->mActionType == ACT_ELSE && result == OK && !jump_to_line)
{
// Since no exception was thrown, execute the ELSE (by jumping to its first statement).
line = line->mNextLine;
continue;
// Since no exception was thrown, execute the ELSE.
if (line->mNextLine->mActionType == ACT_BLOCK_BEGIN)
{
do
result = line->mNextLine->mNextLine->ExecUntil(UNTIL_BLOCK_END, aResultToken, &jump_to_line);
while (jump_to_line == line->mNextLine); // The above call encountered a Goto that jumps to the "{". See ACT_BLOCK_BEGIN in ExecUntil() for details.
}
else
result = line->mNextLine->ExecUntil(ONLY_ONE_LINE, aResultToken, &jump_to_line);
// Continue on in case there is a FINALLY after this ELSE.
UnhandledException_was_not_called = false; // It would have been called by ExecUntil() above if appropriate.
}
}
else // this_act == ACT_CATCH
Expand Down
8 changes: 7 additions & 1 deletion source/script2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lPar
case AHK_HOTSTRING: // Added for v1.0.36.02 so that hotstrings work even while an InputBox or other non-standard msg pump is running.
case AHK_CLIPBOARD_CHANGE: // Added for v1.0.44 so that clipboard notifications aren't lost while the script is displaying a MsgBox or other dialog.
case AHK_INPUT_END:
case AHK_INPUT_KEYDOWN:
case AHK_INPUT_CHAR:
case AHK_INPUT_KEYUP:
// If the following facts are ever confirmed, there would be no need to post the message in cases where
// the MsgSleep() won't be done:
// 1) The mere fact that any of the above messages has been received here in MainWindowProc means that a
Expand Down Expand Up @@ -1497,7 +1500,7 @@ bif_impl FResult MouseGetPos(int *aX, int *aY, ResultToken *aParent, ResultToken
TCHAR class_nn[WINDOW_CLASS_NN_SIZE];
auto fr = ControlGetClassNN(parent_under_cursor, child_under_cursor, class_nn, _countof(class_nn));
if (fr != OK)
return fr;
return OK; // Leave aChild blank and do not throw.
if (!TokenSetResult(*aChild, class_nn))
return aChild->Exited() ? FR_FAIL : FR_ABORTED;
return OK;
Expand Down Expand Up @@ -1782,6 +1785,9 @@ bif_impl FResult FileSelect(optl<StrArg> aOptions, optl<StrArg> aWorkingDir, opt
// from one another, which may help script automation in rare cases:
sntprintf(greeting, _countof(greeting), _T("Select %s - %s")
, (flags & FOS_PICKFOLDERS) ? _T("Folder") : _T("File"), g_script->DefaultDialogTitle());

if (!IsNumeric(options_str, false, true))
return FR_E_ARG(0);

int options = ATOI(options_str);
if (options & 0x20)
Expand Down
3 changes: 2 additions & 1 deletion source/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2823,7 +2823,7 @@ HBITMAP IconToBitmap32(HICON ahIcon, bool aDestroyIcon)
if (!has_nonzero_alpha)
{
// Get bitmap data from the icon's mask.
UINT *mask_bits = (UINT*)_alloca(height*width*4);
UINT *mask_bits = (UINT*)_malloca(height*width*4);
if (GetDIBits(hdc, icon_info.hbmMask, 0, height, (LPVOID)mask_bits, &bitmap_info, 0))
{
UINT *this_mask_pixel;
Expand All @@ -2842,6 +2842,7 @@ HBITMAP IconToBitmap32(HICON ahIcon, bool aDestroyIcon)
for (this_pixel = bits; this_pixel < bits_end; ++this_pixel)
*this_pixel |= 0xff000000;
}
_freea(mask_bits);
}

SelectObject(hdc, old_object);
Expand Down

0 comments on commit 6be86e6

Please sign in to comment.