Skip to content

Commit

Permalink
Merge v2.110
Browse files Browse the repository at this point in the history
  • Loading branch information
HotKeyIt committed Jun 6, 2020
1 parent 76240f7 commit 2f077b2
Show file tree
Hide file tree
Showing 36 changed files with 1,107 additions and 1,471 deletions.
20 changes: 4 additions & 16 deletions source/AutoHotkey.cpp
Expand Up @@ -327,12 +327,6 @@ int WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd
// never returns, perhaps because it contains an infinite loop (intentional or not):
CopyMemory(&g_default, g, sizeof(global_struct));

// Use FindOrAdd vs Add for maintainability, although it shouldn't already exist:
if ( !(g_ErrorLevel = g_script->FindOrAddVar(_T("ErrorLevel"))) )
return CRITICAL_ERROR; // Error. Above already displayed it for us.
// Initialize the var state to zero:
g_ErrorLevel->Assign(ERRORLEVEL_NONE);

// Could use CreateMutex() but that seems pointless because we have to discover the
// hWnd of the existing process so that we can close or restart it, so we would have
// to do this check anyway, which serves both purposes. Alt method is this:
Expand Down Expand Up @@ -518,16 +512,19 @@ unsigned __stdcall ThreadMain(LPTSTR lpScriptCmdLine)
GuiControlType::sPrototype = Object::CreatePrototype(_T("Gui.Control"), Object::sPrototype, GuiControlType::sMembers, _countof(GuiControlType::sMembers));
GuiControlType::sPrototypeList = Object::CreatePrototype(_T("Gui.List"), GuiControlType::sPrototype, GuiControlType::sMembersList, _countof(GuiControlType::sMembersList));
InputObject::sPrototype = Object::CreatePrototype(_T("InputHook"), Object::sPrototype, InputObject::sMembers, _countof(InputObject::sMembers));

Object::sClass = Object::CreateClass(_T("Object"), Object::sClassPrototype, Object::sPrototype, static_cast<ObjectMethod>(&Object::New<Object>));
Object::sClassClass = Object::CreateClass(_T("Class"), Object::sClass, Object::sClassPrototype, static_cast<ObjectMethod>(&Object::New<Object>));
Array::sClass = Object::CreateClass(_T("Array"), Object::sClass, Array::sPrototype, static_cast<ObjectMethod>(&Array::New<Array>));
Map::sClass = Object::CreateClass(_T("Map"), Object::sClass, Map::sPrototype, static_cast<ObjectMethod>(&Map::New<Map>));



Closure::sPrototype = Object::CreatePrototype(_T("Closure"), Func::sPrototype);
BoundFunc::sPrototype = Object::CreatePrototype(_T("BoundFunc"), Func::sPrototype);
EnumBase::sPrototype = Object::CreatePrototype(_T("Enumerator"), Func::sPrototype);


BufferObject::sPrototype = Object::CreatePrototype(_T("Buffer"), Object::sPrototype, BufferObject::sMembers, _countof(BufferObject::sMembers));
ClipboardAll::sPrototype = Object::CreatePrototype(_T("ClipboardAll"), BufferObject::sPrototype);

Expand Down Expand Up @@ -651,15 +648,6 @@ unsigned __stdcall ThreadMain(LPTSTR lpScriptCmdLine)
// never returns, perhaps because it contains an infinite loop (intentional or not):
CopyMemory(&g_default, g, sizeof(global_struct));

// Use FindOrAdd vs Add for maintainability, although it shouldn't already exist:
if (!(g_ErrorLevel = g_script->FindOrAddVar(_T("ErrorLevel"))))
{
_endthreadex(CRITICAL_ERROR);
return CRITICAL_ERROR; // Error. Above already displayed it for us.
}
// Initialize the var state to zero:
g_ErrorLevel->Assign(ERRORLEVEL_NONE);

