1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
8 # include "multithread.h"
\r
9 # include "setting.h"
\r
10 # include "msgstream.h"
\r
18 WM_APP_engineNotify = WM_APP + 110,
\r
24 EngineNotify_shellExecute, ///
\r
25 EngineNotify_loadSetting, ///
\r
26 EngineNotify_showDlg, ///
\r
27 EngineNotify_helpMessage, ///
\r
28 EngineNotify_setForegroundWindow, ///
\r
29 EngineNotify_clearLog, ///
\r
38 MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT = 64, ///
\r
39 MAX_KEYMAP_PREFIX_HISTORY = 64, ///
\r
42 typedef Keymaps::KeymapPtrList KeymapPtrList; ///
\r
44 /// focus of a thread
\r
48 DWORD m_threadId; /// thread id
\r
49 HWND m_hwndFocus; /** window that has focus on
\r
51 tstringi m_className; /// class name of hwndFocus
\r
52 tstringi m_titleName; /// title name of hwndFocus
\r
53 bool m_isConsole; /// is hwndFocus console ?
\r
54 KeymapPtrList m_keymaps; /// keymaps
\r
58 FocusOfThread() : m_threadId(0), m_hwndFocus(NULL), m_isConsole(false) { }
\r
60 typedef std::map<DWORD /*ThreadId*/, FocusOfThread> FocusOfThreads; ///
\r
62 typedef std::list<DWORD /*ThreadId*/> ThreadIds; ///
\r
64 /// current status in generateKeyboardEvents
\r
68 const Keymap *m_keymap; /// current keymap
\r
69 ModifiedKey m_mkey; /// current processing key that user inputed
\r
70 /// index in currentFocusOfThread->keymaps
\r
71 Keymaps::KeymapPtrList::iterator m_i;
\r
75 bool isPressed() const {
\r
76 return m_mkey.m_modifier.isOn(Modifier::Type_Down);
\r
80 friend class FunctionParam;
\r
90 class EmacsEditKillLine
\r
92 tstring m_buf; /// previous kill-line contents
\r
95 bool m_doForceReset; ///
\r
99 HGLOBAL makeNewKillLineBuf(const _TCHAR *i_data, int *i_retval);
\r
106 /** EmacsEditKillLineFunc.
\r
107 clear the contents of the clopboard
\r
108 at that time, confirm if it is the result of the previous kill-line
\r
111 /// EmacsEditKillLinePred
\r
115 /// window positon for &WindowHMaximize, &WindowVMaximize
\r
116 class WindowPosition
\r
134 WindowPosition(HWND i_hwnd, const RECT &i_rc, Mode i_mode)
\r
135 : m_hwnd(i_hwnd), m_rc(i_rc), m_mode(i_mode) { }
\r
137 typedef std::list<WindowPosition> WindowPositions;
\r
139 typedef std::list<HWND> WindowsWithAlpha; /// windows for &WindowSetAlpha
\r
141 enum InterruptThreadReason {
\r
142 InterruptThreadReason_Terminate,
\r
143 InterruptThreadReason_Pause,
\r
144 InterruptThreadReason_Resume,
\r
148 class InputHandler {
\r
150 typedef int (*INSTALL_HOOK)(INPUT_DETOUR i_keyboardDetour, Engine *i_engine, bool i_install);
\r
152 static unsigned int WINAPI run(void *i_this);
\r
154 InputHandler(INSTALL_HOOK i_installHook, INPUT_DETOUR i_inputDetour);
\r
160 int start(Engine *i_engine);
\r
165 unsigned m_threadId;
\r
168 INSTALL_HOOK m_installHook;
\r
169 INPUT_DETOUR m_inputDetour;
\r
174 CriticalSection m_cs; /// criticalSection
\r
177 HWND m_hwndAssocWindow; /** associated window (we post
\r
179 Setting * volatile m_setting; /// setting
\r
181 // engine thread state
\r
182 HANDLE m_threadHandle;
\r
183 unsigned m_threadId;
\r
184 std::deque<KEYBOARD_INPUT_DATA> *m_inputQueue;
\r
185 HANDLE m_queueMutex;
\r
186 MSLLHOOKSTRUCT m_msllHookCurrent;
\r
187 bool m_buttonPressed;
\r
189 InputHandler m_keyboardHandler;
\r
190 InputHandler m_mouseHandler;
\r
191 HANDLE m_readEvent; /** reading from mayu device
\r
192 has been completed */
\r
193 OVERLAPPED m_ol; /** for async read/write of
\r
195 HANDLE m_hookPipe; /// named pipe for &SetImeString
\r
196 HMODULE m_sts4mayu; /// DLL module for ThumbSense
\r
197 HMODULE m_cts4mayu; /// DLL module for ThumbSense
\r
198 bool volatile m_isLogMode; /// is logging mode ?
\r
199 bool volatile m_isEnabled; /// is enabled ?
\r
200 bool volatile m_isSynchronizing; /// is synchronizing ?
\r
201 HANDLE m_eSync; /// event for synchronization
\r
202 int m_generateKeyboardEventsRecursionGuard; /** guard against too many
\r
205 // current key state
\r
206 Modifier m_currentLock; /// current lock key's state
\r
207 int m_currentKeyPressCount; /** how many keys are pressed
\r
209 int m_currentKeyPressCountOnWin32; /** how many keys are pressed
\r
211 Key *m_lastGeneratedKey; /// last generated key
\r
212 Key *m_lastPressedKey[2]; /// last pressed key
\r
213 ModifiedKey m_oneShotKey; /// one shot key
\r
214 unsigned int m_oneShotRepeatableRepeatCount; /// repeat count of one shot key
\r
215 bool m_isPrefix; /// is prefix ?
\r
216 bool m_doesIgnoreModifierForPrefix; /** does ignore modifier key
\r
218 bool m_doesEditNextModifier; /** does edit next user input
\r
219 key's modifier ? */
\r
220 Modifier m_modifierForNextKey; /** modifier for next key if
\r
223 /** current keymaps.
\r
225 <dt>when &OtherWindowClass
\r
226 <dd>currentKeymap becoms currentKeymaps[++ Current::i]
\r
227 <dt>when &KeymapParent
\r
228 <dd>currentKeymap becoms currentKeyamp->parentKeymap
\r
230 <dd>currentKeyamp becoms *Current::i
\r
233 const Keymap * volatile m_currentKeymap; /// current keymap
\r
234 FocusOfThreads /*volatile*/ m_focusOfThreads; ///
\r
235 FocusOfThread * volatile m_currentFocusOfThread; ///
\r
236 FocusOfThread m_globalFocus; ///
\r
237 HWND m_hwndFocus; /// current focus window
\r
238 ThreadIds m_attachedThreadIds; ///
\r
239 ThreadIds m_detachedThreadIds; ///
\r
242 KeymapPtrList m_keymapPrefixHistory; /// for &KeymapPrevPrefix
\r
243 EmacsEditKillLine m_emacsEditKillLine; /// for &EmacsEditKillLine
\r
244 const ActionFunction *m_afShellExecute; /// for &ShellExecute
\r
246 WindowPositions m_windowPositions; ///
\r
247 WindowsWithAlpha m_windowsWithAlpha; ///
\r
249 tstring m_helpMessage; /// for &HelpMessage
\r
250 tstring m_helpTitle; /// for &HelpMessage
\r
251 int m_variable; /// for &Variable,
\r
255 tomsgstream &m_log; /** log stream (output to log
\r
259 /// keyboard handler thread
\r
260 static unsigned int WINAPI keyboardDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam);
\r
261 /// mouse handler thread
\r
262 static unsigned int WINAPI mouseDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam);
\r
265 unsigned int keyboardDetour(KBDLLHOOKSTRUCT *i_kid);
\r
267 unsigned int mouseDetour(WPARAM i_message, MSLLHOOKSTRUCT *i_mid);
\r
269 unsigned int injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw);
\r
272 /// keyboard handler thread
\r
273 static unsigned int WINAPI keyboardHandler(void *i_this);
\r
275 void keyboardHandler();
\r
277 /// check focus window
\r
278 void checkFocusWindow();
\r
279 /// is modifier pressed ?
\r
280 bool isPressed(Modifier::Type i_mt);
\r
281 /// fix modifier key
\r
282 bool fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am);
\r
285 void outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
\r
288 /// genete modifier events
\r
289 void generateModifierEvents(const Modifier &i_mod);
\r
292 void generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event);
\r
294 /// generate keyboard event
\r
295 void generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign);
\r
297 void generateActionEvents(const Current &i_c, const Action *i_a,
\r
300 void generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
\r
303 void generateKeyboardEvents(const Current &i_c);
\r
305 void beginGeneratingKeyboardEvents(const Current &i_c, bool i_isModifier);
\r
307 /// pop all pressed key on win32
\r
308 void keyboardResetOnWin32();
\r
310 /// get current modifiers
\r
311 Modifier getCurrentModifiers(Key *i_key, bool i_isPressed);
\r
313 /// describe bindings
\r
314 void describeBindings();
\r
316 /// update m_lastPressedKey
\r
317 void updateLastPressedKey(Key *i_key);
\r
319 /// set current keymap
\r
320 void setCurrentKeymap(const Keymap *i_keymap,
\r
321 bool i_doesAddToHistory = false);
\r
322 /** open mayu device
\r
323 @return true if mayu device successfully is opened
\r
327 /// close mayu device
\r
330 /// load/unload [sc]ts4mayu.dll
\r
331 void manageTs4mayu(TCHAR *i_ts4mayuDllName, TCHAR *i_dependDllName,
\r
332 bool i_load, HMODULE *i_pTs4mayu);
\r
335 // BEGINING OF FUNCTION DEFINITION
\r
336 /// send a default key to Windows
\r
337 void funcDefault(FunctionParam *i_param);
\r
338 /// use a corresponding key of a parent keymap
\r
339 void funcKeymapParent(FunctionParam *i_param);
\r
340 /// use a corresponding key of a current window
\r
341 void funcKeymapWindow(FunctionParam *i_param);
\r
342 /// use a corresponding key of the previous prefixed keymap
\r
343 void funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous);
\r
344 /// use a corresponding key of an other window class, or use a default key
\r
345 void funcOtherWindowClass(FunctionParam *i_param);
\r
347 void funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
\r
348 BooleanType i_doesIgnoreModifiers = BooleanType_true);
\r
349 /// other keymap's key
\r
350 void funcKeymap(FunctionParam *i_param, const Keymap *i_keymap);
\r
352 void funcSync(FunctionParam *i_param);
\r
354 void funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
\r
355 ToggleType i_toggle = ToggleType_toggle);
\r
356 /// edit next user input key's modifier
\r
357 void funcEditNextModifier(FunctionParam *i_param,
\r
358 const Modifier &i_modifier);
\r
360 void funcVariable(FunctionParam *i_param, int i_mag, int i_inc);
\r
362 void funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
\r
364 /// undefined (bell)
\r
365 void funcUndefined(FunctionParam *i_param);
\r
367 void funcIgnore(FunctionParam *i_param);
\r
369 void funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
\r
370 UINT i_message, WPARAM i_wParam, LPARAM i_lParam);
\r
372 void funcShellExecute(FunctionParam *i_param, const StrExprArg &i_operation,
\r
373 const StrExprArg &i_file, const StrExprArg &i_parameters,
\r
374 const StrExprArg &i_directory,
\r
375 ShowCommandType i_showCommand);
\r
376 /// SetForegroundWindow
\r
377 void funcSetForegroundWindow(FunctionParam *i_param,
\r
378 const tregex &i_windowClassName,
\r
379 LogicalOperatorType i_logicalOp
\r
380 = LogicalOperatorType_and,
\r
381 const tregex &i_windowTitleName
\r
382 = tregex(_T(".*")));
\r
384 void funcLoadSetting(FunctionParam *i_param,
\r
385 const StrExprArg &i_name = StrExprArg());
\r
387 void funcVK(FunctionParam *i_param, VKey i_vkey);
\r
389 void funcWait(FunctionParam *i_param, int i_milliSecond);
\r
390 /// investigate WM_COMMAND, WM_SYSCOMMAND
\r
391 void funcInvestigateCommand(FunctionParam *i_param);
\r
392 /// show mayu dialog box
\r
393 void funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
\r
394 ShowCommandType i_showCommand);
\r
395 /// describe bindings
\r
396 void funcDescribeBindings(FunctionParam *i_param);
\r
397 /// show help message
\r
398 void funcHelpMessage(FunctionParam *i_param,
\r
399 const StrExprArg &i_title = StrExprArg(),
\r
400 const StrExprArg &i_message = StrExprArg());
\r
402 void funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title);
\r
404 void funcWindowRaise(FunctionParam *i_param,
\r
405 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
407 void funcWindowLower(FunctionParam *i_param,
\r
408 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
409 /// minimize window
\r
410 void funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt
\r
411 = TargetWindowType_overlapped);
\r
412 /// maximize window
\r
413 void funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
414 = TargetWindowType_overlapped);
\r
415 /// maximize window horizontally
\r
416 void funcWindowHMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
417 = TargetWindowType_overlapped);
\r
418 /// maximize window virtically
\r
419 void funcWindowVMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
420 = TargetWindowType_overlapped);
\r
421 /// maximize window virtically or horizontally
\r
422 void funcWindowHVMaximize(FunctionParam *i_param, BooleanType i_isHorizontal,
\r
423 TargetWindowType i_twt
\r
424 = TargetWindowType_overlapped);
\r
426 void funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
\r
427 TargetWindowType i_twt
\r
428 = TargetWindowType_overlapped);
\r
429 /// move window to ...
\r
430 void funcWindowMoveTo(FunctionParam *i_param, GravityType i_gravityType,
\r
431 int i_dx, int i_dy, TargetWindowType i_twt
\r
432 = TargetWindowType_overlapped);
\r
433 /// move window visibly
\r
434 void funcWindowMoveVisibly(FunctionParam *i_param,
\r
435 TargetWindowType i_twt
\r
436 = TargetWindowType_overlapped);
\r
437 /// move window to other monitor
\r
438 void funcWindowMonitorTo(FunctionParam *i_param,
\r
439 WindowMonitorFromType i_fromType, int i_monitor,
\r
440 BooleanType i_adjustPos = BooleanType_true,
\r
441 BooleanType i_adjustSize = BooleanType_false);
\r
442 /// move window to other monitor
\r
443 void funcWindowMonitor(FunctionParam *i_param, int i_monitor,
\r
444 BooleanType i_adjustPos = BooleanType_true,
\r
445 BooleanType i_adjustSize = BooleanType_false);
\r
447 void funcWindowClingToLeft(FunctionParam *i_param,
\r
448 TargetWindowType i_twt
\r
449 = TargetWindowType_overlapped);
\r
451 void funcWindowClingToRight(FunctionParam *i_param,
\r
452 TargetWindowType i_twt
\r
453 = TargetWindowType_overlapped);
\r
455 void funcWindowClingToTop(FunctionParam *i_param,
\r
456 TargetWindowType i_twt
\r
457 = TargetWindowType_overlapped);
\r
459 void funcWindowClingToBottom(FunctionParam *i_param,
\r
460 TargetWindowType i_twt
\r
461 = TargetWindowType_overlapped);
\r
463 void funcWindowClose(FunctionParam *i_param,
\r
464 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
465 /// toggle top-most flag of the window
\r
466 void funcWindowToggleTopMost(FunctionParam *i_param);
\r
467 /// identify the window
\r
468 void funcWindowIdentify(FunctionParam *i_param);
\r
469 /// set alpha blending parameter to the window
\r
470 void funcWindowSetAlpha(FunctionParam *i_param, int i_alpha);
\r
471 /// redraw the window
\r
472 void funcWindowRedraw(FunctionParam *i_param);
\r
473 /// resize window to
\r
474 void funcWindowResizeTo(FunctionParam *i_param, int i_width, int i_height,
\r
475 TargetWindowType i_twt
\r
476 = TargetWindowType_overlapped);
\r
477 /// move the mouse cursor
\r
478 void funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy);
\r
479 /// send a mouse-wheel-message to Windows
\r
480 void funcMouseWheel(FunctionParam *i_param, int i_delta);
\r
481 /// convert the contents of the Clipboard to upper case or lower case
\r
482 void funcClipboardChangeCase(FunctionParam *i_param,
\r
483 BooleanType i_doesConvertToUpperCase);
\r
484 /// convert the contents of the Clipboard to upper case
\r
485 void funcClipboardUpcaseWord(FunctionParam *i_param);
\r
486 /// convert the contents of the Clipboard to lower case
\r
487 void funcClipboardDowncaseWord(FunctionParam *i_param);
\r
488 /// set the contents of the Clipboard to the string
\r
489 void funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text);
\r
491 void funcEmacsEditKillLinePred(FunctionParam *i_param,
\r
492 const KeySeq *i_keySeq1,
\r
493 const KeySeq *i_keySeq2);
\r
495 void funcEmacsEditKillLineFunc(FunctionParam *i_param);
\r
497 void funcLogClear(FunctionParam *i_param);
\r
499 void funcRecenter(FunctionParam *i_param);
\r
501 void funcDirectSSTP(FunctionParam *i_param,
\r
502 const tregex &i_name,
\r
503 const StrExprArg &i_protocol,
\r
504 const std::list<tstringq> &i_headers);
\r
506 void funcPlugIn(FunctionParam *i_param,
\r
507 const StrExprArg &i_dllName,
\r
508 const StrExprArg &i_funcName = StrExprArg(),
\r
509 const StrExprArg &i_funcParam = StrExprArg(),
\r
510 BooleanType i_doesCreateThread = BooleanType_false);
\r
511 /// set IME open status
\r
512 void funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle = ToggleType_toggle);
\r
513 /// set string to IME
\r
514 void funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data);
\r
515 /// enter to mouse event hook mode
\r
516 void funcMouseHook(FunctionParam *i_param, MouseHookType i_hookType, int i_hookParam);
\r
518 void funcCancelPrefix(FunctionParam *i_param);
\r
520 // END OF FUNCTION DEFINITION
\r
521 # define FUNCTION_FRIEND
\r
522 # include "functions.h"
\r
523 # undef FUNCTION_FRIEND
\r
527 Engine(tomsgstream &i_log);
\r
531 /// start/stop keyboard handler thread
\r
536 /// pause keyboard handler thread and close device
\r
539 /// resume keyboard handler thread and re-open device
\r
542 /// do some procedure before quit which must be done synchronously
\r
543 /// (i.e. not on WM_QUIT)
\r
544 bool prepairQuit();
\r
547 void enableLogMode(bool i_isLogMode = true) {
\r
548 m_isLogMode = i_isLogMode;
\r
551 void disableLogMode() {
\r
552 m_isLogMode = false;
\r
555 /// enable/disable engine
\r
556 void enable(bool i_isEnabled = true) {
\r
557 m_isEnabled = i_isEnabled;
\r
561 m_isEnabled = false;
\r
564 bool getIsEnabled() const {
\r
565 return m_isEnabled;
\r
568 /// associated window
\r
569 void setAssociatedWndow(HWND i_hwnd) {
\r
570 m_hwndAssocWindow = i_hwnd;
\r
573 /// associated window
\r
574 HWND getAssociatedWndow() const {
\r
575 return m_hwndAssocWindow;
\r
579 bool setSetting(Setting *i_setting);
\r
582 bool setFocus(HWND i_hwndFocus, DWORD i_threadId,
\r
583 const tstringi &i_className,
\r
584 const tstringi &i_titleName, bool i_isConsole);
\r
587 bool setLockState(bool i_isNumLockToggled, bool i_isCapsLockToggled,
\r
588 bool i_isScrollLockToggled, bool i_isKanaLockToggled,
\r
589 bool i_isImeLockToggled, bool i_isImeCompToggled);
\r
592 void checkShow(HWND i_hwnd);
\r
593 bool setShow(bool i_isMaximized, bool i_isMinimized, bool i_isMDI);
\r
598 /// thread attach notify
\r
599 bool threadAttachNotify(DWORD i_threadId);
\r
601 /// thread detach notify
\r
602 bool threadDetachNotify(DWORD i_threadId);
\r
605 void shellExecute();
\r
607 /// get help message
\r
608 void getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle);
\r
611 template <typename WPARAM_T, typename LPARAM_T>
\r
612 void commandNotify(HWND i_hwnd, UINT i_message, WPARAM_T i_wParam,
\r
615 Acquire b(&m_log, 0);
\r
616 HWND hf = m_hwndFocus;
\r
620 if (GetWindowThreadProcessId(hf, NULL) ==
\r
621 GetWindowThreadProcessId(m_hwndAssocWindow, NULL))
\r
622 return; // inhibit the investigation of MADO TSUKAI NO YUUTSU
\r
624 const _TCHAR *target = NULL;
\r
625 int number_target = 0;
\r
628 target = _T("ToItself");
\r
629 else if (i_hwnd == GetParent(hf))
\r
630 target = _T("ToParentWindow");
\r
632 // Function::toMainWindow
\r
635 HWND p = GetParent(h);
\r
641 target = _T("ToMainWindow");
\r
643 // Function::toOverlappedWindow
\r
647 LONG_PTR style = GetWindowLongPtr(h, GWL_STYLE);
\r
649 LONG style = GetWindowLong(h, GWL_STYLE);
\r
651 if ((style & WS_CHILD) == 0)
\r
656 target = _T("ToOverlappedWindow");
\r
660 for (number_target = 0; h; number_target ++, h = GetParent(h))
\r
668 m_log << _T("&PostMessage(");
\r
672 m_log << number_target;
\r
673 m_log << _T(", ") << i_message
\r
674 << _T(", 0x") << std::hex << i_wParam
\r
675 << _T(", 0x") << i_lParam << _T(") # hwnd = ")
\r
676 << reinterpret_cast<int>(i_hwnd) << _T(", ")
\r
677 << _T("message = ") << std::dec;
\r
678 if (i_message == WM_COMMAND)
\r
679 m_log << _T("WM_COMMAND, ");
\r
680 else if (i_message == WM_SYSCOMMAND)
\r
681 m_log << _T("WM_SYSCOMMAND, ");
\r
683 m_log << i_message << _T(", ");
\r
684 m_log << _T("wNotifyCode = ") << HIWORD(i_wParam) << _T(", ")
\r
685 << _T("wID = ") << LOWORD(i_wParam) << _T(", ")
\r
686 << _T("hwndCtrl = 0x") << std::hex << i_lParam << std::dec << std::endl;
\r
689 /// get current window class name
\r
690 const tstringi &getCurrentWindowClassName() const {
\r
691 return m_currentFocusOfThread->m_className;
\r
694 /// get current window title name
\r
695 const tstringi &getCurrentWindowTitleName() const {
\r
696 return m_currentFocusOfThread->m_titleName;
\r
702 class FunctionParam
\r
705 bool m_isPressed; /// is key pressed ?
\r
707 Engine::Current m_c; /// new context
\r
708 bool m_doesNeedEndl; /// need endl ?
\r
709 const ActionFunction *m_af; ///
\r
713 #endif // !_ENGINE_H
\r