1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 # include "multithread.h"
10 # include "msgstream.h"
18 WM_APP_engineNotify = WM_APP + 110,
25 EngineNotify_shellExecute, ///
26 EngineNotify_loadSetting, ///
27 EngineNotify_showDlg, ///
28 EngineNotify_helpMessage, ///
29 EngineNotify_setForegroundWindow, ///
30 EngineNotify_clearLog, ///
40 MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT = 64, ///
41 MAX_KEYMAP_PREFIX_HISTORY = 64, ///
44 typedef Keymaps::KeymapPtrList KeymapPtrList; ///
50 DWORD m_threadId; /// thread id
51 HWND m_hwndFocus; /** window that has focus on
53 tstringi m_className; /// class name of hwndFocus
54 tstringi m_titleName; /// title name of hwndFocus
55 bool m_isConsole; /// is hwndFocus console ?
56 KeymapPtrList m_keymaps; /// keymaps
60 FocusOfThread() : m_threadId(0), m_hwndFocus(NULL), m_isConsole(false) { }
62 typedef std::map<DWORD /*ThreadId*/, FocusOfThread> FocusOfThreads; ///
64 typedef std::list<DWORD /*ThreadId*/> DetachedThreadIds; ///
66 /// current status in generateKeyboardEvents
70 const Keymap *m_keymap; /// current keymap
71 ModifiedKey m_mkey; /// current processing key that user inputed
72 /// index in currentFocusOfThread->keymaps
73 Keymaps::KeymapPtrList::iterator m_i;
77 bool isPressed() const
78 { return m_mkey.m_modifier.isOn(Modifier::Type_Down); }
81 friend class FunctionParam;
92 class EmacsEditKillLine
94 tstring m_buf; /// previous kill-line contents
97 bool m_doForceReset; ///
101 HGLOBAL makeNewKillLineBuf(const _TCHAR *i_data, int *i_retval);
105 void reset() { m_buf.resize(0); }
106 /** EmacsEditKillLineFunc.
107 clear the contents of the clopboard
108 at that time, confirm if it is the result of the previous kill-line
111 /// EmacsEditKillLinePred
115 /// window positon for &WindowHMaximize, &WindowVMaximize
135 WindowPosition(HWND i_hwnd, const RECT &i_rc, Mode i_mode)
136 : m_hwnd(i_hwnd), m_rc(i_rc), m_mode(i_mode) { }
138 typedef std::list<WindowPosition> WindowPositions;
140 typedef std::list<HWND> WindowsWithAlpha; /// windows for &WindowSetAlpha
142 enum InterruptThreadReason
144 InterruptThreadReason_Terminate,
145 InterruptThreadReason_Pause,
146 InterruptThreadReason_Resume,
150 CriticalSection m_cs; /// criticalSection
153 HWND m_hwndAssocWindow; /** associated window (we post
155 Setting * volatile m_setting; /// setting
157 // engine thread state
158 HANDLE m_device; /// mayu device
159 bool m_didMayuStartDevice; /** Did the mayu start the
161 HANDLE m_threadEvent; /** 1. thread has been started
162 2. thread is about to end*/
163 HANDLE m_threadHandle;
165 tstring m_mayudVersion; /// version of mayud.sys
167 std::deque<KEYBOARD_INPUT_DATA> m_kidq;
168 CriticalSection m_cskidq;
170 HANDLE m_readEvent; /** reading from mayu device
171 has been completed */
172 HANDLE m_interruptThreadEvent; /// interrupt thread event
173 volatile InterruptThreadReason
174 m_interruptThreadReason; /// interrupt thread reason
175 OVERLAPPED m_ol; /** for async read/write of
177 HANDLE m_hookPipe; /// named pipe for &SetImeString
178 HMODULE m_sts4mayu; /// DLL module for ThumbSense
179 HMODULE m_cts4mayu; /// DLL module for ThumbSense
180 bool volatile m_doForceTerminate; /// terminate engine thread
181 bool volatile m_isLogMode; /// is logging mode ?
182 bool volatile m_isEnabled; /// is enabled ?
183 bool volatile m_isSynchronizing; /// is synchronizing ?
184 HANDLE m_eSync; /// event for synchronization
185 int m_generateKeyboardEventsRecursionGuard; /** guard against too many
189 Modifier m_currentLock; /// current lock key's state
190 int m_currentKeyPressCount; /** how many keys are pressed
192 int m_currentKeyPressCountOnWin32; /** how many keys are pressed
194 Key *m_lastGeneratedKey; /// last generated key
195 Key *m_lastPressedKey[2]; /// last pressed key
196 ModifiedKey m_oneShotKey; /// one shot key
197 unsigned int m_oneShotRepeatableRepeatCount; /// repeat count of one shot key
198 bool m_isPrefix; /// is prefix ?
199 bool m_doesIgnoreModifierForPrefix; /** does ignore modifier key
201 bool m_doesEditNextModifier; /** does edit next user input
203 Modifier m_modifierForNextKey; /** modifier for next key if
208 <dt>when &OtherWindowClass
209 <dd>currentKeymap becoms currentKeymaps[++ Current::i]
210 <dt>when &KeymapParent
211 <dd>currentKeymap becoms currentKeyamp->parentKeymap
213 <dd>currentKeyamp becoms *Current::i
216 const Keymap * volatile m_currentKeymap; /// current keymap
217 FocusOfThreads /*volatile*/ m_focusOfThreads; ///
218 FocusOfThread * volatile m_currentFocusOfThread; ///
219 FocusOfThread m_globalFocus; ///
220 HWND m_hwndFocus; /// current focus window
221 DetachedThreadIds m_detachedThreadIds; ///
224 KeymapPtrList m_keymapPrefixHistory; /// for &KeymapPrevPrefix
225 EmacsEditKillLine m_emacsEditKillLine; /// for &EmacsEditKillLine
226 const ActionFunction *m_afShellExecute; /// for &ShellExecute
228 WindowPositions m_windowPositions; ///
229 WindowsWithAlpha m_windowsWithAlpha; ///
231 tstring m_helpMessage; /// for &HelpMessage
232 tstring m_helpTitle; /// for &HelpMessage
233 int m_variable; /// for &Variable,
237 tomsgstream &m_log; /** log stream (output to log
242 /// keyboard handler thread
243 static unsigned int WINAPI keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid);
246 unsigned int keyboardDetour(KBDLLHOOKSTRUCT *i_kid);
248 unsigned int injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw);
252 /// keyboard handler thread
253 static unsigned int WINAPI keyboardHandler(void *i_this);
255 void keyboardHandler();
257 /// check focus window
258 void checkFocusWindow();
259 /// is modifier pressed ?
260 bool isPressed(Modifier::Type i_mt);
262 bool fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am);
265 void outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
268 /// genete modifier events
269 void generateModifierEvents(const Modifier &i_mod);
272 void generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event);
274 /// generate keyboard event
275 void generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign);
277 void generateActionEvents(const Current &i_c, const Action *i_a,
280 void generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
283 void generateKeyboardEvents(const Current &i_c);
285 void beginGeneratingKeyboardEvents(const Current &i_c, bool i_isModifier);
287 /// pop all pressed key on win32
288 void keyboardResetOnWin32();
290 /// get current modifiers
291 Modifier getCurrentModifiers(Key *i_key, bool i_isPressed);
293 /// describe bindings
294 void describeBindings();
296 /// update m_lastPressedKey
297 void updateLastPressedKey(Key *i_key);
299 /// set current keymap
300 void setCurrentKeymap(const Keymap *i_keymap,
301 bool i_doesAddToHistory = false);
303 @return true if mayu device successfully is opened
307 /// close mayu device
310 /// load/unload [sc]ts4mayu.dll
311 void manageTs4mayu(TCHAR *i_ts4mayuDllName, TCHAR *i_dependDllName,
312 bool i_load, HMODULE *i_pTs4mayu);
315 // BEGINING OF FUNCTION DEFINITION
316 /// send a default key to Windows
317 void funcDefault(FunctionParam *i_param);
318 /// use a corresponding key of a parent keymap
319 void funcKeymapParent(FunctionParam *i_param);
320 /// use a corresponding key of a current window
321 void funcKeymapWindow(FunctionParam *i_param);
322 /// use a corresponding key of the previous prefixed keymap
323 void funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous);
324 /// use a corresponding key of an other window class, or use a default key
325 void funcOtherWindowClass(FunctionParam *i_param);
327 void funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
328 BooleanType i_doesIgnoreModifiers = BooleanType_true);
329 /// other keymap's key
330 void funcKeymap(FunctionParam *i_param, const Keymap *i_keymap);
332 void funcSync(FunctionParam *i_param);
334 void funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
335 ToggleType i_toggle = ToggleType_toggle);
336 /// edit next user input key's modifier
337 void funcEditNextModifier(FunctionParam *i_param,
338 const Modifier &i_modifier);
340 void funcVariable(FunctionParam *i_param, int i_mag, int i_inc);
342 void funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
345 void funcUndefined(FunctionParam *i_param);
347 void funcIgnore(FunctionParam *i_param);
349 void funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
350 UINT i_message, WPARAM i_wParam, LPARAM i_lParam);
352 void funcShellExecute(FunctionParam *i_param, const StrExprArg &i_operation,
353 const StrExprArg &i_file, const StrExprArg &i_parameters,
354 const StrExprArg &i_directory,
355 ShowCommandType i_showCommand);
356 /// SetForegroundWindow
357 void funcSetForegroundWindow(FunctionParam *i_param,
358 const tregex &i_windowClassName,
359 LogicalOperatorType i_logicalOp
360 = LogicalOperatorType_and,
361 const tregex &i_windowTitleName
364 void funcLoadSetting(FunctionParam *i_param,
365 const StrExprArg &i_name = StrExprArg());
367 void funcVK(FunctionParam *i_param, VKey i_vkey);
369 void funcWait(FunctionParam *i_param, int i_milliSecond);
370 /// investigate WM_COMMAND, WM_SYSCOMMAND
371 void funcInvestigateCommand(FunctionParam *i_param);
372 /// show mayu dialog box
373 void funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
374 ShowCommandType i_showCommand);
375 /// describe bindings
376 void funcDescribeBindings(FunctionParam *i_param);
377 /// show help message
378 void funcHelpMessage(FunctionParam *i_param,
379 const StrExprArg &i_title = StrExprArg(),
380 const StrExprArg &i_message = StrExprArg());
382 void funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title);
384 void funcWindowRaise(FunctionParam *i_param,
385 TargetWindowType i_twt = TargetWindowType_overlapped);
387 void funcWindowLower(FunctionParam *i_param,
388 TargetWindowType i_twt = TargetWindowType_overlapped);
390 void funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt
391 = TargetWindowType_overlapped);
393 void funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt
394 = TargetWindowType_overlapped);
395 /// maximize window horizontally
396 void funcWindowHMaximize(FunctionParam *i_param, TargetWindowType i_twt
397 = TargetWindowType_overlapped);
398 /// maximize window virtically
399 void funcWindowVMaximize(FunctionParam *i_param, TargetWindowType i_twt
400 = TargetWindowType_overlapped);
401 /// maximize window virtically or horizontally
402 void funcWindowHVMaximize(FunctionParam *i_param, BooleanType i_isHorizontal,
403 TargetWindowType i_twt
404 = TargetWindowType_overlapped);
406 void funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
407 TargetWindowType i_twt
408 = TargetWindowType_overlapped);
409 /// move window to ...
410 void funcWindowMoveTo(FunctionParam *i_param, GravityType i_gravityType,
411 int i_dx, int i_dy, TargetWindowType i_twt
412 = TargetWindowType_overlapped);
413 /// move window visibly
414 void funcWindowMoveVisibly(FunctionParam *i_param,
415 TargetWindowType i_twt
416 = TargetWindowType_overlapped);
417 /// move window to other monitor
418 void funcWindowMonitorTo(FunctionParam *i_param,
419 WindowMonitorFromType i_fromType, int i_monitor,
420 BooleanType i_adjustPos = BooleanType_true,
421 BooleanType i_adjustSize = BooleanType_false);
422 /// move window to other monitor
423 void funcWindowMonitor(FunctionParam *i_param, int i_monitor,
424 BooleanType i_adjustPos = BooleanType_true,
425 BooleanType i_adjustSize = BooleanType_false);
427 void funcWindowClingToLeft(FunctionParam *i_param,
428 TargetWindowType i_twt
429 = TargetWindowType_overlapped);
431 void funcWindowClingToRight(FunctionParam *i_param,
432 TargetWindowType i_twt
433 = TargetWindowType_overlapped);
435 void funcWindowClingToTop(FunctionParam *i_param,
436 TargetWindowType i_twt
437 = TargetWindowType_overlapped);
439 void funcWindowClingToBottom(FunctionParam *i_param,
440 TargetWindowType i_twt
441 = TargetWindowType_overlapped);
443 void funcWindowClose(FunctionParam *i_param,
444 TargetWindowType i_twt = TargetWindowType_overlapped);
445 /// toggle top-most flag of the window
446 void funcWindowToggleTopMost(FunctionParam *i_param);
447 /// identify the window
448 void funcWindowIdentify(FunctionParam *i_param);
449 /// set alpha blending parameter to the window
450 void funcWindowSetAlpha(FunctionParam *i_param, int i_alpha);
451 /// redraw the window
452 void funcWindowRedraw(FunctionParam *i_param);
454 void funcWindowResizeTo(FunctionParam *i_param, int i_width, int i_height,
455 TargetWindowType i_twt
456 = TargetWindowType_overlapped);
457 /// move the mouse cursor
458 void funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy);
459 /// send a mouse-wheel-message to Windows
460 void funcMouseWheel(FunctionParam *i_param, int i_delta);
461 /// convert the contents of the Clipboard to upper case or lower case
462 void funcClipboardChangeCase(FunctionParam *i_param,
463 BooleanType i_doesConvertToUpperCase);
464 /// convert the contents of the Clipboard to upper case
465 void funcClipboardUpcaseWord(FunctionParam *i_param);
466 /// convert the contents of the Clipboard to lower case
467 void funcClipboardDowncaseWord(FunctionParam *i_param);
468 /// set the contents of the Clipboard to the string
469 void funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text);
471 void funcEmacsEditKillLinePred(FunctionParam *i_param,
472 const KeySeq *i_keySeq1,
473 const KeySeq *i_keySeq2);
475 void funcEmacsEditKillLineFunc(FunctionParam *i_param);
477 void funcLogClear(FunctionParam *i_param);
479 void funcRecenter(FunctionParam *i_param);
481 void funcDirectSSTP(FunctionParam *i_param,
482 const tregex &i_name,
483 const StrExprArg &i_protocol,
484 const std::list<tstringq> &i_headers);
486 void funcPlugIn(FunctionParam *i_param,
487 const StrExprArg &i_dllName,
488 const StrExprArg &i_funcName = StrExprArg(),
489 const StrExprArg &i_funcParam = StrExprArg(),
490 BooleanType i_doesCreateThread = BooleanType_false);
491 /// set IME open status
492 void funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle = ToggleType_toggle);
493 /// set string to IME
494 void funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data);
495 /// enter to mouse event hook mode
496 void funcMouseHook(FunctionParam *i_param, MouseHookType i_hookType, int i_hookParam);
498 // END OF FUNCTION DEFINITION
499 # define FUNCTION_FRIEND
500 # include "functions.h"
501 # undef FUNCTION_FRIEND
505 Engine(tomsgstream &i_log);
509 /// start/stop keyboard handler thread
514 /// pause keyboard handler thread and close device
517 /// resume keyboard handler thread and re-open device
520 /// do some procedure before quit which must be done synchronously
521 /// (i.e. not on WM_QUIT)
525 void enableLogMode(bool i_isLogMode = true) { m_isLogMode = i_isLogMode; }
527 void disableLogMode() { m_isLogMode = false; }
529 /// enable/disable engine
530 void enable(bool i_isEnabled = true) { m_isEnabled = i_isEnabled; }
532 void disable() { m_isEnabled = false; }
534 bool getIsEnabled() const { return m_isEnabled; }
536 /// associated window
537 void setAssociatedWndow(HWND i_hwnd) { m_hwndAssocWindow = i_hwnd; }
539 /// associated window
540 HWND getAssociatedWndow() const { return m_hwndAssocWindow; }
543 bool setSetting(Setting *i_setting);
546 bool setFocus(HWND i_hwndFocus, DWORD i_threadId,
547 const tstringi &i_className,
548 const tstringi &i_titleName, bool i_isConsole);
551 bool setLockState(bool i_isNumLockToggled, bool i_isCapsLockToggled,
552 bool i_isScrollLockToggled, bool i_isKanaLockToggled,
553 bool i_isImeLockToggled, bool i_isImeCompToggled);
556 void checkShow(HWND i_hwnd);
557 bool setShow(bool i_isMaximized, bool i_isMinimized, bool i_isMDI);
562 /// thread detach notify
563 bool threadDetachNotify(DWORD i_threadId);
569 void getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle);
572 void commandNotify(HWND i_hwnd, UINT i_message, WPARAM i_wParam,
575 /// get current window class name
576 const tstringi &getCurrentWindowClassName() const { return m_currentFocusOfThread->m_className; }
578 /// get current window title name
579 const tstringi &getCurrentWindowTitleName() const { return m_currentFocusOfThread->m_titleName; }
581 /// get mayud version
582 const tstring &getMayudVersion() const { return m_mayudVersion; }
590 bool m_isPressed; /// is key pressed ?
592 Engine::Current m_c; /// new context
593 bool m_doesNeedEndl; /// need endl ?
594 const ActionFunction *m_af; ///