//if (nameHinstanceP.istext)
// GetCurrentDirectory(MAX_PATH, g_script->mFileDir);
// Could use CreateMutex() but that seems pointless because we have to discover the
Expand Down
5 changes: 1 addition & 4 deletions source/Debugger.h
Expand Up @@ -204,10 +204,7 @@ class Debugger
inline bool HasStdErrHook() { return mStdErrMode != SR_Disabled; }
inline bool HasStdOutHook() { return mStdOutMode != SR_Disabled; }

TCHAR *WhatThrew()
{
return mStack.mTop >= mStack.mBottom ? mStack.mTop->Name() : _T("");
}
LPCTSTR WhatThrew();

__declspec(noinline) // Avoiding inlining should reduce the code size of ExpandExpression(), which might help performance since this is only called when the debugger is connected.
void PostExecFunctionCall(Line *aExpressionLine)
Expand Down
2 changes: 1 addition & 1 deletion source/TextIO.cpp
Expand Up @@ -1169,7 +1169,7 @@ BIF_DECL(BIF_FileOpen)
if (aResultToken.object)
aResultToken.symbol = SYM_OBJECT;
else
aResultToken.SetExitResult(g_script->ThrowWin32Exception(GetLastError()));
aResultToken.Win32Error();
return;

invalid_param:
Expand Down
23 changes: 15 additions & 8 deletions source/WinGroup.cpp
Expand Up @@ -28,7 +28,6 @@ _thread_local int WinGroup::sAlreadyVisitedCount = 0;

ResultType WinGroup::AddWindow(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText)
// Caller should ensure that at least one param isn't NULL/blank.
// GroupActivate will tell its caller to jump to aJumpToLabel if a WindowSpec isn't found.
// This function is not thread-safe because it adds an entry to the list of window specs.
// In addition, if this function is being called by one thread while another thread is calling IsMember(),
// the thread-safety notes in IsMember() apply.
Expand Down Expand Up @@ -138,16 +137,23 @@ ResultType WinGroup::CloseAndGoToNext(bool aStartWithMostRecent)
}
}
//else do the activation below anyway, even though no close was done.
return mIsModeActivate ? Activate(aStartWithMostRecent, win_spec) : Deactivate(aStartWithMostRecent);
if (mIsModeActivate)
{
HWND active_window;
if (!Activate(aStartWithMostRecent, active_window, win_spec))
return FAIL;
return active_window ? OK : FAIL;
}
return Deactivate(aStartWithMostRecent);
}



