"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/script.cpp" (8 May 2021, 831555 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "script.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 AutoHotkey
    3 
    4 Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
    5 
    6 This program is free software; you can redistribute it and/or
    7 modify it under the terms of the GNU General Public License
    8 as published by the Free Software Foundation; either version 2
    9 of the License, or (at your option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 */
   16 
   17 #include "stdafx.h" // pre-compiled headers
   18 #include "script.h"
   19 #include "globaldata.h" // for a lot of things
   20 #include "util.h" // for strlcpy() etc.
   21 #include "mt19937ar-cok.h" // for random number generator
   22 #include "window.h" // for a lot of things
   23 #include "application.h" // for MsgSleep()
   24 #include "TextIO.h"
   25 
   26 // Globals that are for only this module:
   27 #define MAX_COMMENT_FLAG_LENGTH 15
   28 static TCHAR g_CommentFlag[MAX_COMMENT_FLAG_LENGTH + 1] = _T(";"); // Adjust the below for any changes.
   29 static size_t g_CommentFlagLength = 1; // pre-calculated for performance
   30 static ExprOpFunc g_ObjGet(BIF_ObjInvoke, IT_GET), g_ObjSet(BIF_ObjInvoke, IT_SET);
   31 static ExprOpFunc g_ObjGetInPlace(BIF_ObjGetInPlace, IT_GET);
   32 static ExprOpFunc g_ObjNew(BIF_ObjNew, IT_CALL);
   33 static ExprOpFunc g_ObjPreInc(BIF_ObjIncDec, SYM_PRE_INCREMENT), g_ObjPreDec(BIF_ObjIncDec, SYM_PRE_DECREMENT)
   34                 , g_ObjPostInc(BIF_ObjIncDec, SYM_POST_INCREMENT), g_ObjPostDec(BIF_ObjIncDec, SYM_POST_DECREMENT);
   35 ExprOpFunc g_ObjCall(BIF_ObjInvoke, IT_CALL); // Also needed in script_expression.cpp.
   36 
   37 
   38 #define VF(name, fn) { _T(#name), fn }
   39 #define A_x(name, fn) { _T(#name), fn }
   40 #define A_(name) A_x(name, BIV_##name)
   41 // IMPORTANT: Both of the following arrays must be kept in alphabetical order
   42 // for binary search to work.  See Script::GetBuiltInVar for further comments.
   43 // g_BIV: All built-in vars not beginning with "A_".  Keeping these separate allows
   44 // the search to be limited to just these few whenever the var name does not begin
   45 // with "A_", as for most user-defined variables.  This helps average-case performance.
   46 VarEntry g_BIV[] =
   47 {
   48     VF(Clipboard, (BuiltInVarType)VAR_CLIPBOARD),
   49     VF(ClipboardAll, (BuiltInVarType)VAR_CLIPBOARDALL),
   50     VF(ComSpec, BIV_ComSpec), // Lacks an "A_" prefix for backward compatibility with pre-NoEnv scripts and also it's easier to type & remember.,
   51     VF(False, BIV_True_False),
   52     VF(ProgramFiles, BIV_SpecialFolderPath), // v1.0.43.08: Added to ease the transition to #NoEnv.,
   53     VF(True, BIV_True_False)
   54 };
   55 // g_BIV_A: All built-in vars beginning with "A_".  The prefix is omitted from each
   56 // name to reduce code size and speed up the comparisons.
   57 VarEntry g_BIV_A[] =
   58 {
   59     A_(AhkPath),
   60     A_(AhkVersion),
   61     A_x(AppData, BIV_SpecialFolderPath),
   62     A_x(AppDataCommon, BIV_SpecialFolderPath),
   63     A_(AutoTrim),
   64     A_x(BatchLines, BIV_BatchLines),
   65     A_x(CaretX, BIV_Caret),
   66     A_x(CaretY, BIV_Caret),
   67     A_x(ComputerName, BIV_UserName_ComputerName),
   68     A_(ComSpec),
   69     A_x(ControlDelay, BIV_xDelay),
   70     A_x(CoordModeCaret, BIV_CoordMode),
   71     A_x(CoordModeMenu, BIV_CoordMode),
   72     A_x(CoordModeMouse, BIV_CoordMode),
   73     A_x(CoordModePixel, BIV_CoordMode),
   74     A_x(CoordModeToolTip, BIV_CoordMode),
   75     A_(Cursor),
   76     A_x(DD, BIV_DateTime),
   77     A_x(DDD, BIV_MMM_DDD),
   78     A_x(DDDD, BIV_MMM_DDD),
   79     A_x(DefaultGui, BIV_DefaultGui),
   80     A_x(DefaultListView, BIV_DefaultGui),
   81     A_(DefaultMouseSpeed),
   82     A_x(DefaultTreeView, BIV_DefaultGui),
   83     A_x(Desktop, BIV_SpecialFolderPath),
   84     A_x(DesktopCommon, BIV_SpecialFolderPath),
   85     A_(DetectHiddenText),
   86     A_(DetectHiddenWindows),
   87     A_(EndChar),
   88     A_(EventInfo), // It's called "EventInfo" vs. "GuiEventInfo" because it applies to non-Gui events such as OnClipboardChange.,
   89     A_(ExitReason),
   90     A_(FileEncoding),
   91     A_(FormatFloat),
   92     A_(FormatInteger),
   93     A_x(Gui, BIV_Gui),
   94     A_(GuiControl),
   95     A_x(GuiControlEvent, BIV_GuiEvent),
   96     A_x(GuiEvent, BIV_GuiEvent), // v1.0.36: A_GuiEvent was added as a synonym for A_GuiControlEvent because it seems unlikely that A_GuiEvent will ever be needed for anything:,
   97     A_x(GuiHeight, BIV_Gui),
   98     A_x(GuiWidth, BIV_Gui),
   99     A_x(GuiX, BIV_Gui), // Naming: Brevity seems more a benefit than would A_GuiEventX's improved clarity.,
  100     A_x(GuiY, BIV_Gui), // These can be overloaded if a GuiMove label or similar is ever needed.,
  101     A_x(Hour, BIV_DateTime),
  102     A_(IconFile),
  103     A_(IconHidden),
  104     A_(IconNumber),
  105     A_(IconTip),
  106     A_x(Index, BIV_LoopIndex),
  107     A_x(IPAddress1, BIV_IPAddress),
  108     A_x(IPAddress2, BIV_IPAddress),
  109     A_x(IPAddress3, BIV_IPAddress),
  110     A_x(IPAddress4, BIV_IPAddress),
  111     A_(Is64bitOS),
  112     A_(IsAdmin),
  113     A_(IsCompiled),
  114     A_(IsCritical),
  115     A_(IsPaused),
  116     A_(IsSuspended),
  117     A_(IsUnicode),
  118     A_x(KeyDelay, BIV_xDelay),
  119     A_x(KeyDelayPlay, BIV_xDelay),
  120     A_x(KeyDuration, BIV_xDelay),
  121     A_x(KeyDurationPlay, BIV_xDelay),
  122     A_(Language),
  123     A_(LastError),
  124     A_(LineFile),
  125     A_(LineNumber),
  126     A_(ListLines),
  127     A_(LoopField),
  128     A_(LoopFileAttrib),
  129     A_(LoopFileDir),
  130     A_(LoopFileExt),
  131     A_x(LoopFileFullPath, BIV_LoopFilePath), // Misnomer for backward-compatibility.
  132     A_(LoopFileLongPath),
  133     A_x(LoopFileName, BIV_LoopFileName),
  134     A_x(LoopFilePath, BIV_LoopFilePath),
  135     A_x(LoopFileShortName, BIV_LoopFileName),
  136     A_(LoopFileShortPath),
  137     A_x(LoopFileSize, BIV_LoopFileSize),
  138     A_x(LoopFileSizeKB, BIV_LoopFileSize),
  139     A_x(LoopFileSizeMB, BIV_LoopFileSize),
  140     A_x(LoopFileTimeAccessed, BIV_LoopFileTime),
  141     A_x(LoopFileTimeCreated, BIV_LoopFileTime),
  142     A_x(LoopFileTimeModified, BIV_LoopFileTime),
  143     A_(LoopReadLine),
  144     A_(LoopRegKey),
  145     A_(LoopRegName),
  146     A_(LoopRegSubKey),
  147     A_(LoopRegTimeModified),
  148     A_(LoopRegType),
  149     A_x(MDay, BIV_DateTime),
  150     A_x(Min, BIV_DateTime),
  151     A_x(MM, BIV_DateTime),
  152     A_x(MMM, BIV_MMM_DDD),
  153     A_x(MMMM, BIV_MMM_DDD),
  154     A_x(Mon, BIV_DateTime),
  155     A_x(MouseDelay, BIV_xDelay),
  156     A_x(MouseDelayPlay, BIV_xDelay),
  157     A_x(MSec, BIV_DateTime),
  158     A_(MyDocuments),
  159     A_x(Now, BIV_Now),
  160     A_x(NowUTC, BIV_Now),
  161     A_x(NumBatchLines, BIV_BatchLines),
  162     A_(OSType),
  163     A_(OSVersion),
  164     A_(PriorHotkey),
  165     A_(PriorKey),
  166     A_x(ProgramFiles, BIV_SpecialFolderPath),
  167     A_x(Programs, BIV_SpecialFolderPath),
  168     A_x(ProgramsCommon, BIV_SpecialFolderPath),
  169     A_(PtrSize),
  170     A_(RegView),
  171     A_(ScreenDPI),
  172     A_x(ScreenHeight, BIV_ScreenWidth_Height),
  173     A_x(ScreenWidth, BIV_ScreenWidth_Height),
  174     A_(ScriptDir),
  175     A_(ScriptFullPath),
  176     A_(ScriptHwnd),
  177     A_(ScriptName),
  178     A_x(Sec, BIV_DateTime),
  179     A_(SendLevel),
  180     A_(SendMode),
  181     A_x(Space, BIV_Space_Tab),
  182     A_x(StartMenu, BIV_SpecialFolderPath),
  183     A_x(StartMenuCommon, BIV_SpecialFolderPath),
  184     A_x(Startup, BIV_SpecialFolderPath),
  185     A_x(StartupCommon, BIV_SpecialFolderPath),
  186     A_(StoreCapslockMode),
  187     A_(StringCaseSense),
  188     A_x(Tab, BIV_Space_Tab),
  189     A_(Temp), // Debatably should be A_TempDir, but brevity seemed more popular with users, perhaps for heavy uses of the temp folder.,
  190     A_(ThisFunc),
  191     A_(ThisHotkey),
  192     A_(ThisLabel),
  193     A_(ThisMenu),
  194     A_(ThisMenuItem),
  195     A_(ThisMenuItemPos),
  196     A_(TickCount),
  197     A_(TimeIdle),
  198     A_x(TimeIdleKeyboard, BIV_TimeIdlePhysical),
  199     A_x(TimeIdleMouse, BIV_TimeIdlePhysical),
  200     A_(TimeIdlePhysical),
  201     A_(TimeSincePriorHotkey),
  202     A_(TimeSinceThisHotkey),
  203     A_(TitleMatchMode),
  204     A_(TitleMatchModeSpeed),
  205     A_x(UserName, BIV_UserName_ComputerName),
  206     A_x(WDay, BIV_DateTime),
  207     A_x(WinDelay, BIV_xDelay),
  208     A_(WinDir),
  209     A_(WorkingDir),
  210     A_x(YDay, BIV_DateTime),
  211     A_x(Year, BIV_DateTime),
  212     A_x(YWeek, BIV_DateTime),
  213     A_x(YYYY, BIV_DateTime)
  214 };
  215 #undef A_
  216 #undef VF
  217 
  218 
  219 // See Script::CreateWindows() for details about the following:
  220 typedef BOOL (WINAPI* AddRemoveClipboardListenerType)(HWND);
  221 static AddRemoveClipboardListenerType MyRemoveClipboardListener = (AddRemoveClipboardListenerType)
  222     GetProcAddress(GetModuleHandle(_T("user32")), "RemoveClipboardFormatListener");
  223 static AddRemoveClipboardListenerType MyAddClipboardListener = (AddRemoveClipboardListenerType)
  224     GetProcAddress(GetModuleHandle(_T("user32")), "AddClipboardFormatListener");
  225 
  226 // General note about the methods in here:
  227 // Want to be able to support multiple simultaneous points of execution
  228 // because more than one subroutine can be executing simultaneously
  229 // (well, more precisely, there can be more than one script subroutine
  230 // that's in a "currently running" state, even though all such subroutines,
  231 // except for the most recent one, are suspended.  So keep this in mind when
  232 // using things such as static data members or static local variables.
  233 
  234 
  235 Script::Script()
  236     : mFirstLine(NULL), mLastLine(NULL), mCurrLine(NULL), mPlaceholderLabel(NULL), mFirstStaticLine(NULL), mLastStaticLine(NULL)
  237     , mThisHotkeyName(_T("")), mPriorHotkeyName(_T("")), mThisHotkeyStartTime(0), mPriorHotkeyStartTime(0)
  238     , mEndChar(0), mThisHotkeyModifiersLR(0)
  239     , mNextClipboardViewer(NULL), mOnClipboardChangeIsRunning(false), mOnClipboardChangeLabel(NULL)
  240     , mOnExitLabel(NULL), mExitReason(EXIT_NONE)
  241     , mFirstLabel(NULL), mLastLabel(NULL)
  242     , mFunc(NULL), mFuncCount(0), mFuncCountMax(0)
  243     , mFirstTimer(NULL), mLastTimer(NULL), mTimerEnabledCount(0), mTimerCount(0)
  244     , mFirstMenu(NULL), mLastMenu(NULL), mMenuCount(0), mThisMenuItem(NULL)
  245     , mVar(NULL), mVarCount(0), mVarCountMax(0), mLazyVar(NULL), mLazyVarCount(0)
  246     , mCurrentFuncOpenBlockCount(0), mNextLineIsFunctionBody(false), mNoUpdateLabels(false)
  247     , mClassObjectCount(0), mUnresolvedClasses(NULL), mClassProperty(NULL), mClassPropertyDef(NULL)
  248     , mCurrFileIndex(0), mCombinedLineNumber(0), mNoHotkeyLabels(true), mMenuUseErrorLevel(false)
  249     , mFileSpec(_T("")), mFileDir(_T("")), mFileName(_T("")), mOurEXE(_T("")), mOurEXEDir(_T("")), mMainWindowTitle(_T(""))
  250     , mIsReadyToExecute(false), mAutoExecSectionIsRunning(false)
  251     , mIsRestart(false), mErrorStdOut(false), mErrorStdOutCP(-1)
  252 #ifndef AUTOHOTKEYSC
  253     , mIncludeLibraryFunctionsThenExit(NULL)
  254 #endif
  255     , mLinesExecutedThisCycle(0), mUninterruptedLineCountMax(1000), mUninterruptibleTime(15)
  256     , mCustomIcon(NULL), mCustomIconSmall(NULL) // Normally NULL unless there's a custom tray icon loaded dynamically.
  257     , mCustomIconFile(NULL), mIconFrozen(false), mTrayIconTip(NULL) // Allocated on first use.
  258     , mCustomIconNumber(0)
  259 {
  260     // v1.0.25: mLastScriptRest and mLastPeekTime are now initialized right before the auto-exec
  261     // section of the script is launched, which avoids an initial Sleep(10) in ExecUntil
  262     // that would otherwise occur.
  263     *mThisMenuItemName = *mThisMenuName = '\0';
  264     ZeroMemory(&mNIC, sizeof(mNIC));  // Constructor initializes this, to be safe.
  265     mNIC.hWnd = NULL;  // Set this as an indicator that it tray icon is not installed.
  266 
  267     // Lastly (after the above have been initialized), anything that can fail:
  268     if (   !(mTrayMenu = AddMenu(_T("Tray")))   ) // realistically never happens
  269     {
  270         ScriptError(_T("No tray mem"));
  271         ExitApp(EXIT_CRITICAL);
  272     }
  273     else
  274         mTrayMenu->mIncludeStandardItems = true;
  275 
  276 #ifdef _DEBUG
  277     if (ID_FILE_EXIT < ID_MAIN_FIRST) // Not a very thorough check.
  278         ScriptError(_T("DEBUG: ID_FILE_EXIT is too large (conflicts with IDs reserved via ID_USER_FIRST)."));
  279     if (MAX_CONTROLS_PER_GUI > ID_USER_FIRST - 3)
  280         ScriptError(_T("DEBUG: MAX_CONTROLS_PER_GUI is too large (conflicts with IDs reserved via ID_USER_FIRST)."));
  281     if (g_ActionCount != ACT_COUNT) // This enum value only exists in debug mode.
  282         ScriptError(_T("DEBUG: g_act and enum_act are out of sync."));
  283     int LargestMaxParams, i, j;
  284     ActionTypeType *np;
  285     // Find the Largest value of MaxParams used by any command and make sure it
  286     // isn't something larger than expected by the parsing routines:
  287     for (LargestMaxParams = i = 0; i < g_ActionCount; ++i)
  288     {
  289         if (g_act[i].MaxParams > LargestMaxParams)
  290             LargestMaxParams = g_act[i].MaxParams;
  291         // This next part has been tested and it does work, but only if one of the arrays
  292         // contains exactly MAX_NUMERIC_PARAMS number of elements and isn't zero terminated.
  293         // Relies on short-circuit boolean order:
  294         for (np = g_act[i].NumericParams, j = 0; j < MAX_NUMERIC_PARAMS && *np; ++j, ++np);
  295         if (j >= MAX_NUMERIC_PARAMS)
  296         {
  297             ScriptError(_T("DEBUG: At least one command has a NumericParams array that isn't zero-terminated.")
  298                 _T("  This would result in reading beyond the bounds of the array."));
  299             return;
  300         }
  301     }
  302     if (LargestMaxParams > MAX_ARGS)
  303         ScriptError(_T("DEBUG: At least one command supports more arguments than allowed."));
  304     if (sizeof(ActionTypeType) == 1 && g_ActionCount > 256)
  305         ScriptError(_T("DEBUG: Since there are now more than 256 Action Types, the ActionTypeType")
  306             _T(" typedef must be changed."));
  307 #endif
  308     OleInitialize(NULL);
  309 }
  310 
  311 
  312 
  313 Script::~Script() // Destructor.
  314 {
  315     // MSDN: "Before terminating, an application must call the UnhookWindowsHookEx function to free
  316     // system resources associated with the hook."
  317     AddRemoveHooks(0); // Remove all hooks.
  318     if (mNIC.hWnd) // Tray icon is installed.
  319         Shell_NotifyIcon(NIM_DELETE, &mNIC); // Remove it.
  320     // Destroy any Progress/SplashImage windows that haven't already been destroyed.  This is necessary
  321     // because sometimes these windows aren't owned by the main window:
  322     int i;
  323     for (i = 0; i < MAX_PROGRESS_WINDOWS; ++i)
  324     {
  325         if (g_Progress[i].hwnd && IsWindow(g_Progress[i].hwnd))
  326             DestroyWindow(g_Progress[i].hwnd);
  327         if (g_Progress[i].hfont1) // Destroy font only after destroying the window that uses it.
  328             DeleteObject(g_Progress[i].hfont1);
  329         if (g_Progress[i].hfont2) // Destroy font only after destroying the window that uses it.
  330             DeleteObject(g_Progress[i].hfont2);
  331         if (g_Progress[i].hbrush)
  332             DeleteObject(g_Progress[i].hbrush);
  333     }
  334     for (i = 0; i < MAX_SPLASHIMAGE_WINDOWS; ++i)
  335     {
  336         if (g_SplashImage[i].pic_bmp)
  337         {
  338             if (g_SplashImage[i].pic_type == IMAGE_BITMAP)
  339                 DeleteObject(g_SplashImage[i].pic_bmp);
  340             else
  341                 DestroyIcon(g_SplashImage[i].pic_icon);
  342         }
  343         if (g_SplashImage[i].hwnd && IsWindow(g_SplashImage[i].hwnd))
  344             DestroyWindow(g_SplashImage[i].hwnd);
  345         if (g_SplashImage[i].hfont1) // Destroy font only after destroying the window that uses it.
  346             DeleteObject(g_SplashImage[i].hfont1);
  347         if (g_SplashImage[i].hfont2) // Destroy font only after destroying the window that uses it.
  348             DeleteObject(g_SplashImage[i].hfont2);
  349         if (g_SplashImage[i].hbrush)
  350             DeleteObject(g_SplashImage[i].hbrush);
  351     }
  352 
  353     // It is safer/easier to destroy the GUI windows prior to the menus (especially the menu bars).
  354     // This is because one GUI window might get destroyed and take with it a menu bar that is still
  355     // in use by an existing GUI window.  GuiType::Destroy() adheres to this philosophy by detaching
  356     // its menu bar prior to destroying its window:
  357     while (g_guiCount)
  358         GuiType::Destroy(*g_gui[g_guiCount-1]); // Static method to avoid problems with object destroying itself.
  359     for (i = 0; i < GuiType::sFontCount; ++i) // Now that GUI windows are gone, delete all GUI fonts.
  360         if (GuiType::sFont[i].hfont)
  361             DeleteObject(GuiType::sFont[i].hfont);
  362     // The above might attempt to delete an HFONT from GetStockObject(DEFAULT_GUI_FONT), etc.
  363     // But that should be harmless:
  364     // MSDN: "It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject."
  365 
  366     // Above: Probably best to have removed icon from tray and destroyed any Gui/Splash windows that were
  367     // using it prior to getting rid of the script's custom icon below:
  368     if (mCustomIcon)
  369     {
  370         DestroyIcon(mCustomIcon);
  371         DestroyIcon(mCustomIconSmall); // Should always be non-NULL if mCustomIcon is non-NULL.
  372     }
  373 
  374     // Since they're not associated with a window, we must free the resources for all popup menus.
  375     // Update: Even if a menu is being used as a GUI window's menu bar, see note above for why menu
  376     // destruction is done AFTER the GUI windows are destroyed:
  377     UserMenu *menu_to_delete;
  378     for (UserMenu *m = mFirstMenu; m;)
  379     {
  380         menu_to_delete = m;
  381         m = m->mNextMenu;
  382         ScriptDeleteMenu(menu_to_delete);
  383         // Above call should not return FAIL, since the only way FAIL can realistically happen is
  384         // when a GUI window is still using the menu as its menu bar.  But all GUI windows are gone now.
  385     }
  386 
  387     // Since tooltip windows are unowned, they should be destroyed to avoid resource leak:
  388     for (i = 0; i < MAX_TOOLTIPS; ++i)
  389         if (g_hWndToolTip[i] && IsWindow(g_hWndToolTip[i]))
  390             DestroyWindow(g_hWndToolTip[i]);
  391 
  392     if (g_hFontSplash) // The splash window itself should auto-destroyed, since it's owned by main.
  393         DeleteObject(g_hFontSplash);
  394 
  395     if (mOnClipboardChangeLabel || mOnClipboardChange.Count()) // Remove from viewer chain.
  396         EnableClipboardListener(false);
  397 
  398     // Close any open sound item to prevent hang-on-exit in certain operating systems or conditions.
  399     // If there's any chance that a sound was played and not closed out, or that it is still playing,
  400     // this check is done.  Otherwise, the check is avoided since it might be a high overhead call,
  401     // especially if the sound subsystem part of the OS is currently swapped out or something:
  402     if (g_SoundWasPlayed)
  403     {
  404         TCHAR buf[MAX_PATH * 2]; // See "MAX_PATH note" in Line::SoundPlay for comments.
  405         mciSendString(_T("status ") SOUNDPLAY_ALIAS _T(" mode"), buf, _countof(buf), NULL);
  406         if (*buf) // "playing" or "stopped"
  407             mciSendString(_T("close ") SOUNDPLAY_ALIAS, NULL, 0, NULL);
  408     }
  409 
  410 #ifdef ENABLE_KEY_HISTORY_FILE
  411     KeyHistoryToFile();  // Close the KeyHistory file if it's open.
  412 #endif
  413 
  414     DeleteCriticalSection(&g_CriticalRegExCache); // g_CriticalRegExCache is used elsewhere for thread-safety.
  415     OleUninitialize();
  416 }
  417 
  418 
  419 
  420 ResultType Script::Init(global_struct &g, LPTSTR aScriptFilename, bool aIsRestart)
  421 // Returns OK or FAIL.
  422 // Caller has provided an empty string for aScriptFilename if this is a compiled script.
  423 // Otherwise, aScriptFilename can be NULL if caller hasn't determined the filename of the script yet.
  424 {
  425     mIsRestart = aIsRestart;
  426     TCHAR buf[UorA(T_MAX_PATH, 2048)]; // Just to make sure we have plenty of room to do things with.
  427     size_t buf_length;
  428 #ifdef AUTOHOTKEYSC
  429     // Fix for v1.0.29: Override the caller's use of __argv[0] by using GetModuleFileName(),
  430     // so that when the script is started from the command line but the user didn't type the
  431     // extension, the extension will be included.  This necessary because otherwise
  432     // #SingleInstance wouldn't be able to detect duplicate versions in every case.
  433     // It also provides more consistency.
  434     buf_length = GetModuleFileName(NULL, buf, _countof(buf));
  435 #else
  436     TCHAR def_buf[MAX_PATH + 1], exe_buf[MAX_PATH + 20]; // For simplicity, allow at least space for +2 (see below) and "AutoHotkey.chm".
  437     if (!aScriptFilename) // v1.0.46.08: Change in policy: store the default script in the My Documents directory rather than in Program Files.  It's more correct and solves issues that occur due to Vista's file-protection scheme.
  438     {
  439         // Since no script-file was specified on the command line, use the default name.
  440         // For portability, first check if there's an <EXENAME>.ahk file in the current directory.
  441         LPTSTR suffix, dot;
  442         DWORD exe_len = GetModuleFileName(NULL, exe_buf, MAX_PATH + 2);
  443         // MAX_PATH+1 could mean it was truncated.  Any path longer than MAX_PATH is probably
  444         // impossible as of 2018 since testing indicates the program can't start if its path
  445         // is longer than MAX_PATH-1 even with Windows 10 long path awareness enabled.
  446         // On Windows XP, exe_len of exactly the buffer size specified would indicate the path
  447         // was truncated and not null-terminated, but is probably impossible in this case.
  448         if (exe_len > MAX_PATH)
  449             return FAIL; // Seems the safest option for this unlikely case.
  450         if (  (suffix = _tcsrchr(exe_buf, '\\')) // Find name part of path.
  451             && (dot = _tcsrchr(suffix, '.'))  ) // Find extension part of name.
  452             // Even if the extension is somehow zero characters, more than enough space was
  453             // reserved in exe_buf to add "ahk":
  454             //&& dot - exe_buf + 5 < _countof(exe_buf)  ) // Enough space in buffer?
  455         {
  456             _tcscpy(dot, EXT_AUTOHOTKEY);
  457         }
  458         else // Very unlikely.
  459             return FAIL;
  460 
  461         aScriptFilename = exe_buf; // Use the entire path, including the exe's directory.
  462         if (GetFileAttributes(aScriptFilename) == 0xFFFFFFFF) // File doesn't exist, so fall back to new method.
  463         {
  464             aScriptFilename = def_buf;
  465             VarSizeType filespec_length = BIV_MyDocuments(aScriptFilename, _T("")); // e.g. C:\Documents and Settings\Home\My Documents
  466             if (filespec_length + _tcslen(suffix) + 1 > _countof(def_buf))
  467                 return FAIL; // Very rare, so for simplicity just abort.
  468             _tcscpy(aScriptFilename + filespec_length, suffix); // Append the filename: .ahk vs. .ini seems slightly better in terms of clarity and usefulness (e.g. the ability to double click the default script to launch it).
  469             if (GetFileAttributes(aScriptFilename) == 0xFFFFFFFF)
  470             {
  471                 _tcscpy(suffix, _T("\\") AHK_HELP_FILE); // Replace the executable name.
  472                 if (GetFileAttributes(exe_buf) != 0xFFFFFFFF) // Avoids hh.exe showing an error message if the file doesn't exist.
  473                 {
  474                     _sntprintf(buf, _countof(buf), _T("\"ms-its:%s::/docs/Welcome.htm\""), exe_buf);
  475                     if (ActionExec(_T("hh.exe"), buf, exe_buf, false, _T("Max")))
  476                         return FAIL;
  477                 }
  478                 // Since above didn't return, the help file is missing or failed to launch,
  479                 // so continue on and let the missing script file be reported as an error.
  480             }
  481         }
  482         //else since the file exists, everything is now set up right. (The file might be a directory, but that isn't checked due to rarity.)
  483     }
  484     // In case the script is a relative filespec (relative to current working dir):
  485     buf_length = GetFullPathName(aScriptFilename, _countof(buf), buf, NULL); // This is also relied upon by mIncludeLibraryFunctionsThenExit.  Succeeds even on nonexistent files.
  486     if (!buf_length)
  487         return FAIL; // Due to rarity, no error msg, just abort.
  488 #endif
  489     if (g_RunStdIn = (*aScriptFilename == '*' && !aScriptFilename[1])) // v1.1.17: Read script from stdin.
  490     {
  491         // Seems best to disable #SingleInstance and enable #NoEnv for stdin scripts.
  492         g_AllowOnlyOneInstance = SINGLE_INSTANCE_OFF;
  493         g_NoEnv = true;
  494     }
  495     else // i.e. don't call the following function for stdin.
  496     {
  497         // Using the correct case not only makes it look better in title bar & tray tool tip,
  498         // it also helps with the detection of "this script already running" since otherwise
  499         // it might not find the dupe if the same script name is launched with different
  500         // lowercase/uppercase letters:
  501         ConvertFilespecToCorrectCase(buf, _countof(buf), buf_length); // This might change the length, e.g. due to expansion of 8.3 filename.
  502     }
  503     if (   !(mFileSpec = SimpleHeap::Malloc(buf))   )  // The full spec is stored for convenience, and it's relied upon by mIncludeLibraryFunctionsThenExit.
  504         return FAIL;  // It already displayed the error for us.
  505     LPTSTR filename_marker;
  506     if (filename_marker = _tcsrchr(buf, '\\'))
  507     {
  508         *filename_marker = '\0'; // Terminate buf in this position to divide the string.
  509         if (   !(mFileDir = SimpleHeap::Malloc(buf))   )
  510             return FAIL;  // It already displayed the error for us.
  511         ++filename_marker;
  512     }
  513     else
  514     {
  515         // The only known cause of this condition is a path being too long for GetFullPathName
  516         // to expand it into buf, in which case buf and mFileSpec are now empty, and this will
  517         // cause LoadFromFile() to fail and the program to exit.
  518         //mFileDir = _T(""); // Already done by the constructor.
  519         filename_marker = buf;
  520     }
  521     if (   !(mFileName = SimpleHeap::Malloc(filename_marker))   )
  522         return FAIL;  // It already displayed the error for us.
  523 #ifdef AUTOHOTKEYSC
  524     // Omit AutoHotkey from the window title, like AutoIt3 does for its compiled scripts.
  525     // One reason for this is to reduce backlash if evil-doers create viruses and such
  526     // with the program:
  527     sntprintf(buf, _countof(buf), _T("%s\\%s"), mFileDir, mFileName);
  528 #else
  529     sntprintf(buf, _countof(buf), _T("%s\\%s - %s"), mFileDir, mFileName, T_AHK_NAME_VERSION);
  530 #endif
  531     if (   !(mMainWindowTitle = SimpleHeap::Malloc(buf))   )
  532         return FAIL;  // It already displayed the error for us.
  533 
  534     // It may be better to get the module name this way rather than reading it from the registry
  535     // (though it might be more proper to parse it out of the command line args or something),
  536     // in case the user has moved it to a folder other than the install folder, hasn't installed it,
  537     // or has renamed the EXE file itself.  Also, enclose the full filespec of the module in double
  538     // quotes since that's how callers usually want it because ActionExec() currently needs it that way:
  539     *buf = '"';
  540     if (GetModuleFileName(NULL, buf + 1, _countof(buf) - 2)) // -2 to leave room for the enclosing double quotes.
  541     {
  542         size_t buf_length = _tcslen(buf);
  543         buf[buf_length++] = '"';
  544         buf[buf_length] = '\0';
  545         if (   !(mOurEXE = SimpleHeap::Malloc(buf))   )
  546             return FAIL;  // It already displayed the error for us.
  547         else
  548         {
  549             LPTSTR last_backslash = _tcsrchr(buf, '\\');
  550             if (!last_backslash) // probably can't happen due to the nature of GetModuleFileName().
  551                 mOurEXEDir = _T("");
  552             *last_backslash = '\0';
  553             if (   !(mOurEXEDir = SimpleHeap::Malloc(buf + 1))   ) // +1 to omit the leading double-quote.
  554                 return FAIL;  // It already displayed the error for us.
  555         }
  556     }
  557     return OK;
  558 }
  559 
  560     
  561 
  562 ResultType Script::CreateWindows()
  563 // Returns OK or FAIL.
  564 {
  565     if (!mMainWindowTitle || !*mMainWindowTitle) return FAIL;  // Init() must be called before this function.
  566     // Register a window class for the main window:
  567     WNDCLASSEX wc = {0};
  568     wc.cbSize = sizeof(wc);
  569     wc.lpszClassName = WINDOW_CLASS_MAIN;
  570     wc.hInstance = g_hInstance;
  571     wc.lpfnWndProc = MainWindowProc;
  572     // The following are left at the default of NULL/0 set higher above:
  573     //wc.style = 0;  // CS_HREDRAW | CS_VREDRAW
  574     //wc.cbClsExtra = 0;
  575     //wc.cbWndExtra = 0;
  576     // Load the main icon in the two sizes needed throughout the program:
  577     g_IconLarge = ExtractIconFromExecutable(NULL, -IDI_MAIN, 0, 0);
  578     g_IconSmall = ExtractIconFromExecutable(NULL, -IDI_MAIN, GetSystemMetrics(SM_CXSMICON), 0);
  579     wc.hIcon = g_IconLarge;
  580     wc.hIconSm = g_IconSmall;
  581     wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
  582     wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);  // Needed for ProgressBar. Old: (HBRUSH)GetStockObject(WHITE_BRUSH);
  583     wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_MAIN); // NULL; // "MainMenu";
  584     if (!RegisterClassEx(&wc))
  585     {
  586         MsgBox(_T("RegClass")); // Short/generic msg since so rare.
  587         return FAIL;
  588     }
  589 
  590     // Register a second class for the splash window.  The only difference is that
  591     // it doesn't have the menu bar:
  592     wc.lpszClassName = WINDOW_CLASS_SPLASH;
  593     wc.lpszMenuName = NULL; // Override the non-NULL value set higher above.
  594     if (!RegisterClassEx(&wc))
  595     {
  596         MsgBox(_T("RegClass")); // Short/generic msg since so rare.
  597         return FAIL;
  598     }
  599 
  600     TCHAR class_name[64];
  601     HWND fore_win = GetForegroundWindow();
  602     bool do_minimize = !fore_win || (GetClassName(fore_win, class_name, _countof(class_name))
  603         && !_tcsicmp(class_name, _T("Shell_TrayWnd"))); // Shell_TrayWnd is the taskbar's class on Win98/XP and probably the others too.
  604 
  605     // Note: the title below must be constructed the same was as is done by our
  606     // WinMain() (so that we can detect whether this script is already running)
  607     // which is why it's standardized in g_script.mMainWindowTitle.
  608     // Create the main window.  Prevent momentary disruption of Start Menu, which
  609     // some users understandably don't like, by omitting the taskbar button temporarily.
  610     // This is done because testing shows that minimizing the window further below, even
  611     // though the window is hidden, would otherwise briefly show the taskbar button (or
  612     // at least redraw the taskbar).  Sometimes this isn't noticeable, but other times
  613     // (such as when the system is under heavy load) a user reported that it is quite
  614     // noticeable. WS_EX_TOOLWINDOW is used instead of WS_EX_NOACTIVATE because
  615     // WS_EX_NOACTIVATE is available only on 2000/XP.
  616     if (   !(g_hWnd = CreateWindowEx(do_minimize ? WS_EX_TOOLWINDOW : 0
  617         , WINDOW_CLASS_MAIN
  618         , mMainWindowTitle
  619         , WS_OVERLAPPEDWINDOW // Style.  Alt: WS_POPUP or maybe 0.
  620         , CW_USEDEFAULT // xpos
  621         , CW_USEDEFAULT // ypos
  622         , CW_USEDEFAULT // width
  623         , CW_USEDEFAULT // height
  624         , NULL // parent window
  625         , NULL // Identifies a menu, or specifies a child-window identifier depending on the window style
  626         , g_hInstance // passed into WinMain
  627         , NULL))   ) // lpParam
  628     {
  629         MsgBox(_T("CreateWindow")); // Short msg since so rare.
  630         return FAIL;
  631     }
  632 #ifdef AUTOHOTKEYSC
  633     HMENU menu = GetMenu(g_hWnd);
  634     // Disable the Edit menu item, since it does nothing for a compiled script:
  635     EnableMenuItem(menu, ID_FILE_EDITSCRIPT, MF_DISABLED | MF_GRAYED);
  636     EnableOrDisableViewMenuItems(menu, MF_DISABLED | MF_GRAYED); // Fix for v1.0.47.06: No point in checking g_AllowMainWindow because the script hasn't starting running yet, so it will always be false.
  637     // But leave the ID_VIEW_REFRESH menu item enabled because if the script contains a
  638     // command such as ListLines in it, Refresh can be validly used.
  639 #endif
  640 
  641     if (    !(g_hWndEdit = CreateWindow(_T("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER
  642         | ES_LEFT | ES_MULTILINE | ES_READONLY | WS_VSCROLL // | WS_HSCROLL (saves space)
  643         , 0, 0, 0, 0, g_hWnd, (HMENU)1, g_hInstance, NULL))   )
  644     {
  645         MsgBox(_T("CreateWindow")); // Short msg since so rare.
  646         return FAIL;
  647     }
  648     // FONTS: The font used by default, at least on XP, is GetStockObject(SYSTEM_FONT).
  649     // Use something more appealing (monospaced seems preferable):
  650     HDC hdc = GetDC(g_hWndEdit);
  651     g_hFontEdit = CreateFont(FONT_POINT(hdc, 10), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  652         , DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE
  653         , g_os.IsWinVistaOrLater() ? _T("Consolas") : _T("Lucida Console"));
  654     ReleaseDC(g_hWndEdit, hdc);
  655     SendMessage(g_hWndEdit, WM_SETFONT, (WPARAM)g_hFontEdit, 0);
  656 
  657     // v1.0.30.05: Specifying a limit of zero opens the control to its maximum text capacity,
  658     // which removes the 32K size restriction.  Testing shows that this does not increase the actual
  659     // amount of memory used for controls containing small amounts of text.  All it does is allow
  660     // the control to allocate more memory as needed.
  661     SendMessage(g_hWndEdit, EM_LIMITTEXT, 0, 0);
  662 
  663     // Some of the MSDN docs mention that an app's very first call to ShowWindow() makes that
  664     // function operate in a special mode. Therefore, it seems best to get that first call out
  665     // of the way to avoid the possibility that the first-call behavior will cause problems with
  666     // our normal use of ShowWindow() below and other places.  Also, decided to ignore nCmdShow,
  667     // to avoid any momentary visual effects on startup.
  668     // Update: It's done a second time because the main window might now be visible if the process
  669     // that launched ours specified that.  It seems best to override the requested state because
  670     // some calling processes might specify "maximize" or "shownormal" as generic launch method.
  671     // The script can display it's own main window with ListLines, etc.
  672     // MSDN: "the nCmdShow value is ignored in the first call to ShowWindow if the program that
  673     // launched the application specifies startup information in the structure. In this case,
  674     // ShowWindow uses the information specified in the STARTUPINFO structure to show the window.
  675     // On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT
  676     // to use the startup information provided by the program that launched the application."
  677     ShowWindow(g_hWnd, SW_HIDE);
  678     ShowWindow(g_hWnd, SW_HIDE);
  679 
  680     // Now that the first call to ShowWindow() is out of the way, minimize the main window so that
  681     // if the script is launched from the Start Menu (and perhaps other places such as the
  682     // Quick-launch toolbar), the window that was active before the Start Menu was displayed will
  683     // become active again.  But as of v1.0.25.09, this minimize is done more selectively to prevent
  684     // the launch of a script from knocking the user out of a full-screen game or other application
  685     // that would be disrupted by an SW_MINIMIZE:
  686     if (do_minimize)
  687     {
  688         ShowWindow(g_hWnd, SW_MINIMIZE);
  689         SetWindowLong(g_hWnd, GWL_EXSTYLE, 0); // Give the main window back its taskbar button.
  690     }
  691     // Note: When the window is not minimized, task manager reports that a simple script (such as
  692     // one consisting only of the single line "#Persistent") uses 2600 KB of memory vs. ~452 KB if
  693     // it were immediately minimized.  That is probably just due to the vagaries of how the OS
  694     // manages windows and memory and probably doesn't actually impact system performance to the
  695     // degree indicated.  In other words, it's hard to imagine that the failure to do
  696     // ShowWidnow(g_hWnd, SW_MINIMIZE) unconditionally upon startup (which causes the side effects
  697     // discussed further above) significantly increases the actual memory load on the system.
  698 
  699     g_hAccelTable = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
  700 
  701     if (g_NoTrayIcon)
  702         mNIC.hWnd = NULL;  // Set this as an indicator that tray icon is not installed.
  703     else
  704         // Even if the below fails, don't return FAIL in case the user is using a different shell
  705         // or something.  In other words, it is expected to fail under certain circumstances and
  706         // we want to tolerate that:
  707         CreateTrayIcon();
  708 
  709     if (mOnClipboardChangeLabel)
  710         EnableClipboardListener(true);
  711 
  712     return OK;
  713 }
  714 
  715 
  716 
  717 void Script::EnableClipboardListener(bool aEnable)
  718 {
  719     static bool sEnabled = false;
  720     if (aEnable == sEnabled) // Simplifies BIF_On.
  721         return;
  722     if (aEnable)
  723     {
  724         if (MyAddClipboardListener && MyRemoveClipboardListener) // Should be impossible for only one of these to be NULL, but check both anyway to be safe.
  725         {
  726             // The old clipboard viewer chain method is prone to break when some other application uses
  727             // it incorrectly.  This newer method should be more reliable, but requires Vista or later:
  728             MyAddClipboardListener(g_hWnd);
  729             // But this method doesn't appear to send an initial WM_CLIPBOARDUPDATE message.
  730             // For consistency with the other method (below) and for backward compatibility,
  731             // run the OnClipboardChange label once when the script first starts:
  732             if (!mIsReadyToExecute)
  733             {
  734                 // Pass 1 for wParam so that MsgSleep() will call only the legacy OnClipboardChange label,
  735                 // not any functions which are registered between now and when the message is handled.
  736                 PostMessage(g_hWnd, AHK_CLIPBOARD_CHANGE, 1, 0);
  737             }
  738         }
  739         else
  740         {
  741             mNextClipboardViewer = SetClipboardViewer(g_hWnd);
  742             // SetClipboardViewer() sends a WM_DRAWCLIPBOARD message and causes MainWindowProc()
  743             // to be called before returning.  MainWindowProc() posts an AHK_CLIPBOARD_CHANGE
  744             // message only if an OnClipboardChange label exists, since mOnClipboardChange.Count()
  745             // is always 0 at this point.  It also uses wParam for the reason described above.
  746         }
  747     }
  748     else
  749     {
  750         if (MyRemoveClipboardListener && MyAddClipboardListener)
  751             MyRemoveClipboardListener(g_hWnd); // MyAddClipboardListener was used.
  752         else
  753             ChangeClipboardChain(g_hWnd, mNextClipboardViewer); // SetClipboardViewer was used.
  754     }
  755     sEnabled = aEnable;
  756 }
  757 
  758 
  759 
  760 void Script::EnableOrDisableViewMenuItems(HMENU aMenu, UINT aFlags)
  761 {
  762     EnableMenuItem(aMenu, ID_VIEW_KEYHISTORY, aFlags);
  763     EnableMenuItem(aMenu, ID_VIEW_LINES, aFlags);
  764     EnableMenuItem(aMenu, ID_VIEW_VARIABLES, aFlags);
  765     EnableMenuItem(aMenu, ID_VIEW_HOTKEYS, aFlags);
  766 }
  767 
  768 
  769 
  770 void Script::CreateTrayIcon()
  771 // It is the caller's responsibility to ensure that the previous icon is first freed/destroyed
  772 // before calling us to install a new one.  However, that is probably not needed if the Explorer
  773 // crashed, since the memory used by the tray icon was probably destroyed along with it.
  774 {
  775     ZeroMemory(&mNIC, sizeof(mNIC));  // To be safe.
  776     // Using NOTIFYICONDATA_V2_SIZE vs. sizeof(NOTIFYICONDATA) improves compatibility with Win9x maybe.
  777     // MSDN: "Using [NOTIFYICONDATA_V2_SIZE] for cbSize will allow your application to use NOTIFYICONDATA
  778     // with earlier Shell32.dll versions, although without the version 6.0 enhancements."
  779     // Update: Using V2 gives an compile error so trying V1.  Update: Trying sizeof(NOTIFYICONDATA)
  780     // for compatibility with VC++ 6.x.  This is also what AutoIt3 uses:
  781     mNIC.cbSize = sizeof(NOTIFYICONDATA);  // NOTIFYICONDATA_V1_SIZE
  782     mNIC.hWnd = g_hWnd;
  783     mNIC.uID = AHK_NOTIFYICON; // This is also used for the ID, see TRANSLATE_AHK_MSG for details.
  784     mNIC.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON;
  785     mNIC.uCallbackMessage = AHK_NOTIFYICON;
  786     mNIC.hIcon = mCustomIconSmall ? mCustomIconSmall : g_IconSmall;
  787     UPDATE_TIP_FIELD
  788     if (!Shell_NotifyIcon(NIM_ADD, &mNIC))
  789         mNIC.hWnd = NULL;  // Set this as an indicator that tray icon is not installed.
  790 }
  791 
  792 
  793 
  794 void Script::RestoreTrayIcon()
  795 {
  796     // v1.1.33.07: This function is called when the TaskbarCreated message is received, instead of calling
  797     // CreateTrayIcon() and UpdateTrayIcon(true).  mNIC already contains the values needed to recreate the
  798     // icon as it was.  NIM_ADD fails if the icon already exists, such as if the message was received due
  799     // to a screen DPI change or explicit SendMessage; for those cases, attempt NIM_MODIFY to be sure that
  800     // the icon really doesn't exist.  This also fixes the icon becoming blurry when the DPI is changed
  801     // repeatedly (presumably because the tray resizes its copy of the icon, but NIM_MODIFY refreshes it).
  802     // This isn't done by UpdateTrayIcon() in case any scripts rely on the fact that the icon won't be
  803     // recreated if it is killed by explicitly calling Shell_NotifyIcon().
  804     if (  !(Shell_NotifyIcon(NIM_ADD, &mNIC) || Shell_NotifyIcon(NIM_MODIFY, &mNIC))  )
  805         mNIC.hWnd = NULL;  // Set this as an indicator that tray icon is not installed.
  806 }
  807 
  808 
  809 
  810 void Script::UpdateTrayIcon(bool aForceUpdate)
  811 {
  812     if (!mNIC.hWnd) // tray icon is not installed
  813         return;
  814     static bool icon_shows_paused = false;
  815     static bool icon_shows_suspended = false;
  816     if (!aForceUpdate && (mIconFrozen || (g->IsPaused == icon_shows_paused && g_IsSuspended == icon_shows_suspended)))
  817         return; // it's already in the right state
  818     int icon;
  819     if (g->IsPaused && g_IsSuspended)
  820         icon = IDI_PAUSE_SUSPEND;
  821     else if (g->IsPaused)
  822         icon = IDI_PAUSE;
  823     else if (g_IsSuspended)
  824         icon = IDI_SUSPEND;
  825     else
  826         icon = IDI_MAIN;
  827     // Use the custom tray icon if the icon is normal (non-paused & non-suspended):
  828     mNIC.hIcon = (mCustomIconSmall && (mIconFrozen || (!g->IsPaused && !g_IsSuspended))) ? mCustomIconSmall // L17: Always use small icon for tray.
  829         : (icon == IDI_MAIN) ? g_IconSmall // Use the pre-loaded small icon for best quality.
  830         : (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_SHARED); // Use LR_SHARED for simplicity and performance more than to conserve memory in this case.
  831     if (Shell_NotifyIcon(NIM_MODIFY, &mNIC))
  832     {
  833         icon_shows_paused = g->IsPaused;
  834         icon_shows_suspended = g_IsSuspended;
  835     }
  836     // else do nothing, just leave it in the same state.
  837 }
  838 
  839 
  840 
  841 ResultType Script::AutoExecSection()
  842 // Returns FAIL if can't run due to critical error.  Otherwise returns OK.
  843 {
  844     // Now that g_MaxThreadsTotal has been permanently set by the processing of script directives like
  845     // #MaxThreads, an appropriately sized array can be allocated:
  846     if (   !(g_array = (global_struct *)malloc((g_MaxThreadsTotal+TOTAL_ADDITIONAL_THREADS) * sizeof(global_struct)))   )
  847         return FAIL; // Due to rarity, just abort. It wouldn't be safe to run ExitApp() due to possibility of an OnExit routine.
  848     CopyMemory(g_array, g, sizeof(global_struct)); // Copy the temporary/startup "g" into array[0] to preserve historical behaviors that may rely on the idle thread starting with that "g".
  849     g = g_array; // Must be done after above.
  850 
  851     // v1.0.48: Due to switching from SET_UNINTERRUPTIBLE_TIMER to IsInterruptible():
  852     // In spite of the comments in IsInterruptible(), periodically have a timer call IsInterruptible() due to
  853     // the following scenario:
  854     // - Interrupt timeout is 60 seconds (or 60 milliseconds for that matter).
  855     // - For some reason IsInterrupt() isn't called for 24+ hours even though there is a current/active thread.
  856     // - RefreshInterruptibility() fires at 23 hours and marks the thread interruptible.
  857     // - Sometime after that, one of the following happens:
  858     //      Computer is suspended/hibernated and stays that way for 50+ days.
  859     //      IsInterrupt() is never called (except by RefreshInterruptibility()) for 50+ days.
  860     //      (above is currently unlikely because MSG_FILTER_MAX calls IsInterruptible())
  861     // In either case, RefreshInterruptibility() has prevented the uninterruptibility duration from being
  862     // wrongly extended by up to 100% of g_script.mUninterruptibleTime.  This isn't a big deal if
  863     // g_script.mUninterruptibleTime is low (like it almost always is); but if it's fairly large, say an hour,
  864     // this can prevent an unwanted extension of up to 1 hour.
  865     // Although any call frequency less than 49.7 days should work, currently calling once per 23 hours
  866     // in case any older operating systems have a SetTimer() limit of less than 0x7FFFFFFF (and also to make
  867     // it less likely that a long suspend/hibernate would cause the above issue).  The following was
  868     // actually tested on Windows XP and a message does indeed arrive 23 hours after the script starts.
  869     SetTimer(g_hWnd, TIMER_ID_REFRESH_INTERRUPTIBILITY, 23*60*60*1000, RefreshInterruptibility); // 3rd param must not exceed 0x7FFFFFFF (2147483647; 24.8 days).
  870 
  871     ResultType ExecUntil_result;
  872 
  873     if (!mFirstLine) // In case it's ever possible to be empty.
  874         ExecUntil_result = OK;
  875         // And continue on to do normal exit routine so that the right ExitCode is returned by the program.
  876     else
  877     {
  878         // Choose a timeout that's a reasonable compromise between the following competing priorities:
  879         // 1) That we want hotkeys to be responsive as soon as possible after the program launches
  880         //    in case the user launches by pressing ENTER on a script, for example, and then immediately
  881         //    tries to use a hotkey.  In addition, we want any timed subroutines to start running ASAP
  882         //    because in rare cases the user might rely upon that happening.
  883         // 2) To support the case when the auto-execute section never finishes (such as when it contains
  884         //    an infinite loop to do background processing), yet we still want to allow the script
  885         //    to put custom defaults into effect globally (for things such as KeyDelay).
  886         // Obviously, the above approach has its flaws; there are ways to construct a script that would
  887         // result in unexpected behavior.  However, the combination of this approach with the fact that
  888         // the global defaults are updated *again* when/if the auto-execute section finally completes
  889         // raises the expectation of proper behavior to a very high level.  In any case, I'm not sure there
  890         // is any better approach that wouldn't break existing scripts or require a redesign of some kind.
  891         // If this method proves unreliable due to disk activity slowing the program down to a crawl during
  892         // the critical milliseconds after launch, one thing that might fix that is to have ExecUntil()
  893         // be forced to run a minimum of, say, 100 lines (if there are that many) before allowing the
  894         // timer expiration to have its effect.  But that's getting complicated and I'd rather not do it
  895         // unless someone actually reports that such a thing ever happens.  Still, to reduce the chance
  896         // of such a thing ever happening, it seems best to boost the timeout from 50 up to 100:
  897         SET_AUTOEXEC_TIMER(100);
  898         mAutoExecSectionIsRunning = true;
  899 
  900         // v1.0.25: This is now done here, closer to the actual execution of the first line in the script,
  901         // to avoid an unnecessary Sleep(10) that would otherwise occur in ExecUntil:
  902         mLastScriptRest = mLastPeekTime = GetTickCount();
  903 
  904         ++g_nThreads;
  905         DEBUGGER_STACK_PUSH(_T("Auto-execute"))
  906         ExecUntil_result = mFirstLine->ExecUntil(UNTIL_RETURN); // Might never return (e.g. infinite loop or ExitApp).
  907         DEBUGGER_STACK_POP()
  908         --g_nThreads;
  909         // Our caller will take care of setting g_default properly.
  910 
  911         KILL_AUTOEXEC_TIMER // See also: AutoExecSectionTimeout().
  912         mAutoExecSectionIsRunning = false;
  913     }
  914     // REMEMBER: The ExecUntil() call above will never return if the AutoExec section never finishes
  915     // (e.g. infinite loop) or it uses Exit/ExitApp.
  916 
  917     // Check if an exception has been thrown
  918     if (g->ThrownToken)
  919         g_script.FreeExceptionToken(g->ThrownToken);
  920 
  921     // The below is done even if AutoExecSectionTimeout() already set the values once.
  922     // This is because when the AutoExecute section finally does finish, by definition it's
  923     // supposed to store the global settings that are currently in effect as the default values.
  924     // In other words, the only purpose of AutoExecSectionTimeout() is to handle cases where
  925     // the AutoExecute section takes a long time to complete, or never completes (perhaps because
  926     // it is being used by the script as a "background thread" of sorts):
  927     // Save the values of KeyDelay, WinDelay etc. in case they were changed by the auto-execute part
  928     // of the script.  These new defaults will be put into effect whenever a new hotkey subroutine
  929     // is launched.  Each launched subroutine may then change the values for its own purposes without
  930     // affecting the settings for other subroutines:
  931     global_clear_state(*g);  // Start with a "clean slate" in both g_default and g (in case things like InitNewThread() check some of the values in g prior to launching a new thread).
  932 
  933     // Always want g_default.AllowInterruption==true so that InitNewThread()  doesn't have to
  934     // set it except when Critical or "Thread Interrupt" require it.  If the auto-execute section ended
  935     // without anyone needing to call IsInterruptible() on it, AllowInterruption could be false
  936     // even when Critical is off.
  937     // Even if the still-running AutoExec section has turned on Critical, the assignment below is still okay
  938     // because InitNewThread() adjusts AllowInterruption based on the value of ThreadIsCritical.
  939     // See similar code in AutoExecSectionTimeout().
  940     g->AllowThreadToBeInterrupted = true; // Mostly for the g_default line below. See comments above.
  941     CopyMemory(&g_default, g, sizeof(global_struct)); // g->IsPaused has been set to false higher above in case it's ever possible that it's true as a result of AutoExecSection().
  942     // After this point, the values in g_default should never be changed.
  943     global_maximize_interruptibility(*g); // See below.
  944     // Now that any changes made by the AutoExec section have been saved to g_default (including
  945     // the commands Critical and Thread), ensure that the very first g-item is always interruptible.
  946     // This avoids having to treat the first g-item as special in various places.
  947 
  948     // It seems best to set ErrorLevel to NONE after the auto-execute part of the script is done.
  949     // However, it isn't set to NONE right before launching each new thread (e.g. hotkey subroutine)
  950     // because it's more flexible that way (i.e. the user may want one hotkey subroutine to use the value
  951     // of ErrorLevel set by another).  This reset was also done by LoadFromFile(), but it is done again
  952     // here in case the auto-execute section changed it:
  953     g_ErrorLevel->Assign(ERRORLEVEL_NONE);
  954 
  955     // BEFORE DOING THE BELOW, "g" and "g_default" should be set up properly in case there's an OnExit
  956     // routine (even non-persistent scripts can have one).
  957     // If no hotkeys are in effect, the user hasn't requested a hook to be activated, and the script
  958     // doesn't contain the #Persistent directive we're done unless there is an OnExit subroutine and it
  959     // doesn't do "ExitApp":
  960     if (!IS_PERSISTENT) // Resolve macro again in case any of its components changed since the last time.
  961         g_script.ExitApp(ExecUntil_result == FAIL ? EXIT_ERROR : EXIT_EXIT);
  962 
  963     return OK;
  964 }
  965 
  966 
  967 
  968 ResultType Script::Edit()
  969 {
  970 #ifdef AUTOHOTKEYSC
  971     return OK; // Do nothing.
  972 #else
  973     // This is here in case a compiled script ever uses the Edit command.  Since the "Edit This
  974     // Script" menu item is not available for compiled scripts, it can't be called from there.
  975     TitleMatchModes old_mode = g->TitleMatchMode;
  976     g->TitleMatchMode = FIND_ANYWHERE;
  977     HWND hwnd = WinExist(*g, mFileName, _T(""), mMainWindowTitle, _T("")); // Exclude our own main window.
  978     g->TitleMatchMode = old_mode;
  979     if (hwnd)
  980     {
  981         TCHAR class_name[32];
  982         GetClassName(hwnd, class_name, _countof(class_name));
  983         if (!_tcscmp(class_name, _T("#32770")) || !_tcsnicmp(class_name, _T("AutoHotkey"), 10)) // MessageBox(), InputBox(), FileSelectFile(), or GUI/script-owned window.
  984             hwnd = NULL;  // Exclude it from consideration.
  985     }
  986     if (hwnd)  // File appears to already be open for editing, so use the current window.
  987         SetForegroundWindowEx(hwnd);
  988     else
  989     {
  990         TCHAR buf[T_MAX_PATH + 2]; // +2 for the two quote marks.
  991         // Enclose in double quotes anything that might contain spaces since the CreateProcess()
  992         // method, which is attempted first, is more likely to succeed.  This is because it uses
  993         // the command line method of creating the process, with everything all lumped together:
  994         sntprintf(buf, _countof(buf), _T("\"%s\""), mFileSpec);
  995         if (!ActionExec(_T("edit"), buf, mFileDir, false))  // Since this didn't work, try notepad.
  996         {
  997             // v1.0.40.06: Try to open .ini files first with their associated editor rather than trying the
  998             // "edit" verb on them:
  999             LPTSTR file_ext;
 1000             if (   !(file_ext = _tcsrchr(mFileName, '.')) || _tcsicmp(file_ext, _T(".ini"))
 1001                 || !ActionExec(_T("open"), buf, mFileDir, false)   ) // Relies on short-circuit boolean order.
 1002             {
 1003                 // Even though notepad properly handles filenames with spaces in them under WinXP,
 1004                 // even without double quotes around them, it seems safer and more correct to always
 1005                 // enclose the filename in double quotes for maximum compatibility with all OSes:
 1006                 if (!ActionExec(_T("notepad.exe"), buf, mFileDir, false))
 1007                     MsgBox(_T("Could not open script.")); // Short message since so rare.
 1008             }
 1009         }
 1010     }
 1011     return OK;
 1012 #endif
 1013 }
 1014 
 1015 
 1016 
 1017 ResultType Script::Reload(bool aDisplayErrors)
 1018 {
 1019     // The new instance we're about to start will tell our process to stop, or it will display
 1020     // a syntax error or some other error, in which case our process will still be running:
 1021 #ifdef AUTOHOTKEYSC
 1022     // This is here in case a compiled script ever uses the Reload command.  Since the "Reload This
 1023     // Script" menu item is not available for compiled scripts, it can't be called from there.
 1024     return g_script.ActionExec(mOurEXE, _T("/restart"), g_WorkingDirOrig, aDisplayErrors);
 1025 #else
 1026     TCHAR arg_string[T_MAX_PATH + 16];
 1027     sntprintf(arg_string, _countof(arg_string), _T("/restart \"%s\""), mFileSpec);
 1028     return g_script.ActionExec(mOurEXE, arg_string, g_WorkingDirOrig, aDisplayErrors);
 1029 #endif
 1030 }
 1031 
 1032 
 1033 
 1034 ResultType Script::ExitApp(ExitReasons aExitReason, int aExitCode)
 1035 // Normal exit (if aBuf is NULL), or a way to exit immediately on error (which is mostly
 1036 // for times when it would be unsafe to call MsgBox() due to the possibility that it would
 1037 // make the situation even worse).
 1038 {
 1039     mExitReason = aExitReason;
 1040     static bool sOnExitIsRunning = false, sExitAppShouldTerminate = true;
 1041     static int sExitCode;
 1042     if (sOnExitIsRunning || !mIsReadyToExecute)
 1043     {
 1044         // There is another instance of this function beneath us on the stack, executing an
 1045         // OnExit subroutine or function.  If a legacy OnExit sub is running, we still need
 1046         // to execute any other OnExit callbacks before exiting.  Otherwise ExitApp should
 1047         // terminate the app.  Causes of script exit other than ExitApp are expected to
 1048         // terminate the app immediately even if OnExit is running.
 1049         if (sExitAppShouldTerminate || aExitReason != EXIT_EXIT)
 1050             TerminateApp(aExitReason, aExitCode); // Exit early; don't run the OnExit callbacks (again).
 1051         if (*Line::sArgDeref[0]) // ExitApp with a parameter -- relies on the aExitReason check above.
 1052             sExitCode = aExitCode; // Override the previous exit code.
 1053         sExitAppShouldTerminate = true; // Signal our other instance that ExitApp was called.
 1054         return EARLY_EXIT; // Exit the thread (our other instance will call TerminateApp).
 1055         // MUST NOT create a new thread when sOnExitIsRunning because g_array allows only one
 1056         // extra thread for ExitApp() (which allows it to run even when MAX_THREADS_EMERGENCY
 1057         // has been reached).  See TOTAL_ADDITIONAL_THREADS for details.
 1058     }
 1059     sExitCode = aExitCode;
 1060 
 1061     // Otherwise, the script contains the special RunOnExit label that we will run here instead
 1062     // of exiting.  And since it does, we know that the script is in a ready-to-execute state
 1063     // because that is the only way an OnExit label could have been defined in the first place.
 1064     // Usually, the RunOnExit subroutine will contain an Exit or ExitApp statement
 1065     // which results in a recursive call to this function, but this is not required (e.g. the
 1066     // Exit subroutine could display an "Are you sure?" prompt, and if the user chooses "No",
 1067     // the Exit sequence can be aborted by simply not calling ExitApp and letting the thread
 1068     // we create below end normally).
 1069 
 1070     // Next, save the current state of the globals so that they can be restored just prior
 1071     // to returning to our caller:
 1072     TCHAR ErrorLevel_saved[ERRORLEVEL_SAVED_SIZE];
 1073     tcslcpy(ErrorLevel_saved, g_ErrorLevel->Contents(), _countof(ErrorLevel_saved)); // Save caller's errorlevel.
 1074     InitNewThread(0, true, true, ACT_INVALID); // Uninterruptibility is handled below. Since this special thread should always run, no checking of g_MaxThreadsTotal is done before calling this.
 1075 
 1076     // Turn on uninterruptibility to forbid any hotkeys, timers, or user defined menu items
 1077     // to interrupt.  This is mainly done for peace-of-mind (since possible interactions due to
 1078     // interruptions have not been studied) and the fact that this most users would not want this
 1079     // subroutine to be interruptible (it usually runs quickly anyway).  Another reason to make
 1080     // it non-interruptible is that some OnExit subroutines might destruct things used by the
 1081     // script's hotkeys/timers/menu items, and activating these items during the deconstruction
 1082     // would not be safe.  Finally, if a logoff or shutdown is occurring, it seems best to prevent
 1083     // timed subroutines from running -- which might take too much time and prevent the exit from
 1084     // occurring in a timely fashion.  An option can be added via the FutureUse param to make it
 1085     // interruptible if there is ever a demand for that.
 1086     // UPDATE: g_AllowInterruption is now used instead of g->AllowThreadToBeInterrupted for two reasons:
 1087     // 1) It avoids the need to do "int mUninterruptedLineCountMax_prev = g_script.mUninterruptedLineCountMax;"
 1088     //    (Disable this item so that ExecUntil() won't automatically make our new thread uninterruptible
 1089     //    after it has executed a certain number of lines).
 1090     // 2) Mostly obsolete: If the thread we're interrupting is uninterruptible, the uninterruptible timer
 1091     //    might be currently pending.  When it fires, it would make the OnExit subroutine interruptible
 1092     //    rather than the underlying subroutine.  The above fixes the first part of that problem.
 1093     //    The 2nd part is fixed by reinstating the timer when the uninterruptible thread is resumed.
 1094     //    This special handling is only necessary here -- not in other places where new threads are
 1095     //    created -- because OnExit is the only type of thread that can interrupt an uninterruptible
 1096     //    thread.
 1097     BOOL g_AllowInterruption_prev = g_AllowInterruption;  // Save current setting.
 1098     g_AllowInterruption = FALSE; // Mark the thread just created above as permanently uninterruptible (i.e. until it finishes and is destroyed).
 1099 
 1100     sOnExitIsRunning = true;
 1101     DEBUGGER_STACK_PUSH(_T("OnExit"))
 1102 
 1103     bool terminate_afterward = true; // Set default - see below for comments.
 1104     
 1105     // When a legacy OnExit label is present, the default behaviour is to exit the script only if
 1106     // it calls ExitApp.  Therefore to make OnExit() useful in a script which uses legacy OnExit,
 1107     // we need to prevent ExitApp from actually terminating the app:
 1108     sExitAppShouldTerminate = false;
 1109     // If the subroutine encounters a failure condition such as a runtime error, exit afterward.
 1110     // Otherwise, there will be no way to exit the script if the subroutine fails on each attempt.
 1111     if (mOnExitLabel && mOnExitLabel->Execute() && !sExitAppShouldTerminate)
 1112     {
 1113         // The subroutine completed normally and did not call ExitApp, so don't exit.
 1114         terminate_afterward = false;
 1115     }
 1116     sExitAppShouldTerminate = true;
 1117 
 1118     // If an OnExit label was called and didn't call ExitApp, terminate_afterward was set to false,
 1119     // so the script isn't exiting.  Otherwise, call the chain of OnExit functions:
 1120     if (terminate_afterward)
 1121     {
 1122         ExprTokenType param[] = { GetExitReasonString(aExitReason), (__int64)sExitCode };
 1123         if (mOnExit.Call(param, _countof(param), mOnExitLabel ? 0 : 1) == CONDITION_TRUE)
 1124             terminate_afterward = false; // A handler returned true to prevent exit.
 1125     }
 1126     
 1127     DEBUGGER_STACK_POP()
 1128     sOnExitIsRunning = false;  // In case the user wanted the thread to end normally (see above).
 1129 
 1130     if (terminate_afterward || EXITREASON_MUST_EXIT(aExitReason))
 1131         TerminateApp(aExitReason, aExitCode);
 1132 
 1133     // Otherwise:
 1134     ResumeUnderlyingThread(ErrorLevel_saved);
 1135     g_AllowInterruption = g_AllowInterruption_prev;  // Restore original setting.
 1136 
 1137     return EARLY_EXIT;
 1138 }
 1139 
 1140 
 1141 
 1142 void Script::TerminateApp(ExitReasons aExitReason, int aExitCode)
 1143 // Note that g_script's destructor takes care of most other cleanup work, such as destroying
 1144 // tray icons, menus, and unowned windows such as ToolTip.
 1145 {
 1146     // L31: Release objects stored in variables, where possible.
 1147     if (aExitReason != EXIT_CRITICAL) // i.e. Avoid making matters worse if EXIT_CRITICAL.
 1148     {
 1149         // Ensure the current thread is not paused and can't be interrupted
 1150         // in case one or more objects need to call a __delete meta-function.
 1151         g_AllowInterruption = FALSE;
 1152         g->IsPaused = false;
 1153 
 1154         int v, i;
 1155         for (v = 0; v < mVarCount; ++v)
 1156             if (mVar[v]->IsObject())
 1157                 mVar[v]->ReleaseObject();
 1158         for (v = 0; v < mLazyVarCount; ++v)
 1159             if (mLazyVar[v]->IsObject())
 1160                 mLazyVar[v]->ReleaseObject();
 1161         for (i = 0; i < mFuncCount; ++i)
 1162         {
 1163             Func &f = *mFunc[i];
 1164             if (f.mIsBuiltIn)
 1165                 continue;
 1166             // Since it doesn't seem feasible to release all var backups created by recursive function
 1167             // calls and all tokens in the 'stack' of each currently executing expression, currently
 1168             // only static and global variables are released.  It seems best for consistency to also
 1169             // avoid releasing top-level non-static local variables (i.e. which aren't in var backups).
 1170             for (v = 0; v < f.mVarCount; ++v)
 1171                 if (f.mVar[v]->IsStatic() && f.mVar[v]->IsObject()) // For consistency, only free static vars (see above).
 1172                     f.mVar[v]->ReleaseObject();
 1173             for (v = 0; v < f.mLazyVarCount; ++v)
 1174                 if (f.mLazyVar[v]->IsStatic() && f.mLazyVar[v]->IsObject())
 1175                     f.mLazyVar[v]->ReleaseObject();
 1176         }
 1177     }
 1178 #ifdef CONFIG_DEBUGGER // L34: Exit debugger *after* the above to allow debugging of any invoked __Delete handlers.
 1179     g_Debugger.Exit(aExitReason);
 1180 #endif
 1181 
 1182     // We call DestroyWindow() because MainWindowProc() has left that up to us.
 1183     // DestroyWindow() will cause MainWindowProc() to immediately receive and process the
 1184     // WM_DESTROY msg, which should in turn result in any child windows being destroyed
 1185     // and other cleanup being done:
 1186     if (IsWindow(g_hWnd)) // Adds peace of mind in case WM_DESTROY was already received in some unusual way.
 1187     {
 1188         g_DestroyWindowCalled = true;
 1189         DestroyWindow(g_hWnd);
 1190     }
 1191     Hotkey::AllDestructAndExit(aExitCode);
 1192 }
 1193 
 1194 
 1195 
 1196 UINT Script::LoadFromFile()
 1197 // Returns the number of non-comment lines that were loaded, or LOADING_FAILED on error.
 1198 {
 1199     mNoHotkeyLabels = true;  // Indicate that there are no hotkey labels, since we're (re)loading the entire file.
 1200     mIsReadyToExecute = mAutoExecSectionIsRunning = false;
 1201     if (!mFileSpec || !*mFileSpec) return LOADING_FAILED;
 1202 
 1203 #ifndef AUTOHOTKEYSC  // When not in stand-alone mode, read an external script file.
 1204     DWORD attr = g_RunStdIn ? 0 : GetFileAttributes(mFileSpec); // v1.1.17: Don't check if reading script from stdin.
 1205     if (attr == MAXDWORD) // File does not exist or lacking the authorization to get its attributes.
 1206     {
 1207         TCHAR buf[T_MAX_PATH + 24];
 1208         sntprintf(buf, _countof(buf), _T("Script file not found:\n%s"), mFileSpec);
 1209         MsgBox(buf, MB_ICONHAND);
 1210         return 0;
 1211     }
 1212 #endif
 1213 
 1214     // v1.0.42: Placeholder to use in place of a NULL label to simplify code in some places.
 1215     // This must be created before loading the script because it's relied upon when creating
 1216     // hotkeys to provide an alternative to having a NULL label. It will be given a non-NULL
 1217     // mJumpToLine further down.
 1218     if (   !(mPlaceholderLabel = new Label(_T("")))   ) // Not added to linked list since it's never looked up.
 1219         return LOADING_FAILED;
 1220 
 1221     // L4: Changed this next section to support lines added for #if (expression).
 1222     // Each #if (expression) is pre-parsed *before* the main script in order for
 1223     // function library auto-inclusions to be processed correctly.
 1224 
 1225     // Load the main script file.  This will also load any files it includes with #Include.
 1226     if (   LoadIncludedFile(g_RunStdIn ? _T("*") : mFileSpec, false, false) != OK
 1227         || !AddLine(ACT_EXIT)) // Add an Exit to ensure lib auto-includes aren't auto-executed, for backward compatibility.
 1228         return LOADING_FAILED;
 1229     mLastLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;
 1230 
 1231     if (!PreparseExpressions(mFirstLine))
 1232         return LOADING_FAILED; // Error was already displayed by the above call.
 1233     // ABOVE: In v1.0.47, the above may have auto-included additional files from the userlib/stdlib.
 1234     // That's why the above is done prior to adding the EXIT lines and other things below.
 1235 
 1236     // Preparse static initializers and #if expressions.
 1237     PreparseStaticLines(mFirstLine);
 1238     if (mFirstStaticLine)
 1239     {
 1240         // Prepend all Static initializers to the beginning of the auto-execute section.
 1241         mLastStaticLine->mNextLine = mFirstLine;
 1242         mFirstLine->mPrevLine = mLastStaticLine;
 1243         mFirstLine = mFirstStaticLine;
 1244     }
 1245     
 1246     // Scan for undeclared local variables which are named the same as a global variable.
 1247     // This loop has two purposes (but it's all handled in PreprocessLocalVars()):
 1248     //
 1249     //  1) Allow super-global variables to be referenced above the point of declaration.
 1250     //     This is a bit of a hack to work around the fact that variable references are
 1251     //     resolved as they are encountered, before all declarations have been processed.
 1252     //
 1253     //  2) Warn the user (if appropriate) since they probably meant it to be global.
 1254     //
 1255     for (int i = 0; i < mFuncCount; ++i)
 1256     {
 1257         Func &func = *mFunc[i];
 1258         if (!func.mIsBuiltIn && !(func.mDefaultVarType & VAR_FORCE_LOCAL))
 1259         {
 1260             PreprocessLocalVars(func, func.mVar, func.mVarCount);
 1261             PreprocessLocalVars(func, func.mLazyVar, func.mLazyVarCount);
 1262         }
 1263     }
 1264 
 1265     // Resolve any unresolved base classes.
 1266     if (mUnresolvedClasses)
 1267     {
 1268         if (!ResolveClasses())
 1269             return LOADING_FAILED;
 1270         mUnresolvedClasses->Release();
 1271         mUnresolvedClasses = NULL;
 1272     }
 1273 
 1274     // Check for classes potentially being overwritten.
 1275     if (g_Warn_ClassOverwrite)
 1276         CheckForClassOverwrite();
 1277 
 1278 #ifndef AUTOHOTKEYSC
 1279     if (mIncludeLibraryFunctionsThenExit)
 1280     {
 1281         delete mIncludeLibraryFunctionsThenExit;
 1282         return 0; // Tell our caller to do a normal exit.
 1283     }
 1284 #endif
 1285 
 1286     // v1.0.35.11: Restore original working directory so that changes made to it by the above (via
 1287     // "#Include C:\Scripts" or "#Include %A_ScriptDir%" or even stdlib/userlib) do not affect the
 1288     // script's runtime working directory.  This preserves the flexibility of having a startup-determined
 1289     // working directory for the script's runtime (i.e. it seems best that the mere presence of
 1290     // "#Include NewDir" should not entirely eliminate this flexibility).
 1291     SetCurrentDirectory(g_WorkingDirOrig); // g_WorkingDirOrig previously set by WinMain().
 1292 
 1293     // Rather than do this, which seems kinda nasty if ever someday support same-line
 1294     // else actions such as "else return", just add two EXITs to the end of every script.
 1295     // That way, if the first EXIT added accidentally "corrects" an actionless ELSE
 1296     // or IF, the second one will serve as the anchoring end-point (mRelatedLine) for that
 1297     // IF or ELSE.  In other words, since we never want mRelatedLine to be NULL, this should
 1298     // make absolutely sure of that:
 1299     //if (mLastLine->mActionType == ACT_ELSE ||
 1300     //  ACT_IS_IF(mLastLine->mActionType)
 1301     //  ...
 1302     // Second ACT_EXIT: even if the last line of the script is already "exit", always add
 1303     // another one in case the script ends in a label.  That way, every label will have
 1304     // a non-NULL target, which simplifies other aspects of script execution.
 1305     // Making sure that all scripts end with an EXIT ensures that if the script
 1306     // file ends with ELSEless IF or an ELSE, that IF's or ELSE's mRelatedLine
 1307     // will be non-NULL, which further simplifies script execution.
 1308     // Not done since it's number doesn't much matter: ++mCombinedLineNumber;
 1309     ++mCombinedLineNumber;  // So that the EXITs will both show up in ListLines as the line # after the last physical one in the script.
 1310     if (!(AddLine(ACT_EXIT) && AddLine(ACT_EXIT))) // Second exit guaranties non-NULL mRelatedLine(s).
 1311         return LOADING_FAILED;
 1312     mLastLine->mPrevLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;
 1313     mLastLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;
 1314     mPlaceholderLabel->mJumpToLine = mLastLine; // To follow the rule "all labels should have a non-NULL line before the script starts running".
 1315 
 1316     if (   !PreparseBlocks(mFirstLine)
 1317         || !PreparseCommands(mFirstLine)   )
 1318         return LOADING_FAILED; // Error was already displayed by the above calls.
 1319 
 1320     // Use FindOrAdd, not Add, because the user may already have added it simply by
 1321     // referring to it in the script:
 1322     if (   !(g_ErrorLevel = FindOrAddVar(_T("ErrorLevel")))   )
 1323         return LOADING_FAILED; // Error.  Above already displayed it for us.
 1324     // Initialize the var state to zero right before running anything in the script:
 1325     g_ErrorLevel->Assign(ERRORLEVEL_NONE);
 1326 
 1327     // Initialize the random number generator:
 1328     // Note: On 32-bit hardware, the generator module uses only 2506 bytes of static
 1329     // data, so it doesn't seem worthwhile to put it in a class (so that the mem is
 1330     // only allocated on first use of the generator).  For v1.0.24, _ftime() is not
 1331     // used since it could be as large as 0.5 KB of non-compressed code.  A simple call to
 1332     // GetSystemTimeAsFileTime() seems just as good or better, since it produces
 1333     // a FILETIME, which is "the number of 100-nanosecond intervals since January 1, 1601."
 1334     // Use the low-order DWORD since the high-order one rarely changes.  If my calculations are correct,
 1335     // the low-order 32-bits traverses its full 32-bit range every 7.2 minutes, which seems to make
 1336     // using it as a seed superior to GetTickCount for most purposes.
 1337     RESEED_RANDOM_GENERATOR;
 1338 
 1339     return TRUE; // Must be non-zero.
 1340     // OBSOLETE: mLineCount was always non-zero at this point since above did AddLine().
 1341     //return mLineCount; // The count of runnable lines that were loaded, which might be zero.
 1342 }
 1343 
 1344 
 1345 
 1346 bool IsFunction(LPTSTR aBuf, bool *aPendingFunctionHasBrace = NULL)
 1347 // Helper function for LoadIncludedFile().
 1348 // Caller passes in an aBuf containing a candidate line such as "function(x, y)"
 1349 // Caller has ensured that aBuf is rtrim'd.
 1350 // Caller should pass NULL for aPendingFunctionHasBrace to indicate that function definitions (open-brace
 1351 // on same line as function) are not allowed.  When non-NULL *and* aBuf is a function call/def,
 1352 // *aPendingFunctionHasBrace is set to true if a brace is present at the end, or false otherwise.
 1353 // In addition, any open-brace is removed from aBuf in this mode.
 1354 {
 1355     LPTSTR action_end = StrChrAny(aBuf, EXPR_ALL_SYMBOLS EXPR_ILLEGAL_CHARS);
 1356     // Can't be a function definition or call without an open-parenthesis as first char found by the above.
 1357     // In addition, if action_end isn't NULL, that confirms that the string in aBuf prior to action_end contains
 1358     // no spaces, tabs, colons, or equal-signs.  As a result, it can't be:
 1359     // 1) a hotstring, since they always start with at least one colon that would be caught immediately as 
 1360     //    first-expr-char-is-not-open-parenthesis by the above.
 1361     // 2) Any kind of math or assignment, such as var:=(x+y) or var+=(x+y).
 1362     // The only things it could be other than a function call or function definition are:
 1363     // Normal label that ends in single colon but contains an open-parenthesis prior to the colon, e.g. Label(x):
 1364     // Single-line hotkey such as KeyName::MsgBox.  But since '(' isn't valid inside KeyName, this isn't a concern.
 1365     // In addition, note that it isn't necessary to check for colons that lie outside of quoted strings because
 1366     // we're only interested in the first "word" of aBuf: If this is indeed a function call or definition, what
 1367     // lies to the left of its first open-parenthesis can't contain any colons anyway because the above would
 1368     // have caught it as first-expr-char-is-not-open-parenthesis.  In other words, there's no way for a function's
 1369     // opening parenthesis to occur after a legitimate/quoted colon or double-colon in its parameters.
 1370     // v1.0.40.04: Added condition "action_end != aBuf" to allow a hotkey or remap or hotkey such as
 1371     // such as "(::" to work even if it ends in a close-parenthesis such as "(::)" or "(::MsgBox )"
 1372     if (   !(action_end && *action_end == '(' && action_end != aBuf
 1373         && tcslicmp(aBuf, _T("IF"), action_end - aBuf)
 1374         && tcslicmp(aBuf, _T("WHILE"), action_end - aBuf)) // v1.0.48.04: Recognize While() as loop rather than a function because many programmers are in the habit of writing while() and if().
 1375         || action_end[1] == ':'   ) // v1.0.44.07: This prevents "$(::fn_call()" from being seen as a function-call vs. hotkey-with-call.  For simplicity and due to rarity, omit_leading_whitespace() isn't called; i.e. assumes that the colon immediate follows the '('.
 1376         return false;
 1377     LPTSTR aBuf_last_char = action_end + _tcslen(action_end) - 1; // Above has already ensured that action_end is "(...".
 1378     if (aPendingFunctionHasBrace) // Caller specified that an optional open-brace may be present at the end of aBuf.
 1379     {
 1380         if (*aPendingFunctionHasBrace = (*aBuf_last_char == '{')) // Caller has ensured that aBuf is rtrim'd.
 1381         {
 1382             *aBuf_last_char = '\0'; // For the caller, remove it from further consideration.
 1383             aBuf_last_char = aBuf + rtrim(aBuf, aBuf_last_char - aBuf) - 1; // Omit trailing whitespace too.
 1384         }
 1385     }
 1386     return *aBuf_last_char == ')'; // This last check avoids detecting a label such as "Label(x):" as a function.
 1387     // Also, it seems best never to allow if(...) to be a function call, even if it's blank inside such as if().
 1388     // In addition, it seems best not to allow if(...) to ever be a function definition since such a function
 1389     // could never be called as ACT_EXPRESSION since it would be seen as an IF-stmt instead.
 1390 }
 1391 
 1392 
 1393 
 1394 inline LPTSTR IsClassDefinition(LPTSTR aBuf, bool &aHasOTB)
 1395 {
 1396     if (_tcsnicmp(aBuf, _T("Class"), 5) || !IS_SPACE_OR_TAB(aBuf[5])) // i.e. it's not "Class" followed by a space or tab.
 1397         return NULL;
 1398     LPTSTR class_name = omit_leading_whitespace(aBuf + 6);
 1399     if (_tcschr(EXPR_ALL_SYMBOLS EXPR_ILLEGAL_CHARS, *class_name))
 1400         // It's probably something like "Class := GetClass()".
 1401         return NULL;
 1402     // Check for opening brace on same line:
 1403     LPTSTR aBuf_last_char = class_name + _tcslen(class_name) - 1;
 1404     if (aHasOTB = (*aBuf_last_char == '{')) // Caller has ensured that aBuf is rtrim'd.
 1405     {
 1406         *aBuf_last_char = '\0'; // For the caller, remove it from further consideration.
 1407         rtrim(aBuf, aBuf_last_char - aBuf); // Omit trailing whitespace too.
 1408     }
 1409     // Validation of the name is left up to the caller, for simplicity.
 1410     return class_name;
 1411 }
 1412 
 1413 
 1414 
 1415 ResultType Script::OpenIncludedFile(TextStream &ts, LPTSTR aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure)
 1416 // Open the included file.  Returns CONDITION_TRUE if the file is to
 1417 // be loaded, otherwise OK (duplicate/already loaded) or FAIL (error).
 1418 // See "full_path" below for why this is separate to LoadIncludedFile().  
 1419 {
 1420 #ifndef AUTOHOTKEYSC
 1421     if (!aFileSpec || !*aFileSpec) return FAIL;
 1422 
 1423     if (Line::sSourceFileCount >= Line::sMaxSourceFiles)
 1424     {
 1425         if (Line::sSourceFileCount >= ABSOLUTE_MAX_SOURCE_FILES)
 1426             return ScriptError(_T("Too many includes.")); // Short msg since so rare.
 1427         int new_max;
 1428         if (Line::sMaxSourceFiles)
 1429         {
 1430             new_max = 2*Line::sMaxSourceFiles;
 1431             if (new_max > ABSOLUTE_MAX_SOURCE_FILES)
 1432                 new_max = ABSOLUTE_MAX_SOURCE_FILES;
 1433         }
 1434         else
 1435             new_max = 100;
 1436         // For simplicity and due to rarity of every needing to, expand by reallocating the array.
 1437         // Use a temp var. because realloc() returns NULL on failure but leaves original block allocated.
 1438         LPTSTR *realloc_temp = (LPTSTR *)realloc(Line::sSourceFile, new_max * sizeof(LPTSTR)); // If passed NULL, realloc() will do a malloc().
 1439         if (!realloc_temp)
 1440             return ScriptError(ERR_OUTOFMEM); // Short msg since so rare.
 1441         Line::sSourceFile = realloc_temp;
 1442         Line::sMaxSourceFiles = new_max;
 1443     }
 1444 
 1445     // Use of stack memory here to build the full path is the most efficient method,
 1446     // but utilizes 64KB per buffer on Unicode builds.  There is virtually no cost
 1447     // when used here, but if used directly in LoadIncludedFile(), this would mean
 1448     // 64KB used *for each instance on the stack*, which significantly reduces the
 1449     // recursion limit for #include inside #include.  Note that enclosing the buf
 1450     // within a limited scope is insufficient, as the compiler will (or may) still
 1451     // allocate the required stack space on entry to the function.
 1452     TCHAR full_path[T_MAX_PATH];
 1453 
 1454     int source_file_index = Line::sSourceFileCount;
 1455     if (!source_file_index)
 1456         // Since this is the first source file, it must be the main script file.  Just point it to the
 1457         // location of the filespec already dynamically allocated:
 1458         Line::sSourceFile[source_file_index] = mFileSpec;
 1459     else
 1460     {
 1461         // Get the full path in case aFileSpec has a relative path.  This is done so that duplicates
 1462         // can be reliably detected (we only want to avoid including a given file more than once):
 1463         LPTSTR filename_marker;
 1464         GetFullPathName(aFileSpec, _countof(full_path), full_path, &filename_marker);
 1465         // Check if this file was already included.  If so, it's not an error because we want
 1466         // to support automatic "include once" behavior.  So just ignore repeats:
 1467         if (!aAllowDuplicateInclude)
 1468             for (int f = 0; f < source_file_index; ++f) // Here, source_file_index==Line::sSourceFileCount
 1469                 if (!lstrcmpi(Line::sSourceFile[f], full_path)) // Case insensitive like the file system (testing shows that "Ä" == "ä" in the NTFS, which is hopefully how lstrcmpi works regardless of locale).
 1470                     return OK;
 1471         // The file is added to the list further below, after the file has been opened, in case the
 1472         // opening fails and aIgnoreLoadFailure==true.
 1473     }
 1474 
 1475     if (!ts.Open(aFileSpec, DEFAULT_READ_FLAGS, g_DefaultScriptCodepage))
 1476     {
 1477         if (aIgnoreLoadFailure)
 1478             return OK;
 1479         TCHAR msg_text[T_MAX_PATH + 64]; // T_MAX_PATH vs. MAX_PATH because the full length could be utilized with ErrorStdOut.
 1480         sntprintf(msg_text, _countof(msg_text), _T("%s file \"%s\" cannot be opened.")
 1481             , source_file_index ? _T("#Include") : _T("Script"), aFileSpec);
 1482         return ScriptError(msg_text);
 1483     }
 1484 
 1485     // This is done only after the file has been successfully opened in case aIgnoreLoadFailure==true:
 1486     if (source_file_index > 0)
 1487         if (  !(Line::sSourceFile[source_file_index] = SimpleHeap::Malloc(full_path))  )
 1488             return ScriptError(ERR_OUTOFMEM);
 1489     //else the first file was already taken care of by another means.
 1490 
 1491 #else // Stand-alone mode (there are no include files in this mode since all of them were merged into the main script at the time of compiling).
 1492 
 1493     TextMem::Buffer textbuf(NULL, 0, false);
 1494 
 1495     HRSRC hRes;
 1496     HGLOBAL hResData;
 1497 
 1498 #ifdef _DEBUG
 1499     if (hRes = FindResource(NULL, _T("AHK"), RT_RCDATA))
 1500 #else
 1501     if (hRes = FindResource(NULL, _T(">AUTOHOTKEY SCRIPT<"), RT_RCDATA))
 1502 #endif
 1503     {}
 1504     else if (hRes = FindResource(NULL, _T(">AHK WITH ICON<"), RT_RCDATA))
 1505     {}
 1506     
 1507     if ( !( hRes 
 1508             && (textbuf.mLength = SizeofResource(NULL, hRes))
 1509             && (hResData = LoadResource(NULL, hRes))
 1510             && (textbuf.mBuffer = LockResource(hResData)) ) )
 1511     {
 1512         MsgBox(_T("Could not extract script from EXE."), 0, aFileSpec);
 1513         return FAIL;
 1514     }
 1515 
 1516     // NOTE: Ahk2Exe strips off the UTF-8 BOM.
 1517     ts.Open(textbuf, TextStream::READ | TextStream::EOL_CRLF | TextStream::EOL_ORPHAN_CR, CP_UTF8);
 1518 
 1519     // Since this is a compiled script, there is only one script file.
 1520     // Just point it to the location of the filespec already dynamically allocated:
 1521     Line::sSourceFile[0] = mFileSpec;
 1522 
 1523 #endif
 1524     
 1525     // Since above did not continue, proceed with loading the file.
 1526     ++Line::sSourceFileCount;
 1527     return CONDITION_TRUE;
 1528 }
 1529 
 1530 
 1531 
 1532 ResultType Script::LoadIncludedFile(LPTSTR aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure)
 1533 // Returns OK or FAIL.
 1534 {
 1535 #ifndef AUTOHOTKEYSC
 1536     TextFile ts;
 1537 #else
 1538     TextMem ts;
 1539 #endif
 1540 
 1541     ResultType result = OpenIncludedFile(ts, aFileSpec, aAllowDuplicateInclude, aIgnoreLoadFailure);
 1542     if (result != CONDITION_TRUE)
 1543         return result; // OK or FAIL.
 1544 
 1545     // Off-loading to another function significantly reduces code size, perhaps because
 1546     // the TextFile/TextMem destructor is called from fewer places (each "return"):
 1547     return LoadIncludedFile(&ts);
 1548 }
 1549 
 1550 
 1551 
 1552 ResultType Script::LoadIncludedFile(TextStream *fp)
 1553 // Returns OK or FAIL.
 1554 {
 1555     // Keep this var on the stack due to recursion, which allows newly created lines to be given the
 1556     // correct file number even when some #include's have been encountered in the middle of the script:
 1557     int source_file_index = Line::sSourceFileCount - 1;
 1558 
 1559     // <buf> should be no larger than LINE_SIZE because some later functions rely upon that:
 1560     TCHAR buf1[LINE_SIZE], buf2[LINE_SIZE], suffix[16], pending_buf[LINE_SIZE];
 1561     *pending_buf = '\0';
 1562     LPTSTR buf = buf1, next_buf = buf2; // Oscillate between bufs to improve performance (avoids memcpy from buf2 to buf1).
 1563     size_t buf_length, next_buf_length, suffix_length;
 1564     bool pending_buf_has_brace;
 1565     enum {
 1566         Pending_Func,
 1567         Pending_Class,
 1568         Pending_Property
 1569     } pending_buf_type;
 1570 
 1571     // File is now open, read lines from it.
 1572 
 1573     LPTSTR hotkey_flag, cp, cp1, hotstring_start, hotstring_options;
 1574     Hotkey *hk;
 1575     LineNumberType pending_buf_line_number, saved_line_number;
 1576     HookActionType hook_action;
 1577     bool is_label, suffix_has_tilde, hook_is_mandatory, in_comment_section, hotstring_options_all_valid, hotstring_execute;
 1578     ResultType hotkey_validity;
 1579 
 1580     // For the remap mechanism, e.g. a::b
 1581     int remap_stage;
 1582     vk_type remap_source_vk, remap_dest_vk = 0; // Only dest is initialized to enforce the fact that it is the flag/signal to indicate whether remapping is in progress.
 1583     TCHAR remap_source[32], remap_dest[32], remap_dest_modifiers[8]; // Must fit the longest key name (currently Browser_Favorites [17]), but buffer overflow is checked just in case.
 1584     LPTSTR extra_event;
 1585     bool remap_source_is_combo, remap_source_is_mouse, remap_dest_is_mouse, remap_keybd_to_mouse;
 1586 
 1587     // For the line continuation mechanism:
 1588     bool do_ltrim, do_rtrim, literal_escapes, literal_derefs, literal_delimiters
 1589         , has_continuation_section, is_continuation_line;
 1590     #define CONTINUATION_SECTION_WITHOUT_COMMENTS 1 // MUST BE 1 because it's the default set by anything that's boolean-true.
 1591     #define CONTINUATION_SECTION_WITH_COMMENTS    2 // Zero means "not in a continuation section".
 1592     int in_continuation_section;
 1593 
 1594     LPTSTR next_option, option_end;
 1595     TCHAR orig_char, one_char_string[2], two_char_string[3]; // Line continuation mechanism's option parsing.
 1596     one_char_string[1] = '\0';  // Pre-terminate these to simplify code later below.
 1597     two_char_string[2] = '\0';  //
 1598     int continuation_line_count;
 1599 
 1600     #define MAX_FUNC_VAR_GLOBALS 2000
 1601     Var *func_global_var[MAX_FUNC_VAR_GLOBALS];
 1602 
 1603     // Init both for main file and any included files loaded by this function:
 1604     mCurrFileIndex = source_file_index;  // source_file_index is kept on the stack due to recursion (from #include).
 1605 
 1606 #ifdef AUTOHOTKEYSC
 1607     // -1 (MAX_UINT in this case) to compensate for the fact that there is a comment containing
 1608     // the version number added to the top of each compiled script:
 1609     LineNumberType phys_line_number = -1;
 1610 #else
 1611     LineNumberType phys_line_number = 0;
 1612 #endif
 1613     buf_length = GetLine(buf, LINE_SIZE - 1, 0, fp);
 1614 
 1615     if (in_comment_section = !_tcsncmp(buf, _T("/*"), 2))
 1616     {
 1617         // Fixed for v1.0.35.08. Must reset buffer to allow a script's first line to be "/*".
 1618         *buf = '\0';
 1619         buf_length = 0;
 1620     }
 1621 
 1622     while (buf_length != -1)  // Compare directly to -1 since length is unsigned.
 1623     {
 1624         // For each whole line (a line with continuation section is counted as only a single line
 1625         // for the purpose of this outer loop).
 1626 
 1627         // Keep track of this line's *physical* line number within its file for A_LineNumber and
 1628         // error reporting purposes.  This must be done only in the outer loop so that it tracks
 1629         // the topmost line of any set of lines merged due to continuation section/line(s)..
 1630         mCombinedLineNumber = phys_line_number + 1;
 1631 
 1632         // This must be reset for each iteration because a prior iteration may have changed it, even
 1633         // indirectly by calling something that changed it:
 1634         mCurrLine = NULL;  // To signify that we're in transition, trying to load a new one.
 1635 
 1636         // v1.0.44.13: An additional call to IsDirective() is now made up here so that #CommentFlag affects
 1637         // the line beneath it the same way as other lines (#EscapeChar et. al. didn't have this bug).
 1638         // It's best not to process ALL directives up here because then they would no longer support a
 1639         // continuation section beneath them (and possibly other drawbacks because it was never thoroughly
 1640         // tested).
 1641         if (!_tcsnicmp(buf, _T("#CommentFlag"), 12)) // Have IsDirective() process this now (it will also process it again later, which is harmless).
 1642             if (IsDirective(buf) == FAIL) // IsDirective() already displayed the error.
 1643                 return FAIL;
 1644 
 1645         // Read in the next line (if that next line is the start of a continuation section, append
 1646         // it to the line currently being processed:
 1647         for (has_continuation_section = false, in_continuation_section = 0;;)
 1648         {
 1649             // This increment relies on the fact that this loop always has at least one iteration:
 1650             ++phys_line_number; // Tracks phys. line number in *this* file (independent of any recursion caused by #Include).
 1651             next_buf_length = GetLine(next_buf, LINE_SIZE - 1, in_continuation_section, fp);
 1652             if (next_buf_length && next_buf_length != -1 // Prevents infinite loop when file ends with an unclosed "/*" section.  Compare directly to -1 since length is unsigned.
 1653                 && !in_continuation_section) // Multi-line comments can't be used in continuation sections. This line fixes '*/' being discarded in continuation sections (broken by L54).
 1654             {
 1655                 if (!_tcsncmp(next_buf, _T("*/"), 2) // Check this even if !in_comment_section so it can be ignored (for convenience) and not treated as a line-continuation operator.
 1656                     && (in_comment_section || next_buf[2] != ':' || next_buf[3] != ':')) // ...but support */:: as a hotkey.
 1657                 {
 1658                     in_comment_section = false;
 1659                     next_buf_length -= 2; // Adjust for removal of /* from the beginning of the string.
 1660                     tmemmove(next_buf, next_buf + 2, next_buf_length + 1);  // +1 to include the string terminator.
 1661                     next_buf_length = ltrim(next_buf, next_buf_length); // Get rid of any whitespace that was between the comment-end and remaining text.
 1662                     if (!*next_buf) // The rest of the line is empty, so it was just a naked comment-end.
 1663                         continue;
 1664                 }
 1665                 else if (in_comment_section)
 1666                     continue;
 1667 
 1668                 if (!_tcsncmp(next_buf, _T("/*"), 2))
 1669                 {
 1670                     in_comment_section = true;
 1671                     continue; // It's now commented out, so the rest of this line is ignored.
 1672                 }
 1673             }
 1674 
 1675             if (in_comment_section) // Above has incremented and read the next line, which is everything needed while inside /* .. */
 1676             {
 1677                 if (next_buf_length == -1) // Compare directly to -1 since length is unsigned.
 1678                     break; // By design, it's not an error.  This allows "/*" to be used to comment out the bottommost portion of the script without needing a matching "*/".
 1679                 // Otherwise, continue reading lines so that they can be merged with the line above them
 1680                 // if they qualify as continuation lines.
 1681                 continue;
 1682             }
 1683 
 1684             if (!in_continuation_section) // This is either the first iteration or the line after the end of a previous continuation section.
 1685             {
 1686                 // v1.0.38.06: The following has been fixed to exclude "(:" and "(::".  These should be
 1687                 // labels/hotkeys, not the start of a continuation section.  In addition, a line that starts
 1688                 // with '(' but that ends with ':' should be treated as a label because labels such as
 1689                 // "(label):" are far more common than something obscure like a continuation section whose
 1690                 // join character is colon, namely "(Join:".
 1691                 if (   !(in_continuation_section = (next_buf_length != -1 && *next_buf == '(' // Compare directly to -1 since length is unsigned.
 1692                     && next_buf[1] != ':' && next_buf[next_buf_length - 1] != ':'))   ) // Relies on short-circuit boolean order.
 1693                 {
 1694                     if (next_buf_length == -1)  // Compare directly to -1 since length is unsigned.
 1695                         break;
 1696                     if (!next_buf_length)
 1697                         // It is permitted to have blank lines and comment lines in between the line above
 1698                         // and any continuation section/line that might come after the end of the
 1699                         // comment/blank lines:
 1700                         continue;
 1701                     // SINCE ABOVE DIDN'T BREAK/CONTINUE, NEXT_BUF IS NON-BLANK.
 1702                     if (next_buf[next_buf_length - 1] == ':' && *next_buf != ',')
 1703                         // With the exception of lines starting with a comma, the last character of any
 1704                         // legitimate continuation line can't be a colon because expressions can't end
 1705                         // in a colon. The only exception is the ternary operator's colon, but that is
 1706                         // very rare because it requires the line after it also be a continuation line
 1707                         // or section, which is unusual to say the least -- so much so that it might be
 1708                         // too obscure to even document as a known limitation.  Anyway, by excluding lines
 1709                         // that end with a colon from consideration ambiguity with normal labels
 1710                         // and non-single-line hotkeys and hotstrings is eliminated.
 1711                         break;
 1712 
 1713                     is_continuation_line = false; // Set default.
 1714                     switch(ctoupper(*next_buf)) // Above has ensured *next_buf != '\0' (toupper might have problems with '\0').
 1715                     {
 1716                     case 'A': // "AND".
 1717                         // See comments in the default section further below.
 1718                         if (!_tcsnicmp(next_buf, _T("and"), 3) && IS_SPACE_OR_TAB_OR_NBSP(next_buf[3])) // Relies on short-circuit boolean order.
 1719                         {
 1720                             cp = omit_leading_whitespace(next_buf + 3);
 1721                             // v1.0.38.06: The following was fixed to use EXPR_CORE vs. EXPR_OPERAND_TERMINATORS
 1722                             // to properly detect a continuation line whose first char after AND/OR is "!~*&-+()":
 1723                             if (!_tcschr(EXPR_CORE, *cp))
 1724                                 // This check recognizes the following examples as NON-continuation lines by checking
 1725                                 // that AND/OR aren't followed immediately by something that's obviously an operator:
 1726                                 //    and := x, and = 2 (but not and += 2 since the an operand can have a unary plus/minus).
 1727                                 // This is done for backward compatibility.  Also, it's documented that
 1728                                 // AND/OR/NOT aren't supported as variable names inside expressions.
 1729                                 is_continuation_line = true; // Override the default set earlier.
 1730                         }
 1731                         break;
 1732                     case 'O': // "OR".
 1733                         // See comments in the default section further below.
 1734                         if (ctoupper(next_buf[1]) == 'R' && IS_SPACE_OR_TAB_OR_NBSP(next_buf[2])) // Relies on short-circuit boolean order.
 1735                         {
 1736                             cp = omit_leading_whitespace(next_buf + 2);
 1737                             // v1.0.38.06: The following was fixed to use EXPR_CORE vs. EXPR_OPERAND_TERMINATORS
 1738                             // to properly detect a continuation line whose first char after AND/OR is "!~*&-+()":
 1739                             if (!_tcschr(EXPR_CORE, *cp)) // See comment in the "AND" case above.
 1740                                 is_continuation_line = true; // Override the default set earlier.
 1741                         }
 1742                         break;
 1743                     default:
 1744                         // Desired line continuation operators:
 1745                         // Pretty much everything, namely:
 1746                         // +, -, *, /, //, **, <<, >>, &, |, ^, <, >, <=, >=, =, ==, <>, !=, :=, +=, -=, /=, *=, ?, :
 1747                         // And also the following remaining unaries (i.e. those that aren't also binaries): !, ~
 1748                         // The first line below checks for ::, ++, and --.  Those can't be continuation lines because:
 1749                         // "::" isn't a valid operator (this also helps performance if there are many hotstrings).
 1750                         // ++ and -- are ambiguous with an isolated line containing ++Var or --Var (and besides,
 1751                         // wanting to use ++ to continue an expression seems extremely rare, though if there's ever
 1752                         // demand for it, might be able to look at what lies to the right of the operator's operand
 1753                         // -- though that would produce inconsistent continuation behavior since ++Var itself still
 1754                         // could never be a continuation line due to ambiguity).
 1755                         //
 1756                         // The logic here isn't smart enough to differentiate between a leading ! or - that's
 1757                         // meant as a continuation character and one that isn't. Even if it were, it would
 1758                         // still be ambiguous in some cases because the author's intent isn't known; for example,
 1759                         // the leading minus sign on the second line below is ambiguous, so will probably remain
 1760                         // a continuation character in both v1 and v2:
 1761                         //    x := y 
 1762                         //    -z ? a:=1 : func() 
 1763                         if ((*next_buf == ':' || *next_buf == '+' || *next_buf == '-') && next_buf[1] == *next_buf // See above.
 1764                             // L31: '.' and '?' no longer require spaces; '.' without space is member-access (object) operator.
 1765                             //|| (*next_buf == '.' || *next_buf == '?') && !IS_SPACE_OR_TAB_OR_NBSP(next_buf[1]) // The "." and "?" operators require a space or tab after them to be legitimate.  For ".", this is done in case period is ever a legal character in var names, such as struct support.  For "?", it's done for backward compatibility since variable names can contain question marks (though "?" by itself is not considered a variable in v1.0.46).
 1766                                 //&& next_buf[1] != '=' // But allow ".=" (and "?=" too for code simplicity), since ".=" is the concat-assign operator.
 1767                             || !_tcschr(CONTINUATION_LINE_SYMBOLS, *next_buf)) // Line doesn't start with a continuation char.
 1768                             break; // Leave is_continuation_line set to its default of false.
 1769                         // Some of the above checks must be done before the next ones.
 1770                         if (   !(hotkey_flag = _tcsstr(next_buf, HOTKEY_FLAG))   ) // Without any "::", it can't be a hotkey or hotstring.
 1771                         {
 1772                             is_continuation_line = true; // Override the default set earlier.
 1773                             break;
 1774                         }
 1775                         if (*next_buf == ':') // First char is ':', so it's more likely a hotstring than a hotkey.
 1776                         {
 1777                             // Remember that hotstrings can contain what *appear* to be quoted literal strings,
 1778                             // so detecting whether a "::" is in a quoted/literal string in this case would
 1779                             // be more complicated.  That's one reason this other method is used.
 1780                             for (hotstring_options_all_valid = true, cp = next_buf + 1; *cp && *cp != ':'; ++cp)
 1781                                 if (!IS_HOTSTRING_OPTION(*cp)) // Not a perfect test, but eliminates most of what little remaining ambiguity exists between ':' as a continuation character vs. ':' as the start of a hotstring.  It especially eliminates the ":=" operator.
 1782                                 {
 1783                                     hotstring_options_all_valid = false;
 1784                                     break;
 1785                                 }
 1786                             if (hotstring_options_all_valid && *cp == ':') // It's almost certainly a hotstring.
 1787                                 break; // So don't treat it as a continuation line.
 1788                             //else it's not a hotstring but it might still be a hotkey such as ": & x::".
 1789                             // So continue checking below.
 1790                         }
 1791                         // Since above didn't "break", this line isn't a hotstring but it is probably a hotkey
 1792                         // because above already discovered that it contains "::" somewhere. So try to find out
 1793                         // if there's anything that disqualifies this from being a hotkey, such as some
 1794                         // expression line that contains a quoted/literal "::" (or a line starting with
 1795                         // a comma that contains an unquoted-but-literal "::" such as for FileAppend).
 1796                         if (*next_buf == ',')
 1797                         {
 1798                             cp = omit_leading_whitespace(next_buf + 1);
 1799                             // The above has set cp to the position of the non-whitespace item to the right of
 1800                             // this comma.  Normal (single-colon) labels can't contain commas, so only hotkey
 1801                             // labels are sources of ambiguity.  In addition, normal labels and hotstrings have
 1802                             // already been checked for, higher above.
 1803                             if (   _tcsncmp(cp, HOTKEY_FLAG, HOTKEY_FLAG_LENGTH) // It's not a hotkey such as ",::action".
 1804                                 && _tcsncmp(cp - 1, COMPOSITE_DELIMITER, COMPOSITE_DELIMITER_LENGTH)   ) // ...and it's not a hotkey such as ", & y::action".
 1805                                 is_continuation_line = true; // Override the default set earlier.
 1806                         }
 1807                         else // First symbol in line isn't a comma but some other operator symbol.
 1808                         {
 1809                             // Check if the "::" found earlier appears to be inside a quoted/literal string.
 1810                             // This check is NOT done for a line beginning with a comma since such lines
 1811                             // can contain an unquoted-but-literal "::".  In addition, this check is done this
 1812                             // way to detect hotkeys such as the following:
 1813                             //   +keyname:: (and other hotkey modifier symbols such as ! and ^)
 1814                             //   +keyname1 & keyname2::
 1815                             //   +^:: (i.e. a modifier symbol followed by something that is a hotkey modifier and/or a hotkey suffix and/or an expression operator).
 1816                             //   <:: and &:: (i.e. hotkeys that are also expression-continuation symbols)
 1817                             // By contrast, expressions that qualify as continuation lines can look like:
 1818                             //   . "xxx::yyy"
 1819                             //   + x . "xxx::yyy"
 1820                             // In addition, hotkeys like the following should continue to be supported regardless
 1821                             // of how things are done here:
 1822                             //   ^"::
 1823                             //   . & "::
 1824                             // Finally, keep in mind that an expression-continuation line can start with two
 1825                             // consecutive unary operators like !! or !*. It can also start with a double-symbol
 1826                             // operator such as <=, <>, !=, &&, ||, //, **.
 1827                             for (cp = next_buf; cp < hotkey_flag && *cp != '"'; ++cp);
 1828                             if (cp == hotkey_flag) // No '"' found to left of "::", so this "::" appears to be a real hotkey flag rather than part of a literal string.
 1829                                 break; // Treat this line as a normal line vs. continuation line.
 1830                             for (cp = hotkey_flag + HOTKEY_FLAG_LENGTH; *cp && *cp != '"'; ++cp);
 1831                             if (*cp)
 1832                             {
 1833                                 // Closing quote was found so "::" is probably inside a literal string of an
 1834                                 // expression (further checking seems unnecessary given the fairly extreme
 1835                                 // rarity of using '"' as a key in a hotkey definition).
 1836                                 is_continuation_line = true; // Override the default set earlier.
 1837                             }
 1838                             //else no closing '"' found, so this "::" probably belongs to something like +":: or
 1839                             // . & "::.  Treat this line as a normal line vs. continuation line.
 1840                         }
 1841                     } // switch(toupper(*next_buf))
 1842 
 1843                     if (is_continuation_line)
 1844                     {
 1845                         if (buf_length + next_buf_length >= LINE_SIZE - 1) // -1 to account for the extra space added below.
 1846                             return ScriptError(ERR_CONTINUATION_SECTION_TOO_LONG, next_buf);
 1847                         if (*next_buf != ',') // Insert space before expression operators so that built/combined expression works correctly (some operators like 'and', 'or', '.', and '?' currently require spaces on either side) and also for readability of ListLines.
 1848                             buf[buf_length++] = ' ';
 1849                         tmemcpy(buf + buf_length, next_buf, next_buf_length + 1); // Append this line to prev. and include the zero terminator.
 1850                         buf_length += next_buf_length;
 1851                         continue; // Check for yet more continuation lines after this one.
 1852                     }
 1853                     // Since above didn't continue, there is no continuation line or section.  In addition,
 1854                     // since this line isn't blank, no further searching is needed.
 1855                     break;
 1856                 } // if (!in_continuation_section)
 1857 
 1858                 // OTHERWISE in_continuation_section != 0, so the above has found the first line of a new
 1859                 // continuation section.
 1860                 continuation_line_count = 0; // Reset for this new section.
 1861                 // Otherwise, parse options.  First set the defaults, which can be individually overridden
 1862                 // by any options actually present.  RTrim defaults to ON for two reasons:
 1863                 // 1) Whitespace often winds up at the end of a lines in a text editor by accident.  In addition,
 1864                 //    whitespace at the end of any consolidated/merged line will be rtrim'd anyway, since that's
 1865                 //    how command parsing works.
 1866                 // 2) Copy & paste from the forum and perhaps other web sites leaves a space at the end of each
 1867                 //    line.  Although this behavior is probably site/browser-specific, it's a consideration.
 1868                 do_ltrim = g_ContinuationLTrim; // Start off at global default.
 1869                 do_rtrim = true; // Seems best to rtrim even if this line is a hotstring, since it is very rare that trailing spaces and tabs would ever be desirable.
 1870                 // For hotstrings (which could be detected via *buf==':'), it seems best not to default the
 1871                 // escape character (`) to be literal because the ability to have `t `r and `n inside the
 1872                 // hotstring continuation section seems more useful/common than the ability to use the
 1873                 // accent character by itself literally (which seems quite rare in most languages).
 1874                 literal_escapes = false;
 1875                 literal_derefs = false;
 1876                 literal_delimiters = true; // This is the default even for hotstrings because although using (*buf != ':') would improve loading performance, it's not a 100% reliable way to detect hotstrings.
 1877                 // The default is linefeed because:
 1878                 // 1) It's the best choice for hotstrings, for which the line continuation mechanism is well suited.
 1879                 // 2) It's good for FileAppend.
 1880                 // 3) Minor: Saves memory in large sections by being only one character instead of two.
 1881                 suffix[0] = '\n';
 1882                 suffix[1] = '\0';
 1883                 suffix_length = 1;
 1884                 for (next_option = omit_leading_whitespace(next_buf + 1); *next_option; next_option = omit_leading_whitespace(option_end))
 1885                 {
 1886                     // Find the end of this option item:
 1887                     if (   !(option_end = StrChrAny(next_option, _T(" \t")))   )  // Space or tab.
 1888                         option_end = next_option + _tcslen(next_option); // Set to position of zero terminator instead.
 1889 
 1890                     // Temporarily terminate to help eliminate ambiguity for words contained inside other words,
 1891                     // such as hypothetical "Checked" inside of "CheckedGray":
 1892                     orig_char = *option_end;
 1893                     *option_end = '\0';
 1894 
 1895                     if (!_tcsnicmp(next_option, _T("Join"), 4))
 1896                     {
 1897                         next_option += 4;
 1898                         tcslcpy(suffix, next_option, _countof(suffix)); // The word "Join" by itself will product an empty string, as documented.
 1899                         // Passing true for the last parameter supports `s as the special escape character,
 1900                         // which allows space to be used by itself and also at the beginning or end of a string
 1901                         // containing other chars.
 1902                         ConvertEscapeSequences(suffix, g_EscapeChar, true);
 1903                         suffix_length = _tcslen(suffix);
 1904                     }
 1905                     else if (!_tcsnicmp(next_option, _T("LTrim"), 5))
 1906                         do_ltrim = (next_option[5] != '0');  // i.e. Only an explicit zero will turn it off.
 1907                     else if (!_tcsnicmp(next_option, _T("RTrim"), 5))
 1908                         do_rtrim = (next_option[5] != '0');
 1909                     else
 1910                     {
 1911                         // Fix for v1.0.36.01: Missing "else" above, because otherwise, the option Join`r`n
 1912                         // would be processed above but also be processed again below, this time seeing the
 1913                         // accent and thinking it's the signal to treat accents literally for the entire
 1914                         // continuation section rather than as escape characters.
 1915                         // Within this terminated option substring, allow the characters to be adjacent to
 1916                         // improve usability:
 1917                         for (; *next_option; ++next_option)
 1918                         {
 1919                             switch (*next_option)
 1920                             {
 1921                             case '`': // Although not using g_EscapeChar (reduces code size/complexity), #EscapeChar is still supported by continuation sections; it's just that enabling the option uses '`' rather than the custom escape-char (one reason is that that custom escape-char might be ambiguous with future/past options if it's something weird like an alphabetic character).
 1922                                 literal_escapes = true;
 1923                                 break;
 1924                             case '%': // Same comment as above.
 1925                                 literal_derefs = true;
 1926                                 break;
 1927                             case ',': // Same comment as above.
 1928                                 literal_delimiters = false;
 1929                                 break;
 1930                             case 'C': // v1.0.45.03: For simplicity, anything that begins with "C" is enough to
 1931                             case 'c': // identify it as the option to allow comments in the section.
 1932                                 in_continuation_section = CONTINUATION_SECTION_WITH_COMMENTS; // Override the default, which is boolean true (i.e. 1).
 1933                                 break;
 1934                             case ')':
 1935                                 // Probably something like (x.y)[z](), which is not intended as the beginning of
 1936                                 // a continuation section.  Doing this only when ")" is found should remove the
 1937                                 // need to escape "(" in most real-world expressions while still allowing new
 1938                                 // options to be added later with minimal risk of breaking scripts.
 1939                                 in_continuation_section = 0;
 1940                                 *option_end = orig_char; // Undo the temporary termination.
 1941                                 goto process_completed_line;
 1942                             }
 1943                         }
 1944                     }
 1945 
 1946                     // If the item was not handled by the above, ignore it because it is unknown.
 1947                     *option_end = orig_char; // Undo the temporary termination.
 1948                 } // for() each item in option list
 1949 
 1950                 // "has_continuation_section" indicates whether the line we're about to construct is partially
 1951                 // composed of continuation lines beneath it.  It's separate from continuation_line_count
 1952                 // in case there is another continuation section immediately after/adjacent to the first one,
 1953                 // but the second one doesn't have any lines in it:
 1954                 has_continuation_section = true;
 1955 
 1956                 continue; // Now that the open-parenthesis of this continuation section has been processed, proceed to the next line.
 1957             } // if (!in_continuation_section)
 1958 
 1959             // Since above didn't "continue", we're in the continuation section and thus next_buf contains
 1960             // either a line to be appended onto buf or the closing parenthesis of this continuation section.
 1961             if (next_buf_length == -1) // Compare directly to -1 since length is unsigned.
 1962                 return ScriptError(ERR_MISSING_CLOSE_PAREN, buf);
 1963             if (next_buf_length == -2) // v1.0.45.03: Special flag that means "this is a commented-out line to be
 1964                 continue;              // entirely omitted from the continuation section." Compare directly to -2 since length is unsigned.
 1965 
 1966             if (*next_buf == ')')
 1967             {
 1968                 in_continuation_section = 0; // Facilitates back-to-back continuation sections and proper incrementing of phys_line_number.
 1969                 next_buf_length = rtrim(next_buf); // Done because GetLine() wouldn't have done it due to have told it we're in a continuation section.
 1970                 // Anything that lies to the right of the close-parenthesis gets appended verbatim, with
 1971                 // no trimming (for flexibility) and no options-driven translation:
 1972                 cp = next_buf + 1;  // Use temp var cp to avoid altering next_buf (for maintainability).
 1973                 --next_buf_length;  // This is now the length of cp, not next_buf.
 1974             }
 1975             else
 1976             {
 1977                 cp = next_buf;
 1978                 // The following are done in this block only because anything that comes after the closing
 1979                 // parenthesis (i.e. the block above) is exempt from translations and custom trimming.
 1980                 // This means that commas are always delimiters and percent signs are always deref symbols
 1981                 // in the previous block.
 1982                 if (do_rtrim)
 1983                     next_buf_length = rtrim(next_buf, next_buf_length);
 1984                 if (do_ltrim)
 1985                     next_buf_length = ltrim(next_buf, next_buf_length);
 1986                 // Escape each comma and percent sign in the body of the continuation section so that
 1987                 // the later parsing stages will see them as literals.  Although, it's not always
 1988                 // necessary to do this (e.g. commas in the last parameter of a command don't need to
 1989                 // be escaped, nor do percent signs in hotstrings' auto-replace text), the settings
 1990                 // are applied unconditionally because:
 1991                 // 1) Determining when its safe to omit the translation would add a lot of code size and complexity.
 1992                 // 2) The translation doesn't affect the functionality of the script since escaped literals
 1993                 //    are always de-escaped at a later stage, at least for everything that's likely to matter
 1994                 //    or that's reasonable to put into a continuation section (e.g. a hotstring's replacement text).
 1995                 // UPDATE for v1.0.44.11: #EscapeChar, #DerefChar, #Delimiter are now supported by continuation
 1996                 // sections because there were some requests for that in forum.
 1997                 int replacement_count = 0;
 1998                 if (literal_escapes) // literal_escapes must be done FIRST because otherwise it would also replace any accents added for literal_delimiters or literal_derefs.
 1999                 {
 2000                     one_char_string[0] = g_EscapeChar; // These strings were terminated earlier, so no need to
 2001                     two_char_string[0] = g_EscapeChar; // do it here.  In addition, these strings must be set by
 2002                     two_char_string[1] = g_EscapeChar; // each iteration because the #EscapeChar (and similar directives) can occur multiple times, anywhere in the script.
 2003                     replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
 2004                 }
 2005                 if (literal_derefs)
 2006                 {
 2007                     one_char_string[0] = g_DerefChar;
 2008                     two_char_string[0] = g_EscapeChar;
 2009                     two_char_string[1] = g_DerefChar;
 2010                     replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
 2011                 }
 2012                 if (literal_delimiters)
 2013                 {
 2014                     one_char_string[0] = g_delimiter;
 2015                     two_char_string[0] = g_EscapeChar;
 2016                     two_char_string[1] = g_delimiter;
 2017                     replacement_count += StrReplace(next_buf, one_char_string, two_char_string, SCS_SENSITIVE, UINT_MAX, LINE_SIZE);
 2018                 }
 2019 
 2020                 if (replacement_count) // Update the length if any actual replacements were done.
 2021                     next_buf_length = _tcslen(next_buf);
 2022             } // Handling of a normal line within a continuation section.
 2023 
 2024             // Must check the combined length only after anything that might have expanded the string above.
 2025             if (buf_length + next_buf_length + suffix_length >= LINE_SIZE)
 2026                 return ScriptError(ERR_CONTINUATION_SECTION_TOO_LONG, cp);
 2027 
 2028             ++continuation_line_count;
 2029             // Append this continuation line onto the primary line.
 2030             // The suffix for the previous line gets written immediately prior writing this next line,
 2031             // which allows the suffix to be omitted for the final line.  But if this is the first line,
 2032             // No suffix is written because there is no previous line in the continuation section.
 2033             // In addition, cp!=next_buf, this is the special line whose text occurs to the right of the
 2034             // continuation section's closing parenthesis. In this case too, the previous line doesn't
 2035             // get a suffix.
 2036             if (continuation_line_count > 1 && suffix_length && cp == next_buf)
 2037             {
 2038                 tmemcpy(buf + buf_length, suffix, suffix_length + 1); // Append and include the zero terminator.
 2039                 buf_length += suffix_length; // Must be done only after the old value of buf_length was used above.
 2040             }
 2041             if (next_buf_length)
 2042             {
 2043                 tmemcpy(buf + buf_length, cp, next_buf_length + 1); // Append this line to prev. and include the zero terminator.
 2044                 buf_length += next_buf_length; // Must be done only after the old value of buf_length was used above.
 2045             }
 2046         } // for() each sub-line (continued line) that composes this line.
 2047 
 2048 process_completed_line:
 2049         // buf_length can't be -1 (though next_buf_length can) because outer loop's condition prevents it:
 2050         if (!buf_length) // Done only after the line number increments above so that the physical line number is properly tracked.
 2051             goto continue_main_loop; // In lieu of "continue", for performance.
 2052 
 2053         // Since neither of the above executed, or they did but didn't "continue",
 2054         // buf now contains a non-commented line, either by itself or built from
 2055         // any continuation sections/lines that might have been present.  Also note that
 2056         // by design, phys_line_number will be greater than mCombinedLineNumber whenever
 2057         // a continuation section/lines were used to build this combined line.
 2058 
 2059         // If there's a previous line waiting to be processed, its fate can now be determined based on the
 2060         // nature of *this* line:
 2061         if (*pending_buf)
 2062         {
 2063             // Somewhat messy to decrement then increment later, but it's probably easier than the
 2064             // alternatives due to the use of "continue" in some places above.  NOTE: phys_line_number
 2065             // would not need to be decremented+incremented even if the below resulted in a recursive
 2066             // call to us (though it doesn't currently) because line_number's only purpose is to
 2067             // remember where this layer left off when the recursion collapses back to us.
 2068             // Fix for v1.0.31.05: It's not enough just to decrement mCombinedLineNumber because there
 2069             // might be some blank lines or commented-out lines between this function call/definition
 2070             // and the line that follows it, each of which will have previously incremented mCombinedLineNumber.
 2071             saved_line_number = mCombinedLineNumber;
 2072             mCombinedLineNumber = pending_buf_line_number;  // Done so that any syntax errors that occur during the calls below will report the correct line number.
 2073             // Open brace means this is a function definition. NOTE: buf was already ltrimmed by GetLine().
 2074             // Could use *g_act[ACT_BLOCK_BEGIN].Name instead of '{', but it seems too elaborate to be worth it.
 2075             if (*buf == '{' || pending_buf_has_brace) // v1.0.41: Support one-true-brace, e.g. fn(...) {
 2076             {
 2077                 switch (pending_buf_type)
 2078                 {
 2079                 case Pending_Class:
 2080                     if (!DefineClass(pending_buf))
 2081                         return FAIL;
 2082                     break;
 2083                 case Pending_Property:
 2084                     if (!DefineClassProperty(pending_buf))
 2085                         return FAIL;
 2086                     break;
 2087                 case Pending_Func:
 2088                     // Note that two consecutive function definitions aren't possible:
 2089                     // fn1()
 2090                     // fn2()
 2091                     // {
 2092                     //  ...
 2093                     // }
 2094                     // In the above, the first would automatically be deemed a function call by means of
 2095                     // the check higher above (by virtue of the fact that the line after it isn't an open-brace).
 2096                     if (g->CurrentFunc)
 2097                     {
 2098                         // Though it might be allowed in the future -- perhaps to have nested functions have
 2099                         // access to their parent functions' local variables, or perhaps just to improve
 2100                         // script readability and maintainability -- it's currently not allowed because of
 2101                         // the practice of maintaining the func_global_var list on our stack:
 2102                         return ScriptError(_T("Functions cannot contain functions."), pending_buf);
 2103                     }
 2104                     if (!DefineFunc(pending_buf, func_global_var))
 2105                         return FAIL;
 2106                     if (pending_buf_has_brace) // v1.0.41: Support one-true-brace for function def, e.g. fn() {
 2107                     {
 2108                         if (!AddLine(ACT_BLOCK_BEGIN))
 2109                             return FAIL;
 2110                         mCurrLine = NULL; // L30: Prevents showing misleading vicinity lines if the line after a OTB function def is a syntax error.
 2111                     }
 2112                     break;
 2113 #ifdef _DEBUG
 2114                 default:
 2115                     return ScriptError(_T("DEBUG: pending_buf_type has an unexpected value."));
 2116 #endif
 2117                 }
 2118             }
 2119             else // It's a function call on a line by itself, such as fn(x). It can't be if(..) because another section checked that.
 2120             {
 2121                 if (pending_buf_type != Pending_Func) // Missing open-brace for class definition.
 2122                     return ScriptError(ERR_MISSING_OPEN_BRACE, pending_buf);
 2123                 if (mClassObjectCount && !g->CurrentFunc) // Unexpected function call in class definition.
 2124                     return ScriptError(mClassProperty ? ERR_MISSING_OPEN_BRACE : ERR_INVALID_LINE_IN_CLASS_DEF, pending_buf);
 2125                 if (!ParseAndAddLine(pending_buf, ACT_EXPRESSION))
 2126                     return FAIL;
 2127                 mCurrLine = NULL; // Prevents showing misleading vicinity lines if the line after a function call is a syntax error.
 2128             }
 2129             *pending_buf = '\0'; // Reset now that it's been fully handled, as an indicator for subsequent iterations.
 2130             if (pending_buf_type != Pending_Func) // Class or property.
 2131             {
 2132                 if (!pending_buf_has_brace)
 2133                 {
 2134                     // This is the open-brace of a class definition, so requires no further processing.
 2135                     if (  !*(cp = omit_leading_whitespace(buf + 1))  )
 2136                     {
 2137                         mCombinedLineNumber = saved_line_number;
 2138                         goto continue_main_loop;
 2139                     }
 2140                     // Otherwise, there's something following the "{", possibly "}" or a function definition.
 2141                     tmemmove(buf, cp, (buf_length = _tcslen(cp)) + 1);
 2142                 }
 2143             }
 2144             mCombinedLineNumber = saved_line_number;
 2145             // Now fall through to the below so that *this* line (the one after it) will be processed.
 2146             // Note that this line might be a pre-processor directive, label, etc. that won't actually
 2147             // become a runtime line per se.
 2148         } // if (*pending_function)
 2149 
 2150         if (*buf == '}' && mClassObjectCount && !g->CurrentFunc)
 2151         {
 2152             if (mClassProperty)
 2153             {
 2154                 // Close this property definition.
 2155                 mClassProperty = NULL;
 2156                 if (mClassPropertyDef)
 2157                 {
 2158                     free(mClassPropertyDef);
 2159                     mClassPropertyDef = NULL;
 2160                 }
 2161             }
 2162             else
 2163             {
 2164                 // End of class definition.
 2165                 --mClassObjectCount;
 2166                 mClassObject[mClassObjectCount]->EndClassDefinition(); // Remove instance variables from the class object.
 2167                 mClassObject[mClassObjectCount]->Release();
 2168                 // Revert to the name of the class this class is nested inside, or "" if none.
 2169                 if (cp1 = _tcsrchr(mClassName, '.'))
 2170                     *cp1 = '\0';
 2171                 else
 2172                     *mClassName = '\0';
 2173             }
 2174             // Allow multiple end-braces or other declarations to the right of "}":
 2175             if (   *(buf = omit_leading_whitespace(buf + 1))   )
 2176             {
 2177                 buf_length = _tcslen(buf); // Update.
 2178                 mCurrLine = NULL;  // To signify that we're in transition, trying to load a new line.
 2179                 goto process_completed_line; // Have the main loop process the contents of "buf" as though it came in from the script.
 2180             }
 2181             goto continue_main_loop; // It's just a naked "{" or "}", so no more processing needed for this line.
 2182         }
 2183 
 2184         if (mClassProperty && !g->CurrentFunc) // This is checked before IsFunction() to prevent method definitions inside a property.
 2185         {
 2186             if (!_tcsnicmp(buf, _T("Get"), 3) || !_tcsnicmp(buf, _T("Set"), 3))
 2187             {
 2188                 LPTSTR cp = omit_leading_whitespace(buf + 3);
 2189                 if ( !*cp || (*cp == '{' && !cp[1]) )
 2190                 {
 2191                     // Defer this line until the next line comes in to simplify handling of '{' and OTB.
 2192                     // For simplicity, pass the property definition to DefineFunc instead of the actual
 2193                     // line text, even though it makes some error messages a bit inaccurate. (That would
 2194                     // happen anyway when DefineFunc() finds a syntax error in the parameter list.)
 2195                     _tcscpy(pending_buf, mClassPropertyDef);
 2196                     LPTSTR dot = _tcschr(pending_buf, '.');
 2197                     dot[1] = *buf; // Replace the x in property.xet(params).
 2198                     pending_buf_line_number = mCombinedLineNumber;
 2199                     pending_buf_has_brace = *cp == '{';
 2200                     pending_buf_type = Pending_Func;
 2201                     goto continue_main_loop;
 2202                 }
 2203             }
 2204             return ScriptError(ERR_INVALID_LINE_IN_PROPERTY_DEF, buf);
 2205         }
 2206 
 2207         // By doing the following section prior to checking for hotkey and hotstring labels, double colons do
 2208         // not need to be escaped inside naked function calls and function definitions such as the following:
 2209         // fn("::")      ; Function call.
 2210         // fn(Str="::")  ; Function definition with default value for its parameter.
 2211         if (IsFunction(buf, &pending_buf_has_brace)) // If true, it's either a function definition or a function call (to be distinguished later).
 2212         {
 2213             // Defer this line until the next line comes in, which helps determine whether this line is
 2214             // a function call vs. definition:
 2215             _tcscpy(pending_buf, buf);
 2216             pending_buf_line_number = mCombinedLineNumber;
 2217             pending_buf_type = Pending_Func;
 2218             goto continue_main_loop; // In lieu of "continue", for performance.
 2219         }
 2220         
 2221         if (!g->CurrentFunc)
 2222         {
 2223             if (LPTSTR class_name = IsClassDefinition(buf, pending_buf_has_brace))
 2224             {
 2225                 // Defer this line until the next line comes in to simplify handling of '{' and OTB:
 2226                 _tcscpy(pending_buf, class_name);
 2227                 pending_buf_line_number = mCombinedLineNumber;
 2228                 pending_buf_type = Pending_Class;
 2229                 goto continue_main_loop; // In lieu of "continue", for performance.
 2230             }
 2231 
 2232             if (mClassObjectCount)
 2233             {
 2234                 // Check for assignment first, in case of something like "Static := 123".
 2235                 for (cp = buf; IS_IDENTIFIER_CHAR(*cp) || *cp == '.'; ++cp);
 2236                 if (cp > buf) // i.e. buf begins with an identifier.
 2237                 {
 2238                     cp = omit_leading_whitespace(cp);
 2239                     if (*cp == ':' && cp[1] == '=') // This is an assignment.
 2240                     {
 2241                         if (!DefineClassVars(buf, false)) // See above for comments.
 2242                             return FAIL;
 2243                         goto continue_main_loop;
 2244                     }
 2245                     if ( !*cp || *cp == '[' || (*cp == '{' && !cp[1]) ) // Property
 2246                     {
 2247                         size_t length = _tcslen(buf);
 2248                         if (pending_buf_has_brace = (buf[length - 1] == '{'))
 2249                         {
 2250                             // Omit '{' and trailing whitespace from further consideration.
 2251                             rtrim(buf, length - 1);
 2252                         }
 2253                         
 2254                         // Defer this line until the next line comes in to simplify handling of '{' and OTB:
 2255                         _tcscpy(pending_buf, buf);
 2256                         pending_buf_line_number = mCombinedLineNumber;
 2257                         pending_buf_type = Pending_Property;
 2258                         goto continue_main_loop; // In lieu of "continue", for performance.
 2259                     }
 2260                 }
 2261                 if (!_tcsnicmp(buf, _T("Static"), 6) && IS_SPACE_OR_TAB(buf[6]))
 2262                 {
 2263                     if (!DefineClassVars(buf + 7, true))
 2264                         return FAIL; // Above already displayed the error.
 2265                     goto continue_main_loop; // In lieu of "continue", for performance.
 2266                 }
 2267                 if (*buf == '#') // See the identical section further below for comments.
 2268                 {
 2269                     saved_line_number = mCombinedLineNumber;
 2270                     switch(IsDirective(buf))
 2271                     {
 2272                     case CONDITION_TRUE:
 2273                         mCurrFileIndex = source_file_index;
 2274                         mCombinedLineNumber = saved_line_number;
 2275                         goto continue_main_loop;
 2276                     case FAIL:
 2277                         return FAIL;
 2278                     }
 2279                 }
 2280                 // Anything not already handled above is not valid directly inside a class definition.
 2281                 return ScriptError(ERR_INVALID_LINE_IN_CLASS_DEF, buf);
 2282             }
 2283         }
 2284 
 2285         // The following "examine_line" label skips the following parts above:
 2286         // 1) IsFunction() because that's only for a function call or definition alone on a line
 2287         //    e.g. not "if fn()" or x := fn().  Those who goto this label don't need that processing.
 2288         // 2) The "if (*pending_function)" block: Doesn't seem applicable for the callers of this label.
 2289         // 3) The inner loop that handles continuation sections: Not needed by the callers of this label.
 2290         // 4) Things like the following should be skipped because callers of this label don't want the
 2291         //    physical line number changed (which would throw off the count of lines that lie beneath a remap):
 2292         //    mCombinedLineNumber = phys_line_number + 1;
 2293         //    ++phys_line_number;
 2294         // 5) "mCurrLine = NULL": Probably not necessary since it's only for error reporting.  Worst thing
 2295         //    that could happen is that syntax errors would be thrown off, which testing shows isn't the case.
 2296 examine_line:
 2297         // "::" alone isn't a hotstring, it's a label whose name is colon.
 2298         // Below relies on the fact that no valid hotkey can start with a colon, since
 2299         // ": & somekey" is not valid (since colon is a shifted key) and colon itself
 2300         // should instead be defined as "+;::".  It also relies on short-circuit boolean:
 2301         hotstring_start = NULL;
 2302         hotkey_flag = NULL;
 2303         if (buf[0] == ':' && buf[1])
 2304         {
 2305             hotstring_options = buf + 1; // Point it to the hotstring's option letters, if any.
 2306             if (buf[1] != ':')
 2307             {
 2308                 // The following relies on the fact that options should never contain a literal colon.
 2309                 // ALSO, the following doesn't use IS_HOTSTRING_OPTION() for backward compatibility,
 2310                 // performance, and because it seems seldom if ever necessary at this late a stage.
 2311                 if (   !(hotstring_start = _tcschr(hotstring_options, ':'))   )
 2312                     hotstring_start = NULL; // Indicate that this isn't a hotstring after all.
 2313                 else
 2314                     ++hotstring_start; // Points to the hotstring itself.
 2315             }
 2316             else // Double-colon, so it's a hotstring if there's more after this (but this means no options are present).
 2317                 if (buf[2])
 2318                     hotstring_start = buf + 2;
 2319                 //else it's just a naked "::", which is considered to be an ordinary label whose name is colon.
 2320         }
 2321         if (hotstring_start)
 2322         {
 2323             // Check for 'X' option early since escape sequence processing depends on it.
 2324             hotstring_execute = g_HSSameLineAction;
 2325             for (cp = hotstring_options; cp < hotstring_start; ++cp)
 2326                 if (ctoupper(*cp) == 'X')
 2327                 {
 2328                     hotstring_execute = cp[1] != '0';
 2329                     break;
 2330                 }
 2331             // Find the hotstring's final double-colon by considering escape sequences from left to right.
 2332             // This is necessary for to handles cases such as the following:
 2333             // ::abc```::::Replacement String
 2334             // The above hotstring translates literally into "abc`::".
 2335             LPTSTR escaped_double_colon = NULL;
 2336             for (cp = hotstring_start; ; ++cp)  // Increment to skip over the symbol just found by the inner for().
 2337             {
 2338                 for (; *cp && *cp != g_EscapeChar && *cp != ':'; ++cp);  // Find the next escape char or colon.
 2339                 if (!*cp) // end of string.
 2340                     break;
 2341                 cp1 = cp + 1;
 2342                 if (*cp == ':')
 2343                 {
 2344                     if (*cp1 == ':') // Found a non-escaped double-colon, so this is the right one.
 2345                     {
 2346                         hotkey_flag = cp++;  // Increment to have loop skip over both colons.
 2347                         if (hotstring_execute)
 2348                             break; // Let ParseAndAddLine() properly handle any escape sequences.
 2349                         // else continue with the loop so that escape sequences in the replacement
 2350                         // text (if there is replacement text) are also translated.
 2351                     }
 2352                     // else just a single colon, or the second colon of an escaped pair (`::), so continue.
 2353                     continue;
 2354                 }
 2355                 switch (*cp1)
 2356                 {
 2357                     // Only lowercase is recognized for these:
 2358                     case 'a': *cp1 = '\a'; break;  // alert (bell) character
 2359                     case 'b': *cp1 = '\b'; break;  // backspace
 2360                     case 'f': *cp1 = '\f'; break;  // formfeed
 2361                     case 'n': *cp1 = '\n'; break;  // newline
 2362                     case 'r': *cp1 = '\r'; break;  // carriage return
 2363                     case 't': *cp1 = '\t'; break;  // horizontal tab
 2364                     case 'v': *cp1 = '\v'; break;  // vertical tab
 2365                     // Otherwise, if it's not one of the above, the escape-char is considered to
 2366                     // mark the next character as literal, regardless of what it is. Examples:
 2367                     // `` -> `
 2368                     // `:: -> :: (effectively)
 2369                     // `; -> ;
 2370                     // `c -> c (i.e. unknown escape sequences resolve to the char after the `)
 2371                 }
 2372                 // Below has a final +1 to include the terminator:
 2373                 tmemmove(cp, cp1, _tcslen(cp1) + 1);
 2374                 // Since single colons normally do not need to be escaped, this increments one extra
 2375                 // for double-colons to skip over the entire pair so that its second colon
 2376                 // is not seen as part of the hotstring's final double-colon.  Example:
 2377                 // ::ahc```::::Replacement String
 2378                 if (*cp == ':' && *cp1 == ':')
 2379                     ++cp;
 2380             } // for()
 2381             if (!hotkey_flag)
 2382                 hotstring_start = NULL;  // Indicate that this isn't a hotstring after all.
 2383         }
 2384         if (!hotstring_start) // Not a hotstring (hotstring_start is checked *again* in case above block changed it; otherwise hotkeys like ": & x" aren't recognized).
 2385         {
 2386             // Note that there may be an action following the HOTKEY_FLAG (on the same line).
 2387             if (hotkey_flag = _tcsstr(buf, HOTKEY_FLAG)) // Find the first one from the left, in case there's more than 1.
 2388             {
 2389                 if (hotkey_flag == buf && hotkey_flag[2] == ':') // v1.0.46: Support ":::" to mean "colon is a hotkey".
 2390                     ++hotkey_flag;
 2391                 // v1.0.40: It appears to be a hotkey, but validate it as such before committing to processing
 2392                 // it as a hotkey.  If it fails validation as a hotkey, treat it as a command that just happens
 2393                 // to contain a double-colon somewhere.  This avoids the need to escape double colons in scripts.
 2394                 // Note: Hotstrings can't suffer from this type of ambiguity because a leading colon or pair of
 2395                 // colons makes them easier to detect.
 2396                 cp = omit_trailing_whitespace(buf, hotkey_flag); // For maintainability.
 2397                 orig_char = *cp;
 2398                 *cp = '\0'; // Temporarily terminate.
 2399                 hotkey_validity = Hotkey::TextInterpret(omit_leading_whitespace(buf), NULL, false); // Passing NULL calls it in validate-only mode.
 2400                 switch (hotkey_validity)
 2401                 {
 2402                 case FAIL:
 2403                     hotkey_flag = NULL; // It's not a valid hotkey, so indicate that it's a command (i.e. one that contains a literal double-colon, which avoids the need to escape the double-colon).
 2404                     break;
 2405                 case CONDITION_FALSE:
 2406                     return FAIL; // It's an invalid hotkey and above already displayed the error message.
 2407                 //case CONDITION_TRUE:
 2408                     // It's a key that doesn't exist on the current keyboard layout.  Leave hotkey_flag set
 2409                     // so that the section below handles it as a hotkey.  This allows it to end the auto-exec
 2410                     // section and register the appropriate label even though it won't be an active hotkey.
 2411                 }
 2412                 *cp = orig_char; // Undo the temp. termination above.
 2413             }
 2414         }
 2415 
 2416         // Treat a naked "::" as a normal label whose label name is colon:
 2417         if (is_label = (hotkey_flag && hotkey_flag > buf)) // It's a hotkey/hotstring label.
 2418         {
 2419             if (g->CurrentFunc)
 2420             {
 2421                 // Even if it weren't for the reasons below, the first hotkey/hotstring label in a script
 2422                 // will end the auto-execute section with a "return".  Therefore, if this restriction here
 2423                 // is ever removed, be sure that that extra return doesn't get put inside the function.
 2424                 //
 2425                 // The reason for not allowing hotkeys and hotstrings inside a function's body is that
 2426                 // when the subroutine is launched, the hotstring/hotkey would be using the function's
 2427                 // local variables.  But that is not appropriate and it's likely to cause problems even
 2428                 // if it were.  It doesn't seem useful in any case.  By contrast, normal labels can
 2429                 // safely exist inside a function body and since the body is a block, other validation
 2430                 // ensures that a Gosub or Goto can't jump to it from outside the function.
 2431                 return ScriptError(_T("Hotkeys/hotstrings are not allowed inside functions."), buf);
 2432             }
 2433             if (mLastLine && mLastLine->mActionType == ACT_IFWINACTIVE)
 2434             {
 2435                 mCurrLine = mLastLine; // To show vicinity lines.
 2436                 return ScriptError(_T("IfWin should be #IfWin."), buf);
 2437             }
 2438             *hotkey_flag = '\0'; // Terminate so that buf is now the label itself.
 2439             hotkey_flag += HOTKEY_FLAG_LENGTH;  // Now hotkey_flag is the hotkey's action, if any.
 2440             if (!hotstring_start)
 2441             {
 2442                 ltrim(hotkey_flag); // Has already been rtrimmed by GetLine().
 2443                 // Not done because Hotkey::TextInterpret() does not allow trailing whitespace: 
 2444                 //rtrim(buf); // Trim the new substring inside of buf (due to temp termination). It has already been ltrimmed.
 2445                 cp = hotkey_flag; // Set default, conditionally overridden below (v1.0.44.07).
 2446                 // v1.0.40: Check if this is a remap rather than hotkey:
 2447                 if (   *hotkey_flag // This hotkey's action is on the same line as its label.
 2448                     && (remap_dest_vk = hotkey_flag[1] ? TextToVK(cp = Hotkey::TextToModifiers(hotkey_flag, NULL)) : 0xFF)   ) // And the action appears to be a remap destination rather than a command.
 2449                     // For above:
 2450                     // Fix for v1.0.44.07: Set remap_dest_vk to 0xFF if hotkey_flag's length is only 1 because:
 2451                     // 1) It allows a destination key that doesn't exist in the keyboard layout (such as 6::ð in
 2452                     //    English).
 2453                     // 2) It improves performance a little by not calling TextToVK except when the destination key
 2454                     //    might be a mouse button or some longer key name whose actual/correct VK value is relied
 2455                     //    upon by other places below.
 2456                     // Fix for v1.0.40.01: Since remap_dest_vk is also used as the flag to indicate whether
 2457                     // this line qualifies as a remap, must do it last in the statement above.  Otherwise,
 2458                     // the statement might short-circuit and leave remap_dest_vk as non-zero even though
 2459                     // the line shouldn't be a remap.  For example, I think a hotkey such as "x & y::return"
 2460                     // would trigger such a bug.
 2461                 {
 2462                     // These will be ignored in other stages if it turns out not to be a remap later below:
 2463                     remap_source_vk = TextToVK(cp1 = Hotkey::TextToModifiers(buf, NULL)); // An earlier stage verified that it's a valid hotkey, though VK could be zero.
 2464                     remap_source_is_combo = _tcsstr(cp1, COMPOSITE_DELIMITER);
 2465                     remap_source_is_mouse = IsMouseVK(remap_source_vk);
 2466                     remap_dest_is_mouse = IsMouseVK(remap_dest_vk);
 2467                     remap_keybd_to_mouse = !remap_source_is_mouse && remap_dest_is_mouse;
 2468                     sntprintf(remap_source, _countof(remap_source), _T("%s%s%s")
 2469                         , remap_source_is_combo ? _T("") : _T("*") // v1.1.27.01: Omit * when the remap source is a custom combo.
 2470                         , _tcslen(cp1) == 1 && IsCharUpper(*cp1) ? _T("+") : _T("")  // Allow A::b to be different than a::b.
 2471                         , buf); // Include any modifiers too, e.g. ^b::c.
 2472                     tcslcpy(remap_dest, cp, _countof(remap_dest));      // But exclude modifiers here; they're wanted separately.
 2473                     tcslcpy(remap_dest_modifiers, hotkey_flag, _countof(remap_dest_modifiers));
 2474                     if (cp - hotkey_flag < _countof(remap_dest_modifiers)) // Avoid reading beyond the end.
 2475                         remap_dest_modifiers[cp - hotkey_flag] = '\0';   // Terminate at the proper end of the modifier string.
 2476                     remap_stage = 0; // Init for use in the next stage.
 2477                     // In the unlikely event that the dest key has the same name as a command, disqualify it
 2478                     // from being a remap (as documented).  v1.0.40.05: If the destination key has any modifiers,
 2479                     // it is unambiguously a key name rather than a command, so the switch() isn't necessary.
 2480                     if (*remap_dest_modifiers)
 2481                         goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
 2482                     switch (remap_dest_vk)
 2483                     {
 2484                     // "Control" and "Sleep" are permitted to be keys when no parameters are present.
 2485                     // TextToVK() returns 0 in those cases, so there's no need to handle them here.
 2486                     // "Return" and "Pause" as destination keys are always considered commands instead.
 2487                     // This is documented and is done to preserve backward compatibility.
 2488                     case VK_RETURN:
 2489                         // v1.0.40.05: Although "Return" can't be a destination, "Enter" can be.  Must compare
 2490                         // to "Return" not "Enter" so that things like "vk0d" (the VK of "Enter") can also be a
 2491                         // destination key:
 2492                         if (!_tcsicmp(remap_dest, _T("Return")))
 2493                             break;
 2494                         goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
 2495                     case VK_PAUSE:  // Used for both "Pause" and "Break"
 2496                         if (ctoupper(*remap_dest) == 'P' || ctoupper(*remap_dest) == 'B') // Rule out vk13 and sc045.
 2497                             break;
 2498                     default: // All other VKs are valid destinations and thus the remap is valid.
 2499                         goto continue_main_loop; // It will see that remap_dest_vk is non-zero and act accordingly.
 2500                     }
 2501                     // Since above didn't goto, indicate that this is not a remap after all:
 2502                     remap_dest_vk = 0;
 2503                 }
 2504             }
 2505             // else don't trim hotstrings since literal spaces in both substrings are significant.
 2506 
 2507             // If this is the first hotkey label encountered, Add a return before
 2508             // adding the label, so that the auto-execute section is terminated.
 2509             // Only do this if the label is a hotkey because, for example,
 2510             // the user may want to fully execute a normal script that contains
 2511             // no hotkeys but does contain normal labels to which the execution
 2512             // should fall through, if specified, rather than returning.
 2513             // But this might result in weirdness?  Example:
 2514             //testlabel:
 2515             // Sleep, 1
 2516             // return
 2517             // ^a::
 2518             // return
 2519             // It would put the hard return in between, which is wrong.  But in the case above,
 2520             // the first sub shouldn't have a return unless there's a part up top that ends in Exit.
 2521             // So if Exit is encountered before the first hotkey, don't add the return?
 2522             // Even though wrong, the return is harmless because it's never executed?  Except when
 2523             // falling through from above into a hotkey (which probably isn't very valid anyway)?
 2524             // Update: Below must check if there are any true hotkey labels, not just regular labels.
 2525             // Otherwise, a normal (non-hotkey) label in the autoexecute section would count and
 2526             // thus the RETURN would never be added here, even though it should be:
 2527             
 2528             // Notes about the below macro:
 2529             // Fix for v1.0.34: Don't point labels to this particular RETURN so that labels
 2530             // can point to the very first hotkey or hotstring in a script.  For example:
 2531             // Goto Test
 2532             // Test:
 2533             // ^!z::ToolTip Without the fix`, this is never displayed by "Goto Test".
 2534             // UCHAR_MAX signals it not to point any pending labels to this RETURN.
 2535             // mCurrLine = NULL -> signifies that we're in transition, trying to load a new one.
 2536             #define CHECK_mNoHotkeyLabels \
 2537             if (mNoHotkeyLabels)\
 2538             {\
 2539                 mNoHotkeyLabels = false;\
 2540                 if (!AddLine(ACT_RETURN, NULL, UCHAR_MAX))\
 2541                     return FAIL;\
 2542                 mLastLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;\
 2543                 mCurrLine = NULL;\
 2544             }
 2545             CHECK_mNoHotkeyLabels
 2546             // For hotstrings, the below makes the label include leading colon(s) and the full option
 2547             // string (if any) so that the uniqueness of labels is preserved.  For example, we want
 2548             // the following two hotstring labels to be unique rather than considered duplicates:
 2549             // ::abc::
 2550             // :c:abc::
 2551             if (!AddLabel(buf, true)) // Always add a label before adding the first line of its section.
 2552                 return FAIL;
 2553             
 2554             if (hotstring_start)
 2555             {
 2556                 if (!*hotstring_start)
 2557                 {
 2558                     // The following error message won't indicate the correct line number because
 2559                     // the hotstring (as a label) does not actually exist as a line.  But it seems
 2560                     // best to report it this way in case the hotstring is inside a #Include file,
 2561                     // so that the correct file name and approximate line number are shown:
 2562                     return ScriptError(_T("This hotstring is missing its abbreviation."), buf); // Display buf vs. hotkey_flag in case the line is simply "::::".
 2563                 }
 2564                 // In the case of hotstrings, hotstring_start is the beginning of the hotstring itself,
 2565                 // i.e. the character after the second colon.  hotstring_options is the first character
 2566                 // in the options list (which is terminated by a colon).  hotkey_flag is blank or the
 2567                 // hotstring's auto-replace text or same-line action.
 2568                 // v1.0.42: Unlike hotkeys, duplicate hotstrings are not detected.  This is because
 2569                 // hotstrings are less commonly used and also because it requires more code to find
 2570                 // hotstring duplicates (and performs a lot worse if a script has thousands of
 2571                 // hotstrings) because of all the hotstring options.
 2572                 if (!Hotstring::AddHotstring(mLastLabel->mName, mLastLabel, hotstring_options
 2573                     , hotstring_start, hotstring_execute ? _T("") : hotkey_flag, has_continuation_section))
 2574                     return FAIL;
 2575                 // The following section is similar to the one for hotkeys below, but is done after
 2576                 // parsing the hotstring's options. An attempt at combining the two sections actually
 2577                 // increased the final code size, so they're left separate.
 2578                 if (*hotkey_flag)
 2579                 {
 2580                     if (hotstring_execute)
 2581                     {
 2582                         if (!ParseAndAddLine(omit_leading_whitespace(hotkey_flag)))
 2583                             return FAIL;
 2584                         if (ACT_IS_LINE_PARENT(mLastLine->mActionType))
 2585                         {
 2586                             hotkey_flag[-HOTKEY_FLAG_LENGTH] = ':';
 2587                             return ScriptError(ERR_INVALID_SINGLELINE_HOT, buf);
 2588                         }
 2589                     }
 2590                     // This is done for hotstrings with same-line action via 'X' and also auto-replace
 2591                     // hotstrings in case gosub/goto is ever used to jump to their labels:
 2592                     if (!AddLine(ACT_RETURN))
 2593                         return FAIL;
 2594                     mLastLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;
 2595                 }
 2596             }
 2597             else // It's a hotkey vs. hotstring.
 2598             {
 2599                 hook_action = 0; // Set default.
 2600                 if (*hotkey_flag) // This hotkey's action is on the same line as its label.
 2601                 {
 2602                     // Don't add the alt-tabs as a line, since it has no meaning as a script command.
 2603                     // But do put in the Return regardless, in case this label is ever jumped to
 2604                     // via Goto/Gosub:
 2605                     if (   !(hook_action = Hotkey::ConvertAltTab(hotkey_flag, false))   )
 2606                     {
 2607                         if (!ParseAndAddLine(hotkey_flag))
 2608                             return FAIL;
 2609                         if (ACT_IS_LINE_PARENT(mLastLine->mActionType))
 2610                         {
 2611                             hotkey_flag[-HOTKEY_FLAG_LENGTH] = ':';
 2612                             return ScriptError(ERR_INVALID_SINGLELINE_HOT, buf);
 2613                         }
 2614                     }
 2615                     // Also add a Return that's implicit for a single-line hotkey.
 2616                     if (!AddLine(ACT_RETURN))
 2617                         return FAIL;
 2618                     mLastLine->mAttribute = ATTR_LINE_CAN_BE_UNREACHABLE;
 2619                 }
 2620                 if (hk = Hotkey::FindHotkeyByTrueNature(buf, suffix_has_tilde, hook_is_mandatory)) // Parent hotkey found.  Add a child/variant hotkey for it.
 2621                 {
 2622                     if (hook_action) // suffix_has_tilde has always been ignored for these types (alt-tab hotkeys).
 2623                     {
 2624                         // Hotkey::Dynamic() contains logic and comments similar to this, so maintain them together.
 2625                         // An attempt to add an alt-tab variant to an existing hotkey.  This might have
 2626                         // merit if the intention is to make it alt-tab now but to later disable that alt-tab
 2627                         // aspect via the Hotkey cmd to let the context-sensitive variants shine through
 2628                         // (take effect).
 2629                         hk->mHookAction = hook_action;
 2630                     }
 2631                     else
 2632                     {
 2633                         // Detect duplicate hotkey variants to help spot bugs in scripts.
 2634                         if (hk->FindVariant()) // See if there's already a variant matching the current criteria (suffix_has_tilde does not make variants distinct form each other because it would require firing two hotkey IDs in response to pressing one hotkey, which currently isn't in the design).
 2635                         {
 2636                             mCurrLine = NULL;  // Prevents showing unhelpful vicinity lines.
 2637                             return ScriptError(_T("Duplicate hotkey."), buf);
 2638                         }
 2639                         if (!hk->AddVariant(mLastLabel, suffix_has_tilde))
 2640                             return ScriptError(ERR_OUTOFMEM, buf);
 2641                         if (hook_is_mandatory || g_ForceKeybdHook)
 2642                         {
 2643                             // Require the hook for all variants of this hotkey if any variant requires it.
 2644                             // This seems more intuitive than the old behaviour, which required $ or #UseHook
 2645                             // to be used on the *first* variant, even though it affected all variants.
 2646                             hk->mKeybdHookMandatory = true;
 2647                         }
 2648                     }
 2649                 }
 2650                 else // No parent hotkey yet, so create it.
 2651                     if (   !(hk = Hotkey::AddHotkey(mLastLabel, hook_action, mLastLabel->mName, suffix_has_tilde, false))   )
 2652                     {
 2653                         if (hotkey_validity != CONDITION_TRUE)
 2654                             return FAIL; // It already displayed the error.
 2655                         // This hotkey uses a single-character key name, which could be valid on some other
 2656                         // keyboard layout.  Allow the script to start, but warn the user about the problem.
 2657                         // Note that this hotkey's label is still valid even though the hotkey wasn't created.
 2658 #ifndef AUTOHOTKEYSC
 2659                         if (!mIncludeLibraryFunctionsThenExit) // Current keyboard layout is not relevant in /iLib mode.
 2660 #endif
 2661                         {
 2662                             TCHAR msg_text[128];
 2663                             sntprintf(msg_text, _countof(msg_text), _T("Note: The hotkey %s will not be active because it does not exist in the current keyboard layout."), buf);
 2664                             MsgBox(msg_text);
 2665                         }
 2666                     }
 2667             }
 2668             goto continue_main_loop; // In lieu of "continue", for performance.
 2669         } // if (is_label = ...)
 2670 
 2671         // Otherwise, not a hotkey or hotstring.  Check if it's a generic, non-hotkey label:
 2672         if (buf[buf_length - 1] == ':') // Labels must end in a colon (buf was previously rtrimmed).
 2673         {
 2674             if (buf_length == 1) // v1.0.41.01: Properly handle the fact that this line consists of only a colon.
 2675                 return ScriptError(ERR_UNRECOGNIZED_ACTION, buf);
 2676             // Labels (except hotkeys) must contain no whitespace, delimiters, or escape-chars.
 2677             // This is to avoid problems where a legitimate action-line ends in a colon,
 2678             // such as "WinActivate SomeTitle" and "#Include c:".
 2679             // We allow hotkeys to violate this since they may contain commas, and since a normal
 2680             // script line (i.e. just a plain command) is unlikely to ever end in a double-colon:
 2681             for (cp = buf, is_label = true; *cp; ++cp)
 2682                 if (IS_SPACE_OR_TAB(*cp) || *cp == g_delimiter || *cp == g_EscapeChar)
 2683                 {
 2684                     is_label = false;
 2685                     break;
 2686                 }
 2687             if (is_label // It's a generic label, since valid hotkeys and hotstrings have already been handled.
 2688                 && !(buf[buf_length - 2] == ':' && buf_length > 2)) // i.e. allow "::" as a normal label, but consider anything else with double-colon to be an error (reported at a later stage).
 2689             {
 2690                 // v1.0.44.04: Fixed this check by moving it after the above loop.
 2691                 // Above has ensured buf_length>1, so it's safe to check for double-colon:
 2692                 // v1.0.44.03: Don't allow anything that ends in "::" (other than a line consisting only
 2693                 // of "::") to be a normal label.  Assume it's a command instead (if it actually isn't, a
 2694                 // later stage will report it as "invalid hotkey"). This change avoids the situation in
 2695                 // which a hotkey like ^!ä:: is seen as invalid because the current keyboard layout doesn't
 2696                 // have a "ä" key. Without this change, if such a hotkey appears at the top of the script,
 2697                 // its subroutine would execute immediately as a normal label, which would be especially
 2698                 // bad if the hotkey were something like the "Shutdown" command.
 2699                 // Update: Hotkeys with single-character names like ^!ä are now handled earlier, so that
 2700                 // anything else with double-colon can be detected as an error.  The checks above prevent
 2701                 // something like foo:: from being interpreted as a generic label, so when the line fails
 2702                 // to resolve to a command or expression, an error message will be shown.
 2703                 buf[--buf_length] = '\0';  // Remove the trailing colon.
 2704                 if (!_tcsicmp(buf, _T("Default")) && mOpenBlock && mOpenBlock->mPrevLine // "Default:" case.
 2705                     && mOpenBlock->mPrevLine->mActionType == ACT_SWITCH) // For backward-compatibility, it's a normal label in any other case.
 2706                 {
 2707                     if (!AddLine(ACT_CASE))
 2708                         return FAIL;
 2709                 }
 2710                 else
 2711                 {
 2712                     if (!AddLabel(buf, false))
 2713                         return FAIL;
 2714                 }
 2715                 goto continue_main_loop; // In lieu of "continue", for performance.
 2716             }
 2717         }
 2718         // Since above didn't "goto", it's not a label.
 2719         if (*buf == '#')
 2720         {
 2721             saved_line_number = mCombinedLineNumber; // Backup in case IsDirective() processes an include file, which would change mCombinedLineNumber's value.
 2722             switch(IsDirective(buf)) // Note that it may alter the contents of buf, at least in the case of #IfWin.
 2723             {
 2724             case CONDITION_TRUE:
 2725                 // Since the directive may have been a #include which called us recursively,
 2726                 // restore the class's values for these two, which are maintained separately
 2727                 // like this to avoid having to specify them in various calls, especially the
 2728                 // hundreds of calls to ScriptError() and LineError():
 2729                 mCurrFileIndex = source_file_index;
 2730                 mCombinedLineNumber = saved_line_number;
 2731                 goto continue_main_loop; // In lieu of "continue", for performance.
 2732             case FAIL: // IsDirective() already displayed the error.
 2733                 return FAIL;
 2734             //case CONDITION_FALSE: Do nothing; let processing below handle it.
 2735             }
 2736         }
 2737         // Otherwise, treat it as a normal script line.
 2738 
 2739         if (*buf == '{' || *buf == '}')
 2740         {
 2741             if (!AddLine(*buf == '{' ? ACT_BLOCK_BEGIN : ACT_BLOCK_END))
 2742                 return FAIL;
 2743             // Allow any command/action, directive or label to the right of "{" or "}":
 2744             if (   *(buf = omit_leading_whitespace(buf + 1))   )
 2745             {
 2746                 buf_length = _tcslen(buf); // Update.
 2747                 mCurrLine = NULL;  // To signify that we're in transition, trying to load a new line.
 2748                 goto process_completed_line; // Have the main loop process the contents of "buf" as though it came in from the script.
 2749             }
 2750             goto continue_main_loop; // It's just a naked "{" or "}", so no more processing needed for this line.
 2751         }
 2752 
 2753         // Parse the command, assignment or expression, including any same-line open brace or sub-action
 2754         // for ELSE, TRY, CATCH or FINALLY.  Unlike braces at the start of a line (processed above), this
 2755         // does not allow directives or labels to the right of the command.
 2756         if (!ParseAndAddLine(buf))
 2757             return FAIL;
 2758 
 2759 continue_main_loop: // This method is used in lieu of "continue" for performance and code size reduction.
 2760         if (remap_dest_vk)
 2761         {
 2762             // For remapping, decided to use a "macro expansion" approach because I think it's considerably
 2763             // smaller in code size and complexity than other approaches would be.  I originally wanted to
 2764             // do it with the hook by changing the incoming event prior to passing it back out again (for
 2765             // example, a::b would transform an incoming 'a' keystroke into 'b' directly without having
 2766             // to suppress the original keystroke and simulate a new one).  Unfortunately, the low-level
 2767             // hooks apparently do not allow this.  Here is the test that confirmed it:
 2768             // if (event.vkCode == 'A')
 2769             // {
 2770             //  event.vkCode = 'B';
 2771             //  event.scanCode = 0x30; // Or use vk_to_sc(event.vkCode).
 2772             //  return CallNextHookEx(g_KeybdHook, aCode, wParam, lParam);
 2773             // }
 2774             switch (++remap_stage)
 2775             {
 2776             case 1: // Stage 1: Add key-down hotkey label, e.g. *LButton::
 2777                 buf_length = _stprintf(buf, _T("%s::"), remap_source); // Should be no risk of buffer overflow due to prior validation.
 2778                 goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
 2779             case 2: // Stage 2.
 2780                 // Copied into a writable buffer for maintainability: AddLine() might rely on this.
 2781                 // Also, it seems unnecessary to set press-duration to -1 even though the auto-exec section might
 2782                 // have set it to something higher than -1 because:
 2783                 // 1) Press-duration doesn't apply to normal remappings since they use down-only and up-only events.
 2784                 // 2) Although it does apply to remappings such as a::B and a::^b (due to press-duration being
 2785                 //    applied after a change to modifier state), those remappings are fairly rare and supporting
 2786                 //    a non-negative-one press-duration (almost always 0) probably adds a degree of flexibility
 2787                 //    that may be desirable to keep.
 2788                 // 3) SendInput may become the predominant SendMode, so press-duration won't often be in effect anyway.
 2789                 // 4) It has been documented that remappings use the auto-execute section's press-duration.
 2790                 _tcscpy(buf, _T("-1")); // Does NOT need to be "-1, -1" for SetKeyDelay (see above).
 2791                 // The primary reason for adding Key/MouseDelay -1 is to minimize the chance that a one of
 2792                 // these hotkey threads will get buried under some other thread such as a timer, which
 2793                 // would disrupt the remapping if #MaxThreadsPerHotkey is at its default of 1.
 2794                 AddLine(remap_dest_is_mouse ? ACT_SETMOUSEDELAY : ACT_SETKEYDELAY, &buf, 1, NULL); // PressDuration doesn't need to be specified because it doesn't affect down-only and up-only events.
 2795                 if (remap_keybd_to_mouse)
 2796                 {
 2797                     // Since source is keybd and dest is mouse, prevent keyboard auto-repeat from auto-repeating
 2798                     // the mouse button (since that would be undesirable 90% of the time).  This is done
 2799                     // by inserting a single extra IF-statement above the Send that produces the down-event:
 2800                     buf_length = _stprintf(buf, _T("if not GetKeyState(\"%s\")"), remap_dest); // Should be no risk of buffer overflow due to prior validation.
 2801                     remap_stage = 9; // Have it hit special stage 9+1 next time for code reduction purposes.
 2802                     goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
 2803                 }
 2804                 // Otherwise, remap_keybd_to_mouse==false, so fall through to next case.
 2805             case 10:
 2806                 extra_event = _T(""); // Set default.
 2807                 switch (remap_dest_vk)
 2808                 {
 2809                 case VK_LMENU:
 2810                 case VK_RMENU:
 2811                 case VK_MENU:
 2812                     switch (remap_source_vk)
 2813                     {
 2814                     case VK_LCONTROL:
 2815                     case VK_CONTROL:
 2816                         extra_event = _T("{LCtrl up}"); // Somewhat surprisingly, this is enough to make "Ctrl::Alt" properly remap both right and left control.
 2817                         break;
 2818                     case VK_RCONTROL:
 2819                         extra_event = _T("{RCtrl up}");
 2820                         break;
 2821                     // Below is commented out because its only purpose was to allow a shift key remapped to alt
 2822                     // to be able to alt-tab.  But that wouldn't work correctly due to the need for the following
 2823                     // hotkey, which does more harm than good by impacting the normal Alt key's ability to alt-tab
 2824                     // (if the normal Alt key isn't remapped): *Tab::Send {Blind}{Tab}
 2825                     //case VK_LSHIFT:
 2826                     //case VK_SHIFT:
 2827                     //  extra_event = "{LShift up}";
 2828                     //  break;
 2829                     //case VK_RSHIFT:
 2830                     //  extra_event = "{RShift up}";
 2831                     //  break;
 2832                     }
 2833                     break;
 2834                 }
 2835                 mCurrLine = NULL; // v1.0.40.04: Prevents showing misleading vicinity lines for a syntax-error such as %::%
 2836                 _stprintf(buf, _T("{Blind}%s%s{%s DownR}"), extra_event, remap_dest_modifiers, remap_dest); // v1.0.44.05: DownTemp vs. Down. See Send's DownTemp handler for details.
 2837                 if (!AddLine(ACT_SEND, &buf, 1, NULL)) // v1.0.40.04: Check for failure due to bad remaps such as %::%.
 2838                     return FAIL;
 2839                 AddLine(ACT_RETURN);
 2840                 mCurrLine = NULL; // Prevents showing misleading vicinity lines for something like "RAlt up::AppsKey" -> "*RAlt up up::".
 2841                 // Add key-up hotkey label, e.g. *LButton up::
 2842                 buf_length = _stprintf(buf, _T("%s up::"), remap_source); // Should be no risk of buffer overflow due to prior validation.
 2843                 remap_stage = 2; // Adjust to hit stage 3 next time (in case this is stage 10).
 2844                 goto examine_line; // Have the main loop process the contents of "buf" as though it came in from the script.
 2845             case 3: // Stage 3.
 2846                 _tcscpy(buf, _T("-1"));
 2847                 AddLine(remap_dest_is_mouse ? ACT_SETMOUSEDELAY : ACT_SETKEYDELAY, &buf, 1, NULL);
 2848                 _stprintf(buf, _T("{Blind}{%s Up}"), remap_dest); // Unlike the down-event above, remap_dest_modifiers is not included for the up-event; e.g. ^{b up} is inappropriate.
 2849                 AddLine(ACT_SEND, &buf, 1, NULL);
 2850                 AddLine(ACT_RETURN);
 2851                 remap_dest_vk = 0; // Reset to signal that the remapping expansion is now complete.
 2852                 break; // Fall through to the next section so that script loading can resume at the next line.
 2853             }
 2854         } // if (remap_dest_vk)
 2855         // Since above didn't "continue", resume loading script line by line:
 2856         buf = next_buf;
 2857         buf_length = next_buf_length;
 2858         next_buf = (buf == buf1) ? buf2 : buf1;
 2859         // The line above alternates buffers (toggles next_buf to be the unused buffer), which helps
 2860         // performance because it avoids memcpy from buf2 to buf1.
 2861     } // for each whole/constructed line.
 2862 
 2863     if (*pending_buf) // Since this is the last non-comment line, the pending function must be a function call, not a function definition.
 2864     {
 2865         // Somewhat messy to decrement then increment later, but it's probably easier than the
 2866         // alternatives due to the use of "continue" in some places above.
 2867         saved_line_number = mCombinedLineNumber;
 2868         mCombinedLineNumber = pending_buf_line_number; // Done so that any syntax errors that occur during the calls below will report the correct line number.
 2869         if (pending_buf_type != Pending_Func)
 2870             return ScriptError(pending_buf_has_brace ? ERR_MISSING_CLOSE_BRACE : ERR_MISSING_OPEN_BRACE, pending_buf);
 2871         if (!ParseAndAddLine(pending_buf, ACT_EXPRESSION)) // Must be function call vs. definition since otherwise the above would have detected the opening brace beneath it and already cleared pending_function.
 2872             return FAIL;
 2873         mCombinedLineNumber = saved_line_number;
 2874     }
 2875 
 2876     if (mClassObjectCount && !source_file_index) // or mClassProperty, which implies mClassObjectCount != 0.
 2877     {
 2878         // A class definition has not been closed with "}".  Previously this was detected by adding
 2879         // the open and close braces as lines, but this way is simpler and has less overhead.
 2880         // The downside is that the line number won't be shown; however, the class name will.
 2881         // Seems okay not to show mClassProperty->mName since the class is missing "}" as well.
 2882         return ScriptError(ERR_MISSING_CLOSE_BRACE, mClassName);
 2883     }
 2884 
 2885     ++mCombinedLineNumber; // L40: Put the implicit ACT_EXIT on the line after the last physical line (for the debugger).
 2886 
 2887     // This is not required, it is called by the destructor.
 2888     // fp->Close();
 2889     return OK;
 2890 }
 2891 
 2892 
 2893 
 2894 size_t Script::GetLine(LPTSTR aBuf, int aMaxCharsToRead, int aInContinuationSection, TextStream *ts)
 2895 {
 2896     size_t aBuf_length = 0;
 2897 
 2898     if (!aBuf || !ts) return -1;
 2899     if (aMaxCharsToRead < 1) return 0;
 2900     if (  !(aBuf_length = ts->ReadLine(aBuf, aMaxCharsToRead))  ) // end-of-file or error
 2901     {
 2902         *aBuf = '\0';  // Reset since on error, contents added by fgets() are indeterminate.
 2903         return -1;
 2904     }
 2905     if (aBuf[aBuf_length-1] == '\n')
 2906         --aBuf_length;
 2907     aBuf[aBuf_length] = '\0';
 2908 
 2909     if (aInContinuationSection)
 2910     {
 2911         LPTSTR cp = omit_leading_whitespace(aBuf);
 2912         if (aInContinuationSection == CONTINUATION_SECTION_WITHOUT_COMMENTS) // By default, continuation sections don't allow comments (lines beginning with a semicolon are treated as literal text).
 2913         {
 2914             // Caller relies on us to detect the end of the continuation section so that trimming
 2915             // will be done on the final line of the section and so that a comment can immediately
 2916             // follow the closing parenthesis (on the same line).  Example:
 2917             // (
 2918             //  Text
 2919             // ) ; Same line comment.
 2920             if (*cp != ')') // This isn't the last line of the continuation section, so leave the line untrimmed (caller will apply the ltrim setting on its own).
 2921                 return aBuf_length; // Earlier sections are responsible for keeping aBufLength up-to-date with any changes to aBuf.
 2922             //else this line starts with ')', so continue on to later section that checks for a same-line comment on its right side.
 2923         }
 2924         else // aInContinuationSection == CONTINUATION_SECTION_WITH_COMMENTS (i.e. comments are allowed in this continuation section).
 2925         {
 2926             // Fix for v1.0.46.09+: The "com" option shouldn't put "ltrim" into effect.
 2927             if (!_tcsncmp(cp, g_CommentFlag, g_CommentFlagLength)) // Case sensitive.
 2928             {
 2929                 *aBuf = '\0'; // Since this line is a comment, have the caller ignore it.
 2930                 return -2; // Callers tolerate -2 only when in a continuation section.  -2 indicates, "don't include this line at all, not even as a blank line to which the JOIN string (default "\n") will apply.
 2931             }
 2932             if (*cp == ')') // This isn't the last line of the continuation section, so leave the line untrimmed (caller will apply the ltrim setting on its own).
 2933             {
 2934                 ltrim(aBuf); // Ltrim this line unconditionally so that caller will see that it starts with ')' without having to do extra steps.
 2935                 aBuf_length = _tcslen(aBuf); // ltrim() doesn't always return an accurate length, so do it this way.
 2936             }
 2937         }
 2938     }
 2939     // Since above didn't return, either:
 2940     // 1) We're not in a continuation section at all, so apply ltrim() to support semicolons after tabs or
 2941     //    other whitespace.  Seems best to rtrim also.
 2942     // 2) CONTINUATION_SECTION_WITHOUT_COMMENTS but this line is the final line of the section.  Apply
 2943     //    trim() and other logic further below because caller might rely on it.
 2944     // 3) CONTINUATION_SECTION_WITH_COMMENTS (i.e. comments allowed), but this line isn't a comment (though
 2945     //    it may start with ')' and thus be the final line of this section). In either case, need to check
 2946     //    for same-line comments further below.
 2947     if (aInContinuationSection != CONTINUATION_SECTION_WITH_COMMENTS) // Case #1 & #2 above.
 2948     {
 2949         aBuf_length = trim(aBuf);
 2950         if (!_tcsncmp(aBuf, g_CommentFlag, g_CommentFlagLength)) // Case sensitive.
 2951         {
 2952             // Due to other checks, aInContinuationSection==false whenever the above condition is true.
 2953             *aBuf = '\0';
 2954             return 0;
 2955         }
 2956     }
 2957     //else CONTINUATION_SECTION_WITH_COMMENTS (case #3 above), which due to other checking also means that
 2958     // this line isn't a comment (though it might have a comment on its right side, which is checked below).
 2959     // CONTINUATION_SECTION_WITHOUT_COMMENTS would already have returned higher above if this line isn't
 2960     // the last line of the continuation section.
 2961 
 2962     // Handle comment-flags that appear to the right of a valid line.
 2963     LPTSTR cp, prevp;
 2964     for (cp = _tcsstr(aBuf, g_CommentFlag); cp; cp = _tcsstr(cp + g_CommentFlagLength, g_CommentFlag))
 2965     {
 2966         // If no whitespace to its left, it's not a valid comment.
 2967         // We insist on this so that a semi-colon (for example) immediately after
 2968         // a word (as semi-colons are often used) will not be considered a comment.
 2969         prevp = cp - 1;
 2970         if (prevp < aBuf) // should never happen because we already checked above.
 2971         {
 2972             *aBuf = '\0';
 2973             return 0;
 2974         }
 2975         if (IS_SPACE_OR_TAB_OR_NBSP(*prevp)) // consider it to be a valid comment flag
 2976         {
 2977             *prevp = '\0';
 2978             aBuf_length = rtrim_with_nbsp(aBuf, prevp - aBuf); // Since it's our responsibility to return a fully trimmed string.
 2979             break; // Once the first valid comment-flag is found, nothing after it can matter.
 2980         }
 2981         else // No whitespace to the left.
 2982         {
 2983             // The following is done here, at this early stage, to support escaping the comment flag in
 2984             // hotkeys and directives (the latter is mostly for backward-compatibility).
 2985             LPTSTR p;
 2986             for (p = prevp; p > aBuf && *p == g_EscapeChar && p[-1] == g_EscapeChar; p -= 2);
 2987             if (p >= aBuf && *p == g_EscapeChar) // Odd number of escape chars: remove the final escape char.
 2988             {
 2989                 // The following isn't exactly correct because it prevents an include filename from ever
 2990                 // containing the literal string "`;".  This is because attempts to escape the accent via
 2991                 // "``;" are not supported.  This is documented here as a known limitation because fixing
 2992                 // it would probably break existing scripts that rely on the fact that accents do not need
 2993                 // to be escaped inside #Include.  Also, the likelihood of "`;" appearing literally in a
 2994                 // legitimate #Include file seems vanishingly small.
 2995                 tmemmove(prevp, prevp + 1, _tcslen(prevp + 1) + 1);  // +1 for the terminator.
 2996                 --aBuf_length;
 2997                 // Then continue looking for others.
 2998             }
 2999             // else there wasn't any whitespace to its left, so keep looking in case there's
 3000             // another further on in the line.
 3001         }
 3002     } // for()
 3003 
 3004     return aBuf_length; // The above is responsible for keeping aBufLength up-to-date with any changes to aBuf.
 3005 }
 3006 
 3007 
 3008 
 3009 inline ResultType Script::IsDirective(LPTSTR aBuf)
 3010 // aBuf must be a modifiable string since this function modifies it in the case of "#Include %A_ScriptDir%"
 3011 // changes it.  It must also be large enough to accept the replacement of %A_ScriptDir% with a larger string.
 3012 // Returns CONDITION_TRUE, CONDITION_FALSE, or FAIL.
 3013 // Note: Don't assume that every line in the script that starts with '#' is a directive
 3014 // because hotkeys can legitimately start with that as well.  i.e., the following line should
 3015 // not be unconditionally ignored, just because it starts with '#', since it is a valid hotkey:
 3016 // #y::run, notepad
 3017 {
 3018     TCHAR end_flags[] = {' ', '\t', g_delimiter, '\0'}; // '\0' must be last.
 3019     LPTSTR directive_end, parameter_raw;
 3020     if (   !(directive_end = StrChrAny(aBuf, end_flags))   )
 3021     {
 3022         directive_end = aBuf + _tcslen(aBuf); // Point it to the zero terminator.
 3023         parameter_raw = NULL;
 3024     }
 3025     else
 3026         if (!*(parameter_raw = omit_leading_whitespace(directive_end)))
 3027             parameter_raw = NULL;
 3028 
 3029     // The raw parameter retains any leading comma for those directives that need that (none currently).
 3030     // But the following omits that comma:
 3031     LPTSTR parameter;
 3032     if (!parameter_raw)
 3033         parameter = NULL;
 3034     else // Since parameter_raw is non-NULL, it's also non-blank and non-whitespace due to the above checking.
 3035         if (*parameter_raw != g_delimiter)
 3036             parameter = parameter_raw;
 3037         else // It's a delimiter, so "parameter" will be whatever non-whitespace character follows it, if any.
 3038             if (!*(parameter = omit_leading_whitespace(parameter_raw + 1)))
 3039                 parameter = NULL;
 3040             //else leave it set to the value returned by omit_leading_whitespace().
 3041 
 3042     int value; // Helps detect values that are too large, since some of the target globals are UCHAR.
 3043 
 3044     // Use _tcsnicmp() so that a match is found as long as aBuf starts with the string in question.
 3045     // e.g. so that "#SingleInstance, on" will still work too, but
 3046     // "#a::run, something, "#SingleInstance" (i.e. a hotkey) will not be falsely detected
 3047     // due to using a more lenient function such as tcscasestr().
 3048     // UPDATE: Using strlicmp() now so that overlapping names, such as #MaxThreads and #MaxThreadsPerHotkey,
 3049     // won't get mixed up:
 3050     #define IS_DIRECTIVE_MATCH(directive) (!tcslicmp(aBuf, directive, directive_name_length))
 3051     size_t directive_name_length = directive_end - aBuf; // To avoid calculating it every time in the macro above.
 3052 
 3053     bool is_include_again = false; // Set default in case of short-circuit boolean.
 3054     if (IS_DIRECTIVE_MATCH(_T("#Include")) || (is_include_again = IS_DIRECTIVE_MATCH(_T("#IncludeAgain"))))
 3055     {
 3056         // Standalone EXEs ignore this directive since the included files were already merged in
 3057         // with the main file when the script was compiled.  These should have been removed
 3058         // or commented out by Ahk2Exe, but just in case, it's safest to ignore them:
 3059 #ifdef AUTOHOTKEYSC
 3060         return CONDITION_TRUE;
 3061 #else
 3062         // If the below decision is ever changed, be sure to update ahk2exe with the same change:
 3063         // "parameter" is checked rather than parameter_raw for backward compatibility with earlier versions,
 3064         // in which a leading comma is not considered part of the filename.  Although this behavior is incorrect
 3065         // because it prevents files whose names start with a comma from being included without the first
 3066         // delim-comma being there too, it is kept because filenames that start with a comma seem
 3067         // exceedingly rare.  As a workaround, the script can do #Include ,,FilenameWithLeadingComma.ahk
 3068         if (!parameter)
 3069             return ScriptError(ERR_PARAM1_REQUIRED, aBuf);
 3070         // v1.0.32:
 3071         bool ignore_load_failure = (parameter[0] == '*' && ctoupper(parameter[1]) == 'I'); // Relies on short-circuit boolean order.
 3072         if (ignore_load_failure)
 3073         {
 3074             parameter += 2;
 3075             if (IS_SPACE_OR_TAB(*parameter)) // Skip over at most one space or tab, since others might be a literal part of the filename.
 3076                 ++parameter;
 3077         }
 3078 
 3079         if (*parameter == '<') // Support explicitly-specified <standard_lib_name>.
 3080         {
 3081             LPTSTR parameter_end = _tcschr(parameter, '>');
 3082             if (parameter_end && !parameter_end[1])
 3083             {
 3084                 ++parameter; // Remove '<'.
 3085                 *parameter_end = '\0'; // Remove '>'.
 3086                 bool error_was_shown, file_was_found;
 3087                 // Save the working directory.
 3088                 LPTSTR prev_dir = GetWorkingDir();
 3089                 // Attempt to include a script file based on the same rules as func() auto-include:
 3090                 FindFuncInLibrary(parameter, parameter_end - parameter, error_was_shown, file_was_found, false);
 3091                 // Restore the working directory so that any ordinary #includes will work correctly.
 3092                 if (prev_dir)
 3093                 {
 3094                     SetCurrentDirectory(prev_dir);
 3095                     free(prev_dir);
 3096                 }
 3097                 // If any file was included, consider it a success; i.e. allow #include <lib> and #include <lib_func>.
 3098                 if (!error_was_shown && (file_was_found || ignore_load_failure))
 3099                     return CONDITION_TRUE;
 3100                 *parameter_end = '>'; // Restore '>' for display to the user.
 3101                 return error_was_shown ? FAIL : ScriptError(_T("Function library not found."), aBuf);
 3102             }
 3103             //else invalid syntax; treat it as a regular #include which will almost certainly fail.
 3104         }
 3105 
 3106         LPTSTR include_path;
 3107         if (!DerefInclude(include_path, parameter))
 3108             return FAIL;
 3109 
 3110         DWORD attr = GetFileAttributes(include_path);
 3111         if (attr != 0xFFFFFFFF && (attr & FILE_ATTRIBUTE_DIRECTORY)) // File exists and its a directory (possibly A_ScriptDir or A_AppData set above).
 3112         {
 3113             // v1.0.35.11 allow changing of load-time directory to increase flexibility.  This feature has
 3114             // been asked for directly or indirectly several times.
 3115             // If a script ever wants to use a string like "%A_ScriptDir%" literally in an include's filename,
 3116             // that would not work.  But that seems too rare to worry about.
 3117             // v1.0.45.01: Call SetWorkingDir() vs. SetCurrentDirectory() so that it succeeds even for a root
 3118             // drive like C: that lacks a backslash (see SetWorkingDir() for details).
 3119             SetWorkingDir(include_path);
 3120             free(include_path);
 3121             return CONDITION_TRUE;
 3122         }
 3123         // Since above didn't return, it's a file (or non-existent file, in which case the below will display
 3124         // the error).  This will also display any other errors that occur:
 3125         ResultType result = LoadIncludedFile(include_path, is_include_again, ignore_load_failure) ? CONDITION_TRUE : FAIL;
 3126         free(include_path);
 3127         return result;
 3128 #endif
 3129     }
 3130 
 3131     if (IS_DIRECTIVE_MATCH(_T("#NoEnv")))
 3132     {
 3133         g_NoEnv = TRUE;
 3134         return CONDITION_TRUE;
 3135     }
 3136     if (IS_DIRECTIVE_MATCH(_T("#NoTrayIcon")))
 3137     {
 3138         g_NoTrayIcon = true;
 3139         return CONDITION_TRUE;
 3140     }
 3141     if (IS_DIRECTIVE_MATCH(_T("#Persistent")))
 3142     {
 3143         g_persistent = true;
 3144         return CONDITION_TRUE;
 3145     }
 3146     if (IS_DIRECTIVE_MATCH(_T("#SingleInstance")))
 3147     {
 3148         g_AllowOnlyOneInstance = SINGLE_INSTANCE_PROMPT; // Set default.
 3149         if (parameter)
 3150         {
 3151             if (!_tcsicmp(parameter, _T("Force")))
 3152                 g_AllowOnlyOneInstance = SINGLE_INSTANCE_REPLACE;
 3153             else if (!_tcsicmp(parameter, _T("Ignore")))
 3154                 g_AllowOnlyOneInstance = SINGLE_INSTANCE_IGNORE;
 3155             else if (!_tcsicmp(parameter, _T("Off")))
 3156                 g_AllowOnlyOneInstance = SINGLE_INSTANCE_OFF;
 3157         }
 3158         return CONDITION_TRUE;
 3159     }
 3160     if (IS_DIRECTIVE_MATCH(_T("#InstallKeybdHook")))
 3161     {
 3162         Hotkey::RequireHook(HOOK_KEYBD);
 3163         return CONDITION_TRUE;
 3164     }
 3165     if (IS_DIRECTIVE_MATCH(_T("#InstallMouseHook")))
 3166     {
 3167         Hotkey::RequireHook(HOOK_MOUSE);
 3168         return CONDITION_TRUE;
 3169     }
 3170     if (IS_DIRECTIVE_MATCH(_T("#UseHook")))
 3171     {
 3172         g_ForceKeybdHook = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
 3173         return CONDITION_TRUE;
 3174     }
 3175 
 3176     // L4: Handle #if (expression) directive.
 3177     if (IS_DIRECTIVE_MATCH(_T("#If")))
 3178     {
 3179         if (!parameter) // The omission of the parameter indicates that any existing criteria should be turned off.
 3180         {
 3181             g_HotCriterion = NULL; // Indicate that no criteria are in effect for subsequent hotkeys.
 3182             return CONDITION_TRUE;
 3183         }
 3184 
 3185         // Check for a duplicate #If expression;
 3186         //  - Prevents duplicate hotkeys under separate copies of the same expression.
 3187         //  - Hotkey,If would only be able to select the first expression with the given source code.
 3188         //  - Conserves memory.
 3189         if (g_HotCriterion = FindHotkeyIfExpr(parameter))
 3190             return CONDITION_TRUE;
 3191         
 3192         Func *current_func = g->CurrentFunc;
 3193         g->CurrentFunc = NULL; // Use global scope.
 3194         mNoUpdateLabels = true; // Avoid pointing any pending labels at this line.
 3195         
 3196         if (!ParseAndAddLine(parameter, ACT_HOTKEY_IF, 0, _T(""))) // Pass non-NULL for aActionName.
 3197             return FAIL;
 3198         
 3199         mNoUpdateLabels = false;
 3200         g->CurrentFunc = current_func;
 3201         
 3202         Line *hot_expr_line = mLastLine;
 3203 
 3204         // Set the new criterion.
 3205         if (  !(g_HotCriterion = AddHotkeyIfExpr())  )
 3206             return FAIL;
 3207         g_HotCriterion->Type = HOT_IF_EXPR;
 3208         g_HotCriterion->ExprLine = hot_expr_line;
 3209         g_HotCriterion->WinTitle = hot_expr_line->mArg[0].text;
 3210         g_HotCriterion->WinText = _T("");
 3211         return CONDITION_TRUE;
 3212     }
 3213 
 3214     // L4: Allow #if timeout to be adjusted.
 3215     if (IS_DIRECTIVE_MATCH(_T("#IfTimeout")))
 3216     {
 3217         if (parameter)
 3218             g_HotExprTimeout = ATOU(parameter);
 3219         return CONDITION_TRUE;
 3220     }
 3221 
 3222     if (!_tcsnicmp(aBuf, _T("#IfWin"), 6))
 3223     {
 3224         HotCriterionType hot_criterion;
 3225         bool invert = !_tcsnicmp(aBuf + 6, _T("Not"), 3);
 3226         if (!_tcsnicmp(aBuf + (invert ? 9 : 6), _T("Active"), 6)) // It matches #IfWin[Not]Active.
 3227             hot_criterion = invert ? HOT_IF_NOT_ACTIVE : HOT_IF_ACTIVE;
 3228         else if (!_tcsnicmp(aBuf + (invert ? 9 : 6), _T("Exist"), 5))
 3229             hot_criterion = invert ? HOT_IF_NOT_EXIST : HOT_IF_EXIST;
 3230         else // It starts with #IfWin but isn't Active or Exist: Don't alter g_HotCriterion.
 3231             return CONDITION_FALSE; // Indicate unknown directive since there are currently no other possibilities.
 3232         if (!parameter) // The omission of the parameter indicates that any existing criteria should be turned off.
 3233         {
 3234             g_HotCriterion = NULL; // Indicate that no criteria are in effect for subsequent hotkeys.
 3235             return CONDITION_TRUE;
 3236         }
 3237         LPTSTR hot_win_title = parameter, hot_win_text; // Set default for title; text is determined later.
 3238         // Scan for the first non-escaped comma.  If there is one, it marks the second parameter: WinText.
 3239         LPTSTR cp, first_non_escaped_comma;
 3240         for (first_non_escaped_comma = NULL, cp = hot_win_title; ; ++cp)  // Increment to skip over the symbol just found by the inner for().
 3241         {
 3242             for (; *cp && !(*cp == g_EscapeChar || *cp == g_delimiter || *cp == g_DerefChar); ++cp);  // Find the next escape char, comma, or %.
 3243             if (!*cp) // End of string was found.
 3244                 break;
 3245 #define ERR_ESCAPED_COMMA_PERCENT _T("Literal commas and percent signs must be escaped (e.g. `%)")
 3246             if (*cp == g_DerefChar)
 3247                 return ScriptError(ERR_ESCAPED_COMMA_PERCENT, aBuf);
 3248             if (*cp == g_delimiter) // non-escaped delimiter was found.
 3249             {
 3250                 // Preserve the ability to add future-use parameters such as section of window
 3251                 // over which the mouse is hovering, e.g. #IfWinActive, Untitled - Notepad,, TitleBar
 3252                 if (first_non_escaped_comma) // A second non-escaped comma was found.
 3253                     return ScriptError(ERR_ESCAPED_COMMA_PERCENT, aBuf);
 3254                 // Otherwise:
 3255                 first_non_escaped_comma = cp;
 3256                 continue; // Check if there are any more non-escaped commas.
 3257             }
 3258             // Otherwise, an escape character was found, so skip over the next character (if any).
 3259             if (!*(++cp)) // The string unexpectedly ends in an escape character, so avoid out-of-bounds.
 3260                 break;
 3261             // Otherwise, the ++cp above has skipped over the escape-char itself, and the loop's ++cp will now
 3262             // skip over the char-to-be-escaped, which is not the one we want (even if it is a comma).
 3263         }
 3264         if (first_non_escaped_comma) // Above found a non-escaped comma, so there is a second parameter (WinText).
 3265         {
 3266             // Omit whitespace to (seems best to conform to convention/expectations rather than give
 3267             // strange whitespace flexibility that would likely cause unwanted bugs due to inadvertently
 3268             // have two spaces instead of one).  The user may use `s and `t to put literal leading/trailing
 3269             // spaces/tabs into these parameters.
 3270             hot_win_text = omit_leading_whitespace(first_non_escaped_comma + 1);
 3271             *first_non_escaped_comma = '\0'; // Terminate at the comma to split off hot_win_title on its own.
 3272             rtrim(hot_win_title, first_non_escaped_comma - hot_win_title);  // Omit whitespace (see similar comment above).
 3273             // The following must be done only after trimming and omitting whitespace above, so that
 3274             // `s and `t can be used to insert leading/trailing spaces/tabs.  ConvertEscapeSequences()
 3275             // also supports insertion of literal commas via escaped sequences.
 3276             ConvertEscapeSequences(hot_win_text, g_EscapeChar, true);
 3277         }
 3278         else
 3279             hot_win_text = _T(""); // And leave hot_win_title set to the entire string because there's only one parameter.
 3280         // The following must be done only after trimming and omitting whitespace above (see similar comment above).
 3281         ConvertEscapeSequences(hot_win_title, g_EscapeChar, true);
 3282         // The following also handles the case where both title and text are blank, which could happen
 3283         // due to something weird but legit like: #IfWinActive, ,
 3284         if (!SetHotkeyCriterion(hot_criterion, hot_win_title, hot_win_text))
 3285             return ScriptError(ERR_OUTOFMEM); // So rare that no second param is provided (since its contents may have been temp-terminated or altered above).
 3286         return CONDITION_TRUE;
 3287     } // Above completely handles all directives and non-directives that start with "#IfWin".
 3288 
 3289     if (IS_DIRECTIVE_MATCH(_T("#Hotstring")))
 3290     {
 3291         if (parameter)
 3292         {
 3293             LPTSTR suboption = tcscasestr(parameter, _T("EndChars"));
 3294             if (suboption)
 3295             {
 3296                 // Since it's not realistic to have only a couple, spaces and literal tabs
 3297                 // must be included in between other chars, e.g. `n `t has a space in between.
 3298                 // Also, EndChar  \t  will have a space and a tab since there are two spaces
 3299                 // after the word EndChar.
 3300                 if (    !(parameter = StrChrAny(suboption, _T("\t ")))   )
 3301                     return CONDITION_TRUE;
 3302                 tcslcpy(g_EndChars, ++parameter, _countof(g_EndChars));
 3303                 ConvertEscapeSequences(g_EndChars, g_EscapeChar, false);
 3304                 return CONDITION_TRUE;
 3305             }
 3306             if (!_tcsnicmp(parameter, _T("NoMouse"), 7)) // v1.0.42.03
 3307             {
 3308                 g_HSResetUponMouseClick = false;
 3309                 return CONDITION_TRUE;
 3310             }
 3311             // Otherwise assume it's a list of options.  Note that for compatibility with its
 3312             // other caller, it will stop at end-of-string or ':', whichever comes first.
 3313             Hotstring::ParseOptions(parameter, g_HSPriority, g_HSKeyDelay, g_HSSendMode, g_HSCaseSensitive
 3314                 , g_HSConformToCase, g_HSDoBackspace, g_HSOmitEndChar, g_HSSendRaw, g_HSEndCharRequired
 3315                 , g_HSDetectWhenInsideWord, g_HSDoReset, g_HSSameLineAction);
 3316         }
 3317         return CONDITION_TRUE;
 3318     }
 3319 
 3320     if (IS_DIRECTIVE_MATCH(_T("#HotkeyModifierTimeout")))
 3321     {
 3322         if (parameter)
 3323             g_HotkeyModifierTimeout = ATOI(parameter);  // parameter was set to the right position by the above macro
 3324         return CONDITION_TRUE;
 3325     }
 3326     if (IS_DIRECTIVE_MATCH(_T("#HotkeyInterval")))
 3327     {
 3328         if (parameter)
 3329         {
 3330             g_HotkeyThrottleInterval = ATOI(parameter);  // parameter was set to the right position by the above macro
 3331             if (g_HotkeyThrottleInterval < 10) // values under 10 wouldn't be useful due to timer granularity.
 3332                 g_HotkeyThrottleInterval = 10;
 3333         }
 3334         return CONDITION_TRUE;
 3335     }
 3336     if (IS_DIRECTIVE_MATCH(_T("#MaxHotkeysPerInterval")))
 3337     {
 3338         if (parameter)
 3339         {
 3340             g_MaxHotkeysPerInterval = ATOI(parameter);  // parameter was set to the right position by the above macro
 3341             if (g_MaxHotkeysPerInterval < 1) // sanity check
 3342                 g_MaxHotkeysPerInterval = 1;
 3343         }
 3344         return CONDITION_TRUE;
 3345     }
 3346     if (IS_DIRECTIVE_MATCH(_T("#MaxThreadsPerHotkey")))
 3347     {
 3348         if (parameter)
 3349         {
 3350             // Use value as a temp holder since it's int vs. UCHAR and can thus detect very large or negative values:
 3351             value = ATOI(parameter);  // parameter was set to the right position by the above macro
 3352             if (value > MAX_THREADS_LIMIT) // For now, keep this limited to prevent stack overflow due to too many pseudo-threads.
 3353                 value = MAX_THREADS_LIMIT; // UPDATE: To avoid array overflow, this limit must by obeyed except where otherwise documented.
 3354             else if (value < 1)
 3355                 value = 1;
 3356             g_MaxThreadsPerHotkey = value; // Note: g_MaxThreadsPerHotkey is UCHAR.
 3357         }
 3358         return CONDITION_TRUE;
 3359     }
 3360     if (IS_DIRECTIVE_MATCH(_T("#MaxThreadsBuffer")))
 3361     {
 3362         g_MaxThreadsBuffer = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
 3363         return CONDITION_TRUE;
 3364     }
 3365     if (IS_DIRECTIVE_MATCH(_T("#MaxThreads")))
 3366     {
 3367         if (parameter)
 3368         {
 3369             value = ATOI(parameter);  // parameter was set to the right position by the above macro
 3370             if (value > MAX_THREADS_LIMIT) // For now, keep this limited to prevent stack overflow due to too many pseudo-threads.
 3371                 value = MAX_THREADS_LIMIT; // UPDATE: To avoid array overflow, this limit must by obeyed except where otherwise documented.
 3372             else if (value < 1)
 3373                 value = 1;
 3374             g_MaxThreadsTotal = value;
 3375         }
 3376         return CONDITION_TRUE;
 3377     }
 3378 
 3379     if (IS_DIRECTIVE_MATCH(_T("#ClipboardTimeout")))
 3380     {
 3381         if (parameter)
 3382             g_ClipboardTimeout = ATOI(parameter);  // parameter was set to the right position by the above macro
 3383         return CONDITION_TRUE;
 3384     }
 3385     if (IS_DIRECTIVE_MATCH(_T("#LTrim")))
 3386     {
 3387         g_ContinuationLTrim = !parameter || Line::ConvertOnOff(parameter) != TOGGLED_OFF;
 3388         return CONDITION_TRUE;
 3389     }
 3390 
 3391     if (IS_DIRECTIVE_MATCH(_T("#WinActivateForce")))
 3392     {
 3393         g_WinActivateForce = true;
 3394         return CONDITION_TRUE;
 3395     }
 3396     if (IS_DIRECTIVE_MATCH(_T("#ErrorStdOut")))
 3397     {
 3398         SetErrorStdOut(parameter);
 3399         return CONDITION_TRUE;
 3400     }
 3401     if (IS_DIRECTIVE_MATCH(_T("#MaxMem")))
 3402     {
 3403         if (parameter)
 3404         {
 3405             double valuef = ATOF(parameter);  // parameter was set to the right position by the above macro
 3406             if (valuef > 4095)  // Don't exceed capacity of VarSizeType, which is currently a DWORD (4 gig).
 3407                 valuef = 4095;  // Don't use 4096 since that might be a special/reserved value for some functions.
 3408             else if (valuef  < 1)
 3409                 valuef = 1;
 3410             g_MaxVarCapacity = (VarSizeType)(valuef * 1024 * 1024);
 3411         }
 3412         return CONDITION_TRUE;
 3413     }
 3414     if (IS_DIRECTIVE_MATCH(_T("#KeyHistory")))
 3415     {
 3416         if (parameter)
 3417         {
 3418             g_MaxHistoryKeys = ATOI(parameter);  // parameter was set to the right position by the above macro
 3419             if (g_MaxHistoryKeys < 0)
 3420                 g_MaxHistoryKeys = 0;
 3421             else if (g_MaxHistoryKeys > 500)
 3422                 g_MaxHistoryKeys = 500;
 3423             // Above: There are two reasons for limiting the history file to 500 keystrokes:
 3424             // 1) GetHookStatus() only has a limited size buffer in which to transcribe the keystrokes.
 3425             //    500 events is about what you would expect to fit in a 32 KB buffer (it the unlikely event
 3426             //    that the transcribed events create too much text, the text will be truncated, so it's
 3427             //    not dangerous anyway).
 3428             // 2) To reduce the impression that AutoHotkey designed for key logging (the key history file
 3429             //    is in a very unfriendly format that type of key logging anyway).
 3430         }
 3431         return CONDITION_TRUE;
 3432     }
 3433 
 3434     // For the below series, it seems okay to allow the comment flag to contain other reserved chars,
 3435     // such as DerefChar, since comments are evaluated, and then taken out of the game at an earlier
 3436     // stage than DerefChar and the other special chars.
 3437     if (IS_DIRECTIVE_MATCH(_T("#CommentFlag")))
 3438     {
 3439         if (parameter)
 3440         {
 3441             if (!*(parameter + 1))  // i.e. the length is 1
 3442             {
 3443                 // Don't allow '#' since it's the preprocessor directive symbol being used here.
 3444                 // Seems ok to allow "." to be the comment flag, since other constraints mandate
 3445                 // that at least one space or tab occur to its left for it to be considered a
 3446                 // comment marker.
 3447                 if (*parameter == '#' || *parameter == g_DerefChar || *parameter == g_EscapeChar || *parameter == g_delimiter)
 3448                     return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3449                 // Exclude hotkey definition chars, such as ^ and !, because otherwise
 3450                 // the following example wouldn't work:
 3451                 // User defines ! as the comment flag.
 3452                 // The following hotkey would never be in effect since it's considered to
 3453                 // be commented out:
 3454                 // !^a::run,notepad
 3455                 if (*parameter == '!' || *parameter == '^' || *parameter == '+' || *parameter == '$' || *parameter == '~' || *parameter == '*'
 3456                     || *parameter == '<' || *parameter == '>')
 3457                     // Note that '#' is already covered by the other stmt. above.
 3458                     return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3459             }
 3460             tcslcpy(g_CommentFlag, parameter, MAX_COMMENT_FLAG_LENGTH + 1);
 3461             g_CommentFlagLength = _tcslen(g_CommentFlag);  // Keep this in sync with above.
 3462         }
 3463         return CONDITION_TRUE;
 3464     }
 3465     if (IS_DIRECTIVE_MATCH(_T("#EscapeChar")))
 3466     {
 3467         if (parameter)
 3468         {
 3469             // Don't allow '.' since that can be part of literal floating point numbers:
 3470             if (   *parameter == '#' || *parameter == g_DerefChar || *parameter == g_delimiter || *parameter == '.'
 3471                 || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag)   )
 3472                 return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3473             g_EscapeChar = *parameter;
 3474         }
 3475         return CONDITION_TRUE;
 3476     }
 3477     if (IS_DIRECTIVE_MATCH(_T("#DerefChar")))
 3478     {
 3479         if (parameter)
 3480         {
 3481             if (   *parameter == g_EscapeChar || *parameter == g_delimiter || *parameter == '.'
 3482                 || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag)   ) // Fix for v1.0.47.05: Allow deref char to be # as documented.
 3483                 return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3484             g_DerefChar = *parameter;
 3485         }
 3486         return CONDITION_TRUE;
 3487     }
 3488     if (IS_DIRECTIVE_MATCH(_T("#Delimiter")))
 3489     {
 3490         // Attempts to change the delimiter to its starting default (comma) are ignored.
 3491         // For example, "#Delimiter ," isn't meaningful if the delimiter already is a comma,
 3492         // which is good because "parameter" has already assumed that the comma is accidental
 3493         // (not a symbol) and omitted it.
 3494         if (parameter)
 3495         {
 3496             if (   *parameter == '#' || *parameter == g_EscapeChar || *parameter == g_DerefChar || *parameter == '.'
 3497                 || (g_CommentFlagLength == 1 && *parameter == *g_CommentFlag)   )
 3498                 return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3499             g_delimiter = *parameter;
 3500         }
 3501         return CONDITION_TRUE;
 3502     }
 3503 
 3504     if (IS_DIRECTIVE_MATCH(_T("#MenuMaskKey")))
 3505     {
 3506         // L38: Allow scripts to specify an alternate "masking" key in place of VK_CONTROL.
 3507         if (parameter)
 3508         {
 3509             // Testing shows that sending an event with zero VK but non-zero SC fails to suppress
 3510             // the Start menu (although it does suppress the window menu).  However, checking the
 3511             // validity of the key seems more correct than requiring g_MenuMaskKeyVK != 0, and
 3512             // adds flexibility at very little cost.  Note that this use of TextToVKandSC()'s
 3513             // return value (vs. checking VK|SC) allows vk00sc000 to turn off masking altogether.
 3514             if (TextToVKandSC(parameter, g_MenuMaskKeyVK, g_MenuMaskKeySC))
 3515                 return CONDITION_TRUE;
 3516             //else: It's okay that above modified our variables since we're about to exit.
 3517         }
 3518         return ScriptError(parameter ? ERR_PARAM1_INVALID : ERR_PARAM1_REQUIRED, aBuf);
 3519     }
 3520     if (IS_DIRECTIVE_MATCH(_T("#InputLevel")))
 3521     {
 3522         // All hotkeys declared after this directive are assigned the specified InputLevel.
 3523         // Input generated at a given SendLevel can only trigger hotkeys that belong to a
 3524         // lower InputLevel. Hotkeys at the lowest level (0) cannot be triggered by any
 3525         // generated input (the same behavior as AHK versions before this feature).
 3526         // The default level is 0.
 3527 
 3528         int group = parameter ? ATOI(parameter) : 0;
 3529         if (!SendLevelIsValid(group))
 3530             return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3531 
 3532         g_InputLevel = group;
 3533         return CONDITION_TRUE;
 3534     }
 3535     if (IS_DIRECTIVE_MATCH(_T("#Warn")))
 3536     {
 3537         if (!parameter)
 3538             parameter = _T("");
 3539 
 3540         LPTSTR param1_end = _tcschr(parameter, g_delimiter);
 3541         LPTSTR param2 = _T("");
 3542         if (param1_end)
 3543         {
 3544             param2 = omit_leading_whitespace(param1_end + 1);
 3545             param1_end = omit_trailing_whitespace(parameter, param1_end - 1);
 3546             param1_end[1] = '\0';
 3547         }
 3548 
 3549         int i;
 3550 
 3551         static LPTSTR sWarnTypes[] = { WARN_TYPE_STRINGS };
 3552         WarnType warnType = WARN_ALL; // Set default.
 3553         if (*parameter)
 3554         {
 3555             for (i = 0; ; ++i)
 3556             {
 3557                 if (i == _countof(sWarnTypes))
 3558                     return ScriptError(ERR_PARAM1_INVALID, aBuf);
 3559                 if (!_tcsicmp(parameter, sWarnTypes[i]))
 3560                     break;
 3561             }
 3562             warnType = (WarnType)i;
 3563         }
 3564 
 3565         static LPTSTR sWarnModes[] = { WARN_MODE_STRINGS };
 3566         WarnMode warnMode = WARNMODE_MSGBOX; // Set default.
 3567         if (*param2)
 3568         {
 3569             for (i = 0; ; ++i)
 3570             {
 3571                 if (i == _countof(sWarnModes))
 3572                     return ScriptError(ERR_PARAM2_INVALID, param2);
 3573                 if (!_tcsicmp(param2, sWarnModes[i]))
 3574                     break;
 3575             }
 3576             warnMode = (WarnMode)i;
 3577         }
 3578 
 3579         // The following series of "if" statements was confirmed to produce smaller code
 3580         // than a switch() with a final case WARN_ALL that duplicates all of the assignments:
 3581 
 3582         if (warnType == WARN_USE_UNSET_LOCAL || warnType == WARN_ALL)
 3583             g_Warn_UseUnsetLocal = warnMode;
 3584 
 3585         if (warnType == WARN_USE_UNSET_GLOBAL || warnType == WARN_ALL)
 3586             g_Warn_UseUnsetGlobal = warnMode;
 3587 
 3588         if (warnType == WARN_USE_ENV || warnType == WARN_ALL)
 3589             g_Warn_UseEnv = warnMode;
 3590 
 3591         if (warnType == WARN_LOCAL_SAME_AS_GLOBAL || warnType == WARN_ALL)
 3592             g_Warn_LocalSameAsGlobal = warnMode;
 3593 
 3594         if (warnType == WARN_CLASS_OVERWRITE || warnType == WARN_ALL)
 3595             g_Warn_ClassOverwrite = warnMode;
 3596 
 3597         if (warnType == WARN_UNREACHABLE || warnType == WARN_ALL)
 3598             g_Warn_Unreachable = warnMode;
 3599 
 3600         return CONDITION_TRUE;
 3601     }
 3602 
 3603     if (IS_DIRECTIVE_MATCH(_T("#Requires")))
 3604     {
 3605 #ifdef AUTOHOTKEYSC
 3606         return CONDITION_TRUE; // Omit the checks for compiled scripts to reduce code size.
 3607 #else
 3608         if (!parameter)
 3609             return ScriptError(ERR_PARAM1_REQUIRED);
 3610 
 3611         bool show_autohotkey_version = false;
 3612         if (!_tcsnicmp(parameter, _T("AutoHotkey"), 10))
 3613         {
 3614             if (!parameter[10]) // Just #requires AutoHotkey; would seem silly to warn the user in this case.
 3615                 return CONDITION_TRUE;
 3616 
 3617             if (IS_SPACE_OR_TAB(parameter[10]))
 3618             {
 3619                 auto cp = omit_leading_whitespace(parameter + 11);
 3620                 if (*cp == 'v')
 3621                     ++cp;
 3622                 if (!_tcsncmp(cp, T_AHK_VERSION, 3) && (!cp[3] || cp[3] == '.') // Major version matches.
 3623                     && CompareVersion(cp, T_AHK_VERSION) <= 0) // Required minor and patch versions <= A_AhkVersion (also taking into account any pre-release suffix).
 3624                     return CONDITION_TRUE;
 3625                 show_autohotkey_version = true;
 3626             }
 3627         }
 3628         TCHAR buf[100];
 3629         sntprintf(buf, _countof(buf), _T("This script requires %s%s.")
 3630             , parameter, show_autohotkey_version ? _T(", but you have v") T_AHK_VERSION : _T(""));
 3631         return ScriptError(buf);
 3632 #endif
 3633     }
 3634 
 3635     // Otherwise, report that this line isn't a directive:
 3636     return CONDITION_FALSE;
 3637 }
 3638 
 3639 
 3640 
 3641 void ScriptTimer::Disable()
 3642 {
 3643     mEnabled = false;
 3644     --g_script.mTimerEnabledCount;
 3645     if (!g_script.mTimerEnabledCount && !g_nLayersNeedingTimer && !Hotkey::sJoyHotkeyCount)
 3646         KILL_MAIN_TIMER
 3647     // Above: If there are now no enabled timed subroutines, kill the main timer since there's no other
 3648     // reason for it to exist if we're here.   This is because or direct or indirect caller is
 3649     // currently always ExecUntil(), which doesn't need the timer while its running except to
 3650     // support timed subroutines.  UPDATE: The above is faulty; Must also check g_nLayersNeedingTimer
 3651     // because our caller can be one that still needs a timer as proven by this script that
 3652     // hangs otherwise:
 3653     //SetTimer, Test, on 
 3654     //Sleep, 1000 
 3655     //msgbox, done
 3656     //return
 3657     //Test: 
 3658     //SetTimer, Test, off 
 3659     //return
 3660 }
 3661 
 3662 
 3663 
 3664 ResultType Script::UpdateOrCreateTimer(IObject *aLabel, LPTSTR aPeriod, LPTSTR aPriority, bool aEnable
 3665     , bool aUpdatePriorityOnly)
 3666 // Caller should specific a blank aPeriod to prevent the timer's period from being changed
 3667 // (i.e. if caller just wants to turn on or off an existing timer).  But if it does this
 3668 // for a non-existent timer, that timer will be created with the default period as specified in
 3669 // the constructor.
 3670 {
 3671     ScriptTimer *timer;
 3672     for (timer = mFirstTimer; timer != NULL; timer = timer->mNextTimer)
 3673         if (timer->mLabel == aLabel) // Match found.
 3674             break;
 3675     bool timer_existed = (timer != NULL);
 3676     if (!timer_existed)  // Create it.
 3677     {
 3678         if (   !(timer = new ScriptTimer(aLabel))   )
 3679             return ScriptError(ERR_OUTOFMEM);
 3680         if (!mFirstTimer)
 3681             mFirstTimer = mLastTimer = timer;
 3682         else
 3683         {
 3684             mLastTimer->mNextTimer = timer;
 3685             // This must be done after the above:
 3686             mLastTimer = timer;
 3687         }
 3688         ++mTimerCount;
 3689     }
 3690     // Update its members:
 3691     if (aEnable && !timer->mEnabled) // Must check both or the mTimerEnabledCount below will be wrong.
 3692     {
 3693         // The exception is if the timer already existed but the caller only wanted its priority changed:
 3694         if (!(timer_existed && aUpdatePriorityOnly))
 3695         {
 3696             timer->mEnabled = true;
 3697             ++mTimerEnabledCount;
 3698             SET_MAIN_TIMER  // Ensure the API timer is always running when there is at least one enabled timed subroutine.
 3699         }
 3700         //else do nothing, leave it disabled.
 3701     }
 3702     else if (!aEnable && timer->mEnabled) // Must check both or the below count will be wrong.
 3703         timer->Disable();
 3704 
 3705     aPeriod = omit_leading_whitespace(aPeriod); // This causes A_Space to be treated as "omitted" rather than zero, so may change the behaviour of some poorly-written scripts, but simplifies the check below which allows -0 to work.
 3706     if (*aPeriod) // Caller wanted us to update this member.
 3707     {
 3708         __int64 period = ATOI64(aPeriod);
 3709         if (*aPeriod == '-') // v1.0.46.16: Support negative periods to mean "run only once".
 3710         {
 3711             timer->mRunOnlyOnce = true;
 3712             timer->mPeriod = (DWORD)-period;
 3713         }
 3714         else // Positive number.  v1.0.36.33: Changed from int to DWORD, and ATOI to ATOU, to double its capacity:
 3715         {
 3716             timer->mPeriod = (DWORD)period; // Always use this method & check to retain compatibility with existing scripts.
 3717             timer->mRunOnlyOnce = false;
 3718         }
 3719     }
 3720 
 3721     if (*aPriority) // Caller wants this member to be changed from its current or default value.
 3722         timer->mPriority = ATOI(aPriority); // Read any float in a runtime variable reference as an int.
 3723 
 3724     if (!(timer_existed && aUpdatePriorityOnly))
 3725         // Caller relies on us updating mTimeLastRun in this case.  This is done because it's more
 3726         // flexible, e.g. a user might want to create a timer that is triggered 5 seconds from now.
 3727         // In such a case, we don't want the timer's first triggering to occur immediately.
 3728         // Instead, we want it to occur only when the full 5 seconds have elapsed:
 3729         timer->mTimeLastRun = GetTickCount();
 3730 
 3731     // Below is obsolete, see above for why:
 3732     // We don't have to kill or set the main timer because the only way this function is called
 3733     // is directly from the execution of a script line inside ExecUntil(), in which case:
 3734     // 1) KILL_MAIN_TIMER is never needed because the timer shouldn't exist while in ExecUntil().
 3735     // 2) SET_MAIN_TIMER is never needed because it will be set automatically the next time ExecUntil()
 3736     //    calls MsgSleep().
 3737     return OK;
 3738 }
 3739 
 3740 
 3741 
 3742 void Script::DeleteTimer(IObject *aLabel)
 3743 {
 3744     ScriptTimer *timer, *previous = NULL;
 3745     for (timer = mFirstTimer; timer != NULL; previous = timer, timer = timer->mNextTimer)
 3746         if (timer->mLabel == aLabel) // Match found.
 3747         {
 3748             // Disable it, even if it's not technically being deleted yet.
 3749             if (timer->mEnabled)
 3750                 timer->Disable(); // Keeps track of mTimerEnabledCount and whether the main timer is needed.
 3751             if (timer->mExistingThreads) // This condition differs from g->CurrentTimer == timer, which only detects the "top-most" timer.
 3752             {
 3753                 if (!aLabel) // Caller requested we delete a previously marked timer which
 3754                     continue; // has now finished, but this one hasn't, so keep looking.
 3755                 // In this case we can't delete the timer yet, so mark it for later deletion.
 3756                 timer->mLabel = NULL;
 3757                 // Clearing mLabel:
 3758                 //  1) Marks the timer to be deleted after its last thread finishes.
 3759                 //  2) Ensures any subsequently created timer will get default settings.
 3760                 //  3) Allows the object to be freed before the timer subroutine returns
 3761                 //     if all other references to it are released.
 3762                 break;
 3763             }
 3764             // Remove it from the list.
 3765             if (previous)
 3766                 previous->mNextTimer = timer->mNextTimer;
 3767             else
 3768                 mFirstTimer = timer->mNextTimer;
 3769             if (mLastTimer == timer)
 3770                 mLastTimer = previous;
 3771             mTimerCount--;
 3772             // Delete the timer, automatically releasing its reference to the object.
 3773             delete timer;
 3774             break;
 3775         }
 3776 }
 3777 
 3778 
 3779 
 3780 Label *Script::FindLabel(LPTSTR aLabelName)
 3781 // Returns the first label whose name matches aLabelName, or NULL if not found.
 3782 // v1.0.42: Since duplicates labels are now possible (to support #IfWin variants of a particular
 3783 // hotkey or hotstring), callers must be aware that only the first match is returned.
 3784 // This helps performance by requiring on average only half the labels to be searched before
 3785 // a match is found.
 3786 {
 3787     if (!aLabelName || !*aLabelName) return NULL;
 3788     for (Label *label = mFirstLabel; label != NULL; label = label->mNextLabel)
 3789         if (!_tcsicmp(label->mName, aLabelName)) // lstrcmpi() is not used: 1) avoids breaking existing scripts; 2) provides consistent behavior across multiple locales; 3) performance.
 3790             return label; // Match found.
 3791     return NULL; // No match found.
 3792 }
 3793 
 3794 
 3795 
 3796 IObject *Script::FindCallable(LPTSTR aLabelName, Var *aVar, int aParamCount)
 3797 {
 3798     if (aVar && aVar->HasObject())
 3799     {
 3800         IObject *obj = aVar->Object();
 3801         if (Func *func = LabelPtr(obj).ToFunc())
 3802         {
 3803             // It seems worth performing this additional check; without it, registration
 3804             // of this function would appear to succeed but it would never be called.
 3805             // In particular, this will alert the user that a *method* is not a valid
 3806             // callable object (because it requires at least one parameter: "this").
 3807             // For simplicity, the error message will indicate that no label was found.
 3808             if (func->mMinParams > aParamCount)
 3809                 return NULL;
 3810         }
 3811         return obj;
 3812     }
 3813     if (*aLabelName)
 3814     {
 3815         if (Label *label = FindLabel(aLabelName))
 3816             return label;
 3817         if (Func *func = FindFunc(aLabelName))
 3818             if (func->mMinParams <= aParamCount) // See comments above.
 3819                 return func;
 3820     }
 3821     return NULL;
 3822 }
 3823 
 3824 
 3825 
 3826 ResultType Script::AddLabel(LPTSTR aLabelName, bool aAllowDupe)
 3827 // Returns OK or FAIL.
 3828 {
 3829     if (!*aLabelName)
 3830         return FAIL; // For now, silent failure because callers should check this beforehand.
 3831     if (!aAllowDupe && FindLabel(aLabelName)) // Relies on short-circuit boolean order.
 3832         // Don't attempt to dereference "duplicate_label->mJumpToLine because it might not
 3833         // exist yet.  Example:
 3834         // label1:
 3835         // label1:  <-- This would be a dupe-error but it doesn't yet have an mJumpToLine.
 3836         // return
 3837         return ScriptError(_T("Duplicate label."), aLabelName);
 3838     LPTSTR new_name = SimpleHeap::Malloc(aLabelName);
 3839     if (!new_name)
 3840         return FAIL;  // It already displayed the error for us.
 3841     Label *the_new_label = new Label(new_name); // Pass it the dynamic memory area we created.
 3842     if (the_new_label == NULL)
 3843         return ScriptError(ERR_OUTOFMEM);
 3844     the_new_label->mPrevLabel = mLastLabel;  // Whether NULL or not.
 3845     if (mFirstLabel == NULL)
 3846         mFirstLabel = the_new_label;
 3847     else
 3848         mLastLabel->mNextLabel = the_new_label;
 3849     // This must be done after the above:
 3850     mLastLabel = the_new_label;
 3851     if (!_tcsicmp(new_name, _T("OnClipboardChange")))
 3852         mOnClipboardChangeLabel = the_new_label;
 3853     return OK;
 3854 }
 3855 
 3856 
 3857 
 3858 void Script::RemoveLabel(Label *aLabel)
 3859 // Remove a label from the linked list.
 3860 // Used by DefineFunc to implement hotkey/hotstring functions.
 3861 {
 3862     if (aLabel->mPrevLabel)
 3863         aLabel->mPrevLabel->mNextLabel = aLabel->mNextLabel;
 3864     else
 3865         mFirstLabel = aLabel->mNextLabel;
 3866     if (aLabel->mNextLabel)
 3867         aLabel->mNextLabel->mPrevLabel = aLabel->mPrevLabel;
 3868     else
 3869         mLastLabel = aLabel->mPrevLabel;
 3870 }
 3871 
 3872 
 3873 
 3874 ResultType Script::ParseAndAddLine(LPTSTR aLineText, ActionTypeType aActionType, ActionTypeType aOldActionType
 3875     , LPTSTR aActionName, LPTSTR aEndMarker, LPTSTR aLiteralMap, size_t aLiteralMapLength)
 3876 // Returns OK or FAIL.
 3877 // aLineText needs to be a string whose contents are modifiable (though the string won't be made any
 3878 // longer than it is now, so it doesn't have to be of size LINE_SIZE). This helps performance by
 3879 // allowing the string to be split into sections without having to make temporary copies.
 3880 {
 3881 #ifdef _DEBUG
 3882     if (!aLineText || !*aLineText)
 3883         return ScriptError(_T("DEBUG: ParseAndAddLine() called incorrectly."));
 3884 #endif
 3885 
 3886     TCHAR action_name[MAX_VAR_NAME_LENGTH + 1], *end_marker;
 3887     if (aActionName) // i.e. this function was called recursively with explicit values for the optional params.
 3888     {
 3889         _tcscpy(action_name, aActionName);
 3890         end_marker = aEndMarker;
 3891     }
 3892     else if (aActionType == ACT_EXPRESSION)
 3893     {
 3894         *action_name = '\0';
 3895         end_marker = NULL; // Indicate that there is no action to mark the end of.
 3896     }
 3897     else // We weren't called recursively from self, nor is it ACT_EXPRESSION, so set action_name and end_marker the normal way.
 3898     {
 3899         for (;;) // A loop with only one iteration so that "break" can be used instead of a lot of nested if's.
 3900         {
 3901             int declare_type;
 3902             LPTSTR cp;
 3903             if (!_tcsnicmp(aLineText, _T("Global"), 6)) // Checked first because it's more common than the others.
 3904             {
 3905                 cp = aLineText + 6; // The character after the declaration word.
 3906                 declare_type = g->CurrentFunc ? VAR_DECLARE_GLOBAL : VAR_DECLARE_SUPER_GLOBAL;
 3907             }
 3908             else
 3909             {
 3910                 if (!g->CurrentFunc) // Not inside a function body, so "Local"/"Static" get no special treatment.
 3911                     break;
 3912 
 3913                 if (!_tcsnicmp(aLineText, _T("Local"), 5))
 3914                 {
 3915                     cp = aLineText + 5; // The character after the declaration word.
 3916                     declare_type = VAR_DECLARE_LOCAL;
 3917                 }
 3918                 else if (!_tcsnicmp(aLineText, _T("Static"), 6)) // Static also implies local (for functions that default to global).
 3919                 {
 3920                     cp = aLineText + 6; // The character after the declaration word.
 3921                     declare_type = VAR_DECLARE_STATIC;
 3922                 }
 3923                 else // It's not the word "global", "local", or static, so no further checking is done.
 3924                     break;
 3925             }
 3926 
 3927             if (*cp && !IS_SPACE_OR_TAB(*cp)) // There is a character following the word local but it's not a space or tab.
 3928                 break; // It doesn't qualify as being the global or local keyword because it's something like global2.
 3929             if (*cp && *(cp = omit_leading_whitespace(cp))) // Probably always a true stmt since caller rtrimmed it, but even if not it's handled correctly.
 3930             {
 3931                 // Check whether the first character is an operator by seeing if it alone would be a
 3932                 // valid variable name.  If it's not valid, this doesn't qualify as the global or local
 3933                 // keyword because it's something like this instead:
 3934                 // local := xyz
 3935                 // local += 3
 3936                 TCHAR orig_char = cp[1];
 3937                 cp[1] = '\0'; // Temporarily terminate.
 3938                 ResultType result = Var::ValidateName(cp, DISPLAY_NO_ERROR);
 3939                 cp[1] = orig_char; // Undo the termination.
 3940                 if (!result) // It's probably operator, e.g. local = %var%
 3941                     break;
 3942             }
 3943             else // It's the word "global", "local", "static" by itself.
 3944             {
 3945                 // All of the following must be checked to catch back-to-back conflicting declarations such
 3946                 // as these:
 3947                 //    global x
 3948                 //    global  ; Should be an error because global vars are implied/automatic.
 3949                 // v1.0.48: Lexikos: Added assume-static mode. For now, this requires "static" to be
 3950                 // placed above local or global variable declarations.
 3951                 if (mNextLineIsFunctionBody)
 3952                 {
 3953                     if (g->CurrentFunc->mDefaultVarType == VAR_DECLARE_NONE)
 3954                     {
 3955                         if (declare_type == VAR_DECLARE_LOCAL)
 3956                             declare_type |= VAR_FORCE_LOCAL; // v1.1.27: "local" by itself restricts globals to only those declared inside the function.
 3957                         g->CurrentFunc->mDefaultVarType = declare_type;
 3958                         // No further action is required.
 3959                         return OK;
 3960                     }
 3961                     // v1.1.27: Allow "local" and "static" to be combined, leaving the restrictions on globals in place.
 3962                     else if (g->CurrentFunc->mDefaultVarType == (VAR_DECLARE_LOCAL | VAR_FORCE_LOCAL) && declare_type == VAR_DECLARE_STATIC)
 3963                     {
 3964                         g->CurrentFunc->mDefaultVarType = (VAR_DECLARE_STATIC | VAR_FORCE_LOCAL);
 3965                         return OK;
 3966                     }
 3967                 }
 3968                 // Otherwise, it occurs too far down in the body.
 3969                 return ScriptError(ERR_UNRECOGNIZED_ACTION, aLineText); // Vague error since so rare.
 3970             }
 3971             if (mNextLineIsFunctionBody && g->CurrentFunc->mDefaultVarType == VAR_DECLARE_NONE)
 3972             {
 3973                 // Both of the above must be checked to catch back-to-back conflicting declarations such
 3974                 // as these:
 3975                 // local x
 3976                 // global y  ; Should be an error because global vars are implied/automatic.
 3977                 // This line will become first non-directive, non-label line in the function's body.
 3978 
 3979                 // If the first non-directive, non-label line in the function's body contains
 3980                 // the "local" keyword, everything inside this function will assume that variables
 3981                 // are global unless they are explicitly declared local (this is the opposite of
 3982                 // the default).  The converse is also true.
 3983                 if (declare_type != VAR_DECLARE_STATIC)
 3984                     g->CurrentFunc->mDefaultVarType = declare_type == VAR_DECLARE_LOCAL ? VAR_DECLARE_GLOBAL : VAR_DECLARE_LOCAL;
 3985                 // Otherwise, leave it as-is to allow the following:
 3986                 // static x
 3987                 // local y
 3988             }
 3989             else // Since this isn't the first line of the function's body, mDefaultVarType has already been set permanently.
 3990             {
 3991                 if (g->CurrentFunc && declare_type == g->CurrentFunc->mDefaultVarType) // Can't be VAR_DECLARE_NONE at this point.
 3992                 {
 3993                     // Seems best to flag redundant/unnecessary declarations since they might be an indication
 3994                     // to the user that something is being done incorrectly in this function. This errors also
 3995                     // remind the user what mode the function is in:
 3996                     if (declare_type == VAR_DECLARE_GLOBAL)
 3997                         return ScriptError(_T("Global variables must not be declared in this function."), aLineText);
 3998                     if (declare_type == VAR_DECLARE_LOCAL)
 3999                         return ScriptError(_T("Local variables must not be declared in this function."), aLineText);
 4000                     // In assume-static mode, allow declarations in case they contain initializers.
 4001                     // Would otherwise lose the ability to "initialize only once upon startup".
 4002                     //if (declare_type == VAR_DECLARE_STATIC)
 4003                     //  return ScriptError("Static variables must not be declared in this function.", aLineText);
 4004                 }
 4005             }
 4006             // Since above didn't break or return, a variable is being declared as an exception to the
 4007             // mode specified by mDefaultVarType.
 4008 
 4009             bool open_brace_was_added, belongs_to_line_above;
 4010             size_t var_name_length;
 4011             LPTSTR item;
 4012 
 4013             for (belongs_to_line_above = mLastLine && ACT_IS_LINE_PARENT(mLastLine->mActionType)
 4014                 , open_brace_was_added = false, item = cp
 4015                 ; *item;) // FOR EACH COMMA-SEPARATED ITEM IN THE DECLARATION LIST.
 4016             {
 4017                 LPTSTR item_end = StrChrAny(item, _T(", \t=:"));  // Comma, space or tab, equal-sign, colon.
 4018                 if (!item_end) // This is probably the last/only variable in the list; e.g. the "x" in "local x"
 4019                     item_end = item + _tcslen(item);
 4020                 var_name_length = (VarSizeType)(item_end - item);
 4021 
 4022                 Var *var = NULL;
 4023                 int i;
 4024                 if (g->CurrentFunc)
 4025                 {
 4026                     for (i = 0; i < g->CurrentFunc->mParamCount; ++i) // Search by name to find both global and local declarations.
 4027                         if (!tcslicmp(item, g->CurrentFunc->mParam[i].var->mName, var_name_length))
 4028                             return ScriptError(_T("Parameters must not be declared."), item);
 4029                     // Detect conflicting declarations:
 4030                     var = FindVar(item, var_name_length, NULL, FINDVAR_LOCAL);
 4031                     if (var && (var->Scope() & ~VAR_DECLARED) == (declare_type & ~VAR_DECLARED) && declare_type != VAR_DECLARE_STATIC)
 4032                         var = NULL; // Allow redeclaration using same scope; e.g. "local x := 1 ... local x := 2" down two different code paths.
 4033                     if (!var && declare_type != VAR_DECLARE_GLOBAL)
 4034                         for (i = 0; i < g->CurrentFunc->mGlobalVarCount; ++i) // Explicitly search this array vs calling FindVar() in case func is assume-global.
 4035                             if (!tcslicmp(g->CurrentFunc->mGlobalVar[i]->mName, item, -1, var_name_length))
 4036                             {
 4037                                 var = g->CurrentFunc->mGlobalVar[i];
 4038                                 break;
 4039                             }
 4040                     if (var)
 4041                         return ScriptError(var->IsDeclared() ? ERR_DUPLICATE_DECLARATION : _T("Declaration conflicts with existing var."), item);
 4042                 }
 4043                 
 4044                 if (   !(var = FindOrAddVar(item, var_name_length, declare_type))   )
 4045                     return FAIL; // It already displayed the error.
 4046                 if (var->Type() != VAR_NORMAL || !tcslicmp(item, _T("ErrorLevel"), var_name_length)) // Shouldn't be declared either way (global or local).
 4047                     return ScriptError(_T("Built-in variables must not be declared."), item);
 4048                 if (declare_type == VAR_DECLARE_GLOBAL) // Can only be true if g->CurrentFunc is non-NULL.
 4049                 {
 4050                     if (g->CurrentFunc->mGlobalVarCount >= MAX_FUNC_VAR_GLOBALS)
 4051                         return ScriptError(_T("Too many declarations."), item); // Short message since it's so unlikely.
 4052                     g->CurrentFunc->mGlobalVar[g->CurrentFunc->mGlobalVarCount++] = var;
 4053                 }
 4054                 else if (declare_type == VAR_DECLARE_SUPER_GLOBAL)
 4055                 {
 4056                     // Ensure the "declared" and "super-global" flags are set, in case this
 4057                     // var was added to the list via a reference prior to the declaration.
 4058                     var->Scope() = declare_type;
 4059                 }
 4060 
 4061                 item_end = omit_leading_whitespace(item_end); // Move up to the next comma, assignment-op, or '\0'.
 4062 
 4063                 LPTSTR the_operator = item_end;
 4064                 bool convert_the_operator;
 4065                 switch(*item_end)
 4066                 {
 4067                 case ',':  // No initializer is present for this variable, so move on to the next one.
 4068                     item = omit_leading_whitespace(item_end + 1); // Set "item" for use by the next iteration.
 4069                     continue; // No further processing needed below.
 4070                 case '\0': // No initializer is present for this variable, so move on to the next one.
 4071                     item = item_end; // Set "item" for use by the next iteration.
 4072                     continue;
 4073                 case ':':
 4074                     if (item_end[1] != '=') // Colon with no following '='.
 4075                         return ScriptError(ERR_UNRECOGNIZED_ACTION, item); // Vague error since so rare.
 4076                     item_end += 2; // Point to the character after the ":=".
 4077                     convert_the_operator = false;
 4078                     break;
 4079                 case '=': // Here '=' is clearly an assignment not a comparison, so further below it will be converted to :=
 4080                     ++item_end; // Point to the character after the "=".
 4081                     convert_the_operator = true;
 4082                     break;
 4083                 default:
 4084                     // L31: This can be reached by something not officially supported like "global var .= value_to_append".
 4085                     // In previous versions, convert_the_operator was left uninitialized and whether it would work or be
 4086                     // replaced with ".:=" and fail was up to chance.  (Testing showed it failed only in Debug mode.)
 4087                     convert_the_operator = false;
 4088                 }
 4089 
 4090                 // Since above didn't "continue", this declared variable also has an initializer.
 4091                 // Add that initializer as a separate line to be executed at runtime. Separate lines
 4092                 // might actually perform better at runtime because most initializers tend to be simple
 4093                 // literals or variables that are simplified into non-expressions at runtime. In addition,
 4094                 // items without an initializer are omitted, further improving runtime performance.
 4095                 // However, the following must be done ONLY after having done the FindOrAddVar()
 4096                 // above, since that may have changed this variable to a non-default type (local or global).
 4097                 // But what about something like "global x, y=x"? Even that should work as long as x
 4098                 // appears in the list prior to initializers that use it.
 4099                 // Now, find the comma (or terminator) that marks the end of this sub-statement.
 4100                 // The search must exclude commas that are inside quoted/literal strings and those that
 4101                 // are inside parentheses (chiefly those of function-calls, but possibly others).
 4102 
 4103                 item_end += FindNextDelimiter(item_end); // FIND THE NEXT "REAL" COMMA (or the end of the string).
 4104                 
 4105                 // Above has now found the final comma of this sub-statement (or the terminator if there is no comma).
 4106                 LPTSTR terminate_here = omit_trailing_whitespace(item, item_end-1) + 1; // v1.0.47.02: Fix the fact that "x=5 , y=6" would preserve the whitespace at the end of "5".  It also fixes wrongly showing a syntax error for things like: static d="xyz"  , e = 5
 4107                 TCHAR orig_char = *terminate_here;
 4108                 *terminate_here = '\0'; // Temporarily terminate (it might already be the terminator, but that's harmless).
 4109 
 4110                 // PERFORMANCE: As of v1.0.48 (with cached binary numbers and pre-postfixed expressions),
 4111                 // assignments of literal integers to variables are up to 10% slower when done as a combined
 4112                 // (comma-separated) expression rather than each as a separate line.  However,  this slowness
 4113                 // eventually disappears and may even reverse as more and more such expressions are combined
 4114                 // into a single expression (e.g. the following is almost the same speed either way:
 4115                 // x:=1,y:=22,z:=333,a:=4444,b:=55555).  By contrast, assigning a literal string, another
 4116                 // variable, or a complex expression is the opposite: they are always faster when done via
 4117                 // commas, and they continue to get faster and faster as more expressions are merged into a
 4118                 // single comma-separated expression. In light of this, a future version could combine ONLY
 4119                 // those declarations that have initializers into a single comma-separately expression rather
 4120                 // than making a separate expression for each.  However, since it's not always faster to do
 4121                 // so (e.g. x:=0,y:=1 is faster as separate statements), and since it is somewhat rare to
 4122                 // have a long chain of initializers, and since these performance differences are documented,
 4123                 // it might not be worth changing.
 4124                 LPTSTR line_to_add;
 4125                 TCHAR new_buf[LINE_SIZE]; // Declared outside the braces below so that it stays in scope long enough. Using so much stack space here and in caller seems unlikely to affect performance, so _alloca seems unlikely to help.
 4126                 if (convert_the_operator) // Convert first '=' in item to be ":=".
 4127                 {
 4128                     // Prevent any chance of overflow by using new_buf (overflow might otherwise occur in cases
 4129                     // such as this sub-statement being the very last one in the declaration list, and being
 4130                     // at the limit of the buffer's capacity).
 4131                     StrReplace(_tcscpy(new_buf, item), _T("="), _T(":="), SCS_SENSITIVE, 1); // Can't overflow because there's only one replacement and we know item's length can't be that close to the capacity limit.
 4132                     line_to_add = new_buf;
 4133                 }
 4134                 else
 4135                     line_to_add = item;
 4136                 if (declare_type == VAR_DECLARE_STATIC)
 4137                 {
 4138                     // Avoid pointing labels or the function's mJumpToLine at a static declaration.
 4139                     mNoUpdateLabels = true;
 4140                 }
 4141                 else if (belongs_to_line_above && !open_brace_was_added) // v1.0.46.01: Put braces to allow initializers to work even directly under an IF/ELSE/LOOP.  Note that the braces aren't added or needed for static initializers.
 4142                 {
 4143                     if (!AddLine(ACT_BLOCK_BEGIN))
 4144                         return FAIL;
 4145                     open_brace_was_added = true;
 4146                 }
 4147                 // Call Parse() vs. AddLine() because it detects and optimizes simple assignments into
 4148                 // non-expressions for faster runtime execution.
 4149                 if (!ParseAndAddLine(line_to_add)) // For simplicity and maintainability, call self rather than trying to set things up properly to stay in self.
 4150                     return FAIL; // Above already displayed the error.
 4151                 if (declare_type == VAR_DECLARE_STATIC)
 4152                 {
 4153                     mNoUpdateLabels = false;
 4154                     mLastLine->mAttribute = (AttributeType)mLastLine->mActionType;
 4155                     mLastLine->mActionType = ACT_STATIC; // Mark this line for the preparser.
 4156                 }
 4157 
 4158                 *terminate_here = orig_char; // Undo the temporary termination.
 4159                 // Set "item" for use by the next iteration:
 4160                 item = (*item_end == ',') // i.e. it's not the terminator and thus not the final item in the list.
 4161                     ? omit_leading_whitespace(item_end + 1)
 4162                     : item_end; // It's the terminator, so let the loop detect that to finish.
 4163             } // for() each item in the declaration list.
 4164             if (open_brace_was_added)
 4165                 if (!AddLine(ACT_BLOCK_END))
 4166                     return FAIL;
 4167             return OK;
 4168         } // single-iteration for-loop
 4169 
 4170         // Since above didn't return, it's not a declaration such as "global MyVar".
 4171         if (   !(end_marker = ParseActionType(action_name, aLineText, true))   )
 4172             return FAIL; // It already displayed the error.
 4173     }
 4174     
 4175     // Above has ensured that end_marker is the address of the last character of the action name,
 4176     // or NULL if there is no action name.
 4177     // Find the arguments (not to be confused with exec_params) of this action, if it has any:
 4178     LPTSTR action_args;
 4179     bool could_be_named_action;
 4180     if (end_marker)
 4181     {
 4182         action_args = omit_leading_whitespace(end_marker + 1);
 4183         // L34: Require that named commands and their args are delimited with a space, tab or comma.
 4184         // Detects errors such as "MsgBox< foo" or "If!foo" and allows things like "control[x]:=y".
 4185         TCHAR end_char = end_marker[1];
 4186         could_be_named_action = (end_char == g_delimiter || !end_char || IS_SPACE_OR_TAB(end_char)
 4187             // Allow If() and While() but something like MsgBox() should always be a function-call:
 4188             || (end_char == '(' && (!_tcsicmp(action_name, _T("IF")) || !_tcsicmp(action_name, _T("WHILE")))));
 4189     }
 4190     else
 4191     {
 4192         action_args = aLineText;
 4193         // Since this entire line is the action's arg, it can't contain an action name.
 4194         could_be_named_action = false;
 4195     }
 4196     // Now action_args is either the first delimiter or the first parameter (if the optional first
 4197     // delimiter was omitted).
 4198     bool add_openbrace_afterward = false; // v1.0.41: Set default for use in supporting brace in "if (expr) {" and "Loop {".
 4199 
 4200     if (*action_args == g_delimiter)
 4201     {
 4202         // Since there's a comma, don't change aActionType because if it's ACT_INVALID, it should stay that way
 4203         // so that "something, += 4" is not a valid assignment or other operator, but should still be checked
 4204         // against the list of commands to see if it's something like "MsgBox, += 4" (in this case, a script may
 4205         // use the comma to avoid ambiguity).
 4206         // Find the start of the next token (or its ending delimiter if the token is blank such as ", ,"):
 4207         for (++action_args; IS_SPACE_OR_TAB(*action_args); ++action_args);
 4208     }
 4209     else if (!aActionType && !aOldActionType) // i.e. the caller hasn't yet determined this line's action type.
 4210     {
 4211         if (could_be_named_action && !_tcsicmp(action_name, _T("IF"))) // It's an IF-statement.
 4212         {
 4213             /////////////////////////////////////
 4214             // Detect all types of IF-statements.
 4215             /////////////////////////////////////
 4216             LPTSTR operation, next_word;
 4217             if (   *action_args == '(' // i.e. if (expression)
 4218                 || *action_args == g_DerefChar && IS_SPACE_OR_TAB(action_args[1])   ) // v1.0.48.04: "if % expr" is always an expressions. This check was added to allow lines like "if % IniWinCount = b" to work rather than being misinterpreted as "if var in", "if var is", and possibly other things.  However, "if %var%..." is NOT always an expression because it might be something like: if %A_Index%Array <> unquoted_literal_string
 4219             {
 4220                 // To support things like the following, the outermost enclosing parentheses are not removed:
 4221                 // if (x < 3) or (x > 6)
 4222                 // Also note that although the expression must normally start with an open-parenthesis to be
 4223                 // recognized as ACT_IFEXPR, it need not end in a close-paren; e.g. if (x = 1) or !done.
 4224                 // If these or any other parentheses are unbalanced, it will caught further below.
 4225                 aActionType = ACT_IFEXPR; // Fixed for v1.0.31.01.
 4226             }
 4227             else // Generic or indeterminate IF-statement, so find out what type it is.
 4228             {
 4229                 // Skip over the variable name so that the "is" and "is not" operators are properly supported:
 4230                 DEFINE_END_FLAGS
 4231                 if (operation = StrChrAny(action_args, end_flags))
 4232                     operation = omit_leading_whitespace(operation);
 4233                 else
 4234                     operation = action_args + _tcslen(action_args); // Point it to the NULL terminator instead.
 4235 
 4236                 // v1.0.42: Fix "If not Installed" not be seen as "If var-named-'not' in MatchList", being
 4237                 // careful not to break "If NotInstalled in MatchList".  The following are also fixed in
 4238                 // a similar way:
 4239                 // If not BetweenXXX
 4240                 // If not ContainsXXX
 4241                 bool first_word_is_not = !_tcsnicmp(action_args, _T("Not"), 3) && _tcschr(end_flags, action_args[3]);
 4242 
 4243                 switch (*operation)
 4244                 {
 4245                 case '=': // But don't allow == to be "Equals" since the 2nd '=' might be literal.
 4246                     aActionType = ACT_IFEQUAL;
 4247                     break;
 4248                 case '<':
 4249                     switch(operation[1])
 4250                     {
 4251                     // Note: User can use whitespace to differentiate a literal symbol from
 4252                     // part of an operator, e.g. if var1 < =  <--- char is literal
 4253                     case '=':
 4254                         aActionType = ACT_IFLESSOREQUAL;
 4255                         operation[1] = ' ';
 4256                         break;
 4257                     case '>':
 4258                         aActionType = ACT_IFNOTEQUAL;
 4259                         operation[1] = ' ';
 4260                         break;
 4261                     default: // i.e. some other character follows '<'
 4262                         aActionType = ACT_IFLESS;
 4263                     }
 4264                     break;
 4265                 case '>': // Don't allow >< to be NotEqual since the '<' might be intended as a literal part of an arg.
 4266                     if (operation[1] == '=')
 4267                     {
 4268                         aActionType = ACT_IFGREATEROREQUAL;
 4269                         operation[1] = ' '; // Remove it from so that it won't be considered by later parsing.
 4270                     }
 4271                     else
 4272                         aActionType = ACT_IFGREATER;
 4273                     break;
 4274                 case '!':
 4275                     if (operation[1] == '=')
 4276                     {
 4277                         aActionType = ACT_IFNOTEQUAL;
 4278                         operation[1] = ' '; // Remove it from so that it won't be considered by later parsing.
 4279                     }
 4280                     else
 4281                         // To minimize the times where expressions must have an outer set of parentheses,
 4282                         // assume all unknown operators are expressions, e.g. "if !var"
 4283                         aActionType = ACT_IFEXPR;
 4284                     break;
 4285                 case 'b': // "Between"
 4286                 case 'B':
 4287                     // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_b" is a syntax error.
 4288                     if (first_word_is_not || _tcsnicmp(operation, _T("between"), 7))
 4289                         aActionType = ACT_IFEXPR;
 4290                     else
 4291                     {
 4292                         aActionType = ACT_IFBETWEEN;
 4293                         // Set things up to be parsed as args further down.  A delimiter is inserted later below:
 4294                         tmemset(operation, ' ', 7);
 4295                     }
 4296                     break;
 4297                 case 'c': // "Contains"
 4298                 case 'C':
 4299                     // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_c" is a syntax error.
 4300                     if (first_word_is_not || _tcsnicmp(operation, _T("contains"), 8))
 4301                         aActionType = ACT_IFEXPR;
 4302                     else
 4303                     {
 4304                         aActionType = ACT_IFCONTAINS;
 4305                         // Set things up to be parsed as args further down.  A delimiter is inserted later below:
 4306                         tmemset(operation, ' ', 8);
 4307                     }
 4308                     break;
 4309                 case 'i':  // "is" or "is not"
 4310                 case 'I':
 4311                     switch (ctoupper(operation[1]))
 4312                     {
 4313                     case 's':  // "IS"
 4314                     case 'S':
 4315                         if (first_word_is_not)        // v1.0.45: Had forgotten to fix this one with the others,
 4316                             aActionType = ACT_IFEXPR; // so now "if not is_something" and "if not is_something()" work.
 4317                         else
 4318                         {
 4319                             next_word = omit_leading_whitespace(operation + 2);
 4320                             if (_tcsnicmp(next_word, _T("not"), 3)) // No need to check for whitespace after the word "not" because things like "if var is notxxx" are never valid.
 4321                                 aActionType = ACT_IFIS;
 4322                             else
 4323                             {
 4324                                 aActionType = ACT_IFISNOT;
 4325                                 // Remove the word "not" to set things up to be parsed as args further down.
 4326                                 tmemset(next_word, ' ', 3);
 4327                             }
 4328                             operation[1] = ' '; // Remove the 'S' in "IS".  'I' is replaced with ',' later below.
 4329                         }
 4330                         break;
 4331                     case 'n':  // "IN"
 4332                     case 'N':
 4333                         if (first_word_is_not)
 4334                             aActionType = ACT_IFEXPR;
 4335                         else
 4336                         {
 4337                             aActionType = ACT_IFIN;
 4338                             operation[1] = ' '; // Remove the 'N' in "IN".  'I' is replaced with ',' later below.
 4339                         }
 4340                         break;
 4341                     default:
 4342                         // v1.0.35.01 It must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_i"
 4343                         // is a syntax error.
 4344                         aActionType = ACT_IFEXPR;
 4345                     } // switch()
 4346                     break;
 4347                 case 'n':  // It's either "not in", "not between", or "not contains"
 4348                 case 'N':
 4349                     // Must fall back to ACT_IFEXPR, otherwise "if not var_name_beginning_with_n" is a syntax error.
 4350                     if (_tcsnicmp(operation, _T("not"), 3) || !IS_SPACE_OR_TAB(operation[3])) // Fix for v1.0.48: Must also check for whitespace after the word "not" to avoid a syntax error for lines like "if not note".
 4351                         aActionType = ACT_IFEXPR;
 4352                     else
 4353                     {
 4354                         // Remove the "NOT" separately in case there is more than one space or tab between
 4355                         // it and the following word, e.g. "not   between":
 4356                         tmemset(operation, ' ', 3);
 4357                         next_word = omit_leading_whitespace(operation + 3);
 4358                         if (!_tcsnicmp(next_word, _T("in"), 2))
 4359                         {
 4360                             aActionType = ACT_IFNOTIN;
 4361                             tmemset(next_word, ' ', 2);
 4362                         }
 4363                         else if (!_tcsnicmp(next_word, _T("between"), 7))
 4364                         {
 4365                             aActionType = ACT_IFNOTBETWEEN;
 4366                             tmemset(next_word, ' ', 7);
 4367                         }
 4368                         else if (!_tcsnicmp(next_word, _T("contains"), 8))
 4369                         {
 4370                             aActionType = ACT_IFNOTCONTAINS;
 4371                             tmemset(next_word, ' ', 8);
 4372                         }
 4373                     }
 4374                     break;
 4375 
 4376                 default: // To minimize the times where expressions must have an outer set of parentheses, assume all unknown operators are expressions.
 4377                     aActionType = ACT_IFEXPR;
 4378                 } // switch()
 4379             } // Detection of type of IF-statement.
 4380 
 4381             if (aActionType == ACT_IFEXPR) // There are various ways above for aActionType to become ACT_IFEXPR.
 4382             {
 4383                 // Since this is ACT_IFEXPR, action_args is known not to be an empty string, which is relied on below.
 4384                 LPTSTR action_args_last_char = action_args + _tcslen(action_args) - 1; // Shouldn't be a whitespace char since those should already have been removed at an earlier stage.
 4385                 if (*action_args_last_char == '{') // This is an if-expression statement with an open-brace on the same line.
 4386                 {
 4387                     *action_args_last_char = '\0';
 4388                     rtrim(action_args, action_args_last_char - action_args);  // Remove the '{' and all its whitespace from further consideration.
 4389                     add_openbrace_afterward = true;
 4390                 }
 4391             }
 4392             else // It's a IF-statement, but a traditional/non-expression one.
 4393             {
 4394                 // Set things up to be parsed as args later on.
 4395                 *operation = g_delimiter;
 4396                 if (aActionType == ACT_IFBETWEEN || aActionType == ACT_IFNOTBETWEEN)
 4397                 {
 4398                     // I decided against the syntax "if var between 3,8" because the gain in simplicity
 4399                     // and the small avoidance of ambiguity didn't seem worth the cost in terms of readability.
 4400                     for (next_word = operation;;)
 4401                     {
 4402                         if (   !(next_word = tcscasestr(next_word, _T("and")))   )
 4403                             return ScriptError(_T("BETWEEN requires the word AND."), aLineText); // Seems too rare a thing to warrant falling back to ACT_IFEXPR for this.
 4404                         if (_tcschr(_T(" \t"), *(next_word - 1)) && _tcschr(_T(" \t"), *(next_word + 3)))
 4405                         {
 4406                             // Since there's a space or tab on both sides, we know this is the correct "and",
 4407                             // i.e. not one contained within one of the parameters.  Examples:
 4408                             // if var between band and cat  ; Don't falsely detect "band"
 4409                             // if var between Andy and David  ; Don't falsely detect "Andy".
 4410                             // Replace the word AND with a delimiter so that it will be parsed correctly later:
 4411                             *next_word = g_delimiter;
 4412                             *(next_word + 1) = ' ';
 4413                             *(next_word + 2) = ' ';
 4414                             break;
 4415                         }
 4416                         else
 4417                             next_word += 3;  // Skip over this false "and".
 4418                     } // for()
 4419                 } // ACT_IFBETWEEN
 4420             } // aActionType != ACT_IFEXPR
 4421         }
 4422         else // It isn't an IF-statement, so check for assignments/operators that determine that this line isn't one that starts with a named command.
 4423         {
 4424             //////////////////////////////////////////////////////
 4425             // Detect operators and assignments such as := and +=
 4426             //////////////////////////////////////////////////////
 4427             // This section is done before the section that checks whether action_name is a valid command
 4428             // because it avoids ambiguity in a line such as the following:
 4429             //    Input = test  ; Would otherwise be confused with the Input command.
 4430             // But there may be times when a line like this is used:
 4431             //    MsgBox =  ; i.e. the equals is intended to be the first parameter, not an operator.
 4432             // In the above case, the user can provide the optional comma to avoid the ambiguity:
 4433             //    MsgBox, =
 4434             TCHAR action_args_2nd_char = action_args[1];
 4435             bool convert_pre_inc_or_dec = false; // Set default.
 4436 
 4437             switch(*action_args)
 4438             {
 4439             case '=': // i.e. var=value (old-style assignment)
 4440                 aActionType = ACT_ASSIGN;
 4441                 break;
 4442             case ':':
 4443                 // v1.0.40: Allow things like "MsgBox :: test" to be valid by insisting that '=' follows ':'.
 4444                 if (action_args_2nd_char == '=') // i.e. :=
 4445                     aActionType = ACT_ASSIGNEXPR;
 4446                 break;
 4447             case '+':
 4448                 // Support for ++i (and in the next case, --i).  In these cases, action_name must be either
 4449                 // "+" or "-", and the first character of action_args must match it.
 4450                 if ((convert_pre_inc_or_dec = action_name[0] == '+' && !action_name[1]) // i.e. the pre-increment operator; e.g. ++index.
 4451                     || action_args_2nd_char == '=') // i.e. x+=y (by contrast, post-increment is recognized only after we check for a command name to cut down on ambiguity).
 4452                     aActionType = ACT_ADD;
 4453                 break;
 4454             case '-':
 4455                 // Do a complete validation/recognition of the operator to allow a line such as the following,
 4456                 // which omits the first optional comma, to still be recognized as a command rather than a
 4457                 // variable-with-operator:
 4458                 // SetBatchLines -1
 4459                 if ((convert_pre_inc_or_dec = action_name[0] == '-' && !action_name[1]) // i.e. the pre-decrement operator; e.g. --index.
 4460                     || action_args_2nd_char == '=') // i.e. x-=y  (by contrast, post-decrement is recognized only after we check for a command name to cut down on ambiguity).
 4461                     aActionType = ACT_SUB;
 4462                 break;
 4463             case '*':
 4464                 if (action_args_2nd_char == '=') // i.e. *=
 4465                     aActionType = ACT_MULT;
 4466                 break;
 4467             case '/':
 4468                 if (action_args_2nd_char == '=') // i.e. /=
 4469                     aActionType = ACT_DIV;
 4470                 // ACT_DIV is different than //= and // because ACT_DIV supports floating point inputs by yielding
 4471                 // a floating point result (i.e. it doesn't Floor() the result when the inputs are floats).
 4472                 else if (action_args_2nd_char == '/' && action_args[2] == '=') // i.e. //=
 4473                     aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4474                 break;
 4475             case '|':
 4476             case '&':
 4477             case '^':
 4478                 if (action_args_2nd_char == '=') // i.e. .= and |= and &= and ^=
 4479                     aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4480                 break;
 4481             //case '?': Stand-alone ternary such as true ? fn1() : fn2().  These are rare so are
 4482             // checked later, only after action_name has been checked to see if it's a valid command.
 4483             case '>':
 4484             case '<':
 4485                 if (action_args_2nd_char == *action_args && action_args[2] == '=') // i.e. >>= and <<=
 4486                     aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4487                 break;
 4488             case '.': // L34: Handle dot differently now that dot is considered an action end flag. Detects some more errors and allows some valid expressions which weren't previously allowed.
 4489                 if (action_args_2nd_char == '=')
 4490                 {   // Concat-assign .=
 4491                     aActionType = ACT_EXPRESSION;
 4492                 }
 4493                 else
 4494                 {
 4495                     LPTSTR id_begin = action_args + 1;
 4496                     LPTSTR cp;
 4497                     for (;;) // L35: Loop to fix x.y.z() and similar.
 4498                     {
 4499                         cp = find_identifier_end(id_begin);
 4500                         if (*cp == '(')
 4501                         {   // Allow function/method Call as standalone expression.
 4502                             aActionType = ACT_EXPRESSION;
 4503                             break;
 4504                         }
 4505                         if (cp == id_begin)
 4506                             // No valid identifier, doesn't look like a valid expression.
 4507                             break;
 4508                         cp = omit_leading_whitespace(cp);
 4509                         if (*cp == '[' || !*cp // x.y[z] or x.y
 4510                             || cp[1] == '=' && _tcschr(_T(":+-*/|&^."), cp[0]) // Two-char assignment operator.
 4511                             || cp[1] == cp[0]
 4512                                 && (   _tcschr(_T("/<>"), cp[0]) && cp[2] == '=' // //=, <<= or >>=
 4513                                     || *cp == '+' || *cp == '-'   )) // x.y++ or x.y--
 4514                         {   // Allow Set and bracketed Get as standalone expression.
 4515                             aActionType = ACT_EXPRESSION;
 4516                             break;
 4517                         }
 4518                         if (*cp != '.')
 4519                             // Must be something which is not allowed as a standalone expression.
 4520                             break;
 4521                         id_begin = cp + 1;
 4522                     }
 4523                 }
 4524                 break;
 4525             //default: Leave aActionType set to ACT_INVALID. This also covers case '\0' in case that's possible.
 4526             } // switch()
 4527 
 4528             if (aActionType) // An assignment or other type of action was discovered above.
 4529             {
 4530                 if (convert_pre_inc_or_dec) // Set up pre-ops like ++index and --index to be parsed properly later.
 4531                 {
 4532                     // The following converts:
 4533                     // ++x -> EnvAdd x,1 (not really "EnvAdd" per se; but ACT_ADD).
 4534                     // Set action_args to be the word that occurs after the ++ or --:
 4535                     action_args = omit_leading_whitespace(++action_args); // Though there generally isn't any.
 4536                     if (StrChrAny(action_args, EXPR_ALL_SYMBOLS)) // Support things like ++Var ? f1() : f2() and ++Var /= 5. Don't need strstr(action_args, " ?") because the search already looks for ':'.
 4537                         aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4538                     else
 4539                     {
 4540                         // Set up aLineText and action_args to be parsed later on as a list of two parameters:
 4541                         // The variable name followed by the amount to be added or subtracted (e.g. "ScriptVar, 1").
 4542                         // We're not changing the length of aLineText by doing this, so it should be large enough:
 4543                         size_t new_length = _tcslen(action_args);
 4544                         // Since action_args is just a pointer into the aLineText buffer (which caller has ensured
 4545                         // is modifiable), use memmove() so that overlapping source & dest are properly handled:
 4546                         tmemmove(aLineText, action_args, new_length + 1); // +1 to include the zero terminator.
 4547                         // Append the second param, which is just "1" since the ++ and -- only inc/dec by 1:
 4548                         aLineText[new_length++] = g_delimiter;
 4549                         aLineText[new_length++] = '1';
 4550                         aLineText[new_length] = '\0';
 4551                     }
 4552                 }
 4553                 else if (aActionType != ACT_EXPRESSION) // i.e. it's ACT_ASSIGN/ASSIGNEXPR/ADD/SUB/MULT/DIV
 4554                 {
 4555                     if (aActionType != ACT_ASSIGN) // i.e. it's ACT_ASSIGNEXPR/ADD/SUB/MULT/DIV
 4556                     {
 4557                         // Find the first non-function comma, which in the case of ACT_ADD/SUB can be
 4558                         // either a statement-separator comma (expression) or the time units arg.
 4559                         // Reasons for this:
 4560                         // 1) ACT_ADD/SUB: Need to distinguish compound statements from date/time math;
 4561                         //    e.g. "x+=1, y+=2" should be marked as a stand-alone expression, not date math.
 4562                         // 2) ACT_ASSIGNEXPR/MULT/DIV (and ACT_ADD/SUB for that matter): Need to make
 4563                         //    comma-separated sub-expressions into one big ACT_EXPRESSION so that the
 4564                         //    leftmost sub-expression will get evaluated prior to the others (for consistency
 4565                         //    and as documented).  However, this has some side-effects, such as making
 4566                         //    the leftmost /= operator into true division rather than ENV_DIV behavior,
 4567                         //    and treating blanks as errors in math expressions when otherwise ENV_MULT
 4568                         //    would treat them as zero.
 4569                         // ALSO: ACT_ASSIGNEXPR/ADD/SUB/MULT/DIV are made into ACT_EXPRESSION *only* when multi-
 4570                         // statement commas are present because the following legacy behaviors must be retained:
 4571                         // 1) Math treatment of blanks as zero in ACT_ADD/SUB/etc.
 4572                         // 2) EnvDiv's special behavior, which is different than both true divide and floor divide.
 4573                         // 3) Possibly add/sub's date/time math.
 4574                         // 4) Maybe obsolete: For performance, don't want trivial assignments to become ACT_EXPRESSION.
 4575                         LPTSTR cp = action_args + FindNextDelimiter(action_args, g_delimiter, 2);
 4576                         if (*cp) // Found a delimiting comma other than one in a sub-statement or function. Shouldn't need to worry about unquoted escaped commas since they don't make sense with += and -=.
 4577                         {
 4578                             if (aActionType == ACT_ADD || aActionType == ACT_SUB)
 4579                             {
 4580                                 cp = omit_leading_whitespace(cp + 1);
 4581                                 if (StrChrAny(cp, EXPR_ALL_SYMBOLS)) // Don't need strstr(cp, " ?") because the search already looks for ':'.
 4582                                     aActionType = ACT_EXPRESSION; // It's clearly an expression not a word like Days or %VarContainingTheWordDays%.
 4583                                 //else it's probably date/time math, so leave it as-is.
 4584                             }
 4585                             else // ACT_ASSIGNEXPR/MULT/DIV, for which any non-function comma qualifies it as multi-statement.
 4586                                 aActionType = ACT_EXPRESSION;
 4587                         }
 4588                     }
 4589                     if (aActionType != ACT_EXPRESSION) // The above didn't make it a stand-alone expression.
 4590                     {
 4591                         // The following converts:
 4592                         // x+=2 -> ACT_ADD x, 2.
 4593                         // x:=2 -> ACT_ASSIGNEXPR, x, 2
 4594                         // etc.
 4595                         // But post-inc/dec are recognized only after we check for a command name to cut down on ambiguity
 4596                         *action_args = g_delimiter; // Replace the =,+,-,:,*,/ with a delimiter for later parsing.
 4597                         if (aActionType != ACT_ASSIGN) // i.e. it's not just a plain equal-sign (which has no 2nd char).
 4598                             action_args[1] = ' '; // Remove the "=" from consideration.
 4599                     }
 4600                 }
 4601                 //else it's already an isolated expression, so no changes are desired.
 4602                 action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
 4603             } // if (aActionType)
 4604         } // Handling of assignments and other operators.
 4605     }
 4606     //else aActionType was already determined by the caller.
 4607 
 4608     // Now the above has ensured that action_args is the first parameter itself, or empty-string if none.
 4609     // If action_args now starts with a delimiter, it means that the first param is blank/empty.
 4610 
 4611     if (!aActionType && could_be_named_action && !aOldActionType) // Caller nor logic above has yet determined the action.
 4612         if (   !(aActionType = ConvertActionType(action_name))   ) // Is this line a command?
 4613             aOldActionType = ConvertOldActionType(action_name);    // If not, is it an old-command?
 4614 
 4615     if (!aActionType && !aOldActionType) // Didn't find any action or command in this line.
 4616     {
 4617         // v1.0.41: Support one-true brace style even if there's no space, but make it strict so that
 4618         // things like "Loop{ string" are reported as errors (in case user intended a file-pattern loop).
 4619         if (*action_args == '{')
 4620         {
 4621             switch (ActionTypeType otb_act = ConvertActionType(action_name))
 4622             {
 4623             case ACT_LOOP:
 4624                 add_openbrace_afterward = true;
 4625                 if (action_args[1]) // See above.
 4626                     break;
 4627                 //else fall through:
 4628             case ACT_ELSE:
 4629             case ACT_TRY:
 4630             case ACT_CATCH:
 4631             case ACT_FINALLY:
 4632                 aActionType = otb_act;
 4633                 break;
 4634             }
 4635         }
 4636         else if (*action_args == ':')
 4637         {
 4638             // Default isn't handled as its own action type because that would only cover the cases
 4639             // where there is a space after the name.  This covers "Default: subaction", "Default :"
 4640             // and "Default : subaction".  "Default:" on its own is handled by label-parsing.
 4641             if (!_tcsicmp(action_name, _T("Default")))
 4642             {
 4643                 if (!AddLine(ACT_CASE))
 4644                     return FAIL;
 4645                 action_args = omit_leading_whitespace(action_args + 1);
 4646                 if (!*action_args)
 4647                     return OK;
 4648                 return ParseAndAddLine(action_args);
 4649             }
 4650         }
 4651         if (!aActionType && _tcschr(EXPR_ALL_SYMBOLS, *action_args))
 4652         {
 4653             LPTSTR question_mark;
 4654             if ((*action_args == '+' || *action_args == '-') && action_args[1] == *action_args) // Post-inc/dec. See comments further below.
 4655             {
 4656                 if (action_args[2]) // i.e. if the ++ and -- isn't the last thing; e.g. x++ ? fn1() : fn2() ... Var++ //= 2
 4657                     aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4658                 else
 4659                 {
 4660                     // The logic here allows things like IfWinActive-- to be seen as commands even without
 4661                     // a space before the -- or ++.  For backward compatibility and code simplicity, it seems
 4662                     // best to keep that behavior rather than distinguishing between Command-- and Command --.
 4663                     // In any case, "Command --" should continue to be seen as a command regardless of what
 4664                     // changes are ever made.  That's why this section occurs below the command-name lookup.
 4665                     // The following converts x++ to "ACT_ADD x,1".
 4666                     aActionType = (*action_args == '+') ? ACT_ADD : ACT_SUB;
 4667                     *action_args = g_delimiter;
 4668                     action_args[1] = '1';
 4669                 }
 4670                 action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
 4671             }
 4672             else if (*action_args == '?'  // L34: Below no longer requires spaces around '?'.
 4673                 || (question_mark = _tcschr(action_args,'?')) && _tcschr(question_mark,':')) // Rough check (see comments below). Relies on short-circuit boolean order.
 4674             {
 4675                 // To avoid hindering load-time error detection such as misspelled command names, allow stand-alone
 4676                 // expressions only for things that can produce a side-effect (currently only ternaries like
 4677                 // the ones mentioned later below need to be checked since the following other things were
 4678                 // previously recognized as ACT_EXPRESSION if appropriate: function-calls, post- and
 4679                 // pre-inc/dec (++/--), and assignment operators like := += *= (though these don't necessarily
 4680                 // need to be ACT_EXPRESSION to support multi-statement; they can be ACT_ASSIGNEXPR, ACT_ADD, etc.
 4681                 // and still support comma-separated statements.
 4682                 // Stand-alone ternaries are checked for here rather than earlier to allow a command name
 4683                 // (of present) to take precedence (since stand-alone ternaries seem much rarer than 
 4684                 // "Command ? something" such as "MsgBox ? something".  Could also check for a colon somewhere
 4685                 // to the right if further ambiguity-resolution is ever needed.  Also, a stand-alone ternary
 4686                 // should have at least one function-call and/or assignment; otherwise it would serve no purpose.
 4687                 // A line may contain a stand-alone ternary operator to call functions that have side-effects
 4688                 // or perform assignments.  For example:
 4689                 //    IsDone ? fn1() : fn2()
 4690                 //    3 > 2 ? x:=1 : y:=1
 4691                 //    (3 > 2) ... not supported due to overlap with continuation sections.
 4692                 aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4693                 action_args = aLineText; // Since this is an assignment and/or expression, use the line's full text for later parsing.
 4694             }
 4695             //else leave it as an unknown action to avoid hindering load-time error detection.
 4696             // In other words, don't be too permissive about what gets marked as a stand-alone expression.
 4697         }
 4698         if (!aActionType) // Above still didn't find a valid action (i.e. check aActionType again in case the above changed it).
 4699         {
 4700             if (*action_args == '(' || *action_args == '[' // v1.0.46.11: Recognize as multi-statements that start with a function, like "fn(), x:=4".  v1.0.47.03: Removed the following check to allow a close-brace to be followed by a comma-less function-call: strchr(action_args, g_delimiter).
 4701                 || *aLineText == '(' // Probably an expression with parentheses to control order of evaluation.
 4702                 || !_tcsnicmp(aLineText, _T("new"), 3) && IS_SPACE_OR_TAB(aLineText[3]))
 4703             {
 4704                 aActionType = ACT_EXPRESSION; // Mark this line as a stand-alone expression.
 4705                 action_args = aLineText; // Since this is a function-call followed by a comma and some other expression, use the line's full text for later parsing.
 4706             }
 4707             else
 4708                 // v1.0.40: Give a more specific error message now that hotkeys can make it here due to
 4709                 // the change that avoids the need to escape double-colons:
 4710                 return ScriptError(_tcsstr(aLineText, HOTKEY_FLAG) ? _T("Invalid hotkey.") : ERR_UNRECOGNIZED_ACTION, aLineText);
 4711         }
 4712     }
 4713 
 4714     int mark;
 4715     LPTSTR subaction_start = NULL;
 4716     switch (aActionType)
 4717     {
 4718     case ACT_CATCH:
 4719         if (*action_args != '{') // i.e. "Catch varname" must be handled a different way.
 4720             break;
 4721         // Fall through:
 4722     case ACT_ELSE:
 4723     case ACT_TRY:
 4724     case ACT_FINALLY:
 4725         if (*action_args == '{')
 4726         {
 4727             add_openbrace_afterward = true;
 4728             action_args = omit_leading_whitespace(action_args + 1);
 4729         }
 4730         if (*action_args)
 4731         {
 4732             subaction_start = action_args;
 4733             *--action_args = '\0'; // Relies on there being a space, tab or brace at this position.
 4734         }
 4735         break;
 4736     case ACT_CASE:
 4737         mark = FindExprDelim(action_args, ':');
 4738         if (!action_args[mark])
 4739             return ScriptError(ERR_MISSING_COLON, aLineText);
 4740         action_args[mark] = '\0';
 4741         rtrim(action_args);
 4742         subaction_start = omit_leading_whitespace(action_args + mark + 1);
 4743         if (!*subaction_start) // Nothing to the right of ':'.
 4744             subaction_start = NULL;
 4745         break;
 4746     }
 4747 
 4748     Action &this_action = aActionType ? g_act[aActionType] : g_old_act[aOldActionType];
 4749 
 4750     //////////////////////////////////////////////////////////////////////////////////////////////
 4751     // Handle escaped-sequences (escaped delimiters and all others except variable deref symbols).
 4752     // This section must occur after all other changes to the pointer value action_args have
 4753     // occurred above.
 4754     //////////////////////////////////////////////////////////////////////////////////////////////
 4755     // The size of this relies on the fact that caller made sure that aLineText isn't
 4756     // longer than LINE_SIZE.  Also, it seems safer to use char rather than bool, even
 4757     // though on most compilers they're the same size.  Char is always of size 1, but bool
 4758     // can be bigger depending on platform/compiler:
 4759     TCHAR literal_map[LINE_SIZE];
 4760     ZeroMemory(literal_map, sizeof(literal_map));  // Must be fully zeroed for this purpose.
 4761     if (aLiteralMap)
 4762     {
 4763         // Since literal map is NOT a string, just an array of char values, be sure to
 4764         // use memcpy() vs. _tcscpy() on it.  Also, caller's aLiteralMap starts at aEndMarker,
 4765         // so adjust it so that it starts at the newly found position of action_args instead:
 4766         int map_offset = (int)(action_args - end_marker);  // end_marker is known not to be NULL when aLiteralMap is non-NULL.
 4767         int map_length = (int)(aLiteralMapLength - map_offset);
 4768         if (map_length > 0)
 4769             tmemcpy(literal_map, aLiteralMap + map_offset, map_length);
 4770     }
 4771     else
 4772     {
 4773         // Resolve escaped sequences and make a map of which characters in the string should
 4774         // be interpreted literally rather than as their native function.  In other words,
 4775         // convert any escape sequences in order from left to right (this order is important,
 4776         // e.g. ``% should evaluate to `g_DerefChar not `LITERAL_PERCENT.  This part must be
 4777         // done *after* checking for comment-flags that appear to the right of a valid line, above.
 4778         // How literal comment-flags (e.g. semicolons) work:
 4779         //string1; string2 <-- not a problem since string2 won't be considered a comment by the above.
 4780         //string1 ; string2  <-- this would be a user mistake if string2 wasn't supposed to be a comment.
 4781         //string1 `; string 2  <-- since esc seq. is resolved *after* checking for comments, this behaves as intended.
 4782         // Current limitation: a comment-flag longer than 1 can't be escaped, so if "//" were used,
 4783         // as a comment flag, it could never have whitespace to the left of it if it were meant to be literal.
 4784         // Note: This section resolves all escape sequences except those involving g_DerefChar, which
 4785         // are handled by a later section.
 4786         TCHAR c;
 4787         int i;
 4788         for (i = 0; ; ++i)  // Increment to skip over the symbol just found by the inner for().
 4789         {
 4790             for (; action_args[i] && action_args[i] != g_EscapeChar; ++i);  // Find the next escape char.
 4791             if (!action_args[i]) // end of string.
 4792                 break;
 4793             c = action_args[i + 1];
 4794             switch (c)
 4795             {
 4796                 // Only lowercase is recognized for these:
 4797                 case 'a': action_args[i + 1] = '\a'; break;  // alert (bell) character
 4798                 case 'b': action_args[i + 1] = '\b'; break;  // backspace
 4799                 case 'f': action_args[i + 1] = '\f'; break;  // formfeed
 4800                 case 'n': action_args[i + 1] = '\n'; break;  // newline