"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/script.h" (8 May 2021, 167345 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.h" 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 #ifndef script_h
   18 #define script_h
   19 
   20 #include "stdafx.h" // pre-compiled headers
   21 #include "defines.h"
   22 #include "SimpleHeap.h" // for overloaded new/delete operators.
   23 #include "keyboard_mouse.h" // for modLR_type
   24 #include "var.h" // for a script's variables.
   25 #include "WinGroup.h" // for a script's Window Groups.
   26 #include "Util.h" // for FileTimeToYYYYMMDD(), strlcpy()
   27 #include "resources/resource.h"  // For tray icon.
   28 #include "script_object.h"
   29 #include "Debugger.h"
   30 
   31 #include "os_version.h" // For the global OS_Version object
   32 EXTERN_OSVER; // For the access to the g_os version object without having to include globaldata.h
   33 EXTERN_G;
   34 
   35 #define MAX_THREADS_LIMIT UCHAR_MAX // Uses UCHAR_MAX (255) because some variables that store a thread count are UCHARs.
   36 #define MAX_THREADS_DEFAULT 10 // Must not be higher than above.
   37 #define EMERGENCY_THREADS 2 // This is the number of extra threads available after g_MaxThreadsTotal has been reached for the following to launch: hotkeys/etc. whose first line is something important like ExitApp or Pause. (see #MaxThreads documentation).
   38 #define MAX_THREADS_EMERGENCY (g_MaxThreadsTotal + EMERGENCY_THREADS)
   39 #define TOTAL_ADDITIONAL_THREADS (EMERGENCY_THREADS + 2) // See below.
   40 // Must allow two beyond EMERGENCY_THREADS: One for the AutoExec/idle thread and one so that ExitApp()
   41 // can run even when MAX_THREADS_EMERGENCY has been reached.
   42 // Explanation: If/when AutoExec() finishes, although it no longer needs g_array[0] (not even
   43 // AutoExecSectionTimeout() needs it because it either won't be called or it will return early),
   44 // at least the following might still use g_array[0]:
   45 // 1) Threadless (fast-mode) callbacks that have no controlling script thread; see RegisterCallbackCStub().
   46 // 2) g_array[0].IsPaused indicates whether the script is in a paused state while idle.
   47 // In addition, it probably simplifies the code not to reclaim g_array[0]; e.g. ++g and --g can be done
   48 // unconditionally when creating new threads.
   49 
   50 enum ExecUntilMode {NORMAL_MODE, UNTIL_RETURN, UNTIL_BLOCK_END, ONLY_ONE_LINE};
   51 
   52 // It's done this way so that mAttribute can store a pointer or one of these constants.
   53 // If it is storing a pointer for a given Action Type, be sure never to compare it
   54 // for equality against these constants because by coincidence, the pointer value
   55 // might just match one of them:
   56 #define ATTR_NONE (void *)0  // Some places might rely on this being zero.
   57 #define ATTR_TRUE (void *)1
   58 #define ATTR_LINE_CAN_BE_UNREACHABLE ATTR_TRUE // A flag for ACT_RETURN and ACT_EXIT to indicate PreparseCommands() should not show a warning if the line is unreachable.
   59 #define ATTR_LOOP_UNKNOWN (void *)1 // Same value as the above.        // KEEP IN SYNC WITH BELOW.
   60 #define ATTR_LOOP_IS_UNKNOWN_OR_NONE(attr) (attr <= ATTR_LOOP_UNKNOWN) // KEEP IN SYNC WITH ABOVE.
   61 #define ATTR_LOOP_NORMAL (void *)2
   62 #define ATTR_LOOP_FILEPATTERN (void *)3
   63 #define ATTR_LOOP_REG (void *)4
   64 #define ATTR_LOOP_READ_FILE (void *)5
   65 #define ATTR_LOOP_PARSE (void *)6
   66 #define ATTR_LOOP_WHILE (void *)7 // Lexikos: This is used to differentiate ACT_WHILE from ACT_LOOP, allowing code to be shared.
   67 #define ATTR_LOOP_FOR (void *)8
   68 #define ATTR_LOOP_NEW_REG (void *)9
   69 #define ATTR_LOOP_NEW_FILES (void *)10
   70 #define ATTR_LOOP_OBSCURED (void *)100 // fincs: used by Line::PreparseIfElse() for ACT_FINALLY blocks.
   71 #define ATTR_OBSCURE(attr) ((attr) ? ATTR_LOOP_OBSCURED : ATTR_NONE)
   72 typedef void *AttributeType;
   73 
   74 typedef int FileLoopModeType;
   75 #define FILE_LOOP_INVALID       0
   76 #define FILE_LOOP_FILES_ONLY    1
   77 #define FILE_LOOP_FOLDERS_ONLY  2
   78 #define FILE_LOOP_RECURSE       4
   79 #define FILE_LOOP_FILES_AND_FOLDERS (FILE_LOOP_FILES_ONLY | FILE_LOOP_FOLDERS_ONLY)
   80 
   81 enum VariableTypeType {VAR_TYPE_INVALID, VAR_TYPE_NUMBER, VAR_TYPE_INTEGER, VAR_TYPE_FLOAT
   82     , VAR_TYPE_TIME , VAR_TYPE_DIGIT, VAR_TYPE_XDIGIT, VAR_TYPE_ALNUM, VAR_TYPE_ALPHA
   83     , VAR_TYPE_UPPER, VAR_TYPE_LOWER, VAR_TYPE_SPACE};
   84 
   85 #define ATTACH_THREAD_INPUT \
   86     bool threads_are_attached = false;\
   87     DWORD target_thread = GetWindowThreadProcessId(target_window, NULL);\
   88     if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
   89         threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;
   90 // BELOW IS SAME AS ABOVE except it checks do_activate and also does a SetActiveWindow():
   91 #define ATTACH_THREAD_INPUT_AND_SETACTIVEWINDOW_IF_DO_ACTIVATE \
   92     bool threads_are_attached = false;\
   93     DWORD target_thread;\
   94     if (do_activate)\
   95     {\
   96         target_thread = GetWindowThreadProcessId(target_window, NULL);\
   97         if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
   98             threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;\
   99         SetActiveWindow(target_window);\
  100     }
  101 
  102 #define DETACH_THREAD_INPUT \
  103     if (threads_are_attached)\
  104         AttachThreadInput(g_MainThreadID, target_thread, FALSE);
  105 
  106 #define RESEED_RANDOM_GENERATOR \
  107 {\
  108     FILETIME ft;\
  109     GetSystemTimeAsFileTime(&ft);\
  110     init_genrand(ft.dwLowDateTime);\
  111 }
  112 
  113 #define IS_PERSISTENT (Hotkey::sHotkeyCount || Hotstring::sHotstringCount || g_KeybdHook || g_MouseHook || g_persistent)
  114 
  115 // Since WM_COMMAND IDs must be shared among all menus and controls, they are carefully conserved,
  116 // especially since there are only 65,535 possible IDs.  In addition, they are assigned to ranges
  117 // to minimize the need that they will need to be changed in the future (changing the ID of a main
  118 // menu item, tray menu item, or a user-defined menu item [by way of increasing MAX_CONTROLS_PER_GUI]
  119 // is bad because some scripts might be using PostMessage/SendMessage to automate AutoHotkey itself).
  120 // For this reason, the following ranges are reserved:
  121 // 0: unused (possibly special in some contexts)
  122 // 1: IDOK
  123 // 2: IDCANCEL
  124 // 3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
  125 // 1003 to 65299: User Defined Menu IDs
  126 // 65300 to 65399: Standard tray menu items.
  127 // 65400 to 65534: main menu items (might be best to leave 65535 unused in case it ever has special meaning)
  128 enum CommandIDs {CONTROL_ID_FIRST = IDCANCEL + 1
  129     , ID_USER_FIRST = MAX_CONTROLS_PER_GUI + 3 // The first ID available for user defined menu items. Do not change this (see above for why).
  130     , ID_USER_LAST = 65299  // The last. Especially do not change this due to scripts using Post/SendMessage to automate AutoHotkey.
  131     , ID_TRAY_FIRST, ID_TRAY_OPEN = ID_TRAY_FIRST
  132     , ID_TRAY_HELP, ID_TRAY_WINDOWSPY, ID_TRAY_RELOADSCRIPT
  133     , ID_TRAY_EDITSCRIPT, ID_TRAY_SUSPEND, ID_TRAY_PAUSE, ID_TRAY_EXIT
  134     , ID_TRAY_SEP1, ID_TRAY_SEP2, ID_TRAY_LAST = ID_TRAY_SEP2 // But this value should never hit the below. There is debug code to enforce.
  135     , ID_MAIN_FIRST = 65400, ID_MAIN_LAST = 65534}; // These should match the range used by resource.h
  136 
  137 #define GUI_INDEX_TO_ID(index) (index + CONTROL_ID_FIRST)
  138 #define GUI_ID_TO_INDEX(id) (id - CONTROL_ID_FIRST) // Returns a small negative if "id" is invalid, such as 0.
  139 #define GUI_HWND_TO_INDEX(hwnd) GUI_ID_TO_INDEX(GetDlgCtrlID(hwnd)) // Returns a small negative on failure (e.g. HWND not found).
  140 // Notes about above:
  141 // 1) Callers should call GuiType::FindControl() instead of GUI_HWND_TO_INDEX() if the hwnd might be a combobox's
  142 //    edit control.
  143 // 2) Testing shows that GetDlgCtrlID() is much faster than looping through a GUI window's control array to find
  144 //    a matching HWND.
  145 
  146 
  147 #define ERR_ABORT_NO_SPACES _T("The current thread will exit.")
  148 #define ERR_ABORT _T("  ") ERR_ABORT_NO_SPACES
  149 #define WILL_EXIT _T("The program will exit.")
  150 #define UNSTABLE_WILL_EXIT _T("The program is now unstable and will exit.")
  151 #define OLD_STILL_IN_EFFECT _T("The script was not reloaded; the old version will remain in effect.")
  152 #define ERR_ABORT_DELETE _T("__Delete will now return.")
  153 #define ERR_CONTINUATION_SECTION_TOO_LONG _T("Continuation section too long.")
  154 #define ERR_UNRECOGNIZED_ACTION _T("This line does not contain a recognized action.")
  155 #define ERR_NONEXISTENT_HOTKEY _T("Nonexistent hotkey.")
  156 #define ERR_NONEXISTENT_VARIANT _T("Nonexistent hotkey variant (IfWin).")
  157 #define ERR_INVALID_SINGLELINE_HOT _T("Invalid single-line hotkey/hotstring.")
  158 #define ERR_NONEXISTENT_FUNCTION _T("Call to nonexistent function.")
  159 #define ERR_EXE_CORRUPTED _T("EXE corrupted")
  160 #define ERR_INVALID_VALUE _T("Invalid value.")
  161 #define ERR_PARAM1_INVALID _T("Parameter #1 invalid.")
  162 #define ERR_PARAM2_INVALID _T("Parameter #2 invalid.")
  163 #define ERR_PARAM3_INVALID _T("Parameter #3 invalid.")
  164 #define ERR_PARAM4_INVALID _T("Parameter #4 invalid.")
  165 #define ERR_PARAM5_INVALID _T("Parameter #5 invalid.")
  166 #define ERR_PARAM6_INVALID _T("Parameter #6 invalid.")
  167 #define ERR_PARAM7_INVALID _T("Parameter #7 invalid.")
  168 #define ERR_PARAM8_INVALID _T("Parameter #8 invalid.")
  169 #define ERR_PARAM1_REQUIRED _T("Parameter #1 required")
  170 #define ERR_PARAM2_REQUIRED _T("Parameter #2 required")
  171 #define ERR_PARAM3_REQUIRED _T("Parameter #3 required")
  172 #define ERR_PARAM2_MUST_BE_BLANK _T("Parameter #2 must be blank in this case.")
  173 #define ERR_PARAM3_MUST_BE_BLANK _T("Parameter #3 must be blank in this case.")
  174 #define ERR_PARAM4_MUST_BE_BLANK _T("Parameter #4 must be blank in this case.")
  175 #define ERR_PARAM1_MUST_NOT_BE_BLANK _T("Parameter #1 must not be blank in this case.")
  176 #define ERR_PARAM2_MUST_NOT_BE_BLANK _T("Parameter #2 must not be blank in this case.")
  177 #define ERR_PARAM3_MUST_NOT_BE_BLANK _T("Parameter #3 must not be blank in this case.")
  178 #define ERR_PARAM4_MUST_NOT_BE_BLANK _T("Parameter #4 must not be blank in this case.")
  179 #define ERR_MISSING_OUTPUT_VAR _T("Requires at least one of its output variables.")
  180 #define ERR_MISSING_OPEN_PAREN _T("Missing \"(\"")
  181 #define ERR_MISSING_OPEN_BRACE _T("Missing \"{\"")
  182 #define ERR_MISSING_CLOSE_PAREN _T("Missing \")\"")
  183 #define ERR_MISSING_CLOSE_BRACE _T("Missing \"}\"")
  184 #define ERR_MISSING_CLOSE_BRACKET _T("Missing \"]\"") // L31
  185 #define ERR_UNEXPECTED_CLOSE_PAREN _T("Unexpected \")\"")
  186 #define ERR_UNEXPECTED_CLOSE_BRACKET _T("Unexpected \"]\"")
  187 #define ERR_UNEXPECTED_CLOSE_BRACE _T("Unexpected \"}\"")
  188 #define ERR_MISSING_CLOSE_QUOTE _T("Missing close-quote") // No period after short phrases.
  189 #define ERR_MISSING_COMMA _T("Missing comma")             //
  190 #define ERR_MISSING_COLON _T("Missing \":\"")             //
  191 #define ERR_BLANK_PARAM _T("Blank parameter")             //
  192 #define ERR_TOO_MANY_PARAMS _T("Too many parameters passed to function.") // L31
  193 #define ERR_TOO_FEW_PARAMS _T("Too few parameters passed to function.") // L31
  194 #define ERR_BAD_OPTIONAL_PARAM _T("Expected \":=\"")
  195 #define ERR_HOTKEY_FUNC_PARAMS _T("Parameters of hotkey functions must be optional.")
  196 #define ERR_ELSE_WITH_NO_IF _T("ELSE with no matching IF")
  197 #define ERR_UNTIL_WITH_NO_LOOP _T("UNTIL with no matching LOOP")
  198 #define ERR_CATCH_WITH_NO_TRY _T("CATCH with no matching TRY")
  199 #define ERR_FINALLY_WITH_NO_PRECEDENT _T("FINALLY with no matching TRY or CATCH")
  200 #define ERR_BAD_JUMP_INSIDE_FINALLY _T("Jumps cannot exit a FINALLY block.")
  201 #define ERR_BAD_JUMP_OUT_OF_FUNCTION _T("Cannot jump from inside a function to outside.")
  202 #define ERR_UNEXPECTED_CASE _T("Case/Default must be enclosed by a Switch.")
  203 #define ERR_TOO_MANY_CASE_VALUES _T("Too many case values.")
  204 #define ERR_EXPECTED_BLOCK_OR_ACTION _T("Expected \"{\" or single-line action.")
  205 #define ERR_OUTOFMEM _T("Out of memory.")  // Used by RegEx too, so don't change it without also changing RegEx to keep the former string.
  206 #define ERR_EXPR_TOO_LONG _T("Expression too long")
  207 #define ERR_MEM_LIMIT_REACHED _T("Memory limit reached (see #MaxMem in the help file).")
  208 #define ERR_NO_LABEL _T("Target label does not exist.")
  209 #define ERR_MENU _T("Menu does not exist.")
  210 #define ERR_SUBMENU _T("Submenu does not exist.")
  211 #define ERR_WINDOW_PARAM _T("Requires at least one of its window parameters.")
  212 #define ERR_MENUTRAY _T("Supported only for the tray menu")
  213 #define ERR_MOUSE_COORD _T("X & Y must be either both absent or both present.")
  214 #define ERR_DIVIDEBYZERO _T("Divide by zero")
  215 #define ERR_VAR_IS_READONLY _T("Not allowed as an output variable.")
  216 #define ERR_INVALID_CHAR _T("This character is not allowed here.")
  217 #define ERR_INVALID_DOT _T("Ambiguous or invalid use of \".\"")
  218 #define ERR_UNQUOTED_NON_ALNUM _T("Unquoted literals may only consist of alphanumeric characters/underscore.")
  219 #define ERR_DUPLICATE_DECLARATION _T("Duplicate declaration.")
  220 #define ERR_INVALID_FUNCDECL _T("Invalid function declaration.")
  221 #define ERR_INVALID_CLASS_VAR _T("Invalid class variable declaration.")
  222 #define ERR_INVALID_LINE_IN_CLASS_DEF _T("Not a valid method, class or property definition.")
  223 #define ERR_INVALID_LINE_IN_PROPERTY_DEF _T("Not a valid property getter/setter.")
  224 #define ERR_INVALID_GUI_NAME _T("Invalid Gui name.")
  225 #define ERR_INVALID_OPTION _T("Invalid option.") // Generic message used by Gui and GuiControl/Get.
  226 #define ERR_HOTKEY_IF_EXPR _T("Parameter #2 must match an existing #If expression.")
  227 #define ERR_EXCEPTION _T("An exception was thrown.")
  228 #define ERR_INVALID_USAGE _T("Invalid usage.")
  229 
  230 #define WARNING_USE_UNSET_VARIABLE _T("This variable has not been assigned a value.")
  231 #define WARNING_LOCAL_SAME_AS_GLOBAL _T("This local variable has the same name as a global variable.")
  232 #define WARNING_USE_ENV_VARIABLE _T("An environment variable is being accessed; see #NoEnv.")
  233 #define WARNING_CLASS_OVERWRITE _T("Class may be overwritten.")
  234 
  235 //----------------------------------------------------------------------------------
  236 
  237 void DoIncrementalMouseMove(int aX1, int aY1, int aX2, int aY2, int aSpeed);
  238 
  239 DWORD ProcessExist(LPTSTR aProcess);
  240 DWORD GetProcessName(DWORD aProcessID, LPTSTR aBuf, DWORD aBufSize, bool aGetNameOnly);
  241 
  242 bool Util_Shutdown(int nFlag);
  243 BOOL Util_ShutdownHandler(HWND hwnd, DWORD lParam);
  244 void Util_WinKill(HWND hWnd);
  245 
  246 enum MainWindowModes {MAIN_MODE_NO_CHANGE, MAIN_MODE_LINES, MAIN_MODE_VARS
  247     , MAIN_MODE_HOTKEYS, MAIN_MODE_KEYHISTORY, MAIN_MODE_REFRESH};
  248 ResultType ShowMainWindow(MainWindowModes aMode = MAIN_MODE_NO_CHANGE, bool aRestricted = true);
  249 DWORD GetAHKInstallDir(LPTSTR aBuf);
  250 
  251 
  252 struct InputBoxType
  253 {
  254     LPTSTR title;
  255     LPTSTR text;
  256     int width;
  257     int height;
  258     int xpos;
  259     int ypos;
  260     Var *output_var;
  261     TCHAR password_char;
  262     LPTSTR default_string;
  263     DWORD timeout;
  264     HWND hwnd;
  265     HFONT font;
  266     bool locale;
  267 };
  268 
  269 struct SplashType
  270 {
  271     int width;
  272     int height;
  273     int bar_pos;  // The amount of progress of the bar (it's position).
  274     int margin_x; // left/right margin
  275     int margin_y; // top margin
  276     int text1_height; // Height of main text control.
  277     int object_width;   // Width of image.
  278     int object_height;  // Height of the progress bar or image.
  279     HWND hwnd;
  280     int pic_type;
  281     union
  282     {
  283         HBITMAP pic_bmp; // For SplashImage.
  284         HICON pic_icon;
  285     };
  286     HWND hwnd_bar;
  287     HWND hwnd_text1;  // MainText
  288     HWND hwnd_text2;  // SubText
  289     HFONT hfont1; // Main
  290     HFONT hfont2; // Sub
  291     HBRUSH hbrush; // Window background color brush.
  292     COLORREF color_bk; // The background color itself.
  293     COLORREF color_text; // Color of the font.
  294 };
  295 
  296 // Use GetClientRect() to determine the available width so that control's can be centered.
  297 #define SPLASH_CALC_YPOS \
  298     int bar_y = splash.margin_y + (splash.text1_height ? (splash.text1_height + splash.margin_y) : 0);\
  299     int sub_y = bar_y + splash.object_height + (splash.object_height ? splash.margin_y : 0); // i.e. don't include margin_y twice if there's no bar.
  300 #define PROGRESS_MAIN_POS splash.margin_x, splash.margin_y, control_width, splash.text1_height
  301 #define PROGRESS_BAR_POS  splash.margin_x, bar_y, control_width, splash.object_height
  302 #define PROGRESS_SUB_POS  splash.margin_x, sub_y, control_width, (client_rect.bottom - client_rect.top) - sub_y
  303 
  304 // From AutoIt3's InputBox.  This doesn't add a measurable amount of code size, so the compiler seems to implement
  305 // it efficiently (somewhat like a macro).
  306 template <class T>
  307 inline void swap(T &v1, T &v2) {
  308     T tmp=v1;
  309     v1=v2;
  310     v2=tmp;
  311 }
  312 
  313 // The following functions are used in GUI DPI scaling, so that
  314 // GUIs designed for a 96 DPI setting (i.e. using absolute coords
  315 // or explicit widths/sizes) can continue to run with mostly no issues.
  316 
  317 static inline int DPIScale(int x)
  318 {
  319     extern int g_ScreenDPI;
  320     return MulDiv(x, g_ScreenDPI, 96);
  321 }
  322 
  323 static inline int DPIUnscale(int x)
  324 {
  325     extern int g_ScreenDPI;
  326     return MulDiv(x, 96, g_ScreenDPI);
  327 }
  328 
  329 #define INPUTBOX_DEFAULT INT_MIN
  330 ResultType InputBox(Var *aOutputVar, LPTSTR aTitle, LPTSTR aText, bool aHideInput
  331     , int aWidth, int aHeight, int aX, int aY, bool aLocale, double aTimeout, LPTSTR aDefault);
  332 INT_PTR CALLBACK InputBoxProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  333 VOID CALLBACK InputBoxTimeout(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
  334 VOID CALLBACK DerefTimeout(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
  335 BOOL CALLBACK EnumChildFindSeqNum(HWND aWnd, LPARAM lParam);
  336 BOOL CALLBACK EnumChildFindPoint(HWND aWnd, LPARAM lParam);
  337 BOOL CALLBACK EnumChildGetControlList(HWND aWnd, LPARAM lParam);
  338 BOOL CALLBACK EnumMonitorProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM lParam);
  339 BOOL CALLBACK EnumChildGetText(HWND aWnd, LPARAM lParam);
  340 LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  341 bool HandleMenuItem(HWND aHwnd, WORD aMenuItemID, HWND aGuiHwnd);
  342 INT_PTR CALLBACK TabDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  343 #define TABDIALOG_ATTRIB_BACKGROUND_DEFAULT 1
  344 #define TABDIALOG_ATTRIB_THEMED 2
  345 
  346 
  347 typedef UINT LineNumberType;
  348 typedef WORD FileIndexType; // Use WORD to conserve memory due to its use in the Line class (adjacency to other members and due to 4-byte struct alignment).
  349 #define ABSOLUTE_MAX_SOURCE_FILES 0xFFFF // Keep this in sync with the capacity of the type above.  Actually it could hold 0xFFFF+1, but avoid the final item for maintainability (otherwise max-index won't be able to fit inside a variable of that type).
  350 
  351 #define LOADING_FAILED UINT_MAX
  352 
  353 // -2 for the beginning and ending g_DerefChars:
  354 #define MAX_VAR_NAME_LENGTH (UCHAR_MAX - 2)
  355 #define MAX_FUNCTION_PARAMS UCHAR_MAX // Also conserves stack space to support future attributes such as param default values.
  356 #define MAX_DEREFS_PER_ARG 512
  357 
  358 typedef WORD DerefLengthType; // WORD might perform better than UCHAR, but this can be changed to UCHAR if another field is ever needed in the struct.
  359 typedef UCHAR DerefParamCountType;
  360 
  361 class Func; // Forward declaration for use below.
  362 struct DerefType
  363 {
  364     LPTSTR marker;
  365     union
  366     {
  367         Var *var;
  368         Func *func;
  369     };
  370     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  371     // due to byte-alignment:
  372     BYTE is_function;
  373 #define DEREF_VARIADIC 2
  374     DerefParamCountType param_count; // The actual number of parameters present in this function *call*.  Left uninitialized except for functions.
  375     DerefLengthType length; // Listed only after byte-sized fields, due to it being a WORD.
  376 };
  377 
  378 typedef UCHAR ArgTypeType;  // UCHAR vs. an enum, to save memory.
  379 #define ARG_TYPE_NORMAL     (UCHAR)0
  380 #define ARG_TYPE_INPUT_VAR  (UCHAR)1
  381 #define ARG_TYPE_OUTPUT_VAR (UCHAR)2
  382 
  383 struct ArgStruct
  384 {
  385     ArgTypeType type;
  386     bool is_expression; // Whether this ARG is known to contain an expression.
  387     // Above are kept adjacent to each other to conserve memory (any fields that aren't an even
  388     // multiple of 4, if adjacent to each other, consume less memory due to default byte alignment
  389     // setting [which helps performance]).
  390     WORD length; // Keep adjacent to above so that it uses no extra memory. This member was added in v1.0.44.14 to improve runtime performance.  It relies on the fact that an arg's literal text can't be longer than LINE_SIZE.
  391     LPTSTR text;
  392     DerefType *deref;  // Will hold a NULL-terminated array of var-deref locations within <text>.
  393     ExprTokenType *postfix;  // An array of tokens in postfix order. Also used for ACT_ADD and others to store pre-converted binary integers.
  394 };
  395 
  396 #define BIF_DECL_PARAMS ResultType &aResult, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount
  397 
  398 // The following macro is used for definitions and declarations of built-in functions:
  399 #define BIF_DECL(name) void name(BIF_DECL_PARAMS)
  400 
  401 // NOTE FOR v1: The following macros currently aren't used much; they're for use in new code
  402 // to facilitate merging into the v2 branch, which uses its own versions of these macros heavily.
  403 // This is just the subset of the macros that don't rely on other changes.
  404 #define _f__oneline(act)        do { act } while (0)        // Make the macro safe to use like a function, under if(), etc.
  405 #define _f__ret(act)            _f__oneline( aResult = (act); return; ) // BIFs have no return value.
  406 #define _o__ret(act)            return (act)                // IObject::Invoke() returns ResultType.
  407 #define _f_throw(...)           _f__ret(g_script.ScriptError(__VA_ARGS__))
  408 #define _o_throw(...)           _o__ret(g_script.ScriptError(__VA_ARGS__))
  409 #define _f_return_FAIL          _f__ret(FAIL)
  410 #define _o_return_FAIL          _o__ret(FAIL)
  411 #define _f_retval_buf           (aResultToken.buf)
  412 #define _f_retval_buf_size      MAX_NUMBER_SIZE
  413 #define _f_number_buf           _f_retval_buf  // An alias to show intended usage, and in case the buffer size is changed.
  414 
  415 
  416 struct LoopFilesStruct : WIN32_FIND_DATA
  417 {
  418     // Note that using fixed buffer sizes significantly reduces code size vs. using CString
  419     // or probably any other method of dynamically allocating/expanding the buffers.  It also
  420     // performs marginally better, but file system performance has a much bigger impact.
  421     // Unicode builds allow for the maximum path size supported by Win32 as of 2018, although
  422     // in some cases the script might need to use the \\?\ prefix to go beyond MAX_PATH.
  423     // On Windows 10 v1607+, MAX_PATH limits can be lifted by opting-in to long path support
  424     // via the application's manifest and LongPathsEnabled registry setting.  In any case,
  425     // ANSI APIs are still limited to MAX_PATH, but MAX_PATH*2 allows for the longest path
  426     // supported by FindFirstFile() concatenated with the longest filename it can return.
  427     // This preserves backward-compatibility under the following set of conditions:
  428     //  1) the absolute path and pattern fits within MAX_PATH;
  429     //  2) the relative path and filename fits within MAX_PATH; and
  430     //  3) the absolute path and filename exceeds MAX_PATH.
  431     static const size_t BUF_SIZE = UorA(MAX_WIDE_PATH, MAX_PATH*2);
  432     // file_path contains the full path of the directory being looped, with trailing slash.
  433     // Temporarily also contains the pattern for FindFirstFile(), which is either a copy of
  434     // 'pattern' or "*" for scanning sub-directories.
  435     // During execution of the loop body, it contains the full path of the file.
  436     TCHAR file_path[BUF_SIZE];
  437     TCHAR pattern[MAX_PATH]; // Naked filename or pattern.  Allows max NTFS filename length plus a few chars.
  438     TCHAR short_path[BUF_SIZE]; // Short name version of orig_dir.
  439     TCHAR *file_path_suffix; // The dynamic part of file_path (used by A_LoopFilePath).
  440     TCHAR *orig_dir; // Initial directory as specified by caller (used by A_LoopFilePath).
  441     TCHAR *long_dir; // Full/long path of initial directory (used by A_LoopFileLongPath).
  442     size_t file_path_length, pattern_length, short_path_length, orig_dir_length, long_dir_length
  443         , dir_length; // Portion of file_path which is the directory, used by BIVs.
  444 
  445     LoopFilesStruct() : orig_dir_length(0), long_dir(NULL) {}
  446     ~LoopFilesStruct()
  447     {
  448         if (orig_dir_length)
  449             free(orig_dir);
  450         //else: orig_dir is the constant _T("").
  451         free(long_dir);
  452     }
  453 };
  454 
  455 // Some of these lengths and such are based on the MSDN example at
  456 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/enumerating_registry_subkeys.asp:
  457 // FIX FOR v1.0.48: 
  458 // OLDER (v1.0.44.07): Someone reported that a stack overflow was possible, implying that it only happens
  459 // during extremely deep nesting of subkey names (perhaps a hundred or more nested subkeys).  Upon review, it seems
  460 // that the prior limit of 16383 for value-name-length is higher than needed; testing shows that a value name can't
  461 // be longer than 259 (limit might even be 255 if API vs. RegEdit is used to create the name).  Testing also shows
  462 // that the total path name of a registry item (including item/value name but excluding the name of the root key)
  463 // obeys the same limit BUT ONLY within the RegEdit GUI.  RegEdit seems capable of importing subkeys whose names
  464 // (even without any value name appended) are longer than 259 characters (see comments higher above).
  465 #define MAX_REG_ITEM_SIZE 1024 // Needs to be greater than 260 (see comments above), but I couldn't find any documentation at MSDN or the web about the max length of a subkey name.  One example at MSDN RegEnumKeyEx() uses MAX_KEY_LENGTH=255 and MAX_VALUE_NAME=16383, but clearly MAX_KEY_LENGTH should be larger.
  466 #define REG_SUBKEY -2 // Custom type, not standard in Windows.
  467 struct RegItemStruct
  468 {
  469     HKEY root_key_type, root_key;  // root_key_type is always a local HKEY, whereas root_key can be a remote handle.
  470     TCHAR subkey[MAX_REG_ITEM_SIZE];  // The branch of the registry where this subkey or value is located.
  471     TCHAR name[MAX_REG_ITEM_SIZE]; // The subkey or value name.
  472     DWORD type; // Value Type (e.g REG_DWORD).
  473     FILETIME ftLastWriteTime; // Non-initialized.
  474     void InitForValues() {ftLastWriteTime.dwHighDateTime = ftLastWriteTime.dwLowDateTime = 0;}
  475     void InitForSubkeys() {type = REG_SUBKEY;}  // To distinguish REG_DWORD and such from the subkeys themselves.
  476     RegItemStruct(HKEY aRootKeyType, HKEY aRootKey, LPTSTR aSubKey)
  477         : root_key_type(aRootKeyType), root_key(aRootKey), type(REG_NONE)
  478     {
  479         *name = '\0';
  480         // Make a local copy on the caller's stack so that if the current script subroutine is
  481         // interrupted to allow another to run, the contents of the deref buffer is saved here:
  482         tcslcpy(subkey, aSubKey, _countof(subkey));
  483         // Even though the call may work with a trailing backslash, it's best to remove it
  484         // so that consistent results are delivered to the user.  For example, if the script
  485         // is enumerating recursively into a subkey, subkeys deeper down will not include the
  486         // trailing backslash when they are reported.  So the user's own subkey should not
  487         // have one either so that when A_ScriptSubKey is referenced in the script, it will
  488         // always show up as the value without a trailing backslash:
  489         size_t length = _tcslen(subkey);
  490         if (length && subkey[length - 1] == '\\')
  491             subkey[length - 1] = '\0';
  492     }
  493 };
  494 
  495 class TextStream; // TextIO
  496 struct LoopReadFileStruct
  497 {
  498     TextStream *mReadFile, *mWriteFile;
  499     LPTSTR mWriteFileName;
  500     #define READ_FILE_LINE_SIZE (64 * 1024)  // This is also used by FileReadLine().
  501     TCHAR mCurrentLine[READ_FILE_LINE_SIZE];
  502     LoopReadFileStruct(TextStream *aReadFile, LPTSTR aWriteFileName)
  503         : mReadFile(aReadFile), mWriteFile(NULL) // mWriteFile is opened by FileAppend() only upon first use.
  504         , mWriteFileName(aWriteFileName) // Caller has passed the result of _tcsdup() for us to take over.
  505     {
  506         *mCurrentLine = '\0';
  507     }
  508     ~LoopReadFileStruct()
  509     {
  510         free(mWriteFileName);
  511     }
  512 };
  513 
  514 // TextStream flags for LoadIncludedFile (script files), file-reading loops and FileReadLine.
  515 // Do not lock read/write: older versions used fopen(), which is implicitly permissive.
  516 #define DEFAULT_READ_FLAGS (TextStream::READ | TextStream::EOL_CRLF | TextStream::EOL_ORPHAN_CR | TextStream::SHARE_READ | TextStream::SHARE_WRITE)
  517 
  518 
  519 typedef UCHAR ArgCountType;
  520 #define MAX_ARGS 20   // Maximum number of args used by any command.
  521 
  522 
  523 enum DllArgTypes {
  524       DLL_ARG_INVALID
  525     , DLL_ARG_ASTR
  526     , DLL_ARG_INT
  527     , DLL_ARG_SHORT
  528     , DLL_ARG_CHAR
  529     , DLL_ARG_INT64
  530     , DLL_ARG_FLOAT
  531     , DLL_ARG_DOUBLE
  532     , DLL_ARG_WSTR
  533     , DLL_ARG_STR  = UorA(DLL_ARG_WSTR, DLL_ARG_ASTR)
  534     , DLL_ARG_xSTR = UorA(DLL_ARG_ASTR, DLL_ARG_WSTR) // To simplify some sections.
  535 };  // Some sections might rely on DLL_ARG_INVALID being 0.
  536 
  537 
  538 // Note that currently this value must fit into a sc_type variable because that is how TextToKey()
  539 // stores it in the hotkey class.  sc_type is currently a UINT, and will always be at least a
  540 // WORD in size, so it shouldn't be much of an issue:
  541 #define MAX_JOYSTICKS 16  // The maximum allowed by any Windows operating system.
  542 #define MAX_JOY_BUTTONS 32 // Also the max that Windows supports.
  543 enum JoyControls {JOYCTRL_INVALID, JOYCTRL_XPOS, JOYCTRL_YPOS, JOYCTRL_ZPOS
  544 , JOYCTRL_RPOS, JOYCTRL_UPOS, JOYCTRL_VPOS, JOYCTRL_POV
  545 , JOYCTRL_NAME, JOYCTRL_BUTTONS, JOYCTRL_AXES, JOYCTRL_INFO
  546 , JOYCTRL_1, JOYCTRL_2, JOYCTRL_3, JOYCTRL_4, JOYCTRL_5, JOYCTRL_6, JOYCTRL_7, JOYCTRL_8  // Buttons.
  547 , JOYCTRL_9, JOYCTRL_10, JOYCTRL_11, JOYCTRL_12, JOYCTRL_13, JOYCTRL_14, JOYCTRL_15, JOYCTRL_16
  548 , JOYCTRL_17, JOYCTRL_18, JOYCTRL_19, JOYCTRL_20, JOYCTRL_21, JOYCTRL_22, JOYCTRL_23, JOYCTRL_24
  549 , JOYCTRL_25, JOYCTRL_26, JOYCTRL_27, JOYCTRL_28, JOYCTRL_29, JOYCTRL_30, JOYCTRL_31, JOYCTRL_32
  550 , JOYCTRL_BUTTON_MAX = JOYCTRL_32
  551 };
  552 #define IS_JOYSTICK_BUTTON(joy) (joy >= JOYCTRL_1 && joy <= JOYCTRL_BUTTON_MAX)
  553 
  554 enum WinGetCmds {WINGET_CMD_INVALID, WINGET_CMD_ID, WINGET_CMD_IDLAST, WINGET_CMD_PID, WINGET_CMD_PROCESSNAME
  555     , WINGET_CMD_COUNT, WINGET_CMD_LIST, WINGET_CMD_MINMAX, WINGET_CMD_CONTROLLIST, WINGET_CMD_CONTROLLISTHWND
  556     , WINGET_CMD_STYLE, WINGET_CMD_EXSTYLE, WINGET_CMD_TRANSPARENT, WINGET_CMD_TRANSCOLOR, WINGET_CMD_PROCESSPATH
  557 };
  558 
  559 enum SysGetCmds {SYSGET_CMD_INVALID, SYSGET_CMD_METRICS, SYSGET_CMD_MONITORCOUNT, SYSGET_CMD_MONITORPRIMARY
  560     , SYSGET_CMD_MONITORAREA, SYSGET_CMD_MONITORWORKAREA, SYSGET_CMD_MONITORNAME
  561 };
  562 
  563 enum TransformCmds {TRANS_CMD_INVALID, TRANS_CMD_ASC, TRANS_CMD_CHR, TRANS_CMD_DEREF
  564     , TRANS_CMD_UNICODE, TRANS_CMD_HTML
  565     , TRANS_CMD_MOD, TRANS_CMD_POW, TRANS_CMD_EXP, TRANS_CMD_SQRT, TRANS_CMD_LOG, TRANS_CMD_LN
  566     , TRANS_CMD_ROUND, TRANS_CMD_CEIL, TRANS_CMD_FLOOR, TRANS_CMD_ABS
  567     , TRANS_CMD_SIN, TRANS_CMD_COS, TRANS_CMD_TAN, TRANS_CMD_ASIN, TRANS_CMD_ACOS, TRANS_CMD_ATAN
  568     , TRANS_CMD_BITAND, TRANS_CMD_BITOR, TRANS_CMD_BITXOR, TRANS_CMD_BITNOT
  569     , TRANS_CMD_BITSHIFTLEFT, TRANS_CMD_BITSHIFTRIGHT
  570 };
  571 
  572 enum MenuCommands {MENU_CMD_INVALID, MENU_CMD_SHOW, MENU_CMD_USEERRORLEVEL
  573     , MENU_CMD_ADD, MENU_CMD_RENAME, MENU_CMD_INSERT
  574     , MENU_CMD_CHECK, MENU_CMD_UNCHECK, MENU_CMD_TOGGLECHECK
  575     , MENU_CMD_ENABLE, MENU_CMD_DISABLE, MENU_CMD_TOGGLEENABLE
  576     , MENU_CMD_STANDARD, MENU_CMD_NOSTANDARD, MENU_CMD_COLOR, MENU_CMD_DEFAULT, MENU_CMD_NODEFAULT
  577     , MENU_CMD_DELETE, MENU_CMD_DELETEALL, MENU_CMD_TIP, MENU_CMD_ICON, MENU_CMD_NOICON
  578     , MENU_CMD_CLICK, MENU_CMD_MAINWINDOW, MENU_CMD_NOMAINWINDOW
  579 };
  580 
  581 #define AHK_LV_SELECT       0x0100
  582 #define AHK_LV_DESELECT     0x0200
  583 #define AHK_LV_FOCUS        0x0400
  584 #define AHK_LV_DEFOCUS      0x0800
  585 #define AHK_LV_CHECK        0x1000
  586 #define AHK_LV_UNCHECK      0x2000
  587 #define AHK_LV_DROPHILITE   0x4000
  588 #define AHK_LV_UNDROPHILITE 0x8000
  589 // Although there's no room remaining in the BYTE for LVIS_CUT (AHK_LV_CUT) [assuming it's ever needed],
  590 // it might be possible to squeeze more info into it as follows:
  591 // Each pair of bits can represent three values (other than zero).  But since only two values are needed
  592 // (since an item can't be both selected an deselected simultaneously), one value in each pair is available
  593 // for future use such as LVIS_CUT.
  594 
  595 enum GuiCommands {GUI_CMD_INVALID, GUI_CMD_OPTIONS, GUI_CMD_ADD, GUI_CMD_MARGIN, GUI_CMD_MENU
  596     , GUI_CMD_SHOW, GUI_CMD_SUBMIT, GUI_CMD_CANCEL, GUI_CMD_MINIMIZE, GUI_CMD_MAXIMIZE, GUI_CMD_RESTORE
  597     , GUI_CMD_DESTROY, GUI_CMD_FONT, GUI_CMD_TAB, GUI_CMD_LISTVIEW, GUI_CMD_TREEVIEW, GUI_CMD_DEFAULT
  598     , GUI_CMD_COLOR, GUI_CMD_FLASH, GUI_CMD_NEW
  599 };
  600 
  601 enum GuiControlCmds {GUICONTROL_CMD_INVALID, GUICONTROL_CMD_OPTIONS, GUICONTROL_CMD_CONTENTS, GUICONTROL_CMD_TEXT
  602     , GUICONTROL_CMD_MOVE, GUICONTROL_CMD_MOVEDRAW, GUICONTROL_CMD_FOCUS, GUICONTROL_CMD_ENABLE, GUICONTROL_CMD_DISABLE
  603     , GUICONTROL_CMD_SHOW, GUICONTROL_CMD_HIDE, GUICONTROL_CMD_CHOOSE, GUICONTROL_CMD_CHOOSESTRING
  604     , GUICONTROL_CMD_FONT
  605 };
  606 
  607 enum GuiControlGetCmds {GUICONTROLGET_CMD_INVALID, GUICONTROLGET_CMD_CONTENTS, GUICONTROLGET_CMD_POS
  608     , GUICONTROLGET_CMD_FOCUS, GUICONTROLGET_CMD_FOCUSV, GUICONTROLGET_CMD_ENABLED, GUICONTROLGET_CMD_VISIBLE
  609     , GUICONTROLGET_CMD_HWND, GUICONTROLGET_CMD_NAME
  610 };
  611 
  612 typedef UCHAR GuiControls;
  613 enum GuiControlTypes {GUI_CONTROL_INVALID // GUI_CONTROL_INVALID must be zero due to things like ZeroMemory() on the struct.
  614     , GUI_CONTROL_TEXT, GUI_CONTROL_PIC, GUI_CONTROL_GROUPBOX
  615     , GUI_CONTROL_BUTTON, GUI_CONTROL_CHECKBOX, GUI_CONTROL_RADIO
  616     , GUI_CONTROL_DROPDOWNLIST, GUI_CONTROL_COMBOBOX
  617     , GUI_CONTROL_LISTBOX, GUI_CONTROL_LISTVIEW, GUI_CONTROL_TREEVIEW
  618     , GUI_CONTROL_EDIT, GUI_CONTROL_DATETIME, GUI_CONTROL_MONTHCAL, GUI_CONTROL_HOTKEY
  619     , GUI_CONTROL_UPDOWN, GUI_CONTROL_SLIDER, GUI_CONTROL_PROGRESS, GUI_CONTROL_TAB, GUI_CONTROL_TAB2, GUI_CONTROL_TAB3
  620     , GUI_CONTROL_ACTIVEX, GUI_CONTROL_LINK, GUI_CONTROL_CUSTOM, GUI_CONTROL_STATUSBAR}; // Kept last to reflect it being bottommost in switch()s (for perf), since not too often used.
  621 
  622 enum ThreadCommands {THREAD_CMD_INVALID, THREAD_CMD_PRIORITY, THREAD_CMD_INTERRUPT, THREAD_CMD_NOTIMERS};
  623 
  624 #define PROCESS_PRIORITY_LETTERS _T("LBNAHR")
  625 enum ProcessCmds {PROCESS_CMD_INVALID, PROCESS_CMD_EXIST, PROCESS_CMD_CLOSE, PROCESS_CMD_PRIORITY
  626     , PROCESS_CMD_WAIT, PROCESS_CMD_WAITCLOSE};
  627 
  628 enum ControlCmds {CONTROL_CMD_INVALID, CONTROL_CMD_CHECK, CONTROL_CMD_UNCHECK
  629     , CONTROL_CMD_ENABLE, CONTROL_CMD_DISABLE, CONTROL_CMD_SHOW, CONTROL_CMD_HIDE
  630     , CONTROL_CMD_STYLE, CONTROL_CMD_EXSTYLE
  631     , CONTROL_CMD_SHOWDROPDOWN, CONTROL_CMD_HIDEDROPDOWN
  632     , CONTROL_CMD_TABLEFT, CONTROL_CMD_TABRIGHT
  633     , CONTROL_CMD_ADD, CONTROL_CMD_DELETE, CONTROL_CMD_CHOOSE
  634     , CONTROL_CMD_CHOOSESTRING, CONTROL_CMD_EDITPASTE};
  635 
  636 enum ControlGetCmds {CONTROLGET_CMD_INVALID, CONTROLGET_CMD_CHECKED, CONTROLGET_CMD_ENABLED
  637     , CONTROLGET_CMD_VISIBLE, CONTROLGET_CMD_TAB, CONTROLGET_CMD_FINDSTRING
  638     , CONTROLGET_CMD_CHOICE, CONTROLGET_CMD_LIST, CONTROLGET_CMD_LINECOUNT, CONTROLGET_CMD_CURRENTLINE
  639     , CONTROLGET_CMD_CURRENTCOL, CONTROLGET_CMD_LINE, CONTROLGET_CMD_SELECTED
  640     , CONTROLGET_CMD_STYLE, CONTROLGET_CMD_EXSTYLE, CONTROLGET_CMD_HWND};
  641 
  642 enum DriveCmds {DRIVE_CMD_INVALID, DRIVE_CMD_EJECT, DRIVE_CMD_LOCK, DRIVE_CMD_UNLOCK, DRIVE_CMD_LABEL};
  643 
  644 enum DriveGetCmds {DRIVEGET_CMD_INVALID, DRIVEGET_CMD_LIST, DRIVEGET_CMD_FILESYSTEM, DRIVEGET_CMD_LABEL
  645     , DRIVEGET_CMD_SETLABEL, DRIVEGET_CMD_SERIAL, DRIVEGET_CMD_TYPE, DRIVEGET_CMD_STATUS
  646     , DRIVEGET_CMD_STATUSCD, DRIVEGET_CMD_CAPACITY};
  647 
  648 enum WinSetAttributes {WINSET_INVALID, WINSET_TRANSPARENT, WINSET_TRANSCOLOR, WINSET_ALWAYSONTOP
  649     , WINSET_BOTTOM, WINSET_TOP, WINSET_STYLE, WINSET_EXSTYLE, WINSET_REDRAW, WINSET_ENABLE, WINSET_DISABLE
  650     , WINSET_REGION};
  651 
  652 
  653 class Label; // Forward declaration so that each can use the other.
  654 class Line
  655 {
  656 private:
  657     ResultType EvaluateCondition();
  658     bool EvaluateLoopUntil(ResultType &aResult);
  659     ResultType Line::PerformLoop(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
  660         , __int64 aIterationLimit, bool aIsInfinite);
  661     ResultType PerformLoopFilePattern(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
  662         , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, LPTSTR aFilePattern);
  663     bool ParseLoopFilePattern(LPTSTR aFilePattern, LoopFilesStruct &lfs, ResultType &aResult);
  664     ResultType PerformLoopFilePattern(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
  665         , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, LoopFilesStruct &lfs);
  666     ResultType PerformLoopReg(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
  667         , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, HKEY aRootKeyType, HKEY aRootKey, LPTSTR aRegSubkey);
  668     ResultType PerformLoopParse(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil);
  669     ResultType Line::PerformLoopParseCSV(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil);
  670     ResultType PerformLoopReadFile(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil, TextStream *aReadFile, LPTSTR aWriteFileName);
  671     ResultType PerformLoopWhile(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine); // Lexikos: ACT_WHILE.
  672     ResultType PerformLoopFor(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil); // Lexikos: ACT_FOR.
  673     ResultType Perform();
  674 
  675     ResultType MouseGetPos(DWORD aOptions);
  676     ResultType FormatTime(LPTSTR aYYYYMMDD, LPTSTR aFormat);
  677     ResultType PerformAssign();
  678     ResultType StringReplace();
  679     ResultType StringSplit(LPTSTR aArrayName, LPTSTR aInputString, LPTSTR aDelimiterList, LPTSTR aOmitList);
  680     ResultType SplitPath(LPTSTR aFileSpec);
  681     ResultType PerformSort(LPTSTR aContents, LPTSTR aOptions);
  682     ResultType GetKeyJoyState(LPTSTR aKeyName, LPTSTR aOption);
  683     ResultType DriveSpace(LPTSTR aPath, bool aGetFreeSpace);
  684     ResultType Drive(LPTSTR aCmd, LPTSTR aValue, LPTSTR aValue2);
  685     ResultType DriveLock(TCHAR aDriveLetter, bool aLockIt);
  686     ResultType DriveGet(LPTSTR aCmd, LPTSTR aValue);
  687     ResultType SoundSetGet(LPTSTR aSetting, LPTSTR aComponentType, LPTSTR aControlType, LPTSTR aDevice);
  688     ResultType SoundSetGet2kXP(LPTSTR aSetting, DWORD aComponentType, int aComponentInstance
  689         , DWORD aControlType, LPTSTR aDevice);
  690     ResultType SoundSetGetVista(LPTSTR aSetting, DWORD aComponentType, int aComponentInstance
  691         , DWORD aControlType, LPTSTR aDevice);
  692     ResultType SoundGetWaveVolume(HWAVEOUT aDeviceID);
  693     ResultType SoundSetWaveVolume(LPTSTR aVolume, HWAVEOUT aDeviceID);
  694     ResultType SoundPlay(LPTSTR aFilespec, bool aSleepUntilDone);
  695     ResultType URLDownloadToFile(LPTSTR aURL, LPTSTR aFilespec);
  696     ResultType FileSelectFile(LPTSTR aOptions, LPTSTR aWorkingDir, LPTSTR aGreeting, LPTSTR aFilter);
  697 
  698     // Bitwise flags:
  699     #define FSF_ALLOW_CREATE 0x01
  700     #define FSF_EDITBOX      0x02
  701     #define FSF_NONEWDIALOG  0x04
  702     ResultType FileSelectFolder(LPTSTR aRootDir, LPTSTR aOptions, LPTSTR aGreeting);
  703 
  704     ResultType FileGetShortcut(LPTSTR aShortcutFile);
  705     ResultType FileCreateShortcut(LPTSTR aTargetFile, LPTSTR aShortcutFile, LPTSTR aWorkingDir, LPTSTR aArgs
  706         , LPTSTR aDescription, LPTSTR aIconFile, LPTSTR aHotkey, LPTSTR aIconNumber, LPTSTR aRunState);
  707     static bool FileCreateDir(LPTSTR aDirSpec, LPTSTR aCanModifyDirSpec = NULL);
  708     ResultType FileRead(LPTSTR aFilespec);
  709     ResultType FileReadLine(LPTSTR aFilespec, LPTSTR aLineNumber);
  710     ResultType FileAppend(LPTSTR aFilespec, LPTSTR aBuf, LoopReadFileStruct *aCurrentReadFile);
  711     ResultType WriteClipboardToFile(LPTSTR aFilespec, Var *aBinaryClipVar = NULL);
  712     ResultType FileDelete(LPTSTR aFilePattern);
  713     ResultType FileRecycle(LPTSTR aFilePattern);
  714     ResultType FileRecycleEmpty(LPTSTR aDriveLetter);
  715     ResultType FileInstall(LPTSTR aSource, LPTSTR aDest, LPTSTR aFlag);
  716 
  717     typedef BOOL (* FilePatternCallback)(LPTSTR aFilename, WIN32_FIND_DATA &aFile, void *aCallbackData);
  718     struct FilePatternStruct
  719     {
  720         TCHAR path[T_MAX_PATH]; // Directory and naked filename or pattern.
  721         TCHAR pattern[MAX_PATH]; // Naked filename or pattern.
  722         size_t dir_length, pattern_length;
  723         FilePatternCallback aCallback;
  724         void *aCallbackData;
  725         FileLoopModeType aOperateOnFolders;
  726         bool aDoRecurse;
  727         int failure_count;
  728     };
  729     ResultType FilePatternApply(LPTSTR aFilePattern, FileLoopModeType aOperateOnFolders
  730         , bool aDoRecurse, FilePatternCallback aCallback, void *aCallbackData);
  731     void FilePatternApply(FilePatternStruct &);
  732 
  733     ResultType FileGetAttrib(LPTSTR aFilespec);
  734     ResultType FileSetAttrib(LPTSTR aAttributes, LPTSTR aFilePattern
  735         , FileLoopModeType aOperateOnFolders, bool aDoRecurse);
  736     ResultType FileGetTime(LPTSTR aFilespec, TCHAR aWhichTime);
  737     ResultType FileSetTime(LPTSTR aYYYYMMDD, LPTSTR aFilePattern, TCHAR aWhichTime
  738         , FileLoopModeType aOperateOnFolders, bool aDoRecurse);
  739     ResultType FileGetSize(LPTSTR aFilespec, LPTSTR aGranularity);
  740     ResultType FileGetVersion(LPTSTR aFilespec);
  741 
  742     ResultType IniRead(LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey, LPTSTR aDefault);
  743     ResultType IniWrite(LPTSTR aValue, LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey);
  744     ResultType IniDelete(LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey);
  745     ResultType RegRead(HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName);
  746     ResultType RegWrite(DWORD aValueType, HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName, LPTSTR aValue);
  747     ResultType RegDelete(HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName);
  748     static LONG RegRemoveSubkeys(HKEY hRegKey);
  749 
  750     #define DESTROY_SPLASH \
  751     {\
  752         if (g_hWndSplash && IsWindow(g_hWndSplash))\
  753             DestroyWindow(g_hWndSplash);\
  754         g_hWndSplash = NULL;\
  755     }
  756     ResultType SplashTextOn(int aWidth, int aHeight, LPTSTR aTitle, LPTSTR aText);
  757     ResultType Splash(LPTSTR aOptions, LPTSTR aSubText, LPTSTR aMainText, LPTSTR aTitle, LPTSTR aFontName
  758         , LPTSTR aImageFile, bool aSplashImage);
  759 
  760     ResultType ToolTip(LPTSTR aText, LPTSTR aX, LPTSTR aY, LPTSTR aID);
  761     ResultType TrayTip(LPTSTR aTitle, LPTSTR aText, LPTSTR aTimeout, LPTSTR aOptions);
  762     ResultType Transform(LPTSTR aCmd, LPTSTR aValue1, LPTSTR aValue2);
  763     ResultType Input(); // The Input command.
  764 
  765     #define SW_NONE -1
  766     ResultType PerformShowWindow(ActionTypeType aActionType, LPTSTR aTitle = _T(""), LPTSTR aText = _T("")
  767         , LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
  768     ResultType PerformWait();
  769 
  770     ResultType WinMove(LPTSTR aTitle, LPTSTR aText, LPTSTR aX, LPTSTR aY
  771         , LPTSTR aWidth = _T(""), LPTSTR aHeight = _T(""), LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
  772     ResultType WinMenuSelectItem(LPTSTR aTitle, LPTSTR aText, LPTSTR aMenu1, LPTSTR aMenu2
  773         , LPTSTR aMenu3, LPTSTR aMenu4, LPTSTR aMenu5, LPTSTR aMenu6, LPTSTR aMenu7
  774         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  775     ResultType ControlSend(LPTSTR aControl, LPTSTR aKeysToSend, LPTSTR aTitle, LPTSTR aText
  776         , LPTSTR aExcludeTitle, LPTSTR aExcludeText, SendRawModes aSendRaw);
  777     ResultType ControlClick(vk_type aVK, int aClickCount, LPTSTR aOptions, LPTSTR aControl
  778         , LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  779     ResultType ControlMove(LPTSTR aControl, LPTSTR aX, LPTSTR aY, LPTSTR aWidth, LPTSTR aHeight
  780         , LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  781     ResultType ControlGetPos(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  782     ResultType ControlGetFocus(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  783     ResultType ControlFocus(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
  784         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  785     ResultType ControlSetText(LPTSTR aControl, LPTSTR aNewText, LPTSTR aTitle, LPTSTR aText
  786         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  787     ResultType ControlGetText(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
  788         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  789     ResultType ControlGetListView(Var &aOutputVar, HWND aHwnd, LPTSTR aOptions);
  790     ResultType Control(LPTSTR aCmd, LPTSTR aValue, LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
  791         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  792     ResultType ControlGet(LPTSTR aCommand, LPTSTR aValue, LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
  793         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  794     ResultType GuiControl(LPTSTR aCommand, LPTSTR aControlID, LPTSTR aParam3, Var *aParam3Var);
  795     ResultType GuiControlGet(LPTSTR aCommand, LPTSTR aControlID, LPTSTR aParam3);
  796     ResultType StatusBarGetText(LPTSTR aPart, LPTSTR aTitle, LPTSTR aText
  797         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  798     ResultType StatusBarWait(LPTSTR aTextToWaitFor, LPTSTR aSeconds, LPTSTR aPart, LPTSTR aTitle, LPTSTR aText
  799         , LPTSTR aInterval, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  800     ResultType ScriptPostSendMessage(bool aUseSend);
  801     ResultType ScriptProcess(LPTSTR aCmd, LPTSTR aProcess, LPTSTR aParam3);
  802     ResultType WinSet(LPTSTR aAttrib, LPTSTR aValue, LPTSTR aTitle, LPTSTR aText
  803         , LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  804     ResultType WinSetRegion(HWND aWnd, LPTSTR aPoints);
  805     ResultType WinSetTitle(LPTSTR aTitle, LPTSTR aText, LPTSTR aNewTitle
  806         , LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
  807     ResultType WinGetTitle(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  808     ResultType WinGetClass(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  809     ResultType WinGet(LPTSTR aCmd, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  810     ResultType WinGetControlList(Var &aOutputVar, HWND aTargetWindow, bool aFetchHWNDs);
  811     ResultType WinGetText(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  812     ResultType WinGetPos(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
  813     ResultType EnvGet(LPTSTR aEnvVarName);
  814     ResultType SysGet(LPTSTR aCmd, LPTSTR aValue);
  815     ResultType PixelSearch(int aLeft, int aTop, int aRight, int aBottom, COLORREF aColorBGR, int aVariation
  816         , LPTSTR aOptions, bool aIsPixelGetColor);
  817     ResultType ImageSearch(int aLeft, int aTop, int aRight, int aBottom, LPTSTR aImageFile);
  818     ResultType PixelGetColor(int aX, int aY, LPTSTR aOptions);
  819 
  820     static ResultType SetToggleState(vk_type aVK, ToggleValueType &ForceLock, LPTSTR aToggleText);
  821 
  822 public:
  823     #define SET_S_DEREF_BUF(ptr, size) Line::sDerefBuf = ptr, Line::sDerefBufSize = size
  824 
  825     #define NULLIFY_S_DEREF_BUF \
  826     {\
  827         SET_S_DEREF_BUF(NULL, 0);\
  828         if (sDerefBufSize > LARGE_DEREF_BUF_SIZE)\
  829             --sLargeDerefBufs;\
  830     }
  831 
  832     #define PRIVATIZE_S_DEREF_BUF \
  833         LPTSTR our_deref_buf = Line::sDerefBuf;\
  834         size_t our_deref_buf_size = Line::sDerefBufSize;\
  835         SET_S_DEREF_BUF(NULL, 0) // For detecting whether ExpandExpression() caused a new buffer to be created.
  836 
  837     #define DEPRIVATIZE_S_DEREF_BUF \
  838         if (our_deref_buf)\
  839         {\
  840             if (Line::sDerefBuf)\
  841             {\
  842                 free(Line::sDerefBuf);\
  843                 if (Line::sDerefBufSize > LARGE_DEREF_BUF_SIZE)\
  844                     --Line::sLargeDerefBufs;\
  845             }\
  846             SET_S_DEREF_BUF(our_deref_buf, our_deref_buf_size);\
  847         }
  848         //else the original buffer is NULL, so keep any new sDerefBuf that might have been created (should
  849         // help avg-case performance).
  850 
  851     static LPTSTR sDerefBuf;  // Buffer to hold the values of any args that need to be dereferenced.
  852     static size_t sDerefBufSize;
  853     static int sLargeDerefBufs;
  854 
  855     // Static because only one line can be Expanded at a time (not to mention the fact that we
  856     // wouldn't want the size of each line to be expanded by this size):
  857     static LPTSTR sArgDeref[MAX_ARGS];
  858     static Var *sArgVar[MAX_ARGS];
  859 
  860     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  861     // due to byte-alignment:
  862     ActionTypeType mActionType; // What type of line this is.
  863     ArgCountType mArgc; // How many arguments exist in mArg[].
  864     FileIndexType mFileIndex; // Which file the line came from.  0 is the first, and it's the main script file.
  865     LineNumberType mLineNumber;  // The line number in the file from which the script was loaded, for debugging.
  866 
  867     ArgStruct *mArg; // Will be used to hold a dynamic array of dynamic Args.
  868     AttributeType mAttribute;
  869     Line *mPrevLine, *mNextLine; // The prev & next lines adjacent to this one in the linked list; NULL if none.
  870     Line *mRelatedLine;  // e.g. the "else" that belongs to this "if"
  871     Line *mParentLine; // Indicates the parent (owner) of this line.
  872 
  873 #ifdef CONFIG_DEBUGGER
  874     Breakpoint *mBreakpoint;
  875 #endif
  876 
  877     // Probably best to always use ARG1 even if other things have supposedly verified
  878     // that it exists, since it's count-check should make the dereference of a NULL
  879     // pointer (or accessing non-existent array elements) virtually impossible.
  880     // Empty-string is probably more universally useful than NULL, since some
  881     // API calls and other functions might not appreciate receiving NULLs.  In addition,
  882     // always remembering to have to check for NULL makes things harder to maintain
  883     // and more bug-prone.  The below macros rely upon the fact that the individual
  884     // elements of mArg cannot be NULL (because they're explicitly set to be blank
  885     // when the user has omitted an arg in between two non-blank args).  Later, might
  886     // want to review if any of the API calls used expect a string whose contents are
  887     // modifiable.
  888     #define RAW_ARG1 (mArgc > 0 ? mArg[0].text : _T(""))
  889     #define RAW_ARG2 (mArgc > 1 ? mArg[1].text : _T(""))
  890     #define RAW_ARG3 (mArgc > 2 ? mArg[2].text : _T(""))
  891     #define RAW_ARG4 (mArgc > 3 ? mArg[3].text : _T(""))
  892     #define RAW_ARG5 (mArgc > 4 ? mArg[4].text : _T(""))
  893     #define RAW_ARG6 (mArgc > 5 ? mArg[5].text : _T(""))
  894     #define RAW_ARG7 (mArgc > 6 ? mArg[6].text : _T(""))
  895     #define RAW_ARG8 (mArgc > 7 ? mArg[7].text : _T(""))
  896 
  897     #define LINE_RAW_ARG1 (line->mArgc > 0 ? line->mArg[0].text : _T(""))
  898     #define LINE_RAW_ARG2 (line->mArgc > 1 ? line->mArg[1].text : _T(""))
  899     #define LINE_RAW_ARG3 (line->mArgc > 2 ? line->mArg[2].text : _T(""))
  900     #define LINE_RAW_ARG4 (line->mArgc > 3 ? line->mArg[3].text : _T(""))
  901     #define LINE_RAW_ARG5 (line->mArgc > 4 ? line->mArg[4].text : _T(""))
  902     #define LINE_RAW_ARG6 (line->mArgc > 5 ? line->mArg[5].text : _T(""))
  903     #define LINE_RAW_ARG7 (line->mArgc > 6 ? line->mArg[6].text : _T(""))
  904     #define LINE_RAW_ARG8 (line->mArgc > 7 ? line->mArg[7].text : _T(""))
  905     #define LINE_RAW_ARG9 (line->mArgc > 8 ? line->mArg[8].text : _T(""))
  906     
  907     #define NEW_RAW_ARG1 (aArgc > 0 ? new_arg[0].text : _T("")) // Helps performance to use this vs. LINE_RAW_ARG where possible.
  908     #define NEW_RAW_ARG2 (aArgc > 1 ? new_arg[1].text : _T(""))
  909     #define NEW_RAW_ARG3 (aArgc > 2 ? new_arg[2].text : _T(""))
  910     #define NEW_RAW_ARG4 (aArgc > 3 ? new_arg[3].text : _T(""))
  911     #define NEW_RAW_ARG5 (aArgc > 4 ? new_arg[4].text : _T(""))
  912     #define NEW_RAW_ARG6 (aArgc > 5 ? new_arg[5].text : _T(""))
  913     #define NEW_RAW_ARG7 (aArgc > 6 ? new_arg[6].text : _T(""))
  914     #define NEW_RAW_ARG8 (aArgc > 7 ? new_arg[7].text : _T(""))
  915     #define NEW_RAW_ARG9 (aArgc > 8 ? new_arg[8].text : _T(""))
  916     
  917     #define SAVED_ARG1 (mArgc > 0 ? arg[0] : _T(""))
  918     #define SAVED_ARG2 (mArgc > 1 ? arg[1] : _T(""))
  919     #define SAVED_ARG3 (mArgc > 2 ? arg[2] : _T(""))
  920     #define SAVED_ARG4 (mArgc > 3 ? arg[3] : _T(""))
  921     #define SAVED_ARG5 (mArgc > 4 ? arg[4] : _T(""))
  922 
  923     // For the below, it is the caller's responsibility to ensure that mArgc is
  924     // large enough (either via load-time validation or a runtime check of mArgc).
  925     // This is because for performance reasons, the sArgVar entry for omitted args isn't
  926     // initialized, so may have an old/obsolete value from some previous command.
  927     #define OUTPUT_VAR (*sArgVar) // ExpandArgs() has ensured this first ArgVar is always initialized, so there's never any need to check mArgc > 0.
  928     #define ARGVARRAW1 (*sArgVar)   // i.e. sArgVar[0], and same as OUTPUT_VAR (it's a duplicate to help readability).
  929     #define ARGVARRAW2 (sArgVar[1]) // It's called RAW because its user is responsible for ensuring the arg
  930     #define ARGVARRAW3 (sArgVar[2]) // exists by checking mArgc at loadtime or runtime.
  931     #define ARGVAR1 ARGVARRAW1 // This first one doesn't need the check below because ExpandArgs() has ensured it's initialized.
  932     #define ARGVAR2 (mArgc > 1 ? sArgVar[1] : NULL) // Caller relies on the check of mArgc because for performance,
  933     #define ARGVAR3 (mArgc > 2 ? sArgVar[2] : NULL) // sArgVar[] isn't initialized for parameters the script
  934     #define ARGVAR4 (mArgc > 3 ? sArgVar[3] : NULL) // omitted entirely from the end of the parameter list.
  935     #define ARGVAR5 (mArgc > 4 ? sArgVar[4] : NULL)
  936     #define ARGVAR6 (mArgc > 5 ? sArgVar[5] : NULL)
  937     #define ARGVAR7 (mArgc > 6 ? sArgVar[6] : NULL)
  938     #define ARGVAR8 (mArgc > 7 ? sArgVar[7] : NULL)
  939 
  940     #define ARG1 sArgDeref[0] // These are the expanded/resolved parameters for the currently-executing command.
  941     #define ARG2 sArgDeref[1] // They're populated by ExpandArgs().
  942     #define ARG3 sArgDeref[2]
  943     #define ARG4 sArgDeref[3]
  944     #define ARG5 sArgDeref[4]
  945     #define ARG6 sArgDeref[5]
  946     #define ARG7 sArgDeref[6]
  947     #define ARG8 sArgDeref[7]
  948     #define ARG9 sArgDeref[8]
  949     #define ARG10 sArgDeref[9]
  950     #define ARG11 sArgDeref[10]
  951 
  952     #define TWO_ARGS    ARG1, ARG2
  953     #define THREE_ARGS  ARG1, ARG2, ARG3
  954     #define FOUR_ARGS   ARG1, ARG2, ARG3, ARG4
  955     #define FIVE_ARGS   ARG1, ARG2, ARG3, ARG4, ARG5
  956     #define SIX_ARGS    ARG1, ARG2, ARG3, ARG4, ARG5, ARG6
  957     #define SEVEN_ARGS  ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7
  958     #define EIGHT_ARGS  ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8
  959     #define NINE_ARGS   ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9
  960     #define TEN_ARGS    ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10
  961     #define ELEVEN_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10, ARG11
  962 
  963     // If the arg's text is non-blank, it means the variable is a dynamic name such as array%i%
  964     // that must be resolved at runtime rather than load-time.  Therefore, this macro must not
  965     // be used without first having checked that arg.text is blank:
  966     #define VAR(arg) ((Var *)arg.deref)
  967     // Uses arg number (i.e. the first arg is 1, not 0).  Caller must ensure that ArgNum >= 1 and that
  968     // the arg in question is an input or output variable (since that isn't checked there).
  969     //#define ARG_HAS_VAR(ArgNum) (mArgc >= ArgNum && (*mArg[ArgNum-1].text || mArg[ArgNum-1].deref))
  970 
  971     // Shouldn't go much higher than 400 since the main window's Edit control is currently limited
  972     // to 64KB to be compatible with the Win9x limit.  Avg. line length is probably under 100 for
  973     // the vast majority of scripts, so 400 seems unlikely to exceed the buffer size.  Even in the
  974     // worst case where the buffer size is exceeded, the text is simply truncated, so it's not too bad:
  975     #define LINE_LOG_SIZE 400  // See above.
  976     static Line *sLog[LINE_LOG_SIZE];
  977     static DWORD sLogTick[LINE_LOG_SIZE];
  978     static int sLogNext;
  979 
  980 #ifdef AUTOHOTKEYSC  // Reduces code size to omit things that are unused, and helps catch bugs at compile-time.
  981     static LPTSTR sSourceFile[1]; // Only need to be able to hold the main script since compiled scripts don't support dynamic including.
  982 #else
  983     static LPTSTR *sSourceFile;   // Will hold an array of strings.
  984     static int sMaxSourceFiles;  // Maximum number of items it can currently hold.
  985 #endif
  986     static int sSourceFileCount; // Number of items in the above array.
  987 
  988     static void FreeDerefBufIfLarge();
  989 
  990     ResultType ExecUntil(ExecUntilMode aMode, ExprTokenType *apReturnValue = NULL, Line **apJumpToLine = NULL);
  991 
  992     // The following are characters that can't legally occur after an AND or OR.  It excludes all unary operators
  993     // "!~*&-+" as well as the parentheses chars "()":
  994     #define EXPR_CORE _T("<>=/|^,:")
  995     // The characters common to both EXPR_TELLTALES and EXPR_OPERAND_TERMINATORS:
  996     #define EXPR_COMMON _T(" \t") EXPR_CORE _T("*&~!()[]{}")  // Space and Tab are included at the beginning for performance.  L31: Added [] for array-like syntax.
  997     #define CONTINUATION_LINE_SYMBOLS EXPR_CORE _T(".+-*&!?~") // v1.0.46.
  998     // Characters whose presence in a mandatory-numeric param make it an expression for certain.
  999     // + and - are not included here because legacy numeric parameters can contain unary plus or minus,
 1000     // e.g. WinMove, -%x%, -%y%:
 1001     #define EXPR_TELLTALES EXPR_COMMON _T("\"")
 1002     // Characters that mark the end of an operand inside an expression.  Double-quote must not be included:
 1003     #define EXPR_OPERAND_TERMINATORS_EX_DOT EXPR_COMMON _T("+-?") // L31: Used in a few places where '.' needs special treatment.
 1004     #define EXPR_OPERAND_TERMINATORS EXPR_OPERAND_TERMINATORS_EX_DOT _T(".") // L31: Used in expressions where '.' is always an operator.
 1005     #define EXPR_ALL_SYMBOLS EXPR_OPERAND_TERMINATORS _T("\"")
 1006     #define EXPR_ILLEGAL_CHARS _T("'\\;`") // Characters illegal in an expression.
 1007     // The following HOTSTRING option recognizer is kept somewhat forgiving/non-specific for backward compatibility
 1008     // (e.g. scripts may have some invalid hotstring options, which are simply ignored).  This definition is here
 1009     // because it's related to continuation line symbols. Also, avoid ever adding "&" to hotstring options because
 1010     // it might introduce ambiguity in the differentiation of things like:
 1011     //    : & x::hotkey action
 1012     //    : & *::abbrev with leading colon::
 1013     #define IS_HOTSTRING_OPTION(chr) (cisalnum(chr) || _tcschr(_T("?*- \t"), chr))
 1014     // The characters below are ordered with most-often used ones first, for performance:
 1015     #define DEFINE_END_FLAGS \
 1016         TCHAR end_flags[] = {' ', g_delimiter, '(', '\t', '<', '>', ':', '=', '+', '-', '*', '/', '!', '~', '&', '|', '^', '[', '.', '?', '{', '\0'}; // '\0' must be last.
 1017         // L31: Added '[' for standalone ObjSet/Get to work as ACT_EXPRESSION.  "Get" is allowed for simplicity and for future use with functions-as-values (e.g. varContainingFunc[]).
 1018         // L34: Added '.' and changed dot handling to fix x.=y, improve support in other areas, catch more errors and give slightly better error messages.
 1019         // v1.1.22.01: Added '{' to simplify OTB handling for else/try/finally.
 1020 
 1021     #define ArgLength(aArgNum) ArgIndexLength((aArgNum)-1)
 1022     #define ArgToDouble(aArgNum) ArgIndexToDouble((aArgNum)-1)
 1023     #define ArgToInt64(aArgNum) ArgIndexToInt64((aArgNum)-1)
 1024     #define ArgToInt(aArgNum) (int)ArgToInt64(aArgNum) // Benchmarks show that having a "real" ArgToInt() that calls ATOI vs. ATOI64 (and ToInt() vs. ToInt64()) doesn't measurably improve performance.
 1025     #define ArgToUInt(aArgNum) (UINT)ArgToInt64(aArgNum) // Similar to what ATOU() does.
 1026     __int64 ArgIndexToInt64(int aArgIndex);
 1027     double ArgIndexToDouble(int aArgIndex);
 1028     size_t ArgIndexLength(int aArgIndex);
 1029 
 1030     Var *ResolveVarOfArg(int aArgIndex, bool aCreateIfNecessary = true);
 1031     ResultType ExpandArgs(ExprTokenType *aResultToken = NULL, VarSizeType aSpaceNeeded = VARSIZE_ERROR, Var *aArgVar[] = NULL);
 1032     VarSizeType GetExpandedArgSize(Var *aArgVar[]);
 1033     LPTSTR ExpandArg(LPTSTR aBuf, int aArgIndex, Var *aArgVar = NULL);
 1034     LPTSTR ExpandExpression(int aArgIndex, ResultType &aResult, ExprTokenType *aResultToken
 1035         , LPTSTR &aTarget, LPTSTR &aDerefBuf, size_t &aDerefBufSize, LPTSTR aArgDeref[], size_t aExtraSize);
 1036     ResultType ExpandSingleArg(int aArgIndex, ExprTokenType &aResultToken, LPTSTR &aDerefBuf, size_t &aDerefBufSize);
 1037     ResultType ExpressionToPostfix(ArgStruct &aArg);
 1038     ResultType EvaluateHotCriterionExpression(); // Called by HotkeyCriterion::Eval().
 1039 
 1040     ResultType Deref(Var *aOutputVar, LPTSTR aBuf);
 1041 
 1042     static bool FileIsFilteredOut(LoopFilesStruct &aCurrentFile, FileLoopModeType aFileLoopMode);
 1043 
 1044     Label *GetJumpTarget(bool aIsDereferenced);
 1045     Label *IsJumpValid(Label &aTargetLabel, bool aSilent = false);
 1046     BOOL IsOutsideAnyFunctionBody();
 1047     BOOL CheckValidFinallyJump(Line* jumpTarget);
 1048 
 1049     HWND DetermineTargetWindow(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
 1050 
 1051     
 1052     // This is in the .h file so that it's more likely the compiler's cost/benefit estimate will
 1053     // make it inline (since it is called from only one place).  Inline would be good since it
 1054     // is called frequently during script loading and is difficult to macro-ize in a way that
 1055     // retains readability.
 1056     static ArgTypeType ArgIsVar(ActionTypeType aActionType, int aArgIndex)
 1057     {
 1058         switch(aArgIndex)
 1059         {
 1060         case 0:  // Arg #1
 1061             switch(aActionType)
 1062             {
 1063             case ACT_ASSIGN:
 1064             case ACT_ASSIGNEXPR:
 1065             case ACT_ADD:
 1066             case ACT_SUB:
 1067             case ACT_MULT:
 1068             case ACT_DIV:
 1069             case ACT_TRANSFORM:
 1070             case ACT_STRINGLEFT:
 1071             case ACT_STRINGRIGHT:
 1072             case ACT_STRINGMID:
 1073             case ACT_STRINGTRIMLEFT:
 1074             case ACT_STRINGTRIMRIGHT:
 1075             case ACT_STRINGLOWER:
 1076             case ACT_STRINGUPPER:
 1077             case ACT_STRINGLEN:
 1078             case ACT_STRINGREPLACE:
 1079             case ACT_STRINGGETPOS:
 1080             case ACT_GETKEYSTATE:
 1081             case ACT_CONTROLGETFOCUS:
 1082             case ACT_CONTROLGETTEXT:
 1083             case ACT_CONTROLGET:
 1084             case ACT_GUICONTROLGET:
 1085             case ACT_STATUSBARGETTEXT:
 1086             case ACT_INPUTBOX:
 1087             case ACT_RANDOM:
 1088             case ACT_INIREAD:
 1089             case ACT_REGREAD:
 1090             case ACT_DRIVESPACEFREE:
 1091             case ACT_DRIVEGET:
 1092             case ACT_SOUNDGET:
 1093             case ACT_SOUNDGETWAVEVOLUME:
 1094             case ACT_FILEREAD:
 1095             case ACT_FILEREADLINE:
 1096             case ACT_FILEGETATTRIB:
 1097             case ACT_FILEGETTIME:
 1098             case ACT_FILEGETSIZE:
 1099             case ACT_FILEGETVERSION:
 1100             case ACT_FILESELECTFILE:
 1101             case ACT_FILESELECTFOLDER:
 1102             case ACT_MOUSEGETPOS:
 1103             case ACT_WINGETTITLE:
 1104             case ACT_WINGETCLASS:
 1105             case ACT_WINGET:
 1106             case ACT_WINGETTEXT:
 1107             case ACT_WINGETPOS:
 1108             case ACT_SYSGET:
 1109             case ACT_ENVGET:
 1110             case ACT_CONTROLGETPOS:
 1111             case ACT_PIXELGETCOLOR:
 1112             case ACT_PIXELSEARCH:
 1113             case ACT_IMAGESEARCH:
 1114             case ACT_INPUT:
 1115             case ACT_FORMATTIME:
 1116             case ACT_FOR:
 1117             case ACT_CATCH:
 1118                 return ARG_TYPE_OUTPUT_VAR;
 1119 
 1120             case ACT_SORT:
 1121             case ACT_SPLITPATH:
 1122             case ACT_IFINSTRING:
 1123             case ACT_IFNOTINSTRING:
 1124             case ACT_IFEQUAL:
 1125             case ACT_IFNOTEQUAL:
 1126             case ACT_IFGREATER:
 1127             case ACT_IFGREATEROREQUAL:
 1128             case ACT_IFLESS:
 1129             case ACT_IFLESSOREQUAL:
 1130             case ACT_IFBETWEEN:
 1131             case ACT_IFNOTBETWEEN:
 1132             case ACT_IFIN:
 1133             case ACT_IFNOTIN:
 1134             case ACT_IFCONTAINS:
 1135             case ACT_IFNOTCONTAINS:
 1136             case ACT_IFIS:
 1137             case ACT_IFISNOT:
 1138                 return ARG_TYPE_INPUT_VAR;
 1139             }
 1140             break;
 1141 
 1142         case 1:  // Arg #2
 1143             switch(aActionType)
 1144             {
 1145             case ACT_STRINGLEFT:
 1146             case ACT_STRINGRIGHT:
 1147             case ACT_STRINGMID:
 1148             case ACT_STRINGTRIMLEFT:
 1149             case ACT_STRINGTRIMRIGHT:
 1150             case ACT_STRINGLOWER:
 1151             case ACT_STRINGUPPER:
 1152             case ACT_STRINGLEN:
 1153             case ACT_STRINGREPLACE:
 1154             case ACT_STRINGGETPOS:
 1155             case ACT_STRINGSPLIT:
 1156                 return ARG_TYPE_INPUT_VAR;
 1157 
 1158             case ACT_MOUSEGETPOS:
 1159             case ACT_WINGETPOS:
 1160             case ACT_CONTROLGETPOS:
 1161             case ACT_PIXELSEARCH:
 1162             case ACT_IMAGESEARCH:
 1163             case ACT_SPLITPATH:
 1164             case ACT_FILEGETSHORTCUT:
 1165             case ACT_FOR:
 1166                 return ARG_TYPE_OUTPUT_VAR;
 1167             }
 1168             break;
 1169 
 1170         case 2:  // Arg #3
 1171             switch(aActionType)
 1172             {
 1173             case ACT_WINGETPOS:
 1174             case ACT_CONTROLGETPOS:
 1175             case ACT_MOUSEGETPOS:
 1176             case ACT_SPLITPATH:
 1177             case ACT_FILEGETSHORTCUT:
 1178                 return ARG_TYPE_OUTPUT_VAR;
 1179             }
 1180             break;
 1181 
 1182         case 3:  // Arg #4
 1183             switch(aActionType)
 1184             {
 1185             case ACT_WINGETPOS:
 1186             case ACT_CONTROLGETPOS:
 1187             case ACT_MOUSEGETPOS:
 1188             case ACT_SPLITPATH:
 1189             case ACT_FILEGETSHORTCUT:
 1190             case ACT_RUN:
 1191             case ACT_RUNWAIT:
 1192                 return ARG_TYPE_OUTPUT_VAR;
 1193             }
 1194             break;
 1195 
 1196         case 4:  // Arg #5
 1197         case 5:  // Arg #6
 1198             if (aActionType == ACT_SPLITPATH || aActionType == ACT_FILEGETSHORTCUT)
 1199                 return ARG_TYPE_OUTPUT_VAR;
 1200             break;
 1201 
 1202         case 6:  // Arg #7
 1203         case 7:  // Arg #8
 1204             if (aActionType == ACT_FILEGETSHORTCUT)
 1205                 return ARG_TYPE_OUTPUT_VAR;
 1206         }
 1207         // Otherwise:
 1208         return ARG_TYPE_NORMAL;
 1209     }
 1210 
 1211 
 1212 
 1213     ResultType ArgMustBeDereferenced(Var *aVar, int aArgIndex, Var *aArgVar[]);
 1214 
 1215     #define ArgHasDeref(aArgNum) ArgIndexHasDeref((aArgNum)-1)
 1216     bool ArgIndexHasDeref(int aArgIndex)
 1217     // This function should always be called in lieu of doing something like "strchr(arg.text, g_DerefChar)"
 1218     // because that method is unreliable due to the possible presence of literal (escaped) g_DerefChars
 1219     // in the text.
 1220     // Caller must ensure that aArgIndex is 0 or greater.
 1221     {
 1222 #ifdef _DEBUG
 1223         if (aArgIndex < 0)
 1224         {
 1225             LineError(_T("DEBUG: BAD"), WARN);
 1226             aArgIndex = 0;  // But let it continue.
 1227         }
 1228 #endif
 1229         if (aArgIndex >= mArgc) // Arg doesn't exist.
 1230             return false;
 1231         ArgStruct &arg = mArg[aArgIndex]; // For performance.
 1232         // Return false if it's not of a type caller wants deemed to have derefs.
 1233         if (arg.type == ARG_TYPE_NORMAL)
 1234             return arg.deref && arg.deref[0].marker // Relies on short-circuit boolean evaluation order to prevent NULL-deref.
 1235                 || arg.is_expression; // Return true for this case since most callers assume the arg is a simple literal string if we return false.
 1236         else // Callers rely on input variables being seen as "true" because sometimes single isolated derefs are converted into ARG_TYPE_INPUT_VAR at load-time.
 1237             return (arg.type == ARG_TYPE_INPUT_VAR);
 1238     }
 1239 
 1240     static HKEY RegConvertRootKey(LPTSTR aBuf, bool *aIsRemoteRegistry = NULL)
 1241     {
 1242         // Even if the computer name is a single letter, it seems like using a colon as delimiter is ok
 1243         // (e.g. a:HKEY_LOCAL_MACHINE), since we wouldn't expect the root key to be used as a filename
 1244         // in that exact way, i.e. a drive letter should be followed by a backslash 99% of the time in
 1245         // this context.
 1246         // Research indicates that colon is an illegal char in a computer name (at least for NT,
 1247         // and by extension probably all other OSes).  So it should be safe to use it as a delimiter
 1248         // for the remote registry feature.  But just in case, get the right-most one,
 1249         // e.g. Computer:01:HKEY_LOCAL_MACHINE  ; the first colon is probably illegal on all OSes.
 1250         // Additional notes from the Internet:
 1251         // "A Windows NT computer name can be up to 15 alphanumeric characters with no blank spaces
 1252         // and must be unique on the network. It can contain the following special characters:
 1253         // ! @ # $ % ^ & ( ) -   ' { } .
 1254         // It may not contain:
 1255         // \ * + = | : ; " ? ,
 1256         // The following is a list of illegal characters in a computer name:
 1257         // regEx.Pattern = "`|~|!|@|#|\$|\^|\&|\*|\(|\)|\=|\+|{|}|\\|;|:|'|<|>|/|\?|\||%"
 1258         return RegConvertKey(aBuf, REG_OLD_SYNTAX, NULL, aIsRemoteRegistry);
 1259     }
 1260     static HKEY RegConvertKey(LPTSTR aBuf, RegSyntax aSyntax, LPTSTR *aSubkey = NULL, bool *aIsRemoteRegistry = NULL)
 1261     {
 1262         const size_t COMPUTER_NAME_BUF_SIZE = 128;
 1263 
 1264         LPTSTR key_name_pos = aBuf, computer_name_end = NULL;
 1265 
 1266         // Check for a computer name, as in \\ComputerName\HKLM or \\ComputerName:HKLM.
 1267         if (*aBuf == '\\' && aBuf[1] == '\\')
 1268         {
 1269             LPTSTR delim
 1270                 = aSyntax == REG_NEW_SYNTAX ? _T("\\")
 1271                 : aSyntax == REG_OLD_SYNTAX ? _T(":")
 1272                 : _T("\\:"); // REG_EITHER_SYNTAX
 1273             if (  !(computer_name_end = StrChrAny(aBuf + 2, delim))
 1274                 || (computer_name_end - aBuf) >= COMPUTER_NAME_BUF_SIZE  )
 1275                 return NULL;
 1276             key_name_pos = computer_name_end + 1;
 1277             if (*computer_name_end == ':') // For backward-compatibility:
 1278                 key_name_pos = omit_leading_whitespace(key_name_pos);
 1279         }
 1280 
 1281         // Copy root key name into temporary buffer for use by _tcsicmp().
 1282         TCHAR key_name[20];
 1283         int i;
 1284         for (i = 0; key_name_pos[i] && key_name_pos[i] != '\\'; ++i)
 1285         {
 1286             if (i == 19)
 1287                 return NULL; // Too long to be valid.
 1288             key_name[i] = key_name_pos[i];
 1289         }
 1290         key_name[i] = '\0';
 1291 
 1292         if (key_name_pos[i] && aSyntax == REG_OLD_SYNTAX) // There's a \SubKey, but caller wasn't expecting one.
 1293             return NULL;
 1294 
 1295         // Set output parameters for caller.
 1296         if (aSubkey)
 1297         {
 1298             if (key_name_pos[i] != '\\') // No subkey (not even a blank one).
 1299                 *aSubkey = (aSyntax == REG_NEW_SYNTAX) ? _T("") : NULL; // In REG_EITHER_SYNTAX mode, caller wants to know it was omitted.
 1300             else
 1301                 *aSubkey = key_name_pos + i + 1; // +1 for the slash.
 1302         }
 1303         if (aIsRemoteRegistry)
 1304             *aIsRemoteRegistry = (computer_name_end != NULL);
 1305 
 1306         HKEY root_key = RegConvertRootKeyType(key_name);
 1307         if (!root_key) // Invalid or unsupported root key name.
 1308             return NULL;
 1309 
 1310         if (!aIsRemoteRegistry || !computer_name_end) // Either caller didn't want it opened, or it doesn't need to be.
 1311             return root_key; // If it's a remote key, this value should only be used by the caller as an indicator.
 1312         // Otherwise, it's a remote computer whose registry the caller wants us to open:
 1313         // It seems best to require the two leading backslashes in case the computer name contains
 1314         // spaces (just in case spaces are allowed on some OSes or perhaps for Unix interoperability, etc.).
 1315         // Therefore, make no attempt to trim leading and trailing spaces from the computer name:
 1316         TCHAR computer_name[COMPUTER_NAME_BUF_SIZE];
 1317         tcslcpy(computer_name, aBuf, _countof(computer_name));
 1318         computer_name[computer_name_end - aBuf] = '\0';
 1319         HKEY remote_key;
 1320         return (RegConnectRegistry(computer_name, root_key, &remote_key) == ERROR_SUCCESS) ? remote_key : NULL;
 1321     }
 1322 
 1323     static HKEY RegConvertRootKeyType(LPTSTR aName);
 1324     static LPTSTR RegConvertRootKeyType(HKEY aKey);
 1325 
 1326     static int RegConvertValueType(LPTSTR aValueType)
 1327     {
 1328         if (!_tcsicmp(aValueType, _T("REG_SZ"))) return REG_SZ;
 1329         if (!_tcsicmp(aValueType, _T("REG_EXPAND_SZ"))) return REG_EXPAND_SZ;
 1330         if (!_tcsicmp(aValueType, _T("REG_MULTI_SZ"))) return REG_MULTI_SZ;
 1331         if (!_tcsicmp(aValueType, _T("REG_DWORD"))) return REG_DWORD;
 1332         if (!_tcsicmp(aValueType, _T("REG_BINARY"))) return REG_BINARY;
 1333         return REG_NONE; // Unknown or unsupported type.
 1334     }
 1335     static LPTSTR RegConvertValueType(DWORD aValueType)
 1336     {
 1337         switch(aValueType)
 1338         {
 1339         case REG_SZ: return _T("REG_SZ");
 1340         case REG_EXPAND_SZ: return _T("REG_EXPAND_SZ");
 1341         case REG_BINARY: return _T("REG_BINARY");
 1342         case REG_DWORD: return _T("REG_DWORD");
 1343         case REG_DWORD_BIG_ENDIAN: return _T("REG_DWORD_BIG_ENDIAN");
 1344         case REG_LINK: return _T("REG_LINK");
 1345         case REG_MULTI_SZ: return _T("REG_MULTI_SZ");
 1346         case REG_RESOURCE_LIST: return _T("REG_RESOURCE_LIST");
 1347         case REG_FULL_RESOURCE_DESCRIPTOR: return _T("REG_FULL_RESOURCE_DESCRIPTOR");
 1348         case REG_RESOURCE_REQUIREMENTS_LIST: return _T("REG_RESOURCE_REQUIREMENTS_LIST");
 1349         case REG_QWORD: return _T("REG_QWORD");
 1350         case REG_SUBKEY: return _T("KEY");  // Custom (non-standard) type.
 1351         default: return _T("");  // Make it be the empty string for REG_NONE and anything else.
 1352         }
 1353     }
 1354     static DWORD RegConvertView(LPTSTR aBuf)
 1355     {
 1356         if (!_tcsicmp(aBuf, _T("Default")))
 1357             return 0;
 1358         else if (!_tcscmp(aBuf, _T("32")))
 1359             return KEY_WOW64_32KEY;
 1360         else if (!_tcscmp(aBuf, _T("64")))
 1361             return KEY_WOW64_64KEY;
 1362         else
 1363             return -1;
 1364     }
 1365 
 1366     static DWORD SoundConvertComponentType(LPTSTR aBuf, int *aInstanceNumber = NULL)
 1367     {
 1368         LPTSTR colon_pos = _tcschr(aBuf, ':');
 1369         size_t length_to_check = colon_pos ? colon_pos - aBuf : _tcslen(aBuf);
 1370         if (aInstanceNumber) // Caller wanted the below put into the output parameter.
 1371         {
 1372             if (colon_pos)
 1373             {
 1374                 *aInstanceNumber = ATOI(colon_pos + 1);
 1375                 if (*aInstanceNumber < 1)
 1376                     *aInstanceNumber = 1;
 1377             }
 1378             else
 1379                 *aInstanceNumber = 1;
 1380         }
 1381         if (!tcslicmp(aBuf, _T("Master"), length_to_check)
 1382             || !tcslicmp(aBuf, _T("Speakers"), length_to_check))   return MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
 1383         if (!tcslicmp(aBuf, _T("Headphones"), length_to_check))    return MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
 1384         if (!tcslicmp(aBuf, _T("Digital"), length_to_check))       return MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
 1385         if (!tcslicmp(aBuf, _T("Line"), length_to_check))          return MIXERLINE_COMPONENTTYPE_SRC_LINE;
 1386         if (!tcslicmp(aBuf, _T("Microphone"), length_to_check))    return MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
 1387         if (!tcslicmp(aBuf, _T("Synth"), length_to_check))         return MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
 1388         if (!tcslicmp(aBuf, _T("CD"), length_to_check))            return MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
 1389         if (!tcslicmp(aBuf, _T("Telephone"), length_to_check))     return MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
 1390         if (!tcslicmp(aBuf, _T("PCSpeaker"), length_to_check))     return MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER;
 1391         if (!tcslicmp(aBuf, _T("Wave"), length_to_check))          return MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
 1392         if (!tcslicmp(aBuf, _T("Aux"), length_to_check))           return MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
 1393         if (!tcslicmp(aBuf, _T("Analog"), length_to_check))        return MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
 1394         // v1.0.37.06: The following was added because it's legitimate on some sound cards such as
 1395         // SB Audigy's recording (dest #2) Wave/Mp3 volume:
 1396         if (!tcslicmp(aBuf, _T("N/A"), length_to_check))           return MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED; // 0x1000
 1397         return MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; // Zero.
 1398     }
 1399     static DWORD SoundConvertControlType(LPTSTR aBuf)
 1400     {
 1401         // v1.0.37.06: The following was added to allow unnamed control types (if any) to be accessed via number:
 1402         if (IsPureNumeric(aBuf, false, false, true)) // Seems best to allowing floating point here, since .000 on the end might happen sometimes.
 1403             return ATOU(aBuf);
 1404         // The following are the types that seem to correspond to actual sound attributes.  Some of the
 1405         // values are not included here, such as MIXERCONTROL_CONTROLTYPE_FADER, which seems to be a type
 1406         // of sound control rather than a quality of the sound itself.  For performance, put the most
 1407         // often used ones up top.
 1408         if (!_tcsicmp(aBuf, _T("Vol"))
 1409             || !_tcsicmp(aBuf, _T("Volume"))) return MIXERCONTROL_CONTROLTYPE_VOLUME;
 1410         if (!_tcsicmp(aBuf, _T("OnOff")))     return MIXERCONTROL_CONTROLTYPE_ONOFF;
 1411         if (!_tcsicmp(aBuf, _T("Mute")))      return MIXERCONTROL_CONTROLTYPE_MUTE;
 1412         if (!_tcsicmp(aBuf, _T("Mono")))      return MIXERCONTROL_CONTROLTYPE_MONO;
 1413         if (!_tcsicmp(aBuf, _T("Loudness")))  return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
 1414         if (!_tcsicmp(aBuf, _T("StereoEnh"))) return MIXERCONTROL_CONTROLTYPE_STEREOENH;
 1415         if (!_tcsicmp(aBuf, _T("BassBoost"))) return MIXERCONTROL_CONTROLTYPE_BASS_BOOST;
 1416         if (!_tcsicmp(aBuf, _T("Pan")))       return MIXERCONTROL_CONTROLTYPE_PAN;
 1417         if (!_tcsicmp(aBuf, _T("QSoundPan"))) return MIXERCONTROL_CONTROLTYPE_QSOUNDPAN;
 1418         if (!_tcsicmp(aBuf, _T("Bass")))      return MIXERCONTROL_CONTROLTYPE_BASS;
 1419         if (!_tcsicmp(aBuf, _T("Treble")))    return MIXERCONTROL_CONTROLTYPE_TREBLE;
 1420         if (!_tcsicmp(aBuf, _T("Equalizer"))) return MIXERCONTROL_CONTROLTYPE_EQUALIZER;
 1421         #define MIXERCONTROL_CONTROLTYPE_INVALID 0xFFFFFFFF // 0 might be a valid type, so use something definitely undefined.
 1422         return MIXERCONTROL_CONTROLTYPE_INVALID;
 1423     }
 1424 
 1425     static TitleMatchModes ConvertTitleMatchMode(LPTSTR aBuf)
 1426     {
 1427         if (!aBuf || !*aBuf) return MATCHMODE_INVALID;
 1428         if (*aBuf == '1' && !*(aBuf + 1)) return FIND_IN_LEADING_PART;
 1429         if (*aBuf == '2' && !*(aBuf + 1)) return FIND_ANYWHERE;
 1430         if (*aBuf == '3' && !*(aBuf + 1)) return FIND_EXACT;
 1431         if (!_tcsicmp(aBuf, _T("RegEx"))) return FIND_REGEX; // Goes with the above, not fast/slow below.
 1432 
 1433         if (!_tcsicmp(aBuf, _T("FAST"))) return FIND_FAST;
 1434         if (!_tcsicmp(aBuf, _T("SLOW"))) return FIND_SLOW;
 1435         return MATCHMODE_INVALID;
 1436     }
 1437 
 1438     static SysGetCmds ConvertSysGetCmd(LPTSTR aBuf)
 1439     {
 1440         if (!aBuf || !*aBuf) return SYSGET_CMD_INVALID;
 1441         if (IsPureNumeric(aBuf)) return SYSGET_CMD_METRICS;
 1442         if (!_tcsicmp(aBuf, _T("MonitorCount"))) return SYSGET_CMD_MONITORCOUNT;
 1443         if (!_tcsicmp(aBuf, _T("MonitorPrimary"))) return SYSGET_CMD_MONITORPRIMARY;
 1444         if (!_tcsicmp(aBuf, _T("Monitor"))) return SYSGET_CMD_MONITORAREA; // Called "Monitor" vs. "MonitorArea" to make it easier to remember.
 1445         if (!_tcsicmp(aBuf, _T("MonitorWorkArea"))) return SYSGET_CMD_MONITORWORKAREA;
 1446         if (!_tcsicmp(aBuf, _T("MonitorName"))) return SYSGET_CMD_MONITORNAME;
 1447         return SYSGET_CMD_INVALID;
 1448     }
 1449 
 1450     static TransformCmds ConvertTransformCmd(LPTSTR aBuf)
 1451     {
 1452         if (!aBuf || !*aBuf) return TRANS_CMD_INVALID;
 1453         if (!_tcsicmp(aBuf, _T("Asc"))) return TRANS_CMD_ASC;
 1454         if (!_tcsicmp(aBuf, _T("Chr"))) return TRANS_CMD_CHR;
 1455         if (!_tcsicmp(aBuf, _T("Deref"))) return TRANS_CMD_DEREF;
 1456 #ifndef UNICODE
 1457         if (!_tcsicmp(aBuf, _T("Unicode"))) return TRANS_CMD_UNICODE;
 1458 #endif
 1459         if (!_tcsicmp(aBuf, _T("HTML"))) return TRANS_CMD_HTML;
 1460         if (!_tcsicmp(aBuf, _T("Mod"))) return TRANS_CMD_MOD;
 1461         if (!_tcsicmp(aBuf, _T("Pow"))) return TRANS_CMD_POW;
 1462         if (!_tcsicmp(aBuf, _T("Exp"))) return TRANS_CMD_EXP;
 1463         if (!_tcsicmp(aBuf, _T("Sqrt"))) return TRANS_CMD_SQRT;
 1464         if (!_tcsicmp(aBuf, _T("Log"))) return TRANS_CMD_LOG;
 1465         if (!_tcsicmp(aBuf, _T("Ln"))) return TRANS_CMD_LN;  // Natural log.
 1466         if (!_tcsicmp(aBuf, _T("Round"))) return TRANS_CMD_ROUND;
 1467         if (!_tcsicmp(aBuf, _T("Ceil"))) return TRANS_CMD_CEIL;
 1468         if (!_tcsicmp(aBuf, _T("Floor"))) return TRANS_CMD_FLOOR;
 1469         if (!_tcsicmp(aBuf, _T("Abs"))) return TRANS_CMD_ABS;
 1470         if (!_tcsicmp(aBuf, _T("Sin"))) return TRANS_CMD_SIN;
 1471         if (!_tcsicmp(aBuf, _T("Cos"))) return TRANS_CMD_COS;
 1472         if (!_tcsicmp(aBuf, _T("Tan"))) return TRANS_CMD_TAN;
 1473         if (!_tcsicmp(aBuf, _T("ASin"))) return TRANS_CMD_ASIN;
 1474         if (!_tcsicmp(aBuf, _T("ACos"))) return TRANS_CMD_ACOS;
 1475         if (!_tcsicmp(aBuf, _T("ATan"))) return TRANS_CMD_ATAN;
 1476         if (!_tcsicmp(aBuf, _T("BitAnd"))) return TRANS_CMD_BITAND;
 1477         if (!_tcsicmp(aBuf, _T("BitOr"))) return TRANS_CMD_BITOR;
 1478         if (!_tcsicmp(aBuf, _T("BitXOr"))) return TRANS_CMD_BITXOR;
 1479         if (!_tcsicmp(aBuf, _T("BitNot"))) return TRANS_CMD_BITNOT;
 1480         if (!_tcsicmp(aBuf, _T("BitShiftLeft"))) return TRANS_CMD_BITSHIFTLEFT;
 1481         if (!_tcsicmp(aBuf, _T("BitShiftRight"))) return TRANS_CMD_BITSHIFTRIGHT;
 1482         return TRANS_CMD_INVALID;
 1483     }
 1484 
 1485     static MenuCommands ConvertMenuCommand(LPTSTR aBuf)
 1486     {
 1487         if (!aBuf || !*aBuf) return MENU_CMD_INVALID;
 1488         if (!_tcsicmp(aBuf, _T("Show"))) return MENU_CMD_SHOW;
 1489         if (!_tcsicmp(aBuf, _T("UseErrorLevel"))) return MENU_CMD_USEERRORLEVEL;
 1490         if (!_tcsicmp(aBuf, _T("Add"))) return MENU_CMD_ADD;
 1491         if (!_tcsicmp(aBuf, _T("Rename"))) return MENU_CMD_RENAME;
 1492         if (!_tcsicmp(aBuf, _T("Insert"))) return MENU_CMD_INSERT;
 1493         if (!_tcsicmp(aBuf, _T("Check"))) return MENU_CMD_CHECK;
 1494         if (!_tcsicmp(aBuf, _T("Uncheck"))) return MENU_CMD_UNCHECK;
 1495         if (!_tcsicmp(aBuf, _T("ToggleCheck"))) return MENU_CMD_TOGGLECHECK;
 1496         if (!_tcsicmp(aBuf, _T("Enable"))) return MENU_CMD_ENABLE;
 1497         if (!_tcsicmp(aBuf, _T("Disable"))) return MENU_CMD_DISABLE;
 1498         if (!_tcsicmp(aBuf, _T("ToggleEnable"))) return MENU_CMD_TOGGLEENABLE;
 1499         if (!_tcsicmp(aBuf, _T("Standard"))) return MENU_CMD_STANDARD;
 1500         if (!_tcsicmp(aBuf, _T("NoStandard"))) return MENU_CMD_NOSTANDARD;
 1501         if (!_tcsicmp(aBuf, _T("Color"))) return MENU_CMD_COLOR;
 1502         if (!_tcsicmp(aBuf, _T("Default"))) return MENU_CMD_DEFAULT;
 1503         if (!_tcsicmp(aBuf, _T("NoDefault"))) return MENU_CMD_NODEFAULT;
 1504         if (!_tcsicmp(aBuf, _T("Delete"))) return MENU_CMD_DELETE;
 1505         if (!_tcsicmp(aBuf, _T("DeleteAll"))) return MENU_CMD_DELETEALL;
 1506         if (!_tcsicmp(aBuf, _T("Tip"))) return MENU_CMD_TIP;
 1507         if (!_tcsicmp(aBuf, _T("Icon"))) return MENU_CMD_ICON;
 1508         if (!_tcsicmp(aBuf, _T("NoIcon"))) return MENU_CMD_NOICON;
 1509         if (!_tcsicmp(aBuf, _T("Click"))) return MENU_CMD_CLICK;
 1510         if (!_tcsicmp(aBuf, _T("MainWindow"))) return MENU_CMD_MAINWINDOW;
 1511         if (!_tcsicmp(aBuf, _T("NoMainWindow"))) return MENU_CMD_NOMAINWINDOW;
 1512         return MENU_CMD_INVALID;
 1513     }
 1514     
 1515     static void ConvertGuiName(LPTSTR aBuf, LPTSTR &aCommand, LPTSTR *aName = NULL, size_t *aNameLength = NULL)
 1516     {
 1517         LPTSTR colon_pos;
 1518         // Check for '+' and '-' to avoid ambiguity with something like "gui +Delimiter:".
 1519         if (*aBuf == '+' || !(colon_pos = _tcschr(aBuf, ':'))) // Assignment.
 1520         {
 1521             aCommand = aBuf;
 1522             // Name not specified, so leave it at the default set by caller.
 1523             return;
 1524         }
 1525 
 1526         size_t name_length = colon_pos - aBuf;
 1527         
 1528         // Fix for v1.1.24.02: Support trailing spaces as in v1.1.02.03 and earlier:
 1529         while (name_length && IS_SPACE_OR_TAB(aBuf[name_length-1]))
 1530             --name_length;
 1531 
 1532         if (*aBuf == '-') // Fix for v1.1.24.02: Support negative integers for HWND.
 1533         {
 1534             TCHAR number_buf[MAX_INTEGER_SIZE + 1];
 1535             if (name_length >= _countof(number_buf))
 1536                 *number_buf = '\0'; // A non-numeric value (with third parameter FALSE below).
 1537             else
 1538                 tcslcpy(number_buf, aBuf, name_length + 1);
 1539             if (!IsPureNumeric(number_buf, TRUE, FALSE))
 1540             {
 1541                 // This is an option rather than a HWND.
 1542                 aCommand = aBuf;
 1543                 return;
 1544             }
 1545         }
 1546     
 1547         // For backward compatibility, "01" to "09" must be treated as "1" to "9".
 1548         if (name_length == 2 && *aBuf == '0' && aBuf[1] >= '1' && aBuf[1] <= '9')
 1549         {
 1550             // Normalize the number by excluding its leading "0".
 1551             ++aBuf;
 1552             --name_length;
 1553         }
 1554     
 1555         if (aName)
 1556             *aName = aBuf;
 1557         if (aNameLength)
 1558             *aNameLength = name_length;
 1559         aCommand = omit_leading_whitespace(colon_pos + 1);
 1560     }
 1561 
 1562     static GuiCommands ConvertGuiCommand(LPTSTR aBuf)
 1563     {
 1564         if (!*aBuf || *aBuf == '+' || *aBuf == '-') // Assume a var ref that resolves to blank is "options" (for runtime flexibility).
 1565             return GUI_CMD_OPTIONS;
 1566         if (!_tcsicmp(aBuf, _T("Add"))) return GUI_CMD_ADD;
 1567         if (!_tcsicmp(aBuf, _T("Show"))) return GUI_CMD_SHOW;
 1568         if (!_tcsicmp(aBuf, _T("Submit"))) return GUI_CMD_SUBMIT;
 1569         if (!_tcsicmp(aBuf, _T("Cancel")) || !_tcsicmp(aBuf, _T("Hide"))) return GUI_CMD_CANCEL;
 1570         if (!_tcsicmp(aBuf, _T("Minimize"))) return GUI_CMD_MINIMIZE;
 1571         if (!_tcsicmp(aBuf, _T("Maximize"))) return GUI_CMD_MAXIMIZE;
 1572         if (!_tcsicmp(aBuf, _T("Restore"))) return GUI_CMD_RESTORE;
 1573         if (!_tcsicmp(aBuf, _T("Destroy"))) return GUI_CMD_DESTROY;
 1574         if (!_tcsicmp(aBuf, _T("Margin"))) return GUI_CMD_MARGIN;
 1575         if (!_tcsicmp(aBuf, _T("Menu"))) return GUI_CMD_MENU;
 1576         if (!_tcsicmp(aBuf, _T("Font"))) return GUI_CMD_FONT;
 1577         if (!_tcsicmp(aBuf, _T("Tab"))) return GUI_CMD_TAB;
 1578         if (!_tcsicmp(aBuf, _T("ListView"))) return GUI_CMD_LISTVIEW;
 1579         if (!_tcsicmp(aBuf, _T("TreeView"))) return GUI_CMD_TREEVIEW;
 1580         if (!_tcsicmp(aBuf, _T("Default"))) return GUI_CMD_DEFAULT;
 1581         if (!_tcsicmp(aBuf, _T("Color"))) return GUI_CMD_COLOR;
 1582         if (!_tcsicmp(aBuf, _T("Flash"))) return GUI_CMD_FLASH;
 1583         if (!_tcsicmp(aBuf, _T("New"))) return GUI_CMD_NEW;
 1584         return GUI_CMD_INVALID;
 1585     }
 1586 
 1587     static GuiControlCmds ConvertGuiControlCmd(LPTSTR aBuf)
 1588     {
 1589         // If it's blank without a deref, that's CONTENTS.  Otherwise, assume it's OPTIONS for better
 1590         // runtime flexibility (i.e. user can leave the variable blank to make the command do nothing).
 1591         // Fix for v1.0.40.11: Since the above is counterintuitive and undocumented, it has been fixed
 1592         // to behave the way most users would expect; that is, the contents of any deref in parameter 1
 1593         // will behave the same as when such contents is present literally as parameter 1.  Another
 1594         // reason for doing this is that otherwise, there is no way to specify the CONTENTS sub-command
 1595         // in a variable.  For example, the following wouldn't work:
 1596         // GuiControl, %WindowNumber%:, ...
 1597         // GuiControl, %WindowNumberWithColon%, ...
 1598         if (!*aBuf)
 1599             return GUICONTROL_CMD_CONTENTS;
 1600         if (*aBuf == '+' || *aBuf == '-') // Assume a var ref that resolves to blank is "options" (for runtime flexibility).
 1601             return GUICONTROL_CMD_OPTIONS;
 1602         if (!_tcsicmp(aBuf, _T("Text"))) return GUICONTROL_CMD_TEXT;
 1603         if (!_tcsicmp(aBuf, _T("Move"))) return GUICONTROL_CMD_MOVE;
 1604         if (!_tcsicmp(aBuf, _T("MoveDraw"))) return GUICONTROL_CMD_MOVEDRAW;
 1605         if (!_tcsicmp(aBuf, _T("Focus"))) return GUICONTROL_CMD_FOCUS;
 1606         if (!_tcsicmp(aBuf, _T("Choose"))) return GUICONTROL_CMD_CHOOSE;
 1607         if (!_tcsicmp(aBuf, _T("ChooseString"))) return GUICONTROL_CMD_CHOOSESTRING;
 1608         if (!_tcsicmp(aBuf, _T("Font"))) return GUICONTROL_CMD_FONT;
 1609 
 1610         // v1.0.38.02: Anything not already returned from above supports an optional boolean suffix.
 1611         // The following example would hide the control: GuiControl, Show%VarContainingFalse%, MyControl
 1612         // To support hex (due to the 'x' in it), search from the left rather than the right for the
 1613         // first digit:
 1614         LPTSTR suffix;
 1615         for (suffix = aBuf; *suffix && !_istdigit(*suffix); ++suffix);
 1616         bool invert = (*suffix ? !ATOI(suffix) : false);
 1617         if (!_tcsnicmp(aBuf, _T("Enable"), 6)) return invert ? GUICONTROL_CMD_DISABLE : GUICONTROL_CMD_ENABLE;
 1618         if (!_tcsnicmp(aBuf, _T("Disable"), 7)) return invert ? GUICONTROL_CMD_ENABLE : GUICONTROL_CMD_DISABLE;
 1619         if (!_tcsnicmp(aBuf, _T("Show"), 4)) return invert ? GUICONTROL_CMD_HIDE : GUICONTROL_CMD_SHOW;
 1620         if (!_tcsnicmp(aBuf, _T("Hide"), 4)) return invert ? GUICONTROL_CMD_SHOW : GUICONTROL_CMD_HIDE;
 1621 
 1622         return GUICONTROL_CMD_INVALID;
 1623     }
 1624 
 1625     static GuiControlGetCmds ConvertGuiControlGetCmd(LPTSTR aBuf)
 1626     {
 1627         if (!*aBuf) return GUICONTROLGET_CMD_CONTENTS; // The implicit command when nothing was specified.
 1628         if (!_tcsicmp(aBuf, _T("Pos"))) return GUICONTROLGET_CMD_POS;
 1629         if (!_tcsicmp(aBuf, _T("Focus"))) return GUICONTROLGET_CMD_FOCUS;
 1630         if (!_tcsicmp(aBuf, _T("FocusV"))) return GUICONTROLGET_CMD_FOCUSV; // Returns variable vs. ClassNN.
 1631         if (!_tcsicmp(aBuf, _T("Enabled"))) return GUICONTROLGET_CMD_ENABLED;
 1632         if (!_tcsicmp(aBuf, _T("Visible"))) return GUICONTROLGET_CMD_VISIBLE;
 1633         if (!_tcsicmp(aBuf, _T("Hwnd"))) return GUICONTROLGET_CMD_HWND;
 1634         if (!_tcsicmp(aBuf, _T("Name"))) return GUICONTROLGET_CMD_NAME;
 1635         return GUICONTROLGET_CMD_INVALID;
 1636     }
 1637 
 1638     static GuiControls ConvertGuiControl(LPTSTR aBuf)
 1639     {
 1640         if (!aBuf || !*aBuf) return GUI_CONTROL_INVALID;
 1641         if (!_tcsicmp(aBuf, _T("Text"))) return GUI_CONTROL_TEXT;
 1642         if (!_tcsicmp(aBuf, _T("Edit"))) return GUI_CONTROL_EDIT;
 1643         if (!_tcsicmp(aBuf, _T("Button"))) return GUI_CONTROL_BUTTON;
 1644         if (!_tcsicmp(aBuf, _T("Checkbox"))) return GUI_CONTROL_CHECKBOX;
 1645         if (!_tcsicmp(aBuf, _T("Radio"))) return GUI_CONTROL_RADIO;
 1646         if (!_tcsicmp(aBuf, _T("DDL")) || !_tcsicmp(aBuf, _T("DropDownList"))) return GUI_CONTROL_DROPDOWNLIST;
 1647         if (!_tcsicmp(aBuf, _T("ComboBox"))) return GUI_CONTROL_COMBOBOX;
 1648         if (!_tcsicmp(aBuf, _T("ListBox"))) return GUI_CONTROL_LISTBOX;
 1649         if (!_tcsicmp(aBuf, _T("ListView"))) return GUI_CONTROL_LISTVIEW;
 1650         if (!_tcsicmp(aBuf, _T("TreeView"))) return GUI_CONTROL_TREEVIEW;
 1651         // Keep those seldom used at the bottom for performance:
 1652         if (!_tcsicmp(aBuf, _T("UpDown"))) return GUI_CONTROL_UPDOWN;
 1653         if (!_tcsicmp(aBuf, _T("Slider"))) return GUI_CONTROL_SLIDER;
 1654         if (!_tcsicmp(aBuf, _T("Progress"))) return GUI_CONTROL_PROGRESS;
 1655         if (!_tcsicmp(aBuf, _T("Tab"))) return GUI_CONTROL_TAB;
 1656         if (!_tcsicmp(aBuf, _T("Tab2"))) return GUI_CONTROL_TAB2; // v1.0.47.05: Used only temporarily: becomes TAB vs. TAB2 upon creation.
 1657         if (!_tcsicmp(aBuf, _T("Tab3"))) return GUI_CONTROL_TAB3; // v1.1.23.00: As above.
 1658         if (!_tcsicmp(aBuf, _T("GroupBox"))) return GUI_CONTROL_GROUPBOX;
 1659         if (!_tcsicmp(aBuf, _T("Pic")) || !_tcsicmp(aBuf, _T("Picture"))) return GUI_CONTROL_PIC;
 1660         if (!_tcsicmp(aBuf, _T("DateTime"))) return GUI_CONTROL_DATETIME;
 1661         if (!_tcsicmp(aBuf, _T("MonthCal"))) return GUI_CONTROL_MONTHCAL;
 1662         if (!_tcsicmp(aBuf, _T("Hotkey"))) return GUI_CONTROL_HOTKEY;
 1663         if (!_tcsicmp(aBuf, _T("StatusBar"))) return GUI_CONTROL_STATUSBAR;
 1664         if (!_tcsicmp(aBuf, _T("ActiveX"))) return GUI_CONTROL_ACTIVEX;
 1665         if (!_tcsicmp(aBuf, _T("Link"))) return GUI_CONTROL_LINK;
 1666         if (!_tcsicmp(aBuf, _T("Custom"))) return GUI_CONTROL_CUSTOM;
 1667         return GUI_CONTROL_INVALID;
 1668     }
 1669 
 1670     static ThreadCommands ConvertThreadCommand(LPTSTR aBuf)
 1671     {
 1672         if (!aBuf || !*aBuf) return THREAD_CMD_INVALID;
 1673         if (!_tcsicmp(aBuf, _T("Priority"))) return THREAD_CMD_PRIORITY;
 1674         if (!_tcsicmp(aBuf, _T("Interrupt"))) return THREAD_CMD_INTERRUPT;
 1675         if (!_tcsicmp(aBuf, _T("NoTimers"))) return THREAD_CMD_NOTIMERS;
 1676         return THREAD_CMD_INVALID;
 1677     }
 1678     
 1679     static ProcessCmds ConvertProcessCmd(LPTSTR aBuf)
 1680     {
 1681         if (!aBuf || !*aBuf) return PROCESS_CMD_INVALID;
 1682         if (!_tcsicmp(aBuf, _T("Exist"))) return PROCESS_CMD_EXIST;
 1683         if (!_tcsicmp(aBuf, _T("Close"))) return PROCESS_CMD_CLOSE;
 1684         if (!_tcsicmp(aBuf, _T("Priority"))) return PROCESS_CMD_PRIORITY;
 1685         if (!_tcsicmp(aBuf, _T("Wait"))) return PROCESS_CMD_WAIT;
 1686         if (!_tcsicmp(aBuf, _T("WaitClose"))) return PROCESS_CMD_WAITCLOSE;
 1687         return PROCESS_CMD_INVALID;
 1688     }
 1689 
 1690     static ControlCmds ConvertControlCmd(LPTSTR aBuf)
 1691     {
 1692         if (!aBuf || !*aBuf) return CONTROL_CMD_INVALID;
 1693         if (!_tcsicmp(aBuf, _T("Check"))) return CONTROL_CMD_CHECK;
 1694         if (!_tcsicmp(aBuf, _T("Uncheck"))) return CONTROL_CMD_UNCHECK;
 1695         if (!_tcsicmp(aBuf, _T("Enable"))) return CONTROL_CMD_ENABLE;
 1696         if (!_tcsicmp(aBuf, _T("Disable"))) return CONTROL_CMD_DISABLE;
 1697         if (!_tcsicmp(aBuf, _T("Show"))) return CONTROL_CMD_SHOW;
 1698         if (!_tcsicmp(aBuf, _T("Hide"))) return CONTROL_CMD_HIDE;
 1699         if (!_tcsicmp(aBuf, _T("Style"))) return CONTROL_CMD_STYLE;
 1700         if (!_tcsicmp(aBuf, _T("ExStyle"))) return CONTROL_CMD_EXSTYLE;
 1701         if (!_tcsicmp(aBuf, _T("ShowDropDown"))) return CONTROL_CMD_SHOWDROPDOWN;
 1702         if (!_tcsicmp(aBuf, _T("HideDropDown"))) return CONTROL_CMD_HIDEDROPDOWN;
 1703         if (!_tcsicmp(aBuf, _T("TabLeft"))) return CONTROL_CMD_TABLEFT;
 1704         if (!_tcsicmp(aBuf, _T("TabRight"))) return CONTROL_CMD_TABRIGHT;
 1705         if (!_tcsicmp(aBuf, _T("Add"))) return CONTROL_CMD_ADD;
 1706         if (!_tcsicmp(aBuf, _T("Delete"))) return CONTROL_CMD_DELETE;
 1707         if (!_tcsicmp(aBuf, _T("Choose"))) return CONTROL_CMD_CHOOSE;
 1708         if (!_tcsicmp(aBuf, _T("ChooseString"))) return CONTROL_CMD_CHOOSESTRING;
 1709         if (!_tcsicmp(aBuf, _T("EditPaste"))) return CONTROL_CMD_EDITPASTE;
 1710         return CONTROL_CMD_INVALID;
 1711     }
 1712 
 1713     static ControlGetCmds ConvertControlGetCmd(LPTSTR aBuf)
 1714     {
 1715         if (!aBuf || !*aBuf) return CONTROLGET_CMD_INVALID;
 1716         if (!_tcsicmp(aBuf, _T("Checked"))) return CONTROLGET_CMD_CHECKED;
 1717         if (!_tcsicmp(aBuf, _T("Enabled"))) return CONTROLGET_CMD_ENABLED;
 1718         if (!_tcsicmp(aBuf, _T("Visible"))) return CONTROLGET_CMD_VISIBLE;
 1719         if (!_tcsicmp(aBuf, _T("Tab"))) return CONTROLGET_CMD_TAB;
 1720         if (!_tcsicmp(aBuf, _T("FindString"))) return CONTROLGET_CMD_FINDSTRING;
 1721         if (!_tcsicmp(aBuf, _T("Choice"))) return CONTROLGET_CMD_CHOICE;
 1722         if (!_tcsicmp(aBuf, _T("List"))) return CONTROLGET_CMD_LIST;
 1723         if (!_tcsicmp(aBuf, _T("LineCount"))) return CONTROLGET_CMD_LINECOUNT;
 1724         if (!_tcsicmp(aBuf, _T("CurrentLine"))) return CONTROLGET_CMD_CURRENTLINE;
 1725         if (!_tcsicmp(aBuf, _T("CurrentCol"))) return CONTROLGET_CMD_CURRENTCOL;
 1726         if (!_tcsicmp(aBuf, _T("Line"))) return CONTROLGET_CMD_LINE;
 1727         if (!_tcsicmp(aBuf, _T("Selected"))) return CONTROLGET_CMD_SELECTED;
 1728         if (!_tcsicmp(aBuf, _T("Style"))) return CONTROLGET_CMD_STYLE;
 1729         if (!_tcsicmp(aBuf, _T("ExStyle"))) return CONTROLGET_CMD_EXSTYLE;
 1730         if (!_tcsicmp(aBuf, _T("Hwnd"))) return CONTROLGET_CMD_HWND;
 1731         return CONTROLGET_CMD_INVALID;
 1732     }
 1733 
 1734     static DriveCmds ConvertDriveCmd(LPTSTR aBuf)
 1735     {
 1736         if (!aBuf || !*aBuf) return DRIVE_CMD_INVALID;
 1737         if (!_tcsicmp(aBuf, _T("Eject"))) return DRIVE_CMD_EJECT;
 1738         if (!_tcsicmp(aBuf, _T("Lock"))) return DRIVE_CMD_LOCK;
 1739         if (!_tcsicmp(aBuf, _T("Unlock"))) return DRIVE_CMD_UNLOCK;
 1740         if (!_tcsicmp(aBuf, _T("Label"))) return DRIVE_CMD_LABEL;
 1741         return DRIVE_CMD_INVALID;
 1742     }
 1743 
 1744     static DriveGetCmds ConvertDriveGetCmd(LPTSTR aBuf)
 1745     {
 1746         if (!aBuf || !*aBuf) return DRIVEGET_CMD_INVALID;
 1747         if (!_tcsicmp(aBuf, _T("List"))) return DRIVEGET_CMD_LIST;
 1748         if (!_tcsicmp(aBuf, _T("FileSystem")) || !_tcsicmp(aBuf, _T("FS"))) return DRIVEGET_CMD_FILESYSTEM;
 1749         if (!_tcsicmp(aBuf, _T("Label"))) return DRIVEGET_CMD_LABEL;
 1750         if (!_tcsnicmp(aBuf, _T("SetLabel:"), 9)) return DRIVEGET_CMD_SETLABEL;  // Uses strnicmp() vs. stricmp().
 1751         if (!_tcsicmp(aBuf, _T("Serial"))) return DRIVEGET_CMD_SERIAL;
 1752         if (!_tcsicmp(aBuf, _T("Type"))) return DRIVEGET_CMD_TYPE;
 1753         if (!_tcsicmp(aBuf, _T("Status"))) return DRIVEGET_CMD_STATUS;
 1754         if (!_tcsicmp(aBuf, _T("StatusCD"))) return DRIVEGET_CMD_STATUSCD;
 1755         if (!_tcsicmp(aBuf, _T("Capacity")) || !_tcsicmp(aBuf, _T("Cap"))) return DRIVEGET_CMD_CAPACITY;
 1756         return DRIVEGET_CMD_INVALID;
 1757     }
 1758 
 1759     static WinSetAttributes ConvertWinSetAttribute(LPTSTR aBuf)
 1760     {
 1761         if (!aBuf || !*aBuf) return WINSET_INVALID;
 1762         if (!_tcsicmp(aBuf, _T("Trans")) || !_tcsicmp(aBuf, _T("Transparent"))) return WINSET_TRANSPARENT;
 1763         if (!_tcsicmp(aBuf, _T("TransColor"))) return WINSET_TRANSCOLOR;
 1764         if (!_tcsicmp(aBuf, _T("AlwaysOnTop")) || !_tcsicmp(aBuf, _T("Topmost"))) return WINSET_ALWAYSONTOP;
 1765         if (!_tcsicmp(aBuf, _T("Bottom"))) return WINSET_BOTTOM;
 1766         if (!_tcsicmp(aBuf, _T("Top"))) return WINSET_TOP;
 1767         if (!_tcsicmp(aBuf, _T("Style"))) return WINSET_STYLE;
 1768         if (!_tcsicmp(aBuf, _T("ExStyle"))) return WINSET_EXSTYLE;
 1769         if (!_tcsicmp(aBuf, _T("Redraw"))) return WINSET_REDRAW;
 1770         if (!_tcsicmp(aBuf, _T("Enable"))) return WINSET_ENABLE;
 1771         if (!_tcsicmp(aBuf, _T("Disable"))) return WINSET_DISABLE;
 1772         if (!_tcsicmp(aBuf, _T("Region"))) return WINSET_REGION;
 1773         return WINSET_INVALID;
 1774     }
 1775 
 1776 
 1777     static WinGetCmds ConvertWinGetCmd(LPTSTR aBuf)
 1778     {
 1779         if (!aBuf || !*aBuf) return WINGET_CMD_ID;  // If blank, return the default command.
 1780         if (!_tcsicmp(aBuf, _T("ID"))) return WINGET_CMD_ID;
 1781         if (!_tcsicmp(aBuf, _T("IDLast"))) return WINGET_CMD_IDLAST;
 1782         if (!_tcsicmp(aBuf, _T("PID"))) return WINGET_CMD_PID;
 1783         if (!_tcsicmp(aBuf, _T("ProcessName"))) return WINGET_CMD_PROCESSNAME;
 1784         if (!_tcsicmp(aBuf, _T("ProcessPath"))) return WINGET_CMD_PROCESSPATH;
 1785         if (!_tcsicmp(aBuf, _T("Count"))) return WINGET_CMD_COUNT;
 1786         if (!_tcsicmp(aBuf, _T("List"))) return WINGET_CMD_LIST;
 1787         if (!_tcsicmp(aBuf, _T("MinMax"))) return WINGET_CMD_MINMAX;
 1788         if (!_tcsicmp(aBuf, _T("Style"))) return WINGET_CMD_STYLE;
 1789         if (!_tcsicmp(aBuf, _T("ExStyle"))) return WINGET_CMD_EXSTYLE;
 1790         if (!_tcsicmp(aBuf, _T("Transparent"))) return WINGET_CMD_TRANSPARENT;
 1791         if (!_tcsicmp(aBuf, _T("TransColor"))) return WINGET_CMD_TRANSCOLOR;
 1792         if (!_tcsnicmp(aBuf, _T("ControlList"), 11))
 1793         {
 1794             aBuf += 11;
 1795             if (!*aBuf)
 1796                 return WINGET_CMD_CONTROLLIST;
 1797             if (!_tcsicmp(aBuf, _T("Hwnd")))
 1798                 return WINGET_CMD_CONTROLLISTHWND;
 1799             // Otherwise fall through to the below.
 1800         }
 1801         // Otherwise:
 1802         return WINGET_CMD_INVALID;
 1803     }
 1804 
 1805     static ToggleValueType ConvertOnOff(LPTSTR aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
 1806     // Returns aDefault if aBuf isn't either ON, OFF, or blank.
 1807     {
 1808         if (!aBuf || !*aBuf) return NEUTRAL;
 1809         if (!_tcsicmp(aBuf, _T("On")) || !_tcscmp(aBuf, _T("1"))) return TOGGLED_ON;
 1810         if (!_tcsicmp(aBuf, _T("Off")) || !_tcscmp(aBuf, _T("0"))) return TOGGLED_OFF;
 1811         return aDefault;
 1812     }
 1813 
 1814     static ToggleValueType ConvertOnOffAlways(LPTSTR aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
 1815     // Returns aDefault if aBuf isn't either ON, OFF, ALWAYSON, ALWAYSOFF, or blank.
 1816     {
 1817         if (ToggleValueType toggle = ConvertOnOff(aBuf))
 1818             return toggle;
 1819         if (!_tcsicmp(aBuf, _T("AlwaysOn"))) return ALWAYS_ON;
 1820         if (!_tcsicmp(aBuf, _T("AlwaysOff"))) return ALWAYS_OFF;
 1821         return aDefault;
 1822     }
 1823 
 1824     static ToggleValueType ConvertOnOffToggle(LPTSTR aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
 1825     // Returns aDefault if aBuf isn't either ON, OFF, TOGGLE, or blank.
 1826     {
 1827         if (ToggleValueType toggle = ConvertOnOff(aBuf))
 1828             return toggle;
 1829         if (!_tcsicmp(aBuf, _T("Toggle")) || !_tcscmp(aBuf, _T("-1"))) return TOGGLE;
 1830         return aDefault;
 1831     }
 1832 
 1833     static StringCaseSenseType ConvertStringCaseSense(LPTSTR aBuf)
 1834     {
 1835         if (!_tcsicmp(aBuf, _T("On")) || !_tcscmp(aBuf, _T("1"))) return SCS_SENSITIVE;
 1836         if (!_tcsicmp(aBuf, _T("Off")) || !_tcscmp(aBuf, _T("0"))) return SCS_INSENSITIVE;
 1837         if (!_tcsicmp(aBuf, _T("Locale"))) return SCS_INSENSITIVE_LOCALE;
 1838         return SCS_INVALID;
 1839     }
 1840 
 1841     static ToggleValueType ConvertOnOffTogglePermit(LPTSTR aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
 1842     // Returns aDefault if aBuf isn't either ON, OFF, TOGGLE, PERMIT, or blank.
 1843     {
 1844         if (ToggleValueType toggle = ConvertOnOffToggle(aBuf))
 1845             return toggle;
 1846         if (!_tcsicmp(aBuf, _T("Permit"))) return TOGGLE_PERMIT;
 1847         return aDefault;
 1848     }
 1849 
 1850     static ToggleValueType ConvertBlockInput(LPTSTR aBuf)
 1851     {
 1852         if (ToggleValueType toggle = ConvertOnOff(aBuf))
 1853             return toggle;
 1854         if (!_tcsicmp(aBuf, _T("Send"))) return TOGGLE_SEND;
 1855         if (!_tcsicmp(aBuf, _T("Mouse"))) return TOGGLE_MOUSE;
 1856         if (!_tcsicmp(aBuf, _T("SendAndMouse"))) return TOGGLE_SENDANDMOUSE;
 1857         if (!_tcsicmp(aBuf, _T("Default"))) return TOGGLE_DEFAULT;
 1858         if (!_tcsicmp(aBuf, _T("MouseMove"))) return TOGGLE_MOUSEMOVE;
 1859         if (!_tcsicmp(aBuf, _T("MouseMoveOff"))) return TOGGLE_MOUSEMOVEOFF;
 1860         return TOGGLE_INVALID;
 1861     }
 1862 
 1863     static SendModes ConvertSendMode(LPTSTR aBuf, SendModes aValueToReturnIfInvalid)
 1864     {
 1865         if (!_tcsicmp(aBuf, _T("Play"))) return SM_PLAY;
 1866         if (!_tcsicmp(aBuf, _T("Event"))) return SM_EVENT;
 1867         if (!_tcsnicmp(aBuf, _T("Input"), 5)) // This IF must be listed last so that it can fall through to bottom line.
 1868         {
 1869             aBuf += 5;
 1870             if (!*aBuf || !_tcsicmp(aBuf, _T("ThenEvent"))) // "ThenEvent" is supported for backward compatibility with 1.0.43.00.
 1871                 return SM_INPUT;
 1872             if (!_tcsicmp(aBuf, _T("ThenPlay")))
 1873                 return SM_INPUT_FALLBACK_TO_PLAY;
 1874             //else fall through and return the indication of invalidity.
 1875         }
 1876         return aValueToReturnIfInvalid;
 1877     }
 1878 
 1879     static FileLoopModeType ConvertLoopMode(LPTSTR aBuf)
 1880     // Returns the file loop mode, or FILE_LOOP_INVALID if aBuf contains an invalid mode.
 1881     {
 1882         switch (ATOI(aBuf))
 1883         {
 1884         case 0: return FILE_LOOP_FILES_ONLY; // This is also the default mode if the param is blank.
 1885         case 1: return FILE_LOOP_FILES_AND_FOLDERS;
 1886         case 2: return FILE_LOOP_FOLDERS_ONLY;
 1887         }
 1888         // Otherwise:
 1889         return FILE_LOOP_INVALID;
 1890     }
 1891 
 1892     static FileLoopModeType ConvertLoopModeString(LPTSTR aBuf)
 1893     {
 1894         for (FileLoopModeType mode = FILE_LOOP_INVALID;;)
 1895         {
 1896             switch (ctoupper(*aBuf++))
 1897             {
 1898             // For simplicity, both are allowed with either kind of loop:
 1899             case 'F': // Files
 1900             case 'V': // Values
 1901                 mode |= FILE_LOOP_FILES_ONLY;
 1902                 break;
 1903             case 'D': // Directories
 1904             case 'K': // Keys
 1905                 mode |= FILE_LOOP_FOLDERS_ONLY;
 1906                 break;
 1907             case 'R':
 1908                 mode |= FILE_LOOP_RECURSE;
 1909                 break;
 1910             case ' ':  // Allow whitespace.
 1911             case '\t': //
 1912                 break;
 1913             case '\0':
 1914                 if ((mode & FILE_LOOP_FILES_AND_FOLDERS) == 0)
 1915                     mode |= FILE_LOOP_FILES_ONLY; // Set default.
 1916                 return mode;
 1917             default: // Invalid character.
 1918                 return FILE_LOOP_INVALID;
 1919             }
 1920         }
 1921     }
 1922 
 1923     static int ConvertMsgBoxResult(LPTSTR aBuf)
 1924     // Returns the matching ID, or zero if none.
 1925     {
 1926         if (!aBuf || !*aBuf) return 0;
 1927         // Keeping the most oft-used ones up top helps perf. a little:
 1928         if (!_tcsicmp(aBuf, _T("YES"))) return IDYES;
 1929         if (!_tcsicmp(aBuf, _T("NO"))) return IDNO;
 1930         if (!_tcsicmp(aBuf, _T("OK"))) return IDOK;
 1931         if (!_tcsicmp(aBuf, _T("CANCEL"))) return IDCANCEL;
 1932         if (!_tcsicmp(aBuf, _T("ABORT"))) return IDABORT;
 1933         if (!_tcsicmp(aBuf, _T("IGNORE"))) return IDIGNORE;
 1934         if (!_tcsicmp(aBuf, _T("RETRY"))) return IDRETRY;
 1935         if (!_tcsicmp(aBuf, _T("CONTINUE"))) return IDCONTINUE; // v1.0.44.08: For use with 2000/XP's "Cancel/Try Again/Continue" MsgBox.
 1936         if (!_tcsicmp(aBuf, _T("TRYAGAIN"))) return IDTRYAGAIN; //
 1937         if (!_tcsicmp(aBuf, _T("Timeout"))) return AHK_TIMEOUT; // Our custom result value.
 1938         return 0;
 1939     }
 1940 
 1941     static int ConvertRunMode(LPTSTR aBuf)
 1942     // Returns the matching WinShow mode, or SW_SHOWNORMAL if none.
 1943     // These are also the modes that AutoIt3 uses.
 1944     {
 1945         // For v1.0.19, this was made more permissive (the use of strcasestr vs. stricmp) to support
 1946         // the optional word UseErrorLevel inside this parameter:
 1947         if (!aBuf || !*aBuf) return SW_SHOWNORMAL;
 1948         if (tcscasestr(aBuf, _T("MIN"))) return SW_MINIMIZE;
 1949         if (tcscasestr(aBuf, _T("MAX"))) return SW_MAXIMIZE;
 1950         if (tcscasestr(aBuf, _T("HIDE"))) return SW_HIDE;
 1951         return SW_SHOWNORMAL;
 1952     }
 1953 
 1954     static int ConvertMouseButton(LPTSTR aBuf, bool aAllowWheel = true, bool aUseLogicalButton = false)
 1955     // Returns the matching VK, or zero if none.
 1956     {
 1957         if (!*aBuf || !_tcsicmp(aBuf, _T("LEFT")) || !_tcsicmp(aBuf, _T("L")))
 1958             return aUseLogicalButton ? VK_LBUTTON_LOGICAL : VK_LBUTTON; // Some callers rely on this default when !*aBuf.
 1959         if (!_tcsicmp(aBuf, _T("RIGHT")) || !_tcsicmp(aBuf, _T("R"))) return aUseLogicalButton ? VK_RBUTTON_LOGICAL : VK_RBUTTON;
 1960         if (!_tcsicmp(aBuf, _T("MIDDLE")) || !_tcsicmp(aBuf, _T("M"))) return VK_MBUTTON;
 1961         if (!_tcsicmp(aBuf, _T("X1"))) return VK_XBUTTON1;
 1962         if (!_tcsicmp(aBuf, _T("X2"))) return VK_XBUTTON2;
 1963         if (aAllowWheel)
 1964         {
 1965             if (!_tcsicmp(aBuf, _T("WheelUp")) || !_tcsicmp(aBuf, _T("WU"))) return VK_WHEEL_UP;
 1966             if (!_tcsicmp(aBuf, _T("WheelDown")) || !_tcsicmp(aBuf, _T("WD"))) return VK_WHEEL_DOWN;
 1967             // Lexikos: Support horizontal scrolling in Windows Vista and later.
 1968             if (!_tcsicmp(aBuf, _T("WheelLeft")) || !_tcsicmp(aBuf, _T("WL"))) return VK_WHEEL_LEFT;
 1969             if (!_tcsicmp(aBuf, _T("WheelRight")) || !_tcsicmp(aBuf, _T("WR"))) return VK_WHEEL_RIGHT;
 1970         }
 1971         return 0;
 1972     }
 1973 
 1974     static CoordModeType ConvertCoordMode(LPTSTR aBuf)
 1975     {
 1976         if (!aBuf || !*aBuf || !_tcsicmp(aBuf, _T("Screen")))
 1977             return COORD_MODE_SCREEN;
 1978         else if (!_tcsicmp(aBuf, _T("Relative")) || !_tcsicmp(aBuf, _T("Window")))
 1979             return COORD_MODE_WINDOW;
 1980         else if (!_tcsicmp(aBuf, _T("Client")))
 1981             return COORD_MODE_CLIENT;
 1982         return -1;
 1983     }
 1984 
 1985     static CoordModeType ConvertCoordModeCmd(LPTSTR aBuf)
 1986     {
 1987         if (!aBuf || !*aBuf) return -1;
 1988         if (!_tcsicmp(aBuf, _T("Pixel"))) return COORD_MODE_PIXEL;
 1989         if (!_tcsicmp(aBuf, _T("Mouse"))) return COORD_MODE_MOUSE;
 1990         if (!_tcsicmp(aBuf, _T("ToolTip"))) return COORD_MODE_TOOLTIP;
 1991         if (!_tcsicmp(aBuf, _T("Caret"))) return COORD_MODE_CARET;
 1992         if (!_tcsicmp(aBuf, _T("Menu"))) return COORD_MODE_MENU;
 1993         return -1;
 1994     }
 1995 
 1996     static VariableTypeType ConvertVariableTypeName(LPTSTR aBuf)
 1997     // Returns the matching type, or zero if none.
 1998     {
 1999         if (!aBuf || !*aBuf) return VAR_TYPE_INVALID;
 2000         if (!_tcsicmp(aBuf, _T("Integer"))) return VAR_TYPE_INTEGER;
 2001         if (!_tcsicmp(aBuf, _T("Float"))) return VAR_TYPE_FLOAT;
 2002         if (!_tcsicmp(aBuf, _T("Number"))) return VAR_TYPE_NUMBER;
 2003         if (!_tcsicmp(aBuf, _T("Time"))) return VAR_TYPE_TIME;
 2004         if (!_tcsicmp(aBuf, _T("Date"))) return VAR_TYPE_TIME;  // "date" is just an alias for "time".
 2005         if (!_tcsicmp(aBuf, _T("Digit"))) return VAR_TYPE_DIGIT;
 2006         if (!_tcsicmp(aBuf, _T("Xdigit"))) return VAR_TYPE_XDIGIT;
 2007         if (!_tcsicmp(aBuf, _T("Alnum"))) return VAR_TYPE_ALNUM;
 2008         if (!_tcsicmp(aBuf, _T("Alpha"))) return VAR_TYPE_ALPHA;
 2009         if (!_tcsicmp(aBuf, _T("Upper"))) return VAR_TYPE_UPPER;
 2010         if (!_tcsicmp(aBuf, _T("Lower"))) return VAR_TYPE_LOWER;
 2011         if (!_tcsicmp(aBuf, _T("Space"))) return VAR_TYPE_SPACE;
 2012         return VAR_TYPE_INVALID;
 2013     }
 2014 
 2015     static UINT ConvertFileEncoding(LPTSTR aBuf)
 2016     // Returns the encoding with possible CP_AHKNOBOM flag, or (UINT)-1 if invalid.
 2017     {
 2018         if (!aBuf || !*aBuf)
 2019             // Active codepage, equivalent to specifying CP0.
 2020             return CP_ACP;
 2021         if (!_tcsicmp(aBuf, _T("UTF-8")))       return CP_UTF8;
 2022         if (!_tcsicmp(aBuf, _T("UTF-8-RAW")))   return CP_UTF8 | CP_AHKNOBOM;
 2023         if (!_tcsicmp(aBuf, _T("UTF-16")))      return 1200;
 2024         if (!_tcsicmp(aBuf, _T("UTF-16-RAW")))  return 1200 | CP_AHKNOBOM;
 2025         if (!_tcsnicmp(aBuf, _T("CP"), 2) && IsPureNumeric(aBuf + 2, false, false))
 2026             // CPnnn
 2027             return ATOU(aBuf + 2);
 2028         return -1;
 2029     }
 2030 
 2031     static ResultType ValidateMouseCoords(LPTSTR aX, LPTSTR aY)
 2032     {
 2033         // OK: Both are absent, which is the signal to use the current position.
 2034         // OK: Both are present (that they are numeric is validated elsewhere).
 2035         // FAIL: One is absent but the other is present.
 2036         return (!*aX && !*aY) || (*aX && *aY) ? OK : FAIL;
 2037     }
 2038 
 2039     bool IsExemptFromSuspend()
 2040     {
 2041         // Hotkey and Hotstring subroutines whose first line is the Suspend command are exempt from
 2042         // being suspended themselves except when their first parameter is the literal
 2043         // word "on":
 2044         return mActionType == ACT_SUSPEND && (!mArgc || ArgHasDeref(1) || _tcsicmp(mArg[0].text, _T("On")));
 2045     }
 2046 
 2047     static LPTSTR LogToText(LPTSTR aBuf, int aBufSize);
 2048     LPTSTR VicinityToText(LPTSTR aBuf, int aBufSize);
 2049     LPTSTR ToText(LPTSTR aBuf, int aBufSize, bool aCRLF, DWORD aElapsed = 0, bool aLineWasResumed = false);
 2050 
 2051     static void ToggleSuspendState();
 2052     static void PauseUnderlyingThread(bool aTrueForPauseFalseForUnpause);
 2053     ResultType ChangePauseState(ToggleValueType aChangeTo, bool aAlwaysOperateOnUnderlyingThread);
 2054     static ResultType ScriptBlockInput(bool aEnable);
 2055 
 2056     Line *PreparseError(LPTSTR aErrorText, LPTSTR aExtraInfo = _T(""));
 2057     // Call this LineError to avoid confusion with Script's error-displaying functions:
 2058     ResultType LineError(LPCTSTR aErrorText, ResultType aErrorType = FAIL, LPCTSTR aExtraInfo = _T(""));
 2059     static int FormatError(LPTSTR aBuf, int aBufSize, ResultType aErrorType, LPCTSTR aErrorText, LPCTSTR aExtraInfo, Line *aLine, LPCTSTR aFooter);
 2060     IObject *CreateRuntimeException(LPCTSTR aErrorText, LPCTSTR aWhat = NULL, LPCTSTR aExtraInfo = _T(""));
 2061     ResultType ThrowRuntimeException(LPCTSTR aErrorText, LPCTSTR aWhat = NULL, LPCTSTR aExtraInfo = _T(""));
 2062     
 2063     ResultType SetErrorsOrThrow(bool aError, DWORD aLastErrorOverride = -1);
 2064     ResultType SetErrorLevelOrThrow() { return SetErrorLevelOrThrowBool(true); }
 2065     ResultType SetErrorLevelOrThrowBool(bool aError);        //
 2066     ResultType SetErrorLevelOrThrowStr(LPCTSTR aErrorValue); // Explicit names to avoid calling the wrong overload.
 2067     ResultType SetErrorLevelOrThrowInt(int aErrorValue);     //
 2068 
 2069     Line(FileIndexType aFileIndex, LineNumberType aFileLineNumber, ActionTypeType aActionType
 2070         , ArgStruct aArg[], ArgCountType aArgc) // Constructor
 2071         : mFileIndex(aFileIndex), mLineNumber(aFileLineNumber), mActionType(aActionType)
 2072         , mAttribute(ATTR_NONE), mArgc(aArgc), mArg(aArg)
 2073         , mPrevLine(NULL), mNextLine(NULL), mRelatedLine(NULL), mParentLine(NULL)
 2074 #ifdef CONFIG_DEBUGGER
 2075         , mBreakpoint(NULL)
 2076 #endif
 2077         {}
 2078     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2079     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2080     void operator delete(void *aPtr) {}  // Intentionally does nothing because we're using SimpleHeap for everything.
 2081     void operator delete[](void *aPtr) {}
 2082 
 2083     // AutoIt3 functions:
 2084     static bool Util_CopyDir(LPCTSTR szInputSource, LPCTSTR szInputDest, int OverwriteMode, bool bMove);
 2085     static bool Util_RemoveDir(LPCTSTR szInputSource, bool bRecurse);
 2086     static int Util_CopyFile(LPCTSTR szInputSource, LPCTSTR szInputDest, bool bOverwrite, bool bMove, DWORD &aLastError);
 2087     static void Util_ExpandFilenameWildcard(LPCTSTR szSource, LPCTSTR szDest, LPTSTR szExpandedDest);
 2088     static void Util_ExpandFilenameWildcardPart(LPCTSTR szSource, LPCTSTR szDest, LPTSTR szExpandedDest);
 2089     static bool Util_DoesFileExist(LPCTSTR szFilename);
 2090     static bool Util_IsDir(LPCTSTR szPath);
 2091     static void Util_GetFullPathName(LPCTSTR szIn, LPTSTR szOut);
 2092     static void Util_GetFullPathName(LPCTSTR szIn, LPTSTR szOut, DWORD aBufSize);
 2093 };
 2094 
 2095 
 2096 
 2097 class Label : public IObjectComCompatible
 2098 {
 2099 public:
 2100     LPTSTR mName;
 2101     Line *mJumpToLine;
 2102     Label *mPrevLabel, *mNextLabel;  // Prev & Next items in linked list.
 2103 
 2104     bool IsExemptFromSuspend()
 2105     {
 2106         // See Line::IsExemptFromSuspend() for comments.
 2107         return mJumpToLine->IsExemptFromSuspend();
 2108     }
 2109 
 2110     ResultType Execute()
 2111     // This function was added in v1.0.46.16 to support A_ThisLabel.
 2112     {
 2113         Label *prev_label =g->CurrentLabel; // This will be non-NULL when a subroutine is called from inside another subroutine.
 2114         g->CurrentLabel = this;
 2115         ResultType result;
 2116         DEBUGGER_STACK_PUSH(this)
 2117         // I'm pretty sure it's not valid for the following call to ExecUntil() to tell us to jump
 2118         // somewhere, because the called function, or a layer even deeper, should handle the goto
 2119         // prior to returning to us?  So the last parameter is omitted:
 2120         result = mJumpToLine->ExecUntil(UNTIL_RETURN); // The script loader has ensured that Label::mJumpToLine can't be NULL.
 2121         DEBUGGER_STACK_POP()
 2122         g->CurrentLabel = prev_label;
 2123         return result;
 2124     }
 2125 
 2126     Label(LPTSTR aLabelName)
 2127         : mName(aLabelName) // Caller gave us a pointer to dynamic memory for this (or an empty string in the case of mPlaceholderLabel).
 2128         , mJumpToLine(NULL)
 2129         , mPrevLabel(NULL), mNextLabel(NULL)
 2130     {}
 2131     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2132     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2133     void operator delete(void *aPtr) {}
 2134     void operator delete[](void *aPtr) {}
 2135 
 2136     // IObject.
 2137     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
 2138     ULONG STDMETHODCALLTYPE AddRef() { return 1; }
 2139     ULONG STDMETHODCALLTYPE Release() { return 1; }
 2140     IObject_Type_Impl("Label") // Currently never called since Label isn't accessible to script.
 2141 #ifdef CONFIG_DEBUGGER
 2142     void DebugWriteProperty(IDebugProperties *, int aPage, int aPageSize, int aDepth) {}
 2143 #endif
 2144 };
 2145 
 2146 
 2147 
 2148 // This class encapsulates a pointer to an object which can be called by a timer,
 2149 // hotkey, etc.  It provides common functionality that wouldn't be suitable for the
 2150 // base IObject interface, but is needed for detection of "Suspend" or "Critical"
 2151 // prior to calling the sub or function.
 2152 class LabelPtr
 2153 {
 2154 protected:
 2155     IObject *mObject;
 2156     
 2157     enum CallableType
 2158     {
 2159         Callable_Label,
 2160         Callable_Func,
 2161         Callable_Object
 2162     };
 2163     static Line *getJumpToLine(IObject *aObject);
 2164     static CallableType getType(IObject *aObject);
 2165 
 2166 public:
 2167     LabelPtr() : mObject(NULL) {}
 2168     LabelPtr(IObject *object) : mObject(object) {}
 2169     ResultType ExecuteInNewThread(TCHAR *aNewThreadDesc
 2170         , ExprTokenType *aParamValue = NULL, int aParamCount = 0, INT_PTR *aRetVal = NULL) const;
 2171     const LabelPtr* operator-> () { return this; } // Act like a pointer.
 2172     operator void *() const { return mObject; } // For comparisons and boolean eval.
 2173 
 2174     // Caller beware: does not check for NULL.
 2175     Label *ToLabel() const { return getType(mObject) == Callable_Label ? (Label *)mObject : NULL; }
 2176     // Caller beware: does not check for NULL.
 2177     Func *ToFunc() const { return getType(mObject) == Callable_Func ? (Func *)mObject : NULL; }
 2178     IObject *ToObject() const { return mObject; }
 2179     
 2180     // True if it is a dynamically-allocated object, not a Label or Func.
 2181     bool IsLiveObject() const { return mObject && getType(mObject) == Callable_Object; }
 2182     
 2183     // Helper methods for legacy code which deals with Labels.
 2184     bool IsExemptFromSuspend() const;
 2185     ActionTypeType TypeOfFirstLine() const;
 2186     LPTSTR Name() const;
 2187 };
 2188 
 2189 // LabelPtr with automatic reference-counting, for storing an object safely,
 2190 // such as in a HotkeyVariant, UserMenuItem, etc.  Its specific purpose is to
 2191 // work with old code that wasn't concerned with reference counting.
 2192 class LabelRef : public LabelPtr
 2193 {
 2194 private:
 2195     LabelRef(const LabelRef &); // Disable default copy constructor.
 2196     LabelRef & operator = (const LabelRef &); // ...and copy assignment.
 2197 
 2198 public:
 2199     LabelRef() : LabelPtr() {}
 2200     LabelRef(IObject *object) : LabelPtr(object)
 2201     {
 2202         if (object)
 2203             object->AddRef();
 2204     }
 2205     LabelRef(const LabelPtr &other) : LabelPtr(other)
 2206     {
 2207         if (mObject)
 2208             mObject->AddRef();
 2209     }
 2210     LabelRef & operator = (IObject *object)
 2211     {
 2212         if (object)
 2213             object->AddRef();
 2214         if (mObject)
 2215             mObject->Release();
 2216         mObject = object;
 2217         return *this;
 2218     }
 2219     LabelRef & operator = (const LabelPtr &other)
 2220     {
 2221         return *this = other.ToObject();
 2222     }
 2223     ~LabelRef()
 2224     {
 2225         if (mObject)
 2226             mObject->Release();
 2227     }
 2228 };
 2229 
 2230 
 2231 
 2232 enum FuncParamDefaults {PARAM_DEFAULT_NONE, PARAM_DEFAULT_STR, PARAM_DEFAULT_INT, PARAM_DEFAULT_FLOAT};
 2233 struct FuncParam
 2234 {
 2235     Var *var;
 2236     WORD is_byref; // Boolean, but defined as WORD in case it helps data alignment and/or performance (BOOL vs. WORD didn't help benchmarks).
 2237     WORD default_type;
 2238     union {LPTSTR default_str; __int64 default_int64; double default_double;};
 2239 };
 2240 
 2241 struct UDFCallInfo
 2242 {
 2243     Func *func; // If non-NULL, indicates this is a UDF whose vars will need to be freed/restored later.
 2244     VarBkp *backup; // Backup of previous instance's local vars.  NULL if no previous instance or no vars.
 2245     int backup_count; // Number of previous instance's local vars.  0 if no previous instance or no vars.
 2246     UDFCallInfo() : func(NULL), backup(NULL), backup_count(0) {}
 2247     ~UDFCallInfo();
 2248 };
 2249 
 2250 
 2251 typedef BIF_DECL((* BuiltInFunctionType));
 2252 
 2253 class Func : public IObjectComCompatible
 2254 {
 2255 public:
 2256     LPTSTR mName;
 2257     union {BuiltInFunctionType mBIF; Line *mJumpToLine;};
 2258     FuncParam *mParam;  // Will hold an array of FuncParams.
 2259     int mParamCount; // The number of items in the above array.  This is also the function's maximum number of params.
 2260     int mMinParams;  // The number of mandatory parameters (populated for both UDFs and built-in's).
 2261     Object *mClass; // The class which this Func was defined in, if applicable.
 2262     Var **mVar, **mLazyVar; // Array of pointers-to-variable, allocated upon first use and later expanded as needed.
 2263     Var **mGlobalVar; // Array of global declarations.
 2264     int mVarCount, mVarCountMax, mLazyVarCount, mGlobalVarCount; // Count of items in the above array as well as the maximum capacity.
 2265     int mInstances; // How many instances currently exist on the call stack (due to recursion or thread interruption).  Future use: Might be used to limit how deep recursion can go to help prevent stack overflow.
 2266 
 2267     // Keep small members adjacent to each other to save space and improve perf. due to byte alignment:
 2268     UCHAR mDefaultVarType;
 2269     #define VAR_DECLARE_NONE   0
 2270     #define VAR_DECLARE_GLOBAL (VAR_DECLARED | VAR_GLOBAL)
 2271     #define VAR_DECLARE_SUPER_GLOBAL (VAR_DECLARE_GLOBAL | VAR_SUPER_GLOBAL)
 2272     #define VAR_DECLARE_LOCAL  (VAR_DECLARED | VAR_LOCAL)
 2273     #define VAR_DECLARE_STATIC (VAR_DECLARED | VAR_LOCAL | VAR_LOCAL_STATIC)
 2274     // The last two may be combined (bitwise-OR) with VAR_FORCE_LOCAL.
 2275 
 2276     bool mIsBuiltIn; // Determines contents of union. Keep this member adjacent/contiguous with the above.
 2277     // Note that it's possible for a built-in function such as WinExist() to become a normal/UDF via
 2278     // override in the script.  So mIsBuiltIn should always be used to determine whether the function
 2279     // is truly built-in, not its name.
 2280     bool mIsVariadic;
 2281 
 2282     bool Call(UDFCallInfo &aFuncCall, ResultType &aResult, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount, bool aIsVariadic = false);
 2283 
 2284     ResultType Call(ExprTokenType *aResultToken) // Making this a function vs. inline doesn't measurably impact performance.
 2285     {
 2286         if (aResultToken) // L31: Return value is returned via token rather than char** to support objects (and binary numbers as an added benefit).
 2287         {
 2288             // Init to default in case function doesn't return a value or it EXITs or fails.
 2289             aResultToken->symbol = SYM_STRING;
 2290             aResultToken->marker = _T("");
 2291         }
 2292         // Launch the function similar to Gosub (i.e. not as a new quasi-thread):
 2293         // The performance gain of conditionally passing NULL in place of result (when this is the
 2294         // outermost function call of a line consisting only of function calls, namely ACT_EXPRESSION)
 2295         // would not be significant because the Return command's expression (arg1) must still be evaluated
 2296         // in case it calls any functions that have side-effects, e.g. "return LogThisError()".
 2297         Func *prev_func = g->CurrentFunc; // This will be non-NULL when a function is called from inside another function.
 2298         g->CurrentFunc = this;
 2299         // Although a GOTO that jumps to a position outside of the function's body could be supported,
 2300         // it seems best not to for these reasons:
 2301         // 1) The extreme rarity of a legitimate desire to intentionally do so.
 2302         // 2) The fact that any return encountered after the Goto cannot provide a return value for
 2303         //    the function because load-time validation checks for this (it's preferable not to
 2304         //    give up this check, since it is an informative error message and might also help catch
 2305         //    bugs in the script).  Gosub does not suffer from this because the return that brings it
 2306         //    back into the function body belongs to the Gosub and not the function itself.
 2307         // 3) More difficult to maintain because we have handle jump_to_line the same way ExecUntil() does,
 2308         //    checking aResult the same way it does, then checking jump_to_line the same way it does, etc.
 2309         // Fix for v1.0.31.05: g->mLoopFile and the other g_script members that follow it are
 2310         // now passed to ExecUntil() for two reasons (update for v1.0.44.14: now they're implicitly "passed"
 2311         // because they're done via parameter anymore):
 2312         // 1) To fix the fact that any function call in one parameter of a command would reset
 2313         // A_Index and related variables so that if those variables are referenced in another
 2314         // parameter of the same command, they would be wrong.
 2315         // 2) So that the caller's value of A_Index and such will always be valid even inside
 2316         // of called functions (unless overridden/eclipsed by a loop in the body of the function),
 2317         // which seems to add flexibility without giving up anything.  This fix is necessary at least
 2318         // for a command that references A_Index in two of its args such as the following:
 2319         // ToolTip, O, ((cos(A_Index) * 500) + 500), A_Index
 2320         ++mInstances;
 2321 
 2322         ResultType result;
 2323         result = mJumpToLine->ExecUntil(UNTIL_BLOCK_END, aResultToken);
 2324 #ifdef CONFIG_DEBUGGER
 2325         if (g_Debugger.IsConnected())
 2326         {
 2327             if (result == EARLY_RETURN)
 2328             {
 2329                 // Find the end of this function.
 2330                 //Line *line;
 2331                 //for (line = mJumpToLine; line && (line->mActionType != ACT_BLOCK_END || !line->mAttribute); line = line->mNextLine);
 2332                 // Since mJumpToLine points at the first line *inside* the body, mJumpToLine->mPrevLine
 2333                 // is the block-begin.  That line's mRelatedLine is the line *after* the block-end, so
 2334                 // use it's mPrevLine.  mRelatedLine is guaranteed to be non-NULL by load-time logic.
 2335                 Line *line = mJumpToLine->mPrevLine->mRelatedLine->mPrevLine;
 2336                 // Give user the opportunity to inspect variables before returning.
 2337                 if (line)
 2338                     g_Debugger.PreExecLine(line);
 2339             }
 2340         }
 2341 #endif
 2342 
 2343         --mInstances;
 2344         // Restore the original value in case this function is called from inside another function.
 2345         // Due to the synchronous nature of recursion and recursion-collapse, this should keep
 2346         // g->CurrentFunc accurate, even amidst the asynchronous saving and restoring of "g" itself:
 2347         g->CurrentFunc = prev_func;
 2348         return result;
 2349     }
 2350 
 2351     // IObject.
 2352     ResultType STDMETHODCALLTYPE Invoke(ExprTokenType &aResultToken, ExprTokenType &aThisToken, int aFlags, ExprTokenType *aParam[], int aParamCount);
 2353     ULONG STDMETHODCALLTYPE AddRef() { return 1; }
 2354     ULONG STDMETHODCALLTYPE Release() { return 1; }
 2355     IObject_Type_Impl("Func")
 2356 #ifdef CONFIG_DEBUGGER
 2357     void DebugWriteProperty(IDebugProperties *, int aPage, int aPageSize, int aDepth);
 2358 #endif
 2359 
 2360     Func(LPTSTR aFuncName, bool aIsBuiltIn) // Constructor.
 2361         : mName(aFuncName) // Caller gave us a pointer to dynamic memory for this.
 2362         , mBIF(NULL)
 2363         , mParam(NULL), mParamCount(0), mMinParams(0)
 2364         , mClass(NULL)
 2365         , mVar(NULL), mVarCount(0), mVarCountMax(0), mLazyVar(NULL), mLazyVarCount(0)
 2366         , mGlobalVar(NULL), mGlobalVarCount(0)
 2367         , mInstances(0)
 2368         , mDefaultVarType(VAR_DECLARE_NONE)
 2369         , mIsBuiltIn(aIsBuiltIn)
 2370         , mIsVariadic(false)
 2371     {}
 2372     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2373     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
 2374     void operator delete(void *aPtr) {}
 2375     void operator delete[](void *aPtr) {}
 2376 };
 2377 
 2378 
 2379 class ExprOpFunc : public Func
 2380 {   // ExprOpFunc: Used in combination with SYM_FUNC to implement certain operations in expressions.
 2381     // These are not inserted into the script's function list, so mName is used only to pass a simple
 2382     // identifier to mBIF (currently only BIF_ObjInvoke).
 2383 public:
 2384     ExprOpFunc(BuiltInFunctionType aBIF, INT_PTR aID, int aMinParams = 1, int aParamCount = 1000)
 2385         : Func((LPTSTR)aID, true)
 2386     {
 2387         mBIF = aBIF;
 2388         mMinParams = aMinParams;    // These are only enforced in some cases.
 2389         mParamCount = aParamCount;  //
 2390     }
 2391 };
 2392 
 2393 
 2394 
 2395 class ScriptTimer
 2396 {
 2397 public:
 2398     LabelRef mLabel;
 2399     DWORD mPeriod; // v1.0.36.33: Changed from int to DWORD to double its capacity.
 2400     DWORD mTimeLastRun;  // TickCount
 2401     int mPriority;  // Thread priority relative to other threads, default 0.
 2402     UCHAR mExistingThreads;  // Whether this timer is already running its subroutine.
 2403     bool mEnabled;
 2404     bool mRunOnlyOnce;
 2405     ScriptTimer *mNextTimer;  // Next items in linked list
 2406     void ScriptTimer::Disable();
 2407     ScriptTimer(IObject *aLabel)
 2408         #define DEFAULT_TIMER_PERIOD 250
 2409         : mLabel(aLabel), mPeriod(DEFAULT_TIMER_PERIOD), mPriority(0) // Default is always 0.
 2410         , mExistingThreads(0), mTimeLastRun(0)
 2411         , mEnabled(false), mRunOnlyOnce(false), mNextTimer(NULL)  // Note that mEnabled must default to false for the counts to be right.
 2412     {}
 2413 };
 2414 
 2415 
 2416 
 2417 struct MsgMonitorStruct
 2418 {
 2419     IObject *func;
 2420     UINT msg;
 2421     // Keep any members smaller than 4 bytes adjacent to save memory:
 2422     static const UCHAR MAX_INSTANCES = MAX_THREADS_LIMIT; // For maintainability.  Causes a compiler warning if MAX_THREADS_LIMIT > MAX_UCHAR.
 2423     UCHAR instance_count; // Distinct from func.mInstances because the script might have called the function explicitly.
 2424     UCHAR max_instances; // v1.0.47: Support more than one thread.
 2425     bool is_legacy_monitor; // true if this is the backwards-compatible "singleton" monitor for this message.
 2426 };
 2427 
 2428 
 2429 struct MsgMonitorInstance;
 2430 class MsgMonitorList
 2431 {
 2432     MsgMonitorStruct *mMonitor;
 2433     MsgMonitorInstance *mTop;
 2434     int mCount, mCountMax;
 2435 
 2436     friend struct MsgMonitorInstance;
 2437 
 2438 public:
 2439     MsgMonitorStruct *Find(UINT aMsg, IObject *aCallback, bool aIsLegacyMode);
 2440     MsgMonitorStruct *Add(UINT aMsg, IObject *aCallback, bool aIsLegacyMode, bool aAppend = TRUE);
 2441     void Remove(MsgMonitorStruct *aMonitor);
 2442     ResultType Call(ExprTokenType *aParamValue, int aParamCount, int aInitNewThreadIndex); // Used for OnExit and OnClipboardChange, but not OnMessage.
 2443 
 2444     MsgMonitorStruct& operator[] (const int aIndex) { return mMonitor[aIndex]; }
 2445     int Count() { return mCount; }
 2446 
 2447     MsgMonitorList() : mCount(0), mCountMax(0), mMonitor(NULL) {}
 2448 };
 2449 
 2450 
 2451 struct MsgMonitorInstance
 2452 {
 2453     MsgMonitorList &list;
 2454     MsgMonitorInstance *previous;
 2455     int index;
 2456     int count;
 2457 
 2458     MsgMonitorInstance(MsgMonitorList &aList)
 2459         : list(aList), previous(aList.mTop), index(0), count(aList.mCount)
 2460     {
 2461         aList.mTop = this;
 2462     }
 2463 
 2464     ~MsgMonitorInstance()
 2465     {
 2466         list.mTop = previous;
 2467     }
 2468 };
 2469 
 2470 
 2471 
 2472 #define MAX_MENU_NAME_LENGTH MAX_PATH // For both menu and menu item names.
 2473 class UserMenuItem;  // Forward declaration since classes use each other (i.e. a menu *item* can have a submenu).
 2474 class UserMenu
 2475 {
 2476 public:
 2477     LPTSTR mName;  // Dynamically allocated.
 2478     UserMenuItem *mFirstMenuItem, *mLastMenuItem, *mDefault;
 2479     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
 2480     // due to byte-alignment:
 2481     bool mIncludeStandardItems;
 2482     int mClickCount; // How many clicks it takes to trigger the default menu item.  2 = double-click
 2483     UINT mMenuItemCount;  // The count of user-defined menu items (doesn't include the standard items, if present).
 2484     UserMenu *mNextMenu;  // Next item in linked list
 2485     HMENU mMenu;
 2486     MenuTypeType mMenuType; // MENU_TYPE_POPUP (via CreatePopupMenu) vs. MENU_TYPE_BAR (via CreateMenu).
 2487     HBRUSH mBrush;   // Background color to apply to menu.
 2488     COLORREF mColor; // The color that corresponds to the above.
 2489 
 2490     // Don't overload new and delete operators in this case since we want to use real dynamic memory
 2491     // (since menus can be read in from a file, destroyed and recreated, over and over).
 2492 
 2493     UserMenu(LPTSTR aName) // Constructor
 2494         : mName(aName), mFirstMenuItem(NULL), mLastMenuItem(NULL), mDefault(NULL)
 2495         , mIncludeStandardItems(false), mClickCount(2), mMenuItemCount(0), mNextMenu(NULL), mMenu(NULL)
 2496         , mMenuType(MENU_TYPE_POPUP) // The MENU_TYPE_NONE flag is not used in this context.  Default = POPUP.
 2497         , mBrush(NULL), mColor(CLR_DEFAULT)
 2498     {
 2499     }
 2500 
 2501     ResultType AddItem(LPTSTR aName, UINT aMenuID, IObject *aLabel, UserMenu *aSubmenu, LPTSTR aOptions, UserMenuItem **aInsertAt);
 2502     ResultType InternalAppendMenu(UserMenuItem *aMenuItem, UserMenuItem *aInsertBefore = NULL);
 2503     ResultType DeleteItem(UserMenuItem *aMenuItem, UserMenuItem *aMenuItemPrev);
 2504     ResultType DeleteAllItems();
 2505     ResultType ModifyItem(UserMenuItem *aMenuItem, IObject *aLabel, UserMenu *aSubmenu, LPTSTR aOptions);
 2506     void UpdateOptions(UserMenuItem *aMenuItem, LPTSTR aOptions);
 2507     ResultType RenameItem(UserMenuItem *aMenuItem, LPTSTR aNewName);
 2508     ResultType UpdateName(UserMenuItem *aMenuItem, LPTSTR aNewName);
 2509     ResultType SetItemState(UserMenuItem *aMenuItem, UINT aState, UINT aStateMask);
 2510     ResultType CheckItem(UserMenuItem *aMenuItem);
 2511     ResultType UncheckItem(UserMenuItem *aMenuItem);
 2512     ResultType ToggleCheckItem(UserMenuItem *aMenuItem);
 2513     ResultType EnableItem(UserMenuItem *aMenuItem);
 2514     ResultType DisableItem(UserMenuItem *aMenuItem);
 2515     ResultType ToggleEnableItem(UserMenuItem *aMenuItem);
 2516     ResultType SetDefault(UserMenuItem *aMenuItem = NULL);
 2517     ResultType IncludeStandardItems();
 2518     ResultType ExcludeStandardItems();
 2519     ResultType Create(MenuTypeType aMenuType = MENU_TYPE_NONE); // NONE means UNSPECIFIED in this context.
 2520     void SetColor(LPTSTR aColorName, bool aApplyToSubmenus);
 2521     void ApplyColor(bool aApplyToSubmenus);
 2522     ResultType AppendStandardItems();
 2523     ResultType Destroy();
 2524     ResultType Display(bool aForceToForeground = true, int aX = COORD_UNSPECIFIED, int aY = COORD_UNSPECIFIED);
 2525     UserMenuItem *FindItem(LPTSTR aNameOrPos, UserMenuItem *&aPrevItem, bool &aByPos);
 2526     UINT GetSubmenuPos(HMENU ahMenu);
 2527     UINT GetItemPos(LPTSTR aMenuItemName);
 2528     bool ContainsMenu(UserMenu *aMenu);
 2529     void UpdateAccelerators();
 2530     // L17: Functions for menu icons.
 2531     ResultType SetItemIcon(UserMenuItem *aMenuItem, LPTSTR aFilename, int aIconNumber, int aWidth);
 2532     ResultType ApplyItemIcon(UserMenuItem *aMenuItem);
 2533     ResultType RemoveItemIcon(UserMenuItem *aMenuItem);
 2534     static BOOL OwnerMeasureItem(LPMEASUREITEMSTRUCT aParam);
 2535     static BOOL OwnerDrawItem(LPDRAWITEMSTRUCT aParam);
 2536 };
 2537 
 2538 
 2539 
 2540 class UserMenuItem
 2541 {
 2542 public:
 2543     LPTSTR mName;  // Dynamically allocated.
 2544     size_t mNameCapacity;
 2545     LabelRef mLabel;
 2546     UserMenu *mSubmenu;
 2547     UserMenu *mMenu;  // The menu to which this item belongs.  Needed to support script var A_ThisMenu.
 2548     UINT mMenuID;
 2549     int mPriority;
 2550     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
 2551     // due to byte-alignment:
 2552     WORD mMenuState;
 2553     WORD mMenuType;
 2554     UserMenuItem *mNextMenuItem;  // Next item in linked list
 2555     
 2556     union
 2557     {
 2558         // L17: Implementation of menu item icons is OS-dependent (g_os.IsWinVistaOrLater()).
 2559         
 2560         // Older versions of Windows do not support alpha channels in menu item bitmaps, so owner-drawing
 2561         // must be used for icons with transparent backgrounds to appear correctly. Owner-drawing also
 2562         // prevents the icon colours from inverting when the item is selected. DrawIcon() gives the best
 2563         // results, so we store the icon handle as is.
 2564         //
 2565         HICON mIcon;
 2566         
 2567         // Windows Vista and later support alpha channels via 32-bit bitmaps. Since owner-drawing prevents
 2568         // visual styles being applied to menus, we convert each icon to a 32-bit bitmap, calculating the
 2569         // alpha channel as necessary. This is done only once, when the icon is initially set.
 2570         //
 2571         HBITMAP mBitmap;
 2572     };
 2573 
 2574     // Constructor:
 2575     UserMenuItem(LPTSTR aName, size_t aNameCapacity, UINT aMenuID, IObject *aLabel, UserMenu *aSubmenu, UserMenu *aMenu);
 2576 
 2577     // Don't overload new and delete operators in this case since we want to use real dynamic memory
 2578     // (since menus can be read in from a file, destroyed and recreated, over and over).
 2579 };
 2580 
 2581 
 2582 
 2583 struct FontType
 2584 {
 2585     #define MAX_FONT_NAME_LENGTH 63  // Longest name I've seen is 29 chars, "Franklin Gothic Medium Italic". Anyway, there's protection against overflow.
 2586     TCHAR name[MAX_FONT_NAME_LENGTH + 1];
 2587     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
 2588     // due to byte-alignment:
 2589     bool italic;
 2590     bool underline;
 2591     bool strikeout;
 2592     int point_size; // Decided to use int vs. float to simplify the code in many places. Fractional sizes seem rarely needed.
 2593     int weight;
 2594     DWORD quality; // L19: Allow control over font quality (anti-aliasing, etc.).
 2595     HFONT hfont;
 2596 };
 2597 
 2598 #define LV_REMOTE_BUF_SIZE 1024  // 8192 (below) seems too large in hindsight, given that an LV can only display the first 260 chars in a field.
 2599 #define LV_TEXT_BUF_SIZE 8192  // Max amount of text in a ListView sub-item.  Somewhat arbitrary: not sure what the real limit is, if any.
 2600 enum LVColTypes {LV_COL_TEXT, LV_COL_INTEGER, LV_COL_FLOAT}; // LV_COL_TEXT must be zero so that it's the default with ZeroMemory.
 2601 struct lv_col_type
 2602 {
 2603     UCHAR type;             // UCHAR vs. enum LVColTypes to save memory.
 2604     bool sort_disabled;     // If true, clicking the column will have no automatic sorting effect.
 2605     UCHAR case_sensitive;   // Ignored if type isn't LV_COL_TEXT.  SCS_INSENSITIVE is the default.
 2606     bool unidirectional;    // Sorting cannot be reversed/toggled.
 2607     bool prefer_descending; // Whether this column defaults to descending order (on first click or for unidirectional).
 2608 };
 2609 
 2610 struct lv_attrib_type
 2611 {
 2612     int sorted_by_col; // Index of column by which the control is currently sorted (-1 if none).
 2613     bool is_now_sorted_ascending; // The direction in which the above column is currently sorted.
 2614     bool no_auto_sort; // Automatic sorting disabled.
 2615     #define LV_MAX_COLUMNS 200
 2616     lv_col_type col[LV_MAX_COLUMNS];
 2617     int col_count; // Number of columns currently in the above array.
 2618     int row_count_hint;
 2619 };
 2620 
 2621 typedef UCHAR TabControlIndexType;
 2622 typedef UCHAR TabIndexType;
 2623 // Keep the below in sync with the size of the types above:
 2624 #define MAX_TAB_CONTROLS 255  // i.e. the value 255 itself is reserved to mean "doesn't belong to a tab".
 2625 #define MAX_TABS_PER_CONTROL 256
 2626 struct GuiControlType
 2627 {
 2628     HWND hwnd;
 2629     // Keep any fields that are smaller than 4 bytes adjacent to each other.  This conserves memory
 2630     // due to byte-alignment.  It has been verified to save 4 bytes per struct in this case:
 2631     GuiControls type;
 2632     #define GUI_CONTROL_ATTRIB_IMPLICIT_CANCEL     0x01
 2633     #define GUI_CONTROL_ATTRIB_ALTSUBMIT           0x02
 2634     #define GUI_CONTROL_ATTRIB_LABEL_IS_RUNNING    0x04
 2635     #define GUI_CONTROL_ATTRIB_EXPLICITLY_HIDDEN   0x08
 2636     #define GUI_CONTROL_ATTRIB_EXPLICITLY_DISABLED 0x10
 2637     #define GUI_CONTROL_ATTRIB_BACKGROUND_DEFAULT  0x20 // i.e. Don't conform to window/control background color; use default instead.
 2638     #define GUI_CONTROL_ATTRIB_BACKGROUND_TRANS    0x40 // i.e. Leave this control's background transparent.
 2639     #define GUI_CONTROL_ATTRIB_ALTBEHAVIOR         0x80 // For sliders: Reverse/Invert the value. Also for up-down controls (ALT means 32-bit vs. 16-bit). Also for ListView and Tab, and for Edit.
 2640     UCHAR attrib; // A field of option flags/bits defined above.
 2641     TabControlIndexType tab_control_index; // Which tab control this control belongs to, if any.
 2642     TabIndexType tab_index; // For type==TAB, this stores the tab control's index.  For other types, it stores the page.
 2643     Var *output_var;
 2644     LabelRef jump_to_label;
 2645     union
 2646     {
 2647         COLORREF union_color;  // Color of the control's text.
 2648         HBITMAP union_hbitmap; // For PIC controls, stores the bitmap.
 2649         // Note: Pic controls cannot obey the text color, but they can obey the window's background
 2650         // color if the picture's background is transparent (at least in the case of icons on XP).
 2651         lv_attrib_type *union_lv_attrib; // For ListView: Some attributes and an array of columns.
 2652     };
 2653     #define USES_FONT_AND_TEXT_COLOR(type) !(type == GUI_CONTROL_PIC || type == GUI_CONTROL_UPDOWN \
 2654         || type == GUI_CONTROL_SLIDER || type == GUI_CONTROL_PROGRESS)
 2655 };
 2656 
 2657 struct GuiControlOptionsType
 2658 {
 2659     DWORD style_add, style_remove, exstyle_add, exstyle_remove, listview_style;
 2660     int listview_view; // Viewing mode, such as LVS_ICON, LVS_REPORT.  Int vs. DWORD to more easily use any negative value as "invalid".
 2661     HIMAGELIST himagelist;
 2662     Var *hwnd_output_var; // v1.0.46.01: Allows a script to retrieve the control's HWND upon creation of control.
 2663     int x, y, width, height;  // Position info.
 2664     float row_count;
 2665     int choice;  // Which item of a DropDownList/ComboBox/ListBox to initially choose.
 2666     int range_min, range_max;  // Allowable range, such as for a slider control.
 2667     int tick_interval; // The interval at which to draw tickmarks for a slider control.
 2668     int line_size, page_size; // Also for slider.
 2669     int thickness;  // Thickness of slider's thumb.
 2670     int tip_side; // Which side of the control to display the tip on (0 to use default side).
 2671     GuiControlType *buddy1, *buddy2;
 2672     COLORREF color_listview; // Used only for those controls that need control.union_color for something other than color.
 2673     COLORREF color_bk; // Control's background color.
 2674     int limit;   // The max number of characters to permit in an edit or combobox's edit (also used by ListView).
 2675     int hscroll_pixels;  // The number of pixels for a listbox's horizontal scrollbar to be able to scroll.
 2676     int checked; // When zeroed, struct contains default starting state of checkbox/radio, i.e. BST_UNCHECKED.
 2677     int icon_number; // Which icon of a multi-icon file to use.  Zero means use-default, i.e. the first icon.
 2678     #define GUI_MAX_TABSTOPS 50
 2679     UINT tabstop[GUI_MAX_TABSTOPS]; // Array of tabstops for the interior of a multi-line edit control.
 2680     UINT tabstop_count;  // The number of entries in the above array.
 2681     SYSTEMTIME sys_time[2]; // Needs to support 2 elements for MONTHCAL's multi/range mode.
 2682     SYSTEMTIME sys_time_range[2];
 2683     DWORD gdtr, gdtr_range; // Used in connection with sys_time and sys_time_range.
 2684     ResultType redraw;  // Whether the state of WM_REDRAW should be changed.
 2685     TCHAR password_char; // When zeroed, indicates "use default password" for an edit control with the password style.
 2686     bool range_changed;
 2687     bool color_changed; // To discern when a control has been put back to the default color. [v1.0.26]
 2688     bool tick_interval_changed, tick_interval_specified;
 2689     bool start_new_section;
 2690     bool use_theme; // v1.0.32: Provides the means for the window's current setting of mUseTheme to be overridden.
 2691     bool listview_no_auto_sort; // v1.0.44: More maintainable and frees up GUI_CONTROL_ATTRIB_ALTBEHAVIOR for other uses.
 2692     bool tab_control_uses_dialog;
 2693     #define TAB3_AUTOWIDTH 1
 2694     #define TAB3_AUTOHEIGHT 2
 2695     CHAR tab_control_autosize;
 2696     ATOM customClassAtom;
 2697 };
 2698 
 2699 LRESULT CALLBACK GuiWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
 2700 LRESULT CALLBACK TabWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
 2701 
 2702 class GuiType
 2703 {
 2704 public:
 2705     #define GUI_STANDARD_WIDTH_MULTIPLIER 15 // This times font size = width, if all other means of determining it are exhausted.
 2706     #define GUI_STANDARD_WIDTH DPIScale(GUI_STANDARD_WIDTH_MULTIPLIER * sFont[mCurrentFontIndex].point_size)
 2707     // Update for v1.0.21: Reduced it to 8 vs. 9 because 8 causes the height each edit (with the
 2708     // default style) to exactly match that of a Combo or DropDownList.  This type of spacing seems
 2709     // to be what other apps use too, and seems to make edits stand out a little nicer:
 2710     #define GUI_CTL_VERTICAL_DEADSPACE DPIScale(8)
 2711     #define PROGRESS_DEFAULT_THICKNESS DPIScale(2 * sFont[mCurrentFontIndex].point_size)
 2712     LPTSTR mName;
 2713     HWND mHwnd, mStatusBarHwnd;
 2714     HWND mOwner;  // The window that owns this one, if any.  Note that Windows provides no way to change owners after window creation.
 2715     // Control IDs are higher than their index in the array by the below amount.  This offset is
 2716     // necessary because windows that behave like dialogs automatically return IDOK and IDCANCEL in
 2717     // response to certain types of standard actions:
 2718     GuiIndexType mControlCount;
 2719     GuiIndexType mControlCapacity; // How many controls can fit into the current memory size of mControl.
 2720     GuiControlType *mControl; // Will become an array of controls when the window is first created.
 2721     GuiIndexType mDefaultButtonIndex; // Index vs. pointer is needed for some things.
 2722     ULONG mReferenceCount; // For keeping this structure in memory during execution of the Gui's labels.
 2723     LabelPtr mLabelForClose, mLabelForEscape, mLabelForSize, mLabelForDropFiles, mLabelForContextMenu; // These aren't reference counted, as they can only be a Func or Label, not a dynamic object.
 2724     bool mLabelForCloseIsRunning, mLabelForEscapeIsRunning, mLabelForSizeIsRunning; // DropFiles doesn't need one of these.
 2725     bool mLabelsHaveBeenSet;
 2726     DWORD mStyle, mExStyle; // Style of window.
 2727     bool mInRadioGroup; // Whether the control currently being created is inside a prior radio-group.
 2728     bool mUseTheme;  // Whether XP theme and styles should be applied to the parent window and subsequently added controls.
 2729     TCHAR mDelimiter;  // The default field delimiter when adding items to ListBox, DropDownList, ListView, etc.
 2730     GuiControlType *mCurrentListView, *mCurrentTreeView; // The ListView and TreeView upon which the LV/TV functions operate.
 2731     int mCurrentFontIndex;
 2732     COLORREF mCurrentColor;       // The default color of text in controls.
 2733     COLORREF mBackgroundColorWin; // The window's background color itself.
 2734     COLORREF mBackgroundColorCtl; // Background color for controls.
 2735     HBRUSH mBackgroundBrushWin;   // Brush corresponding to mBackgroundColorWin.
 2736     HBRUSH mBackgroundBrushCtl;   // Brush corresponding to mBackgroundColorCtl.
 2737     HDROP mHdrop;                 // Used for drag and drop operations.
 2738     HICON mIconEligibleForDestruction; // The window's icon, which can be destroyed when the window is destroyed if nothing else is using it.
 2739     HICON mIconEligibleForDestructionSmall; // L17: A window may have two icons: ICON_SMALL and ICON_BIG.
 2740     HACCEL mAccel; // Keyboard accelerator table.
 2741     int mMarginX, mMarginY, mPrevX, mPrevY, mPrevWidth, mPrevHeight, mMaxExtentRight, mMaxExtentDown
 2742         , mSectionX, mSectionY, mMaxExtentRightSection, mMaxExtentDownSection;
 2743     LONG mMinWidth, mMinHeight, mMaxWidth, mMaxHeight;
 2744     TabControlIndexType mTabControlCount;
 2745     TabControlIndexType mCurrentTabControlIndex; // Which tab control of the window.
 2746     TabIndexType mCurrentTabIndex;// Which tab of a tab control is currently the default for newly added controls.
 2747     bool mGuiShowHasNeverBeenDone, mFirstActivation, mShowIsInProgress, mDestroyWindowHasBeenCalled;
 2748     bool mControlWidthWasSetByContents; // Whether the most recently added control was auto-width'd to fit its contents.
 2749     bool mUsesDPIScaling; // Whether the GUI uses DPI scaling.
 2750     bool mIsMinimized; // Workaround for bad OS behaviour; see "case WM_SETFOCUS".
 2751 
 2752     #define MAX_GUI_FONTS 200  // v1.0.44.14: Increased from 100 to 200 due to feedback that 100 wasn't enough.  But to alleviate memory usage, the array is now allocated upon first use.
 2753     static FontType *sFont; // An array of structs, allocated upon first use.
 2754     static int sFontCount;
 2755     static HWND sTreeWithEditInProgress; // Needed because TreeView's edit control for label-editing conflicts with IDOK (default button).
 2756 
 2757     // Don't overload new and delete operators in this case since we want to use real dynamic memory
 2758     // (since GUIs can be destroyed and recreated, over and over).
 2759 
 2760     // Keep the default destructor to avoid entering the "Law of the Big Three": If your class requires a
 2761     // copy constructor, copy assignment operator, or a destructor, then it very likely will require all three.
 2762 
 2763     GuiType() // Constructor
 2764         : mName(NULL), mHwnd(NULL), mStatusBarHwnd(NULL), mControlCount(0), mControlCapacity(0)
 2765         , mDefaultButtonIndex(-1), mLabelForClose(NULL), mLabelForEscape(NULL), mLabelForSize(NULL)
 2766         , mLabelForDropFiles(NULL), mLabelForContextMenu(NULL), mReferenceCount(1)
 2767         , mLabelForCloseIsRunning(false), mLabelForEscapeIsRunning(false), mLabelForSizeIsRunning(false)
 2768         , mLabelsHaveBeenSet(false), mUsesDPIScaling(true)
 2769         // The styles DS_CENTER and DS_3DLOOK appear to be ineffectual in this case.
 2770         // Also note that WS_CLIPSIBLINGS winds up on the window even if unspecified, which is a strong hint
 2771         // that it should always be used for top level windows across all OSes.  Usenet posts confirm this.
 2772         // Also, it seems safer to have WS_POPUP under a vague feeling that it seems to apply to dialog
 2773         // style windows such as this one, and the fact that it also allows the window's caption to be
 2774         // removed, which implies that POPUP windows are more flexible than OVERLAPPED windows.
 2775         , mStyle(WS_POPUP|WS_CLIPSIBLINGS|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX) // WS_CLIPCHILDREN (doesn't seem helpful currently)
 2776         , mExStyle(0) // This and the above should not be used once the window has been created since they might get out of date.
 2777         , mInRadioGroup(false), mUseTheme(true), mOwner(NULL), mDelimiter('|')
 2778         , mCurrentFontIndex(FindOrCreateFont()) // Must call this in constructor to ensure sFont array is never empty while a GUI object exists.  Omit params to tell it to find or create DEFAULT_GUI_FONT.
 2779         , mCurrentListView(NULL), mCurrentTreeView(NULL)
 2780         , mTabControlCount(0), mCurrentTabControlIndex(MAX_TAB_CONTROLS), mCurrentTabIndex(0)
 2781         , mCurrentColor(CLR_DEFAULT)
 2782         , mBackgroundColorWin(CLR_DEFAULT), mBackgroundBrushWin(NULL)
 2783         , mBackgroundColorCtl(CLR_DEFAULT), mBackgroundBrushCtl(NULL)
 2784         , mHdrop(NULL), mIconEligibleForDestruction(NULL), mIconEligibleForDestructionSmall(NULL)
 2785         , mAccel(NULL)
 2786         , mMarginX(COORD_UNSPECIFIED), mMarginY(COORD_UNSPECIFIED) // These will be set when the first control is added.
 2787         , mPrevX(0), mPrevY(0)
 2788         , mPrevWidth(0), mPrevHeight(0) // Needs to be zero for first control to start off at right offset.
 2789         , mMaxExtentRight(0), mMaxExtentDown(0)
 2790         , mSectionX(COORD_UNSPECIFIED), mSectionY(COORD_UNSPECIFIED)
 2791         , mMaxExtentRightSection(COORD_UNSPECIFIED), mMaxExtentDownSection(COORD_UNSPECIFIED)
 2792         , mMinWidth(COORD_UNSPECIFIED), mMinHeight(COORD_UNSPECIFIED)
 2793         , mMaxWidth(COORD_UNSPECIFIED), mMaxHeight(COORD_UNSPECIFIED)
 2794         , mGuiShowHasNeverBeenDone(true), mFirstActivation(true), mShowIsInProgress(false)
 2795         , mDestroyWindowHasBeenCalled(false), mControlWidthWasSetByContents(false)
 2796     {
 2797         // The array of controls is left uninitialized to catch bugs.  Each control's attributes should be
 2798         // fully populated when it is created.
 2799         //ZeroMemory(mControl, sizeof(mControl));
 2800     }
 2801 
 2802     static ResultType Destroy(GuiType &gui);
 2803     static void DestroyIconsIfUnused(HICON ahIcon, HICON ahIconSmall); // L17: Renamed function and added parameter to also handle the window's small icon.
 2804     ResultType Create();
 2805     void AddRef();
 2806     void Release();
 2807     void SetLabels(LPTSTR aLabelPrefix);
 2808     static LPTSTR ConvertEvent(GuiEventType evt);
 2809     static IObject* CreateDropArray(HDROP hDrop);
 2810     static void UpdateMenuBars(HMENU aMenu);
 2811     ResultType AddControl(GuiControls aControlType, LPTSTR aOptions, LPTSTR aText);
 2812 
 2813     ResultType ParseOptions(LPTSTR aOptions, bool &aSetLastFoundWindow, ToggleValueType &aOwnDialogs, Var *&aHwndVar);
 2814     void GetNonClientArea(LONG &aWidth, LONG &aHeight);
 2815     void GetTotalWidthAndHeight(LONG &aWidth, LONG &aHeight);
 2816 
 2817     ResultType ControlParseOptions(LPTSTR aOptions, GuiControlOptionsType &aOpt, GuiControlType &aControl
 2818         , GuiIndexType aControlIndex = -1, Var *aParam3Var = NULL); // aControlIndex is not needed upon control creation.
 2819     void ControlInitOptions(GuiControlOptionsType &aOpt, GuiControlType &aControl);
 2820     void ControlAddContents(GuiControlType &aControl, LPTSTR aContent, int aChoice, GuiControlOptionsType *aOpt = NULL);
 2821     ResultType ControlLoadPicture(GuiControlType &aControl, LPTSTR aFilename, int aWidth, int aHeight, int aIconNumber);
 2822     ResultType Show(LPTSTR aOptions, LPTSTR aTitle);
 2823     ResultType Clear();
 2824     ResultType Cancel();
 2825     ResultType Close(); // Due to SC_CLOSE, etc.
 2826     ResultType Escape(); // Similar to close, except typically called when the user presses ESCAPE.
 2827     ResultType Submit(bool aHideIt);
 2828     ResultType ControlGetContents(Var &aOutputVar, GuiControlType &aControl, LPTSTR aMode = _T(""));
 2829 
 2830     static VarSizeType ControlGetName(GuiType *aGuiWindow, GuiIndexType aControlIndex, LPTSTR aBuf);
 2831     
 2832     static GuiType *FindGui(LPTSTR aName);
 2833     static GuiType *FindGui(HWND aHwnd);
 2834     static GuiType *FindGuiParent(HWND aHwnd);
 2835 
 2836     static GuiType *ValidGui(GuiType *&aGuiRef); // Updates aGuiRef if it points to a destroyed Gui.
 2837 
 2838     GuiIndexType FindControl(LPTSTR aControlID);
 2839     GuiIndexType FindControlIndex(HWND aHwnd)
 2840     {
 2841         GuiIndexType index = GUI_HWND_TO_INDEX(aHwnd); // Retrieves a small negative on failure, which will be out of bounds when converted to unsigned.
 2842         if (index >= mControlCount) // Not found yet; try again with parent.
 2843         {
 2844             // Since ComboBoxes (and possibly other future control types) have children, try looking
 2845             // up aHwnd's parent to see if its a known control of this dialog.  Some callers rely on us making
 2846             // this extra effort:
 2847             if (aHwnd = GetParent(aHwnd)) // Note that a ComboBox's drop-list (class ComboLBox) is apparently a direct child of the desktop, so this won't help us in that case.
 2848                 index = GUI_HWND_TO_INDEX(aHwnd); // Retrieves a small negative on failure, which will be out of bounds when converted to unsigned.
 2849         }
 2850         if (index < mControlCount && mControl[index].hwnd == aHwnd) // A match was found.  Fix for v1.1.09.03: Confirm it is actually one of our controls.
 2851             return index;
 2852         else // No match, so indicate failure.
 2853             return NO_CONTROL_INDEX;
 2854     }
 2855     GuiControlType *FindControl(HWND aHwnd)
 2856     {
 2857         GuiIndexType index = FindControlIndex(aHwnd);
 2858         return index == NO_CONTROL_INDEX ? NULL : mControl + index;
 2859     }
 2860 
 2861     int FindGroup(GuiIndexType aControlIndex, GuiIndexType &aGroupStart, GuiIndexType &aGroupEnd);
 2862 
 2863     ResultType SetCurrentFont(LPTSTR aOptions, LPTSTR aFontName);
 2864     static int FindOrCreateFont(LPTSTR aOptions = _T(""), LPTSTR aFontName = _T(""), FontType *aFoundationFont = NULL
 2865         , COLORREF *aColor = NULL);
 2866     static int FindFont(FontType &aFont);
 2867 
 2868     void Event(GuiIndexType aControlIndex, UINT aNotifyCode, USHORT aGuiEvent = GUI_EVENT_NONE, UINT_PTR aEventInfo = 0);
 2869     LRESULT CustomCtrlWmNotify(GuiIndexType aControlIndex, LPNMHDR aNmHdr);
 2870 
 2871     static WORD TextToHotkey(LPTSTR aText);
 2872     static LPTSTR HotkeyToText(WORD aHotkey, LPTSTR aBuf);
 2873     void ControlCheckRadioButton(GuiControlType &aControl, GuiIndexType aControlIndex, WPARAM aCheckType);
 2874     void ControlSetUpDownOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
 2875     int ControlGetDefaultSliderThickness(DWORD aStyle, int aThumbThickness);
 2876     void ControlSetSliderOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
 2877     int ControlInvertSliderIfNeeded(GuiControlType &aControl, int aPosition);
 2878     void ControlSetListViewOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
 2879     void ControlSetTreeViewOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
 2880     void ControlSetProgressOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt, DWORD aStyle);
 2881     bool ControlOverrideBkColor(GuiControlType &aControl);
 2882 
 2883     void ControlUpdateCurrentTab(GuiControlType &aTabControl, bool aFocusFirstControl);
 2884     GuiControlType *FindTabControl(TabControlIndexType aTabControlIndex);
 2885     int FindTabIndexByName(GuiControlType &aTabControl, LPTSTR aName, bool aExactMatch = false);
 2886     int GetControlCountOnTabPage(TabControlIndexType aTabControlIndex, TabIndexType aTabIndex);
 2887     void GetTabDisplayAreaRect(HWND aTabControlHwnd, RECT &aRect);
 2888     POINT GetPositionOfTabDisplayArea(GuiControlType &aTabControl);
 2889     ResultType SelectAdjacentTab(GuiControlType &aTabControl, bool aMoveToRight, bool aFocusFirstControl
 2890         , bool aWrapAround);
 2891     void AutoSizeTabControl(GuiControlType &aTabControl);
 2892     ResultType CreateTabDialog(GuiControlType &aTabControl, GuiControlOptionsType &aOpt);
 2893     void UpdateTabDialog(HWND aTabControlHwnd);
 2894     void ControlGetPosOfFocusedItem(GuiControlType &aControl, POINT &aPoint);
 2895     static void LV_Sort(GuiControlType &aControl, int aColumnIndex, bool aSortOnlyIfEnabled, TCHAR aForceDirection = '\0');
 2896     static DWORD ControlGetListViewMode(HWND aWnd);
 2897     static IObject *ControlGetActiveX(HWND aWnd);
 2898     
 2899     void UpdateAccelerators(UserMenu &aMenu);
 2900     void UpdateAccelerators(UserMenu &aMenu, LPACCEL aAccel, int &aAccelCount);
 2901     void RemoveAccelerators();
 2902     static bool ConvertAccelerator(LPTSTR aString, ACCEL &aAccel);
 2903 
 2904     // See DPIScale() and DPIUnscale() for more details.
 2905     int Scale(int x) { return mUsesDPIScaling ? DPIScale(x) : x; }
 2906     int Unscale(int x) { return mUsesDPIScaling ? DPIUnscale(x) : x; }
 2907     // The following is a workaround for the "w-1" and "h-1" options:
 2908     int ScaleSize(int x) { return mUsesDPIScaling && x != -1 ? DPIScale(x) : x; }
 2909 };
 2910 
 2911 
 2912 
 2913 class Script
 2914 {
 2915 private:
 2916     friend class Hotkey;
 2917 #ifdef CONFIG_DEBUGGER
 2918     friend class Debugger;
 2919 #endif
 2920 
 2921     Line *mFirstLine, *mLastLine;     // The first and last lines in the linked list.
 2922     Line *mFirstStaticLine, *mLastStaticLine; // The first and last static var initializer.
 2923     Label *mFirstLabel, *mLastLabel;  // The first and last labels in the linked list.
 2924     Func **mFunc;  // Binary-searchable array of functions.
 2925     int mFuncCount, mFuncCountMax;
 2926     Var **mVar, **mLazyVar; // Array of pointers-to-variable, allocated upon first use and later expanded as needed.
 2927     int mVarCount, mVarCountMax, mLazyVarCount; // Count of items in the above array as well as the maximum capacity.
 2928     WinGroup *mFirstGroup, *mLastGroup;  // The first and last variables in the linked list.
 2929     Line *mOpenBlock; // While loading the script, this is the beginning of a block which is currently open.
 2930     int mCurrentFuncOpenBlockCount; // While loading the script, this is how many blocks are currently open in the current function's body.
 2931     bool mNextLineIsFunctionBody; // Whether the very next line to be added will be the first one of the body.
 2932     bool mNoUpdateLabels;
 2933 
 2934 #define MAX_NESTED_CLASSES 5
 2935 #define MAX_CLASS_NAME_LENGTH UCHAR_MAX
 2936     int mClassObjectCount;
 2937     Object *mClassObject[MAX_NESTED_CLASSES]; // Class definition currently being parsed.
 2938     TCHAR mClassName[MAX_CLASS_NAME_LENGTH + 1]; // Only used during load-time.
 2939     Object *mUnresolvedClasses;
 2940     Property *mClassProperty;
 2941     LPTSTR mClassPropertyDef;
 2942 
 2943     // These two track the file number and line number in that file of the line currently being loaded,
 2944     // which simplifies calls to ScriptError() and LineError() (reduces the number of params that must be passed).
 2945     // These are used ONLY while loading the script into memory.  After that (while the script is running),
 2946     // only mCurrLine is kept up-to-date:
 2947     int mCurrFileIndex;
 2948     LineNumberType mCombinedLineNumber; // In the case of a continuation section/line(s), this is always the top line.
 2949 
 2950     bool mNoHotkeyLabels;
 2951     bool mMenuUseErrorLevel;  // Whether runtime errors should be displayed by the Menu command, vs. ErrorLevel.
 2952 
 2953     #define UPDATE_TIP_FIELD tcslcpy(mNIC.szTip, (mTrayIconTip && *mTrayIconTip) ? mTrayIconTip \
 2954         : (mFileName ? mFileName : T_AHK_NAME), _countof(mNIC.szTip));
 2955     NOTIFYICONDATA mNIC; // For ease of adding and deleting our tray icon.
 2956 
 2957     size_t GetLine(LPTSTR aBuf, int aMaxCharsToRead, int aInContinuationSection, TextStream *ts);
 2958     ResultType IsDirective(LPTSTR aBuf);
 2959     ResultType ParseAndAddLine(LPTSTR aLineText, ActionTypeType aActionType = ACT_INVALID
 2960         , ActionTypeType aOldActionType = OLD_INVALID, LPTSTR aActionName = NULL
 2961         , LPTSTR aEndMarker = NULL, LPTSTR aLiteralMap = NULL, size_t aLiteralMapLength = 0);
 2962     ResultType ParseDerefs(LPTSTR aArgText, LPTSTR aArgMap, DerefType *aDeref, int &aDerefCount);
 2963     LPTSTR ParseActionType(LPTSTR aBufTarget, LPTSTR aBufSource, bool aDisplayErrors);
 2964     static ActionTypeType ConvertActionType(LPTSTR aActionTypeString);
 2965     static ActionTypeType ConvertOldActionType(LPTSTR aActionTypeString);
 2966     static bool ArgIsNumeric(ActionTypeType aActionType, ActionTypeType *np, LPTSTR arg[], int aArgIndex, int aArgCount = -1);
 2967     ResultType AddLabel(LPTSTR aLabelName, bool aAllowDupe);
 2968     void RemoveLabel(Label *aLabel);
 2969     ResultType AddLine(ActionTypeType aActionType, LPTSTR aArg[] = NULL, int aArgc = 0, LPTSTR aArgMap[] = NULL);
 2970 
 2971     // These aren't in the Line class because I think they're easier to implement
 2972     // if aStartingLine is allowed to be NULL (for recursive calls).  If they
 2973     // were member functions of class Line, a check for NULL would have to
 2974     // be done before dereferencing any line's mNextLine, for example:
 2975     ResultType PreparseExpressions(Line *aStartingLine);
 2976     ResultType PreparseStaticLines(Line *aStartingLine);
 2977     Line *PreparseBlocks(Line *aStartingLine, ExecUntilMode aMode = NORMAL_MODE, Line *aParentLine = NULL, const AttributeType aLoopType = ATTR_NONE);
 2978     Line *PreparseCommands(Line *aStartingLine);
 2979     bool IsLabelTarget(Line *aLine);
 2980 
 2981 public:
 2982     Line *mCurrLine;     // Seems better to make this public than make Line our friend.
 2983     Label *mPlaceholderLabel; // Used in place of a NULL label to simplify code.
 2984     UserMenuItem *mThisMenuItem;
 2985     TCHAR mThisMenuItemName[MAX_MENU_NAME_LENGTH + 1];
 2986     TCHAR mThisMenuName[MAX_MENU_NAME_LENGTH + 1];
 2987     LPTSTR mThisHotkeyName, mPriorHotkeyName;
 2988     MsgMonitorList mOnExit, mOnClipboardChange, mOnError; // Event handlers for OnExit(), OnClipboardChange() and OnError().
 2989     Label *mOnClipboardChangeLabel; // Separate from mOnClipboardChange for backward-compatibility reasons.
 2990     Label *mOnExitLabel;  // The label to run when the script terminates (NULL if none).
 2991     HWND mNextClipboardViewer;
 2992     bool mOnClipboardChangeIsRunning;
 2993     ExitReasons mExitReason;
 2994 
 2995     ScriptTimer *mFirstTimer, *mLastTimer;  // The first and last script timers in the linked list.
 2996     UINT mTimerCount, mTimerEnabledCount;
 2997 
 2998     UserMenu *mFirstMenu, *mLastMenu;
 2999     UINT mMenuCount;
 3000 
 3001     DWORD mThisHotkeyStartTime, mPriorHotkeyStartTime;  // Tickcount timestamp of when its subroutine began.
 3002     TCHAR mEndChar;  // The ending character pressed to trigger the most recent non-auto-replace hotstring.
 3003     modLR_type mThisHotkeyModifiersLR;
 3004     LPTSTR mFileSpec; // Will hold the full filespec, for convenience.
 3005     LPTSTR mFileDir;  // Will hold the directory containing the script file.
 3006     LPTSTR mFileName; // Will hold the script's naked file name.
 3007     LPTSTR mOurEXE; // Will hold this app's module name (e.g. C:\Program Files\AutoHotkey\AutoHotkey.exe).
 3008     LPTSTR mOurEXEDir;  // Same as above but just the containing directory (for convenience).
 3009     LPTSTR mMainWindowTitle; // Will hold our main window's title, for consistency & convenience.
 3010     bool mIsReadyToExecute;
 3011     bool mAutoExecSectionIsRunning;
 3012     bool mIsRestart; // The app is restarting rather than starting from scratch.
 3013     bool mErrorStdOut; // true if load-time syntax errors should be sent to stdout vs. a MsgBox.
 3014     UINT mErrorStdOutCP;
 3015     void SetErrorStdOut(LPTSTR aParam);
 3016     void PrintErrorStdOut(LPCTSTR aErrorText, int aLength = 0, LPCTSTR aFile = _T("*"));
 3017     void PrintErrorStdOut(LPCTSTR aErrorText, LPCTSTR aExtraInfo, FileIndexType aFileIndex, LineNumberType aLineNumber);
 3018 #ifndef AUTOHOTKEYSC
 3019     TextStream *mIncludeLibraryFunctionsThenExit;
 3020 #endif
 3021     __int64 mLinesExecutedThisCycle; // Use 64-bit to match the type of g->LinesPerCycle
 3022     int mUninterruptedLineCountMax; // 32-bit for performance (since huge values seem unnecessary here).
 3023     int mUninterruptibleTime;
 3024     DWORD mLastScriptRest, mLastPeekTime;
 3025 
 3026     CStringW mRunAsUser, mRunAsPass, mRunAsDomain;
 3027 
 3028     HICON mCustomIcon;  // NULL unless the script has loaded a custom icon during its runtime.
 3029     HICON mCustomIconSmall; // L17: Use separate big/small icons for best results.
 3030     LPTSTR mCustomIconFile; // Filename of icon.  Allocated on first use.
 3031     bool mIconFrozen; // If true, the icon does not change state when the state of pause or suspend changes.
 3032     LPTSTR mTrayIconTip;  // Custom tip text for tray icon.  Allocated on first use.
 3033     UINT mCustomIconNumber; // The number of the icon inside the above file.
 3034 
 3035     UserMenu *mTrayMenu; // Our tray menu, which should be destroyed upon exiting the program.
 3036     
 3037     ResultType Init(global_struct &g, LPTSTR aScriptFilename, bool aIsRestart);
 3038     ResultType CreateWindows();
 3039     void EnableClipboardListener(bool aEnable);
 3040     void EnableOrDisableViewMenuItems(HMENU aMenu, UINT aFlags);
 3041     void CreateTrayIcon();
 3042     void RestoreTrayIcon();
 3043     void UpdateTrayIcon(bool aForceUpdate = false);
 3044     ResultType AutoExecSection();
 3045     ResultType Edit();
 3046     ResultType Reload(bool aDisplayErrors);
 3047     ResultType ExitApp(ExitReasons aExitReason, int aExitCode = 0);
 3048     void TerminateApp(ExitReasons aExitReason, int aExitCode); // L31: Added aExitReason. See script.cpp.
 3049     LineNumberType LoadFromFile();
 3050     ResultType LoadIncludedFile(LPTSTR aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure);
 3051     ResultType LoadIncludedFile(TextStream *fp);
 3052     ResultType OpenIncludedFile(TextStream &ts, LPTSTR aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure);
 3053     LineNumberType CurrentLine();
 3054     LPTSTR CurrentFile();
 3055 
 3056     ResultType UpdateOrCreateTimer(IObject *aLabel, LPTSTR aPeriod, LPTSTR aPriority, bool aEnable
 3057         , bool aUpdatePriorityOnly);
 3058     void DeleteTimer(IObject *aLabel);
 3059 
 3060     ResultType DefineFunc(LPTSTR aBuf, Var *aFuncGlobalVar[]);
 3061 #ifndef AUTOHOTKEYSC
 3062     struct FuncLibrary
 3063     {
 3064         LPTSTR path;
 3065         size_t length;
 3066     };
 3067     void InitFuncLibraries(FuncLibrary aLibs[]);
 3068     void InitFuncLibrary(FuncLibrary &aLib, LPTSTR aPathBase, LPTSTR aPathSuffix);
 3069     Func *FindFuncInLibrary(LPTSTR aFuncName, size_t aFuncNameLength, bool &aErrorWasShown, bool &aFileWasFound, bool aIsAutoInclude);
 3070 #endif
 3071     Func *FindFunc(LPCTSTR aFuncName, size_t aFuncNameLength = 0, int *apInsertPos = NULL);
 3072     Func *AddFunc(LPCTSTR aFuncName, size_t aFuncNameLength, bool aIsBuiltIn, int aInsertPos, Object *aClassObject = NULL);
 3073 
 3074     ResultType DefineClass(LPTSTR aBuf);
 3075     ResultType DefineClassVars(LPTSTR aBuf, bool aStatic);
 3076     ResultType DefineClassProperty(LPTSTR aBuf);
 3077     Object *FindClass(LPCTSTR aClassName, size_t aClassNameLength = 0);
 3078     ResultType ResolveClasses();
 3079 
 3080     #define FINDVAR_DEFAULT  (VAR_LOCAL | VAR_GLOBAL)
 3081     #define FINDVAR_GLOBAL   VAR_GLOBAL
 3082     #define FINDVAR_LOCAL    VAR_LOCAL
 3083     // For pseudo-arrays, force-local mode overrides the legacy behaviour (a common source of
 3084     // confusion) and resolves the array elements individually, consistent with double-derefs:
 3085     #define FINDVAR_FOR_PSEUDO_ARRAY(array_start_var) \
 3086         ((g->CurrentFunc && (g->CurrentFunc->mDefaultVarType & VAR_FORCE_LOCAL)) ? FINDVAR_DEFAULT \
 3087         : (array_start_var).IsLocal() ? FINDVAR_LOCAL : FINDVAR_GLOBAL)
 3088     Var *FindOrAddVar(LPTSTR aVarName, size_t aVarNameLength = 0, int aScope = FINDVAR_DEFAULT);
 3089     Var *FindVar(LPTSTR aVarName, size_t aVarNameLength = 0, int *apInsertPos = NULL
 3090         , int aScope = FINDVAR_DEFAULT
 3091         , bool *apIsLocal = NULL);
 3092     Var *AddVar(LPTSTR aVarName, size_t aVarNameLength, int aInsertPos, int aScope);
 3093     static VarEntry *GetBuiltInVar(LPTSTR aVarName);
 3094 
 3095     ResultType DerefInclude(LPTSTR &aOutput, LPTSTR aBuf);
 3096 
 3097     WinGroup *FindGroup(LPTSTR aGroupName, bool aCreateIfNotFound = false);
 3098     ResultType AddGroup(LPTSTR aGroupName);
 3099     Label *FindLabel(LPTSTR aLabelName);
 3100     IObject *FindCallable(LPTSTR aLabelName, Var *aVar = NULL, int aParamCount = 0);
 3101 
 3102     ResultType DoRunAs(LPTSTR aCommandLine, LPTSTR aWorkingDir, bool aDisplayErrors, WORD aShowWindow
 3103         , Var *aOutputVar, PROCESS_INFORMATION &aPI, bool &aSuccess, HANDLE &aNewProcess, DWORD &aLastError);
 3104     ResultType ActionExec(LPTSTR aAction, LPTSTR aParams = NULL, LPTSTR aWorkingDir = NULL
 3105         , bool aDisplayErrors = true, LPTSTR aRunShowMode = NULL, HANDLE *aProcess = NULL
 3106         , bool aUpdateLastError = false, bool aUseRunAs = false, Var *aOutputVar = NULL);
 3107 
 3108     LPTSTR ListVars(LPTSTR aBuf, int aBufSize);
 3109     LPTSTR ListKeyHistory(LPTSTR aBuf, int aBufSize);
 3110 
 3111     ResultType PerformMenu(LPTSTR aMenu, LPTSTR aCommand, LPTSTR aParam3, LPTSTR aParam4, LPTSTR aOptions, LPTSTR aOptions2, Var *aParam4Var, Var *aParam5Var);
 3112     ResultType MenuError(LPTSTR aMessage, LPTSTR aInfo);
 3113     UINT GetFreeMenuItemID();
 3114     UserMenu *FindMenu(LPTSTR aMenuName);
 3115     UserMenu *FindMenu(HMENU aMenuHandle);
 3116     UserMenu *AddMenu(LPTSTR aMenuName);
 3117     UINT ThisMenuItemPos();
 3118     ResultType ScriptDeleteMenu(UserMenu *aMenu);
 3119     UserMenuItem *FindMenuItemByID(UINT aID)
 3120     {
 3121         UserMenuItem *mi;
 3122         for (UserMenu *m = mFirstMenu; m; m = m->mNextMenu)
 3123             for (mi = m->mFirstMenuItem; mi; mi = mi->mNextMenuItem)
 3124                 if (mi->mMenuID == aID)
 3125                     return mi;
 3126         return NULL;
 3127     }
 3128     UserMenuItem *FindMenuItemBySubmenu(HMENU aSubmenu) // L26: Used by WM_MEASUREITEM/WM_DRAWITEM to find the menu item with an associated submenu. Fixes icons on such items when owner-drawn menus are in use.
 3129     {
 3130         UserMenuItem *mi;
 3131         for (UserMenu *m = mFirstMenu; m; m = m->mNextMenu)
 3132             for (mi = m->mFirstMenuItem; mi; mi = mi->mNextMenuItem)
 3133                 if (mi->mSubmenu && mi->mSubmenu->mMenu == aSubmenu)
 3134                     return mi;
 3135         return NULL;
 3136     }
 3137 
 3138     ResultType PerformGui(LPTSTR aBuf, LPTSTR aControlType, LPTSTR aOptions, LPTSTR aParam4);
 3139     static GuiType *ResolveGui(LPTSTR aBuf, LPTSTR &aCommand, LPTSTR *aName = NULL, size_t *aNameLength = NULL, LPTSTR aControlID = NULL);
 3140 
 3141     // Call this SciptError to avoid confusion with Line's error-displaying functions:
 3142     ResultType ScriptError(LPCTSTR aErrorText, LPCTSTR aExtraInfo = _T("")); // , ResultType aErrorType = FAIL);
 3143     ResultType CriticalError(LPCTSTR aErrorText, LPCTSTR aExtraInfo = _T(""));
 3144 
 3145     void ScriptWarning(WarnMode warnMode, LPCTSTR aWarningText, LPCTSTR aExtraInfo = _T(""), Line *line = NULL);
 3146     void WarnUninitializedVar(Var *var);
 3147     void MaybeWarnLocalSameAsGlobal(Func &func, Var &var);
 3148 
 3149     void PreprocessLocalVars(Func &aFunc, Var **aVarList, int &aVarCount);
 3150     void CheckForClassOverwrite();
 3151 
 3152     static ResultType UnhandledException(Line* aLine);
 3153     static ResultType SetErrorLevelOrThrow() { return SetErrorLevelOrThrowBool(true); }
 3154     static ResultType SetErrorLevelOrThrowBool(bool aError);
 3155     static ResultType SetErrorLevelOrThrowInt(int aErrorValue, LPCTSTR aWhat);
 3156     static ResultType SetErrorLevelOrThrowStr(LPCTSTR aErrorValue, LPCTSTR aWhat = NULL);
 3157     static ResultType ThrowRuntimeException(LPCTSTR aErrorText, LPCTSTR aWhat = NULL, LPCTSTR aExtraInfo = _T(""));
 3158     static void FreeExceptionToken(ExprTokenType*& aToken);
 3159 
 3160     #define SOUNDPLAY_ALIAS _T("AHK_PlayMe")  // Used by destructor and SoundPlay().
 3161 
 3162     Script();
 3163     ~Script();
 3164     // Note that the anchors to any linked lists will be lost when this
 3165     // object goes away, so for now, be sure the destructor is only called
 3166     // when the program is about to be exited, which will thereby reclaim
 3167     // the memory used by the abandoned linked lists (otherwise, a memory
 3168     // leak will result).
 3169 };
 3170 
 3171 
 3172 
 3173 ////////////////////////
 3174 // BUILT-IN VARIABLES //
 3175 ////////////////////////
 3176 
 3177 // Declare built-in var read function.
 3178 #define BIV_DECL_R(name) VarSizeType name(LPTSTR aBuf, LPTSTR aVarName)
 3179 
 3180 BIV_DECL_R (BIV_True_False);
 3181 BIV_DECL_R (BIV_MMM_DDD);
 3182 BIV_DECL_R (BIV_DateTime);
 3183 BIV_DECL_R (BIV_BatchLines);
 3184 BIV_DECL_R (BIV_ListLines);
 3185 BIV_DECL_R (BIV_TitleMatchMode);
 3186 BIV_DECL_R (BIV_TitleMatchModeSpeed);
 3187 BIV_DECL_R (BIV_DetectHiddenWindows);
 3188 BIV_DECL_R (BIV_DetectHiddenText);
 3189 BIV_DECL_R (BIV_AutoTrim);
 3190 BIV_DECL_R (BIV_StringCaseSense);
 3191 BIV_DECL_R (BIV_FormatInteger);
 3192 BIV_DECL_R (BIV_FormatFloat);
 3193 BIV_DECL_R (BIV_xDelay);
 3194 BIV_DECL_R (BIV_DefaultMouseSpeed);
 3195 BIV_DECL_R (BIV_CoordMode);
 3196 BIV_DECL_R (BIV_SendMode);
 3197 BIV_DECL_R (BIV_SendLevel);
 3198 BIV_DECL_R (BIV_StoreCapslockMode);
 3199 BIV_DECL_R (BIV_IsPaused);
 3200 BIV_DECL_R (BIV_IsCritical);
 3201 BIV_DECL_R (BIV_IsSuspended);
 3202 BIV_DECL_R (BIV_IsCompiled);
 3203 BIV_DECL_R (BIV_IsUnicode);
 3204 BIV_DECL_R (BIV_FileEncoding);
 3205 BIV_DECL_R (BIV_RegView);
 3206 BIV_DECL_R (BIV_LastError);
 3207 BIV_DECL_R (BIV_IconHidden);
 3208 BIV_DECL_R (BIV_IconTip);
 3209 BIV_DECL_R (BIV_IconFile);
 3210 BIV_DECL_R (BIV_IconNumber);
 3211 BIV_DECL_R (BIV_ExitReason);
 3212 BIV_DECL_R (BIV_Space_Tab);
 3213 BIV_DECL_R (BIV_AhkVersion);
 3214 BIV_DECL_R (BIV_AhkPath);
 3215 BIV_DECL_R (BIV_TickCount);
 3216 BIV_DECL_R (BIV_Now);
 3217 BIV_DECL_R (BIV_OSType);
 3218 BIV_DECL_R (BIV_OSVersion);
 3219 BIV_DECL_R (BIV_Is64bitOS);
 3220 BIV_DECL_R (BIV_Language);
 3221 BIV_DECL_R (BIV_UserName_ComputerName);
 3222 BIV_DECL_R (BIV_WorkingDir);
 3223 BIV_DECL_R (BIV_WinDir);
 3224 BIV_DECL_R (BIV_Temp);
 3225 BIV_DECL_R (BIV_ComSpec);
 3226 BIV_DECL_R (BIV_SpecialFolderPath); // Handles various variables.
 3227 BIV_DECL_R (BIV_MyDocuments);
 3228 BIV_DECL_R (BIV_Caret);
 3229 BIV_DECL_R (BIV_Cursor);
 3230 BIV_DECL_R (BIV_ScreenWidth_Height);
 3231 BIV_DECL_R (BIV_ScriptName);
 3232 BIV_DECL_R (BIV_ScriptDir);
 3233 BIV_DECL_R (BIV_ScriptFullPath);
 3234 BIV_DECL_R (BIV_ScriptHwnd);
 3235 BIV_DECL_R (BIV_LineNumber);
 3236 BIV_DECL_R (BIV_LineFile);
 3237 BIV_DECL_R (BIV_LoopFileName);
 3238 BIV_DECL_R (BIV_LoopFileExt);
 3239 BIV_DECL_R (BIV_LoopFileDir);
 3240 BIV_DECL_R (BIV_LoopFilePath);
 3241 BIV_DECL_R (BIV_LoopFileLongPath);
 3242 BIV_DECL_R (BIV_LoopFileShortPath);
 3243 BIV_DECL_R (BIV_LoopFileTime);
 3244 BIV_DECL_R (BIV_LoopFileAttrib);
 3245 BIV_DECL_R (BIV_LoopFileSize);
 3246 BIV_DECL_R (BIV_LoopRegType);
 3247 BIV_DECL_R (BIV_LoopRegKey);
 3248 BIV_DECL_R (BIV_LoopRegSubKey);
 3249 BIV_DECL_R (BIV_LoopRegName);
 3250 BIV_DECL_R (BIV_LoopRegTimeModified);
 3251 BIV_DECL_R (BIV_LoopReadLine);
 3252 BIV_DECL_R (BIV_LoopField);
 3253 BIV_DECL_R (BIV_LoopIndex);
 3254 BIV_DECL_R (BIV_ThisFunc);
 3255 BIV_DECL_R (BIV_ThisLabel);
 3256 BIV_DECL_R (BIV_ThisMenuItem);
 3257 BIV_DECL_R (BIV_ThisMenuItemPos);
 3258 BIV_DECL_R (BIV_ThisMenu);
 3259 BIV_DECL_R (BIV_ThisHotkey);
 3260 BIV_DECL_R (BIV_PriorHotkey);
 3261 BIV_DECL_R (BIV_TimeSinceThisHotkey);
 3262 BIV_DECL_R (BIV_TimeSincePriorHotkey);
 3263 BIV_DECL_R (BIV_EndChar);
 3264 BIV_DECL_R (BIV_Gui);
 3265 BIV_DECL_R (BIV_GuiControl);
 3266 BIV_DECL_R (BIV_GuiEvent);
 3267 BIV_DECL_R (BIV_DefaultGui);
 3268 BIV_DECL_R (BIV_EventInfo);
 3269 BIV_DECL_R (BIV_TimeIdle);
 3270 BIV_DECL_R (BIV_TimeIdlePhysical);
 3271 BIV_DECL_R (BIV_IPAddress);
 3272 BIV_DECL_R (BIV_IsAdmin);
 3273 BIV_DECL_R (BIV_PtrSize);
 3274 BIV_DECL_R (BIV_PriorKey);
 3275 BIV_DECL_R (BIV_ScreenDPI);
 3276 
 3277 
 3278 ////////////////////////
 3279 // BUILT-IN FUNCTIONS //
 3280 ////////////////////////
 3281 // Caller has ensured that SYM_VAR's Type() is VAR_NORMAL and that it's either not an environment
 3282 // variable or the caller wants environment variables treated as having zero length.
 3283 #define EXPR_TOKEN_LENGTH(token_raw, token_as_string) \
 3284 ( (token_raw->symbol == SYM_VAR && !token_raw->var->IsBinaryClip()) \
 3285     ? token_raw->var->Length()\
 3286     : _tcslen(token_as_string) )
 3287 
 3288 #ifdef ENABLE_DLLCALL
 3289 bool IsDllArgTypeName(LPTSTR name);
 3290 void *GetDllProcAddress(LPCTSTR aDllFileFunc, HMODULE *hmodule_to_free = NULL);
 3291 BIF_DECL(BIF_DllCall);
 3292 #endif
 3293 
 3294 BIF_DECL(BIF_StrLen);
 3295 BIF_DECL(BIF_SubStr);
 3296 BIF_DECL(BIF_InStr);
 3297 BIF_DECL(BIF_StrSplit);
 3298 BIF_DECL(BIF_StrReplace);
 3299 BIF_DECL(BIF_RegEx);
 3300 BIF_DECL(BIF_Ord);
 3301 BIF_DECL(BIF_Chr);
 3302 BIF_DECL(BIF_Format);
 3303 BIF_DECL(BIF_NumGet);
 3304 BIF_DECL(BIF_NumPut);
 3305 BIF_DECL(BIF_StrGetPut);
 3306 BIF_DECL(BIF_IsLabel);
 3307 BIF_DECL(BIF_IsFunc);
 3308 BIF_DECL(BIF_Func);
 3309 BIF_DECL(BIF_IsByRef);
 3310 BIF_DECL(BIF_GetKeyState);
 3311 BIF_DECL(BIF_GetKeyName);
 3312 BIF_DECL(BIF_VarSetCapacity);
 3313 BIF_DECL(BIF_FileExist);
 3314 BIF_DECL(BIF_WinExistActive);
 3315 BIF_DECL(BIF_Round);
 3316 BIF_DECL(BIF_FloorCeil);
 3317 BIF_DECL(BIF_Mod);
 3318 BIF_DECL(BIF_Abs);
 3319 BIF_DECL(BIF_Sin);
 3320 BIF_DECL(BIF_Cos);
 3321 BIF_DECL(BIF_Tan);
 3322 BIF_DECL(BIF_ASinACos);
 3323 BIF_DECL(BIF_ATan);
 3324 BIF_DECL(BIF_Exp);
 3325 BIF_DECL(BIF_SqrtLogLn);
 3326 BIF_DECL(BIF_MinMax);
 3327 
 3328 BIF_DECL(BIF_OnMessage);
 3329 BIF_DECL(BIF_On);
 3330 
 3331 #ifdef ENABLE_REGISTERCALLBACK
 3332 BIF_DECL(BIF_RegisterCallback);
 3333 #endif
 3334 
 3335 BIF_DECL(BIF_MenuGet);
 3336 
 3337 BIF_DECL(BIF_StatusBar);
 3338 
 3339 BIF_DECL(BIF_LV_GetNextOrCount);
 3340 BIF_DECL(BIF_LV_GetText);
 3341 BIF_DECL(BIF_LV_AddInsertModify);
 3342 BIF_DECL(BIF_LV_Delete);
 3343 BIF_DECL(BIF_LV_InsertModifyDeleteCol);
 3344 BIF_DECL(BIF_LV_SetImageList);
 3345 
 3346 BIF_DECL(BIF_TV_AddModifyDelete);
 3347 BIF_DECL(BIF_TV_GetRelatedItem);
 3348 BIF_DECL(BIF_TV_Get);
 3349 BIF_DECL(BIF_TV_SetImageList);
 3350 
 3351 BIF_DECL(BIF_IL_Create);
 3352 BIF_DECL(BIF_IL_Destroy);
 3353 BIF_DECL(BIF_IL_Add);
 3354 
 3355 BIF_DECL(BIF_LoadPicture);
 3356 
 3357 BIF_DECL(BIF_Trim); // L31: Also handles LTrim and RTrim.
 3358 
 3359 BIF_DECL(BIF_Hotstring);
 3360 BIF_DECL(BIF_InputHook);
 3361 
 3362 
 3363 BIF_DECL(BIF_IsObject);
 3364 BIF_DECL(BIF_ObjCreate);
 3365 BIF_DECL(BIF_ObjArray);
 3366 BIF_DECL(BIF_ObjInvoke); // Pseudo-operator. See script_object.cpp for comments.
 3367 BIF_DECL(BIF_ObjGetInPlace); // Pseudo-operator.
 3368 BIF_DECL(BIF_ObjNew); // Pseudo-operator.
 3369 BIF_DECL(BIF_ObjIncDec); // Pseudo-operator.
 3370 BIF_DECL(BIF_ObjAddRefRelease);
 3371 BIF_DECL(BIF_ObjBindMethod);
 3372 BIF_DECL(BIF_ObjRaw);
 3373 BIF_DECL(BIF_ObjBase);
 3374 // Built-ins also available as methods -- these are available as functions for use primarily by overridden methods (i.e. where using the built-in methods isn't possible as they're no longer accessible).
 3375 BIF_DECL(BIF_ObjInsert);
 3376 BIF_DECL(BIF_ObjInsertAt);
 3377 BIF_DECL(BIF_ObjPush);
 3378 BIF_DECL(BIF_ObjPop);
 3379 BIF_DECL(BIF_ObjDelete);
 3380 BIF_DECL(BIF_ObjRemove);
 3381 BIF_DECL(BIF_ObjRemoveAt);
 3382 BIF_DECL(BIF_ObjGetCapacity);
 3383 BIF_DECL(BIF_ObjSetCapacity);
 3384 BIF_DECL(BIF_ObjGetAddress);
 3385 BIF_DECL(BIF_ObjCount);
 3386 BIF_DECL(BIF_ObjLength);
 3387 BIF_DECL(BIF_ObjMaxIndex);
 3388 BIF_DECL(BIF_ObjMinIndex);
 3389 BIF_DECL(BIF_ObjNewEnum);
 3390 BIF_DECL(BIF_ObjHasKey);
 3391 BIF_DECL(BIF_ObjClone);
 3392 
 3393 
 3394 // Advanced file IO interfaces
 3395 BIF_DECL(BIF_FileOpen);
 3396 BIF_DECL(BIF_ComObjActive);
 3397 BIF_DECL(BIF_ComObjCreate);
 3398 BIF_DECL(BIF_ComObjGet);
 3399 BIF_DECL(BIF_ComObjConnect);
 3400 BIF_DECL(BIF_ComObjError);
 3401 BIF_DECL(BIF_ComObjTypeOrValue);
 3402 BIF_DECL(BIF_ComObjFlags);
 3403 BIF_DECL(BIF_ComObjArray);
 3404 BIF_DECL(BIF_ComObjQuery);
 3405 
 3406 
 3407 BIF_DECL(BIF_Exception);
 3408 
 3409 
 3410 BOOL LegacyResultToBOOL(LPTSTR aResult);
 3411 BOOL LegacyVarToBOOL(Var &aVar);
 3412 BOOL TokenToBOOL(ExprTokenType &aToken, SymbolType aTokenIsNumber = SYM_INVALID);
 3413 SymbolType TokenIsPureNumeric(ExprTokenType &aToken);
 3414 BOOL TokenIsEmptyString(ExprTokenType &aToken);
 3415 BOOL TokenIsEmptyString(ExprTokenType &aToken, BOOL aWarnUninitializedVar); // Same as TokenIsEmptyString but optionally warns if the token is an uninitialized var.
 3416 __int64 TokenToInt64(ExprTokenType &aToken, BOOL aIsPureInteger = FALSE);
 3417 double TokenToDouble(ExprTokenType &aToken, BOOL aCheckForHex = TRUE, BOOL aIsPureFloat = FALSE);
 3418 LPTSTR TokenToString(ExprTokenType &aToken, LPTSTR aBuf = NULL);
 3419 ResultType TokenToDoubleOrInt64(const ExprTokenType &aInput, ExprTokenType &aOutput);
 3420 IObject *TokenToObject(ExprTokenType &aToken); // L31
 3421 Func *TokenToFunc(ExprTokenType &aToken);
 3422 ResultType TokenSetResult(ExprTokenType &aResultToken, LPCTSTR aResult, size_t aResultLength = -1);
 3423 BOOL TokensAreEqual(ExprTokenType &left, ExprTokenType &right);
 3424 
 3425 LPTSTR RegExMatch(LPTSTR aHaystack, LPTSTR aNeedleRegEx);
 3426 void SetWorkingDir(LPTSTR aNewDir);
 3427 void UpdateWorkingDir(LPTSTR aNewDir = NULL);
 3428 LPTSTR GetWorkingDir();
 3429 int ConvertJoy(LPTSTR aBuf, int *aJoystickID = NULL, bool aAllowOnlyButtons = false);
 3430 bool ScriptGetKeyState(vk_type aVK, KeyStateTypes aKeyStateType);
 3431 double ScriptGetJoyState(JoyControls aJoy, int aJoystickID, ExprTokenType &aToken, bool aUseBoolForUpDown);
 3432 LPTSTR GetExitReasonString(ExitReasons aExitReason);
 3433 
 3434 #endif
 3435