ResultType WinGroup::Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec)
ResultType WinGroup::Activate(bool aStartWithMostRecent, HWND &aHwnd, WindowSpec *aWinSpec)
{
aHwnd = NULL; // Set default.
if (IsEmpty())
return OK; // OK since this is the expected behavior in this case.
// Otherwise:
return OK;
if (!Update(true)) // Update our private member vars.
return FAIL; // It already displayed the error for us.
WindowSpec *win, *win_to_activate_next = aWinSpec;
Expand All @@ -164,6 +170,7 @@ ResultType WinGroup::Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec)
{
group_is_active = true;
MarkAsVisited(active_window);
aHwnd = active_window;
return OK;
}
// else don't mark as visited even if it's a member of the group because
Expand Down Expand Up @@ -221,14 +228,14 @@ ResultType WinGroup::Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec)
// group isn't currently active (i.e. we're starting fresh), because otherwise
// windows would be activated in an order different from what was already shown
// the first time through the enumeration, which doesn't seem to be ever desirable:
, !aStartWithMostRecent || group_is_active
, !aStartWithMostRecent || group_is_active, true
, sAlreadyVisited, sAlreadyVisitedCount) )
{
// We found a window to activate, so we're done.
// Probably best to do this before WinDelay in case another hotkey fires during the delay:
MarkAsVisited(activate_win);
aHwnd = activate_win;
DoWinDelay;
//MsgBox(win->mText, 0, win->mTitle);
break;
}
// Otherwise, no window was found to activate.
Expand Down Expand Up @@ -269,7 +276,7 @@ ResultType WinGroup::Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec)
// than getting stuck on this one.
}
else
return FAIL; // Let GroupActivate set ErrorLevel to indicate what happened.
break;
}
}
return OK;
Expand Down
2 changes: 1 addition & 1 deletion source/WinGroup.h
Expand Up @@ -84,7 +84,7 @@ class WinGroup
ResultType AddWindow(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
void ActUponAll(BuiltInFunctionID aActionType, int aTimeToWaitForClose);
ResultType CloseAndGoToNext(bool aStartWithMostRecent);
ResultType Activate(bool aStartWithMostRecent, WindowSpec *aWinSpec = NULL);
ResultType Activate(bool aStartWithMostRecent, HWND &aHwnd, WindowSpec *aWinSpec = nullptr);
ResultType Deactivate(bool aStartWithMostRecent);
bool IsEmpty() {return mFirstWindow == NULL;}
WindowSpec *IsMember(HWND aWnd, global_struct &aSettings);
Expand Down
32 changes: 4 additions & 28 deletions source/application.cpp
Expand Up @@ -127,13 +127,6 @@ bool MsgSleep(int aSleepDuration, MessageMode aMode)
// definitely routes to the hook, perhaps only if called regularly (i.e. a single
// isolated call might not help much).

// This var allows us to suspend the currently-running subroutine and run any
// hotkey events waiting in the message queue (if there are more than one, they
// will be executed in sequence prior to resuming the suspended subroutine).
// Never static because we could be recursed (e.g. when one hotkey interrupts
// a hotkey that has already been interrupted) and each recursion layer should
// have it's own value for this:
VarBkp ErrorLevel_saved;
// Decided to support a true Sleep(0) for aSleepDuration == 0, as well
// as no delay at all if aSleepDuration < 0. This is needed to implement
// "SetKeyDelay, 0" and possibly other things. I believe a Sleep(0)
Expand Down Expand Up @@ -1052,13 +1045,8 @@ bool MsgSleep(int aSleepDuration, MessageMode aMode)
g_script->mThisHotkeyStartTime = GetTickCount(); // Fixed for v1.0.35.10 to not happen for GUI threads.
}

// Also save the ErrorLevel of the subroutine that's about to be suspended.
ErrorLevel_Backup(ErrorLevel_saved);
// Make every newly launched subroutine start off with the global default values that
// the user set up in the auto-execute part of the script (e.g. KeyDelay, WinDelay, etc.).
// However, we do not set ErrorLevel to anything special here (except for GUI threads, later
// below) because it's more flexible that way (i.e. the user may want one hotkey subroutine
// to use the value of ErrorLevel set by another):
InitNewThread(priority, false, true);
global_struct &g = *::g; // ONLY AFTER above is it safe to "lock in". Reduces code size a bit (31 bytes currently) and may improve performance. Eclipsing ::g with local g makes compiler remind/enforce the use of the right one.

Expand Down Expand Up @@ -1383,7 +1371,7 @@ bool MsgSleep(int aSleepDuration, MessageMode aMode)

// v1.0.37.06: Call ResumeUnderlyingThread() even if aMode==WAIT_FOR_MESSAGES; this is for
// maintainability and also in case the pause command has been used to unpause the idle thread.
ResumeUnderlyingThread(ErrorLevel_saved);
ResumeUnderlyingThread();
// DUE TO THE --g DONE BY THE LINE ABOVE, ANYTHING BETWEEN THIS POINT AND THE NEXT '}' MUST USE :;g INSTEAD OF g.

if (aMode == WAIT_FOR_MESSAGES) // This is the idle state, so we were called directly from WinMain().
Expand Down Expand Up @@ -1633,7 +1621,6 @@ bool CheckScriptTimers()
ScriptTimer *ptimer, *next_timer;
BOOL at_least_one_timer_launched;
DWORD tick_start;
VarBkp ErrorLevel_saved;

