"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/hotkey.h" (8 May 2021, 19346 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


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

    1 /*
    2 AutoHotkey
    3 
    4 Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
    5 
    6 This program is free software; you can redistribute it and/or
    7 modify it under the terms of the GNU General Public License
    8 as published by the Free Software Foundation; either version 2
    9 of the License, or (at your option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 */
   16 
   17 #ifndef hotkey_h
   18 #define hotkey_h
   19 
   20 #include "keyboard_mouse.h"
   21 #include "script.h"  // For which label (and in turn which line) in the script to jump to.
   22 EXTERN_SCRIPT;  // For g_script.
   23 
   24 // Due to control/alt/shift modifiers, quite a lot of hotkey combinations are possible, so support any
   25 // conceivable use.  This value is used for initial sizing of the shk array, which doubles in size each
   26 // time its capacity is reached (making the need for expansion rare).
   27 #define INITIAL_MAX_HOTKEYS 256
   28 
   29 // Note: 0xBFFF is the largest ID that can be used with RegisterHotkey().
   30 // But further limit this to 0x7FFF (32,767) so that the highest order bit
   31 // is reserved for our other use:
   32 #define HOTKEY_KEY_UP                  0x8000
   33 #define HOTKEY_ID_MASK                 0x7FFF
   34 #define HOTKEY_ID_INVALID              HOTKEY_ID_MASK
   35 #define HOTKEY_ID_ALT_TAB              0x7FFE
   36 #define HOTKEY_ID_ALT_TAB_SHIFT        0x7FFD
   37 #define HOTKEY_ID_ALT_TAB_MENU         0x7FFC
   38 #define HOTKEY_ID_ALT_TAB_AND_MENU     0x7FFB
   39 #define HOTKEY_ID_ALT_TAB_MENU_DISMISS 0x7FFA
   40 #define HOTKEY_ID_MAX                  0x7FF9  // 32762 hotkeys
   41 #define HOTKEY_ID_ON                   0x01  // This and the next 2 are used only for convenience by ConvertAltTab().
   42 #define HOTKEY_ID_OFF                  0x02
   43 #define HOTKEY_ID_TOGGLE               0x03
   44 #define IS_ALT_TAB(id) (id > HOTKEY_ID_MAX && id < HOTKEY_ID_INVALID)
   45 
   46 // Below: Use double-colon as delimiter to set these apart from normal labels.
   47 // The main reason for this is that otherwise the user would have to worry
   48 // about a normal label being unintentionally valid as a hotkey, e.g. "Shift:"
   49 // might be a legitimate label that the user forgot is also a valid hotkey:
   50 #define HOTKEY_FLAG _T("::")
   51 #define HOTKEY_FLAG_LENGTH 2
   52 
   53 #define COMPOSITE_DELIMITER _T(" & ")
   54 #define COMPOSITE_DELIMITER_LENGTH 3
   55 
   56 // Smallest workable size: to save mem in some large arrays that use this:
   57 typedef USHORT HotkeyIDType; // This is relied upon to be unsigned; e.g. many places omit a check for ID < 0.
   58 typedef HotkeyIDType HookActionType;
   59 
   60 typedef UCHAR HotkeyTypeType;
   61 enum HotkeyTypeEnum {HK_NORMAL, HK_KEYBD_HOOK, HK_MOUSE_HOOK, HK_BOTH_HOOKS, HK_JOYSTICK};
   62 // If above numbers are ever changed/reshuffled, update the macros below.
   63 #define HK_TYPE_CAN_BECOME_KEYBD_HOOK(type) (type == HK_NORMAL)
   64 #define HK_TYPE_IS_HOOK(type) (type > HK_NORMAL && type < HK_JOYSTICK)
   65 
   66 HWND HotCriterionAllowsFiring(HotkeyCriterion *aCriterion, LPTSTR aHotkeyName); // Used by hotkeys and hotstrings.
   67 bool HotInputLevelAllowsFiring(SendLevelType inputLevel, ULONG_PTR aEventExtraInfo, LPTSTR aKeyHistoryChar);
   68 ResultType SetHotkeyCriterion(HotCriterionType aType, LPTSTR aWinTitle, LPTSTR aWinText);
   69 HotkeyCriterion *AddHotkeyIfExpr();
   70 HotkeyCriterion *FindHotkeyIfExpr(LPTSTR aExpr);
   71 
   72 inline int InputLevelFromInfo(ULONG_PTR aExtraInfo)
   73 {
   74     if (aExtraInfo >= KEY_IGNORE_MIN && aExtraInfo <= KEY_IGNORE_MAX)
   75         return (int)(KEY_IGNORE_LEVEL(0) - aExtraInfo);
   76     return SendLevelMax + 1;
   77 }
   78 
   79 
   80 
   81 struct HotkeyVariant
   82 {
   83     LabelRef mJumpToLabel;
   84     HotkeyCriterion *mHotCriterion;
   85     HotkeyVariant *mNextVariant;
   86     DWORD mRunAgainTime;
   87     int mPriority;
   88     // Keep members that are less than 32-bit adjacent to each other to conserve memory in with the default
   89     // 4-byte alignment:
   90     USHORT mIndex;
   91     UCHAR mExistingThreads, mMaxThreads;
   92     SendLevelType mInputLevel;
   93     bool mNoSuppress; // v1.0.44: This became a per-variant attribute because it's more useful/flexible that way.
   94     bool mMaxThreadsBuffer;
   95     bool mRunAgainAfterFinished;
   96     bool mEnabled; // Whether this variant has been disabled via the Hotkey command.
   97 };
   98 
   99 
  100 
  101 class Hotkey
  102 {
  103 private:
  104     // These are done as static, rather than having an outer-class to contain all the hotkeys, because
  105     // the hotkey ID is used as the array index for performance reasons.  Having an outer class implies
  106     // the potential future use of more than one set of hotkeys, which could still be implemented
  107     // within static data and methods to retain the indexing/performance method:
  108     static HookType sWhichHookNeeded;
  109     static HookType sWhichHookAlways;
  110     static DWORD sTimePrev;
  111     static DWORD sTimeNow;
  112     static HotkeyIDType sNextID;
  113 
  114     bool Enable(HotkeyVariant &aVariant) // Returns true if the variant needed to be disabled, in which case caller should generally call ManifestAllHotkeysHotstringsHooks().
  115     {
  116         if (aVariant.mEnabled) // Added for v1.0.23 to greatly improve performance when hotkey is already in the right state.
  117             return false; // Indicate that it's already enabled.
  118         aVariant.mEnabled = true;
  119         return true;
  120     }
  121 
  122     bool Disable(HotkeyVariant &aVariant) // Returns true if the variant needed to be disabled, in which case caller should generally call ManifestAllHotkeysHotstringsHooks().
  123     {
  124         if (!aVariant.mEnabled) // Added for v1.0.23 to greatly improve performance when hotkey is already in the right state.
  125             return false; // Indicate that it's already disabled.
  126         aVariant.mEnabled = false;
  127         aVariant.mRunAgainAfterFinished = false; // ManifestAllHotkeysHotstringsHooks() won't do this unless the entire hotkey is disabled/unregistered.
  128         return true;
  129     }
  130 
  131     bool EnableParent() // Returns true if the hotkey needed to be disabled, in which case caller should generally call ManifestAllHotkeysHotstringsHooks().
  132     {
  133         if (mParentEnabled)
  134             return false; // Indicate that it's already enabled.
  135         mParentEnabled = true;
  136         return true;
  137     }
  138 
  139     bool DisableParent() // Returns true if the hotkey needed to be disabled, in which case caller should generally call ManifestAllHotkeysHotstringsHooks().
  140     {
  141         if (!mParentEnabled)
  142             return false; // Indicate that it's already disabled.
  143         mParentEnabled = false;
  144         return true;
  145     }
  146 
  147     ResultType Register();
  148     ResultType Unregister();
  149 
  150     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  151     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  152     void operator delete(void *aPtr) {SimpleHeap::Delete(aPtr);}  // Deletes aPtr if it was the most recently allocated.
  153     void operator delete[](void *aPtr) {SimpleHeap::Delete(aPtr);}
  154 
  155     // For now, constructor & destructor are private so that only static methods can create new
  156     // objects.  This allow proper tracking of which OS hotkey IDs have been used.
  157     Hotkey(HotkeyIDType aID, IObject *aJumpToLabel, HookActionType aHookAction, LPTSTR aName, bool aSuffixHasTilde, bool aUseErrorLevel);
  158     ~Hotkey() {if (mIsRegistered) Unregister();}
  159 
  160 public:
  161     static Hotkey **shk;
  162     static int shkMax;
  163 
  164     // 32-bit members:
  165     mod_type mModifiers;  // MOD_ALT, MOD_CONTROL, MOD_SHIFT, MOD_WIN, or some additive or bitwise-or combination of these.
  166 
  167     // 16-bit members:
  168     HotkeyIDType mID;  // Must be unique for each hotkey of a given thread.
  169     HookActionType mHookAction;
  170     sc_type mSC; // Scan code.  All vk's have a scan code, but not vice versa.
  171     sc_type mModifierSC; // If mModifierVK is zero, this scan code, if non-zero, will be used as the modifier.
  172     HotkeyIDType mNextHotkey; // ID of the next hotkey with the same suffix as this one (initialized by the hook).
  173 
  174     // Keep single-byte attributes adjacent to each other to conserve memory within byte-aligned class/struct:
  175     modLR_type mModifiersLR;  // Left-right centric versions of the above.
  176     modLR_type mModifiersConsolidatedLR; // The combination of mModifierVK, mModifierSC, mModifiersLR, modifiers
  177     vk_type mVK; // virtual-key code, e.g. VK_TAB, VK_LWIN, VK_LMENU, VK_APPS, VK_F10.  If zero, use sc below.
  178     vk_type mModifierVK; // Any other virtual key that must be pressed down in order to activate "vk" itself.
  179     HotkeyTypeType mType;
  180     #define NO_SUPPRESS_PREFIX 0x01               // Bitwise: Bit #1
  181     #define AT_LEAST_ONE_VARIANT_HAS_TILDE 0x02   // Bitwise: Bit #2
  182     #define AT_LEAST_ONE_VARIANT_LACKS_TILDE 0x04 // Bitwise: Bit #3
  183     #define NO_SUPPRESS_NEXT_UP_EVENT 0x08        // Bitwise: Bit #4
  184     #define NO_SUPPRESS_SUFFIX_VARIES (AT_LEAST_ONE_VARIANT_HAS_TILDE | AT_LEAST_ONE_VARIANT_LACKS_TILDE) // i.e. a hotkey that has variants of both types.
  185     #define NO_SUPPRESS_STATES NO_SUPPRESS_NEXT_UP_EVENT  // This is a bitwise union (currently only one item) of those of the above that represent a the key's dynamically changing state as the user types.
  186     UCHAR mNoSuppress;  // Uses the flags above.  Normally 0, but can be overridden by using the hotkey tilde (~) prefix).
  187     bool mKeybdHookMandatory;
  188     bool mAllowExtraModifiers;  // False if the hotkey should not fire when extraneous modifiers are held down.
  189     bool mKeyUp; // A hotkey that should fire on key-up.
  190     bool mVK_WasSpecifiedByNumber; // A hotkey defined by something like "VK24::" or "Hotkey, VK24, ..."
  191     bool mIsRegistered;  // Whether this hotkey has been successfully registered.
  192     bool mParentEnabled; // When true, the individual variants' mEnabled flags matter. When false, the entire hotkey is disabled.
  193     bool mConstructedOK;
  194     
  195     // 64- or 32-bit members:
  196     LPTSTR mName; // Points to the label name for static hotkeys, or a dynamically-allocated string for dynamic hotkeys.
  197     HotkeyVariant *mFirstVariant, *mLastVariant; // v1.0.42: Linked list of variant hotkeys created via #IfWin directives.
  198 
  199     // Make sHotkeyCount an alias for sNextID.  Make it const to enforce modifying the value in only one way:
  200     static const HotkeyIDType &sHotkeyCount;
  201     static bool sJoystickHasHotkeys[MAX_JOYSTICKS];
  202     static DWORD sJoyHotkeyCount;
  203 
  204     static void AllDestructAndExit(int exit_code);
  205 
  206     #define HOTKEY_EL_BADLABEL           _T("1") // Set as strings so that SetFormat doesn't affect their appearance (for use with "If ErrorLevel in 5,6").
  207     #define HOTKEY_EL_INVALID_KEYNAME    _T("2")
  208     #define HOTKEY_EL_UNSUPPORTED_PREFIX _T("3")
  209     #define HOTKEY_EL_ALTTAB             _T("4")
  210     #define HOTKEY_EL_NOTEXIST           _T("5")
  211     #define HOTKEY_EL_NOTEXISTVARIANT    _T("6")
  212     //#define HOTKEY_EL_WIN9X              _T("50") // Reserved; no longer used.
  213     #define HOTKEY_EL_NOREG              _T("51")
  214     #define HOTKEY_EL_MAXCOUNT           _T("98") // 98 allows room for other ErrorLevels to be added in between.
  215     #define HOTKEY_EL_MEM                _T("99")
  216     static ResultType Dynamic(LPTSTR aHotkeyName, LPTSTR aLabelName, LPTSTR aOptions, IObject *aJumpToLabel, Var *aJumpToLabelVar);
  217 
  218     static Hotkey *AddHotkey(IObject *aJumpToLabel, HookActionType aHookAction, LPTSTR aName, bool aSuffixHasTilde, bool aUseErrorLevel);
  219     HotkeyVariant *FindVariant();
  220     HotkeyVariant *AddVariant(IObject *aJumpToLabel, bool aSuffixHasTilde);
  221     static bool PrefixHasNoEnabledSuffixes(int aVKorSC, bool aIsSC);
  222     HotkeyVariant *CriterionAllowsFiring(HWND *aFoundHWND = NULL, ULONG_PTR aExtraInfo = 0, LPTSTR aSingleChar = NULL);
  223     static HotkeyVariant *CriterionAllowsFiring(HotkeyIDType aHotkeyID, HWND &aFoundHWND);
  224     static HotkeyVariant *CriterionFiringIsCertain(HotkeyIDType &aHotkeyIDwithFlags, bool aKeyUp, ULONG_PTR aExtraInfo
  225         , UCHAR &aNoSuppress, bool &aFireWithNoSuppress, LPTSTR aSingleChar);
  226     static modLR_type HotkeyRequiresModLR(HotkeyIDType aHotkeyIDwithoutflags, modLR_type aModLR);
  227     static void TriggerJoyHotkeys(int aJoystickID, DWORD aButtonsNewlyDown);
  228     void PerformInNewThreadMadeByCaller(HotkeyVariant &aVariant);
  229     static void ManifestAllHotkeysHotstringsHooks();
  230     static void RequireHook(HookType aWhichHook) {sWhichHookAlways |= aWhichHook;}
  231     static void MaybeUninstallHook();
  232     static ResultType TextInterpret(LPTSTR aName, Hotkey *aThisHotkey, bool aUseErrorLevel);
  233 
  234     struct HotkeyProperties // Struct used by TextToModifiers() and its callers.
  235     {
  236         mod_type modifiers;
  237         modLR_type modifiersLR;
  238         TCHAR prefix_text[32];  // Has to be large enough to hold the largest key name in g_key_to_vk,
  239         TCHAR suffix_text[32];  // which is probably "Browser_Favorites" (17).
  240         bool suffix_has_tilde; // As opposed to "prefix has tilde".
  241         bool has_asterisk;
  242         bool is_key_up;
  243         bool hook_is_mandatory;
  244     };
  245     static LPTSTR TextToModifiers(LPTSTR aText, Hotkey *aThisHotkey, HotkeyProperties *aProperties = NULL);
  246     static ResultType TextToKey(LPTSTR aText, LPTSTR aHotkeyName, bool aIsModifier, Hotkey *aThisHotkey, bool aUseErrorLevel);
  247 
  248     static void InstallKeybdHook();
  249     static void InstallMouseHook();
  250 
  251     bool PerformIsAllowed(HotkeyVariant &aVariant)
  252     {
  253         // For now, attempts to launch another simultaneous instance of this subroutine
  254         // are ignored if MaxThreadsPerHotkey (for this particular hotkey) has been reached.
  255         // In the future, it might be better to have this user-configurable, i.e. to devise
  256         // some way for the hotkeys to be kept queued up so that they take effect only when
  257         // the number of currently active threads drops below the max.  But doing such
  258         // might make "infinite key loops" harder to catch because the rate of incoming hotkeys
  259         // would be slowed down to prevent the subroutines from running concurrently:
  260         ActionTypeType act = aVariant.mJumpToLabel->TypeOfFirstLine();
  261         return aVariant.mExistingThreads < aVariant.mMaxThreads || (ACT_IS_ALWAYS_ALLOWED(act)); // See below.
  262         // Although our caller may have already called ACT_IS_ALWAYS_ALLOWED(), it was for a different reason.
  263     }
  264 
  265     bool IsExemptFromSuspend() // A hotkey is considered exempt if even one of its variants is exempt.
  266     {
  267         // It's the caller's responsibility to check vp->mEnabled; that isn't done here.
  268         if (mHookAction) // An alt-tab hotkey (which overrides all its variants) is never exempt.
  269             return false;
  270         for (HotkeyVariant *vp = mFirstVariant; vp; vp = vp->mNextVariant)
  271             if (vp->mJumpToLabel->IsExemptFromSuspend()) // If it has no label, it's never exempt.
  272                 return true; // Even a single exempt variant makes the entire hotkey exempt.
  273         // Otherwise, since the above didn't find any exempt variants, the entire hotkey is non-exempt:
  274         return false;
  275     }
  276 
  277     bool IsCompletelyDisabled()
  278     {
  279         if (mHookAction) // Alt tab hotkeys are disabled completely if and only if the parent is disabled.
  280             return !mParentEnabled;
  281         for (HotkeyVariant *vp = mFirstVariant; vp; vp = vp->mNextVariant)
  282             if (vp->mEnabled)
  283                 return false;
  284         return true;
  285     }
  286 
  287     static void RunAgainAfterFinished(HotkeyVariant &aVariant)
  288     {
  289         if (aVariant.mMaxThreadsBuffer)
  290             aVariant.mRunAgainAfterFinished = true;
  291         aVariant.mRunAgainTime = GetTickCount();
  292         // Above: The time this event was buffered, to make sure it doesn't get too old.
  293     }
  294 
  295     static void ResetRunAgainAfterFinished()  // For all hotkeys and all variants of each.
  296     {
  297         HotkeyVariant *vp;
  298         for (int i = 0; i < sHotkeyCount; ++i)
  299             for (vp = shk[i]->mFirstVariant; vp; vp = vp->mNextVariant)
  300                 vp->mRunAgainAfterFinished = false;
  301     }
  302 
  303     static HookActionType ConvertAltTab(LPTSTR aBuf, bool aAllowOnOff)
  304     {
  305         if (!aBuf || !*aBuf) return 0;
  306         if (!_tcsicmp(aBuf, _T("AltTab"))) return HOTKEY_ID_ALT_TAB;
  307         if (!_tcsicmp(aBuf, _T("ShiftAltTab"))) return HOTKEY_ID_ALT_TAB_SHIFT;
  308         if (!_tcsicmp(aBuf, _T("AltTabMenu"))) return HOTKEY_ID_ALT_TAB_MENU;
  309         if (!_tcsicmp(aBuf, _T("AltTabAndMenu"))) return HOTKEY_ID_ALT_TAB_AND_MENU;
  310         if (!_tcsicmp(aBuf, _T("AltTabMenuDismiss"))) return HOTKEY_ID_ALT_TAB_MENU_DISMISS;
  311         if (aAllowOnOff)
  312         {
  313             if (!_tcsicmp(aBuf, _T("On"))) return HOTKEY_ID_ON;
  314             if (!_tcsicmp(aBuf, _T("Off"))) return HOTKEY_ID_OFF;
  315             if (!_tcsicmp(aBuf, _T("Toggle"))) return HOTKEY_ID_TOGGLE;
  316         }
  317         return 0;
  318     }
  319 
  320     static Hotkey *FindHotkeyByTrueNature(LPTSTR aName, bool &aSuffixHasTilde, bool &aHookIsMandatory);
  321     static Hotkey *FindHotkeyContainingModLR(modLR_type aModifiersLR);  //, HotkeyIDType hotkey_id_to_omit);
  322     //static Hotkey *FindHotkeyWithThisModifier(vk_type aVK, sc_type aSC);
  323     //static Hotkey *FindHotkeyBySC(sc2_type aSC2, mod_type aModifiers, modLR_type aModifiersLR);
  324     static HotkeyIDType FindPairedHotkey(HotkeyIDType aFirstID, modLR_type aModsLR, bool aKeyUp);
  325 
  326     static LPTSTR ListHotkeys(LPTSTR aBuf, int aBufSize);
  327     LPTSTR ToText(LPTSTR aBuf, int aBufSize, bool aAppendNewline);
  328 
  329 private:
  330     static HotkeyVariant *CriterionFiringIsCertainHelper(HotkeyIDType &aHotkeyIDwithFlags, bool aKeyUp, UCHAR &aNoSuppress
  331         , bool &aFireWithNoSuppress, LPTSTR aSingleChar);
  332 };
  333 
  334 
  335 ///////////////////////////////////////////////////////////////////////////////////
  336 
  337 #define MAX_HOTSTRING_LENGTH 40  // Hard to imagine a need for more than this, and most are only a few chars long.
  338 #define MAX_HOTSTRING_LENGTH_STR _T("40")  // Keep in sync with the above.
  339 #define HOTSTRING_BLOCK_SIZE 1024
  340 typedef UINT HotstringIDType;
  341 
  342 enum CaseConformModes {CASE_CONFORM_NONE, CASE_CONFORM_ALL_CAPS, CASE_CONFORM_FIRST_CAP};
  343 
  344 
  345 class Hotstring
  346 {
  347 public:
  348     static Hotstring **shs;  // An array to be allocated on first use (performs better than linked list).
  349     static HotstringIDType sHotstringCount;
  350     static HotstringIDType sHotstringCountMax;
  351     static UINT sEnabledCount; // v1.1.28.00: For performance, such as avoiding calling ToAsciiEx() in the hook.
  352 
  353     LabelRef mJumpToLabel;
  354     LPTSTR mName;
  355     LPTSTR mString, mReplacement;
  356     HotkeyCriterion *mHotCriterion;
  357     int mPriority, mKeyDelay;
  358 
  359     // Keep members that are smaller than 32-bit adjacent with each other to conserve memory (due to 4-byte alignment).
  360     SendModes mSendMode;
  361     SendRawType mSendRaw;
  362     SendLevelType mInputLevel;
  363     UCHAR mStringLength;
  364     UCHAR mSuspended; // FALSE or a combination of one of the following:
  365     #define HS_SUSPENDED 0x01
  366     #define HS_TURNED_OFF 0x02
  367     #define HS_TEMPORARILY_DISABLED 0x04
  368     UCHAR mExistingThreads, mMaxThreads;
  369     bool mCaseSensitive, mConformToCase, mDoBackspace, mOmitEndChar, mEndCharRequired
  370         , mDetectWhenInsideWord, mDoReset, mConstructedOK;
  371 
  372     static void SuspendAll(bool aSuspend);
  373     ResultType PerformInNewThreadMadeByCaller();
  374     void DoReplace(LPARAM alParam);
  375     static Hotstring *FindHotstring(LPTSTR aHotstring, bool aCaseSensitive, bool aDetectWhenInsideWord, HotkeyCriterion *aHotCriterion);
  376     static ResultType AddHotstring(LPTSTR aName, LabelPtr aJumpToLabel, LPTSTR aOptions, LPTSTR aHotstring
  377         , LPTSTR aReplacement, bool aHasContinuationSection, UCHAR aSuspend = FALSE);
  378     static void ParseOptions(LPTSTR aOptions, int &aPriority, int &aKeyDelay, SendModes &aSendMode
  379         , bool &aCaseSensitive, bool &aConformToCase, bool &aDoBackspace, bool &aOmitEndChar, SendRawType &aSendRaw
  380         , bool &aEndCharRequired, bool &aDetectWhenInsideWord, bool &aDoReset, bool &aExecuteAction);
  381     void ParseOptions(LPTSTR aOptions);
  382 
  383     // Constructor & destructor:
  384     Hotstring(LPTSTR aName, LabelPtr aJumpToLabel, LPTSTR aOptions, LPTSTR aHotstring, LPTSTR aReplacement
  385         , bool aHasContinuationSection, UCHAR aSuspend);
  386     ~Hotstring() {}  // Note that mReplacement is sometimes malloc'd, sometimes from SimpleHeap, and sometimes the empty string.
  387 
  388     void *operator new(size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  389     void *operator new[](size_t aBytes) {return SimpleHeap::Malloc(aBytes);}
  390     void operator delete(void *aPtr) {SimpleHeap::Delete(aPtr);}  // Deletes aPtr if it was the most recently allocated.
  391     void operator delete[](void *aPtr) {SimpleHeap::Delete(aPtr);}
  392 };
  393 
  394 
  395 #endif