OSDN Git Service

delete Win9x/NT support code
[yamy/yamy.git] / engine.h
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // engine.h
3
4
5 #ifndef _ENGINE_H
6 #  define _ENGINE_H
7
8 #  include "multithread.h"
9 #  include "setting.h"
10 #  include "msgstream.h"
11 #  include <set>
12 #  include <queue>
13
14
15 enum
16 {
17   ///
18   WM_APP_engineNotify = WM_APP + 110,
19 };
20
21
22 ///
23 enum EngineNotify
24 {
25   EngineNotify_shellExecute,                    ///
26   EngineNotify_loadSetting,                     ///
27   EngineNotify_showDlg,                         ///
28   EngineNotify_helpMessage,                     ///
29   EngineNotify_setForegroundWindow,             ///
30   EngineNotify_clearLog,                        ///
31 };
32
33
34 ///
35 class Engine
36 {
37 private:
38   enum
39   {
40     MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT = 64, ///
41     MAX_KEYMAP_PREFIX_HISTORY = 64, ///
42   };
43
44   typedef Keymaps::KeymapPtrList KeymapPtrList; /// 
45   
46   /// focus of a thread
47   class FocusOfThread
48   {
49   public:
50     DWORD m_threadId;                           /// thread id
51     HWND m_hwndFocus;                           /** window that has focus on
52                                                     the thread */
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
57
58   public:
59     ///
60     FocusOfThread() : m_threadId(0), m_hwndFocus(NULL), m_isConsole(false) { }
61   };
62   typedef std::map<DWORD /*ThreadId*/, FocusOfThread> FocusOfThreads;   ///
63
64   typedef std::list<DWORD /*ThreadId*/> DetachedThreadIds;      ///
65
66   /// current status in generateKeyboardEvents
67   class Current
68   {
69   public:
70     const Keymap *m_keymap;                     /// current keymap
71     ModifiedKey m_mkey;         /// current processing key that user inputed
72                                 /// index in currentFocusOfThread-&gt;keymaps
73     Keymaps::KeymapPtrList::iterator m_i;
74
75   public:
76     ///
77     bool isPressed() const
78     { return m_mkey.m_modifier.isOn(Modifier::Type_Down); }
79   };
80
81   friend class FunctionParam;
82   
83   /// part of keySeq
84   enum Part
85   {
86     Part_all,                                   ///
87     Part_up,                                    ///
88     Part_down,                                  ///
89   };
90
91   ///
92   class EmacsEditKillLine
93   {
94     tstring m_buf;      /// previous kill-line contents
95
96   public:
97     bool m_doForceReset;        ///
98   
99   private:
100     ///
101     HGLOBAL makeNewKillLineBuf(const _TCHAR *i_data, int *i_retval);
102
103   public:
104     ///
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
109     */
110     void func();
111     /// EmacsEditKillLinePred
112     int pred();
113   };
114
115   /// window positon for &amp;WindowHMaximize, &amp;WindowVMaximize
116   class WindowPosition
117   {
118   public:
119     ///
120     enum Mode
121     {
122       Mode_normal,                              ///
123       Mode_H,                                   ///
124       Mode_V,                                   ///
125       Mode_HV,                                  ///
126     };
127
128   public:
129     HWND m_hwnd;                                ///
130     RECT m_rc;                                  ///
131     Mode m_mode;                                ///
132
133   public:
134     ///
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) { }
137   };
138   typedef std::list<WindowPosition> WindowPositions;
139
140   typedef std::list<HWND> WindowsWithAlpha; /// windows for &amp;WindowSetAlpha
141
142   enum InterruptThreadReason
143   {
144     InterruptThreadReason_Terminate,
145     InterruptThreadReason_Pause,
146     InterruptThreadReason_Resume,
147   };
148
149 private:
150   CriticalSection m_cs;                         /// criticalSection
151   
152   // setting
153   HWND m_hwndAssocWindow;                       /** associated window (we post
154                                                     message to it) */
155   Setting * volatile m_setting;                 /// setting
156   
157   // engine thread state
158   HANDLE m_device;                              /// mayu device
159   bool m_didMayuStartDevice;                    /** Did the mayu start the
160                                                     mayu-device ? */
161   HANDLE m_threadEvent;                         /** 1. thread has been started
162                                                     2. thread is about to end*/
163   HANDLE m_threadHandle;
164   unsigned m_threadId;
165   tstring m_mayudVersion;                       /// version of mayud.sys
166 #ifdef NO_DRIVER
167   std::deque<KEYBOARD_INPUT_DATA> m_kidq;
168   CriticalSection m_cskidq;
169 #endif // NO_DRIVER
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
176                                                     mayu device */
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
186                                                     recursion */
187   
188   // current key state
189   Modifier m_currentLock;                       /// current lock key's state
190   int m_currentKeyPressCount;                   /** how many keys are pressed
191                                                     phisically ? */
192   int m_currentKeyPressCountOnWin32;            /** how many keys are pressed
193                                                     on win32 ? */
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
200                                                     when prefixed ? */
201   bool m_doesEditNextModifier;                  /** does edit next user input
202                                                     key's modifier ? */
203   Modifier m_modifierForNextKey;                /** modifier for next key if
204                                                     above is true */
205
206   /** current keymaps.
207       <dl>
208       <dt>when &amp;OtherWindowClass
209       <dd>currentKeymap becoms currentKeymaps[++ Current::i]
210       <dt>when &amp;KeymapParent
211       <dd>currentKeymap becoms currentKeyamp-&gt;parentKeymap
212       <dt>other
213       <dd>currentKeyamp becoms *Current::i
214       </dl>
215   */
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;        ///
222   
223   // for functions
224   KeymapPtrList m_keymapPrefixHistory;          /// for &amp;KeymapPrevPrefix
225   EmacsEditKillLine m_emacsEditKillLine;        /// for &amp;EmacsEditKillLine
226   const ActionFunction *m_afShellExecute;       /// for &amp;ShellExecute
227   
228   WindowPositions m_windowPositions;            ///
229   WindowsWithAlpha m_windowsWithAlpha;          ///
230   
231   tstring m_helpMessage;                        /// for &amp;HelpMessage
232   tstring m_helpTitle;                          /// for &amp;HelpMessage
233   int m_variable;                               /// for &amp;Variable,
234                                                 ///  &amp;Repeat
235
236 public:
237   tomsgstream &m_log;                           /** log stream (output to log
238                                                     dialog's edit) */
239   
240 public:
241 #ifdef NO_DRIVER
242   /// keyboard handler thread
243   static unsigned int WINAPI keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid);
244 private:
245   ///
246   unsigned int keyboardDetour(KBDLLHOOKSTRUCT *i_kid);
247   ///
248   unsigned int injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw);
249 #endif // NO_DRIVER
250   
251 private:
252   /// keyboard handler thread
253   static unsigned int WINAPI keyboardHandler(void *i_this);
254   ///
255   void keyboardHandler();
256
257   /// check focus window
258   void checkFocusWindow();
259   /// is modifier pressed ?
260   bool isPressed(Modifier::Type i_mt);
261   /// fix modifier key
262   bool fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am);
263
264   /// output to log
265   void outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
266                    int i_debugLevel);
267
268   /// genete modifier events
269   void generateModifierEvents(const Modifier &i_mod);
270   
271   /// genete event
272   void generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event);
273   
274   /// generate keyboard event
275   void generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign);
276   ///
277   void generateActionEvents(const Current &i_c, const Action *i_a,
278                             bool i_doPress);
279   ///
280   void generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
281                             Part i_part);
282   ///
283   void generateKeyboardEvents(const Current &i_c);
284   ///
285   void beginGeneratingKeyboardEvents(const Current &i_c, bool i_isModifier);
286   
287   /// pop all pressed key on win32
288   void keyboardResetOnWin32();
289   
290   /// get current modifiers
291   Modifier getCurrentModifiers(Key *i_key, bool i_isPressed);
292
293   /// describe bindings
294   void describeBindings();
295
296   /// update m_lastPressedKey
297   void updateLastPressedKey(Key *i_key);
298
299   /// set current keymap
300   void setCurrentKeymap(const Keymap *i_keymap,
301                         bool i_doesAddToHistory = false);
302   /** open mayu device
303       @return true if mayu device successfully is opened
304   */
305   bool open();
306
307   /// close mayu device
308   void close();
309
310   /// load/unload [sc]ts4mayu.dll
311   void manageTs4mayu(TCHAR *i_ts4mayuDllName, TCHAR *i_dependDllName,
312                      bool i_load, HMODULE *i_pTs4mayu);
313
314 private:
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);
326   /// prefix key
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);
331   /// sync
332   void funcSync(FunctionParam *i_param);
333   /// toggle lock
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);
339   /// variable
340   void funcVariable(FunctionParam *i_param, int i_mag, int i_inc);
341   /// repeat N times
342   void funcRepeat(FunctionParam *i_param, const KeySeq *i_keySeq,
343                   int i_max = 10);
344   /// undefined (bell)
345   void funcUndefined(FunctionParam *i_param);
346   /// ignore
347   void funcIgnore(FunctionParam *i_param);
348   /// post message
349   void funcPostMessage(FunctionParam *i_param, ToWindowType i_window,
350                        UINT i_message, WPARAM i_wParam, LPARAM i_lParam);
351   /// ShellExecute
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
362                                = tregex(_T(".*")));
363   /// load setting
364   void funcLoadSetting(FunctionParam *i_param,
365                        const StrExprArg &i_name = StrExprArg());
366   /// virtual key
367   void funcVK(FunctionParam *i_param, VKey i_vkey);
368   /// wait
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());
381   /// show variable
382   void funcHelpVariable(FunctionParam *i_param, const StrExprArg &i_title);
383   /// raise window
384   void funcWindowRaise(FunctionParam *i_param,
385                        TargetWindowType i_twt = TargetWindowType_overlapped);
386   /// lower window
387   void funcWindowLower(FunctionParam *i_param, 
388                        TargetWindowType i_twt = TargetWindowType_overlapped);
389   /// minimize window
390   void funcWindowMinimize(FunctionParam *i_param, TargetWindowType i_twt
391                           = TargetWindowType_overlapped);
392   /// maximize window
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);
405   /// move window
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);
426   ///
427   void funcWindowClingToLeft(FunctionParam *i_param, 
428                              TargetWindowType i_twt
429                              = TargetWindowType_overlapped);
430   ///
431   void funcWindowClingToRight(FunctionParam *i_param, 
432                               TargetWindowType i_twt
433                               = TargetWindowType_overlapped);
434   ///
435   void funcWindowClingToTop(FunctionParam *i_param, 
436                             TargetWindowType i_twt
437                             = TargetWindowType_overlapped);
438   ///
439   void funcWindowClingToBottom(FunctionParam *i_param, 
440                                TargetWindowType i_twt
441                                = TargetWindowType_overlapped);
442   /// close window
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);
453   /// resize window to
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);
470   ///
471   void funcEmacsEditKillLinePred(FunctionParam *i_param,
472                                  const KeySeq *i_keySeq1,
473                                  const KeySeq *i_keySeq2);
474   ///
475   void funcEmacsEditKillLineFunc(FunctionParam *i_param);
476   /// clear log
477   void funcLogClear(FunctionParam *i_param);
478   /// recenter
479   void funcRecenter(FunctionParam *i_param);
480   /// Direct SSTP
481   void funcDirectSSTP(FunctionParam *i_param,
482                       const tregex &i_name,
483                       const StrExprArg &i_protocol,
484                       const std::list<tstringq> &i_headers);
485   /// PlugIn
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);
497
498   // END OF FUNCTION DEFINITION
499 #  define FUNCTION_FRIEND
500 #  include "functions.h"
501 #  undef FUNCTION_FRIEND
502   
503 public:
504   ///
505   Engine(tomsgstream &i_log);
506   ///
507   ~Engine();
508
509   /// start/stop keyboard handler thread
510   void start();
511   ///
512   void stop();
513
514   /// pause keyboard handler thread and close device
515   bool pause();
516   
517   /// resume keyboard handler thread and re-open device
518   bool resume();
519
520   /// do some procedure before quit which must be done synchronously
521   /// (i.e. not on WM_QUIT)
522   bool prepairQuit();
523
524   /// logging mode
525   void enableLogMode(bool i_isLogMode = true) { m_isLogMode = i_isLogMode; }
526   ///
527   void disableLogMode() { m_isLogMode = false; }
528   
529   /// enable/disable engine
530   void enable(bool i_isEnabled = true) { m_isEnabled = i_isEnabled; }
531   ///
532   void disable() { m_isEnabled = false; }
533   ///
534   bool getIsEnabled() const { return m_isEnabled; }
535
536   /// associated window
537   void setAssociatedWndow(HWND i_hwnd) { m_hwndAssocWindow = i_hwnd; }
538   
539   /// associated window
540   HWND getAssociatedWndow() const { return m_hwndAssocWindow; }
541   
542   /// setting
543   bool setSetting(Setting *i_setting);
544
545   /// focus
546   bool setFocus(HWND i_hwndFocus, DWORD i_threadId,
547                 const tstringi &i_className,
548                 const tstringi &i_titleName, bool i_isConsole);
549
550   /// lock state
551   bool setLockState(bool i_isNumLockToggled, bool i_isCapsLockToggled,
552                     bool i_isScrollLockToggled, bool i_isKanaLockToggled,
553                     bool i_isImeLockToggled, bool i_isImeCompToggled);
554
555   /// show
556   void checkShow(HWND i_hwnd);
557   bool setShow(bool i_isMaximized, bool i_isMinimized, bool i_isMDI);
558
559   /// sync
560   bool syncNotify();
561
562   /// thread detach notify
563   bool threadDetachNotify(DWORD i_threadId);
564
565   /// shell execute
566   void shellExecute();
567   
568   /// get help message
569   void getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle);
570
571   /// command notify
572   void commandNotify(HWND i_hwnd, UINT i_message, WPARAM i_wParam,
573                      LPARAM i_lParam);
574
575   /// get current window class name
576   const tstringi &getCurrentWindowClassName() const { return m_currentFocusOfThread->m_className; }
577
578   /// get current window title name
579   const tstringi &getCurrentWindowTitleName() const { return m_currentFocusOfThread->m_titleName; }
580
581   /// get mayud version
582   const tstring &getMayudVersion() const { return m_mayudVersion; }
583 };
584
585
586 ///
587 class FunctionParam
588 {
589 public:
590   bool m_isPressed;                             /// is key pressed ?
591   HWND m_hwnd;                                  /// 
592   Engine::Current m_c;                          /// new context
593   bool m_doesNeedEndl;                          /// need endl ?
594   const ActionFunction *m_af;                   /// 
595 };
596
597
598 #endif // !_ENGINE_H