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*/> DetachedThreadIds; ///
\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_device; /// mayu device
\r
183 bool m_didMayuStartDevice; /** Did the mayu start the
\r
185 HANDLE m_threadEvent; /** 1. thread has been started
\r
186 2. thread is about to end*/
\r
187 HANDLE m_threadHandle;
\r
188 unsigned m_threadId;
\r
189 tstring m_mayudVersion; /// version of mayud.sys
\r
191 std::deque<KEYBOARD_INPUT_DATA> m_kidq;
\r
192 CriticalSection m_cskidq;
\r
193 MSLLHOOKSTRUCT m_msllHookCurrent;
\r
194 bool m_buttonPressed;
\r
196 InputHandler m_keyboardHandler;
\r
197 InputHandler m_mouseHandler;
\r
198 #endif // NO_DRIVER
\r
199 HANDLE m_readEvent; /** reading from mayu device
\r
200 has been completed */
\r
201 HANDLE m_interruptThreadEvent; /// interrupt thread event
\r
202 volatile InterruptThreadReason
\r
203 m_interruptThreadReason; /// interrupt thread reason
\r
204 OVERLAPPED m_ol; /** for async read/write of
\r
206 HANDLE m_hookPipe; /// named pipe for &SetImeString
\r
207 HMODULE m_sts4mayu; /// DLL module for ThumbSense
\r
208 HMODULE m_cts4mayu; /// DLL module for ThumbSense
\r
209 bool volatile m_doForceTerminate; /// terminate engine thread
\r
210 bool volatile m_isLogMode; /// is logging mode ?
\r
211 bool volatile m_isEnabled; /// is enabled ?
\r
212 bool volatile m_isSynchronizing; /// is synchronizing ?
\r
213 HANDLE m_eSync; /// event for synchronization
\r
214 int m_generateKeyboardEventsRecursionGuard; /** guard against too many
\r
217 // current key state
\r
218 Modifier m_currentLock; /// current lock key's state
\r
219 int m_currentKeyPressCount; /** how many keys are pressed
\r
221 int m_currentKeyPressCountOnWin32; /** how many keys are pressed
\r
223 Key *m_lastGeneratedKey; /// last generated key
\r
224 Key *m_lastPressedKey[2]; /// last pressed key
\r
225 ModifiedKey m_oneShotKey; /// one shot key
\r
226 unsigned int m_oneShotRepeatableRepeatCount; /// repeat count of one shot key
\r
227 bool m_isPrefix; /// is prefix ?
\r
228 bool m_doesIgnoreModifierForPrefix; /** does ignore modifier key
\r
230 bool m_doesEditNextModifier; /** does edit next user input
\r
231 key's modifier ? */
\r
232 Modifier m_modifierForNextKey; /** modifier for next key if
\r
235 /** current keymaps.
\r
237 <dt>when &OtherWindowClass
\r
238 <dd>currentKeymap becoms currentKeymaps[++ Current::i]
\r
239 <dt>when &KeymapParent
\r
240 <dd>currentKeymap becoms currentKeyamp->parentKeymap
\r
242 <dd>currentKeyamp becoms *Current::i
\r
245 const Keymap * volatile m_currentKeymap; /// current keymap
\r
246 FocusOfThreads /*volatile*/ m_focusOfThreads; ///
\r
247 FocusOfThread * volatile m_currentFocusOfThread; ///
\r
248 FocusOfThread m_globalFocus; ///
\r
249 HWND m_hwndFocus; /// current focus window
\r
250 DetachedThreadIds m_detachedThreadIds; ///
\r
253 KeymapPtrList m_keymapPrefixHistory; /// for &KeymapPrevPrefix
\r
254 EmacsEditKillLine m_emacsEditKillLine; /// for &EmacsEditKillLine
\r
255 const ActionFunction *m_afShellExecute; /// for &ShellExecute
\r
257 WindowPositions m_windowPositions; ///
\r
258 WindowsWithAlpha m_windowsWithAlpha; ///
\r
260 tstring m_helpMessage; /// for &HelpMessage
\r
261 tstring m_helpTitle; /// for &HelpMessage
\r
262 int m_variable; /// for &Variable,
\r
266 tomsgstream &m_log; /** log stream (output to log
\r
271 /// keyboard handler thread
\r
272 static unsigned int WINAPI keyboardDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam);
\r
273 /// mouse handler thread
\r
274 static unsigned int WINAPI mouseDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam);
\r
277 unsigned int keyboardDetour(KBDLLHOOKSTRUCT *i_kid);
\r
279 unsigned int mouseDetour(WPARAM i_message, MSLLHOOKSTRUCT *i_mid);
\r
281 unsigned int injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw);
\r
282 #endif // NO_DRIVER
\r
285 /// keyboard handler thread
\r
286 static unsigned int WINAPI keyboardHandler(void *i_this);
\r
288 void keyboardHandler();
\r
290 /// check focus window
\r
291 void checkFocusWindow();
\r
292 /// is modifier pressed ?
\r
293 bool isPressed(Modifier::Type i_mt);
\r
294 /// fix modifier key
\r
295 bool fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am);
\r
298 void outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
\r
301 /// genete modifier events
\r
302 void generateModifierEvents(const Modifier &i_mod);
\r
305 void generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event);
\r
307 /// generate keyboard event
\r
308 void generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign);
\r
310 void generateActionEvents(const Current &i_c, const Action *i_a,
\r
313 void generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
\r
316 void generateKeyboardEvents(const Current &i_c);
\r
318 void beginGeneratingKeyboardEvents(const Current &i_c, bool i_isModifier);
\r
320 /// pop all pressed key on win32
\r
321 void keyboardResetOnWin32();
\r
323 /// get current modifiers
\r
324 Modifier getCurrentModifiers(Key *i_key, bool i_isPressed);
\r
326 /// describe bindings
\r
327 void describeBindings();
\r
329 /// update m_lastPressedKey
\r
330 void updateLastPressedKey(Key *i_key);
\r
332 /// set current keymap
\r
333 void setCurrentKeymap(const Keymap *i_keymap,
\r
334 bool i_doesAddToHistory = false);
\r
335 /** open mayu device
\r
336 @return true if mayu device successfully is opened
\r
340 /// close mayu device
\r
343 /// load/unload [sc]ts4mayu.dll
\r
344 void manageTs4mayu(TCHAR *i_ts4mayuDllName, TCHAR *i_dependDllName,
\r
345 bool i_load, HMODULE *i_pTs4mayu);
\r
348 // BEGINING OF FUNCTION DEFINITION
\r
349 /// send a default key to Windows
\r
350 void funcDefault(FunctionParam *i_param);
\r
351 /// use a corresponding key of a parent keymap
\r
352 void funcKeymapParent(FunctionParam *i_param);
\r
353 /// use a corresponding key of a current window
\r
354 void funcKeymapWindow(FunctionParam *i_param);
\r
355 /// use a corresponding key of the previous prefixed keymap
\r
356 void funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous);
\r
357 /// use a corresponding key of an other window class, or use a default key
\r
358 void funcOtherWindowClass(FunctionParam *i_param);
\r
360 void funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
\r
361 BooleanType i_doesIgnoreModifiers = BooleanType_true);
\r
362 /// other keymap's key
\r
363 void funcKeymap(FunctionParam *i_param, const Keymap *i_keymap);
\r
365 void funcSync(FunctionParam *i_param);
\r
367 void funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
\r
368 ToggleType i_toggle = ToggleType_toggle);
\r
369 /// edit next user input key's modifier
\r
370 void funcEditNextModifier(FunctionParam *i_param,
\r
371 const Modifier &i_modifier);
\r
373 void funcVariable(FunctionParam *i_param, int i_mag, int i_inc);
\r
375 void funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
\r
377 /// undefined (bell)
\r
378 void funcUndefined(FunctionParam *i_param);
\r
380 void funcIgnore(FunctionParam *i_param);
\r
382 void funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
\r
383 UINT i_message, WPARAM i_wParam, LPARAM i_lParam);
\r
385 void funcShellExecute(FunctionParam *i_param, const StrExprArg &i_operation,
\r
386 const StrExprArg &i_file, const StrExprArg &i_parameters,
\r
387 const StrExprArg &i_directory,
\r
388 ShowCommandType i_showCommand);
\r
389 /// SetForegroundWindow
\r
390 void funcSetForegroundWindow(FunctionParam *i_param,
\r
391 const tregex &i_windowClassName,
\r
392 LogicalOperatorType i_logicalOp
\r
393 = LogicalOperatorType_and,
\r
394 const tregex &i_windowTitleName
\r
395 = tregex(_T(".*")));
\r
397 void funcLoadSetting(FunctionParam *i_param,
\r
398 const StrExprArg &i_name = StrExprArg());
\r
400 void funcVK(FunctionParam *i_param, VKey i_vkey);
\r
402 void funcWait(FunctionParam *i_param, int i_milliSecond);
\r
403 /// investigate WM_COMMAND, WM_SYSCOMMAND
\r
404 void funcInvestigateCommand(FunctionParam *i_param);
\r
405 /// show mayu dialog box
\r
406 void funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
\r
407 ShowCommandType i_showCommand);
\r
408 /// describe bindings
\r
409 void funcDescribeBindings(FunctionParam *i_param);
\r
410 /// show help message
\r
411 void funcHelpMessage(FunctionParam *i_param,
\r
412 const StrExprArg &i_title = StrExprArg(),
\r
413 const StrExprArg &i_message = StrExprArg());
\r
415 void funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title);
\r
417 void funcWindowRaise(FunctionParam *i_param,
\r
418 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
420 void funcWindowLower(FunctionParam *i_param,
\r
421 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
422 /// minimize window
\r
423 void funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt
\r
424 = TargetWindowType_overlapped);
\r
425 /// maximize window
\r
426 void funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
427 = TargetWindowType_overlapped);
\r
428 /// maximize window horizontally
\r
429 void funcWindowHMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
430 = TargetWindowType_overlapped);
\r
431 /// maximize window virtically
\r
432 void funcWindowVMaximize(FunctionParam *i_param, TargetWindowType i_twt
\r
433 = TargetWindowType_overlapped);
\r
434 /// maximize window virtically or horizontally
\r
435 void funcWindowHVMaximize(FunctionParam *i_param, BooleanType i_isHorizontal,
\r
436 TargetWindowType i_twt
\r
437 = TargetWindowType_overlapped);
\r
439 void funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
\r
440 TargetWindowType i_twt
\r
441 = TargetWindowType_overlapped);
\r
442 /// move window to ...
\r
443 void funcWindowMoveTo(FunctionParam *i_param, GravityType i_gravityType,
\r
444 int i_dx, int i_dy, TargetWindowType i_twt
\r
445 = TargetWindowType_overlapped);
\r
446 /// move window visibly
\r
447 void funcWindowMoveVisibly(FunctionParam *i_param,
\r
448 TargetWindowType i_twt
\r
449 = TargetWindowType_overlapped);
\r
450 /// move window to other monitor
\r
451 void funcWindowMonitorTo(FunctionParam *i_param,
\r
452 WindowMonitorFromType i_fromType, int i_monitor,
\r
453 BooleanType i_adjustPos = BooleanType_true,
\r
454 BooleanType i_adjustSize = BooleanType_false);
\r
455 /// move window to other monitor
\r
456 void funcWindowMonitor(FunctionParam *i_param, int i_monitor,
\r
457 BooleanType i_adjustPos = BooleanType_true,
\r
458 BooleanType i_adjustSize = BooleanType_false);
\r
460 void funcWindowClingToLeft(FunctionParam *i_param,
\r
461 TargetWindowType i_twt
\r
462 = TargetWindowType_overlapped);
\r
464 void funcWindowClingToRight(FunctionParam *i_param,
\r
465 TargetWindowType i_twt
\r
466 = TargetWindowType_overlapped);
\r
468 void funcWindowClingToTop(FunctionParam *i_param,
\r
469 TargetWindowType i_twt
\r
470 = TargetWindowType_overlapped);
\r
472 void funcWindowClingToBottom(FunctionParam *i_param,
\r
473 TargetWindowType i_twt
\r
474 = TargetWindowType_overlapped);
\r
476 void funcWindowClose(FunctionParam *i_param,
\r
477 TargetWindowType i_twt = TargetWindowType_overlapped);
\r
478 /// toggle top-most flag of the window
\r
479 void funcWindowToggleTopMost(FunctionParam *i_param);
\r
480 /// identify the window
\r
481 void funcWindowIdentify(FunctionParam *i_param);
\r
482 /// set alpha blending parameter to the window
\r
483 void funcWindowSetAlpha(FunctionParam *i_param, int i_alpha);
\r
484 /// redraw the window
\r
485 void funcWindowRedraw(FunctionParam *i_param);
\r
486 /// resize window to
\r
487 void funcWindowResizeTo(FunctionParam *i_param, int i_width, int i_height,
\r
488 TargetWindowType i_twt
\r
489 = TargetWindowType_overlapped);
\r
490 /// move the mouse cursor
\r
491 void funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy);
\r
492 /// send a mouse-wheel-message to Windows
\r
493 void funcMouseWheel(FunctionParam *i_param, int i_delta);
\r
494 /// convert the contents of the Clipboard to upper case or lower case
\r
495 void funcClipboardChangeCase(FunctionParam *i_param,
\r
496 BooleanType i_doesConvertToUpperCase);
\r
497 /// convert the contents of the Clipboard to upper case
\r
498 void funcClipboardUpcaseWord(FunctionParam *i_param);
\r
499 /// convert the contents of the Clipboard to lower case
\r
500 void funcClipboardDowncaseWord(FunctionParam *i_param);
\r
501 /// set the contents of the Clipboard to the string
\r
502 void funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text);
\r
504 void funcEmacsEditKillLinePred(FunctionParam *i_param,
\r
505 const KeySeq *i_keySeq1,
\r
506 const KeySeq *i_keySeq2);
\r
508 void funcEmacsEditKillLineFunc(FunctionParam *i_param);
\r
510 void funcLogClear(FunctionParam *i_param);
\r
512 void funcRecenter(FunctionParam *i_param);
\r
514 void funcDirectSSTP(FunctionParam *i_param,
\r
515 const tregex &i_name,
\r
516 const StrExprArg &i_protocol,
\r
517 const std::list<tstringq> &i_headers);
\r
519 void funcPlugIn(FunctionParam *i_param,
\r
520 const StrExprArg &i_dllName,
\r
521 const StrExprArg &i_funcName = StrExprArg(),
\r
522 const StrExprArg &i_funcParam = StrExprArg(),
\r
523 BooleanType i_doesCreateThread = BooleanType_false);
\r
524 /// set IME open status
\r
525 void funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle = ToggleType_toggle);
\r
526 /// set string to IME
\r
527 void funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data);
\r
528 /// enter to mouse event hook mode
\r
529 void funcMouseHook(FunctionParam *i_param, MouseHookType i_hookType, int i_hookParam);
\r
531 void funcCancelPrefix(FunctionParam *i_param);
\r
533 // END OF FUNCTION DEFINITION
\r
534 # define FUNCTION_FRIEND
\r
535 # include "functions.h"
\r
536 # undef FUNCTION_FRIEND
\r
540 Engine(tomsgstream &i_log);
\r
544 /// start/stop keyboard handler thread
\r
549 /// pause keyboard handler thread and close device
\r
552 /// resume keyboard handler thread and re-open device
\r
555 /// do some procedure before quit which must be done synchronously
\r
556 /// (i.e. not on WM_QUIT)
\r
557 bool prepairQuit();
\r
560 void enableLogMode(bool i_isLogMode = true) {
\r
561 m_isLogMode = i_isLogMode;
\r
564 void disableLogMode() {
\r
565 m_isLogMode = false;
\r
568 /// enable/disable engine
\r
569 void enable(bool i_isEnabled = true) {
\r
570 m_isEnabled = i_isEnabled;
\r
574 m_isEnabled = false;
\r
577 bool getIsEnabled() const {
\r
578 return m_isEnabled;
\r
581 /// associated window
\r
582 void setAssociatedWndow(HWND i_hwnd) {
\r
583 m_hwndAssocWindow = i_hwnd;
\r
586 /// associated window
\r
587 HWND getAssociatedWndow() const {
\r
588 return m_hwndAssocWindow;
\r
592 bool setSetting(Setting *i_setting);
\r
595 bool setFocus(HWND i_hwndFocus, DWORD i_threadId,
\r
596 const tstringi &i_className,
\r
597 const tstringi &i_titleName, bool i_isConsole);
\r
600 bool setLockState(bool i_isNumLockToggled, bool i_isCapsLockToggled,
\r
601 bool i_isScrollLockToggled, bool i_isKanaLockToggled,
\r
602 bool i_isImeLockToggled, bool i_isImeCompToggled);
\r
605 void checkShow(HWND i_hwnd);
\r
606 bool setShow(bool i_isMaximized, bool i_isMinimized, bool i_isMDI);
\r
611 /// thread detach notify
\r
612 bool threadDetachNotify(DWORD i_threadId);
\r
615 void shellExecute();
\r
617 /// get help message
\r
618 void getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle);
\r
621 void commandNotify(HWND i_hwnd, UINT i_message, WPARAM i_wParam,
\r
624 /// get current window class name
\r
625 const tstringi &getCurrentWindowClassName() const {
\r
626 return m_currentFocusOfThread->m_className;
\r
629 /// get current window title name
\r
630 const tstringi &getCurrentWindowTitleName() const {
\r
631 return m_currentFocusOfThread->m_titleName;
\r
634 /// get mayud version
\r
635 const tstring &getMayudVersion() const {
\r
636 return m_mayudVersion;
\r
642 class FunctionParam
\r
645 bool m_isPressed; /// is key pressed ?
\r
647 Engine::Current m_c; /// new context
\r
648 bool m_doesNeedEndl; /// need endl ?
\r
649 const ActionFunction *m_af; ///
\r
653 #endif // !_ENGINE_H
\r