/
script.h
3363 lines (3021 loc) · 159 KB
/
script.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
AutoHotkey
Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef script_h
#define script_h
#include "stdafx.h" // pre-compiled headers
#include "defines.h"
#include "SimpleHeap.h" // for overloaded new/delete operators.
#include "keyboard_mouse.h" // for modLR_type
#include "var.h" // for a script's variables.
#include "WinGroup.h" // for a script's Window Groups.
#include "Util.h" // for FileTimeToYYYYMMDD(), strlcpy()
#include "resources/resource.h" // For tray icon.
#include "script_object.h"
#include "Debugger.h"
#include "os_version.h" // For the global OS_Version object
EXTERN_OSVER; // For the access to the g_os version object without having to include globaldata.h
EXTERN_G;
#define MAX_THREADS_LIMIT UCHAR_MAX // Uses UCHAR_MAX (255) because some variables that store a thread count are UCHARs.
#define MAX_THREADS_DEFAULT 10 // Must not be higher than above.
#define EMERGENCY_THREADS 2 // This is the number of extra threads available after g_MaxThreadsTotal has been reached for the following to launch: hotkeys/etc. whose first line is something important like ExitApp or Pause. (see #MaxThreads documentation).
#define MAX_THREADS_EMERGENCY (g_MaxThreadsTotal + EMERGENCY_THREADS)
#define TOTAL_ADDITIONAL_THREADS (EMERGENCY_THREADS + 2) // See below.
// Must allow two beyond EMERGENCY_THREADS: One for the AutoExec/idle thread and one so that ExitApp()
// can run even when MAX_THREADS_EMERGENCY has been reached.
// Explanation: If/when AutoExec() finishes, although it no longer needs g_array[0] (not even
// AutoExecSectionTimeout() needs it because it either won't be called or it will return early),
// at least the following might still use g_array[0]:
// 1) Threadless (fast-mode) callbacks that have no controlling script thread; see RegisterCallbackCStub().
// 2) g_array[0].IsPaused indicates whether the script is in a paused state while idle.
// In addition, it probably simplifies the code not to reclaim g_array[0]; e.g. ++g and --g can be done
// unconditionally when creating new threads.
enum ExecUntilMode {NORMAL_MODE, UNTIL_RETURN, UNTIL_BLOCK_END, ONLY_ONE_LINE};
// It's done this way so that mAttribute can store a pointer or one of these constants.
// If it is storing a pointer for a given Action Type, be sure never to compare it
// for equality against these constants because by coincidence, the pointer value
// might just match one of them:
#define ATTR_NONE (void *)0 // Some places might rely on this being zero.
#define ATTR_TRUE (void *)1
#define ATTR_LOOP_UNKNOWN (void *)1 // Same value as the above. // KEEP IN SYNC WITH BELOW.
#define ATTR_LOOP_IS_UNKNOWN_OR_NONE(attr) (attr <= ATTR_LOOP_UNKNOWN) // KEEP IN SYNC WITH ABOVE.
#define ATTR_LOOP_NORMAL (void *)2
#define ATTR_LOOP_FILEPATTERN (void *)3
#define ATTR_LOOP_REG (void *)4
#define ATTR_LOOP_READ_FILE (void *)5
#define ATTR_LOOP_PARSE (void *)6
#define ATTR_LOOP_WHILE (void *)7 // Lexikos: This is used to differentiate ACT_WHILE from ACT_LOOP, allowing code to be shared.
#define ATTR_LOOP_FOR (void *)8
#define ATTR_LOOP_NEW_REG (void *)9
#define ATTR_LOOP_NEW_FILES (void *)10
#define ATTR_LOOP_OBSCURED (void *)100 // fincs: used by Line::PreparseIfElse() for ACT_FINALLY blocks.
#define ATTR_OBSCURE(attr) ((attr) ? ATTR_LOOP_OBSCURED : ATTR_NONE)
typedef void *AttributeType;
typedef int FileLoopModeType;
#define FILE_LOOP_INVALID 0
#define FILE_LOOP_FILES_ONLY 1
#define FILE_LOOP_FOLDERS_ONLY 2
#define FILE_LOOP_RECURSE 4
#define FILE_LOOP_FILES_AND_FOLDERS (FILE_LOOP_FILES_ONLY | FILE_LOOP_FOLDERS_ONLY)
enum VariableTypeType {VAR_TYPE_INVALID, VAR_TYPE_NUMBER, VAR_TYPE_INTEGER, VAR_TYPE_FLOAT
, VAR_TYPE_TIME , VAR_TYPE_DIGIT, VAR_TYPE_XDIGIT, VAR_TYPE_ALNUM, VAR_TYPE_ALPHA
, VAR_TYPE_UPPER, VAR_TYPE_LOWER, VAR_TYPE_SPACE};
#define ATTACH_THREAD_INPUT \
bool threads_are_attached = false;\
DWORD target_thread = GetWindowThreadProcessId(target_window, NULL);\
if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;
// BELOW IS SAME AS ABOVE except it checks do_activate and also does a SetActiveWindow():
#define ATTACH_THREAD_INPUT_AND_SETACTIVEWINDOW_IF_DO_ACTIVATE \
bool threads_are_attached = false;\
DWORD target_thread;\
if (do_activate)\
{\
target_thread = GetWindowThreadProcessId(target_window, NULL);\
if (target_thread && target_thread != g_MainThreadID && !IsWindowHung(target_window))\
threads_are_attached = AttachThreadInput(g_MainThreadID, target_thread, TRUE) != 0;\
SetActiveWindow(target_window);\
}
#define DETACH_THREAD_INPUT \
if (threads_are_attached)\
AttachThreadInput(g_MainThreadID, target_thread, FALSE);
#define RESEED_RANDOM_GENERATOR \
{\
FILETIME ft;\
GetSystemTimeAsFileTime(&ft);\
init_genrand(ft.dwLowDateTime);\
}
#define IS_PERSISTENT (Hotkey::sHotkeyCount || Hotstring::sHotstringCount || g_KeybdHook || g_MouseHook || g_persistent)
// Since WM_COMMAND IDs must be shared among all menus and controls, they are carefully conserved,
// especially since there are only 65,535 possible IDs. In addition, they are assigned to ranges
// to minimize the need that they will need to be changed in the future (changing the ID of a main
// menu item, tray menu item, or a user-defined menu item [by way of increasing MAX_CONTROLS_PER_GUI]
// is bad because some scripts might be using PostMessage/SendMessage to automate AutoHotkey itself).
// For this reason, the following ranges are reserved:
// 0: unused (possibly special in some contexts)
// 1: IDOK
// 2: IDCANCEL
// 3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
// 1003 to 65299: User Defined Menu IDs
// 65300 to 65399: Standard tray menu items.
// 65400 to 65534: main menu items (might be best to leave 65535 unused in case it ever has special meaning)
enum CommandIDs {CONTROL_ID_FIRST = IDCANCEL + 1
, 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).
, ID_USER_LAST = 65299 // The last. Especially do not change this due to scripts using Post/SendMessage to automate AutoHotkey.
, ID_TRAY_FIRST, ID_TRAY_OPEN = ID_TRAY_FIRST
, ID_TRAY_HELP, ID_TRAY_WINDOWSPY, ID_TRAY_RELOADSCRIPT
, ID_TRAY_EDITSCRIPT, ID_TRAY_SUSPEND, ID_TRAY_PAUSE, ID_TRAY_EXIT
, ID_TRAY_SEP1, ID_TRAY_SEP2, ID_TRAY_LAST = ID_TRAY_SEP2 // But this value should never hit the below. There is debug code to enforce.
, ID_MAIN_FIRST = 65400, ID_MAIN_LAST = 65534}; // These should match the range used by resource.h
#define GUI_INDEX_TO_ID(index) (index + CONTROL_ID_FIRST)
#define GUI_ID_TO_INDEX(id) (id - CONTROL_ID_FIRST) // Returns a small negative if "id" is invalid, such as 0.
#define GUI_HWND_TO_INDEX(hwnd) GUI_ID_TO_INDEX(GetDlgCtrlID(hwnd)) // Returns a small negative on failure (e.g. HWND not found).
// Notes about above:
// 1) Callers should call GuiType::FindControl() instead of GUI_HWND_TO_INDEX() if the hwnd might be a combobox's
// edit control.
// 2) Testing shows that GetDlgCtrlID() is much faster than looping through a GUI window's control array to find
// a matching HWND.
#define ERR_ABORT_NO_SPACES _T("The current thread will exit.")
#define ERR_ABORT _T(" ") ERR_ABORT_NO_SPACES
#define WILL_EXIT _T("The program will exit.")
#define OLD_STILL_IN_EFFECT _T("The script was not reloaded; the old version will remain in effect.")
#define ERR_ABORT_DELETE _T("__Delete will now return.")
#define ERR_CONTINUATION_SECTION_TOO_LONG _T("Continuation section too long.")
#define ERR_UNRECOGNIZED_ACTION _T("This line does not contain a recognized action.")
#define ERR_NONEXISTENT_HOTKEY _T("Nonexistent hotkey.")
#define ERR_NONEXISTENT_VARIANT _T("Nonexistent hotkey variant (IfWin).")
#define ERR_NONEXISTENT_FUNCTION _T("Call to nonexistent function.")
#define ERR_EXE_CORRUPTED _T("EXE corrupted")
#define ERR_INVALID_VALUE _T("Invalid value.")
#define ERR_PARAM1_INVALID _T("Parameter #1 invalid.")
#define ERR_PARAM2_INVALID _T("Parameter #2 invalid.")
#define ERR_PARAM3_INVALID _T("Parameter #3 invalid.")
#define ERR_PARAM4_INVALID _T("Parameter #4 invalid.")
#define ERR_PARAM5_INVALID _T("Parameter #5 invalid.")
#define ERR_PARAM6_INVALID _T("Parameter #6 invalid.")
#define ERR_PARAM7_INVALID _T("Parameter #7 invalid.")
#define ERR_PARAM8_INVALID _T("Parameter #8 invalid.")
#define ERR_PARAM1_REQUIRED _T("Parameter #1 required")
#define ERR_PARAM2_REQUIRED _T("Parameter #2 required")
#define ERR_PARAM3_REQUIRED _T("Parameter #3 required")
#define ERR_PARAM2_MUST_BE_BLANK _T("Parameter #2 must be blank in this case.")
#define ERR_PARAM3_MUST_BE_BLANK _T("Parameter #3 must be blank in this case.")
#define ERR_PARAM4_MUST_BE_BLANK _T("Parameter #4 must be blank in this case.")
#define ERR_PARAM1_MUST_NOT_BE_BLANK _T("Parameter #1 must not be blank in this case.")
#define ERR_PARAM2_MUST_NOT_BE_BLANK _T("Parameter #2 must not be blank in this case.")
#define ERR_PARAM3_MUST_NOT_BE_BLANK _T("Parameter #3 must not be blank in this case.")
#define ERR_PARAM4_MUST_NOT_BE_BLANK _T("Parameter #4 must not be blank in this case.")
#define ERR_MISSING_OUTPUT_VAR _T("Requires at least one of its output variables.")
#define ERR_MISSING_OPEN_PAREN _T("Missing \"(\"")
#define ERR_MISSING_OPEN_BRACE _T("Missing \"{\"")
#define ERR_MISSING_CLOSE_PAREN _T("Missing \")\"")
#define ERR_MISSING_CLOSE_BRACE _T("Missing \"}\"")
#define ERR_MISSING_CLOSE_BRACKET _T("Missing \"]\"") // L31
#define ERR_UNEXPECTED_CLOSE_PAREN _T("Unexpected \")\"")
#define ERR_UNEXPECTED_CLOSE_BRACKET _T("Unexpected \"]\"")
#define ERR_UNEXPECTED_CLOSE_BRACE _T("Unexpected \"}\"")
#define ERR_MISSING_CLOSE_QUOTE _T("Missing close-quote") // No period after short phrases.
#define ERR_MISSING_COMMA _T("Missing comma") //
#define ERR_BLANK_PARAM _T("Blank parameter") //
#define ERR_TOO_MANY_PARAMS _T("Too many parameters passed to function.") // L31
#define ERR_TOO_FEW_PARAMS _T("Too few parameters passed to function.") // L31
#define ERR_BAD_OPTIONAL_PARAM _T("Expected \":=\"")
#define ERR_HOTKEY_FUNC_PARAMS _T("Parameters of hotkey functions must be optional.")
#define ERR_ELSE_WITH_NO_IF _T("ELSE with no matching IF")
#define ERR_UNTIL_WITH_NO_LOOP _T("UNTIL with no matching LOOP")
#define ERR_CATCH_WITH_NO_TRY _T("CATCH with no matching TRY")
#define ERR_FINALLY_WITH_NO_PRECEDENT _T("FINALLY with no matching TRY or CATCH")
#define ERR_BAD_JUMP_INSIDE_FINALLY _T("Jumps cannot exit a FINALLY block.")
#define ERR_BAD_JUMP_OUT_OF_FUNCTION _T("Cannot jump from inside a function to outside.")
#define ERR_EXPECTED_BLOCK_OR_ACTION _T("Expected \"{\" or single-line action.")
#define ERR_OUTOFMEM _T("Out of memory.") // Used by RegEx too, so don't change it without also changing RegEx to keep the former string.
#define ERR_EXPR_TOO_LONG _T("Expression too long")
#define ERR_MEM_LIMIT_REACHED _T("Memory limit reached (see #MaxMem in the help file).")
#define ERR_NO_LABEL _T("Target label does not exist.")
#define ERR_MENU _T("Menu does not exist.")
#define ERR_SUBMENU _T("Submenu does not exist.")
#define ERR_WINDOW_PARAM _T("Requires at least one of its window parameters.")
#define ERR_MENUTRAY _T("Supported only for the tray menu")
#define ERR_MOUSE_COORD _T("X & Y must be either both absent or both present.")
#define ERR_DIVIDEBYZERO _T("Divide by zero")
#define ERR_VAR_IS_READONLY _T("Not allowed as an output variable.")
#define ERR_INVALID_CHAR _T("This character is not allowed here.")
#define ERR_INVALID_DOT _T("Ambiguous or invalid use of \".\"")
#define ERR_UNQUOTED_NON_ALNUM _T("Unquoted literals may only consist of alphanumeric characters/underscore.")
#define ERR_DUPLICATE_DECLARATION _T("Duplicate declaration.")
#define ERR_INVALID_FUNCDECL _T("Invalid function declaration.")
#define ERR_INVALID_CLASS_VAR _T("Invalid class variable declaration.")
#define ERR_INVALID_LINE_IN_CLASS_DEF _T("Not a valid method, class or property definition.")
#define ERR_INVALID_LINE_IN_PROPERTY_DEF _T("Not a valid property getter/setter.")
#define ERR_INVALID_GUI_NAME _T("Invalid Gui name.")
#define ERR_INVALID_OPTION _T("Invalid option.") // Generic message used by Gui and GuiControl/Get.
#define ERR_HOTKEY_IF_EXPR _T("Parameter #2 must match an existing #If expression.")
#define ERR_EXCEPTION _T("An exception was thrown.")
#define WARNING_USE_UNSET_VARIABLE _T("This variable has not been assigned a value.")
#define WARNING_LOCAL_SAME_AS_GLOBAL _T("This local variable has the same name as a global variable.")
#define WARNING_USE_ENV_VARIABLE _T("An environment variable is being accessed; see #NoEnv.")
#define WARNING_CLASS_OVERWRITE _T("Class may be overwritten.")
//----------------------------------------------------------------------------------
void DoIncrementalMouseMove(int aX1, int aY1, int aX2, int aY2, int aSpeed);
DWORD ProcessExist9x2000(LPTSTR aProcess);
#ifdef CONFIG_WINNT4
DWORD ProcessExistNT4(LPTSTR aProcess);
#endif
inline DWORD ProcessExist(LPTSTR aProcess)
{
return
#ifdef CONFIG_WINNT4
g_os.IsWinNT4() ? ProcessExistNT4(aProcess) :
#endif
ProcessExist9x2000(aProcess);
}
DWORD GetProcessName(DWORD aProcessID, LPTSTR aBuf, DWORD aBufSize, bool aGetNameOnly);
bool Util_Shutdown(int nFlag);
BOOL Util_ShutdownHandler(HWND hwnd, DWORD lParam);
void Util_WinKill(HWND hWnd);
enum MainWindowModes {MAIN_MODE_NO_CHANGE, MAIN_MODE_LINES, MAIN_MODE_VARS
, MAIN_MODE_HOTKEYS, MAIN_MODE_KEYHISTORY, MAIN_MODE_REFRESH};
ResultType ShowMainWindow(MainWindowModes aMode = MAIN_MODE_NO_CHANGE, bool aRestricted = true);
DWORD GetAHKInstallDir(LPTSTR aBuf);
struct InputBoxType
{
LPTSTR title;
LPTSTR text;
int width;
int height;
int xpos;
int ypos;
Var *output_var;
TCHAR password_char;
LPTSTR default_string;
DWORD timeout;
HWND hwnd;
HFONT font;
};
struct SplashType
{
int width;
int height;
int bar_pos; // The amount of progress of the bar (it's position).
int margin_x; // left/right margin
int margin_y; // top margin
int text1_height; // Height of main text control.
int object_width; // Width of image.
int object_height; // Height of the progress bar or image.
HWND hwnd;
int pic_type;
union
{
HBITMAP pic_bmp; // For SplashImage.
HICON pic_icon;
};
HWND hwnd_bar;
HWND hwnd_text1; // MainText
HWND hwnd_text2; // SubText
HFONT hfont1; // Main
HFONT hfont2; // Sub
HBRUSH hbrush; // Window background color brush.
COLORREF color_bk; // The background color itself.
COLORREF color_text; // Color of the font.
};
// Use GetClientRect() to determine the available width so that control's can be centered.
#define SPLASH_CALC_YPOS \
int bar_y = splash.margin_y + (splash.text1_height ? (splash.text1_height + splash.margin_y) : 0);\
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.
#define PROGRESS_MAIN_POS splash.margin_x, splash.margin_y, control_width, splash.text1_height
#define PROGRESS_BAR_POS splash.margin_x, bar_y, control_width, splash.object_height
#define PROGRESS_SUB_POS splash.margin_x, sub_y, control_width, (client_rect.bottom - client_rect.top) - sub_y
// From AutoIt3's InputBox. This doesn't add a measurable amount of code size, so the compiler seems to implement
// it efficiently (somewhat like a macro).
template <class T>
inline void swap(T &v1, T &v2) {
T tmp=v1;
v1=v2;
v2=tmp;
}
// The following functions are used in GUI DPI scaling, so that
// GUIs designed for a 96 DPI setting (i.e. using absolute coords
// or explicit widths/sizes) can continue to run with mostly no issues.
static inline int DPIScale(int x)
{
extern int g_ScreenDPI;
return MulDiv(x, g_ScreenDPI, 96);
}
static inline int DPIUnscale(int x)
{
extern int g_ScreenDPI;
return MulDiv(x, 96, g_ScreenDPI);
}
#define INPUTBOX_DEFAULT INT_MIN
ResultType InputBox(Var *aOutputVar, LPTSTR aTitle, LPTSTR aText, bool aHideInput
, int aWidth, int aHeight, int aX, int aY, double aTimeout, LPTSTR aDefault);
INT_PTR CALLBACK InputBoxProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
VOID CALLBACK InputBoxTimeout(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
VOID CALLBACK DerefTimeout(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
BOOL CALLBACK EnumChildFindSeqNum(HWND aWnd, LPARAM lParam);
BOOL CALLBACK EnumChildFindPoint(HWND aWnd, LPARAM lParam);
BOOL CALLBACK EnumChildGetControlList(HWND aWnd, LPARAM lParam);
BOOL CALLBACK EnumMonitorProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM lParam);
BOOL CALLBACK EnumChildGetText(HWND aWnd, LPARAM lParam);
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
bool HandleMenuItem(HWND aHwnd, WORD aMenuItemID, HWND aGuiHwnd);
INT_PTR CALLBACK TabDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
#define TABDIALOG_ATTRIB_BACKGROUND_DEFAULT 1
#define TABDIALOG_ATTRIB_THEMED 2
typedef UINT LineNumberType;
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).
#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).
#define LOADING_FAILED UINT_MAX
// -2 for the beginning and ending g_DerefChars:
#define MAX_VAR_NAME_LENGTH (UCHAR_MAX - 2)
#define MAX_FUNCTION_PARAMS UCHAR_MAX // Also conserves stack space to support future attributes such as param default values.
#define MAX_DEREFS_PER_ARG 512
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.
typedef UCHAR DerefParamCountType;
class Func; // Forward declaration for use below.
struct DerefType
{
LPTSTR marker;
union
{
Var *var;
Func *func;
};
// Keep any fields that aren't an even multiple of 4 adjacent to each other. This conserves memory
// due to byte-alignment:
BYTE is_function;
#define DEREF_VARIADIC 2
DerefParamCountType param_count; // The actual number of parameters present in this function *call*. Left uninitialized except for functions.
DerefLengthType length; // Listed only after byte-sized fields, due to it being a WORD.
};
typedef UCHAR ArgTypeType; // UCHAR vs. an enum, to save memory.
#define ARG_TYPE_NORMAL (UCHAR)0
#define ARG_TYPE_INPUT_VAR (UCHAR)1
#define ARG_TYPE_OUTPUT_VAR (UCHAR)2
struct ArgStruct
{
ArgTypeType type;
bool is_expression; // Whether this ARG is known to contain an expression.
// Above are kept adjacent to each other to conserve memory (any fields that aren't an even
// multiple of 4, if adjacent to each other, consume less memory due to default byte alignment
// setting [which helps performance]).
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.
LPTSTR text;
DerefType *deref; // Will hold a NULL-terminated array of var-deref locations within <text>.
ExprTokenType *postfix; // An array of tokens in postfix order. Also used for ACT_ADD and others to store pre-converted binary integers.
};
#define BIF_DECL_PARAMS ResultType &aResult, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount
// The following macro is used for definitions and declarations of built-in functions:
#define BIF_DECL(name) void name(BIF_DECL_PARAMS)
// NOTE FOR v1: The following macros currently aren't used much; they're for use in new code
// to facilitate merging into the v2 branch, which uses its own versions of these macros heavily.
// This is just the subset of the macros that don't rely on other changes.
#define _f__oneline(act) do { act } while (0) // Make the macro safe to use like a function, under if(), etc.
#define _f__ret(act) _f__oneline( aResult = (act); return; ) // BIFs have no return value.
#define _o__ret(act) return (act) // IObject::Invoke() returns ResultType.
#define _f_throw(...) _f__ret(g_script.ScriptError(__VA_ARGS__))
#define _o_throw(...) _o__ret(g_script.ScriptError(__VA_ARGS__))
#define _f_return_FAIL _f__ret(FAIL)
#define _o_return_FAIL _o__ret(FAIL)
#define _f_retval_buf (aResultToken.buf)
#define _f_retval_buf_size MAX_NUMBER_SIZE
#define _f_number_buf _f_retval_buf // An alias to show intended usage, and in case the buffer size is changed.
// Some of these lengths and such are based on the MSDN example at
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/enumerating_registry_subkeys.asp:
// FIX FOR v1.0.48:
// OLDER (v1.0.44.07): Someone reported that a stack overflow was possible, implying that it only happens
// during extremely deep nesting of subkey names (perhaps a hundred or more nested subkeys). Upon review, it seems
// that the prior limit of 16383 for value-name-length is higher than needed; testing shows that a value name can't
// be longer than 259 (limit might even be 255 if API vs. RegEdit is used to create the name). Testing also shows
// that the total path name of a registry item (including item/value name but excluding the name of the root key)
// obeys the same limit BUT ONLY within the RegEdit GUI. RegEdit seems capable of importing subkeys whose names
// (even without any value name appended) are longer than 259 characters (see comments higher above).
#define MAX_REG_ITEM_SIZE 1024 // Needs to be greater than 260 (see comments above), but I couldn't find any documentation at MSDN or the web about the max length of a subkey name. One example at MSDN RegEnumKeyEx() uses MAX_KEY_LENGTH=255 and MAX_VALUE_NAME=16383, but clearly MAX_KEY_LENGTH should be larger.
#define REG_SUBKEY -2 // Custom type, not standard in Windows.
struct RegItemStruct
{
HKEY root_key_type, root_key; // root_key_type is always a local HKEY, whereas root_key can be a remote handle.
TCHAR subkey[MAX_REG_ITEM_SIZE]; // The branch of the registry where this subkey or value is located.
TCHAR name[MAX_REG_ITEM_SIZE]; // The subkey or value name.
DWORD type; // Value Type (e.g REG_DWORD).
FILETIME ftLastWriteTime; // Non-initialized.
void InitForValues() {ftLastWriteTime.dwHighDateTime = ftLastWriteTime.dwLowDateTime = 0;}
void InitForSubkeys() {type = REG_SUBKEY;} // To distinguish REG_DWORD and such from the subkeys themselves.
RegItemStruct(HKEY aRootKeyType, HKEY aRootKey, LPTSTR aSubKey)
: root_key_type(aRootKeyType), root_key(aRootKey), type(REG_NONE)
{
*name = '\0';
// Make a local copy on the caller's stack so that if the current script subroutine is
// interrupted to allow another to run, the contents of the deref buffer is saved here:
tcslcpy(subkey, aSubKey, _countof(subkey));
// Even though the call may work with a trailing backslash, it's best to remove it
// so that consistent results are delivered to the user. For example, if the script
// is enumerating recursively into a subkey, subkeys deeper down will not include the
// trailing backslash when they are reported. So the user's own subkey should not
// have one either so that when A_ScriptSubKey is referenced in the script, it will
// always show up as the value without a trailing backslash:
size_t length = _tcslen(subkey);
if (length && subkey[length - 1] == '\\')
subkey[length - 1] = '\0';
}
};
class TextStream; // TextIO
struct LoopReadFileStruct
{
TextStream *mReadFile, *mWriteFile;
TCHAR mWriteFileName[MAX_PATH];
#define READ_FILE_LINE_SIZE (64 * 1024) // This is also used by FileReadLine().
TCHAR mCurrentLine[READ_FILE_LINE_SIZE];
LoopReadFileStruct(TextStream *aReadFile, LPTSTR aWriteFileName)
: mReadFile(aReadFile), mWriteFile(NULL) // mWriteFile is opened by FileAppend() only upon first use.
{
// Use our own buffer because caller's is volatile due to possibly being in the deref buffer:
tcslcpy(mWriteFileName, aWriteFileName, _countof(mWriteFileName));
*mCurrentLine = '\0';
}
};
// TextStream flags for LoadIncludedFile (script files), file-reading loops and FileReadLine.
// Do not lock read/write: older versions used fopen(), which is implicitly permissive.
#define DEFAULT_READ_FLAGS (TextStream::READ | TextStream::EOL_CRLF | TextStream::EOL_ORPHAN_CR | TextStream::SHARE_READ | TextStream::SHARE_WRITE)
typedef UCHAR ArgCountType;
#define MAX_ARGS 20 // Maximum number of args used by any command.
enum DllArgTypes {
DLL_ARG_INVALID
, DLL_ARG_ASTR
, DLL_ARG_INT
, DLL_ARG_SHORT
, DLL_ARG_CHAR
, DLL_ARG_INT64
, DLL_ARG_FLOAT
, DLL_ARG_DOUBLE
, DLL_ARG_WSTR
, DLL_ARG_STR = UorA(DLL_ARG_WSTR, DLL_ARG_ASTR)
, DLL_ARG_xSTR = UorA(DLL_ARG_ASTR, DLL_ARG_WSTR) // To simplify some sections.
}; // Some sections might rely on DLL_ARG_INVALID being 0.
// Note that currently this value must fit into a sc_type variable because that is how TextToKey()
// stores it in the hotkey class. sc_type is currently a UINT, and will always be at least a
// WORD in size, so it shouldn't be much of an issue:
#define MAX_JOYSTICKS 16 // The maximum allowed by any Windows operating system.
#define MAX_JOY_BUTTONS 32 // Also the max that Windows supports.
enum JoyControls {JOYCTRL_INVALID, JOYCTRL_XPOS, JOYCTRL_YPOS, JOYCTRL_ZPOS
, JOYCTRL_RPOS, JOYCTRL_UPOS, JOYCTRL_VPOS, JOYCTRL_POV
, JOYCTRL_NAME, JOYCTRL_BUTTONS, JOYCTRL_AXES, JOYCTRL_INFO
, JOYCTRL_1, JOYCTRL_2, JOYCTRL_3, JOYCTRL_4, JOYCTRL_5, JOYCTRL_6, JOYCTRL_7, JOYCTRL_8 // Buttons.
, JOYCTRL_9, JOYCTRL_10, JOYCTRL_11, JOYCTRL_12, JOYCTRL_13, JOYCTRL_14, JOYCTRL_15, JOYCTRL_16
, JOYCTRL_17, JOYCTRL_18, JOYCTRL_19, JOYCTRL_20, JOYCTRL_21, JOYCTRL_22, JOYCTRL_23, JOYCTRL_24
, JOYCTRL_25, JOYCTRL_26, JOYCTRL_27, JOYCTRL_28, JOYCTRL_29, JOYCTRL_30, JOYCTRL_31, JOYCTRL_32
, JOYCTRL_BUTTON_MAX = JOYCTRL_32
};
#define IS_JOYSTICK_BUTTON(joy) (joy >= JOYCTRL_1 && joy <= JOYCTRL_BUTTON_MAX)
enum WinGetCmds {WINGET_CMD_INVALID, WINGET_CMD_ID, WINGET_CMD_IDLAST, WINGET_CMD_PID, WINGET_CMD_PROCESSNAME
, WINGET_CMD_COUNT, WINGET_CMD_LIST, WINGET_CMD_MINMAX, WINGET_CMD_CONTROLLIST, WINGET_CMD_CONTROLLISTHWND
, WINGET_CMD_STYLE, WINGET_CMD_EXSTYLE, WINGET_CMD_TRANSPARENT, WINGET_CMD_TRANSCOLOR, WINGET_CMD_PROCESSPATH
};
enum SysGetCmds {SYSGET_CMD_INVALID, SYSGET_CMD_METRICS, SYSGET_CMD_MONITORCOUNT, SYSGET_CMD_MONITORPRIMARY
, SYSGET_CMD_MONITORAREA, SYSGET_CMD_MONITORWORKAREA, SYSGET_CMD_MONITORNAME
};
enum TransformCmds {TRANS_CMD_INVALID, TRANS_CMD_ASC, TRANS_CMD_CHR, TRANS_CMD_DEREF
, TRANS_CMD_UNICODE, TRANS_CMD_HTML
, TRANS_CMD_MOD, TRANS_CMD_POW, TRANS_CMD_EXP, TRANS_CMD_SQRT, TRANS_CMD_LOG, TRANS_CMD_LN
, TRANS_CMD_ROUND, TRANS_CMD_CEIL, TRANS_CMD_FLOOR, TRANS_CMD_ABS
, TRANS_CMD_SIN, TRANS_CMD_COS, TRANS_CMD_TAN, TRANS_CMD_ASIN, TRANS_CMD_ACOS, TRANS_CMD_ATAN
, TRANS_CMD_BITAND, TRANS_CMD_BITOR, TRANS_CMD_BITXOR, TRANS_CMD_BITNOT
, TRANS_CMD_BITSHIFTLEFT, TRANS_CMD_BITSHIFTRIGHT
};
enum MenuCommands {MENU_CMD_INVALID, MENU_CMD_SHOW, MENU_CMD_USEERRORLEVEL
, MENU_CMD_ADD, MENU_CMD_RENAME, MENU_CMD_INSERT
, MENU_CMD_CHECK, MENU_CMD_UNCHECK, MENU_CMD_TOGGLECHECK
, MENU_CMD_ENABLE, MENU_CMD_DISABLE, MENU_CMD_TOGGLEENABLE
, MENU_CMD_STANDARD, MENU_CMD_NOSTANDARD, MENU_CMD_COLOR, MENU_CMD_DEFAULT, MENU_CMD_NODEFAULT
, MENU_CMD_DELETE, MENU_CMD_DELETEALL, MENU_CMD_TIP, MENU_CMD_ICON, MENU_CMD_NOICON
, MENU_CMD_CLICK, MENU_CMD_MAINWINDOW, MENU_CMD_NOMAINWINDOW
};
#define AHK_LV_SELECT 0x0100
#define AHK_LV_DESELECT 0x0200
#define AHK_LV_FOCUS 0x0400
#define AHK_LV_DEFOCUS 0x0800
#define AHK_LV_CHECK 0x1000
#define AHK_LV_UNCHECK 0x2000
#define AHK_LV_DROPHILITE 0x4000
#define AHK_LV_UNDROPHILITE 0x8000
// Although there's no room remaining in the BYTE for LVIS_CUT (AHK_LV_CUT) [assuming it's ever needed],
// it might be possible to squeeze more info into it as follows:
// Each pair of bits can represent three values (other than zero). But since only two values are needed
// (since an item can't be both selected an deselected simultaneously), one value in each pair is available
// for future use such as LVIS_CUT.
enum GuiCommands {GUI_CMD_INVALID, GUI_CMD_OPTIONS, GUI_CMD_ADD, GUI_CMD_MARGIN, GUI_CMD_MENU
, GUI_CMD_SHOW, GUI_CMD_SUBMIT, GUI_CMD_CANCEL, GUI_CMD_MINIMIZE, GUI_CMD_MAXIMIZE, GUI_CMD_RESTORE
, GUI_CMD_DESTROY, GUI_CMD_FONT, GUI_CMD_TAB, GUI_CMD_LISTVIEW, GUI_CMD_TREEVIEW, GUI_CMD_DEFAULT
, GUI_CMD_COLOR, GUI_CMD_FLASH, GUI_CMD_NEW
};
enum GuiControlCmds {GUICONTROL_CMD_INVALID, GUICONTROL_CMD_OPTIONS, GUICONTROL_CMD_CONTENTS, GUICONTROL_CMD_TEXT
, GUICONTROL_CMD_MOVE, GUICONTROL_CMD_MOVEDRAW, GUICONTROL_CMD_FOCUS, GUICONTROL_CMD_ENABLE, GUICONTROL_CMD_DISABLE
, GUICONTROL_CMD_SHOW, GUICONTROL_CMD_HIDE, GUICONTROL_CMD_CHOOSE, GUICONTROL_CMD_CHOOSESTRING
, GUICONTROL_CMD_FONT
};
enum GuiControlGetCmds {GUICONTROLGET_CMD_INVALID, GUICONTROLGET_CMD_CONTENTS, GUICONTROLGET_CMD_POS
, GUICONTROLGET_CMD_FOCUS, GUICONTROLGET_CMD_FOCUSV, GUICONTROLGET_CMD_ENABLED, GUICONTROLGET_CMD_VISIBLE
, GUICONTROLGET_CMD_HWND, GUICONTROLGET_CMD_NAME
};
typedef UCHAR GuiControls;
enum GuiControlTypes {GUI_CONTROL_INVALID // GUI_CONTROL_INVALID must be zero due to things like ZeroMemory() on the struct.
, GUI_CONTROL_TEXT, GUI_CONTROL_PIC, GUI_CONTROL_GROUPBOX
, GUI_CONTROL_BUTTON, GUI_CONTROL_CHECKBOX, GUI_CONTROL_RADIO
, GUI_CONTROL_DROPDOWNLIST, GUI_CONTROL_COMBOBOX
, GUI_CONTROL_LISTBOX, GUI_CONTROL_LISTVIEW, GUI_CONTROL_TREEVIEW
, GUI_CONTROL_EDIT, GUI_CONTROL_DATETIME, GUI_CONTROL_MONTHCAL, GUI_CONTROL_HOTKEY
, GUI_CONTROL_UPDOWN, GUI_CONTROL_SLIDER, GUI_CONTROL_PROGRESS, GUI_CONTROL_TAB, GUI_CONTROL_TAB2, GUI_CONTROL_TAB3
, GUI_CONTROL_ACTIVEX, GUI_CONTROL_LINK, GUI_CONTROL_CUSTOM, GUI_CONTROL_STATUSBAR}; // Kept last to reflect it being bottommost in switch()s (for perf), since not too often used.
enum ThreadCommands {THREAD_CMD_INVALID, THREAD_CMD_PRIORITY, THREAD_CMD_INTERRUPT, THREAD_CMD_NOTIMERS};
#define PROCESS_PRIORITY_LETTERS _T("LBNAHR")
enum ProcessCmds {PROCESS_CMD_INVALID, PROCESS_CMD_EXIST, PROCESS_CMD_CLOSE, PROCESS_CMD_PRIORITY
, PROCESS_CMD_WAIT, PROCESS_CMD_WAITCLOSE};
enum ControlCmds {CONTROL_CMD_INVALID, CONTROL_CMD_CHECK, CONTROL_CMD_UNCHECK
, CONTROL_CMD_ENABLE, CONTROL_CMD_DISABLE, CONTROL_CMD_SHOW, CONTROL_CMD_HIDE
, CONTROL_CMD_STYLE, CONTROL_CMD_EXSTYLE
, CONTROL_CMD_SHOWDROPDOWN, CONTROL_CMD_HIDEDROPDOWN
, CONTROL_CMD_TABLEFT, CONTROL_CMD_TABRIGHT
, CONTROL_CMD_ADD, CONTROL_CMD_DELETE, CONTROL_CMD_CHOOSE
, CONTROL_CMD_CHOOSESTRING, CONTROL_CMD_EDITPASTE};
enum ControlGetCmds {CONTROLGET_CMD_INVALID, CONTROLGET_CMD_CHECKED, CONTROLGET_CMD_ENABLED
, CONTROLGET_CMD_VISIBLE, CONTROLGET_CMD_TAB, CONTROLGET_CMD_FINDSTRING
, CONTROLGET_CMD_CHOICE, CONTROLGET_CMD_LIST, CONTROLGET_CMD_LINECOUNT, CONTROLGET_CMD_CURRENTLINE
, CONTROLGET_CMD_CURRENTCOL, CONTROLGET_CMD_LINE, CONTROLGET_CMD_SELECTED
, CONTROLGET_CMD_STYLE, CONTROLGET_CMD_EXSTYLE, CONTROLGET_CMD_HWND};
enum DriveCmds {DRIVE_CMD_INVALID, DRIVE_CMD_EJECT, DRIVE_CMD_LOCK, DRIVE_CMD_UNLOCK, DRIVE_CMD_LABEL};
enum DriveGetCmds {DRIVEGET_CMD_INVALID, DRIVEGET_CMD_LIST, DRIVEGET_CMD_FILESYSTEM, DRIVEGET_CMD_LABEL
, DRIVEGET_CMD_SETLABEL, DRIVEGET_CMD_SERIAL, DRIVEGET_CMD_TYPE, DRIVEGET_CMD_STATUS
, DRIVEGET_CMD_STATUSCD, DRIVEGET_CMD_CAPACITY};
enum WinSetAttributes {WINSET_INVALID, WINSET_TRANSPARENT, WINSET_TRANSCOLOR, WINSET_ALWAYSONTOP
, WINSET_BOTTOM, WINSET_TOP, WINSET_STYLE, WINSET_EXSTYLE, WINSET_REDRAW, WINSET_ENABLE, WINSET_DISABLE
, WINSET_REGION};
class Label; // Forward declaration so that each can use the other.
class Line
{
private:
ResultType EvaluateCondition();
bool EvaluateLoopUntil(ResultType &aResult);
ResultType Line::PerformLoop(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
, __int64 aIterationLimit, bool aIsInfinite);
ResultType Line::PerformLoopFilePattern(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
, FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, LPTSTR aFilePattern);
ResultType PerformLoopReg(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil
, FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, HKEY aRootKeyType, HKEY aRootKey, LPTSTR aRegSubkey);
ResultType PerformLoopParse(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil);
ResultType Line::PerformLoopParseCSV(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil);
ResultType PerformLoopReadFile(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil, TextStream *aReadFile, LPTSTR aWriteFileName);
ResultType PerformLoopWhile(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine); // Lexikos: ACT_WHILE.
ResultType PerformLoopFor(ExprTokenType *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil); // Lexikos: ACT_FOR.
ResultType Perform();
ResultType MouseGetPos(DWORD aOptions);
ResultType FormatTime(LPTSTR aYYYYMMDD, LPTSTR aFormat);
ResultType PerformAssign();
ResultType StringReplace();
ResultType StringSplit(LPTSTR aArrayName, LPTSTR aInputString, LPTSTR aDelimiterList, LPTSTR aOmitList);
ResultType SplitPath(LPTSTR aFileSpec);
ResultType PerformSort(LPTSTR aContents, LPTSTR aOptions);
ResultType GetKeyJoyState(LPTSTR aKeyName, LPTSTR aOption);
ResultType DriveSpace(LPTSTR aPath, bool aGetFreeSpace);
ResultType Drive(LPTSTR aCmd, LPTSTR aValue, LPTSTR aValue2);
ResultType DriveLock(TCHAR aDriveLetter, bool aLockIt);
ResultType DriveGet(LPTSTR aCmd, LPTSTR aValue);
ResultType SoundSetGet(LPTSTR aSetting, LPTSTR aComponentType, LPTSTR aControlType, LPTSTR aDevice);
ResultType SoundSetGet2kXP(LPTSTR aSetting, DWORD aComponentType, int aComponentInstance
, DWORD aControlType, LPTSTR aDevice);
ResultType SoundSetGetVista(LPTSTR aSetting, DWORD aComponentType, int aComponentInstance
, DWORD aControlType, LPTSTR aDevice);
ResultType SoundGetWaveVolume(HWAVEOUT aDeviceID);
ResultType SoundSetWaveVolume(LPTSTR aVolume, HWAVEOUT aDeviceID);
ResultType SoundPlay(LPTSTR aFilespec, bool aSleepUntilDone);
ResultType URLDownloadToFile(LPTSTR aURL, LPTSTR aFilespec);
ResultType FileSelectFile(LPTSTR aOptions, LPTSTR aWorkingDir, LPTSTR aGreeting, LPTSTR aFilter);
// Bitwise flags:
#define FSF_ALLOW_CREATE 0x01
#define FSF_EDITBOX 0x02
#define FSF_NONEWDIALOG 0x04
ResultType FileSelectFolder(LPTSTR aRootDir, LPTSTR aOptions, LPTSTR aGreeting);
ResultType FileGetShortcut(LPTSTR aShortcutFile);
ResultType FileCreateShortcut(LPTSTR aTargetFile, LPTSTR aShortcutFile, LPTSTR aWorkingDir, LPTSTR aArgs
, LPTSTR aDescription, LPTSTR aIconFile, LPTSTR aHotkey, LPTSTR aIconNumber, LPTSTR aRunState);
ResultType FileCreateDir(LPTSTR aDirSpec);
ResultType FileRead(LPTSTR aFilespec);
ResultType FileReadLine(LPTSTR aFilespec, LPTSTR aLineNumber);
ResultType FileAppend(LPTSTR aFilespec, LPTSTR aBuf, LoopReadFileStruct *aCurrentReadFile);
ResultType WriteClipboardToFile(LPTSTR aFilespec, Var *aBinaryClipVar = NULL);
ResultType FileDelete(LPTSTR aFilePattern);
ResultType FileRecycle(LPTSTR aFilePattern);
ResultType FileRecycleEmpty(LPTSTR aDriveLetter);
ResultType FileInstall(LPTSTR aSource, LPTSTR aDest, LPTSTR aFlag);
typedef BOOL (* FilePatternCallback)(LPTSTR aFilename, WIN32_FIND_DATA &aFile, void *aCallbackData);
int FilePatternApply(LPTSTR aFilePattern, FileLoopModeType aOperateOnFolders
, bool aDoRecurse, FilePatternCallback aCallback, void *aCallbackData
, bool aCalledRecursively = false);
ResultType FileGetAttrib(LPTSTR aFilespec);
int FileSetAttrib(LPTSTR aAttributes, LPTSTR aFilePattern, FileLoopModeType aOperateOnFolders
, bool aDoRecurse, bool aCalledRecursively = false);
ResultType FileGetTime(LPTSTR aFilespec, TCHAR aWhichTime);
int FileSetTime(LPTSTR aYYYYMMDD, LPTSTR aFilePattern, TCHAR aWhichTime
, FileLoopModeType aOperateOnFolders, bool aDoRecurse, bool aCalledRecursively = false);
ResultType FileGetSize(LPTSTR aFilespec, LPTSTR aGranularity);
ResultType FileGetVersion(LPTSTR aFilespec);
ResultType IniRead(LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey, LPTSTR aDefault);
ResultType IniWrite(LPTSTR aValue, LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey);
ResultType IniDelete(LPTSTR aFilespec, LPTSTR aSection, LPTSTR aKey);
ResultType RegRead(HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName);
ResultType RegWrite(DWORD aValueType, HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName, LPTSTR aValue);
ResultType RegDelete(HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName);
static LONG RegRemoveSubkeys(HKEY hRegKey);
#define DESTROY_SPLASH \
{\
if (g_hWndSplash && IsWindow(g_hWndSplash))\
DestroyWindow(g_hWndSplash);\
g_hWndSplash = NULL;\
}
ResultType SplashTextOn(int aWidth, int aHeight, LPTSTR aTitle, LPTSTR aText);
ResultType Splash(LPTSTR aOptions, LPTSTR aSubText, LPTSTR aMainText, LPTSTR aTitle, LPTSTR aFontName
, LPTSTR aImageFile, bool aSplashImage);
ResultType ToolTip(LPTSTR aText, LPTSTR aX, LPTSTR aY, LPTSTR aID);
ResultType TrayTip(LPTSTR aTitle, LPTSTR aText, LPTSTR aTimeout, LPTSTR aOptions);
ResultType Transform(LPTSTR aCmd, LPTSTR aValue1, LPTSTR aValue2);
ResultType Input(); // The Input command.
#define SW_NONE -1
ResultType PerformShowWindow(ActionTypeType aActionType, LPTSTR aTitle = _T(""), LPTSTR aText = _T("")
, LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
ResultType PerformWait();
ResultType WinMove(LPTSTR aTitle, LPTSTR aText, LPTSTR aX, LPTSTR aY
, LPTSTR aWidth = _T(""), LPTSTR aHeight = _T(""), LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
ResultType WinMenuSelectItem(LPTSTR aTitle, LPTSTR aText, LPTSTR aMenu1, LPTSTR aMenu2
, LPTSTR aMenu3, LPTSTR aMenu4, LPTSTR aMenu5, LPTSTR aMenu6, LPTSTR aMenu7
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlSend(LPTSTR aControl, LPTSTR aKeysToSend, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText, SendRawModes aSendRaw);
ResultType ControlClick(vk_type aVK, int aClickCount, LPTSTR aOptions, LPTSTR aControl
, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlMove(LPTSTR aControl, LPTSTR aX, LPTSTR aY, LPTSTR aWidth, LPTSTR aHeight
, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlGetPos(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlGetFocus(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlFocus(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlSetText(LPTSTR aControl, LPTSTR aNewText, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlGetText(LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlGetListView(Var &aOutputVar, HWND aHwnd, LPTSTR aOptions);
ResultType Control(LPTSTR aCmd, LPTSTR aValue, LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ControlGet(LPTSTR aCommand, LPTSTR aValue, LPTSTR aControl, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType GuiControl(LPTSTR aCommand, LPTSTR aControlID, LPTSTR aParam3, Var *aParam3Var);
ResultType GuiControlGet(LPTSTR aCommand, LPTSTR aControlID, LPTSTR aParam3);
ResultType StatusBarGetText(LPTSTR aPart, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType StatusBarWait(LPTSTR aTextToWaitFor, LPTSTR aSeconds, LPTSTR aPart, LPTSTR aTitle, LPTSTR aText
, LPTSTR aInterval, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType ScriptPostSendMessage(bool aUseSend);
ResultType ScriptProcess(LPTSTR aCmd, LPTSTR aProcess, LPTSTR aParam3);
ResultType WinSet(LPTSTR aAttrib, LPTSTR aValue, LPTSTR aTitle, LPTSTR aText
, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType WinSetRegion(HWND aWnd, LPTSTR aPoints);
ResultType WinSetTitle(LPTSTR aTitle, LPTSTR aText, LPTSTR aNewTitle
, LPTSTR aExcludeTitle = _T(""), LPTSTR aExcludeText = _T(""));
ResultType WinGetTitle(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType WinGetClass(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType WinGet(LPTSTR aCmd, LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType WinGetControlList(Var &aOutputVar, HWND aTargetWindow, bool aFetchHWNDs);
ResultType WinGetText(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType WinGetPos(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
ResultType EnvGet(LPTSTR aEnvVarName);
ResultType SysGet(LPTSTR aCmd, LPTSTR aValue);
ResultType PixelSearch(int aLeft, int aTop, int aRight, int aBottom, COLORREF aColorBGR, int aVariation
, LPTSTR aOptions, bool aIsPixelGetColor);
ResultType ImageSearch(int aLeft, int aTop, int aRight, int aBottom, LPTSTR aImageFile);
ResultType PixelGetColor(int aX, int aY, LPTSTR aOptions);
static ResultType SetToggleState(vk_type aVK, ToggleValueType &ForceLock, LPTSTR aToggleText);
public:
#define SET_S_DEREF_BUF(ptr, size) Line::sDerefBuf = ptr, Line::sDerefBufSize = size
#define NULLIFY_S_DEREF_BUF \
{\
SET_S_DEREF_BUF(NULL, 0);\
if (sDerefBufSize > LARGE_DEREF_BUF_SIZE)\
--sLargeDerefBufs;\
}
#define PRIVATIZE_S_DEREF_BUF \
LPTSTR our_deref_buf = Line::sDerefBuf;\
size_t our_deref_buf_size = Line::sDerefBufSize;\
SET_S_DEREF_BUF(NULL, 0) // For detecting whether ExpandExpression() caused a new buffer to be created.
#define DEPRIVATIZE_S_DEREF_BUF \
if (our_deref_buf)\
{\
if (Line::sDerefBuf)\
{\
free(Line::sDerefBuf);\
if (Line::sDerefBufSize > LARGE_DEREF_BUF_SIZE)\
--Line::sLargeDerefBufs;\
}\
SET_S_DEREF_BUF(our_deref_buf, our_deref_buf_size);\
}
//else the original buffer is NULL, so keep any new sDerefBuf that might have been created (should
// help avg-case performance).
static LPTSTR sDerefBuf; // Buffer to hold the values of any args that need to be dereferenced.
static size_t sDerefBufSize;
static int sLargeDerefBufs;
// Static because only one line can be Expanded at a time (not to mention the fact that we
// wouldn't want the size of each line to be expanded by this size):
static LPTSTR sArgDeref[MAX_ARGS];
static Var *sArgVar[MAX_ARGS];
// Keep any fields that aren't an even multiple of 4 adjacent to each other. This conserves memory
// due to byte-alignment:
ActionTypeType mActionType; // What type of line this is.
ArgCountType mArgc; // How many arguments exist in mArg[].
FileIndexType mFileIndex; // Which file the line came from. 0 is the first, and it's the main script file.
LineNumberType mLineNumber; // The line number in the file from which the script was loaded, for debugging.
ArgStruct *mArg; // Will be used to hold a dynamic array of dynamic Args.
AttributeType mAttribute;
Line *mPrevLine, *mNextLine; // The prev & next lines adjacent to this one in the linked list; NULL if none.
Line *mRelatedLine; // e.g. the "else" that belongs to this "if"
Line *mParentLine; // Indicates the parent (owner) of this line.
#ifdef CONFIG_DEBUGGER
Breakpoint *mBreakpoint;
#endif
// Probably best to always use ARG1 even if other things have supposedly verified
// that it exists, since it's count-check should make the dereference of a NULL
// pointer (or accessing non-existent array elements) virtually impossible.
// Empty-string is probably more universally useful than NULL, since some
// API calls and other functions might not appreciate receiving NULLs. In addition,
// always remembering to have to check for NULL makes things harder to maintain
// and more bug-prone. The below macros rely upon the fact that the individual
// elements of mArg cannot be NULL (because they're explicitly set to be blank
// when the user has omitted an arg in between two non-blank args). Later, might
// want to review if any of the API calls used expect a string whose contents are
// modifiable.
#define RAW_ARG1 (mArgc > 0 ? mArg[0].text : _T(""))
#define RAW_ARG2 (mArgc > 1 ? mArg[1].text : _T(""))
#define RAW_ARG3 (mArgc > 2 ? mArg[2].text : _T(""))
#define RAW_ARG4 (mArgc > 3 ? mArg[3].text : _T(""))
#define RAW_ARG5 (mArgc > 4 ? mArg[4].text : _T(""))
#define RAW_ARG6 (mArgc > 5 ? mArg[5].text : _T(""))
#define RAW_ARG7 (mArgc > 6 ? mArg[6].text : _T(""))
#define RAW_ARG8 (mArgc > 7 ? mArg[7].text : _T(""))
#define LINE_RAW_ARG1 (line->mArgc > 0 ? line->mArg[0].text : _T(""))
#define LINE_RAW_ARG2 (line->mArgc > 1 ? line->mArg[1].text : _T(""))
#define LINE_RAW_ARG3 (line->mArgc > 2 ? line->mArg[2].text : _T(""))
#define LINE_RAW_ARG4 (line->mArgc > 3 ? line->mArg[3].text : _T(""))
#define LINE_RAW_ARG5 (line->mArgc > 4 ? line->mArg[4].text : _T(""))
#define LINE_RAW_ARG6 (line->mArgc > 5 ? line->mArg[5].text : _T(""))
#define LINE_RAW_ARG7 (line->mArgc > 6 ? line->mArg[6].text : _T(""))
#define LINE_RAW_ARG8 (line->mArgc > 7 ? line->mArg[7].text : _T(""))
#define LINE_RAW_ARG9 (line->mArgc > 8 ? line->mArg[8].text : _T(""))
#define NEW_RAW_ARG1 (aArgc > 0 ? new_arg[0].text : _T("")) // Helps performance to use this vs. LINE_RAW_ARG where possible.
#define NEW_RAW_ARG2 (aArgc > 1 ? new_arg[1].text : _T(""))
#define NEW_RAW_ARG3 (aArgc > 2 ? new_arg[2].text : _T(""))
#define NEW_RAW_ARG4 (aArgc > 3 ? new_arg[3].text : _T(""))
#define NEW_RAW_ARG5 (aArgc > 4 ? new_arg[4].text : _T(""))
#define NEW_RAW_ARG6 (aArgc > 5 ? new_arg[5].text : _T(""))
#define NEW_RAW_ARG7 (aArgc > 6 ? new_arg[6].text : _T(""))
#define NEW_RAW_ARG8 (aArgc > 7 ? new_arg[7].text : _T(""))
#define NEW_RAW_ARG9 (aArgc > 8 ? new_arg[8].text : _T(""))
#define SAVED_ARG1 (mArgc > 0 ? arg[0] : _T(""))
#define SAVED_ARG2 (mArgc > 1 ? arg[1] : _T(""))
#define SAVED_ARG3 (mArgc > 2 ? arg[2] : _T(""))
#define SAVED_ARG4 (mArgc > 3 ? arg[3] : _T(""))
#define SAVED_ARG5 (mArgc > 4 ? arg[4] : _T(""))
// For the below, it is the caller's responsibility to ensure that mArgc is
// large enough (either via load-time validation or a runtime check of mArgc).
// This is because for performance reasons, the sArgVar entry for omitted args isn't
// initialized, so may have an old/obsolete value from some previous command.
#define OUTPUT_VAR (*sArgVar) // ExpandArgs() has ensured this first ArgVar is always initialized, so there's never any need to check mArgc > 0.
#define ARGVARRAW1 (*sArgVar) // i.e. sArgVar[0], and same as OUTPUT_VAR (it's a duplicate to help readability).
#define ARGVARRAW2 (sArgVar[1]) // It's called RAW because its user is responsible for ensuring the arg
#define ARGVARRAW3 (sArgVar[2]) // exists by checking mArgc at loadtime or runtime.
#define ARGVAR1 ARGVARRAW1 // This first one doesn't need the check below because ExpandArgs() has ensured it's initialized.
#define ARGVAR2 (mArgc > 1 ? sArgVar[1] : NULL) // Caller relies on the check of mArgc because for performance,
#define ARGVAR3 (mArgc > 2 ? sArgVar[2] : NULL) // sArgVar[] isn't initialized for parameters the script
#define ARGVAR4 (mArgc > 3 ? sArgVar[3] : NULL) // omitted entirely from the end of the parameter list.
#define ARGVAR5 (mArgc > 4 ? sArgVar[4] : NULL)
#define ARGVAR6 (mArgc > 5 ? sArgVar[5] : NULL)
#define ARGVAR7 (mArgc > 6 ? sArgVar[6] : NULL)
#define ARGVAR8 (mArgc > 7 ? sArgVar[7] : NULL)
#define ARG1 sArgDeref[0] // These are the expanded/resolved parameters for the currently-executing command.
#define ARG2 sArgDeref[1] // They're populated by ExpandArgs().
#define ARG3 sArgDeref[2]
#define ARG4 sArgDeref[3]
#define ARG5 sArgDeref[4]
#define ARG6 sArgDeref[5]
#define ARG7 sArgDeref[6]
#define ARG8 sArgDeref[7]
#define ARG9 sArgDeref[8]
#define ARG10 sArgDeref[9]
#define ARG11 sArgDeref[10]
#define TWO_ARGS ARG1, ARG2
#define THREE_ARGS ARG1, ARG2, ARG3
#define FOUR_ARGS ARG1, ARG2, ARG3, ARG4
#define FIVE_ARGS ARG1, ARG2, ARG3, ARG4, ARG5
#define SIX_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6
#define SEVEN_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7
#define EIGHT_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8
#define NINE_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9
#define TEN_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10
#define ELEVEN_ARGS ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10, ARG11
// If the arg's text is non-blank, it means the variable is a dynamic name such as array%i%
// that must be resolved at runtime rather than load-time. Therefore, this macro must not
// be used without first having checked that arg.text is blank:
#define VAR(arg) ((Var *)arg.deref)
// Uses arg number (i.e. the first arg is 1, not 0). Caller must ensure that ArgNum >= 1 and that
// the arg in question is an input or output variable (since that isn't checked there).
//#define ARG_HAS_VAR(ArgNum) (mArgc >= ArgNum && (*mArg[ArgNum-1].text || mArg[ArgNum-1].deref))
// Shouldn't go much higher than 400 since the main window's Edit control is currently limited
// to 64KB to be compatible with the Win9x limit. Avg. line length is probably under 100 for
// the vast majority of scripts, so 400 seems unlikely to exceed the buffer size. Even in the
// worst case where the buffer size is exceeded, the text is simply truncated, so it's not too bad:
#define LINE_LOG_SIZE 400 // See above.
static Line *sLog[LINE_LOG_SIZE];
static DWORD sLogTick[LINE_LOG_SIZE];
static int sLogNext;
#ifdef AUTOHOTKEYSC // Reduces code size to omit things that are unused, and helps catch bugs at compile-time.
static LPTSTR sSourceFile[1]; // Only need to be able to hold the main script since compiled scripts don't support dynamic including.
#else
static LPTSTR *sSourceFile; // Will hold an array of strings.
static int sMaxSourceFiles; // Maximum number of items it can currently hold.
#endif
static int sSourceFileCount; // Number of items in the above array.
static void FreeDerefBufIfLarge();
ResultType ExecUntil(ExecUntilMode aMode, ExprTokenType *apReturnValue = NULL, Line **apJumpToLine = NULL);
// The following are characters that can't legally occur after an AND or OR. It excludes all unary operators
// "!~*&-+" as well as the parentheses chars "()":
#define EXPR_CORE _T("<>=/|^,:")
// The characters common to both EXPR_TELLTALES and EXPR_OPERAND_TERMINATORS:
#define EXPR_COMMON _T(" \t") EXPR_CORE _T("*&~!()[]{}") // Space and Tab are included at the beginning for performance. L31: Added [] for array-like syntax.
#define CONTINUATION_LINE_SYMBOLS EXPR_CORE _T(".+-*&!?~") // v1.0.46.
// Characters whose presence in a mandatory-numeric param make it an expression for certain.
// + and - are not included here because legacy numeric parameters can contain unary plus or minus,
// e.g. WinMove, -%x%, -%y%:
#define EXPR_TELLTALES EXPR_COMMON _T("\"")
// Characters that mark the end of an operand inside an expression. Double-quote must not be included:
#define EXPR_OPERAND_TERMINATORS_EX_DOT EXPR_COMMON _T("+-?") // L31: Used in a few places where '.' needs special treatment.
#define EXPR_OPERAND_TERMINATORS EXPR_OPERAND_TERMINATORS_EX_DOT _T(".") // L31: Used in expressions where '.' is always an operator.
#define EXPR_ALL_SYMBOLS EXPR_OPERAND_TERMINATORS _T("\"")
#define EXPR_ILLEGAL_CHARS _T("'\\;`") // Characters illegal in an expression.
// The following HOTSTRING option recognizer is kept somewhat forgiving/non-specific for backward compatibility
// (e.g. scripts may have some invalid hotstring options, which are simply ignored). This definition is here
// because it's related to continuation line symbols. Also, avoid ever adding "&" to hotstring options because
// it might introduce ambiguity in the differentiation of things like:
// : & x::hotkey action
// : & *::abbrev with leading colon::
#define IS_HOTSTRING_OPTION(chr) (cisalnum(chr) || _tcschr(_T("?*- \t"), chr))
// The characters below are ordered with most-often used ones first, for performance:
#define DEFINE_END_FLAGS \
TCHAR end_flags[] = {' ', g_delimiter, '(', '\t', '<', '>', ':', '=', '+', '-', '*', '/', '!', '~', '&', '|', '^', '[', '.', '?', '{', '\0'}; // '\0' must be last.
// L31: Added '[' for standalone ObjSet/Get to work as ACT_EXPRESSION. "Get" is allowed for simplicity and for future use with functions-as-values (e.g. varContainingFunc[]).
// L34: Added '.' and changed dot handling to fix x.=y, improve support in other areas, catch more errors and give slightly better error messages.
// v1.1.22.01: Added '{' to simplify OTB handling for else/try/finally.
#define ArgLength(aArgNum) ArgIndexLength((aArgNum)-1)
#define ArgToDouble(aArgNum) ArgIndexToDouble((aArgNum)-1)
#define ArgToInt64(aArgNum) ArgIndexToInt64((aArgNum)-1)
#define ArgToInt(aArgNum) (int)ArgToInt64(aArgNum) // Benchmarks show that having a "real" ArgToInt() that calls ATOI vs. ATOI64 (and ToInt() vs. ToInt64()) doesn't measurably improve performance.
#define ArgToUInt(aArgNum) (UINT)ArgToInt64(aArgNum) // Similar to what ATOU() does.
__int64 ArgIndexToInt64(int aArgIndex);
double ArgIndexToDouble(int aArgIndex);
size_t ArgIndexLength(int aArgIndex);
Var *ResolveVarOfArg(int aArgIndex, bool aCreateIfNecessary = true);
ResultType ExpandArgs(ExprTokenType *aResultToken = NULL, VarSizeType aSpaceNeeded = VARSIZE_ERROR, Var *aArgVar[] = NULL);
VarSizeType GetExpandedArgSize(Var *aArgVar[]);
LPTSTR ExpandArg(LPTSTR aBuf, int aArgIndex, Var *aArgVar = NULL);
LPTSTR ExpandExpression(int aArgIndex, ResultType &aResult, ExprTokenType *aResultToken
, LPTSTR &aTarget, LPTSTR &aDerefBuf, size_t &aDerefBufSize, LPTSTR aArgDeref[], size_t aExtraSize);
ResultType ExpressionToPostfix(ArgStruct &aArg);
ResultType EvaluateHotCriterionExpression(); // Called by HotkeyCriterion::Eval().
ResultType Deref(Var *aOutputVar, LPTSTR aBuf);
static bool FileIsFilteredOut(WIN32_FIND_DATA &aCurrentFile, FileLoopModeType aFileLoopMode
, LPTSTR aFilePath, size_t aFilePathLength);
Label *GetJumpTarget(bool aIsDereferenced);
Label *IsJumpValid(Label &aTargetLabel, bool aSilent = false);
BOOL IsOutsideAnyFunctionBody();
BOOL CheckValidFinallyJump(Line* jumpTarget);
HWND DetermineTargetWindow(LPTSTR aTitle, LPTSTR aText, LPTSTR aExcludeTitle, LPTSTR aExcludeText);
// This is in the .h file so that it's more likely the compiler's cost/benefit estimate will