// Note: It seems inconsequential if a subroutine that the below loop executes causes a
// new timer to be added to the linked list while the loop is still enumerating the timers.
Expand Down Expand Up @@ -1677,7 +1664,6 @@ bool CheckScriptTimers()
// seems best since some timed subroutines might take a long time to run:
++g_nThreads; // These are the counterparts the decrements that will be done further
++g; // below by ResumeUnderlyingThread().
ErrorLevel_Backup(ErrorLevel_saved); // Back up the current ErrorLevel for later restoration.
// But never kill the main timer, since the mere fact that we're here means that
// there's at least one enabled timed subroutine. Though later, performance can
// be optimized by killing it if there's exactly one enabled subroutine, or if
Expand Down Expand Up @@ -1710,9 +1696,6 @@ bool CheckScriptTimers()
// timed subroutine that changed any of the global struct's values. In other words, make
// every newly launched subroutine start off with the global default values that
// the user set up in the auto-execute part of the script (e.g. KeyDelay, WinDelay, etc.).
// However, we do not set ErrorLevel to NONE here for performance and also because it's more
// flexible that way (i.e. the user may want one hotkey subroutine to use the value of
// ErrorLevel set by another).
// Pass false as 3rd param below because ++g_nThreads should be done only once rather than
// for each Init(), and also it's not necessary to call update the tray icon since timers
// won't run if there is any paused thread, thus the icon can't currently be showing "paused".
Expand All @@ -1737,7 +1720,7 @@ bool CheckScriptTimers()

