home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Open Source / AutoHotKey / Source / AutoHotkey104705_source.exe / source / script.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-11-20  |  138.2 KB  |  2,679 lines

  1. /*
  2. AutoHotkey
  3.  
  4. Copyright 2003-2007 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. #ifdef AUTOHOTKEYSC
  29.     #include "lib\exearc_read.h"
  30. #endif
  31.  
  32. #include "os_version.h" // For the global OS_Version object
  33. EXTERN_OSVER; // For the access to the g_os version object without having to include globaldata.h
  34. EXTERN_G;
  35.  
  36. enum ExecUntilMode {NORMAL_MODE, UNTIL_RETURN, UNTIL_BLOCK_END, ONLY_ONE_LINE};
  37.  
  38. // It's done this way so that mAttribute can store a pointer or one of these constants.
  39. // If it is storing a pointer for a given Action Type, be sure never to compare it
  40. // for equality against these constants because by coincidence, the pointer value
  41. // might just match one of them:
  42. #define ATTR_NONE (void *)0  // Some places migh rely on this being zero.
  43. #define ATTR_TRUE (void *)1
  44. #define ATTR_LOOP_UNKNOWN (void *)1 // Same value as the above.        // KEEP IN SYNC WITH BELOW.
  45. #define ATTR_LOOP_IS_UNKNOWN_OR_NONE(attr) (attr <= ATTR_LOOP_UNKNOWN) // KEEP IN SYNC WITH ABOVE.
  46. #define ATTR_LOOP_NORMAL (void *)2
  47. #define ATTR_LOOP_FILEPATTERN (void *)3
  48. #define ATTR_LOOP_REG (void *)4
  49. #define ATTR_LOOP_READ_FILE (void *)5
  50. #define ATTR_LOOP_PARSE (void *)6
  51. typedef void *AttributeType;
  52.  
  53. enum FileLoopModeType {FILE_LOOP_INVALID, FILE_LOOP_FILES_ONLY, FILE_LOOP_FILES_AND_FOLDERS, FILE_LOOP_FOLDERS_ONLY};
  54. enum VariableTypeType {VAR_TYPE_INVALID, VAR_TYPE_NUMBER, VAR_TYPE_INTEGER, VAR_TYPE_FLOAT
  55.     , VAR_TYPE_TIME    , VAR_TYPE_DIGIT, VAR_TYPE_XDIGIT, VAR_TYPE_ALNUM, VAR_TYPE_ALPHA
  56.     , VAR_TYPE_UPPER, VAR_TYPE_LOWER, VAR_TYPE_SPACE};
  57.  
  58. #define ATTACH_THREAD_INPUT \
  59.     bool threads_are_attached = false;\
  60.     DWORD target_thread = GetWindowThreadProcessId(target_window, NULL);\
  61.     if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
  62.         threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;
  63. // BELOW IS SAME AS ABOVE except it checks do_activate and also does a SetActiveWindow():
  64. #define ATTACH_THREAD_INPUT_AND_SETACTIVEWINDOW_IF_DO_ACTIVATE \
  65.     bool threads_are_attached = false;\
  66.     DWORD target_thread;\
  67.     if (do_activate)\
  68.     {\
  69.         target_thread = GetWindowThreadProcessId(target_window, NULL);\
  70.         if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
  71.             threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;\
  72.         SetActiveWindow(target_window);\
  73.     }
  74.  
  75. #define DETACH_THREAD_INPUT \
  76.     if (threads_are_attached)\
  77.         AttachThreadInput(g_MainThreadID, target_thread, FALSE);
  78.  
  79. #define RESEED_RANDOM_GENERATOR \
  80. {\
  81.     FILETIME ft;\
  82.     GetSystemTimeAsFileTime(&ft);\
  83.     init_genrand(ft.dwLowDateTime);\
  84. }
  85.  
  86. // Notes about the below macro:
  87. // One of the menus in the menu bar has been displayed, and the we know the user is is still in
  88. // the menu bar, even moving to different menus and/or menu items, until WM_EXITMENULOOP is received.
  89. // Note: It seems that when window's menu bar is being displayed/navigated by the user, our thread
  90. // is tied up in a message loop other than our own.  In other words, it's very similar to the
  91. // TrackPopupMenuEx() call used to handle the tray menu, which is why g_MenuIsVisible can be used
  92. // for both types of menus to indicate to MainWindowProc() that timed subroutines should not be
  93. // checked or allowed to launch during such times.  Also, "break" is used rather than "return 0"
  94. // to let DefWindowProc()/DefaultDlgProc() take whatever action it needs to do for these.
  95. // UPDATE: The value of g_MenuIsVisible is checked before changing it because it might already be
  96. // set to MENU_TYPE_POPUP (apparently, TrackPopupMenuEx sometimes/always generates WM_ENTERMENULOOP).
  97. // BAR vs. POPUP currently doesn't matter (as long as its non-zero); thus, the above is done for
  98. // maintainability.
  99. #define HANDLE_MENU_LOOP \
  100.     case WM_ENTERMENULOOP:\
  101.         if (!g_MenuIsVisible)\
  102.             g_MenuIsVisible = MENU_TYPE_BAR;\
  103.         break;\
  104.     case WM_EXITMENULOOP:\
  105.         g_MenuIsVisible = MENU_TYPE_NONE;\
  106.         break;
  107.  
  108. #define IS_PERSISTENT (Hotkey::sHotkeyCount || Hotstring::sHotstringCount || g_KeybdHook || g_MouseHook || g_persistent)
  109.  
  110. // Since WM_COMMAND IDs must be shared among all menus and controls, they are carefully conserved,
  111. // especially since there are only 65,535 possible IDs.  In addition, they are assigned to ranges
  112. // to minimize the need that they will need to be changed in the future (changing the ID of a main
  113. // menu item, tray menu item, or a user-defined menu item [by way of increasing MAX_CONTROLS_PER_GUI]
  114. // is bad because some scripts might be using PostMessage/SendMessage to automate AutoHotkey itself).
  115. // For this reason, the following ranges are reserved:
  116. // 0: unused (possibly special in some contexts)
  117. // 1: IDOK
  118. // 2: IDCANCEL
  119. // 3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
  120. // 1003 to 65299: User Defined Menu IDs
  121. // 65300 to 65399: Standard tray menu items.
  122. // 65400 to 65534: main menu items (might be best to leave 65535 unused in case it ever has special meaning)
  123. enum CommandIDs {CONTROL_ID_FIRST = IDCANCEL + 1
  124.     , 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).
  125.     , ID_USER_LAST = 65299  // The last. Especially do not change this due to scripts using Post/SendMessage to automate AutoHotkey.
  126.     , ID_TRAY_FIRST, ID_TRAY_OPEN = ID_TRAY_FIRST
  127.     , ID_TRAY_HELP, ID_TRAY_WINDOWSPY, ID_TRAY_RELOADSCRIPT
  128.     , ID_TRAY_EDITSCRIPT, ID_TRAY_SUSPEND, ID_TRAY_PAUSE, ID_TRAY_EXIT
  129.     , ID_TRAY_LAST = ID_TRAY_EXIT // But this value should never hit the below. There is debug code to enforce.
  130.     , ID_MAIN_FIRST = 65400, ID_MAIN_LAST = 65534}; // These should match the range used by resource.h
  131.  
  132. #define GUI_INDEX_TO_ID(index) (index + CONTROL_ID_FIRST)
  133. #define GUI_ID_TO_INDEX(id) (id - CONTROL_ID_FIRST) // Returns a small negative if "id" is invalid, such as 0.
  134. #define GUI_HWND_TO_INDEX(hwnd) GUI_ID_TO_INDEX(GetDlgCtrlID(hwnd)) // Returns a small negative on failure (e.g. HWND not found).
  135. // Notes about above:
  136. // 1) Callers should call GuiType::FindControl() instead of GUI_HWND_TO_INDEX() if the hwnd might be a combobox's
  137. //    edit control.
  138. // 2) Testing shows that GetDlgCtrlID() is much faster than looping through a GUI window's control array to find
  139. //    a matching HWND.
  140.  
  141.  
  142. #define ERR_ABORT_NO_SPACES "The current thread will exit."
  143. #define ERR_ABORT "  " ERR_ABORT_NO_SPACES
  144. #define WILL_EXIT "The program will exit."
  145. #define OLD_STILL_IN_EFFECT "The script was not reloaded; the old version will remain in effect."
  146. #define ERR_CONTINUATION_SECTION_TOO_LONG "Continuation section too long."
  147. #define ERR_UNRECOGNIZED_ACTION "This line does not contain a recognized action."
  148. #define ERR_NONEXISTENT_HOTKEY "Nonexistent hotkey."
  149. #define ERR_NONEXISTENT_VARIANT "Nonexistent hotkey variant (IfWin)."
  150. #define ERR_NONEXISTENT_FUNCTION "Call to nonexistent function."
  151. #define ERR_EXE_CORRUPTED "EXE corrupted"
  152. #define ERR_PARAM1_INVALID "Parameter #1 invalid"
  153. #define ERR_PARAM2_INVALID "Parameter #2 invalid"
  154. #define ERR_PARAM3_INVALID "Parameter #3 invalid"
  155. #define ERR_PARAM4_INVALID "Parameter #4 invalid"
  156. #define ERR_PARAM5_INVALID "Parameter #5 invalid"
  157. #define ERR_PARAM6_INVALID "Parameter #6 invalid"
  158. #define ERR_PARAM7_INVALID "Parameter #7 invalid"
  159. #define ERR_PARAM8_INVALID "Parameter #8 invalid"
  160. #define ERR_PARAM1_REQUIRED "Parameter #1 required"
  161. #define ERR_PARAM2_REQUIRED "Parameter #2 required"
  162. #define ERR_PARAM3_REQUIRED "Parameter #3 required"
  163. #define ERR_PARAM4_OMIT "Parameter #4 should be omitted in this case."
  164. #define ERR_PARAM2_MUST_BE_BLANK "Parameter #2 must be blank in this case."
  165. #define ERR_PARAM3_MUST_BE_BLANK "Parameter #3 must be blank in this case."
  166. #define ERR_PARAM4_MUST_BE_BLANK "Parameter #4 must be blank in this case."
  167. #define ERR_INVALID_KEY_OR_BUTTON "Invalid key or button name"
  168. #define ERR_MISSING_OUTPUT_VAR "Requires at least one of its output variables."
  169. #define ERR_MISSING_OPEN_PAREN "Missing \"(\""
  170. #define ERR_MISSING_OPEN_BRACE "Missing \"{\""
  171. #define ERR_MISSING_CLOSE_PAREN "Missing \")\""
  172. #define ERR_MISSING_CLOSE_BRACE "Missing \"}\""
  173. #define ERR_MISSING_CLOSE_QUOTE "Missing close-quote" // No period after short phrases.
  174. #define ERR_MISSING_COMMA "Missing comma"             //
  175. #define ERR_BLANK_PARAM "Blank parameter"             //
  176. #define ERR_BYREF "Caller must pass a variable to this ByRef parameter."
  177. #define ERR_ELSE_WITH_NO_IF "ELSE with no matching IF"
  178. #define ERR_OUTOFMEM "Out of memory."  // Used by RegEx too, so don't change it without also changing RegEx to keep the former string.
  179. #define ERR_MEM_LIMIT_REACHED "Memory limit reached (see #MaxMem in the help file)." ERR_ABORT
  180. #define ERR_NO_LABEL "Target label does not exist."
  181. #define ERR_MENU "Menu does not exist."
  182. #define ERR_SUBMENU "Submenu does not exist."
  183. #define ERR_WINDOW_PARAM "Requires at least one of its window parameters."
  184. #define ERR_ON_OFF "Requires ON/OFF/blank"
  185. #define ERR_ON_OFF_LOCALE "Requires ON/OFF/LOCALE"
  186. #define ERR_ON_OFF_TOGGLE "Requires ON/OFF/TOGGLE/blank"
  187. #define ERR_ON_OFF_TOGGLE_PERMIT "Requires ON/OFF/TOGGLE/PERMIT/blank"
  188. #define ERR_TITLEMATCHMODE "Requires 1/2/3/Slow/Fast"
  189. #define ERR_MENUTRAY "Supported only for the tray menu"
  190. #define ERR_REG_KEY "Invalid registry root key"
  191. #define ERR_REG_VALUE_TYPE "Invalid registry value type"
  192. #define ERR_INVALID_DATETIME "Invalid YYYYMMDDHHMISS value"
  193. #define ERR_MOUSE_BUTTON "Invalid mouse button"
  194. #define ERR_MOUSE_COORD "X & Y must be either both absent or both present."
  195. #define ERR_DIVIDEBYZERO "Divide by zero"
  196. #define ERR_PERCENT "Must be between -100 and 100."
  197. #define ERR_MOUSE_SPEED "Mouse speed must be between 0 and " MAX_MOUSE_SPEED_STR "."
  198. #define ERR_VAR_IS_READONLY "Not allowed as an output variable."
  199.  
  200. //----------------------------------------------------------------------------------
  201.  
  202. void DoIncrementalMouseMove(int aX1, int aY1, int aX2, int aY2, int aSpeed);
  203. DWORD ProcessExist9x2000(char *aProcess, char *aProcessName);
  204. DWORD ProcessExistNT4(char *aProcess, char *aProcessName);
  205.  
  206. inline DWORD ProcessExist(char *aProcess, char *aProcessName = NULL)
  207. {
  208.     return g_os.IsWinNT4() ? ProcessExistNT4(aProcess, aProcessName)
  209.         : ProcessExist9x2000(aProcess, aProcessName);
  210. }
  211.  
  212. bool Util_Shutdown(int nFlag);
  213. BOOL Util_ShutdownHandler(HWND hwnd, DWORD lParam);
  214. void Util_WinKill(HWND hWnd);
  215.  
  216. enum MainWindowModes {MAIN_MODE_NO_CHANGE, MAIN_MODE_LINES, MAIN_MODE_VARS
  217.     , MAIN_MODE_HOTKEYS, MAIN_MODE_KEYHISTORY, MAIN_MODE_REFRESH};
  218. ResultType ShowMainWindow(MainWindowModes aMode = MAIN_MODE_NO_CHANGE, bool aRestricted = true);
  219. DWORD GetAHKInstallDir(char *aBuf);
  220.  
  221.  
  222. struct InputBoxType
  223. {
  224.     char *title;
  225.     char *text;
  226.     int width;
  227.     int height;
  228.     int xpos;
  229.     int ypos;
  230.     Var *output_var;
  231.     char password_char;
  232.     char *default_string;
  233.     DWORD timeout;
  234.     HWND hwnd;
  235. };
  236.  
  237. struct SplashType
  238. {
  239.     int width;
  240.     int height;
  241.     int bar_pos;  // The amount of progress of the bar (it's position).
  242.     int margin_x; // left/right margin
  243.     int margin_y; // top margin
  244.     int text1_height; // Height of main text control.
  245.     int object_width;   // Width of image.
  246.     int object_height;  // Height of the progress bar or image.
  247.     HWND hwnd;
  248.     LPPICTURE pic; // For SplashImage.
  249.     HWND hwnd_bar;
  250.     HWND hwnd_text1;  // MainText
  251.     HWND hwnd_text2;  // SubText
  252.     HFONT hfont1; // Main
  253.     HFONT hfont2; // Sub
  254.     HBRUSH hbrush; // Window background color brush.
  255.     COLORREF color_bk; // The background color itself.
  256.     COLORREF color_text; // Color of the font.
  257. };
  258.  
  259. // Use GetClientRect() to determine the available width so that control's can be centered.
  260. #define SPLASH_CALC_YPOS \
  261.     int bar_y = splash.margin_y + (splash.text1_height ? (splash.text1_height + splash.margin_y) : 0);\
  262.     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.
  263. #define PROGRESS_MAIN_POS splash.margin_x, splash.margin_y, control_width, splash.text1_height
  264. #define PROGRESS_BAR_POS  splash.margin_x, bar_y, control_width, splash.object_height
  265. #define PROGRESS_SUB_POS  splash.margin_x, sub_y, control_width, (client_rect.bottom - client_rect.top) - sub_y
  266.  
  267. // From AutoIt3's InputBox.  This doesn't add a measurable amount of code size, so the compiler seems to implement
  268. // it efficiently (somewhat like a macro).
  269. template <class T>
  270. inline void swap(T &v1, T &v2) {
  271.     T tmp=v1;
  272.     v1=v2;
  273.     v2=tmp;
  274. }
  275.  
  276. #define INPUTBOX_DEFAULT INT_MIN
  277. ResultType InputBox(Var *aOutputVar, char *aTitle, char *aText, bool aHideInput
  278.     , int aWidth, int aHeight, int aX, int aY, double aTimeout, char *aDefault);
  279. BOOL CALLBACK InputBoxProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  280. VOID CALLBACK InputBoxTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  281. VOID CALLBACK DerefTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  282. BOOL CALLBACK EnumChildFindSeqNum(HWND aWnd, LPARAM lParam);
  283. BOOL CALLBACK EnumChildFindPoint(HWND aWnd, LPARAM lParam);
  284. BOOL CALLBACK EnumChildGetControlList(HWND aWnd, LPARAM lParam);
  285. BOOL CALLBACK EnumMonitorProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM lParam);
  286. BOOL CALLBACK EnumChildGetText(HWND aWnd, LPARAM lParam);
  287. LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  288. bool HandleMenuItem(HWND aHwnd, WORD aMenuItemID, WPARAM aGuiIndex);
  289.  
  290.  
  291. typedef UINT LineNumberType;
  292. 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).
  293. #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).
  294.  
  295. #define LOADING_FAILED UINT_MAX
  296.  
  297. // -2 for the beginning and ending g_DerefChars:
  298. #define MAX_VAR_NAME_LENGTH (UCHAR_MAX - 2)
  299. #define MAX_FUNCTION_PARAMS UCHAR_MAX // Also conserves stack space to support future attributes such as param default values.
  300. #define MAX_DEREFS_PER_ARG 512
  301.  
  302. 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.
  303. typedef UCHAR DerefParamCountType;
  304.  
  305. class Func; // Forward declaration for use below.
  306. struct DerefType
  307. {
  308.     char *marker;
  309.     union
  310.     {
  311.         Var *var;
  312.         Func *func;
  313.     };
  314.     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  315.     // due to byte-alignment:
  316.     bool is_function; // This should be kept pure bool to allow easy determination of what's in the union, above.
  317.     DerefParamCountType param_count; // The actual number of parameters present in this function *call*.  Left uninitialized except for functions.
  318.     DerefLengthType length; // Listed only after byte-sized fields, due to it being a WORD.
  319. };
  320.  
  321. typedef UCHAR ArgTypeType;  // UCHAR vs. an enum, to save memory.
  322. #define ARG_TYPE_NORMAL     (UCHAR)0
  323. #define ARG_TYPE_INPUT_VAR  (UCHAR)1
  324. #define ARG_TYPE_OUTPUT_VAR (UCHAR)2
  325.  
  326. struct ArgStruct
  327. {
  328.     ArgTypeType type;
  329.     bool is_expression; // Whether this ARG is known to contain an expression.
  330.     // Above are kept adjacent to each other to conserve memory (any fields that aren't an even
  331.     // multiple of 4, if adjacent to each other, consume less memory due to default byte alignment
  332.     // setting [which helps performance]).
  333.     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.
  334.     char *text;
  335.     DerefType *deref;  // Will hold a NULL-terminated array of var-deref locations within <text>.
  336. };
  337.  
  338.  
  339. // Some of these lengths and such are based on the MSDN example at
  340. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/enumerating_registry_subkeys.asp:
  341. // UPDATE for v1.0.44.07: Someone reported that a stack overflow was possible, implying that it only happens
  342. // during extremely deep nesting of subkey names (perhaps a hundred or more nested subkeys).  Upon review, it seems
  343. // that the prior limit of 16383 for value-name-length is higher than needed; testing shows that a value name can't
  344. // be longer than 259 (limit might even be 255 if API vs. RegEdit is used to create the name).  Testing also shows
  345. // that the total path name of a registry item (including item/value name but excluding the name of the root key)
  346. // obeys the same limit.
  347. #define MAX_REG_ITEM_LENGTH 259
  348. #define REG_SUBKEY -2 // Custom type, not standard in Windows.
  349. struct RegItemStruct
  350. {
  351.     HKEY root_key_type, root_key;  // root_key_type is always a local HKEY, whereas root_key can be a remote handle.
  352.     char subkey[MAX_REG_ITEM_LENGTH + 1];  // The branch of the registry where this subkey or value is located.
  353.     char name[MAX_REG_ITEM_LENGTH + 1]; // The subkey or value name.
  354.     DWORD type; // Value Type (e.g REG_DWORD). This is the length used by MSDN in their example code.
  355.     FILETIME ftLastWriteTime; // Non-initialized.
  356.     void InitForValues() {ftLastWriteTime.dwHighDateTime = ftLastWriteTime.dwLowDateTime = 0;}
  357.     void InitForSubkeys() {type = REG_SUBKEY;}  // To distinguish REG_DWORD and such from the subkeys themselves.
  358.     RegItemStruct(HKEY aRootKeyType, HKEY aRootKey, char *aSubKey)
  359.         : root_key_type(aRootKeyType), root_key(aRootKey), type(REG_NONE)
  360.     {
  361.         *name = '\0';
  362.         // Make a local copy on the caller's stack so that if the current script subroutine is
  363.         // interrupted to allow another to run, the contents of the deref buffer is saved here:
  364.         strlcpy(subkey, aSubKey, sizeof(subkey));
  365.         // Even though the call may work with a trailing backslash, it's best to remove it
  366.         // so that consistent results are delivered to the user.  For example, if the script
  367.         // is enumerating recursively into a subkey, subkeys deeper down will not include the
  368.         // trailing backslash when they are reported.  So the user's own subkey should not
  369.         // have one either so that when A_ScriptSubKey is referenced in the script, it will
  370.         // always show up as the value without a trailing backslash:
  371.         size_t length = strlen(subkey);
  372.         if (length && subkey[length - 1] == '\\')
  373.             subkey[length - 1] = '\0';
  374.     }
  375. };
  376.  
  377. struct LoopReadFileStruct
  378. {
  379.     FILE *mReadFile, *mWriteFile;
  380.     char mWriteFileName[MAX_PATH];
  381.     #define READ_FILE_LINE_SIZE (64 * 1024)  // This is also used by FileReadLine().
  382.     char mCurrentLine[READ_FILE_LINE_SIZE];
  383.     LoopReadFileStruct(FILE *aReadFile, char *aWriteFileName)
  384.         : mReadFile(aReadFile), mWriteFile(NULL) // mWriteFile is opened by FileAppend() only upon first use.
  385.     {
  386.         // Use our own buffer because caller's is volatile due to possibly being in the deref buffer:
  387.         strlcpy(mWriteFileName, aWriteFileName, sizeof(mWriteFileName));
  388.         *mCurrentLine = '\0';
  389.     }
  390. };
  391.  
  392.  
  393. typedef UCHAR ArgCountType;
  394. #define MAX_ARGS 20   // Maximum number of args used by any command.
  395.  
  396.  
  397. enum DllArgTypes {DLL_ARG_INVALID, DLL_ARG_STR, DLL_ARG_INT, DLL_ARG_SHORT, DLL_ARG_CHAR, DLL_ARG_INT64
  398.     , DLL_ARG_FLOAT, DLL_ARG_DOUBLE};
  399.  
  400.  
  401. // Note that currently this value must fit into a sc_type variable because that is how TextToKey()
  402. // stores it in the hotkey class.  sc_type is currently a UINT, and will always be at least a
  403. // WORD in size, so it shouldn't be much of an issue:
  404. #define MAX_JOYSTICKS 16  // The maximum allowed by any Windows operating system.
  405. #define MAX_JOY_BUTTONS 32 // Also the max that Windows supports.
  406. enum JoyControls {JOYCTRL_INVALID, JOYCTRL_XPOS, JOYCTRL_YPOS, JOYCTRL_ZPOS
  407. , JOYCTRL_RPOS, JOYCTRL_UPOS, JOYCTRL_VPOS, JOYCTRL_POV
  408. , JOYCTRL_NAME, JOYCTRL_BUTTONS, JOYCTRL_AXES, JOYCTRL_INFO
  409. , JOYCTRL_1, JOYCTRL_2, JOYCTRL_3, JOYCTRL_4, JOYCTRL_5, JOYCTRL_6, JOYCTRL_7, JOYCTRL_8  // Buttons.
  410. , JOYCTRL_9, JOYCTRL_10, JOYCTRL_11, JOYCTRL_12, JOYCTRL_13, JOYCTRL_14, JOYCTRL_15, JOYCTRL_16
  411. , JOYCTRL_17, JOYCTRL_18, JOYCTRL_19, JOYCTRL_20, JOYCTRL_21, JOYCTRL_22, JOYCTRL_23, JOYCTRL_24
  412. , JOYCTRL_25, JOYCTRL_26, JOYCTRL_27, JOYCTRL_28, JOYCTRL_29, JOYCTRL_30, JOYCTRL_31, JOYCTRL_32
  413. , JOYCTRL_BUTTON_MAX = JOYCTRL_32
  414. };
  415. #define IS_JOYSTICK_BUTTON(joy) (joy >= JOYCTRL_1 && joy <= JOYCTRL_BUTTON_MAX)
  416.  
  417. enum WinGetCmds {WINGET_CMD_INVALID, WINGET_CMD_ID, WINGET_CMD_IDLAST, WINGET_CMD_PID, WINGET_CMD_PROCESSNAME
  418.     , WINGET_CMD_COUNT, WINGET_CMD_LIST, WINGET_CMD_MINMAX, WINGET_CMD_CONTROLLIST, WINGET_CMD_CONTROLLISTHWND
  419.     , WINGET_CMD_STYLE, WINGET_CMD_EXSTYLE, WINGET_CMD_TRANSPARENT, WINGET_CMD_TRANSCOLOR
  420. };
  421.  
  422. enum SysGetCmds {SYSGET_CMD_INVALID, SYSGET_CMD_METRICS, SYSGET_CMD_MONITORCOUNT, SYSGET_CMD_MONITORPRIMARY
  423.     , SYSGET_CMD_MONITORAREA, SYSGET_CMD_MONITORWORKAREA, SYSGET_CMD_MONITORNAME
  424. };
  425.  
  426. enum TransformCmds {TRANS_CMD_INVALID, TRANS_CMD_ASC, TRANS_CMD_CHR, TRANS_CMD_DEREF
  427.     , TRANS_CMD_UNICODE, TRANS_CMD_HTML
  428.     , TRANS_CMD_MOD, TRANS_CMD_POW, TRANS_CMD_EXP, TRANS_CMD_SQRT, TRANS_CMD_LOG, TRANS_CMD_LN
  429.     , TRANS_CMD_ROUND, TRANS_CMD_CEIL, TRANS_CMD_FLOOR, TRANS_CMD_ABS
  430.     , TRANS_CMD_SIN, TRANS_CMD_COS, TRANS_CMD_TAN, TRANS_CMD_ASIN, TRANS_CMD_ACOS, TRANS_CMD_ATAN
  431.     , TRANS_CMD_BITAND, TRANS_CMD_BITOR, TRANS_CMD_BITXOR, TRANS_CMD_BITNOT
  432.     , TRANS_CMD_BITSHIFTLEFT, TRANS_CMD_BITSHIFTRIGHT
  433. };
  434.  
  435. enum MenuCommands {MENU_CMD_INVALID, MENU_CMD_SHOW, MENU_CMD_USEERRORLEVEL
  436.     , MENU_CMD_ADD, MENU_CMD_RENAME, MENU_CMD_CHECK, MENU_CMD_UNCHECK, MENU_CMD_TOGGLECHECK
  437.     , MENU_CMD_ENABLE, MENU_CMD_DISABLE, MENU_CMD_TOGGLEENABLE
  438.     , MENU_CMD_STANDARD, MENU_CMD_NOSTANDARD, MENU_CMD_COLOR, MENU_CMD_DEFAULT, MENU_CMD_NODEFAULT
  439.     , MENU_CMD_DELETE, MENU_CMD_DELETEALL, MENU_CMD_TIP, MENU_CMD_ICON, MENU_CMD_NOICON
  440.     , MENU_CMD_CLICK, MENU_CMD_MAINWINDOW, MENU_CMD_NOMAINWINDOW
  441. };
  442.  
  443. #define AHK_LV_SELECT       0x0100
  444. #define AHK_LV_DESELECT     0x0200
  445. #define AHK_LV_FOCUS        0x0400
  446. #define AHK_LV_DEFOCUS      0x0800
  447. #define AHK_LV_CHECK        0x1000
  448. #define AHK_LV_UNCHECK      0x2000
  449. #define AHK_LV_DROPHILITE   0x4000
  450. #define AHK_LV_UNDROPHILITE 0x8000
  451. // Although there's no room remaining in the BYTE for LVIS_CUT (AHK_LV_CUT) [assuming it's ever needed],
  452. // it might be possible to squeeze more info into it as follows:
  453. // Each pair of bits can represent three values (other than zero).  But since only two values are needed
  454. // (since an item can't be both selected an deselected simultaneously), one value in each pair is available
  455. // for future use such as LVIS_CUT.
  456.  
  457. enum GuiCommands {GUI_CMD_INVALID, GUI_CMD_OPTIONS, GUI_CMD_ADD, GUI_CMD_MARGIN, GUI_CMD_MENU
  458.     , GUI_CMD_SHOW, GUI_CMD_SUBMIT, GUI_CMD_CANCEL, GUI_CMD_MINIMIZE, GUI_CMD_MAXIMIZE, GUI_CMD_RESTORE
  459.     , GUI_CMD_DESTROY, GUI_CMD_FONT, GUI_CMD_TAB, GUI_CMD_LISTVIEW, GUI_CMD_TREEVIEW, GUI_CMD_DEFAULT
  460.     , GUI_CMD_COLOR, GUI_CMD_FLASH
  461. };
  462.  
  463. enum GuiControlCmds {GUICONTROL_CMD_INVALID, GUICONTROL_CMD_OPTIONS, GUICONTROL_CMD_CONTENTS, GUICONTROL_CMD_TEXT
  464.     , GUICONTROL_CMD_MOVE, GUICONTROL_CMD_MOVEDRAW, GUICONTROL_CMD_FOCUS, GUICONTROL_CMD_ENABLE, GUICONTROL_CMD_DISABLE
  465.     , GUICONTROL_CMD_SHOW, GUICONTROL_CMD_HIDE, GUICONTROL_CMD_CHOOSE, GUICONTROL_CMD_CHOOSESTRING
  466.     , GUICONTROL_CMD_FONT
  467. };
  468.  
  469. enum GuiControlGetCmds {GUICONTROLGET_CMD_INVALID, GUICONTROLGET_CMD_CONTENTS, GUICONTROLGET_CMD_POS
  470.     , GUICONTROLGET_CMD_FOCUS, GUICONTROLGET_CMD_FOCUSV, GUICONTROLGET_CMD_ENABLED, GUICONTROLGET_CMD_VISIBLE
  471.     , GUICONTROLGET_CMD_HWND
  472. };
  473.  
  474. typedef UCHAR GuiControls;
  475. enum GuiControlTypes {GUI_CONTROL_INVALID // GUI_CONTROL_INVALID must be zero due to things like ZeroMemory() on the struct.
  476.     , GUI_CONTROL_TEXT, GUI_CONTROL_PIC, GUI_CONTROL_GROUPBOX
  477.     , GUI_CONTROL_BUTTON, GUI_CONTROL_CHECKBOX, GUI_CONTROL_RADIO
  478.     , GUI_CONTROL_DROPDOWNLIST, GUI_CONTROL_COMBOBOX
  479.     , GUI_CONTROL_LISTBOX, GUI_CONTROL_LISTVIEW, GUI_CONTROL_TREEVIEW
  480.     , GUI_CONTROL_EDIT, GUI_CONTROL_DATETIME, GUI_CONTROL_MONTHCAL, GUI_CONTROL_HOTKEY
  481.     , GUI_CONTROL_UPDOWN, GUI_CONTROL_SLIDER, GUI_CONTROL_PROGRESS, GUI_CONTROL_TAB, GUI_CONTROL_TAB2
  482.     , GUI_CONTROL_STATUSBAR}; // Kept last to reflect it being bottommost in switch()s (for perf), since not too often used.
  483.  
  484. enum ThreadCommands {THREAD_CMD_INVALID, THREAD_CMD_PRIORITY, THREAD_CMD_INTERRUPT, THREAD_CMD_NOTIMERS};
  485.  
  486. #define PROCESS_PRIORITY_LETTERS "LBNAHR"
  487. enum ProcessCmds {PROCESS_CMD_INVALID, PROCESS_CMD_EXIST, PROCESS_CMD_CLOSE, PROCESS_CMD_PRIORITY
  488.     , PROCESS_CMD_WAIT, PROCESS_CMD_WAITCLOSE};
  489.  
  490. enum ControlCmds {CONTROL_CMD_INVALID, CONTROL_CMD_CHECK, CONTROL_CMD_UNCHECK
  491.     , CONTROL_CMD_ENABLE, CONTROL_CMD_DISABLE, CONTROL_CMD_SHOW, CONTROL_CMD_HIDE
  492.     , CONTROL_CMD_STYLE, CONTROL_CMD_EXSTYLE
  493.     , CONTROL_CMD_SHOWDROPDOWN, CONTROL_CMD_HIDEDROPDOWN
  494.     , CONTROL_CMD_TABLEFT, CONTROL_CMD_TABRIGHT
  495.     , CONTROL_CMD_ADD, CONTROL_CMD_DELETE, CONTROL_CMD_CHOOSE
  496.     , CONTROL_CMD_CHOOSESTRING, CONTROL_CMD_EDITPASTE};
  497.  
  498. enum ControlGetCmds {CONTROLGET_CMD_INVALID, CONTROLGET_CMD_CHECKED, CONTROLGET_CMD_ENABLED
  499.     , CONTROLGET_CMD_VISIBLE, CONTROLGET_CMD_TAB, CONTROLGET_CMD_FINDSTRING
  500.     , CONTROLGET_CMD_CHOICE, CONTROLGET_CMD_LIST, CONTROLGET_CMD_LINECOUNT, CONTROLGET_CMD_CURRENTLINE
  501.     , CONTROLGET_CMD_CURRENTCOL, CONTROLGET_CMD_LINE, CONTROLGET_CMD_SELECTED
  502.     , CONTROLGET_CMD_STYLE, CONTROLGET_CMD_EXSTYLE, CONTROLGET_CMD_HWND};
  503.  
  504. enum DriveCmds {DRIVE_CMD_INVALID, DRIVE_CMD_EJECT, DRIVE_CMD_LOCK, DRIVE_CMD_UNLOCK, DRIVE_CMD_LABEL};
  505.  
  506. enum DriveGetCmds {DRIVEGET_CMD_INVALID, DRIVEGET_CMD_LIST, DRIVEGET_CMD_FILESYSTEM, DRIVEGET_CMD_LABEL
  507.     , DRIVEGET_CMD_SETLABEL, DRIVEGET_CMD_SERIAL, DRIVEGET_CMD_TYPE, DRIVEGET_CMD_STATUS
  508.     , DRIVEGET_CMD_STATUSCD, DRIVEGET_CMD_CAPACITY};
  509.  
  510. enum WinSetAttributes {WINSET_INVALID, WINSET_TRANSPARENT, WINSET_TRANSCOLOR, WINSET_ALWAYSONTOP
  511.     , WINSET_BOTTOM, WINSET_TOP, WINSET_STYLE, WINSET_EXSTYLE, WINSET_REDRAW, WINSET_ENABLE, WINSET_DISABLE
  512.     , WINSET_REGION};
  513.  
  514.  
  515. class Label; // Forward declaration so that each can use the other.
  516. class Line
  517. {
  518. private:
  519.     #define SET_S_DEREF_BUF(ptr, size) sDerefBuf = ptr, sDerefBufSize = size
  520.     #define NULLIFY_S_DEREF_BUF \
  521.     {\
  522.         SET_S_DEREF_BUF(NULL, 0);\
  523.         if (sDerefBufSize > LARGE_DEREF_BUF_SIZE)\
  524.             --sLargeDerefBufs;\
  525.     }
  526.     static char *sDerefBuf;  // Buffer to hold the values of any args that need to be dereferenced.
  527.     static size_t sDerefBufSize;
  528.     static int sLargeDerefBufs;
  529.  
  530.     // Static because only one line can be Expanded at a time (not to mention the fact that we
  531.     // wouldn't want the size of each line to be expanded by this size):
  532.     static char *sArgDeref[MAX_ARGS];
  533.     static Var *sArgVar[MAX_ARGS];
  534.  
  535.     ResultType EvaluateCondition();
  536.     ResultType Line::PerformLoop(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine
  537.         , __int64 aIterationLimit, bool aIsInfinite);
  538.     ResultType Line::PerformLoopFilePattern(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine
  539.         , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, char *aFilePattern);
  540.     ResultType PerformLoopReg(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine
  541.         , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, HKEY aRootKeyType, HKEY aRootKey, char *aRegSubkey);
  542.     ResultType PerformLoopParse(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine);
  543.     ResultType Line::PerformLoopParseCSV(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine);
  544.     ResultType PerformLoopReadFile(char **apReturnValue, bool &aContinueMainLoop, Line *&aJumpToLine, FILE *aReadFile, char *aWriteFileName);
  545.     ResultType Perform();
  546.  
  547.     ResultType MouseGetPos(DWORD aOptions);
  548.     ResultType FormatTime(char *aYYYYMMDD, char *aFormat);
  549.     ResultType PerformAssign();
  550.     ResultType StringReplace();
  551.     ResultType StringSplit(char *aArrayName, char *aInputString, char *aDelimiterList, char *aOmitList);
  552.     ResultType SplitPath(char *aFileSpec);
  553.     ResultType PerformSort(char *aContents, char *aOptions);
  554.     ResultType GetKeyJoyState(char *aKeyName, char *aOption);
  555.     ResultType DriveSpace(char *aPath, bool aGetFreeSpace);
  556.     ResultType Drive(char *aCmd, char *aValue, char *aValue2);
  557.     ResultType DriveLock(char aDriveLetter, bool aLockIt);
  558.     ResultType DriveGet(char *aCmd, char *aValue);
  559.     ResultType SoundSetGet(char *aSetting, DWORD aComponentType, int aComponentInstance
  560.         , DWORD aControlType, UINT aMixerID);
  561.     ResultType SoundGetWaveVolume(HWAVEOUT aDeviceID);
  562.     ResultType SoundSetWaveVolume(char *aVolume, HWAVEOUT aDeviceID);
  563.     ResultType SoundPlay(char *aFilespec, bool aSleepUntilDone);
  564.     ResultType URLDownloadToFile(char *aURL, char *aFilespec);
  565.     ResultType FileSelectFile(char *aOptions, char *aWorkingDir, char *aGreeting, char *aFilter);
  566.  
  567.     // Bitwise flags:
  568.     #define FSF_ALLOW_CREATE 0x01
  569.     #define FSF_EDITBOX      0x02
  570.     ResultType FileSelectFolder(char *aRootDir, char *aOptions, char *aGreeting);
  571.  
  572.     ResultType FileGetShortcut(char *aShortcutFile);
  573.     ResultType FileCreateShortcut(char *aTargetFile, char *aShortcutFile, char *aWorkingDir, char *aArgs
  574.         , char *aDescription, char *aIconFile, char *aHotkey, char *aIconNumber, char *aRunState);
  575.     ResultType FileCreateDir(char *aDirSpec);
  576.     ResultType FileRead(char *aFilespec);
  577.     ResultType FileReadLine(char *aFilespec, char *aLineNumber);
  578.     ResultType FileAppend(char *aFilespec, char *aBuf, LoopReadFileStruct *aCurrentReadFile);
  579.     ResultType WriteClipboardToFile(char *aFilespec);
  580.     ResultType ReadClipboardFromFile(HANDLE hfile);
  581.     ResultType FileDelete();
  582.     ResultType FileRecycle(char *aFilePattern);
  583.     ResultType FileRecycleEmpty(char *aDriveLetter);
  584.     ResultType FileInstall(char *aSource, char *aDest, char *aFlag);
  585.  
  586.     ResultType FileGetAttrib(char *aFilespec);
  587.     int FileSetAttrib(char *aAttributes, char *aFilePattern, FileLoopModeType aOperateOnFolders
  588.         , bool aDoRecurse, bool aCalledRecursively = false);
  589.     ResultType FileGetTime(char *aFilespec, char aWhichTime);
  590.     int FileSetTime(char *aYYYYMMDD, char *aFilePattern, char aWhichTime
  591.         , FileLoopModeType aOperateOnFolders, bool aDoRecurse, bool aCalledRecursively = false);
  592.     ResultType FileGetSize(char *aFilespec, char *aGranularity);
  593.     ResultType FileGetVersion(char *aFilespec);
  594.  
  595.     ResultType IniRead(char *aFilespec, char *aSection, char *aKey, char *aDefault);
  596.     ResultType IniWrite(char *aValue, char *aFilespec, char *aSection, char *aKey);
  597.     ResultType IniDelete(char *aFilespec, char *aSection, char *aKey);
  598.     ResultType RegRead(HKEY aRootKey, char *aRegSubkey, char *aValueName);
  599.     ResultType RegWrite(DWORD aValueType, HKEY aRootKey, char *aRegSubkey, char *aValueName, char *aValue);
  600.     ResultType RegDelete(HKEY aRootKey, char *aRegSubkey, char *aValueName);
  601.     static bool RegRemoveSubkeys(HKEY hRegKey);
  602.  
  603.     #define DESTROY_SPLASH \
  604.     {\
  605.         if (g_hWndSplash && IsWindow(g_hWndSplash))\
  606.             DestroyWindow(g_hWndSplash);\
  607.         g_hWndSplash = NULL;\
  608.     }
  609.     ResultType SplashTextOn(int aWidth, int aHeight, char *aTitle, char *aText);
  610.     ResultType Splash(char *aOptions, char *aSubText, char *aMainText, char *aTitle, char *aFontName
  611.         , char *aImageFile, bool aSplashImage);
  612.  
  613.     ResultType ToolTip(char *aText, char *aX, char *aY, char *aID);
  614.     ResultType TrayTip(char *aTitle, char *aText, char *aTimeout, char *aOptions);
  615.     ResultType Transform(char *aCmd, char *aValue1, char *aValue2);
  616.     ResultType Input(); // The Input command.
  617.  
  618.     #define SW_NONE -1
  619.     ResultType PerformShowWindow(ActionTypeType aActionType, char *aTitle = "", char *aText = ""
  620.         , char *aExcludeTitle = "", char *aExcludeText = "");
  621.     ResultType PerformWait();
  622.  
  623.     ResultType WinMove(char *aTitle, char *aText, char *aX, char *aY
  624.         , char *aWidth = "", char *aHeight = "", char *aExcludeTitle = "", char *aExcludeText = "");
  625.     ResultType WinMenuSelectItem(char *aTitle, char *aText, char *aMenu1, char *aMenu2
  626.         , char *aMenu3, char *aMenu4, char *aMenu5, char *aMenu6, char *aMenu7
  627.         , char *aExcludeTitle, char *aExcludeText);
  628.     ResultType ControlSend(char *aControl, char *aKeysToSend, char *aTitle, char *aText
  629.         , char *aExcludeTitle, char *aExcludeText, bool aSendRaw);
  630.     ResultType ControlClick(vk_type aVK, int aClickCount, char *aOptions, char *aControl
  631.         , char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  632.     ResultType ControlMove(char *aControl, char *aX, char *aY, char *aWidth, char *aHeight
  633.         , char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  634.     ResultType ControlGetPos(char *aControl, char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  635.     ResultType ControlGetFocus(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  636.     ResultType ControlFocus(char *aControl, char *aTitle, char *aText
  637.         , char *aExcludeTitle, char *aExcludeText);
  638.     ResultType ControlSetText(char *aControl, char *aNewText, char *aTitle, char *aText
  639.         , char *aExcludeTitle, char *aExcludeText);
  640.     ResultType ControlGetText(char *aControl, char *aTitle, char *aText
  641.         , char *aExcludeTitle, char *aExcludeText);
  642.     ResultType ControlGetListView(Var &aOutputVar, HWND aHwnd, char *aOptions);
  643.     ResultType Control(char *aCmd, char *aValue, char *aControl, char *aTitle, char *aText
  644.         , char *aExcludeTitle, char *aExcludeText);
  645.     ResultType ControlGet(char *aCommand, char *aValue, char *aControl, char *aTitle, char *aText
  646.         , char *aExcludeTitle, char *aExcludeText);
  647.     ResultType GuiControl(char *aCommand, char *aControlID, char *aParam3);
  648.     ResultType GuiControlGet(char *aCommand, char *aControlID, char *aParam3);
  649.     ResultType StatusBarGetText(char *aPart, char *aTitle, char *aText
  650.         , char *aExcludeTitle, char *aExcludeText);
  651.     ResultType StatusBarWait(char *aTextToWaitFor, char *aSeconds, char *aPart, char *aTitle, char *aText
  652.         , char *aInterval, char *aExcludeTitle, char *aExcludeText);
  653.     ResultType ScriptPostSendMessage(bool aUseSend);
  654.     ResultType ScriptProcess(char *aCmd, char *aProcess, char *aParam3);
  655.     ResultType WinSet(char *aAttrib, char *aValue, char *aTitle, char *aText
  656.         , char *aExcludeTitle, char *aExcludeText);
  657.     ResultType WinSetTitle(char *aTitle, char *aText, char *aNewTitle
  658.         , char *aExcludeTitle = "", char *aExcludeText = "");
  659.     ResultType WinGetTitle(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  660.     ResultType WinGetClass(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  661.     ResultType WinGet(char *aCmd, char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  662.     ResultType WinGetControlList(Var &aOutputVar, HWND aTargetWindow, bool aFetchHWNDs);
  663.     ResultType WinGetText(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  664.     ResultType WinGetPos(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  665.     ResultType EnvGet(char *aEnvVarName);
  666.     ResultType SysGet(char *aCmd, char *aValue);
  667.     ResultType PixelSearch(int aLeft, int aTop, int aRight, int aBottom, COLORREF aColorBGR, int aVariation
  668.         , char *aOptions, bool aIsPixelGetColor);
  669.     ResultType ImageSearch(int aLeft, int aTop, int aRight, int aBottom, char *aImageFile);
  670.     ResultType PixelGetColor(int aX, int aY, char *aOptions);
  671.  
  672.     static ResultType SetToggleState(vk_type aVK, ToggleValueType &ForceLock, char *aToggleText);
  673.  
  674. public:
  675.     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  676.     // due to byte-alignment:
  677.     ActionTypeType mActionType; // What type of line this is.
  678.     ArgCountType mArgc; // How many arguments exist in mArg[].
  679.     FileIndexType mFileIndex; // Which file the line came from.  0 is the first, and it's the main script file.
  680.  
  681.     ArgStruct *mArg; // Will be used to hold a dynamic array of dynamic Args.
  682.     LineNumberType mLineNumber;  // The line number in the file from which the script was loaded, for debugging.
  683.     AttributeType mAttribute;
  684.     Line *mPrevLine, *mNextLine; // The prev & next lines adjacent to this one in the linked list; NULL if none.
  685.     Line *mRelatedLine;  // e.g. the "else" that belongs to this "if"
  686.     Line *mParentLine; // Indicates the parent (owner) of this line.
  687.     // Probably best to always use ARG1 even if other things have supposedly verfied
  688.     // that it exists, since it's count-check should make the dereference of a NULL
  689.     // pointer (or accessing non-existent array elements) virtually impossible.
  690.     // Empty-string is probably more universally useful than NULL, since some
  691.     // API calls and other functions might not appreciate receiving NULLs.  In addition,
  692.     // always remembering to have to check for NULL makes things harder to maintain
  693.     // and more bug-prone.  The below macros rely upon the fact that the individual
  694.     // elements of mArg cannot be NULL (because they're explicitly set to be blank
  695.     // when the user has omitted an arg in between two non-blank args).  Later, might
  696.     // want to review if any of the API calls used expect a string whose contents are
  697.     // modifiable.
  698.     #define RAW_ARG1 (mArgc > 0 ? mArg[0].text : "")
  699.     #define RAW_ARG2 (mArgc > 1 ? mArg[1].text : "")
  700.     #define RAW_ARG3 (mArgc > 2 ? mArg[2].text : "")
  701.     #define RAW_ARG4 (mArgc > 3 ? mArg[3].text : "")
  702.     #define RAW_ARG5 (mArgc > 4 ? mArg[4].text : "")
  703.     #define RAW_ARG6 (mArgc > 5 ? mArg[5].text : "")
  704.     #define RAW_ARG7 (mArgc > 6 ? mArg[6].text : "")
  705.     #define RAW_ARG8 (mArgc > 7 ? mArg[7].text : "")
  706.  
  707.     #define LINE_RAW_ARG1 (line->mArgc > 0 ? line->mArg[0].text : "")
  708.     #define LINE_RAW_ARG2 (line->mArgc > 1 ? line->mArg[1].text : "")
  709.     #define LINE_RAW_ARG3 (line->mArgc > 2 ? line->mArg[2].text : "")
  710.     #define LINE_RAW_ARG4 (line->mArgc > 3 ? line->mArg[3].text : "")
  711.     #define LINE_RAW_ARG5 (line->mArgc > 4 ? line->mArg[4].text : "")
  712.     #define LINE_RAW_ARG6 (line->mArgc > 5 ? line->mArg[5].text : "")
  713.     #define LINE_RAW_ARG7 (line->mArgc > 6 ? line->mArg[6].text : "")
  714.     #define LINE_RAW_ARG8 (line->mArgc > 7 ? line->mArg[7].text : "")
  715.     #define LINE_RAW_ARG9 (line->mArgc > 8 ? line->mArg[8].text : "")
  716.     
  717.     #define NEW_RAW_ARG1 (aArgc > 0 ? new_arg[0].text : "") // Helps performance to use this vs. LINE_RAW_ARG where possible.
  718.     #define NEW_RAW_ARG2 (aArgc > 1 ? new_arg[1].text : "")
  719.     #define NEW_RAW_ARG3 (aArgc > 2 ? new_arg[2].text : "")
  720.     #define NEW_RAW_ARG4 (aArgc > 3 ? new_arg[3].text : "")
  721.     #define NEW_RAW_ARG5 (aArgc > 4 ? new_arg[4].text : "")
  722.     #define NEW_RAW_ARG6 (aArgc > 5 ? new_arg[5].text : "")
  723.     #define NEW_RAW_ARG7 (aArgc > 6 ? new_arg[6].text : "")
  724.     #define NEW_RAW_ARG8 (aArgc > 7 ? new_arg[7].text : "")
  725.     #define NEW_RAW_ARG9 (aArgc > 8 ? new_arg[8].text : "")
  726.     
  727.     #define SAVED_ARG1 (mArgc > 0 ? arg[0] : "")
  728.     #define SAVED_ARG2 (mArgc > 1 ? arg[1] : "")
  729.     #define SAVED_ARG3 (mArgc > 2 ? arg[2] : "")
  730.     #define SAVED_ARG4 (mArgc > 3 ? arg[3] : "")
  731.     #define SAVED_ARG5 (mArgc > 4 ? arg[4] : "")
  732.  
  733.     // For the below, it is the caller's responsibility to ensure that mArgc is
  734.     // large enough (either via load-time validation or a runtime check of mArgc).
  735.     // This is because for performance reasons, the sArgVar entry for omitted args isn't
  736.     // initialized, so may have an old/obsolete value from some previous command.
  737.     #define OUTPUT_VAR (*sArgVar) // ExpandArgs() has ensured this first ArgVar is always initialized, so there's never any need to check mArgc > 0.
  738.     #define ARGVARRAW1 (*sArgVar) // i.e. sArgVar[0], and same as OUTPUT_VAR (it's a duplicate to help readability).
  739.     #define ARGVARRAW2 (sArgVar[1]) // It's called RAW because its user is responsible for ensuring the arg exists by checking mArgc at loadtime or runtime.
  740.     #define ARGVAR1 ARGVARRAW1 // This first one doesn't need the check below because ExpandArgs() has ensured it's initialized.
  741.     #define ARGVAR2 (mArgc > 1 ? sArgVar[1] : NULL) // Caller relies on the check of mArgc because for performance,
  742.     #define ARGVAR3 (mArgc > 2 ? sArgVar[2] : NULL) // sArgVar[] isn't initialied for parameters the script
  743.     #define ARGVAR4 (mArgc > 3 ? sArgVar[3] : NULL) // omitted entirely from the end of the parameter list.
  744.     #define ARGVAR5 (mArgc > 4 ? sArgVar[4] : NULL)
  745.     #define ARGVAR6 (mArgc > 5 ? sArgVar[5] : NULL)
  746.     #define ARGVAR7 (mArgc > 6 ? sArgVar[6] : NULL)
  747.     #define ARGVAR8 (mArgc > 7 ? sArgVar[7] : NULL)
  748.  
  749.     #define ARG1 sArgDeref[0] // These are the expanded/resolved parameters for the currently-executing command.
  750.     #define ARG2 sArgDeref[1] // They're populated by ExpandArgs().
  751.     #define ARG3 sArgDeref[2]
  752.     #define ARG4 sArgDeref[3]
  753.     #define ARG5 sArgDeref[4]
  754.     #define ARG6 sArgDeref[5]
  755.     #define ARG7 sArgDeref[6]
  756.     #define ARG8 sArgDeref[7]
  757.     #define ARG9 sArgDeref[8]
  758.     #define ARG10 sArgDeref[9]
  759.     #define ARG11 sArgDeref[10]
  760.  
  761.     #define TWO_ARGS    ARG1, ARG2
  762.     #define THREE_ARGS  ARG1, ARG2, ARG3
  763.     #define FOUR_ARGS   ARG1, ARG2, ARG3, ARG4
  764.     #define FIVE_ARGS   ARG1, ARG2, ARG3, ARG4, ARG5
  765.     #define SIX_ARGS    ARG1, ARG2, ARG3, ARG4, ARG5, ARG6
  766.     #define SEVEN_ARGS  ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7
  767.     #define EIGHT_ARGS  ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8
  768.     #define NINE_ARGS   ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9
  769.     #define TEN_ARGS    ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10
  770.     #define ELEVEN_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10, ARG11
  771.  
  772.     // If the arg's text is non-blank, it means the variable is a dynamic name such as array%i%
  773.     // that must be resolved at runtime rather than load-time.  Therefore, this macro must not
  774.     // be used without first having checked that arg.text is blank:
  775.     #define VAR(arg) ((Var *)arg.deref)
  776.     // Uses arg number (i.e. the first arg is 1, not 0).  Caller must ensure that ArgNum >= 1 and that
  777.     // the arg in question is an input or output variable (since that isn't checked there):
  778.     #define ARG_HAS_VAR(ArgNum) (mArgc >= ArgNum && (*mArg[ArgNum-1].text || mArg[ArgNum-1].deref))
  779.  
  780.     // Shouldn't go much higher than 400 since the main window's Edit control is currently limited
  781.     // to 64KB to be compatible with the Win9x limit.  Avg. line length is probably under 100 for
  782.     // the vast majority of scripts, so 400 seems unlikely to exceed the buffer size.  Even in the
  783.     // worst case where the buffer size is exceeded, the text is simply truncated, so it's not too bad:
  784.     #define LINE_LOG_SIZE 400  // See above.
  785.     static Line *sLog[LINE_LOG_SIZE];
  786.     static DWORD sLogTick[LINE_LOG_SIZE];
  787.     static int sLogNext;
  788.  
  789. #ifdef AUTOHOTKEYSC  // Reduces code size to omit things that are unused, and helps catch bugs at compile-time.
  790.     static char *sSourceFile[1]; // Only need to be able to hold the main script since compiled scripts don't support dynamic including.
  791. #else
  792.     static char **sSourceFile;   // Will hold an array of strings.
  793.     static int sMaxSourceFiles;  // Maximum number of items it can currently hold.
  794. #endif
  795.     static int sSourceFileCount; // Number of items in the above array.
  796.  
  797.     static void FreeDerefBufIfLarge();
  798.  
  799.     ResultType ExecUntil(ExecUntilMode aMode, char **apReturnValue = NULL, Line **apJumpToLine = NULL);
  800.  
  801.     // The following are characters that can't legally occur after an AND or OR.  It excludes all unary operators
  802.     // "!~*&-+" as well as the parentheses chars "()":
  803.     #define EXPR_CORE "<>=/|^,:"
  804.     // The characters common to both EXPR_TELLTALES and EXPR_OPERAND_TERMINATORS:
  805.     #define EXPR_COMMON " \t" EXPR_CORE "*&~!()"  // Space and Tab are included at the beginning for performance.
  806.     #define EXPR_COMMON_FORBIDDEN_BYREF "<>/|^,*&~!" // Omits space/tab because operators like := can have them. Omits colon because want to be able to pass a ternary byref. Omits = because colon is omitted (otherwise the logic is written in a way that wouldn't allow :=). Omits parentheses because a variable or assignment can be enclosed in them even though they're redundant.
  807.     #define CONTINUATION_LINE_SYMBOLS EXPR_CORE ".+-*&!?~" // v1.0.46.
  808.     // Characters whose presence in a mandatory-numeric param make it an expression for certain.
  809.     // + and - are not included here because legacy numeric parameters can contain unary plus or minus,
  810.     // e.g. WinMove, -%x%, -%y%:
  811.     #define EXPR_TELLTALES EXPR_COMMON "\""
  812.     // Characters that mark the end of an operand inside an expression.  Double-quote must not be included:
  813.     #define EXPR_OPERAND_TERMINATORS EXPR_COMMON "+-"
  814.     #define EXPR_ALL_SYMBOLS EXPR_OPERAND_TERMINATORS "\"" // Excludes '.' and '?' since they need special treatment due to the present/future allowance of them inside the names of variable and functions.
  815.     #define EXPR_FORBIDDEN_BYREF EXPR_COMMON_FORBIDDEN_BYREF ".+-\"" // Dot is also included.
  816.     #define EXPR_ILLEGAL_CHARS "'\\;`{}" // Characters illegal in an expression.
  817.     // The following HOTSTRING option recognizer is kept somewhat forgiving/non-specific for backward compatibility
  818.     // (e.g. scripts may have some invalid hotstring options, which are simply ignored).  This definition is here
  819.     // because it's related to continuation line symbols. Also, avoid ever adding "&" to hotstring options because
  820.     // it might introduce ambiguity in the differentiation of things like:
  821.     //    : & x::hotkey action
  822.     //    : & *::abbrev with leading colon::
  823.     #define IS_HOTSTRING_OPTION(chr) (isalnum(chr) || strchr("?*- \t", chr))
  824.     // The characters below are ordered with most-often used ones first, for performance:
  825.     #define DEFINE_END_FLAGS \
  826.         char end_flags[] = {' ', g_delimiter, '(', '\t', '<', '>', ':', '=', '+', '-', '*', '/', '!', '~', '&', '|', '^', '\0'}; // '\0' must be last.
  827.         // '?' and '.' are omitted from the above because they require special handling due to being permitted
  828.         // in the curruent or future names of variables and functions.
  829.     static bool StartsWithAssignmentOp(char *aStr) // RELATED TO ABOVE, so kept adjacent to it.
  830.     // Returns true if aStr begins with an assignment operator such as :=, >>=, ++, etc.
  831.     // For simplicity, this doesn't check that what comes AFTER an operator is valid.  For example,
  832.     // :== isn't valid, yet is reported as valid here because it starts with :=.
  833.     // Caller is responsible for having omitted leading whitespace, if desired.
  834.     {
  835.         if (!(*aStr && aStr[1])) // Relies on short-circuit boolean order.
  836.             return false;
  837.         char cp0 = *aStr;
  838.         switch(aStr[1])
  839.         {
  840.         // '=' is listed first for performance, since it's the most common.
  841.         case '=': return strchr(":+-*.|&^/", cp0); // Covers :=, +=, -=, *=, .=, |=, &=, ^=, /= (9 operators).
  842.         case '+': // Fall through to below. Covers ++.
  843.         case '-': return cp0 == aStr[1]; // Covers --.
  844.         case '/': // Fall through to below. Covers //=.
  845.         case '>': // Fall through to below. covers >>=.
  846.         case '<': return cp0 == aStr[1] && aStr[2] == '='; // Covers <<=.
  847.         }
  848.         // Otherwise:
  849.         return false;
  850.     }
  851.  
  852.     size_t ArgLength(int aArgNum);
  853.     Var *ResolveVarOfArg(int aArgIndex, bool aCreateIfNecessary = true);
  854.     ResultType ExpandArgs(VarSizeType aSpaceNeeded = VARSIZE_ERROR, Var *aArgVar[] = NULL);
  855.     VarSizeType GetExpandedArgSize(bool aCalcDerefBufSize, Var *aArgVar[]);
  856.     char *ExpandArg(char *aBuf, int aArgIndex, Var *aArgVar = NULL);
  857.     char *ExpandExpression(int aArgIndex, ResultType &aResult, char *&aTarget, char *&aDerefBuf
  858.         , size_t &aDerefBufSize, char *aArgDeref[], size_t aExtraSize);
  859.  
  860.     ResultType Deref(Var *aOutputVar, char *aBuf);
  861.  
  862.     static bool FileIsFilteredOut(WIN32_FIND_DATA &aCurrentFile, FileLoopModeType aFileLoopMode
  863.         , char *aFilePath, size_t aFilePathLength);
  864.  
  865.     Label *GetJumpTarget(bool aIsDereferenced);
  866.     Label *IsJumpValid(Label &aTargetLabel);
  867.  
  868.     HWND DetermineTargetWindow(char *aTitle, char *aText, char *aExcludeTitle, char *aExcludeText);
  869.  
  870. #ifndef AUTOHOTKEYSC
  871.     static int ConvertEscapeChar(char *aFilespec);
  872.     static size_t ConvertEscapeCharGetLine(char *aBuf, int aMaxCharsToRead, FILE *fp);
  873. #endif  // The functions above are not needed by the self-contained version.
  874.  
  875.     
  876.     // This is in the .h file so that it's more likely the compiler's cost/benefit estimate will
  877.     // make it inline (since it is called from only one place).  Inline would be good since it
  878.     // is called frequently during script loading and is difficult to macro-ize in a way that
  879.     // retains readability.
  880.     static ArgTypeType ArgIsVar(ActionTypeType aActionType, int aArgIndex)
  881.     {
  882.         switch(aArgIndex)
  883.         {
  884.         case 0:  // Arg #1
  885.             switch(aActionType)
  886.             {
  887.             case ACT_ASSIGN:
  888.             case ACT_ASSIGNEXPR:
  889.             case ACT_ADD:
  890.             case ACT_SUB:
  891.             case ACT_MULT:
  892.             case ACT_DIV:
  893.             case ACT_TRANSFORM:
  894.             case ACT_STRINGLEFT:
  895.             case ACT_STRINGRIGHT:
  896.             case ACT_STRINGMID:
  897.             case ACT_STRINGTRIMLEFT:
  898.             case ACT_STRINGTRIMRIGHT:
  899.             case ACT_STRINGLOWER:
  900.             case ACT_STRINGUPPER:
  901.             case ACT_STRINGLEN:
  902.             case ACT_STRINGREPLACE:
  903.             case ACT_STRINGGETPOS:
  904.             case ACT_GETKEYSTATE:
  905.             case ACT_CONTROLGETFOCUS:
  906.             case ACT_CONTROLGETTEXT:
  907.             case ACT_CONTROLGET:
  908.             case ACT_GUICONTROLGET:
  909.             case ACT_STATUSBARGETTEXT:
  910.             case ACT_INPUTBOX:
  911.             case ACT_RANDOM:
  912.             case ACT_INIREAD:
  913.             case ACT_REGREAD:
  914.             case ACT_DRIVESPACEFREE:
  915.             case ACT_DRIVEGET:
  916.             case ACT_SOUNDGET:
  917.             case ACT_SOUNDGETWAVEVOLUME:
  918.             case ACT_FILEREAD:
  919.             case ACT_FILEREADLINE:
  920.             case ACT_FILEGETATTRIB:
  921.             case ACT_FILEGETTIME:
  922.             case ACT_FILEGETSIZE:
  923.             case ACT_FILEGETVERSION:
  924.             case ACT_FILESELECTFILE:
  925.             case ACT_FILESELECTFOLDER:
  926.             case ACT_MOUSEGETPOS:
  927.             case ACT_WINGETTITLE:
  928.             case ACT_WINGETCLASS:
  929.             case ACT_WINGET:
  930.             case ACT_WINGETTEXT:
  931.             case ACT_WINGETPOS:
  932.             case ACT_SYSGET:
  933.             case ACT_ENVGET:
  934.             case ACT_CONTROLGETPOS:
  935.             case ACT_PIXELGETCOLOR:
  936.             case ACT_PIXELSEARCH:
  937.             case ACT_IMAGESEARCH:
  938.             case ACT_INPUT:
  939.             case ACT_FORMATTIME:
  940.                 return ARG_TYPE_OUTPUT_VAR;
  941.  
  942.             case ACT_SORT:
  943.             case ACT_SPLITPATH:
  944.             case ACT_IFINSTRING:
  945.             case ACT_IFNOTINSTRING:
  946.             case ACT_IFEQUAL:
  947.             case ACT_IFNOTEQUAL:
  948.             case ACT_IFGREATER:
  949.             case ACT_IFGREATEROREQUAL:
  950.             case ACT_IFLESS:
  951.             case ACT_IFLESSOREQUAL:
  952.             case ACT_IFBETWEEN:
  953.             case ACT_IFNOTBETWEEN:
  954.             case ACT_IFIN:
  955.             case ACT_IFNOTIN:
  956.             case ACT_IFCONTAINS:
  957.             case ACT_IFNOTCONTAINS:
  958.             case ACT_IFIS:
  959.             case ACT_IFISNOT:
  960.                 return ARG_TYPE_INPUT_VAR;
  961.             }
  962.             break;
  963.  
  964.         case 1:  // Arg #2
  965.             switch(aActionType)
  966.             {
  967.             case ACT_STRINGLEFT:
  968.             case ACT_STRINGRIGHT:
  969.             case ACT_STRINGMID:
  970.             case ACT_STRINGTRIMLEFT:
  971.             case ACT_STRINGTRIMRIGHT:
  972.             case ACT_STRINGLOWER:
  973.             case ACT_STRINGUPPER:
  974.             case ACT_STRINGLEN:
  975.             case ACT_STRINGREPLACE:
  976.             case ACT_STRINGGETPOS:
  977.             case ACT_STRINGSPLIT:
  978.                 return ARG_TYPE_INPUT_VAR;
  979.  
  980.             case ACT_MOUSEGETPOS:
  981.             case ACT_WINGETPOS:
  982.             case ACT_CONTROLGETPOS:
  983.             case ACT_PIXELSEARCH:
  984.             case ACT_IMAGESEARCH:
  985.             case ACT_SPLITPATH:
  986.             case ACT_FILEGETSHORTCUT:
  987.                 return ARG_TYPE_OUTPUT_VAR;
  988.             }
  989.             break;
  990.  
  991.         case 2:  // Arg #3
  992.             switch(aActionType)
  993.             {
  994.             case ACT_WINGETPOS:
  995.             case ACT_CONTROLGETPOS:
  996.             case ACT_MOUSEGETPOS:
  997.             case ACT_SPLITPATH:
  998.             case ACT_FILEGETSHORTCUT:
  999.                 return ARG_TYPE_OUTPUT_VAR;
  1000.             }
  1001.             break;
  1002.  
  1003.         case 3:  // Arg #4
  1004.             switch(aActionType)
  1005.             {
  1006.             case ACT_WINGETPOS:
  1007.             case ACT_CONTROLGETPOS:
  1008.             case ACT_MOUSEGETPOS:
  1009.             case ACT_SPLITPATH:
  1010.             case ACT_FILEGETSHORTCUT:
  1011.             case ACT_RUN:
  1012.             case ACT_RUNWAIT:
  1013.                 return ARG_TYPE_OUTPUT_VAR;
  1014.             }
  1015.             break;
  1016.  
  1017.         case 4:  // Arg #5
  1018.         case 5:  // Arg #6
  1019.             if (aActionType == ACT_SPLITPATH || aActionType == ACT_FILEGETSHORTCUT)
  1020.                 return ARG_TYPE_OUTPUT_VAR;
  1021.             break;
  1022.  
  1023.         case 6:  // Arg #7
  1024.         case 7:  // Arg #8
  1025.             if (aActionType == ACT_FILEGETSHORTCUT)
  1026.                 return ARG_TYPE_OUTPUT_VAR;
  1027.         }
  1028.         // Otherwise:
  1029.         return ARG_TYPE_NORMAL;
  1030.     }
  1031.  
  1032.  
  1033.  
  1034.     ResultType ArgMustBeDereferenced(Var *aVar, int aArgIndex, Var *aArgVar[]);
  1035.  
  1036.     bool ArgHasDeref(int aArgNum)
  1037.     // This function should always be called in lieu of doing something like "strchr(arg.text, g_DerefChar)"
  1038.     // because that method is unreliable due to the possible presence of literal (escaped) g_DerefChars
  1039.     // in the text.
  1040.     // Caller must ensure that aArgNum should be 1 or greater.
  1041.     {
  1042. #ifdef _DEBUG
  1043.         if (aArgNum < 1)
  1044.         {
  1045.             LineError("DEBUG: BAD", WARN);
  1046.             aArgNum = 1;  // But let it continue.
  1047.         }
  1048. #endif
  1049.         if (aArgNum > mArgc) // Arg doesn't exist.
  1050.             return false;
  1051.         ArgStruct &arg = mArg[aArgNum - 1]; // For performance.
  1052.         // Return false if it's not of a type caller wants deemed to have derefs.
  1053.         if (arg.type == ARG_TYPE_NORMAL)
  1054.             return arg.deref && arg.deref[0].marker; // Relies on short-circuit boolean evaluation order to prevent NULL-deref.
  1055.         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.
  1056.             return (arg.type == ARG_TYPE_INPUT_VAR);
  1057.     }
  1058.  
  1059.     static HKEY RegConvertRootKey(char *aBuf, bool *aIsRemoteRegistry = NULL)
  1060.     {
  1061.         // Even if the computer name is a single letter, it seems like using a colon as delimiter is ok
  1062.         // (e.g. a:HKEY_LOCAL_MACHINE), since we wouldn't expect the root key to be used as a filename
  1063.         // in that exact way, i.e. a drive letter should be followed by a backslash 99% of the time in
  1064.         // this context.
  1065.         // Research indicates that colon is an illegal char in a computer name (at least for NT,
  1066.         // and by extension probably all other OSes).  So it should be safe to use it as a delimiter
  1067.         // for the remote registry feature.  But just in case, get the right-most one,
  1068.         // e.g. Computer:01:HKEY_LOCAL_MACHINE  ; the first colon is probably illegal on all OSes.
  1069.         // Additional notes from the Internet:
  1070.         // "A Windows NT computer name can be up to 15 alphanumeric characters with no blank spaces
  1071.         // and must be unique on the network. It can contain the following special characters:
  1072.         // ! @ # $ % ^ & ( ) -   ' { } .
  1073.         // It may not contain:
  1074.         // \ * + = | : ; " ? ,
  1075.         // The following is a list of illegal characters in a computer name:
  1076.         // regEx.Pattern = "`|~|!|@|#|\$|\^|\&|\*|\(|\)|\=|\+|{|}|\\|;|:|'|<|>|/|\?|\||%"
  1077.  
  1078.         char *colon_pos = strrchr(aBuf, ':');
  1079.         char *key_name = colon_pos ? omit_leading_whitespace(colon_pos + 1) : aBuf;
  1080.         if (aIsRemoteRegistry) // Caller wanted the below put into the output parameter.
  1081.             *aIsRemoteRegistry = (colon_pos != NULL);
  1082.         HKEY root_key = NULL; // Set default.
  1083.         if (!stricmp(key_name, "HKLM") || !stricmp(key_name, "HKEY_LOCAL_MACHINE"))       root_key = HKEY_LOCAL_MACHINE;
  1084.         else if (!stricmp(key_name, "HKCR") || !stricmp(key_name, "HKEY_CLASSES_ROOT"))   root_key = HKEY_CLASSES_ROOT;
  1085.         else if (!stricmp(key_name, "HKCC") || !stricmp(key_name, "HKEY_CURRENT_CONFIG")) root_key = HKEY_CURRENT_CONFIG;
  1086.         else if (!stricmp(key_name, "HKCU") || !stricmp(key_name, "HKEY_CURRENT_USER"))   root_key = HKEY_CURRENT_USER;
  1087.         else if (!stricmp(key_name, "HKU") || !stricmp(key_name, "HKEY_USERS"))           root_key = HKEY_USERS;
  1088.         if (!root_key)  // Invalid or unsupported root key name.
  1089.             return NULL;
  1090.         if (!aIsRemoteRegistry || !colon_pos) // Either caller didn't want it opened, or it doesn't need to be.
  1091.             return root_key; // If it's a remote key, this value should only be used by the caller as an indicator.
  1092.         // Otherwise, it's a remote computer whose registry the caller wants us to open:
  1093.         // It seems best to require the two leading backslashes in case the computer name contains
  1094.         // spaces (just in case spaces are allowed on some OSes or perhaps for Unix interoperability, etc.).
  1095.         // Therefore, make no attempt to trim leading and trailing spaces from the computer name:
  1096.         char computer_name[128];
  1097.         strlcpy(computer_name, aBuf, sizeof(computer_name));
  1098.         computer_name[colon_pos - aBuf] = '\0';
  1099.         HKEY remote_key;
  1100.         return (RegConnectRegistry(computer_name, root_key, &remote_key) == ERROR_SUCCESS) ? remote_key : NULL;
  1101.     }
  1102.  
  1103.     static char *RegConvertRootKey(char *aBuf, size_t aBufSize, HKEY aRootKey)
  1104.     {
  1105.         // switch() doesn't directly support expression of type HKEY:
  1106.         if (aRootKey == HKEY_LOCAL_MACHINE)       strlcpy(aBuf, "HKEY_LOCAL_MACHINE", aBufSize);
  1107.         else if (aRootKey == HKEY_CLASSES_ROOT)   strlcpy(aBuf, "HKEY_CLASSES_ROOT", aBufSize);
  1108.         else if (aRootKey == HKEY_CURRENT_CONFIG) strlcpy(aBuf, "HKEY_CURRENT_CONFIG", aBufSize);
  1109.         else if (aRootKey == HKEY_CURRENT_USER)   strlcpy(aBuf, "HKEY_CURRENT_USER", aBufSize);
  1110.         else if (aRootKey == HKEY_USERS)          strlcpy(aBuf, "HKEY_USERS", aBufSize);
  1111.         else if (aBufSize)                        *aBuf = '\0'; // Make it be the empty string for anything else.
  1112.         // These are either unused or so rarely used (DYN_DATA on Win9x) that they aren't supported:
  1113.         // HKEY_PERFORMANCE_DATA, HKEY_PERFORMANCE_TEXT, HKEY_PERFORMANCE_NLSTEXT, HKEY_DYN_DATA
  1114.         return aBuf;
  1115.     }
  1116.     static int RegConvertValueType(char *aValueType)
  1117.     {
  1118.         if (!stricmp(aValueType, "REG_SZ")) return REG_SZ;
  1119.         if (!stricmp(aValueType, "REG_EXPAND_SZ")) return REG_EXPAND_SZ;
  1120.         if (!stricmp(aValueType, "REG_MULTI_SZ")) return REG_MULTI_SZ;
  1121.         if (!stricmp(aValueType, "REG_DWORD")) return REG_DWORD;
  1122.         if (!stricmp(aValueType, "REG_BINARY")) return REG_BINARY;
  1123.         return REG_NONE; // Unknown or unsupported type.
  1124.     }
  1125.     static char *RegConvertValueType(char *aBuf, size_t aBufSize, DWORD aValueType)
  1126.     {
  1127.         switch(aValueType)
  1128.         {
  1129.         case REG_SZ: strlcpy(aBuf, "REG_SZ", aBufSize); return aBuf;
  1130.         case REG_EXPAND_SZ: strlcpy(aBuf, "REG_EXPAND_SZ", aBufSize); return aBuf;
  1131.         case REG_BINARY: strlcpy(aBuf, "REG_BINARY", aBufSize); return aBuf;
  1132.         case REG_DWORD: strlcpy(aBuf, "REG_DWORD", aBufSize); return aBuf;
  1133.         case REG_DWORD_BIG_ENDIAN: strlcpy(aBuf, "REG_DWORD_BIG_ENDIAN", aBufSize); return aBuf;
  1134.         case REG_LINK: strlcpy(aBuf, "REG_LINK", aBufSize); return aBuf;
  1135.         case REG_MULTI_SZ: strlcpy(aBuf, "REG_MULTI_SZ", aBufSize); return aBuf;
  1136.         case REG_RESOURCE_LIST: strlcpy(aBuf, "REG_RESOURCE_LIST", aBufSize); return aBuf;
  1137.         case REG_FULL_RESOURCE_DESCRIPTOR: strlcpy(aBuf, "REG_FULL_RESOURCE_DESCRIPTOR", aBufSize); return aBuf;
  1138.         case REG_RESOURCE_REQUIREMENTS_LIST: strlcpy(aBuf, "REG_RESOURCE_REQUIREMENTS_LIST", aBufSize); return aBuf;
  1139.         case REG_QWORD: strlcpy(aBuf, "REG_QWORD", aBufSize); return aBuf;
  1140.         case REG_SUBKEY: strlcpy(aBuf, "KEY", aBufSize); return aBuf;  // Custom (non-standard) type.
  1141.         default: if (aBufSize) *aBuf = '\0'; return aBuf;  // Make it be the empty string for REG_NONE and anything else.
  1142.         }
  1143.     }
  1144.  
  1145.     static DWORD SoundConvertComponentType(char *aBuf, int *aInstanceNumber = NULL)
  1146.     {
  1147.         char *colon_pos = strchr(aBuf, ':');
  1148.         UINT length_to_check = (UINT)(colon_pos ? colon_pos - aBuf : strlen(aBuf));
  1149.         if (aInstanceNumber) // Caller wanted the below put into the output parameter.
  1150.         {
  1151.             if (colon_pos)
  1152.             {
  1153.                 *aInstanceNumber = ATOI(colon_pos + 1);
  1154.                 if (*aInstanceNumber < 1)
  1155.                     *aInstanceNumber = 1;
  1156.             }
  1157.             else
  1158.                 *aInstanceNumber = 1;
  1159.         }
  1160.         if (!strlicmp(aBuf, "Master", length_to_check)
  1161.             || !strlicmp(aBuf, "Speakers", length_to_check))   return MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  1162.         if (!strlicmp(aBuf, "Headphones", length_to_check))    return MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
  1163.         if (!strlicmp(aBuf, "Digital", length_to_check))       return MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
  1164.         if (!strlicmp(aBuf, "Line", length_to_check))          return MIXERLINE_COMPONENTTYPE_SRC_LINE;
  1165.         if (!strlicmp(aBuf, "Microphone", length_to_check))    return MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
  1166.         if (!strlicmp(aBuf, "Synth", length_to_check))         return MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
  1167.         if (!strlicmp(aBuf, "CD", length_to_check))            return MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
  1168.         if (!strlicmp(aBuf, "Telephone", length_to_check))     return MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
  1169.         if (!strlicmp(aBuf, "PCSpeaker", length_to_check))     return MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER;
  1170.         if (!strlicmp(aBuf, "Wave", length_to_check))          return MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
  1171.         if (!strlicmp(aBuf, "Aux", length_to_check))           return MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
  1172.         if (!strlicmp(aBuf, "Analog", length_to_check))        return MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
  1173.         // v1.0.37.06: The following was added because it's legitimate on some sound cards such as
  1174.         // SB Audigy's recording (dest #2) Wave/Mp3 volume:
  1175.         if (!strlicmp(aBuf, "N/A", length_to_check))           return MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED; // 0x1000
  1176.         return MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; // Zero.
  1177.     }
  1178.     static DWORD SoundConvertControlType(char *aBuf)
  1179.     {
  1180.         // v1.0.37.06: The following was added to allow unnamed control types (if any) to be accessed via number:
  1181.         if (IsPureNumeric(aBuf, false, false, true)) // Seems best to allowing floating point here, since .000 on the end might happen sometimes.
  1182.             return ATOU(aBuf);
  1183.         // The following are the types that seem to correspond to actual sound attributes.  Some of the
  1184.         // values are not included here, such as MIXERCONTROL_CONTROLTYPE_FADER, which seems to be a type
  1185.         // of sound control rather than a quality of the sound itself.  For performance, put the most
  1186.         // often used ones up top.
  1187.         if (!stricmp(aBuf, "Vol")
  1188.             || !stricmp(aBuf, "Volume")) return MIXERCONTROL_CONTROLTYPE_VOLUME;
  1189.         if (!stricmp(aBuf, "OnOff"))     return MIXERCONTROL_CONTROLTYPE_ONOFF;
  1190.         if (!stricmp(aBuf, "Mute"))      return MIXERCONTROL_CONTROLTYPE_MUTE;
  1191.         if (!stricmp(aBuf, "Mono"))      return MIXERCONTROL_CONTROLTYPE_MONO;
  1192.         if (!stricmp(aBuf, "Loudness"))  return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
  1193.         if (!stricmp(aBuf, "StereoEnh")) return MIXERCONTROL_CONTROLTYPE_STEREOENH;
  1194.         if (!stricmp(aBuf, "BassBoost")) return MIXERCONTROL_CONTROLTYPE_BASS_BOOST;
  1195.         if (!stricmp(aBuf, "Pan"))       return MIXERCONTROL_CONTROLTYPE_PAN;
  1196.         if (!stricmp(aBuf, "QSoundPan")) return MIXERCONTROL_CONTROLTYPE_QSOUNDPAN;
  1197.         if (!stricmp(aBuf, "Bass"))      return MIXERCONTROL_CONTROLTYPE_BASS;
  1198.         if (!stricmp(aBuf, "Treble"))    return MIXERCONTROL_CONTROLTYPE_TREBLE;
  1199.         if (!stricmp(aBuf, "Equalizer")) return MIXERCONTROL_CONTROLTYPE_EQUALIZER;
  1200.         #define MIXERCONTROL_CONTROLTYPE_INVALID 0xFFFFFFFF // 0 might be a valid type, so use something definitely undefined.
  1201.         return MIXERCONTROL_CONTROLTYPE_INVALID;
  1202.     }
  1203.  
  1204.     static TitleMatchModes ConvertTitleMatchMode(char *aBuf)
  1205.     {
  1206.         if (!aBuf || !*aBuf) return MATCHMODE_INVALID;
  1207.         if (*aBuf == '1' && !*(aBuf + 1)) return FIND_IN_LEADING_PART;
  1208.         if (*aBuf == '2' && !*(aBuf + 1)) return FIND_ANYWHERE;
  1209.         if (*aBuf == '3' && !*(aBuf + 1)) return FIND_EXACT;
  1210.         if (!stricmp(aBuf, "RegEx")) return FIND_REGEX; // Goes with the above, not fast/slow below.
  1211.  
  1212.         if (!stricmp(aBuf, "FAST")) return FIND_FAST;
  1213.         if (!stricmp(aBuf, "SLOW")) return FIND_SLOW;
  1214.         return MATCHMODE_INVALID;
  1215.     }
  1216.  
  1217.     static SysGetCmds ConvertSysGetCmd(char *aBuf)
  1218.     {
  1219.         if (!aBuf || !*aBuf) return SYSGET_CMD_INVALID;
  1220.         if (IsPureNumeric(aBuf)) return SYSGET_CMD_METRICS;
  1221.         if (!stricmp(aBuf, "MonitorCount")) return SYSGET_CMD_MONITORCOUNT;
  1222.         if (!stricmp(aBuf, "MonitorPrimary")) return SYSGET_CMD_MONITORPRIMARY;
  1223.         if (!stricmp(aBuf, "Monitor")) return SYSGET_CMD_MONITORAREA; // Called "Monitor" vs. "MonitorArea" to make it easier to remember.
  1224.         if (!stricmp(aBuf, "MonitorWorkArea")) return SYSGET_CMD_MONITORWORKAREA;
  1225.         if (!stricmp(aBuf, "MonitorName")) return SYSGET_CMD_MONITORNAME;
  1226.         return SYSGET_CMD_INVALID;
  1227.     }
  1228.  
  1229.     static TransformCmds ConvertTransformCmd(char *aBuf)
  1230.     {
  1231.         if (!aBuf || !*aBuf) return TRANS_CMD_INVALID;
  1232.         if (!stricmp(aBuf, "Asc")) return TRANS_CMD_ASC;
  1233.         if (!stricmp(aBuf, "Chr")) return TRANS_CMD_CHR;
  1234.         if (!stricmp(aBuf, "Deref")) return TRANS_CMD_DEREF;
  1235.         if (!stricmp(aBuf, "Unicode")) return TRANS_CMD_UNICODE;
  1236.         if (!stricmp(aBuf, "HTML")) return TRANS_CMD_HTML;
  1237.         if (!stricmp(aBuf, "Mod")) return TRANS_CMD_MOD;
  1238.         if (!stricmp(aBuf, "Pow")) return TRANS_CMD_POW;
  1239.         if (!stricmp(aBuf, "Exp")) return TRANS_CMD_EXP;
  1240.         if (!stricmp(aBuf, "Sqrt")) return TRANS_CMD_SQRT;
  1241.         if (!stricmp(aBuf, "Log")) return TRANS_CMD_LOG;
  1242.         if (!stricmp(aBuf, "Ln")) return TRANS_CMD_LN;  // Natural log.
  1243.         if (!stricmp(aBuf, "Round")) return TRANS_CMD_ROUND;
  1244.         if (!stricmp(aBuf, "Ceil")) return TRANS_CMD_CEIL;
  1245.         if (!stricmp(aBuf, "Floor")) return TRANS_CMD_FLOOR;
  1246.         if (!stricmp(aBuf, "Abs")) return TRANS_CMD_ABS;
  1247.         if (!stricmp(aBuf, "Sin")) return TRANS_CMD_SIN;
  1248.         if (!stricmp(aBuf, "Cos")) return TRANS_CMD_COS;
  1249.         if (!stricmp(aBuf, "Tan")) return TRANS_CMD_TAN;
  1250.         if (!stricmp(aBuf, "ASin")) return TRANS_CMD_ASIN;
  1251.         if (!stricmp(aBuf, "ACos")) return TRANS_CMD_ACOS;
  1252.         if (!stricmp(aBuf, "ATan")) return TRANS_CMD_ATAN;
  1253.         if (!stricmp(aBuf, "BitAnd")) return TRANS_CMD_BITAND;
  1254.         if (!stricmp(aBuf, "BitOr")) return TRANS_CMD_BITOR;
  1255.         if (!stricmp(aBuf, "BitXOr")) return TRANS_CMD_BITXOR;
  1256.         if (!stricmp(aBuf, "BitNot")) return TRANS_CMD_BITNOT;
  1257.         if (!stricmp(aBuf, "BitShiftLeft")) return TRANS_CMD_BITSHIFTLEFT;
  1258.         if (!stricmp(aBuf, "BitShiftRight")) return TRANS_CMD_BITSHIFTRIGHT;
  1259.         return TRANS_CMD_INVALID;
  1260.     }
  1261.  
  1262.     static MenuCommands ConvertMenuCommand(char *aBuf)
  1263.     {
  1264.         if (!aBuf || !*aBuf) return MENU_CMD_INVALID;
  1265.         if (!stricmp(aBuf, "Show")) return MENU_CMD_SHOW;
  1266.         if (!stricmp(aBuf, "UseErrorLevel")) return MENU_CMD_USEERRORLEVEL;
  1267.         if (!stricmp(aBuf, "Add")) return MENU_CMD_ADD;
  1268.         if (!stricmp(aBuf, "Rename")) return MENU_CMD_RENAME;
  1269.         if (!stricmp(aBuf, "Check")) return MENU_CMD_CHECK;
  1270.         if (!stricmp(aBuf, "Uncheck")) return MENU_CMD_UNCHECK;
  1271.         if (!stricmp(aBuf, "ToggleCheck")) return MENU_CMD_TOGGLECHECK;
  1272.         if (!stricmp(aBuf, "Enable")) return MENU_CMD_ENABLE;
  1273.         if (!stricmp(aBuf, "Disable")) return MENU_CMD_DISABLE;
  1274.         if (!stricmp(aBuf, "ToggleEnable")) return MENU_CMD_TOGGLEENABLE;
  1275.         if (!stricmp(aBuf, "Standard")) return MENU_CMD_STANDARD;
  1276.         if (!stricmp(aBuf, "NoStandard")) return MENU_CMD_NOSTANDARD;
  1277.         if (!stricmp(aBuf, "Color")) return MENU_CMD_COLOR;
  1278.         if (!stricmp(aBuf, "Default")) return MENU_CMD_DEFAULT;
  1279.         if (!stricmp(aBuf, "NoDefault")) return MENU_CMD_NODEFAULT;
  1280.         if (!stricmp(aBuf, "Delete")) return MENU_CMD_DELETE;
  1281.         if (!stricmp(aBuf, "DeleteAll")) return MENU_CMD_DELETEALL;
  1282.         if (!stricmp(aBuf, "Tip")) return MENU_CMD_TIP;
  1283.         if (!stricmp(aBuf, "Icon")) return MENU_CMD_ICON;
  1284.         if (!stricmp(aBuf, "NoIcon")) return MENU_CMD_NOICON;
  1285.         if (!stricmp(aBuf, "Click")) return MENU_CMD_CLICK;
  1286.         if (!stricmp(aBuf, "MainWindow")) return MENU_CMD_MAINWINDOW;
  1287.         if (!stricmp(aBuf, "NoMainWindow")) return MENU_CMD_NOMAINWINDOW;
  1288.         return MENU_CMD_INVALID;
  1289.     }
  1290.  
  1291.     static GuiCommands ConvertGuiCommand(char *aBuf, int *aWindowIndex = NULL, char **aOptions = NULL)
  1292.     {
  1293.         // Notes about the below macro:
  1294.         // "< 3" avoids ambiguity with a future use such as "gui +cmd:whatever" while still allowing
  1295.         // up to 99 windows, e.g. "gui 99:add"
  1296.         // omit_leading_whitespace(): Move the buf pointer to the location of the sub-command.
  1297.         #define DETERMINE_WINDOW_INDEX \
  1298.             char *colon_pos = strchr(aBuf, ':');\
  1299.             if (colon_pos && colon_pos - aBuf < 3)\
  1300.             {\
  1301.                 if (aWindowIndex)\
  1302.                     *aWindowIndex = ATOI(aBuf) - 1;\
  1303.                 aBuf = omit_leading_whitespace(colon_pos + 1);\
  1304.             }
  1305.             //else leave it set to the default already put in it by the caller.
  1306.         DETERMINE_WINDOW_INDEX
  1307.         if (aOptions)
  1308.             *aOptions = aBuf; // Return position where options start to the caller.
  1309.         if (!*aBuf || *aBuf == '+' || *aBuf == '-') // Assume a var ref that resolves to blank is "options" (for runtime flexibility).
  1310.             return GUI_CMD_OPTIONS;
  1311.         if (!stricmp(aBuf, "Add")) return GUI_CMD_ADD;
  1312.         if (!stricmp(aBuf, "Show")) return GUI_CMD_SHOW;
  1313.         if (!stricmp(aBuf, "Submit")) return GUI_CMD_SUBMIT;
  1314.         if (!stricmp(aBuf, "Cancel") || !stricmp(aBuf, "Hide")) return GUI_CMD_CANCEL;
  1315.         if (!stricmp(aBuf, "Minimize")) return GUI_CMD_MINIMIZE;
  1316.         if (!stricmp(aBuf, "Maximize")) return GUI_CMD_MAXIMIZE;
  1317.         if (!stricmp(aBuf, "Restore")) return GUI_CMD_RESTORE;
  1318.         if (!stricmp(aBuf, "Destroy")) return GUI_CMD_DESTROY;
  1319.         if (!stricmp(aBuf, "Margin")) return GUI_CMD_MARGIN;
  1320.         if (!stricmp(aBuf, "Menu")) return GUI_CMD_MENU;
  1321.         if (!stricmp(aBuf, "Font")) return GUI_CMD_FONT;
  1322.         if (!stricmp(aBuf, "Tab")) return GUI_CMD_TAB;
  1323.         if (!stricmp(aBuf, "ListView")) return GUI_CMD_LISTVIEW;
  1324.         if (!stricmp(aBuf, "TreeView")) return GUI_CMD_TREEVIEW;
  1325.         if (!stricmp(aBuf, "Default")) return GUI_CMD_DEFAULT;
  1326.         if (!stricmp(aBuf, "Color")) return GUI_CMD_COLOR;
  1327.         if (!stricmp(aBuf, "Flash")) return GUI_CMD_FLASH;
  1328.         return GUI_CMD_INVALID;
  1329.     }
  1330.  
  1331.     GuiControlCmds ConvertGuiControlCmd(char *aBuf, int *aWindowIndex = NULL, char **aOptions = NULL)
  1332.     {
  1333.         DETERMINE_WINDOW_INDEX
  1334.         if (aOptions)
  1335.             *aOptions = aBuf; // Return position where options start to the caller.
  1336.         // If it's blank without a deref, that's CONTENTS.  Otherwise, assume it's OPTIONS for better
  1337.         // runtime flexibility (i.e. user can leave the variable blank to make the command do nothing).
  1338.         // Fix for v1.0.40.11: Since the above is counterintuitive and undocumented, it has been fixed
  1339.         // to behave the way most users would expect; that is, the contents of any deref in parameter 1
  1340.         // will behave the same as when such contents is present literally as parametter 1.  Another
  1341.         // reason for doing this is that otherwise, there is no way to specify the CONTENTS sub-command
  1342.         // in a variable.  For example, the following wouldn't work:
  1343.         // GuiControl, %WindowNumber%:, ...
  1344.         // GuiControl, %WindowNumberWithColon%, ...
  1345.         if (!*aBuf)
  1346.             return GUICONTROL_CMD_CONTENTS;
  1347.         if (*aBuf == '+' || *aBuf == '-') // Assume a var ref that resolves to blank is "options" (for runtime flexibility).
  1348.             return GUICONTROL_CMD_OPTIONS;
  1349.         if (!stricmp(aBuf, "Text")) return GUICONTROL_CMD_TEXT;
  1350.         if (!stricmp(aBuf, "Move")) return GUICONTROL_CMD_MOVE;
  1351.         if (!stricmp(aBuf, "MoveDraw")) return GUICONTROL_CMD_MOVEDRAW;
  1352.         if (!stricmp(aBuf, "Focus")) return GUICONTROL_CMD_FOCUS;
  1353.         if (!stricmp(aBuf, "Choose")) return GUICONTROL_CMD_CHOOSE;
  1354.         if (!stricmp(aBuf, "ChooseString")) return GUICONTROL_CMD_CHOOSESTRING;
  1355.         if (!stricmp(aBuf, "Font")) return GUICONTROL_CMD_FONT;
  1356.  
  1357.         // v1.0.38.02: Anything not already returned from above supports an optional boolean suffix.
  1358.         // The following example would hide the control: GuiControl, Show%VarContainingFalse%, MyControl
  1359.         // To support hex (due to the 'x' in it), search from the left rather than the right for the
  1360.         // first digit:
  1361.         char *suffix;
  1362.         for (suffix = aBuf; *suffix && !isdigit(*suffix); ++suffix);
  1363.         bool invert = (*suffix ? !ATOI(suffix) : false);
  1364.         if (!strnicmp(aBuf, "Enable", 6)) return invert ? GUICONTROL_CMD_DISABLE : GUICONTROL_CMD_ENABLE;
  1365.         if (!strnicmp(aBuf, "Disable", 7)) return invert ? GUICONTROL_CMD_ENABLE : GUICONTROL_CMD_DISABLE;
  1366.         if (!strnicmp(aBuf, "Show", 4)) return invert ? GUICONTROL_CMD_HIDE : GUICONTROL_CMD_SHOW;
  1367.         if (!strnicmp(aBuf, "Hide", 4)) return invert ? GUICONTROL_CMD_SHOW : GUICONTROL_CMD_HIDE;
  1368.  
  1369.         return GUICONTROL_CMD_INVALID;
  1370.     }
  1371.  
  1372.     static GuiControlGetCmds ConvertGuiControlGetCmd(char *aBuf, int *aWindowIndex = NULL)
  1373.     {
  1374.         DETERMINE_WINDOW_INDEX
  1375.         if (!*aBuf) return GUICONTROLGET_CMD_CONTENTS; // The implicit command when nothing was specified.
  1376.         if (!stricmp(aBuf, "Pos")) return GUICONTROLGET_CMD_POS;
  1377.         if (!stricmp(aBuf, "Focus")) return GUICONTROLGET_CMD_FOCUS;
  1378.         if (!stricmp(aBuf, "FocusV")) return GUICONTROLGET_CMD_FOCUSV; // Returns variable vs. ClassNN.
  1379.         if (!stricmp(aBuf, "Enabled")) return GUICONTROLGET_CMD_ENABLED;
  1380.         if (!stricmp(aBuf, "Visible")) return GUICONTROLGET_CMD_VISIBLE;
  1381.         if (!stricmp(aBuf, "Hwnd")) return GUICONTROLGET_CMD_HWND;
  1382.         return GUICONTROLGET_CMD_INVALID;
  1383.     }
  1384.  
  1385.     static GuiControls ConvertGuiControl(char *aBuf)
  1386.     {
  1387.         if (!aBuf || !*aBuf) return GUI_CONTROL_INVALID;
  1388.         if (!stricmp(aBuf, "Text")) return GUI_CONTROL_TEXT;
  1389.         if (!stricmp(aBuf, "Edit")) return GUI_CONTROL_EDIT;
  1390.         if (!stricmp(aBuf, "Button")) return GUI_CONTROL_BUTTON;
  1391.         if (!stricmp(aBuf, "Checkbox")) return GUI_CONTROL_CHECKBOX;
  1392.         if (!stricmp(aBuf, "Radio")) return GUI_CONTROL_RADIO;
  1393.         if (!stricmp(aBuf, "DDL") || !stricmp(aBuf, "DropDownList")) return GUI_CONTROL_DROPDOWNLIST;
  1394.         if (!stricmp(aBuf, "ComboBox")) return GUI_CONTROL_COMBOBOX;
  1395.         if (!stricmp(aBuf, "ListBox")) return GUI_CONTROL_LISTBOX;
  1396.         if (!stricmp(aBuf, "ListView")) return GUI_CONTROL_LISTVIEW;
  1397.         if (!stricmp(aBuf, "TreeView")) return GUI_CONTROL_TREEVIEW;
  1398.         // Keep those seldom used at the bottom for performance:
  1399.         if (!stricmp(aBuf, "UpDown")) return GUI_CONTROL_UPDOWN;
  1400.         if (!stricmp(aBuf, "Slider")) return GUI_CONTROL_SLIDER;
  1401.         if (!stricmp(aBuf, "Progress")) return GUI_CONTROL_PROGRESS;
  1402.         if (!stricmp(aBuf, "Tab")) return GUI_CONTROL_TAB;
  1403.         if (!stricmp(aBuf, "Tab2")) return GUI_CONTROL_TAB2; // v1.0.47.05: Used only temporarily: becomes TAB vs. TAB2 upon creation.
  1404.         if (!stricmp(aBuf, "GroupBox")) return GUI_CONTROL_GROUPBOX;
  1405.         if (!stricmp(aBuf, "Pic") || !stricmp(aBuf, "Picture")) return GUI_CONTROL_PIC;
  1406.         if (!stricmp(aBuf, "DateTime")) return GUI_CONTROL_DATETIME;
  1407.         if (!stricmp(aBuf, "MonthCal")) return GUI_CONTROL_MONTHCAL;
  1408.         if (!stricmp(aBuf, "Hotkey")) return GUI_CONTROL_HOTKEY;
  1409.         if (!stricmp(aBuf, "StatusBar")) return GUI_CONTROL_STATUSBAR;
  1410.         return GUI_CONTROL_INVALID;
  1411.     }
  1412.  
  1413.     static ThreadCommands ConvertThreadCommand(char *aBuf)
  1414.     {
  1415.         if (!aBuf || !*aBuf) return THREAD_CMD_INVALID;
  1416.         if (!stricmp(aBuf, "Priority")) return THREAD_CMD_PRIORITY;
  1417.         if (!stricmp(aBuf, "Interrupt")) return THREAD_CMD_INTERRUPT;
  1418.         if (!stricmp(aBuf, "NoTimers")) return THREAD_CMD_NOTIMERS;
  1419.         return THREAD_CMD_INVALID;
  1420.     }
  1421.     
  1422.     static ProcessCmds ConvertProcessCmd(char *aBuf)
  1423.     {
  1424.         if (!aBuf || !*aBuf) return PROCESS_CMD_INVALID;
  1425.         if (!stricmp(aBuf, "Exist")) return PROCESS_CMD_EXIST;
  1426.         if (!stricmp(aBuf, "Close")) return PROCESS_CMD_CLOSE;
  1427.         if (!stricmp(aBuf, "Priority")) return PROCESS_CMD_PRIORITY;
  1428.         if (!stricmp(aBuf, "Wait")) return PROCESS_CMD_WAIT;
  1429.         if (!stricmp(aBuf, "WaitClose")) return PROCESS_CMD_WAITCLOSE;
  1430.         return PROCESS_CMD_INVALID;
  1431.     }
  1432.  
  1433.     static ControlCmds ConvertControlCmd(char *aBuf)
  1434.     {
  1435.         if (!aBuf || !*aBuf) return CONTROL_CMD_INVALID;
  1436.         if (!stricmp(aBuf, "Check")) return CONTROL_CMD_CHECK;
  1437.         if (!stricmp(aBuf, "Uncheck")) return CONTROL_CMD_UNCHECK;
  1438.         if (!stricmp(aBuf, "Enable")) return CONTROL_CMD_ENABLE;
  1439.         if (!stricmp(aBuf, "Disable")) return CONTROL_CMD_DISABLE;
  1440.         if (!stricmp(aBuf, "Show")) return CONTROL_CMD_SHOW;
  1441.         if (!stricmp(aBuf, "Hide")) return CONTROL_CMD_HIDE;
  1442.         if (!stricmp(aBuf, "Style")) return CONTROL_CMD_STYLE;
  1443.         if (!stricmp(aBuf, "ExStyle")) return CONTROL_CMD_EXSTYLE;
  1444.         if (!stricmp(aBuf, "ShowDropDown")) return CONTROL_CMD_SHOWDROPDOWN;
  1445.         if (!stricmp(aBuf, "HideDropDown")) return CONTROL_CMD_HIDEDROPDOWN;
  1446.         if (!stricmp(aBuf, "TabLeft")) return CONTROL_CMD_TABLEFT;
  1447.         if (!stricmp(aBuf, "TabRight")) return CONTROL_CMD_TABRIGHT;
  1448.         if (!stricmp(aBuf, "Add")) return CONTROL_CMD_ADD;
  1449.         if (!stricmp(aBuf, "Delete")) return CONTROL_CMD_DELETE;
  1450.         if (!stricmp(aBuf, "Choose")) return CONTROL_CMD_CHOOSE;
  1451.         if (!stricmp(aBuf, "ChooseString")) return CONTROL_CMD_CHOOSESTRING;
  1452.         if (!stricmp(aBuf, "EditPaste")) return CONTROL_CMD_EDITPASTE;
  1453.         return CONTROL_CMD_INVALID;
  1454.     }
  1455.  
  1456.     static ControlGetCmds ConvertControlGetCmd(char *aBuf)
  1457.     {
  1458.         if (!aBuf || !*aBuf) return CONTROLGET_CMD_INVALID;
  1459.         if (!stricmp(aBuf, "Checked")) return CONTROLGET_CMD_CHECKED;
  1460.         if (!stricmp(aBuf, "Enabled")) return CONTROLGET_CMD_ENABLED;
  1461.         if (!stricmp(aBuf, "Visible")) return CONTROLGET_CMD_VISIBLE;
  1462.         if (!stricmp(aBuf, "Tab")) return CONTROLGET_CMD_TAB;
  1463.         if (!stricmp(aBuf, "FindString")) return CONTROLGET_CMD_FINDSTRING;
  1464.         if (!stricmp(aBuf, "Choice")) return CONTROLGET_CMD_CHOICE;
  1465.         if (!stricmp(aBuf, "List")) return CONTROLGET_CMD_LIST;
  1466.         if (!stricmp(aBuf, "LineCount")) return CONTROLGET_CMD_LINECOUNT;
  1467.         if (!stricmp(aBuf, "CurrentLine")) return CONTROLGET_CMD_CURRENTLINE;
  1468.         if (!stricmp(aBuf, "CurrentCol")) return CONTROLGET_CMD_CURRENTCOL;
  1469.         if (!stricmp(aBuf, "Line")) return CONTROLGET_CMD_LINE;
  1470.         if (!stricmp(aBuf, "Selected")) return CONTROLGET_CMD_SELECTED;
  1471.         if (!stricmp(aBuf, "Style")) return CONTROLGET_CMD_STYLE;
  1472.         if (!stricmp(aBuf, "ExStyle")) return CONTROLGET_CMD_EXSTYLE;
  1473.         if (!stricmp(aBuf, "Hwnd")) return CONTROLGET_CMD_HWND;
  1474.         return CONTROLGET_CMD_INVALID;
  1475.     }
  1476.  
  1477.     static DriveCmds ConvertDriveCmd(char *aBuf)
  1478.     {
  1479.         if (!aBuf || !*aBuf) return DRIVE_CMD_INVALID;
  1480.         if (!stricmp(aBuf, "Eject")) return DRIVE_CMD_EJECT;
  1481.         if (!stricmp(aBuf, "Lock")) return DRIVE_CMD_LOCK;
  1482.         if (!stricmp(aBuf, "Unlock")) return DRIVE_CMD_UNLOCK;
  1483.         if (!stricmp(aBuf, "Label")) return DRIVE_CMD_LABEL;
  1484.         return DRIVE_CMD_INVALID;
  1485.     }
  1486.  
  1487.     static DriveGetCmds ConvertDriveGetCmd(char *aBuf)
  1488.     {
  1489.         if (!aBuf || !*aBuf) return DRIVEGET_CMD_INVALID;
  1490.         if (!stricmp(aBuf, "List")) return DRIVEGET_CMD_LIST;
  1491.         if (!stricmp(aBuf, "FileSystem") || !stricmp(aBuf, "FS")) return DRIVEGET_CMD_FILESYSTEM;
  1492.         if (!stricmp(aBuf, "Label")) return DRIVEGET_CMD_LABEL;
  1493.         if (!strnicmp(aBuf, "SetLabel:", 9)) return DRIVEGET_CMD_SETLABEL;  // Uses strnicmp() vs. stricmp().
  1494.         if (!stricmp(aBuf, "Serial")) return DRIVEGET_CMD_SERIAL;
  1495.         if (!stricmp(aBuf, "Type")) return DRIVEGET_CMD_TYPE;
  1496.         if (!stricmp(aBuf, "Status")) return DRIVEGET_CMD_STATUS;
  1497.         if (!stricmp(aBuf, "StatusCD")) return DRIVEGET_CMD_STATUSCD;
  1498.         if (!stricmp(aBuf, "Capacity") || !stricmp(aBuf, "Cap")) return DRIVEGET_CMD_CAPACITY;
  1499.         return DRIVEGET_CMD_INVALID;
  1500.     }
  1501.  
  1502.     static WinSetAttributes ConvertWinSetAttribute(char *aBuf)
  1503.     {
  1504.         if (!aBuf || !*aBuf) return WINSET_INVALID;
  1505.         if (!stricmp(aBuf, "Trans") || !stricmp(aBuf, "Transparent")) return WINSET_TRANSPARENT;
  1506.         if (!stricmp(aBuf, "TransColor")) return WINSET_TRANSCOLOR;
  1507.         if (!stricmp(aBuf, "AlwaysOnTop") || !stricmp(aBuf, "Topmost")) return WINSET_ALWAYSONTOP;
  1508.         if (!stricmp(aBuf, "Bottom")) return WINSET_BOTTOM;
  1509.         if (!stricmp(aBuf, "Top")) return WINSET_TOP;
  1510.         if (!stricmp(aBuf, "Style")) return WINSET_STYLE;
  1511.         if (!stricmp(aBuf, "ExStyle")) return WINSET_EXSTYLE;
  1512.         if (!stricmp(aBuf, "Redraw")) return WINSET_REDRAW;
  1513.         if (!stricmp(aBuf, "Enable")) return WINSET_ENABLE;
  1514.         if (!stricmp(aBuf, "Disable")) return WINSET_DISABLE;
  1515.         if (!stricmp(aBuf, "Region")) return WINSET_REGION;
  1516.         return WINSET_INVALID;
  1517.     }
  1518.  
  1519.  
  1520.     static WinGetCmds ConvertWinGetCmd(char *aBuf)
  1521.     {
  1522.         if (!aBuf || !*aBuf) return WINGET_CMD_ID;  // If blank, return the default command.
  1523.         if (!stricmp(aBuf, "ID")) return WINGET_CMD_ID;
  1524.         if (!stricmp(aBuf, "IDLast")) return WINGET_CMD_IDLAST;
  1525.         if (!stricmp(aBuf, "PID")) return WINGET_CMD_PID;
  1526.         if (!stricmp(aBuf, "ProcessName")) return WINGET_CMD_PROCESSNAME;
  1527.         if (!stricmp(aBuf, "Count")) return WINGET_CMD_COUNT;
  1528.         if (!stricmp(aBuf, "List")) return WINGET_CMD_LIST;
  1529.         if (!stricmp(aBuf, "MinMax")) return WINGET_CMD_MINMAX;
  1530.         if (!stricmp(aBuf, "Style")) return WINGET_CMD_STYLE;
  1531.         if (!stricmp(aBuf, "ExStyle")) return WINGET_CMD_EXSTYLE;
  1532.         if (!stricmp(aBuf, "Transparent")) return WINGET_CMD_TRANSPARENT;
  1533.         if (!stricmp(aBuf, "TransColor")) return WINGET_CMD_TRANSCOLOR;
  1534.         if (!strnicmp(aBuf, "ControlList", 11))
  1535.         {
  1536.             aBuf += 11;
  1537.             if (!*aBuf)
  1538.                 return WINGET_CMD_CONTROLLIST;
  1539.             if (!stricmp(aBuf, "Hwnd"))
  1540.                 return WINGET_CMD_CONTROLLISTHWND;
  1541.             // Otherwise fall through to the below.
  1542.         }
  1543.         // Otherwise:
  1544.         return WINGET_CMD_INVALID;
  1545.     }
  1546.  
  1547.     static ToggleValueType ConvertOnOff(char *aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
  1548.     // Returns aDefault if aBuf isn't either ON, OFF, or blank.
  1549.     {
  1550.         if (!aBuf || !*aBuf) return NEUTRAL;
  1551.         if (!stricmp(aBuf, "ON")) return TOGGLED_ON;
  1552.         if (!stricmp(aBuf, "OFF")) return TOGGLED_OFF;
  1553.         return aDefault;
  1554.     }
  1555.  
  1556.     static ToggleValueType ConvertOnOffAlways(char *aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
  1557.     // Returns aDefault if aBuf isn't either ON, OFF, ALWAYSON, ALWAYSOFF, or blank.
  1558.     {
  1559.         if (!aBuf || !*aBuf) return NEUTRAL;
  1560.         if (!stricmp(aBuf, "On")) return TOGGLED_ON;
  1561.         if (!stricmp(aBuf, "Off")) return TOGGLED_OFF;
  1562.         if (!stricmp(aBuf, "AlwaysOn")) return ALWAYS_ON;
  1563.         if (!stricmp(aBuf, "AlwaysOff")) return ALWAYS_OFF;
  1564.         return aDefault;
  1565.     }
  1566.  
  1567.     static ToggleValueType ConvertOnOffToggle(char *aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
  1568.     // Returns aDefault if aBuf isn't either ON, OFF, TOGGLE, or blank.
  1569.     {
  1570.         if (!aBuf || !*aBuf) return NEUTRAL;
  1571.         if (!stricmp(aBuf, "On")) return TOGGLED_ON;
  1572.         if (!stricmp(aBuf, "Off")) return TOGGLED_OFF;
  1573.         if (!stricmp(aBuf, "Toggle")) return TOGGLE;
  1574.         return aDefault;
  1575.     }
  1576.  
  1577.     static StringCaseSenseType ConvertStringCaseSense(char *aBuf)
  1578.     {
  1579.         if (!stricmp(aBuf, "On")) return SCS_SENSITIVE;
  1580.         if (!stricmp(aBuf, "Off")) return SCS_INSENSITIVE;
  1581.         if (!stricmp(aBuf, "Locale")) return SCS_INSENSITIVE_LOCALE;
  1582.         return SCS_INVALID;
  1583.     }
  1584.  
  1585.     static ToggleValueType ConvertOnOffTogglePermit(char *aBuf, ToggleValueType aDefault = TOGGLE_INVALID)
  1586.     // Returns aDefault if aBuf isn't either ON, OFF, TOGGLE, PERMIT, or blank.
  1587.     {
  1588.         if (!aBuf || !*aBuf) return NEUTRAL;
  1589.         if (!stricmp(aBuf, "On")) return TOGGLED_ON;
  1590.         if (!stricmp(aBuf, "Off")) return TOGGLED_OFF;
  1591.         if (!stricmp(aBuf, "Toggle")) return TOGGLE;
  1592.         if (!stricmp(aBuf, "Permit")) return TOGGLE_PERMIT;
  1593.         return aDefault;
  1594.     }
  1595.  
  1596.     static ToggleValueType ConvertBlockInput(char *aBuf)
  1597.     {
  1598.         if (!aBuf || !*aBuf) return NEUTRAL;  // For backward compatibility, blank is not considered INVALID.
  1599.         if (!stricmp(aBuf, "On")) return TOGGLED_ON;
  1600.         if (!stricmp(aBuf, "Off")) return TOGGLED_OFF;
  1601.         if (!stricmp(aBuf, "Send")) return TOGGLE_SEND;
  1602.         if (!stricmp(aBuf, "Mouse")) return TOGGLE_MOUSE;
  1603.         if (!stricmp(aBuf, "SendAndMouse")) return TOGGLE_SENDANDMOUSE;
  1604.         if (!stricmp(aBuf, "Default")) return TOGGLE_DEFAULT;
  1605.         if (!stricmp(aBuf, "MouseMove")) return TOGGLE_MOUSEMOVE;
  1606.         if (!stricmp(aBuf, "MouseMoveOff")) return TOGGLE_MOUSEMOVEOFF;
  1607.         return TOGGLE_INVALID;
  1608.     }
  1609.  
  1610.     static SendModes ConvertSendMode(char *aBuf, SendModes aValueToReturnIfInvalid)
  1611.     {
  1612.         if (!stricmp(aBuf, "Play")) return SM_PLAY;
  1613.         if (!stricmp(aBuf, "Event")) return SM_EVENT;
  1614.         if (!strnicmp(aBuf, "Input", 5)) // This IF must be listed last so that it can fall through to bottom line.
  1615.         {
  1616.             aBuf += 5;
  1617.             if (!*aBuf || !stricmp(aBuf, "ThenEvent")) // "ThenEvent" is supported for backward compatibiltity with 1.0.43.00.
  1618.                 return SM_INPUT;
  1619.             if (!stricmp(aBuf, "ThenPlay"))
  1620.                 return SM_INPUT_FALLBACK_TO_PLAY;
  1621.             //else fall through and return the indication of invalidity.
  1622.         }
  1623.         return aValueToReturnIfInvalid;
  1624.     }
  1625.  
  1626.     static FileLoopModeType ConvertLoopMode(char *aBuf)
  1627.     // Returns the file loop mode, or FILE_LOOP_INVALID if aBuf contains an invalid mode.
  1628.     {
  1629.         switch (ATOI(aBuf))
  1630.         {
  1631.         case 0: return FILE_LOOP_FILES_ONLY; // This is also the default mode if the param is blank.
  1632.         case 1: return FILE_LOOP_FILES_AND_FOLDERS;
  1633.         case 2: return FILE_LOOP_FOLDERS_ONLY;
  1634.         }
  1635.         // Otherwise:
  1636.         return FILE_LOOP_INVALID;
  1637.     }
  1638.  
  1639.     static int ConvertMsgBoxResult(char *aBuf)
  1640.     // Returns the matching ID, or zero if none.
  1641.     {
  1642.         if (!aBuf || !*aBuf) return 0;
  1643.         // Keeping the most oft-used ones up top helps perf. a little:
  1644.         if (!stricmp(aBuf, "YES")) return IDYES;
  1645.         if (!stricmp(aBuf, "NO")) return IDNO;
  1646.         if (!stricmp(aBuf, "OK")) return IDOK;
  1647.         if (!stricmp(aBuf, "CANCEL")) return IDCANCEL;
  1648.         if (!stricmp(aBuf, "ABORT")) return IDABORT;
  1649.         if (!stricmp(aBuf, "IGNORE")) return IDIGNORE;
  1650.         if (!stricmp(aBuf, "RETRY")) return IDRETRY;
  1651.         if (!stricmp(aBuf, "CONTINUE")) return IDCONTINUE; // v1.0.44.08: For use with 2000/XP's "Cancel/Try Again/Continue" MsgBox.
  1652.         if (!stricmp(aBuf, "TRYAGAIN")) return IDTRYAGAIN; //
  1653.         if (!stricmp(aBuf, "Timeout")) return AHK_TIMEOUT; // Our custom result value.
  1654.         return 0;
  1655.     }
  1656.  
  1657.     static int ConvertRunMode(char *aBuf)
  1658.     // Returns the matching WinShow mode, or SW_SHOWNORMAL if none.
  1659.     // These are also the modes that AutoIt3 uses.
  1660.     {
  1661.         // For v1.0.19, this was made more permissive (the use of strcasestr vs. stricmp) to support
  1662.         // the optional word ErrorLevel inside this parameter:
  1663.         if (!aBuf || !*aBuf) return SW_SHOWNORMAL;
  1664.         if (strcasestr(aBuf, "MIN")) return SW_MINIMIZE;
  1665.         if (strcasestr(aBuf, "MAX")) return SW_MAXIMIZE;
  1666.         if (strcasestr(aBuf, "HIDE")) return SW_HIDE;
  1667.         return SW_SHOWNORMAL;
  1668.     }
  1669.  
  1670.     static int ConvertMouseButton(char *aBuf, bool aAllowWheel = true, bool aUseLogicalButton = false)
  1671.     // Returns the matching VK, or zero if none.
  1672.     {
  1673.         if (!*aBuf || !stricmp(aBuf, "LEFT") || !stricmp(aBuf, "L"))
  1674.             return aUseLogicalButton ? VK_LBUTTON_LOGICAL : VK_LBUTTON; // Some callers rely on this default when !*aBuf.
  1675.         if (!stricmp(aBuf, "RIGHT") || !stricmp(aBuf, "R")) return aUseLogicalButton ? VK_RBUTTON_LOGICAL : VK_RBUTTON;
  1676.         if (!stricmp(aBuf, "MIDDLE") || !stricmp(aBuf, "M")) return VK_MBUTTON;
  1677.         if (!stricmp(aBuf, "X1")) return VK_XBUTTON1;
  1678.         if (!stricmp(aBuf, "X2")) return VK_XBUTTON2;
  1679.         if (aAllowWheel)
  1680.         {
  1681.             if (!stricmp(aBuf, "WheelUp") || !stricmp(aBuf, "WU")) return VK_WHEEL_UP;
  1682.             if (!stricmp(aBuf, "WheelDown") || !stricmp(aBuf, "WD")) return VK_WHEEL_DOWN;
  1683.         }
  1684.         return 0;
  1685.     }
  1686.  
  1687.     static CoordModeAttribType ConvertCoordModeAttrib(char *aBuf)
  1688.     {
  1689.         if (!aBuf || !*aBuf) return 0;
  1690.         if (!stricmp(aBuf, "Pixel")) return COORD_MODE_PIXEL;
  1691.         if (!stricmp(aBuf, "Mouse")) return COORD_MODE_MOUSE;
  1692.         if (!stricmp(aBuf, "ToolTip")) return COORD_MODE_TOOLTIP;
  1693.         if (!stricmp(aBuf, "Caret")) return COORD_MODE_CARET;
  1694.         if (!stricmp(aBuf, "Menu")) return COORD_MODE_MENU;
  1695.         return 0;
  1696.     }
  1697.  
  1698.     static VariableTypeType ConvertVariableTypeName(char *aBuf)
  1699.     // Returns the matching type, or zero if none.
  1700.     {
  1701.         if (!aBuf || !*aBuf) return VAR_TYPE_INVALID;
  1702.         if (!stricmp(aBuf, "Integer")) return VAR_TYPE_INTEGER;
  1703.         if (!stricmp(aBuf, "Float")) return VAR_TYPE_FLOAT;
  1704.         if (!stricmp(aBuf, "Number")) return VAR_TYPE_NUMBER;
  1705.         if (!stricmp(aBuf, "Time")) return VAR_TYPE_TIME;
  1706.         if (!stricmp(aBuf, "Date")) return VAR_TYPE_TIME;  // "date" is just an alias for "time".
  1707.         if (!stricmp(aBuf, "Digit")) return VAR_TYPE_DIGIT;
  1708.         if (!stricmp(aBuf, "Xdigit")) return VAR_TYPE_XDIGIT;
  1709.         if (!stricmp(aBuf, "Alnum")) return VAR_TYPE_ALNUM;
  1710.         if (!stricmp(aBuf, "Alpha")) return VAR_TYPE_ALPHA;
  1711.         if (!stricmp(aBuf, "Upper")) return VAR_TYPE_UPPER;
  1712.         if (!stricmp(aBuf, "Lower")) return VAR_TYPE_LOWER;
  1713.         if (!stricmp(aBuf, "Space")) return VAR_TYPE_SPACE;
  1714.         return VAR_TYPE_INVALID;
  1715.     }
  1716.  
  1717.     static ResultType ValidateMouseCoords(char *aX, char *aY)
  1718.     {
  1719.         // OK: Both are absent, which is the signal to use the current position.
  1720.         // OK: Both are present (that they are numeric is validated elsewhere).
  1721.         // FAIL: One is absent but the other is present.
  1722.         return (!*aX && !*aY) || (*aX && *aY) ? OK : FAIL;
  1723.     }
  1724.  
  1725.     static char *LogToText(char *aBuf, int aBufSize);
  1726.     char *VicinityToText(char *aBuf, int aBufSize);
  1727.     char *ToText(char *aBuf, int aBufSize, bool aCRLF, DWORD aElapsed = 0, bool aLineWasResumed = false);
  1728.  
  1729.     static void ToggleSuspendState();
  1730.     ResultType ChangePauseState(ToggleValueType aChangeTo, bool aAlwaysOperateOnUnderlyingThread);
  1731.     static ResultType ScriptBlockInput(bool aEnable);
  1732.  
  1733.     Line *PreparseError(char *aErrorText, char *aExtraInfo = "");
  1734.     // Call this LineError to avoid confusion with Script's error-displaying functions:
  1735.     ResultType LineError(char *aErrorText, ResultType aErrorType = FAIL, char *aExtraInfo = "");
  1736.  
  1737.     Line(FileIndexType aFileIndex, LineNumberType aFileLineNumber, ActionTypeType aActionType
  1738.         , ArgStruct aArg[], ArgCountType aArgc) // Constructor
  1739.         : mFileIndex(aFileIndex), mLineNumber(aFileLineNumber), mActionType(aActionType)
  1740.         , mAttribute(ATTR_NONE), mArgc(aArgc), mArg(aArg)
  1741.         , mPrevLine(NULL), mNextLine(NULL), mRelatedLine(NULL), mParentLine(NULL)
  1742.         {}
  1743.     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1744.     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1745.     void operator delete(void *aPtr) {}  // Intentionally does nothing because we're using SimpleHeap for everything.
  1746.     void operator delete[](void *aPtr) {}
  1747.  
  1748.     // AutoIt3 functions:
  1749.     static bool Util_CopyDir(const char *szInputSource, const char *szInputDest, bool bOverwrite);
  1750.     static bool Util_MoveDir(const char *szInputSource, const char *szInputDest, int OverwriteMode);
  1751.     static bool Util_RemoveDir(const char *szInputSource, bool bRecurse);
  1752.     static int Util_CopyFile(const char *szInputSource, const char *szInputDest, bool bOverwrite, bool bMove);
  1753.     static void Util_ExpandFilenameWildcard(const char *szSource, const char *szDest, char *szExpandedDest);
  1754.     static void Util_ExpandFilenameWildcardPart(const char *szSource, const char *szDest, char *szExpandedDest);
  1755.     static bool Util_CreateDir(const char *szDirName);
  1756.     static bool Util_DoesFileExist(const char *szFilename);
  1757.     static bool Util_IsDir(const char *szPath);
  1758.     static void Util_GetFullPathName(const char *szIn, char *szOut);
  1759.     static bool Util_IsDifferentVolumes(const char *szPath1, const char *szPath2);
  1760. };
  1761.  
  1762.  
  1763.  
  1764. class Label
  1765. {
  1766. public:
  1767.     char *mName;
  1768.     Line *mJumpToLine;
  1769.     Label *mPrevLabel, *mNextLabel;  // Prev & Next items in linked list.
  1770.  
  1771.     bool IsExemptFromSuspend()
  1772.     {
  1773.         // Hotkey and Hotstring subroutines whose first line is the Suspend command are exempt from
  1774.         // being suspended themselves except when their first parameter is the literal
  1775.         // word "on":
  1776.         return mJumpToLine->mActionType == ACT_SUSPEND && (!mJumpToLine->mArgc || mJumpToLine->ArgHasDeref(1)
  1777.             || stricmp(mJumpToLine->mArg[0].text, "On"));
  1778.     }
  1779.  
  1780.     ResultType Execute()
  1781.     // This function was added in v1.0.46.16 to support A_ThisLabel.
  1782.     {
  1783.         Label *prev_label = g.CurrentLabel; // This will be non-NULL when a subroutine is called from inside another subroutine.
  1784.         g.CurrentLabel = this;
  1785.         ResultType result = mJumpToLine->ExecUntil(UNTIL_RETURN); // The script loader has ensured that Label::mJumpToLine can't be NULL.
  1786.         g.CurrentLabel = prev_label;
  1787.         return result;
  1788.     }
  1789.  
  1790.     Label(char *aLabelName)
  1791.         : mName(aLabelName) // Caller gave us a pointer to dynamic memory for this (or an empty string in the case of mPlaceholderLabel).
  1792.         , mJumpToLine(NULL)
  1793.         , mPrevLabel(NULL), mNextLabel(NULL)
  1794.     {}
  1795.     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1796.     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1797.     void operator delete(void *aPtr) {}
  1798.     void operator delete[](void *aPtr) {}
  1799. };
  1800.  
  1801.  
  1802.  
  1803. enum FuncParamDefaults {PARAM_DEFAULT_NONE, PARAM_DEFAULT_STR, PARAM_DEFAULT_INT, PARAM_DEFAULT_FLOAT};
  1804. struct FuncParam
  1805. {
  1806.     Var *var;
  1807.     WORD is_byref; // Boolean, but defined as WORD in case it helps data alignment and/or performance (BOOL vs. WORD didn't help benchmarks).
  1808.     WORD default_type;
  1809.     union {char *default_str; __int64 default_int64; double default_double;};
  1810. };
  1811.  
  1812. typedef void (* BuiltInFunctionType)(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  1813.  
  1814. class Func
  1815. {
  1816. public:
  1817.     char *mName;
  1818.     union {BuiltInFunctionType mBIF; Line *mJumpToLine;};
  1819.     FuncParam *mParam;  // Will hold an array of FuncParams.
  1820.     int mParamCount; // The number of items in the above array.  This is also the function's maximum number of params.
  1821.     int mMinParams;  // The number of mandatory parameters (populated for both UDFs and built-in's).
  1822.     Var **mVar, **mLazyVar; // Array of pointers-to-variable, allocated upon first use and later expanded as needed.
  1823.     int mVarCount, mVarCountMax, mLazyVarCount; // Count of items in the above array as well as the maximum capacity.
  1824.     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.
  1825.     Func *mNextFunc; // Next item in linked list.
  1826.  
  1827.     #define VAR_ASSUME_NONE 0
  1828.     #define VAR_ASSUME_LOCAL 1
  1829.     #define VAR_ASSUME_GLOBAL 2
  1830.     // Keep small members adjacent to each other to save space and improve perf. due to byte alignment:
  1831.     UCHAR mDefaultVarType;
  1832.     bool mIsBuiltIn; // Determines contents of union. Keep this member adjacent/contiguous with the above.
  1833.     // Note that it's possible for a built-in function such as WinExist() to become a normal/UDF via
  1834.     // override in the script.  So mIsBuiltIn should always be used to determine whether the function
  1835.     // is truly built-in, not its name.
  1836.  
  1837.     ResultType Call(char *&aReturnValue) // Making this a function vs. inline doesn't measurable impact performance.
  1838.     {
  1839.         aReturnValue = ""; // Init to default in case function doesn't return a value or it EXITs or fails.
  1840.         // Launch the function similar to Gosub (i.e. not as a new quasi-thread):
  1841.         // The performance gain of conditionally passing NULL in place of result (when this is the
  1842.         // outermost function call of a line consisting only of function calls, namely ACT_EXPRESSION)
  1843.         // would not be significant because the Return command's expression (arg1) must still be evaluated
  1844.         // in case it calls any functions that have side-effects, e.g. "return LogThisError()".
  1845.         Func *prev_func = g.CurrentFunc; // This will be non-NULL when a function is called from inside another function.
  1846.         g.CurrentFunc = this;
  1847.         // Although a GOTO that jumps to a position outside of the function's body could be supported,
  1848.         // it seems best not to for these reasons:
  1849.         // 1) The extreme rarity of a legitimate desire to intentionally do so.
  1850.         // 2) The fact that any return encountered after the Goto cannot provide a return value for
  1851.         //    the function because load-time validation checks for this (it's preferable not to
  1852.         //    give up this check, since it is an informative error message and might also help catch
  1853.         //    bugs in the script).  Gosub does not suffer from this because the return that brings it
  1854.         //    back into the function body belongs to the Gosub and not the function itself.
  1855.         // 3) More difficult to maintain because we have handle jump_to_line the same way ExecUntil() does,
  1856.         //    checking aResult the same way it does, then checking jump_to_line the same way it does, etc.
  1857.         // Fix for v1.0.31.05: g.mLoopFile and the other g_script members that follow it are
  1858.         // now passed to ExecUntil() for two reasons (update for v1.0.44.14: now they're implicitly "passed"
  1859.         // because they're done via parameter anymore):
  1860.         // 1) To fix the fact that any function call in one parameter of a command would reset
  1861.         // A_Index and related variables so that if those variables are referenced in another
  1862.         // parameter of the same command, they would be wrong.
  1863.         // 2) So that the caller's value of A_Index and such will always be valid even inside
  1864.         // of called functions (unless overridden/eclipsed by a loop in the body of the function),
  1865.         // which seems to add flexibility without giving up anything.  This fix is necessary at least
  1866.         // for a command that references A_Index in two of its args such as the following:
  1867.         // ToolTip, O, ((cos(A_Index) * 500) + 500), A_Index
  1868.         ++mInstances;
  1869.         ResultType result = mJumpToLine->ExecUntil(UNTIL_BLOCK_END, &aReturnValue);
  1870.         --mInstances;
  1871.         // Restore the original value in case this function is called from inside another function.
  1872.         // Due to the synchronous nature of recursion and recursion-collapse, this should keep
  1873.         // g.CurrentFunc accurate, even amidst the asynchronous saving and restoring of "g" itself:
  1874.         g.CurrentFunc = prev_func;
  1875.         return result;
  1876.     }
  1877.  
  1878.     Func(char *aFuncName, bool aIsBuiltIn) // Constructor.
  1879.         : mName(aFuncName) // Caller gave us a pointer to dynamic memory for this.
  1880.         , mBIF(NULL)
  1881.         , mParam(NULL), mParamCount(0), mMinParams(0)
  1882.         , mVar(NULL), mVarCount(0), mVarCountMax(0), mLazyVar(NULL), mLazyVarCount(0)
  1883.         , mInstances(0), mNextFunc(NULL)
  1884.         , mDefaultVarType(VAR_ASSUME_NONE)
  1885.         , mIsBuiltIn(aIsBuiltIn)
  1886.     {}
  1887.     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1888.     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1889.     void operator delete(void *aPtr) {}
  1890.     void operator delete[](void *aPtr) {}
  1891. };
  1892.  
  1893.  
  1894.  
  1895. class ScriptTimer
  1896. {
  1897. public:
  1898.     Label *mLabel;
  1899.     DWORD mPeriod; // v1.0.36.33: Changed from int to DWORD to double its capacity.
  1900.     DWORD mTimeLastRun;  // TickCount
  1901.     int mPriority;  // Thread priority relative to other threads, default 0.
  1902.     UCHAR mExistingThreads;  // Whether this timer is already running its subroutine.
  1903.     bool mEnabled;
  1904.     bool mRunOnlyOnce;
  1905.     ScriptTimer *mNextTimer;  // Next items in linked list
  1906.     void ScriptTimer::Disable();
  1907.     ScriptTimer(Label *aLabel)
  1908.         #define DEFAULT_TIMER_PERIOD 250
  1909.         : mLabel(aLabel), mPeriod(DEFAULT_TIMER_PERIOD), mPriority(0) // Default is always 0.
  1910.         , mExistingThreads(0), mTimeLastRun(0)
  1911.         , mEnabled(false), mRunOnlyOnce(false), mNextTimer(NULL)  // Note that mEnabled must default to false for the counts to be right.
  1912.     {}
  1913.     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1914.     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  1915.     void operator delete(void *aPtr) {}
  1916.     void operator delete[](void *aPtr) {}
  1917. };
  1918.  
  1919.  
  1920.  
  1921. struct MsgMonitorStruct
  1922. {
  1923.     UINT msg;
  1924.     Func *func;
  1925.     // Keep any members smaller than 4 bytes adjacent to save memory:
  1926.     short instance_count;  // Distinct from func.mInstances because the script might have called the function explicitly.
  1927.     short max_instances; // v1.0.47: Support more than one thread.
  1928. };
  1929.  
  1930.  
  1931.  
  1932. #define MAX_MENU_NAME_LENGTH MAX_PATH // For both menu and menu item names.
  1933. class UserMenuItem;  // Forward declaration since classes use each other (i.e. a menu *item* can have a submenu).
  1934. class UserMenu
  1935. {
  1936. public:
  1937.     char *mName;  // Dynamically allocated.
  1938.     UserMenuItem *mFirstMenuItem, *mLastMenuItem, *mDefault;
  1939.     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  1940.     // due to byte-alignment:
  1941.     bool mIncludeStandardItems;
  1942.     int mClickCount; // How many clicks it takes to trigger the default menu item.  2 = double-click
  1943.     UINT mMenuItemCount;  // The count of user-defined menu items (doesn't include the standard items, if present).
  1944.     UserMenu *mNextMenu;  // Next item in linked list
  1945.     HMENU mMenu;
  1946.     MenuTypeType mMenuType; // MENU_TYPE_POPUP (via CreatePopupMenu) vs. MENU_TYPE_BAR (via CreateMenu).
  1947.     HBRUSH mBrush;   // Background color to apply to menu.
  1948.     COLORREF mColor; // The color that corresponds to the above.
  1949.  
  1950.     // Don't overload new and delete operators in this case since we want to use real dynamic memory
  1951.     // (since menus can be read in from a file, destroyed and recreated, over and over).
  1952.  
  1953.     UserMenu(char *aName) // Constructor
  1954.         : mName(aName), mFirstMenuItem(NULL), mLastMenuItem(NULL), mDefault(NULL)
  1955.         , mIncludeStandardItems(false), mClickCount(2), mMenuItemCount(0), mNextMenu(NULL), mMenu(NULL)
  1956.         , mMenuType(MENU_TYPE_POPUP) // The MENU_TYPE_NONE flag is not used in this context.  Default = POPUP.
  1957.         , mBrush(NULL), mColor(CLR_DEFAULT)
  1958.     {
  1959.     }
  1960.  
  1961.     ResultType AddItem(char *aName, UINT aMenuID, Label *aLabel, UserMenu *aSubmenu, char *aOptions);
  1962.     ResultType DeleteItem(UserMenuItem *aMenuItem, UserMenuItem *aMenuItemPrev);
  1963.     ResultType DeleteAllItems();
  1964.     ResultType ModifyItem(UserMenuItem *aMenuItem, Label *aLabel, UserMenu *aSubmenu, char *aOptions);
  1965.     void UpdateOptions(UserMenuItem *aMenuItem, char *aOptions);
  1966.     ResultType RenameItem(UserMenuItem *aMenuItem, char *aNewName);
  1967.     ResultType UpdateName(UserMenuItem *aMenuItem, char *aNewName);
  1968.     ResultType CheckItem(UserMenuItem *aMenuItem);
  1969.     ResultType UncheckItem(UserMenuItem *aMenuItem);
  1970.     ResultType ToggleCheckItem(UserMenuItem *aMenuItem);
  1971.     ResultType EnableItem(UserMenuItem *aMenuItem);
  1972.     ResultType DisableItem(UserMenuItem *aMenuItem);
  1973.     ResultType ToggleEnableItem(UserMenuItem *aMenuItem);
  1974.     ResultType SetDefault(UserMenuItem *aMenuItem = NULL);
  1975.     ResultType IncludeStandardItems();
  1976.     ResultType ExcludeStandardItems();
  1977.     ResultType Create(MenuTypeType aMenuType = MENU_TYPE_NONE); // NONE means UNSPECIFIED in this context.
  1978.     void SetColor(char *aColorName, bool aApplyToSubmenus);
  1979.     void ApplyColor(bool aApplyToSubmenus);
  1980.     ResultType AppendStandardItems();
  1981.     ResultType Destroy();
  1982.     ResultType Display(bool aForceToForeground = true, int aX = COORD_UNSPECIFIED, int aY = COORD_UNSPECIFIED);
  1983.     UINT GetSubmenuPos(HMENU ahMenu);
  1984.     UINT GetItemPos(char *aMenuItemName);
  1985.     bool ContainsMenu(UserMenu *aMenu);
  1986. };
  1987.  
  1988.  
  1989.  
  1990. class UserMenuItem
  1991. {
  1992. public:
  1993.     char *mName;  // Dynamically allocated.
  1994.     size_t mNameCapacity;
  1995.     UINT mMenuID;
  1996.     Label *mLabel;
  1997.     UserMenu *mSubmenu;
  1998.     UserMenu *mMenu;  // The menu to which this item belongs.  Needed to support script var A_ThisMenu.
  1999.     int mPriority;
  2000.     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  2001.     // due to byte-alignment:
  2002.     bool mEnabled, mChecked;
  2003.     UserMenuItem *mNextMenuItem;  // Next item in linked list
  2004.  
  2005.     // Constructor:
  2006.     UserMenuItem(char *aName, size_t aNameCapacity, UINT aMenuID, Label *aLabel, UserMenu *aSubmenu, UserMenu *aMenu);
  2007.  
  2008.     // Don't overload new and delete operators in this case since we want to use real dynamic memory
  2009.     // (since menus can be read in from a file, destroyed and recreated, over and over).
  2010. };
  2011.  
  2012.  
  2013.  
  2014. struct FontType
  2015. {
  2016.     #define MAX_FONT_NAME_LENGTH 63  // Longest name I've seen is 29 chars, "Franklin Gothic Medium Italic". Anyway, there's protection against overflow.
  2017.     char name[MAX_FONT_NAME_LENGTH + 1];
  2018.     // Keep any fields that aren't an even multiple of 4 adjacent to each other.  This conserves memory
  2019.     // due to byte-alignment:
  2020.     bool italic;
  2021.     bool underline;
  2022.     bool strikeout;
  2023.     int point_size; // Decided to use int vs. float to simplify the code in many places. Fractional sizes seem rarely needed.
  2024.     int weight;
  2025.     HFONT hfont;
  2026. };
  2027.  
  2028. #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.
  2029. #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.
  2030. 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.
  2031. struct lv_col_type
  2032. {
  2033.     UCHAR type;             // UCHAR vs. enum LVColTypes to save memory.
  2034.     bool sort_disabled;     // If true, clicking the column will have no automatic sorting effect.
  2035.     UCHAR case_sensitive;   // Ignored if type isn't LV_COL_TEXT.  SCS_INSENSITIVE is the default.
  2036.     bool unidirectional;    // Sorting cannot be reversed/toggled.
  2037.     bool prefer_descending; // Whether this column defaults to descending order (on first click or for unidirectional).
  2038. };
  2039.  
  2040. struct lv_attrib_type
  2041. {
  2042.     int sorted_by_col; // Index of column by which the control is currently sorted (-1 if none).
  2043.     bool is_now_sorted_ascending; // The direction in which the above column is currently sorted.
  2044.     bool no_auto_sort; // Automatic sorting disabled.
  2045.     #define LV_MAX_COLUMNS 200
  2046.     lv_col_type col[LV_MAX_COLUMNS];
  2047.     int col_count; // Number of columns currently in the above array.
  2048.     int row_count_hint;
  2049. };
  2050.  
  2051. typedef UCHAR TabControlIndexType;
  2052. typedef UCHAR TabIndexType;
  2053. // Keep the below in sync with the size of the types above:
  2054. #define MAX_TAB_CONTROLS 255  // i.e. the value 255 itself is reserved to mean "doesn't belong to a tab".
  2055. #define MAX_TABS_PER_CONTROL 256
  2056. struct GuiControlType
  2057. {
  2058.     HWND hwnd;
  2059.     // Keep any fields that are smaller than 4 bytes adjacent to each other.  This conserves memory
  2060.     // due to byte-alignment.  It has been verified to save 4 bytes per struct in this case:
  2061.     GuiControls type;
  2062.     #define GUI_CONTROL_ATTRIB_IMPLICIT_CANCEL     0x01
  2063.     #define GUI_CONTROL_ATTRIB_ALTSUBMIT           0x02
  2064.     #define GUI_CONTROL_ATTRIB_LABEL_IS_RUNNING    0x04
  2065.     #define GUI_CONTROL_ATTRIB_EXPLICITLY_HIDDEN   0x08
  2066.     #define GUI_CONTROL_ATTRIB_EXPLICITLY_DISABLED 0x10
  2067.     #define GUI_CONTROL_ATTRIB_BACKGROUND_DEFAULT  0x20 // i.e. Don't conform to window/control background color; use default instead.
  2068.     #define GUI_CONTROL_ATTRIB_BACKGROUND_TRANS    0x40 // i.e. Leave this control's background transparent.
  2069.     #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.
  2070.     UCHAR attrib; // A field of option flags/bits defined above.
  2071.     TabControlIndexType tab_control_index; // Which tab control this control belongs to, if any.
  2072.     TabIndexType tab_index; // For type==TAB, this stores the tab control's index.  For other types, it stores the page.
  2073.     Var *output_var;
  2074.     Label *jump_to_label;
  2075.     union
  2076.     {
  2077.         COLORREF union_color;  // Color of the control's text.
  2078.         HBITMAP union_hbitmap; // For PIC controls, stores the bitmap.
  2079.         // Note: Pic controls cannot obey the text color, but they can obey the window's background
  2080.         // color if the picture's background is transparent (at least in the case of icons on XP).
  2081.         lv_attrib_type *union_lv_attrib; // For ListView: Some attributes and an array of columns.
  2082.     };
  2083.     #define USES_FONT_AND_TEXT_COLOR(type) !(type == GUI_CONTROL_PIC || type == GUI_CONTROL_UPDOWN \
  2084.         || type == GUI_CONTROL_SLIDER || type == GUI_CONTROL_PROGRESS)
  2085. };
  2086.  
  2087. struct GuiControlOptionsType
  2088. {
  2089.     DWORD style_add, style_remove, exstyle_add, exstyle_remove, listview_style;
  2090.     int listview_view; // Viewing mode, such as LVS_ICON, LVS_REPORT.  Int vs. DWORD to more easily use any negative value as "invalid".
  2091.     HIMAGELIST himagelist;
  2092.     Var *hwnd_output_var; // v1.0.46.01: Allows a script to retrieve the control's HWND upon creation of control.
  2093.     int x, y, width, height;  // Position info.
  2094.     float row_count;
  2095.     int choice;  // Which item of a DropDownList/ComboBox/ListBox to initially choose.
  2096.     int range_min, range_max;  // Allowable range, such as for a slider control.
  2097.     int tick_interval; // The interval at which to draw tickmarks for a slider control.
  2098.     int line_size, page_size; // Also for slider.
  2099.     int thickness;  // Thickness of slider's thumb.
  2100.     int tip_side; // Which side of the control to display the tip on (0 to use default side).
  2101.     GuiControlType *buddy1, *buddy2;
  2102.     COLORREF color_listview; // Used only for those controls that need control.union_color for something other than color.
  2103.     COLORREF color_bk; // Control's background color.
  2104.     int limit;   // The max number of characters to permit in an edit or combobox's edit (also used by ListView).
  2105.     int hscroll_pixels;  // The number of pixels for a listbox's horizontal scrollbar to be able to scroll.
  2106.     int checked; // When zeroed, struct contains default starting state of checkbox/radio, i.e. BST_UNCHECKED.
  2107.     int icon_number; // Which icon of a multi-icon file to use.  Zero means use-default, i.e. the first icon.
  2108.     #define GUI_MAX_TABSTOPS 50
  2109.     UINT tabstop[GUI_MAX_TABSTOPS]; // Array of tabstops for the interior of a multi-line edit control.
  2110.     UINT tabstop_count;  // The number of entries in the above array.
  2111.     SYSTEMTIME sys_time[2]; // Needs to support 2 elements for MONTHCAL's multi/range mode.
  2112.     SYSTEMTIME sys_time_range[2];
  2113.     DWORD gdtr, gdtr_range; // Used in connection with sys_time and sys_time_range.
  2114.     ResultType redraw;  // Whether the state of WM_REDRAW should be changed.
  2115.     char password_char; // When zeroed, indicates "use default password" for an edit control with the password style.
  2116.     bool range_changed;
  2117.     bool color_changed; // To discern when a control has been put back to the default color. [v1.0.26]
  2118.     bool start_new_section;
  2119.     bool use_theme; // v1.0.32: Provides the means for the window's current setting of mUseTheme to be overridden.
  2120.     bool listview_no_auto_sort; // v1.0.44: More maintainable and frees up GUI_CONTROL_ATTRIB_ALTBEHAVIOR for other uses.
  2121. };
  2122.  
  2123. LRESULT CALLBACK GuiWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  2124. LRESULT CALLBACK TabWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  2125.  
  2126. class GuiType
  2127. {
  2128. public:
  2129.     #define GUI_STANDARD_WIDTH_MULTIPLIER 15 // This times font size = width, if all other means of determining it are exhausted.
  2130.     #define GUI_STANDARD_WIDTH (GUI_STANDARD_WIDTH_MULTIPLIER * sFont[mCurrentFontIndex].point_size)
  2131.     // Update for v1.0.21: Reduced it to 8 vs. 9 because 8 causes the height each edit (with the
  2132.     // default style) to exactly match that of a Combo or DropDownList.  This type of spacing seems
  2133.     // to be what other apps use too, and seems to make edits stand out a little nicer:
  2134.     #define GUI_CTL_VERTICAL_DEADSPACE 8
  2135.     #define PROGRESS_DEFAULT_THICKNESS (2 * sFont[mCurrentFontIndex].point_size)
  2136.     HWND mHwnd, mStatusBarHwnd;
  2137.     // Control IDs are higher than their index in the array by the below amount.  This offset is
  2138.     // necessary because windows that behave like dialogs automatically return IDOK and IDCANCEL in
  2139.     // response to certain types of standard actions:
  2140.     GuiIndexType mWindowIndex;
  2141.     GuiIndexType mControlCount;
  2142.     GuiIndexType mControlCapacity; // How many controls can fit into the current memory size of mControl.
  2143.     GuiControlType *mControl; // Will become an array of controls when the window is first created.
  2144.     GuiIndexType mDefaultButtonIndex; // Index vs. pointer is needed for some things.
  2145.     Label *mLabelForClose, *mLabelForEscape, *mLabelForSize, *mLabelForDropFiles, *mLabelForContextMenu;
  2146.     bool mLabelForCloseIsRunning, mLabelForEscapeIsRunning, mLabelForSizeIsRunning; // DropFiles doesn't need one of these.
  2147.     bool mLabelsHaveBeenSet;
  2148.     DWORD mStyle, mExStyle; // Style of window.
  2149.     bool mInRadioGroup; // Whether the control currently being created is inside a prior radio-group.
  2150.     bool mUseTheme;  // Whether XP theme and styles should be applied to the parent window and subsequently added controls.
  2151.     HWND mOwner;  // The window that owns this one, if any.  Note that Windows provides no way to change owners after window creation.
  2152.     char mDelimiter;  // The default field delimiter when adding items to ListBox, DropDownList, ListView, etc.
  2153.     int mCurrentFontIndex;
  2154.     GuiControlType *mCurrentListView, *mCurrentTreeView; // The ListView and TreeView upon which the LV/TV functions operate.
  2155.     TabControlIndexType mTabControlCount;
  2156.     TabControlIndexType mCurrentTabControlIndex; // Which tab control of the window.
  2157.     TabIndexType mCurrentTabIndex;// Which tab of a tab control is currently the default for newly added controls.
  2158.     COLORREF mCurrentColor;       // The default color of text in controls.
  2159.     COLORREF mBackgroundColorWin; // The window's background color itself.
  2160.     HBRUSH mBackgroundBrushWin;   // Brush corresponding to the above.
  2161.     COLORREF mBackgroundColorCtl; // Background color for controls.
  2162.     HBRUSH mBackgroundBrushCtl;   // Brush corresponding to the above.
  2163.     HDROP mHdrop;                 // Used for drag and drop operations.
  2164.     HICON mIconEligibleForDestruction; // The window's SysMenu icon, which can be destroyed when the window is destroyed if nothing else is using it.
  2165.     int mMarginX, mMarginY, mPrevX, mPrevY, mPrevWidth, mPrevHeight, mMaxExtentRight, mMaxExtentDown
  2166.         , mSectionX, mSectionY, mMaxExtentRightSection, mMaxExtentDownSection;
  2167.     LONG mMinWidth, mMinHeight, mMaxWidth, mMaxHeight;
  2168.     bool mGuiShowHasNeverBeenDone, mFirstActivation, mShowIsInProgress, mDestroyWindowHasBeenCalled;
  2169.     bool mControlWidthWasSetByContents; // Whether the most recently added control was auto-width'd to fit its contents.
  2170.  
  2171.     #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.
  2172.     static FontType *sFont; // An array of structs, allocated upon first use.
  2173.     static int sFontCount;
  2174.     static int sGuiCount; // The number of non-NULL items in the g_gui array. Maintained only for performance reasons.
  2175.     static HWND sTreeWithEditInProgress; // Needed because TreeView's edit control for label-editing conflicts with IDOK (default button).
  2176.  
  2177.     // Don't overload new and delete operators in this case since we want to use real dynamic memory
  2178.     // (since GUIs can be destroyed and recreated, over and over).
  2179.  
  2180.     // Keep the default destructor to avoid entering the "Law of the Big Three": If your class requires a
  2181.     // copy constructor, copy assignment operator, or a destructor, then it very likely will require all three.
  2182.  
  2183.     GuiType(int aWindowIndex) // Constructor
  2184.         : mHwnd(NULL), mStatusBarHwnd(NULL), mWindowIndex(aWindowIndex), mControlCount(0), mControlCapacity(0)
  2185.         , mDefaultButtonIndex(-1), mLabelForClose(NULL), mLabelForEscape(NULL), mLabelForSize(NULL)
  2186.         , mLabelForDropFiles(NULL), mLabelForContextMenu(NULL)
  2187.         , mLabelForCloseIsRunning(false), mLabelForEscapeIsRunning(false), mLabelForSizeIsRunning(false)
  2188.         , mLabelsHaveBeenSet(false)
  2189.         // The styles DS_CENTER and DS_3DLOOK appear to be ineffectual in this case.
  2190.         // Also note that WS_CLIPSIBLINGS winds up on the window even if unspecified, which is a strong hint
  2191.         // that it should always be used for top level windows across all OSes.  Usenet posts confirm this.
  2192.         // Also, it seems safer to have WS_POPUP under a vague feeling that it seems to apply to dialog
  2193.         // style windows such as this one, and the fact that it also allows the window's caption to be
  2194.         // removed, which implies that POPUP windows are more flexible than OVERLAPPED windows.
  2195.         , mStyle(WS_POPUP|WS_CLIPSIBLINGS|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX) // WS_CLIPCHILDREN (doesn't seem helpful currently)
  2196.         , mExStyle(0) // This and the above should not be used once the window has been created since they might get out of date.
  2197.         , mInRadioGroup(false), mUseTheme(true), mOwner(NULL), mDelimiter('|')
  2198.         , mCurrentFontIndex(FindOrCreateFont()) // Must call this in constructor to ensure sFont array is never NULL while a GUI object exists.  Omit params to tell it to find or create DEFAULT_GUI_FONT.
  2199.         , mCurrentListView(NULL), mCurrentTreeView(NULL)
  2200.         , mTabControlCount(0), mCurrentTabControlIndex(MAX_TAB_CONTROLS), mCurrentTabIndex(0)
  2201.         , mCurrentColor(CLR_DEFAULT)
  2202.         , mBackgroundColorWin(CLR_DEFAULT), mBackgroundBrushWin(NULL)
  2203.         , mBackgroundColorCtl(CLR_DEFAULT), mBackgroundBrushCtl(NULL)
  2204.         , mHdrop(NULL), mIconEligibleForDestruction(NULL)
  2205.         , mMarginX(COORD_UNSPECIFIED), mMarginY(COORD_UNSPECIFIED) // These will be set when the first control is added.
  2206.         , mPrevX(0), mPrevY(0)
  2207.         , mPrevWidth(0), mPrevHeight(0) // Needs to be zero for first control to start off at right offset.
  2208.         , mMaxExtentRight(0), mMaxExtentDown(0)
  2209.         , mSectionX(COORD_UNSPECIFIED), mSectionY(COORD_UNSPECIFIED)
  2210.         , mMaxExtentRightSection(COORD_UNSPECIFIED), mMaxExtentDownSection(COORD_UNSPECIFIED)
  2211.         , mMinWidth(COORD_UNSPECIFIED), mMinHeight(COORD_UNSPECIFIED)
  2212.         , mMaxWidth(COORD_UNSPECIFIED), mMaxHeight(COORD_UNSPECIFIED)
  2213.         , mGuiShowHasNeverBeenDone(true), mFirstActivation(true), mShowIsInProgress(false)
  2214.         , mDestroyWindowHasBeenCalled(false), mControlWidthWasSetByContents(false)
  2215.     {
  2216.         // The array of controls is left unitialized to catch bugs.  Each control's attributes should be
  2217.         // fully populated when it is created.
  2218.         //ZeroMemory(mControl, sizeof(mControl));
  2219.     }
  2220.  
  2221.     static ResultType Destroy(GuiIndexType aWindowIndex);
  2222.     static void DestroyIconIfUnused(HICON ahIcon);
  2223.     ResultType Create();
  2224.     void SetLabels(char *aLabelPrefix);
  2225.     static void UpdateMenuBars(HMENU aMenu);
  2226.     ResultType AddControl(GuiControls aControlType, char *aOptions, char *aText);
  2227.  
  2228.     ResultType ParseOptions(char *aOptions, bool &aSetLastFoundWindow, ToggleValueType &aOwnDialogs);
  2229.     void GetNonClientArea(LONG &aWidth, LONG &aHeight);
  2230.     void GetTotalWidthAndHeight(LONG &aWidth, LONG &aHeight);
  2231.  
  2232.     ResultType ControlParseOptions(char *aOptions, GuiControlOptionsType &aOpt, GuiControlType &aControl
  2233.         , GuiIndexType aControlIndex = -1); // aControlIndex is not needed upon control creation.
  2234.     void ControlInitOptions(GuiControlOptionsType &aOpt, GuiControlType &aControl);
  2235.     void ControlAddContents(GuiControlType &aControl, char *aContent, int aChoice, GuiControlOptionsType *aOpt = NULL);
  2236.     ResultType Show(char *aOptions, char *aTitle);
  2237.     ResultType Clear();
  2238.     ResultType Cancel();
  2239.     ResultType Close(); // Due to SC_CLOSE, etc.
  2240.     ResultType Escape(); // Similar to close, except typically called when the user presses ESCAPE.
  2241.     ResultType Submit(bool aHideIt);
  2242.     ResultType ControlGetContents(Var &aOutputVar, GuiControlType &aControl, char *aMode = "");
  2243.  
  2244.     static VarSizeType ControlGetName(GuiIndexType aGuiWindowIndex, GuiIndexType aControlIndex, char *aBuf);
  2245.     static GuiType *FindGui(HWND aHwnd) // Find which GUI object owns the specified window.
  2246.     {
  2247.         #define EXTERN_GUI extern GuiType *g_gui[MAX_GUI_WINDOWS]
  2248.         EXTERN_GUI;
  2249.         if (!sGuiCount)
  2250.             return NULL;
  2251.  
  2252.         // The loop will usually find it on the first iteration since the #1 window is default
  2253.         // and thus most commonly used.
  2254.         int i, gui_count;
  2255.         for (i = 0, gui_count = 0; i < MAX_GUI_WINDOWS; ++i)
  2256.         {
  2257.             if (g_gui[i])
  2258.             {
  2259.                 if (g_gui[i]->mHwnd == aHwnd)
  2260.                     return g_gui[i];
  2261.                 if (sGuiCount == ++gui_count) // No need to keep searching.
  2262.                     break;
  2263.             }
  2264.         }
  2265.         return NULL;
  2266.     }
  2267.  
  2268.  
  2269.     GuiIndexType FindControl(char *aControlID);
  2270.     GuiControlType *FindControl(HWND aHwnd, bool aRetrieveIndexInstead = false)
  2271.     {
  2272.         GuiIndexType index = GUI_HWND_TO_INDEX(aHwnd); // Retrieves a small negative on failure, which will be out of bounds when converted to unsigned.
  2273.         if (index >= mControlCount) // Not found yet; try again with parent.
  2274.         {
  2275.             // Since ComboBoxes (and possibly other future control types) have children, try looking
  2276.             // up aHwnd's parent to see if its a known control of this dialog.  Some callers rely on us making
  2277.             // this extra effort:
  2278.             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.
  2279.                 index = GUI_HWND_TO_INDEX(aHwnd); // Retrieves a small negative on failure, which will be out of bounds when converted to unsigned.
  2280.         }
  2281.         if (index < mControlCount) // A match was found.
  2282.             return aRetrieveIndexInstead ? (GuiControlType *)(size_t)index : mControl + index;
  2283.         else // No match, so indicate failure.
  2284.             return aRetrieveIndexInstead ? (GuiControlType *)NO_CONTROL_INDEX : NULL;
  2285.     }
  2286.     int FindGroup(GuiIndexType aControlIndex, GuiIndexType &aGroupStart, GuiIndexType &aGroupEnd);
  2287.  
  2288.     ResultType SetCurrentFont(char *aOptions, char *aFontName);
  2289.     static int FindOrCreateFont(char *aOptions = "", char *aFontName = "", FontType *aFoundationFont = NULL
  2290.         , COLORREF *aColor = NULL);
  2291.     static int FindFont(FontType &aFont);
  2292.  
  2293.     void Event(GuiIndexType aControlIndex, UINT aNotifyCode, USHORT aGuiEvent = GUI_EVENT_NONE, UINT aEventInfo = 0);
  2294.  
  2295.     static WORD TextToHotkey(char *aText);
  2296.     static char *HotkeyToText(WORD aHotkey, char *aBuf);
  2297.     void ControlCheckRadioButton(GuiControlType &aControl, GuiIndexType aControlIndex, WPARAM aCheckType);
  2298.     void ControlSetUpDownOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
  2299.     int ControlGetDefaultSliderThickness(DWORD aStyle, int aThumbThickness);
  2300.     void ControlSetSliderOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
  2301.     int ControlInvertSliderIfNeeded(GuiControlType &aControl, int aPosition);
  2302.     void ControlSetListViewOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
  2303.     void ControlSetTreeViewOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt);
  2304.     void ControlSetProgressOptions(GuiControlType &aControl, GuiControlOptionsType &aOpt, DWORD aStyle);
  2305.     bool ControlOverrideBkColor(GuiControlType &aControl);
  2306.  
  2307.     void ControlUpdateCurrentTab(GuiControlType &aTabControl, bool aFocusFirstControl);
  2308.     GuiControlType *FindTabControl(TabControlIndexType aTabControlIndex);
  2309.     int FindTabIndexByName(GuiControlType &aTabControl, char *aName, bool aExactMatch = false);
  2310.     int GetControlCountOnTabPage(TabControlIndexType aTabControlIndex, TabIndexType aTabIndex);
  2311.     POINT GetPositionOfTabClientArea(GuiControlType &aTabControl);
  2312.     ResultType SelectAdjacentTab(GuiControlType &aTabControl, bool aMoveToRight, bool aFocusFirstControl
  2313.         , bool aWrapAround);
  2314.     void ControlGetPosOfFocusedItem(GuiControlType &aControl, POINT &aPoint);
  2315.     static void LV_Sort(GuiControlType &aControl, int aColumnIndex, bool aSortOnlyIfEnabled, char aForceDirection = '\0');
  2316.     static DWORD ControlGetListViewMode(HWND aWnd);
  2317. };
  2318.  
  2319.  
  2320.  
  2321. class Script
  2322. {
  2323. private:
  2324.     friend class Hotkey;
  2325.     Line *mFirstLine, *mLastLine;     // The first and last lines in the linked list.
  2326.     UINT mLineCount;                  // The number of lines.
  2327.     Label *mFirstLabel, *mLastLabel;  // The first and last labels in the linked list.
  2328.     Func *mFirstFunc, *mLastFunc;     // The first and last functions in the linked list.
  2329.     Var **mVar, **mLazyVar; // Array of pointers-to-variable, allocated upon first use and later expanded as needed.
  2330.     int mVarCount, mVarCountMax, mLazyVarCount; // Count of items in the above array as well as the maximum capacity.
  2331.     WinGroup *mFirstGroup, *mLastGroup;  // The first and last variables in the linked list.
  2332.     int mOpenBlockCount; // How many blocks are currently open.
  2333.     bool mNextLineIsFunctionBody; // Whether the very next line to be added will be the first one of the body.
  2334.     Var **mFuncExceptionVar;   // A list of variables declared explicitly local or global.
  2335.     int mFuncExceptionVarCount; // The number of items in the array.
  2336.  
  2337.     // These two track the file number and line number in that file of the line currently being loaded,
  2338.     // which simplifies calls to ScriptError() and LineError() (reduces the number of params that must be passed).
  2339.     // These are used ONLY while loading the script into memory.  After that (while the script is running),
  2340.     // only mCurrLine is kept up-to-date:
  2341.     int mCurrFileIndex;
  2342.     LineNumberType mCombinedLineNumber; // In the case of a continuation section/line(s), this is always the top line.
  2343.  
  2344.     bool mNoHotkeyLabels;
  2345.     bool mMenuUseErrorLevel;  // Whether runtime errors should be displayed by the Menu command, vs. ErrorLevel.
  2346.  
  2347.     #define UPDATE_TIP_FIELD strlcpy(mNIC.szTip, (mTrayIconTip && *mTrayIconTip) ? mTrayIconTip \
  2348.         : (mFileName ? mFileName : NAME_P), sizeof(mNIC.szTip));
  2349.     NOTIFYICONDATA mNIC; // For ease of adding and deleting our tray icon.
  2350.  
  2351. #ifdef AUTOHOTKEYSC
  2352.     ResultType CloseAndReturn(HS_EXEArc_Read *fp, UCHAR *aBuf, ResultType return_value);
  2353.     size_t GetLine(char *aBuf, int aMaxCharsToRead, int aInContinuationSection, UCHAR *&aMemFile);
  2354. #else
  2355.     ResultType CloseAndReturn(FILE *fp, UCHAR *aBuf, ResultType return_value);
  2356.     size_t GetLine(char *aBuf, int aMaxCharsToRead, int aInContinuationSection, FILE *fp);
  2357. #endif
  2358.     ResultType IsDirective(char *aBuf);
  2359.  
  2360.     ResultType ParseAndAddLine(char *aLineText, ActionTypeType aActionType = ACT_INVALID
  2361.         , ActionTypeType aOldActionType = OLD_INVALID, char *aActionName = NULL
  2362.         , char *aEndMarker = NULL, char *aLiteralMap = NULL, size_t aLiteralMapLength = 0);
  2363.     ResultType ParseDerefs(char *aArgText, char *aArgMap, DerefType *aDeref, int &aDerefCount);
  2364.     char *ParseActionType(char *aBufTarget, char *aBufSource, bool aDisplayErrors);
  2365.     static ActionTypeType ConvertActionType(char *aActionTypeString);
  2366.     static ActionTypeType ConvertOldActionType(char *aActionTypeString);
  2367.     ResultType AddLabel(char *aLabelName, bool aAllowDupe);
  2368.     ResultType AddLine(ActionTypeType aActionType, char *aArg[] = NULL, ArgCountType aArgc = 0, char *aArgMap[] = NULL);
  2369.  
  2370.     // These aren't in the Line class because I think they're easier to implement
  2371.     // if aStartingLine is allowed to be NULL (for recursive calls).  If they
  2372.     // were member functions of class Line, a check for NULL would have to
  2373.     // be done before dereferencing any line's mNextLine, for example:
  2374.     Line *PreparseBlocks(Line *aStartingLine, bool aFindBlockEnd = false, Line *aParentLine = NULL);
  2375.     Line *PreparseIfElse(Line *aStartingLine, ExecUntilMode aMode = NORMAL_MODE, AttributeType aLoopTypeFile = ATTR_NONE
  2376.         , AttributeType aLoopTypeReg = ATTR_NONE, AttributeType aLoopTypeRead = ATTR_NONE
  2377.         , AttributeType aLoopTypeParse = ATTR_NONE);
  2378.  
  2379. public:
  2380.     Line *mCurrLine;     // Seems better to make this public than make Line our friend.
  2381.     Label *mPlaceholderLabel; // Used in place of a NULL label to simplify code.
  2382.     char mThisMenuItemName[MAX_MENU_NAME_LENGTH + 1];
  2383.     char mThisMenuName[MAX_MENU_NAME_LENGTH + 1];
  2384.     char *mThisHotkeyName, *mPriorHotkeyName;
  2385.     HWND mNextClipboardViewer;
  2386.     bool mOnClipboardChangeIsRunning;
  2387.     Label *mOnClipboardChangeLabel, *mOnExitLabel;  // The label to run when the script terminates (NULL if none).
  2388.     ExitReasons mExitReason;
  2389.  
  2390.     ScriptTimer *mFirstTimer, *mLastTimer;  // The first and last script timers in the linked list.
  2391.     UINT mTimerCount, mTimerEnabledCount;
  2392.  
  2393.     UserMenu *mFirstMenu, *mLastMenu;
  2394.     UINT mMenuCount;
  2395.  
  2396.     DWORD mThisHotkeyStartTime, mPriorHotkeyStartTime;  // Tickcount timestamp of when its subroutine began.
  2397.     char mEndChar;  // The ending character pressed to trigger the most recent non-auto-replace hotstring.
  2398.     modLR_type mThisHotkeyModifiersLR;
  2399.     char *mFileSpec; // Will hold the full filespec, for convenience.
  2400.     char *mFileDir;  // Will hold the directory containing the script file.
  2401.     char *mFileName; // Will hold the script's naked file name.
  2402.     char *mOurEXE; // Will hold this app's module name (e.g. C:\Program Files\AutoHotkey\AutoHotkey.exe).
  2403.     char *mOurEXEDir;  // Same as above but just the containing diretory (for convenience).
  2404.     char *mMainWindowTitle; // Will hold our main window's title, for consistency & convenience.
  2405.     bool mIsReadyToExecute;
  2406.     bool AutoExecSectionIsRunning;
  2407.     bool mIsRestart; // The app is restarting rather than starting from scratch.
  2408.     bool mIsAutoIt2; // Whether this script is considered to be an AutoIt2 script.
  2409.     bool mErrorStdOut; // true if load-time syntax errors should be sent to stdout vs. a MsgBox.
  2410. #ifdef AUTOHOTKEYSC
  2411.     bool mCompiledHasCustomIcon; // Whether the compiled script uses a custom icon.
  2412. #else
  2413.     FILE *mIncludeLibraryFunctionsThenExit;
  2414. #endif
  2415.     __int64 mLinesExecutedThisCycle; // Use 64-bit to match the type of g.LinesPerCycle
  2416.     int mUninterruptedLineCountMax; // 32-bit for performance (since huge values seem unnecessary here).
  2417.     int mUninterruptibleTime;
  2418.     DWORD mLastScriptRest, mLastPeekTime;
  2419.  
  2420.     #define RUNAS_SIZE_IN_WCHARS 257  // Includes the terminator.
  2421.     #define RUNAS_SIZE_IN_BYTES (RUNAS_SIZE_IN_WCHARS * sizeof(WCHAR))
  2422.     WCHAR *mRunAsUser, *mRunAsPass, *mRunAsDomain; // Memory is allocated at runtime, upon first use.
  2423.  
  2424.     HICON mCustomIcon;  // NULL unless the script has loaded a custom icon during its runtime.
  2425.     char *mCustomIconFile; // Filename of icon.  Allocated on first use.
  2426.     bool mIconFrozen; // If true, the icon does not change state when the state of pause or suspend changes.
  2427.     char *mTrayIconTip;  // Custom tip text for tray icon.  Allocated on first use.
  2428.     UINT mCustomIconNumber; // The number of the icon inside the above file.
  2429.  
  2430.     UserMenu *mTrayMenu; // Our tray menu, which should be destroyed upon exiting the program.
  2431.     
  2432.     ResultType Init(char *aScriptFilename, bool aIsRestart);
  2433.     ResultType CreateWindows();
  2434.     void CreateTrayIcon();
  2435.     void UpdateTrayIcon(bool aForceUpdate = false);
  2436.     ResultType AutoExecSection();
  2437.     ResultType Edit();
  2438.     ResultType Reload(bool aDisplayErrors);
  2439.     ResultType ExitApp(ExitReasons aExitReason, char *aBuf = NULL, int ExitCode = 0);
  2440.     void TerminateApp(int aExitCode);
  2441. #ifdef AUTOHOTKEYSC
  2442.     LineNumberType LoadFromFile();
  2443. #else
  2444.     LineNumberType LoadFromFile(bool aScriptWasNotspecified);
  2445. #endif
  2446.     ResultType LoadIncludedFile(char *aFileSpec, bool aAllowDuplicateInclude, bool aIgnoreLoadFailure);
  2447.     ResultType UpdateOrCreateTimer(Label *aLabel, char *aPeriod, char *aPriority, bool aEnable
  2448.         , bool aUpdatePriorityOnly);
  2449.  
  2450.     ResultType DefineFunc(char *aBuf, Var *aFuncExceptionVar[]);
  2451. #ifndef AUTOHOTKEYSC
  2452.     Func *FindFuncInLibrary(char *aFuncName, size_t aFuncNameLength, bool &aErrorWasShown);
  2453. #endif
  2454.     Func *FindFunc(char *aFuncName, size_t aFuncNameLength = 0);
  2455.     Func *AddFunc(char *aFuncName, size_t aFuncNameLength, bool aIsBuiltIn);
  2456.  
  2457.     #define ALWAYS_USE_DEFAULT  0
  2458.     #define ALWAYS_USE_GLOBAL   1
  2459.     #define ALWAYS_USE_LOCAL    2
  2460.     #define ALWAYS_PREFER_LOCAL 3
  2461.     Var *FindOrAddVar(char *aVarName, size_t aVarNameLength = 0, int aAlwaysUse = ALWAYS_USE_DEFAULT
  2462.         , bool *apIsException = NULL);
  2463.     Var *FindVar(char *aVarName, size_t aVarNameLength = 0, int *apInsertPos = NULL
  2464.         , int aAlwaysUse = ALWAYS_USE_DEFAULT, bool *apIsException = NULL
  2465.         , bool *apIsLocal = NULL);
  2466.     Var *AddVar(char *aVarName, size_t aVarNameLength, int aInsertPos, int aIsLocal);
  2467.     static void *GetVarType(char *aVarName);
  2468.  
  2469.     WinGroup *FindGroup(char *aGroupName, bool aCreateIfNotFound = false);
  2470.     ResultType AddGroup(char *aGroupName);
  2471.     Label *FindLabel(char *aLabelName);
  2472.  
  2473.     ResultType DoRunAs(char *aCommandLine, char *aWorkingDir, bool aDisplayErrors, bool aUpdateLastError, WORD aShowWindow
  2474.         , Var *aOutputVar, PROCESS_INFORMATION &aPI, bool &aSuccess, HANDLE &aNewProcess, char *aSystemErrorText);
  2475.     ResultType ActionExec(char *aAction, char *aParams = NULL, char *aWorkingDir = NULL
  2476.         , bool aDisplayErrors = true, char *aRunShowMode = NULL, HANDLE *aProcess = NULL
  2477.         , bool aUpdateLastError = false, bool aUseRunAs = false, Var *aOutputVar = NULL);
  2478.  
  2479.     char *ListVars(char *aBuf, int aBufSize);
  2480.     char *ListKeyHistory(char *aBuf, int aBufSize);
  2481.  
  2482.     ResultType PerformMenu(char *aMenu, char *aCommand, char *aParam3, char *aParam4, char *aOptions);
  2483.     UserMenu *FindMenu(char *aMenuName);
  2484.     UserMenu *AddMenu(char *aMenuName);
  2485.     ResultType ScriptDeleteMenu(UserMenu *aMenu);
  2486.     UserMenuItem *FindMenuItemByID(UINT aID)
  2487.     {
  2488.         UserMenuItem *mi;
  2489.         for (UserMenu *m = mFirstMenu; m; m = m->mNextMenu)
  2490.             for (mi = m->mFirstMenuItem; mi; mi = mi->mNextMenuItem)
  2491.                 if (mi->mMenuID == aID)
  2492.                     return mi;
  2493.         return NULL;
  2494.     }
  2495.  
  2496.     ResultType PerformGui(char *aCommand, char *aControlType, char *aOptions, char *aParam4);
  2497.  
  2498.     // Call this SciptError to avoid confusion with Line's error-displaying functions:
  2499.     ResultType ScriptError(char *aErrorText, char *aExtraInfo = ""); // , ResultType aErrorType = FAIL);
  2500.  
  2501.     #define SOUNDPLAY_ALIAS "AHK_PlayMe"  // Used by destructor and SoundPlay().
  2502.  
  2503.     Script();
  2504.     ~Script();
  2505.     // Note that the anchors to any linked lists will be lost when this
  2506.     // object goes away, so for now, be sure the destructor is only called
  2507.     // when the program is about to be exited, which will thereby reclaim
  2508.     // the memory used by the abandoned linked lists (otherwise, a memory
  2509.     // leak will result).
  2510. };
  2511.  
  2512.  
  2513.  
  2514. ////////////////////////
  2515. // BUILT-IN VARIABLES //
  2516. ////////////////////////
  2517. VarSizeType BIV_True_False(char *aBuf, char *aVarName);
  2518. VarSizeType BIV_MMM_DDD(char *aBuf, char *aVarName);
  2519. VarSizeType BIV_DateTime(char *aBuf, char *aVarName);
  2520. VarSizeType BIV_BatchLines(char *aBuf, char *aVarName);
  2521. VarSizeType BIV_TitleMatchMode(char *aBuf, char *aVarName);
  2522. VarSizeType BIV_TitleMatchModeSpeed(char *aBuf, char *aVarName);
  2523. VarSizeType BIV_DetectHiddenWindows(char *aBuf, char *aVarName);
  2524. VarSizeType BIV_DetectHiddenText(char *aBuf, char *aVarName);
  2525. VarSizeType BIV_AutoTrim(char *aBuf, char *aVarName);
  2526. VarSizeType BIV_StringCaseSense(char *aBuf, char *aVarName);
  2527. VarSizeType BIV_FormatInteger(char *aBuf, char *aVarName);
  2528. VarSizeType BIV_FormatFloat(char *aBuf, char *aVarName);
  2529. VarSizeType BIV_KeyDelay(char *aBuf, char *aVarName);
  2530. VarSizeType BIV_WinDelay(char *aBuf, char *aVarName);
  2531. VarSizeType BIV_ControlDelay(char *aBuf, char *aVarName);
  2532. VarSizeType BIV_MouseDelay(char *aBuf, char *aVarName);
  2533. VarSizeType BIV_DefaultMouseSpeed(char *aBuf, char *aVarName);
  2534. VarSizeType BIV_IsSuspended(char *aBuf, char *aVarName);
  2535. #ifdef AUTOHOTKEYSC  // A_IsCompiled is left blank/undefined in uncompiled scripts.
  2536. VarSizeType BIV_IsCompiled(char *aBuf, char *aVarName);
  2537. #endif
  2538. VarSizeType BIV_LastError(char *aBuf, char *aVarName);
  2539. VarSizeType BIV_IconHidden(char *aBuf, char *aVarName);
  2540. VarSizeType BIV_IconTip(char *aBuf, char *aVarName);
  2541. VarSizeType BIV_IconFile(char *aBuf, char *aVarName);
  2542. VarSizeType BIV_IconNumber(char *aBuf, char *aVarName);
  2543. VarSizeType BIV_ExitReason(char *aBuf, char *aVarName);
  2544. VarSizeType BIV_Space_Tab(char *aBuf, char *aVarName);
  2545. VarSizeType BIV_AhkVersion(char *aBuf, char *aVarName);
  2546. VarSizeType BIV_AhkPath(char *aBuf, char *aVarName);
  2547. VarSizeType BIV_TickCount(char *aBuf, char *aVarName);
  2548. VarSizeType BIV_Now(char *aBuf, char *aVarName);
  2549. VarSizeType BIV_OSType(char *aBuf, char *aVarName);
  2550. VarSizeType BIV_OSVersion(char *aBuf, char *aVarName);
  2551. VarSizeType BIV_Language(char *aBuf, char *aVarName);
  2552. VarSizeType BIV_UserName_ComputerName(char *aBuf, char *aVarName);
  2553. VarSizeType BIV_WorkingDir(char *aBuf, char *aVarName);
  2554. VarSizeType BIV_WinDir(char *aBuf, char *aVarName);
  2555. VarSizeType BIV_Temp(char *aBuf, char *aVarName);
  2556. VarSizeType BIV_ComSpec(char *aBuf, char *aVarName);
  2557. VarSizeType BIV_ProgramFiles(char *aBuf, char *aVarName);
  2558. VarSizeType BIV_AppData(char *aBuf, char *aVarName);
  2559. VarSizeType BIV_Desktop(char *aBuf, char *aVarName);
  2560. VarSizeType BIV_StartMenu(char *aBuf, char *aVarName);
  2561. VarSizeType BIV_Programs(char *aBuf, char *aVarName);
  2562. VarSizeType BIV_Startup(char *aBuf, char *aVarName);
  2563. VarSizeType BIV_MyDocuments(char *aBuf, char *aVarName);
  2564. VarSizeType BIV_Caret(char *aBuf, char *aVarName);
  2565. VarSizeType BIV_Cursor(char *aBuf, char *aVarName);
  2566. VarSizeType BIV_ScreenWidth_Height(char *aBuf, char *aVarName);
  2567. VarSizeType BIV_ScriptName(char *aBuf, char *aVarName);
  2568. VarSizeType BIV_ScriptDir(char *aBuf, char *aVarName);
  2569. VarSizeType BIV_ScriptFullPath(char *aBuf, char *aVarName);
  2570. VarSizeType BIV_LineNumber(char *aBuf, char *aVarName);
  2571. VarSizeType BIV_LineFile(char *aBuf, char *aVarName);
  2572. VarSizeType BIV_LoopFileName(char *aBuf, char *aVarName);
  2573. VarSizeType BIV_LoopFileShortName(char *aBuf, char *aVarName);
  2574. VarSizeType BIV_LoopFileExt(char *aBuf, char *aVarName);
  2575. VarSizeType BIV_LoopFileDir(char *aBuf, char *aVarName);
  2576. VarSizeType BIV_LoopFileFullPath(char *aBuf, char *aVarName);
  2577. VarSizeType BIV_LoopFileLongPath(char *aBuf, char *aVarName);
  2578. VarSizeType BIV_LoopFileShortPath(char *aBuf, char *aVarName);
  2579. VarSizeType BIV_LoopFileTime(char *aBuf, char *aVarName);
  2580. VarSizeType BIV_LoopFileAttrib(char *aBuf, char *aVarName);
  2581. VarSizeType BIV_LoopFileSize(char *aBuf, char *aVarName);
  2582. VarSizeType BIV_LoopRegType(char *aBuf, char *aVarName);
  2583. VarSizeType BIV_LoopRegKey(char *aBuf, char *aVarName);
  2584. VarSizeType BIV_LoopRegSubKey(char *aBuf, char *aVarName);
  2585. VarSizeType BIV_LoopRegName(char *aBuf, char *aVarName);
  2586. VarSizeType BIV_LoopRegTimeModified(char *aBuf, char *aVarName);
  2587. VarSizeType BIV_LoopReadLine(char *aBuf, char *aVarName);
  2588. VarSizeType BIV_LoopField(char *aBuf, char *aVarName);
  2589. VarSizeType BIV_LoopIndex(char *aBuf, char *aVarName);
  2590. VarSizeType BIV_ThisFunc(char *aBuf, char *aVarName);
  2591. VarSizeType BIV_ThisLabel(char *aBuf, char *aVarName);
  2592. VarSizeType BIV_ThisMenuItem(char *aBuf, char *aVarName);
  2593. VarSizeType BIV_ThisMenuItemPos(char *aBuf, char *aVarName);
  2594. VarSizeType BIV_ThisMenu(char *aBuf, char *aVarName);
  2595. VarSizeType BIV_ThisHotkey(char *aBuf, char *aVarName);
  2596. VarSizeType BIV_PriorHotkey(char *aBuf, char *aVarName);
  2597. VarSizeType BIV_TimeSinceThisHotkey(char *aBuf, char *aVarName);
  2598. VarSizeType BIV_TimeSincePriorHotkey(char *aBuf, char *aVarName);
  2599. VarSizeType BIV_EndChar(char *aBuf, char *aVarName);
  2600. VarSizeType BIV_Gui(char *aBuf, char *aVarName);
  2601. VarSizeType BIV_GuiControl(char *aBuf, char *aVarName);
  2602. VarSizeType BIV_GuiEvent(char *aBuf, char *aVarName);
  2603. VarSizeType BIV_EventInfo(char *aBuf, char *aVarName);
  2604. VarSizeType BIV_TimeIdle(char *aBuf, char *aVarName);
  2605. VarSizeType BIV_TimeIdlePhysical(char *aBuf, char *aVarName);
  2606. VarSizeType BIV_IPAddress(char *aBuf, char *aVarName);
  2607. VarSizeType BIV_IsAdmin(char *aBuf, char *aVarName);
  2608.  
  2609.  
  2610.  
  2611. ////////////////////////
  2612. // BUILT-IN FUNCTIONS //
  2613. ////////////////////////
  2614. // Caller has ensured that SYM_VAR's Type() is VAR_NORMAL and that it's either not an environment
  2615. // variable or the caller wants environment varibles treated as having zero length.
  2616. #define EXPR_TOKEN_LENGTH(token_raw, token_as_string) \
  2617. (token_raw->symbol == SYM_VAR && !token_raw->var->IsBinaryClip()) \
  2618.     ? token_raw->var->Length()\
  2619.     : strlen(token_as_string)
  2620.  
  2621. void BIF_DllCall(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2622. void BIF_StrLen(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2623. void BIF_SubStr(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2624. void BIF_InStr(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2625. void BIF_RegEx(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2626. void BIF_Asc(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2627. void BIF_Chr(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2628. void BIF_NumGet(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2629. void BIF_NumPut(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2630. void BIF_IsLabel(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2631. void BIF_GetKeyState(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2632. void BIF_VarSetCapacity(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2633. void BIF_FileExist(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2634. void BIF_WinExistActive(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2635. void BIF_Round(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2636. void BIF_FloorCeil(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2637. void BIF_Mod(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2638. void BIF_Abs(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2639. void BIF_Sin(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2640. void BIF_Cos(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2641. void BIF_Tan(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2642. void BIF_ASinACos(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2643. void BIF_ATan(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2644. void BIF_Exp(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2645. void BIF_SqrtLogLn(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2646.  
  2647. void BIF_OnMessage(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2648. void BIF_RegisterCallback(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2649.  
  2650. void BIF_StatusBar(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2651.  
  2652. void BIF_LV_GetNextOrCount(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2653. void BIF_LV_GetText(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2654. void BIF_LV_AddInsertModify(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2655. void BIF_LV_Delete(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2656. void BIF_LV_InsertModifyDeleteCol(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2657. void BIF_LV_SetImageList(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2658.  
  2659. void BIF_TV_AddModifyDelete(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2660. void BIF_TV_GetRelatedItem(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2661. void BIF_TV_Get(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2662.  
  2663. void BIF_IL_Create(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2664. void BIF_IL_Destroy(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2665. void BIF_IL_Add(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount);
  2666.  
  2667. __int64 ExprTokenToInt64(ExprTokenType &aToken);
  2668. double ExprTokenToDouble(ExprTokenType &aToken);
  2669. char *ExprTokenToString(ExprTokenType &aToken, char *aBuf);
  2670. ResultType ExprTokenToDoubleOrInt(ExprTokenType &aToken);
  2671.  
  2672. char *RegExMatch(char *aHaystack, char *aNeedleRegEx);
  2673. void SetWorkingDir(char *aNewDir);
  2674. int ConvertJoy(char *aBuf, int *aJoystickID = NULL, bool aAllowOnlyButtons = false);
  2675. bool ScriptGetKeyState(vk_type aVK, KeyStateTypes aKeyStateType);
  2676. double ScriptGetJoyState(JoyControls aJoy, int aJoystickID, ExprTokenType &aToken, bool aUseBoolForUpDown);
  2677.  
  2678. #endif
  2679.