OSDN Git Service

enable command notify on x64
[yamy/yamy.git] / keyboard.h
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // keyboard.h\r
3 \r
4 \r
5 #ifndef _KEYBOARD_H\r
6 #  define _KEYBOARD_H\r
7 \r
8 #  include "misc.h"\r
9 #  include "driver.h"\r
10 #  include "stringtool.h"\r
11 #  include <vector>\r
12 #  include <list>\r
13 #  include <map>\r
14 \r
15 \r
16 /// a scan code with flags\r
17 class ScanCode\r
18 {\r
19 public:\r
20         ///\r
21         enum {\r
22                 BREAK = KEYBOARD_INPUT_DATA::BREAK,             /// key release flag\r
23                 E0    = KEYBOARD_INPUT_DATA::E0,                /// extended key flag\r
24                 E1    = KEYBOARD_INPUT_DATA::E1,                /// extended key flag\r
25                 E0E1  = KEYBOARD_INPUT_DATA::E0E1,              /// extended key flag\r
26         };\r
27 \r
28 public:\r
29         USHORT m_scan;                          ///\r
30         USHORT m_flags;                         ///\r
31 \r
32 public:\r
33         ///\r
34         ScanCode() : m_scan(0), m_flags(0) { }\r
35         ///\r
36         ScanCode(USHORT i_scan, USHORT i_flags)\r
37                         : m_scan(i_scan), m_flags(i_flags) { }\r
38         ///\r
39         bool operator==(const ScanCode &i_sc) const {\r
40                 return (m_scan == i_sc.m_scan &&\r
41                                 (E0E1 & m_flags) == (E0E1 & i_sc.m_flags));\r
42         }\r
43         ///\r
44         bool operator!=(const ScanCode &i_sc) const {\r
45                 return !(*this == i_sc);\r
46         }\r
47 };\r
48 \r
49 \r
50 /// a key\r
51 class Key\r
52 {\r
53 public:\r
54         enum {\r
55                 ///\r
56                 MAX_SCAN_CODES_SIZE = 4,\r
57         };\r
58 \r
59 private:\r
60         ///\r
61         typedef std::vector<tstringi> Names;\r
62 \r
63 public:\r
64         /// if this key pressed physically\r
65         bool m_isPressed;\r
66         /// if this key pressed on Win32\r
67         bool m_isPressedOnWin32;\r
68         /// if this key pressed by assign\r
69         bool m_isPressedByAssign;\r
70 \r
71 private:\r
72         /// key name\r
73         Names m_names;\r
74         /// key scan code length\r
75         size_t m_scanCodesSize;\r
76         /// key scan code\r
77         ScanCode m_scanCodes[MAX_SCAN_CODES_SIZE];\r
78 \r
79 public:\r
80         ///\r
81         Key()\r
82                         : m_isPressed(false),\r
83                         m_isPressedOnWin32(false),\r
84                         m_isPressedByAssign(false),\r
85                         m_scanCodesSize(0) { }\r
86 \r
87         /// for Event::* only\r
88         Key(const tstringi &i_name)\r
89                         : m_isPressed(false),\r
90                         m_isPressedOnWin32(false),\r
91                         m_isPressedByAssign(false),\r
92                         m_scanCodesSize(0) {\r
93                 addName(i_name);\r
94                 addScanCode(ScanCode());\r
95         }\r
96 \r
97         /// get key name (first name)\r
98         const tstringi &getName() const {\r
99                 return m_names.front();\r
100         }\r
101 \r
102         /// get scan codes\r
103         const ScanCode *getScanCodes() const {\r
104                 return m_scanCodes;\r
105         }\r
106         ///\r
107         size_t getScanCodesSize() const {\r
108                 return m_scanCodesSize;\r
109         }\r
110 \r
111         /// add a name of key\r
112         void addName(const tstringi &i_name);\r
113 \r
114         /// add a scan code\r
115         void addScanCode(const ScanCode &i_sc);\r
116 \r
117         /// initializer\r
118         Key &initialize();\r
119 \r
120         /// equation by name\r
121         bool operator==(const tstringi &i_name) const;\r
122         ///\r
123         bool operator!=(const tstringi &i_name) const {\r
124                 return !(*this == i_name);\r
125         }\r
126 \r
127         /// is the scan code of this key ?\r
128         bool isSameScanCode(const Key &i_key) const;\r
129 \r
130         /// is the i_key's scan code the prefix of this key's scan code ?\r
131         bool isPrefixScanCode(const Key &i_key) const;\r
132 \r
133         /// stream output\r
134         friend tostream &operator<<(tostream &i_ost, const Key &i_key);\r
135 \r
136         /// <\r
137         bool operator<(const Key &i_key) const {\r
138                 return getName() < i_key.getName();\r
139         }\r
140 };\r
141 \r
142 \r
143 ///\r
144 class Modifier\r
145 {\r
146         ///\r
147         typedef u_int64 MODIFIERS;\r
148         ///\r
149         MODIFIERS m_modifiers;\r
150         ///\r
151         MODIFIERS m_dontcares;\r
152 \r
153 public:\r
154         ///\r
155         enum Type {\r
156                 Type_begin = 0,                         ///\r
157 \r
158                 Type_Shift = Type_begin,                        /// &lt;BASIC_MODIFIER&gt;\r
159                 Type_Alt,                                       /// &lt;BASIC_MODIFIER&gt;\r
160                 Type_Control,                           /// &lt;BASIC_MODIFIER&gt;\r
161                 Type_Windows,                           /// &lt;BASIC_MODIFIER&gt;\r
162                 Type_BASIC,                                     ///\r
163 \r
164                 Type_Up = Type_BASIC,                   /// &lt;KEYSEQ_MODIFIER&gt;\r
165                 Type_Down,                                      /// &lt;KEYSEQ_MODIFIER&gt;\r
166                 Type_KEYSEQ,                            ///\r
167 \r
168                 Type_Repeat = Type_KEYSEQ,                      /// &lt;ASSIGN_MODIFIER&gt;\r
169                 Type_ImeLock,                           /// &lt;ASSIGN_MODIFIER&gt;\r
170                 Type_ImeComp,                           /// &lt;ASSIGN_MODIFIER&gt;\r
171                 Type_NumLock,                           /// &lt;ASSIGN_MODIFIER&gt;\r
172                 Type_CapsLock,                          /// &lt;ASSIGN_MODIFIER&gt;\r
173                 Type_ScrollLock,                                /// &lt;ASSIGN_MODIFIER&gt;\r
174                 Type_KanaLock,                          /// &lt;ASSIGN_MODIFIER&gt;\r
175                 Type_Maximized,                         /// &lt;ASSIGN_MODIFIER&gt;\r
176                 Type_Minimized,                         /// &lt;ASSIGN_MODIFIER&gt;\r
177                 Type_MdiMaximized,                              /// &lt;ASSIGN_MODIFIER&gt;\r
178                 Type_MdiMinimized,                              /// &lt;ASSIGN_MODIFIER&gt;\r
179                 Type_Touchpad,                          /// &lt;ASSIGN_MODIFIER&gt;\r
180                 Type_TouchpadSticky,                    /// &lt;ASSIGN_MODIFIER&gt;\r
181                 Type_Mod0,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
182                 Type_Mod1,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
183                 Type_Mod2,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
184                 Type_Mod3,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
185                 Type_Mod4,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
186                 Type_Mod5,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
187                 Type_Mod6,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
188                 Type_Mod7,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
189                 Type_Mod8,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
190                 Type_Mod9,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
191                 Type_Lock0,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
192                 Type_Lock1,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
193                 Type_Lock2,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
194                 Type_Lock3,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
195                 Type_Lock4,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
196                 Type_Lock5,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
197                 Type_Lock6,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
198                 Type_Lock7,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
199                 Type_Lock8,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
200                 Type_Lock9,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
201                 Type_ASSIGN,                            ///\r
202 \r
203                 Type_end = Type_ASSIGN                  ///\r
204         };\r
205 \r
206 public:\r
207         ///\r
208         Modifier();\r
209         ///\r
210         Modifier &on(Type i_type) {\r
211                 return press(i_type);\r
212         }\r
213         ///\r
214         Modifier &off(Type i_type) {\r
215                 return release(i_type);\r
216         }\r
217         ///\r
218         Modifier &press(Type i_type) {\r
219                 m_modifiers |= ((MODIFIERS(1)) << i_type);\r
220                 return care(i_type);\r
221         }\r
222         ///\r
223         Modifier &release(Type i_type) {\r
224                 m_modifiers &= ~((MODIFIERS(1)) << i_type);\r
225                 return care(i_type);\r
226         }\r
227         ///\r
228         Modifier &care(Type i_type) {\r
229                 m_dontcares &= ~((MODIFIERS(1)) << i_type);\r
230                 return *this;\r
231         }\r
232         ///\r
233         Modifier &dontcare(Type i_type) {\r
234                 m_dontcares |= ((MODIFIERS(1)) << i_type);\r
235                 return *this;\r
236         }\r
237         /// set all modifiers to dontcare\r
238         Modifier &dontcare() {\r
239                 m_dontcares = ~MODIFIERS(0);\r
240                 return *this;\r
241         }\r
242 \r
243         ///\r
244         Modifier &on(Type i_type, bool i_isOn) {\r
245                 return press(i_type, i_isOn);\r
246         }\r
247         ///\r
248         Modifier &press(Type i_type, bool i_isPressed) {\r
249                 return i_isPressed ? press(i_type) : release(i_type);\r
250         }\r
251         ///\r
252         Modifier &care(Type i_type, bool i_doCare) {\r
253                 return i_doCare ? care(i_type) : dontcare(i_type);\r
254         }\r
255 \r
256         ///\r
257         bool operator==(const Modifier &i_m) const {\r
258                 return m_modifiers == i_m.m_modifiers && m_dontcares == i_m.m_dontcares;\r
259         }\r
260 \r
261         /// add m's modifiers where this dontcare\r
262         void add(const Modifier &i_m);\r
263         //Modifier &operator+=(const Modifier &i_m);\r
264 \r
265         /** does match. (except dontcare modifiers) (is the m included in the *this\r
266             set ?) */\r
267         bool doesMatch(const Modifier &i_m) const {\r
268                 return ((m_modifiers | m_dontcares) == (i_m.m_modifiers | m_dontcares));\r
269         }\r
270 \r
271         ///\r
272         bool isOn(Type i_type) const {\r
273                 return isPressed(i_type);\r
274         }\r
275         ///\r
276         bool isPressed(Type i_type) const {\r
277                 return !!(m_modifiers & ((MODIFIERS(1)) << i_type));\r
278         }\r
279         ///\r
280         bool isDontcare(Type i_type) const {\r
281                 return !!(m_dontcares & ((MODIFIERS(1)) << i_type));\r
282         }\r
283 \r
284         /// stream output\r
285         friend tostream &operator<<(tostream &i_ost, const Modifier &i_m);\r
286 \r
287         /// <\r
288         bool operator<(const Modifier &i_m) const {\r
289                 return m_modifiers < i_m.m_modifiers ||\r
290                            (m_modifiers == i_m.m_modifiers && m_dontcares < i_m.m_dontcares);\r
291         }\r
292 };\r
293 \r
294 \r
295 /// stream output\r
296 tostream &operator<<(tostream &i_ost, Modifier::Type i_type);\r
297 \r
298 \r
299 ///\r
300 class ModifiedKey\r
301 {\r
302 public:\r
303         Modifier m_modifier;    ///\r
304         Key *m_key;             ///\r
305 \r
306 public:\r
307         ///\r
308         ModifiedKey() : m_key(NULL) { }\r
309         ///\r
310         ModifiedKey(Key *i_key) : m_key(i_key) { }\r
311         ///\r
312         ModifiedKey(const Modifier &i_modifier, Key *i_key)\r
313                         : m_modifier(i_modifier), m_key(i_key) { }\r
314         ///\r
315         bool operator==(const ModifiedKey &i_mk) const {\r
316                 return m_modifier == i_mk.m_modifier && m_key == i_mk.m_key;\r
317         }\r
318         ///\r
319         bool operator!=(const ModifiedKey &i_mk) const {\r
320                 return !operator==(i_mk);\r
321         }\r
322 \r
323         /// stream output\r
324         friend tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk);\r
325 \r
326         /// <\r
327         bool operator<(const ModifiedKey &i_mk) const {\r
328                 return *m_key < *i_mk.m_key ||\r
329                            (!(*i_mk.m_key < *m_key) && m_modifier < i_mk.m_modifier);\r
330         }\r
331 };\r
332 \r
333 \r
334 ///\r
335 class Keyboard\r
336 {\r
337 public:\r
338         /// keyboard modifiers (pointer into Keys)\r
339         typedef std::list<Key *> Mods;\r
340 \r
341 private:\r
342         /** keyboard keys (hashed by first scan code).\r
343             Keys must be *list* of Key.\r
344             Because *pointers* into Keys exist anywhere in this program, the address\r
345             of Key's elements must be fixed.  */\r
346         enum {\r
347                 HASHED_KEYS_SIZE = 128,                 ///\r
348         };\r
349         typedef std::list<Key> Keys;                    ///\r
350         typedef std::map<tstringi, Key *> Aliases;      /// key name aliases\r
351         ///\r
352         class Substitute\r
353         {\r
354         public:\r
355                 ModifiedKey m_mkeyFrom;\r
356                 ModifiedKey m_mkeyTo;\r
357         public:\r
358                 Substitute(const ModifiedKey &i_mkeyFrom,\r
359                                    const ModifiedKey &i_mkeyTo)\r
360                                 : m_mkeyFrom(i_mkeyFrom), m_mkeyTo(i_mkeyTo) {\r
361                 }\r
362         };\r
363         typedef std::list<Substitute> Substitutes;      /// substitutes\r
364 \r
365 private:\r
366         Keys m_hashedKeys[HASHED_KEYS_SIZE];            ///\r
367         Aliases m_aliases;                              ///\r
368         Substitutes m_substitutes;                      ///\r
369         Key m_syncKey;                          /// key used to synchronize\r
370 \r
371 private:\r
372         ///\r
373         Mods m_mods[Modifier::Type_BASIC];\r
374 \r
375 public:\r
376         ///\r
377         class KeyIterator\r
378         {\r
379                 ///\r
380                 Keys *m_hashedKeys;\r
381                 ///\r
382                 size_t m_hashedKeysSize;\r
383                 ///\r
384                 Keys::iterator m_i;\r
385 \r
386                 ///\r
387                 void next();\r
388 \r
389         public:\r
390                 ///\r
391                 KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize);\r
392                 ///\r
393                 Key *operator *();\r
394                 ///\r
395                 void operator++() {\r
396                         next();\r
397                 }\r
398         };\r
399 \r
400 private:\r
401         ///\r
402         Keys &getKeys(const Key &i_key);\r
403 \r
404 public:\r
405         /// add a key\r
406         void addKey(const Key &i_key);\r
407 \r
408         /// add a key name alias\r
409         void addAlias(const tstringi &i_aliasName, Key *i_key);\r
410 \r
411         /// add substitute\r
412         void addSubstitute(const ModifiedKey &i_mkeyFrom,\r
413                                            const ModifiedKey &i_mkeyTo);\r
414 \r
415         /// get a sync key\r
416         Key *getSyncKey() {\r
417                 return &m_syncKey;\r
418         }\r
419 \r
420         /// add a modifier key\r
421         void addModifier(Modifier::Type i_mt, Key * i_key);\r
422 \r
423         /// search a key\r
424         Key *searchKey(const Key &i_key);\r
425 \r
426         /// search a key (of which the key's scan code is the prefix)\r
427         Key *searchPrefixKey(const Key &i_key);\r
428 \r
429         /// search a key by name\r
430         Key *searchKey(const tstringi &i_name);\r
431 \r
432         /// search a key by non-alias name\r
433         Key *searchKeyByNonAliasName(const tstringi &i_name);\r
434 \r
435         /// search a substitute\r
436         ModifiedKey searchSubstitute(const ModifiedKey &i_mkey);\r
437 \r
438         /// get modifiers\r
439         Mods &getModifiers(Modifier::Type i_mt) {\r
440                 return m_mods[i_mt];\r
441         }\r
442 \r
443         /// get key iterator\r
444         KeyIterator getKeyIterator() {\r
445                 return KeyIterator(&m_hashedKeys[0], HASHED_KEYS_SIZE);\r
446         }\r
447 };\r
448 \r
449 \r
450 #endif // !_KEYBOARD_H\r