if (at_least_one_timer_launched) // Since at least one subroutine was run above, restore various values for our caller.
{
ResumeUnderlyingThread(ErrorLevel_saved);
ResumeUnderlyingThread();
return true;
}
return false;
Expand Down Expand Up @@ -1863,8 +1846,6 @@ bool MsgMonitor(MsgMonitorInstance &aInstance, HWND aWnd, UINT aMsg, WPARAM awPa
// Since above didn't return, the launch of the new thread is now considered unavoidable.

// See MsgSleep() for comments about the following section.
VarBkp ErrorLevel_saved;
ErrorLevel_Backup(ErrorLevel_saved);
InitNewThread(0, false, true);
DEBUGGER_STACK_PUSH(_T("OnMessage")) // Push a "thread" onto the debugger's stack. For simplicity and performance, use the function name vs something like "message 0x123".

Expand Down Expand Up @@ -1905,7 +1886,7 @@ bool MsgMonitor(MsgMonitorInstance &aInstance, HWND aWnd, UINT aMsg, WPARAM awPa

DEBUGGER_STACK_POP()

ResumeUnderlyingThread(ErrorLevel_saved);
ResumeUnderlyingThread();

// Check that the msg monitor still exists (it may have been deleted during the thread that just finished,
// either by the thread itself or some other thread that interrupted it). The following cases are possible:
Expand Down Expand Up @@ -1972,9 +1953,6 @@ void InitNewThread(int aPriority, bool aSkipUninterruptible, bool aIncrementThre
// in the right state (which it usually, since paused threads are rare), UpdateTrayIcon() is a very fast call.
if (aIncrementThreadCountAndUpdateTrayIcon)
g_script->UpdateTrayIcon(); // Must be done ONLY AFTER updating "g" (e.g, ++g) and/or g->IsPaused.
// For performance reasons, ErrorLevel isn't reset. See similar line in WinMain() for other reasons.
//g_ErrorLevel->Assign(ERRORLEVEL_NONE);

if (g_nFileDialogs)
// Since there is a quasi-thread with an open file dialog underneath the one
// we're about to launch, set the current directory to be the one the user
Expand Down Expand Up @@ -2027,7 +2005,7 @@ void InitNewThread(int aPriority, bool aSkipUninterruptible, bool aIncrementThre



void ResumeUnderlyingThread(VarBkp &aSavedErrorLevel)
void ResumeUnderlyingThread()
{
if (g->ThrownToken)
g_script->FreeExceptionToken(g->ThrownToken);
Expand All @@ -2036,8 +2014,6 @@ void ResumeUnderlyingThread(VarBkp &aSavedErrorLevel)
// The following section handles the switch-over to the former/underlying "g" item:
--g_nThreads; // Other sections below might rely on this having been done early.
--g;
g_ErrorLevel->Free();
g_ErrorLevel->Restore(aSavedErrorLevel);
// The below relies on the above having restored "g" to be the global_struct of the underlying thread.

// If the thread to be resumed was paused and has not been unpaused above, it will automatically be
Expand Down
3 changes: 1 addition & 2 deletions source/application.h
Expand Up @@ -88,8 +88,7 @@ bool MsgMonitor(HWND aWnd, UINT aMsg, WPARAM awParam, LPARAM alParam, MSG *apMsg

void InitNewThread(int aPriority, bool aSkipUninterruptible, bool aIncrementThreadCountAndUpdateTrayIcon
, bool aIsCritical = false);
struct VarBkp;
void ResumeUnderlyingThread(VarBkp &aSavedErrorLevel);
void ResumeUnderlyingThread();
BOOL IsInterruptible();

VOID CALLBACK MsgBoxTimeout(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
Expand Down
4 changes: 2 additions & 2 deletions source/clipboard.cpp
Expand Up @@ -222,13 +222,13 @@ LPTSTR Clipboard::PrepareForWrite(size_t aAllocSize)
// with 16-bit Windows. They are ignored.": GMEM_DDESHARE
if ( !(mClipMemNew = GlobalAlloc(GMEM_MOVEABLE, aAllocSize * sizeof(TCHAR))) )
{
g_script->ScriptError(_T("GlobalAlloc")); // Short error message since so rare.
g_script->ScriptError(ERR_INTERNAL_CALL); // Generic error message since so rare.
return NULL;
}
if ( !(mClipMemNewLocked = (LPTSTR)GlobalLock(mClipMemNew)) )
{
mClipMemNew = GlobalFree(mClipMemNew); // This keeps mClipMemNew in sync with its state.
g_script->ScriptError(_T("GlobalLock")); // Short error message since so rare.
g_script->ScriptError(ERR_INTERNAL_CALL); // Generic error message since so rare.
return NULL;
}
mCapacity = (UINT)aAllocSize; // Keep mCapacity in sync with the state of mClipMemNewLocked.
Expand Down
15 changes: 10 additions & 5 deletions source/defines.h
Expand Up @@ -116,10 +116,12 @@ GNU General Public License for more details.
enum ResultType {FAIL = 0, OK, WARN = OK, CRITICAL_ERROR // Some things might rely on OK==1 (i.e. boolean "true")
, CONDITION_TRUE, CONDITION_FALSE
, LOOP_BREAK, LOOP_CONTINUE
, EARLY_RETURN, EARLY_EXIT}; // EARLY_EXIT needs to be distinct from FAIL for ExitApp() and AutoExecSection().
, EARLY_RETURN, EARLY_EXIT // EARLY_EXIT needs to be distinct from FAIL for ExitApp() and AutoExecSection().
, FAIL_OR_OK // For LineError/RuntimeError, error is continuable.
};

enum ExcptModeType {EXCPTMODE_NONE = 0
//, EXCPTMODE_TRY = 1 // Currently unused: Try block present. Affects SetErrorLevelOrThrow().
//, EXCPTMODE_TRY = 1 // Currently unused: Try block present.
, EXCPTMODE_CATCH = 2 // Exception will be suppressed or caught.
, EXCPTMODE_DELETE = 4 // Unhandled exceptions will display ERR_ABORT_DELETE vs. ERR_ABORT.
, EXCPTMODE_LINE_WORKAROUND = 8}; // See comments in BIF_PerformAction.
Expand Down Expand Up @@ -508,6 +510,10 @@ struct ResultToken : public ExprTokenType
ResultType Error(LPCTSTR aErrorText);
ResultType Error(LPCTSTR aErrorText, LPCTSTR aExtraInfo);
ResultType UnknownMemberError(ExprTokenType &aObject, int aFlags, LPCTSTR aMember);
ResultType Win32Error(DWORD aError = GetLastError());

void SetLastErrorMaybeThrow(bool aError, DWORD aLastError = GetLastError());
void SetLastErrorCloseAndMaybeThrow(HANDLE aHandle, bool aError, DWORD aLastError = GetLastError());

BuiltInFunc *func; // For maintainability, this is separate from the ExprTokenType union. Its main uses are func->mID and func->mOutputVars.

Expand Down Expand Up @@ -556,7 +562,7 @@ enum enum_act {
, ACT_CRITICAL, ACT_THREAD
, ACT_WINMINIMIZEALL, ACT_WINMINIMIZEALLUNDO
// Keep rarely used actions near the bottom for parsing/performance reasons:
, ACT_GROUPADD, ACT_GROUPACTIVATE, ACT_GROUPDEACTIVATE, ACT_GROUPCLOSE
, ACT_GROUPADD, ACT_GROUPDEACTIVATE, ACT_GROUPCLOSE
, ACT_SOUNDBEEP, ACT_SOUNDPLAY
, ACT_FILEDELETE, ACT_FILERECYCLE, ACT_FILERECYCLEEMPTY
, ACT_FILEINSTALL, ACT_FILECOPY, ACT_FILEMOVE, ACT_DIRCOPY, ACT_DIRMOVE
Expand Down Expand Up @@ -602,7 +608,6 @@ enum enum_act {
#define AHK_TIMEOUT -2
// And these to prevent mutual dependency problem between window.h and globaldata.h:
#define MAX_MSGBOXES 7 // Probably best not to change this because it's used by OurTimers to set the timer IDs, which should probably be kept the same for backward compatibility.
#define MAX_INPUTBOXES 4
#define MAX_MSG_MONITORS 500

// IMPORTANT: Before ever changing the below, note that it will impact the IDs of menu items created
Expand Down Expand Up @@ -915,7 +920,7 @@ inline void global_maximize_interruptibility(global_struct &g)
inline void global_clear_state(global_struct &g)
// Reset those values that represent the condition or state created by previously executed commands
// but that shouldn't be retained for future threads (e.g. SetTitleMatchMode should be retained for
// future threads if it occurs in the auto-execute section, but ErrorLevel shouldn't).
// future threads if it occurs in the auto-execute section, but A_ThisFunc shouldn't).
{
g.CurrentFunc = NULL;
g.CurrentFuncGosub = NULL;
Expand Down
9 changes: 0 additions & 9 deletions source/dllmain.cpp
Expand Up @@ -372,15 +372,6 @@ int WINAPI OldWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
// never returns, perhaps because it contains an infinite loop (intentional or not):
CopyMemory(&g_default, g, sizeof(global_struct));

// Use FindOrAdd vs Add for maintainability, although it shouldn't already exist:
if ( !(g_ErrorLevel = g_script->FindOrAddVar(_T("ErrorLevel"))) )
{
g_Reloading = false;
return CRITICAL_ERROR; // Error. Above already displayed it for us.
}
// Initialize the var state to zero:
g_ErrorLevel->Assign(ERRORLEVEL_NONE);

//if (nameHinstanceP.istext)
// GetCurrentDirectory(MAX_PATH, g_script->mFileDir);
// Could use CreateMutex() but that seems pointless because we have to discover the
Expand Down

0 comments on commit 2f077b2

Please sign in to comment.