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
168 std::deque<KEYBOARD_INPUT_DATA> m_kidq;
169 CriticalSection m_cskidq;
171 HANDLE m_readEvent; /** reading from mayu device
172 has been completed */
173 HANDLE m_interruptThreadEvent; /// interrupt thread event
174 volatile InterruptThreadReason
175 m_interruptThreadReason; /// interrupt thread reason
176 OVERLAPPED m_ol; /** for async read/write of
178 HANDLE m_hookPipe; /// named pipe for &SetImeString
179 HMODULE m_sts4mayu; /// DLL module for ThumbSense
180 HMODULE m_cts4mayu; /// DLL module for ThumbSense
182 bool volatile m_doForceTerminate; /// terminate engine thread
183 bool volatile m_isLogMode; /// is logging mode ?
184 bool volatile m_isEnabled; /// is enabled ?
185 bool volatile m_isSynchronizing; /// is synchronizing ?
186 HANDLE m_eSync; /// event for synchronization
187 int m_generateKeyboardEventsRecursionGuard; /** guard against too many
191 Modifier m_currentLock; /// current lock key's state
192 int m_currentKeyPressCount; /** how many keys are pressed
194 int m_currentKeyPressCountOnWin32; /** how many keys are pressed
196 Key *m_lastGeneratedKey; /// last generated key
197 Key *m_lastPressedKey[2]; /// last pressed key
198 ModifiedKey m_oneShotKey; /// one shot key
199 unsigned int m_oneShotRepeatableRepeatCount; /// repeat count of one shot key
200 bool m_isPrefix; /// is prefix ?
201 bool m_doesIgnoreModifierForPrefix; /** does ignore modifier key
203 bool m_doesEditNextModifier; /** does edit next user input
205 Modifier m_modifierForNextKey; /** modifier for next key if
210 <dt>when &OtherWindowClass
211 <dd>currentKeymap becoms currentKeymaps[++ Current::i]
212 <dt>when &KeymapParent
213 <dd>currentKeymap becoms currentKeyamp->parentKeymap
215 <dd>currentKeyamp becoms *Current::i
218 const Keymap * volatile m_currentKeymap; /// current keymap
219 FocusOfThreads /*volatile*/ m_focusOfThreads; ///
220 FocusOfThread * volatile m_currentFocusOfThread; ///
221 FocusOfThread m_globalFocus; ///
222 HWND m_hwndFocus; /// current focus window
223 DetachedThreadIds m_detachedThreadIds; ///
226 KeymapPtrList m_keymapPrefixHistory; /// for &KeymapPrevPrefix
227 EmacsEditKillLine m_emacsEditKillLine; /// for &EmacsEditKillLine
228 const ActionFunction *m_afShellExecute; /// for &ShellExecute
230 WindowPositions m_windowPositions; ///
231 WindowsWithAlpha m_windowsWithAlpha; ///
233 tstring m_helpMessage; /// for &HelpMessage
234 tstring m_helpTitle; /// for &HelpMessage
235 int m_variable; /// for &Variable,
239 tomsgstream &m_log; /** log stream (output to log
244 /// keyboard handler thread
245 static unsigned int WINAPI keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid);
248 unsigned int keyboardDetour(KBDLLHOOKSTRUCT *i_kid);
250 unsigned int injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw);
254 /// keyboard handler thread
255 static unsigned int WINAPI keyboardHandler(void *i_this);
257 void keyboardHandler();
259 /// check focus window
260 void checkFocusWindow();
261 /// is modifier pressed ?
262 bool isPressed(Modifier::Type i_mt);
264 bool fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am);
267 void outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
270 /// genete modifier events
271 void generateModifierEvents(const Modifier &i_mod);
274 void generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event);
276 /// generate keyboard event
277 void generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign);
279 void generateActionEvents(const Current &i_c, const Action *i_a,
282 void generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
285 void generateKeyboardEvents(const Current &i_c);
287 void beginGeneratingKeyboardEvents(const Current &i_c, bool i_isModifier);
289 /// pop all pressed key on win32
290 void keyboardResetOnWin32();
292 /// get current modifiers
293 Modifier getCurrentModifiers(Key *i_key, bool i_isPressed);
295 /// describe bindings
296 void describeBindings();
298 /// update m_lastPressedKey
299 void updateLastPressedKey(Key *i_key);
301 /// set current keymap
302 void setCurrentKeymap(const Keymap *i_keymap,
303 bool i_doesAddToHistory = false);
305 @return true if mayu device successfully is opened
309 /// close mayu device
312 /// load/unload [sc]ts4mayu.dll
313 void manageTs4mayu(TCHAR *i_ts4mayuDllName, TCHAR *i_dependDllName,
314 bool i_load, HMODULE *i_pTs4mayu);
317 // BEGINING OF FUNCTION DEFINITION
318 /// send a default key to Windows
319 void funcDefault(FunctionParam *i_param);
320 /// use a corresponding key of a parent keymap
321 void funcKeymapParent(FunctionParam *i_param);
322 /// use a corresponding key of a current window
323 void funcKeymapWindow(FunctionParam *i_param);
324 /// use a corresponding key of the previous prefixed keymap
325 void funcKeymapPrevPrefix(FunctionParam *i_param, int i_previous);
326 /// use a corresponding key of an other window class, or use a default key
327 void funcOtherWindowClass(FunctionParam *i_param);
329 void funcPrefix(FunctionParam *i_param, const Keymap *i_keymap,
330 BooleanType i_doesIgnoreModifiers = BooleanType_true);
331 /// other keymap's key
332 void funcKeymap(FunctionParam *i_param, const Keymap *i_keymap);
334 void funcSync(FunctionParam *i_param);
336 void funcToggle(FunctionParam *i_param, ModifierLockType i_lock,
337 ToggleType i_toggle = ToggleType_toggle);
338 /// edit next user input key's modifier
339 void funcEditNextModifier(FunctionParam *i_param,
340 const Modifier &i_modifier);
342 void funcVariable(FunctionParam *i_param, int i_mag, int i_inc);
344 void funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
347 void funcUndefined(FunctionParam *i_param);
349 void funcIgnore(FunctionParam *i_param);
351 void funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
352 UINT i_message, WPARAM i_wParam, LPARAM i_lParam);
354 void funcShellExecute(FunctionParam *i_param, const StrExprArg &i_operation,
355 const StrExprArg &i_file, const StrExprArg &i_parameters,
356 const StrExprArg &i_directory,
357 ShowCommandType i_showCommand);
358 /// SetForegroundWindow
359 void funcSetForegroundWindow(FunctionParam *i_param,
360 const tregex &i_windowClassName,
361 LogicalOperatorType i_logicalOp
362 = LogicalOperatorType_and,
363 const tregex &i_windowTitleName
366 void funcLoadSetting(FunctionParam *i_param,
367 const StrExprArg &i_name = StrExprArg());
369 void funcVK(FunctionParam *i_param, VKey i_vkey);
371 void funcWait(FunctionParam *i_param, int i_milliSecond);
372 /// investigate WM_COMMAND, WM_SYSCOMMAND
373 void funcInvestigateCommand(FunctionParam *i_param);
374 /// show mayu dialog box
375 void funcMayuDialog(FunctionParam *i_param, MayuDialogType i_dialog,
376 ShowCommandType i_showCommand);
377 /// describe bindings
378 void funcDescribeBindings(FunctionParam *i_param);
379 /// show help message
380 void funcHelpMessage(FunctionParam *i_param,
381 const StrExprArg &i_title = StrExprArg(),
382 const StrExprArg &i_message = StrExprArg());
384 void funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title);
386 void funcWindowRaise(FunctionParam *i_param,
387 TargetWindowType i_twt = TargetWindowType_overlapped);
389 void funcWindowLower(FunctionParam *i_param,
390 TargetWindowType i_twt = TargetWindowType_overlapped);
392 void funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt
393 = TargetWindowType_overlapped);
395 void funcWindowMaximize(FunctionParam *i_param, TargetWindowType i_twt
396 = TargetWindowType_overlapped);
397 /// maximize window horizontally
398 void funcWindowHMaximize(FunctionParam *i_param, TargetWindowType i_twt
399 = TargetWindowType_overlapped);
400 /// maximize window virtically
401 void funcWindowVMaximize(FunctionParam *i_param, TargetWindowType i_twt
402 = TargetWindowType_overlapped);
403 /// maximize window virtically or horizontally
404 void funcWindowHVMaximize(FunctionParam *i_param, BooleanType i_isHorizontal,
405 TargetWindowType i_twt
406 = TargetWindowType_overlapped);
408 void funcWindowMove(FunctionParam *i_param, int i_dx, int i_dy,
409 TargetWindowType i_twt
410 = TargetWindowType_overlapped);
411 /// move window to ...
412 void funcWindowMoveTo(FunctionParam *i_param, GravityType i_gravityType,
413 int i_dx, int i_dy, TargetWindowType i_twt
414 = TargetWindowType_overlapped);
415 /// move window visibly
416 void funcWindowMoveVisibly(FunctionParam *i_param,
417 TargetWindowType i_twt
418 = TargetWindowType_overlapped);
419 /// move window to other monitor
420 void funcWindowMonitorTo(FunctionParam *i_param,
421 WindowMonitorFromType i_fromType, int i_monitor,
422 BooleanType i_adjustPos = BooleanType_true,
423 BooleanType i_adjustSize = BooleanType_false);
424 /// move window to other monitor
425 void funcWindowMonitor(FunctionParam *i_param, int i_monitor,
426 BooleanType i_adjustPos = BooleanType_true,
427 BooleanType i_adjustSize = BooleanType_false);
429 void funcWindowClingToLeft(FunctionParam *i_param,
430 TargetWindowType i_twt
431 = TargetWindowType_overlapped);
433 void funcWindowClingToRight(FunctionParam *i_param,
434 TargetWindowType i_twt
435 = TargetWindowType_overlapped);
437 void funcWindowClingToTop(FunctionParam *i_param,
438 TargetWindowType i_twt
439 = TargetWindowType_overlapped);
441 void funcWindowClingToBottom(FunctionParam *i_param,
442 TargetWindowType i_twt
443 = TargetWindowType_overlapped);
445 void funcWindowClose(FunctionParam *i_param,
446 TargetWindowType i_twt = TargetWindowType_overlapped);
447 /// toggle top-most flag of the window
448 void funcWindowToggleTopMost(FunctionParam *i_param);
449 /// identify the window
450 void funcWindowIdentify(FunctionParam *i_param);
451 /// set alpha blending parameter to the window
452 void funcWindowSetAlpha(FunctionParam *i_param, int i_alpha);
453 /// redraw the window
454 void funcWindowRedraw(FunctionParam *i_param);
456 void funcWindowResizeTo(FunctionParam *i_param, int i_width, int i_height,
457 TargetWindowType i_twt
458 = TargetWindowType_overlapped);
459 /// move the mouse cursor
460 void funcMouseMove(FunctionParam *i_param, int i_dx, int i_dy);
461 /// send a mouse-wheel-message to Windows
462 void funcMouseWheel(FunctionParam *i_param, int i_delta);
463 /// convert the contents of the Clipboard to upper case or lower case
464 void funcClipboardChangeCase(FunctionParam *i_param,
465 BooleanType i_doesConvertToUpperCase);
466 /// convert the contents of the Clipboard to upper case
467 void funcClipboardUpcaseWord(FunctionParam *i_param);
468 /// convert the contents of the Clipboard to lower case
469 void funcClipboardDowncaseWord(FunctionParam *i_param);
470 /// set the contents of the Clipboard to the string
471 void funcClipboardCopy(FunctionParam *i_param, const StrExprArg &i_text);
473 void funcEmacsEditKillLinePred(FunctionParam *i_param,
474 const KeySeq *i_keySeq1,
475 const KeySeq *i_keySeq2);
477 void funcEmacsEditKillLineFunc(FunctionParam *i_param);
479 void funcLogClear(FunctionParam *i_param);
481 void funcRecenter(FunctionParam *i_param);
483 void funcDirectSSTP(FunctionParam *i_param,
484 const tregex &i_name,
485 const StrExprArg &i_protocol,
486 const std::list<tstringq> &i_headers);
488 void funcPlugIn(FunctionParam *i_param,
489 const StrExprArg &i_dllName,
490 const StrExprArg &i_funcName = StrExprArg(),
491 const StrExprArg &i_funcParam = StrExprArg(),
492 BooleanType i_doesCreateThread = BooleanType_false);
493 /// set IME open status
494 void funcSetImeStatus(FunctionParam *i_param, ToggleType i_toggle = ToggleType_toggle);
495 /// set string to IME
496 void funcSetImeString(FunctionParam *i_param, const StrExprArg &i_data);
497 /// enter to mouse event hook mode
498 void funcMouseHook(FunctionParam *i_param, MouseHookType i_hookType, int i_hookParam);
500 // END OF FUNCTION DEFINITION
501 # define FUNCTION_FRIEND
502 # include "functions.h"
503 # undef FUNCTION_FRIEND
507 Engine(tomsgstream &i_log);
511 /// start/stop keyboard handler thread
516 /// pause keyboard handler thread and close device
519 /// resume keyboard handler thread and re-open device
522 /// do some procedure before quit which must be done synchronously
523 /// (i.e. not on WM_QUIT)
527 void enableLogMode(bool i_isLogMode = true) { m_isLogMode = i_isLogMode; }
529 void disableLogMode() { m_isLogMode = false; }
531 /// enable/disable engine
532 void enable(bool i_isEnabled = true) { m_isEnabled = i_isEnabled; }
534 void disable() { m_isEnabled = false; }
536 bool getIsEnabled() const { return m_isEnabled; }
538 /// associated window
539 void setAssociatedWndow(HWND i_hwnd) { m_hwndAssocWindow = i_hwnd; }
541 /// associated window
542 HWND getAssociatedWndow() const { return m_hwndAssocWindow; }
545 bool setSetting(Setting *i_setting);
548 bool setFocus(HWND i_hwndFocus, DWORD i_threadId,
549 const tstringi &i_className,
550 const tstringi &i_titleName, bool i_isConsole);
553 bool setLockState(bool i_isNumLockToggled, bool i_isCapsLockToggled,
554 bool i_isScrollLockToggled, bool i_isKanaLockToggled,
555 bool i_isImeLockToggled, bool i_isImeCompToggled);
558 void checkShow(HWND i_hwnd);
559 bool setShow(bool i_isMaximized, bool i_isMinimized, bool i_isMDI);
564 /// thread detach notify
565 bool threadDetachNotify(DWORD i_threadId);
571 void getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle);
574 void commandNotify(HWND i_hwnd, UINT i_message, WPARAM i_wParam,
577 /// get current window class name
578 const tstringi &getCurrentWindowClassName() const { return m_currentFocusOfThread->m_className; }
580 /// get current window title name
581 const tstringi &getCurrentWindowTitleName() const { return m_currentFocusOfThread->m_titleName; }
583 /// get mayud version
584 const tstring &getMayudVersion() const { return m_mayudVersion; }
592 bool m_isPressed; /// is key pressed ?
594 Engine::Current m_c; /// new context
595 bool m_doesNeedEndl; /// need endl ?
596 const ActionFunction *m_af; ///