OSDN Git Service

post WM_NULL to attached threads on yamy exit to unmap mayu{32,64}.dll
[yamy/yamy.git] / keyboard.h
index 1d9111f..8bfc42c 100644 (file)
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// keyboard.h
-
-
-#ifndef _KEYBOARD_H
-#  define _KEYBOARD_H
-
-#  include "misc.h"
-#  include "driver.h"
-#  include "stringtool.h"
-#  include <vector>
-#  include <list>
-#  include <map>
-
-
-/// a scan code with flags
-class ScanCode
-{
-public:
-  ///
-  enum
-  {
-    BREAK = KEYBOARD_INPUT_DATA::BREAK,                /// key release flag
-    E0    = KEYBOARD_INPUT_DATA::E0,           /// extended key flag
-    E1    = KEYBOARD_INPUT_DATA::E1,           /// extended key flag
-    E0E1  = KEYBOARD_INPUT_DATA::E0E1,         /// extended key flag
-  };
-
-public:
-  USHORT m_scan;                               ///
-  USHORT m_flags;                              ///
-
-public:
-  ///
-  ScanCode() : m_scan(0), m_flags(0) { }
-  ///
-  ScanCode(USHORT i_scan, USHORT i_flags)
-    : m_scan(i_scan), m_flags(i_flags) { }
-  ///
-  bool operator==(const ScanCode &i_sc) const
-  {
-    return (m_scan == i_sc.m_scan &&
-           (E0E1 & m_flags) == (E0E1 & i_sc.m_flags));
-  }
-  ///
-  bool operator!=(const ScanCode &i_sc) const { return !(*this == i_sc); }
-};
-
-
-/// a key
-class Key
-{
-public:
-  enum
-  {
-    ///
-    MAX_SCAN_CODES_SIZE = 4,
-  };
-
-private:
-  ///
-  typedef std::vector<tstringi> Names;
-
-public:
-  /// if this key pressed physically
-  bool m_isPressed;
-  /// if this key pressed on Win32
-  bool m_isPressedOnWin32;
-  /// if this key pressed by assign
-  bool m_isPressedByAssign;
-
-private:
-  /// key name
-  Names m_names;
-  /// key scan code length
-  size_t m_scanCodesSize;
-  /// key scan code
-  ScanCode m_scanCodes[MAX_SCAN_CODES_SIZE];
-
-public:
-  ///
-  Key()
-    : m_isPressed(false),
-      m_isPressedOnWin32(false),
-      m_isPressedByAssign(false),
-      m_scanCodesSize(0)
-  { }
-
-  /// for Event::* only
-  Key(const tstringi &i_name)
-    : m_isPressed(false),
-      m_isPressedOnWin32(false),
-      m_isPressedByAssign(false),
-      m_scanCodesSize(0)
-  {
-    addName(i_name);
-    addScanCode(ScanCode());
-  }
-
-  /// get key name (first name)
-  const tstringi &getName() const { return m_names.front(); }
-
-  /// get scan codes
-  const ScanCode *getScanCodes() const { return m_scanCodes; }
-  ///
-  size_t getScanCodesSize() const { return m_scanCodesSize; }
-  
-  /// add a name of key
-  void addName(const tstringi &i_name);
-  
-  /// add a scan code
-  void addScanCode(const ScanCode &i_sc);
-  
-  /// initializer
-  Key &initialize();
-  
-  /// equation by name
-  bool operator==(const tstringi &i_name) const;
-  ///
-  bool operator!=(const tstringi &i_name) const
-  { return !(*this == i_name); }
-  
-  /// is the scan code of this key ?
-  bool isSameScanCode(const Key &i_key) const;
-  
-  /// is the i_key's scan code the prefix of this key's scan code ?
-  bool isPrefixScanCode(const Key &i_key) const;
-  
-  /// stream output
-  friend tostream &operator<<(tostream &i_ost, const Key &i_key);
-  
-  /// < 
-  bool operator<(const Key &i_key) const
-  { return getName() < i_key.getName(); }
-};
-
-
-///
-class Modifier
-{
-  ///
-  typedef u_int64 MODIFIERS;
-  ///
-  MODIFIERS m_modifiers;
-  ///
-  MODIFIERS m_dontcares;
-  
-public:
-  ///
-  enum Type
-  {
-    Type_begin = 0,                            ///
-
-    Type_Shift = Type_begin,                   /// &lt;BASIC_MODIFIER&gt;
-    Type_Alt,                                  /// &lt;BASIC_MODIFIER&gt;
-    Type_Control,                              /// &lt;BASIC_MODIFIER&gt;
-    Type_Windows,                              /// &lt;BASIC_MODIFIER&gt;
-    Type_BASIC,                                        ///
-    
-    Type_Up = Type_BASIC,                      /// &lt;KEYSEQ_MODIFIER&gt;
-    Type_Down,                                 /// &lt;KEYSEQ_MODIFIER&gt;
-    Type_KEYSEQ,                               ///
-
-    Type_Repeat = Type_KEYSEQ,                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_ImeLock,                              /// &lt;ASSIGN_MODIFIER&gt;
-    Type_ImeComp,                              /// &lt;ASSIGN_MODIFIER&gt;
-    Type_NumLock,                              /// &lt;ASSIGN_MODIFIER&gt;
-    Type_CapsLock,                             /// &lt;ASSIGN_MODIFIER&gt;
-    Type_ScrollLock,                           /// &lt;ASSIGN_MODIFIER&gt;
-    Type_KanaLock,                             /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Maximized,                            /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Minimized,                            /// &lt;ASSIGN_MODIFIER&gt;
-    Type_MdiMaximized,                         /// &lt;ASSIGN_MODIFIER&gt;
-    Type_MdiMinimized,                         /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Touchpad,                             /// &lt;ASSIGN_MODIFIER&gt;
-    Type_TouchpadSticky,                       /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod0,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod1,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod2,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod3,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod4,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod5,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod6,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod7,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod8,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Mod9,                                 /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock0,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock1,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock2,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock3,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock4,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock5,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock6,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock7,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock8,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_Lock9,                                        /// &lt;ASSIGN_MODIFIER&gt;
-    Type_ASSIGN,                               ///
-
-    Type_end = Type_ASSIGN                     ///
-  };
-  
-public:
-  ///
-  Modifier();
-  ///
-  Modifier &on(Type i_type) { return press(i_type); }
-  ///
-  Modifier &off(Type i_type) { return release(i_type); }
-  ///
-  Modifier &press(Type i_type)
-  { m_modifiers |= ((MODIFIERS(1)) << i_type); return care(i_type); }
-  ///
-  Modifier &release(Type i_type)
-  { m_modifiers &= ~((MODIFIERS(1)) << i_type); return care(i_type); }
-  ///
-  Modifier &care(Type i_type)
-  { m_dontcares &= ~((MODIFIERS(1)) << i_type); return *this; }
-  ///
-  Modifier &dontcare(Type i_type)
-  { m_dontcares |= ((MODIFIERS(1)) << i_type); return *this; }
-  /// set all modifiers to dontcare
-  Modifier &dontcare() { m_dontcares = ~MODIFIERS(0); return *this; }
-
-  ///
-  Modifier &on(Type i_type, bool i_isOn) { return press(i_type, i_isOn); }
-  ///
-  Modifier &press(Type i_type, bool i_isPressed)
-  { return i_isPressed ? press(i_type) : release(i_type); }
-  ///
-  Modifier &care(Type i_type, bool i_doCare)
-  { return i_doCare ? care(i_type) : dontcare(i_type); }
-  
-  ///
-  bool operator==(const Modifier &i_m) const
-  { return m_modifiers == i_m.m_modifiers && m_dontcares == i_m.m_dontcares; }
-
-  /// add m's modifiers where this dontcare
-  void add(const Modifier &i_m);
-  //Modifier &operator+=(const Modifier &i_m);
-
-  /** does match. (except dontcare modifiers) (is the m included in the *this
-      set ?) */
-  bool doesMatch(const Modifier &i_m) const
-  { return ((m_modifiers | m_dontcares) == (i_m.m_modifiers | m_dontcares)); }
-  
-  ///
-  bool isOn(Type i_type) const { return isPressed(i_type); }
-  ///
-  bool isPressed(Type i_type) const
-  { return !!(m_modifiers & ((MODIFIERS(1)) << i_type)); }
-  ///
-  bool isDontcare(Type i_type) const
-  { return !!(m_dontcares & ((MODIFIERS(1)) << i_type)); }
-
-  /// stream output
-  friend tostream &operator<<(tostream &i_ost, const Modifier &i_m);
-  
-  /// < 
-  bool operator<(const Modifier &i_m) const
-  {
-    return m_modifiers < i_m.m_modifiers ||
-      (m_modifiers == i_m.m_modifiers && m_dontcares < i_m.m_dontcares);
-  }
-};
-
-
-/// stream output
-tostream &operator<<(tostream &i_ost, Modifier::Type i_type);
-
-
-///
-class ModifiedKey
-{
-public:
-  Modifier m_modifier; ///
-  Key *m_key;          ///
-  
-public:
-  ///
-  ModifiedKey() : m_key(NULL) { }
-  ///
-  ModifiedKey(Key *i_key) : m_key(i_key) { }
-  ///
-  ModifiedKey(const Modifier &i_modifier, Key *i_key)
-    : m_modifier(i_modifier), m_key(i_key) { }
-  ///
-  bool operator==(const ModifiedKey &i_mk) const
-  { return m_modifier == i_mk.m_modifier && m_key == i_mk.m_key; }
-  ///
-  bool operator!=(const ModifiedKey &i_mk) const
-  { return !operator==(i_mk); }
-  
-  /// stream output
-  friend tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk);
-
-  /// < 
-  bool operator<(const ModifiedKey &i_mk) const
-  {
-    return *m_key < *i_mk.m_key ||
-      (!(*i_mk.m_key < *m_key) && m_modifier < i_mk.m_modifier);
-  }
-};
-
-
-///
-class Keyboard
-{
-public:
-  /// keyboard modifiers (pointer into Keys)
-  typedef std::list<Key *> Mods;
-
-private:
-  /** keyboard keys (hashed by first scan code).
-      Keys must be *list* of Key.
-      Because *pointers* into Keys exist anywhere in this program, the address
-      of Key's elements must be fixed.  */
-  enum {
-    HASHED_KEYS_SIZE = 128,                    ///
-  };
-  typedef std::list<Key> Keys;                 ///
-  typedef std::map<tstringi, Key *> Aliases;   /// key name aliases
-  ///
-  class Substitute
-  {
-  public:
-    ModifiedKey m_mkeyFrom;
-    ModifiedKey m_mkeyTo;
-  public:
-    Substitute(const ModifiedKey &i_mkeyFrom,
-              const ModifiedKey &i_mkeyTo)
-      : m_mkeyFrom(i_mkeyFrom), m_mkeyTo(i_mkeyTo)
-    {
-    }
-  };
-  typedef std::list<Substitute> Substitutes;   /// substitutes
-
-private:
-  Keys m_hashedKeys[HASHED_KEYS_SIZE];         ///
-  Aliases m_aliases;                           ///
-  Substitutes m_substitutes;                   /// 
-  Key m_syncKey;                               /// key used to synchronize
-  
-private:
-  ///
-  Mods m_mods[Modifier::Type_BASIC];
-
-public:
-  ///
-  class KeyIterator
-  {
-    ///
-    Keys *m_hashedKeys;
-    ///
-    size_t m_hashedKeysSize;
-    ///
-    Keys::iterator m_i;
-    
-    ///
-    void next();
-    
-  public:
-    ///
-    KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize);
-    ///
-    Key *operator *();
-    ///
-    void operator++() { next(); }
-  };
-  
-private:
-  ///
-  Keys &getKeys(const Key &i_key);
-
-public:
-  /// add a key
-  void addKey(const Key &i_key);
-
-  /// add a key name alias
-  void addAlias(const tstringi &i_aliasName, Key *i_key);
-  
-  /// add substitute
-  void addSubstitute(const ModifiedKey &i_mkeyFrom,
-                    const ModifiedKey &i_mkeyTo);
-  
-  /// get a sync key
-  Key *getSyncKey() { return &m_syncKey; }
-  
-  /// add a modifier key
-  void addModifier(Modifier::Type i_mt, Key * i_key);
-  
-  /// search a key
-  Key *searchKey(const Key &i_key);
-  
-  /// search a key (of which the key's scan code is the prefix)
-  Key *searchPrefixKey(const Key &i_key);
-  
-  /// search a key by name
-  Key *searchKey(const tstringi &i_name);
-
-  /// search a key by non-alias name
-  Key *searchKeyByNonAliasName(const tstringi &i_name);
-
-  /// search a substitute
-  ModifiedKey searchSubstitute(const ModifiedKey &i_mkey);
-
-  /// get modifiers
-  Mods &getModifiers(Modifier::Type i_mt) { return m_mods[i_mt]; }
-
-  /// get key iterator
-  KeyIterator getKeyIterator()
-  { return KeyIterator(&m_hashedKeys[0], HASHED_KEYS_SIZE); }
-};
-
-
-#endif // !_KEYBOARD_H
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// keyboard.h\r
+\r
+\r
+#ifndef _KEYBOARD_H\r
+#  define _KEYBOARD_H\r
+\r
+#  include "misc.h"\r
+#  include "driver.h"\r
+#  include "stringtool.h"\r
+#  include <vector>\r
+#  include <list>\r
+#  include <map>\r
+\r
+\r
+/// a scan code with flags\r
+class ScanCode\r
+{\r
+public:\r
+       ///\r
+       enum {\r
+               BREAK = KEYBOARD_INPUT_DATA::BREAK,             /// key release flag\r
+               E0    = KEYBOARD_INPUT_DATA::E0,                /// extended key flag\r
+               E1    = KEYBOARD_INPUT_DATA::E1,                /// extended key flag\r
+               E0E1  = KEYBOARD_INPUT_DATA::E0E1,              /// extended key flag\r
+       };\r
+\r
+public:\r
+       USHORT m_scan;                          ///\r
+       USHORT m_flags;                         ///\r
+\r
+public:\r
+       ///\r
+       ScanCode() : m_scan(0), m_flags(0) { }\r
+       ///\r
+       ScanCode(USHORT i_scan, USHORT i_flags)\r
+                       : m_scan(i_scan), m_flags(i_flags) { }\r
+       ///\r
+       bool operator==(const ScanCode &i_sc) const {\r
+               return (m_scan == i_sc.m_scan &&\r
+                               (E0E1 & m_flags) == (E0E1 & i_sc.m_flags));\r
+       }\r
+       ///\r
+       bool operator!=(const ScanCode &i_sc) const {\r
+               return !(*this == i_sc);\r
+       }\r
+};\r
+\r
+\r
+/// a key\r
+class Key\r
+{\r
+public:\r
+       enum {\r
+               ///\r
+               MAX_SCAN_CODES_SIZE = 4,\r
+       };\r
+\r
+private:\r
+       ///\r
+       typedef std::vector<tstringi> Names;\r
+\r
+public:\r
+       /// if this key pressed physically\r
+       bool m_isPressed;\r
+       /// if this key pressed on Win32\r
+       bool m_isPressedOnWin32;\r
+       /// if this key pressed by assign\r
+       bool m_isPressedByAssign;\r
+\r
+private:\r
+       /// key name\r
+       Names m_names;\r
+       /// key scan code length\r
+       size_t m_scanCodesSize;\r
+       /// key scan code\r
+       ScanCode m_scanCodes[MAX_SCAN_CODES_SIZE];\r
+\r
+public:\r
+       ///\r
+       Key()\r
+                       : m_isPressed(false),\r
+                       m_isPressedOnWin32(false),\r
+                       m_isPressedByAssign(false),\r
+                       m_scanCodesSize(0) { }\r
+\r
+       /// for Event::* only\r
+       Key(const tstringi &i_name)\r
+                       : m_isPressed(false),\r
+                       m_isPressedOnWin32(false),\r
+                       m_isPressedByAssign(false),\r
+                       m_scanCodesSize(0) {\r
+               addName(i_name);\r
+               addScanCode(ScanCode());\r
+       }\r
+\r
+       /// get key name (first name)\r
+       const tstringi &getName() const {\r
+               return m_names.front();\r
+       }\r
+\r
+       /// get scan codes\r
+       const ScanCode *getScanCodes() const {\r
+               return m_scanCodes;\r
+       }\r
+       ///\r
+       size_t getScanCodesSize() const {\r
+               return m_scanCodesSize;\r
+       }\r
+\r
+       /// add a name of key\r
+       void addName(const tstringi &i_name);\r
+\r
+       /// add a scan code\r
+       void addScanCode(const ScanCode &i_sc);\r
+\r
+       /// initializer\r
+       Key &initialize();\r
+\r
+       /// equation by name\r
+       bool operator==(const tstringi &i_name) const;\r
+       ///\r
+       bool operator!=(const tstringi &i_name) const {\r
+               return !(*this == i_name);\r
+       }\r
+\r
+       /// is the scan code of this key ?\r
+       bool isSameScanCode(const Key &i_key) const;\r
+\r
+       /// is the i_key's scan code the prefix of this key's scan code ?\r
+       bool isPrefixScanCode(const Key &i_key) const;\r
+\r
+       /// stream output\r
+       friend tostream &operator<<(tostream &i_ost, const Key &i_key);\r
+\r
+       /// <\r
+       bool operator<(const Key &i_key) const {\r
+               return getName() < i_key.getName();\r
+       }\r
+};\r
+\r
+\r
+///\r
+class Modifier\r
+{\r
+       ///\r
+       typedef u_int64 MODIFIERS;\r
+       ///\r
+       MODIFIERS m_modifiers;\r
+       ///\r
+       MODIFIERS m_dontcares;\r
+\r
+public:\r
+       ///\r
+       enum Type {\r
+               Type_begin = 0,                         ///\r
+\r
+               Type_Shift = Type_begin,                        /// &lt;BASIC_MODIFIER&gt;\r
+               Type_Alt,                                       /// &lt;BASIC_MODIFIER&gt;\r
+               Type_Control,                           /// &lt;BASIC_MODIFIER&gt;\r
+               Type_Windows,                           /// &lt;BASIC_MODIFIER&gt;\r
+               Type_BASIC,                                     ///\r
+\r
+               Type_Up = Type_BASIC,                   /// &lt;KEYSEQ_MODIFIER&gt;\r
+               Type_Down,                                      /// &lt;KEYSEQ_MODIFIER&gt;\r
+               Type_KEYSEQ,                            ///\r
+\r
+               Type_Repeat = Type_KEYSEQ,                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_ImeLock,                           /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_ImeComp,                           /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_NumLock,                           /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_CapsLock,                          /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_ScrollLock,                                /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_KanaLock,                          /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Maximized,                         /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Minimized,                         /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_MdiMaximized,                              /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_MdiMinimized,                              /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Touchpad,                          /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_TouchpadSticky,                    /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod0,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod1,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod2,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod3,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod4,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod5,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod6,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod7,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod8,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Mod9,                                      /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock0,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock1,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock2,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock3,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock4,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock5,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock6,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock7,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock8,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_Lock9,                                     /// &lt;ASSIGN_MODIFIER&gt;\r
+               Type_ASSIGN,                            ///\r
+\r
+               Type_end = Type_ASSIGN                  ///\r
+       };\r
+\r
+public:\r
+       ///\r
+       Modifier();\r
+       ///\r
+       Modifier &on(Type i_type) {\r
+               return press(i_type);\r
+       }\r
+       ///\r
+       Modifier &off(Type i_type) {\r
+               return release(i_type);\r
+       }\r
+       ///\r
+       Modifier &press(Type i_type) {\r
+               m_modifiers |= ((MODIFIERS(1)) << i_type);\r
+               return care(i_type);\r
+       }\r
+       ///\r
+       Modifier &release(Type i_type) {\r
+               m_modifiers &= ~((MODIFIERS(1)) << i_type);\r
+               return care(i_type);\r
+       }\r
+       ///\r
+       Modifier &care(Type i_type) {\r
+               m_dontcares &= ~((MODIFIERS(1)) << i_type);\r
+               return *this;\r
+       }\r
+       ///\r
+       Modifier &dontcare(Type i_type) {\r
+               m_dontcares |= ((MODIFIERS(1)) << i_type);\r
+               return *this;\r
+       }\r
+       /// set all modifiers to dontcare\r
+       Modifier &dontcare() {\r
+               m_dontcares = ~MODIFIERS(0);\r
+               return *this;\r
+       }\r
+\r
+       ///\r
+       Modifier &on(Type i_type, bool i_isOn) {\r
+               return press(i_type, i_isOn);\r
+       }\r
+       ///\r
+       Modifier &press(Type i_type, bool i_isPressed) {\r
+               return i_isPressed ? press(i_type) : release(i_type);\r
+       }\r
+       ///\r
+       Modifier &care(Type i_type, bool i_doCare) {\r
+               return i_doCare ? care(i_type) : dontcare(i_type);\r
+       }\r
+\r
+       ///\r
+       bool operator==(const Modifier &i_m) const {\r
+               return m_modifiers == i_m.m_modifiers && m_dontcares == i_m.m_dontcares;\r
+       }\r
+\r
+       /// add m's modifiers where this dontcare\r
+       void add(const Modifier &i_m);\r
+       //Modifier &operator+=(const Modifier &i_m);\r
+\r
+       /** does match. (except dontcare modifiers) (is the m included in the *this\r
+           set ?) */\r
+       bool doesMatch(const Modifier &i_m) const {\r
+               return ((m_modifiers | m_dontcares) == (i_m.m_modifiers | m_dontcares));\r
+       }\r
+\r
+       ///\r
+       bool isOn(Type i_type) const {\r
+               return isPressed(i_type);\r
+       }\r
+       ///\r
+       bool isPressed(Type i_type) const {\r
+               return !!(m_modifiers & ((MODIFIERS(1)) << i_type));\r
+       }\r
+       ///\r
+       bool isDontcare(Type i_type) const {\r
+               return !!(m_dontcares & ((MODIFIERS(1)) << i_type));\r
+       }\r
+\r
+       /// stream output\r
+       friend tostream &operator<<(tostream &i_ost, const Modifier &i_m);\r
+\r
+       /// <\r
+       bool operator<(const Modifier &i_m) const {\r
+               return m_modifiers < i_m.m_modifiers ||\r
+                          (m_modifiers == i_m.m_modifiers && m_dontcares < i_m.m_dontcares);\r
+       }\r
+};\r
+\r
+\r
+/// stream output\r
+tostream &operator<<(tostream &i_ost, Modifier::Type i_type);\r
+\r
+\r
+///\r
+class ModifiedKey\r
+{\r
+public:\r
+       Modifier m_modifier;    ///\r
+       Key *m_key;             ///\r
+\r
+public:\r
+       ///\r
+       ModifiedKey() : m_key(NULL) { }\r
+       ///\r
+       ModifiedKey(Key *i_key) : m_key(i_key) { }\r
+       ///\r
+       ModifiedKey(const Modifier &i_modifier, Key *i_key)\r
+                       : m_modifier(i_modifier), m_key(i_key) { }\r
+       ///\r
+       bool operator==(const ModifiedKey &i_mk) const {\r
+               return m_modifier == i_mk.m_modifier && m_key == i_mk.m_key;\r
+       }\r
+       ///\r
+       bool operator!=(const ModifiedKey &i_mk) const {\r
+               return !operator==(i_mk);\r
+       }\r
+\r
+       /// stream output\r
+       friend tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk);\r
+\r
+       /// <\r
+       bool operator<(const ModifiedKey &i_mk) const {\r
+               return *m_key < *i_mk.m_key ||\r
+                          (!(*i_mk.m_key < *m_key) && m_modifier < i_mk.m_modifier);\r
+       }\r
+};\r
+\r
+\r
+///\r
+class Keyboard\r
+{\r
+public:\r
+       /// keyboard modifiers (pointer into Keys)\r
+       typedef std::list<Key *> Mods;\r
+\r
+private:\r
+       /** keyboard keys (hashed by first scan code).\r
+           Keys must be *list* of Key.\r
+           Because *pointers* into Keys exist anywhere in this program, the address\r
+           of Key's elements must be fixed.  */\r
+       enum {\r
+               HASHED_KEYS_SIZE = 128,                 ///\r
+       };\r
+       typedef std::list<Key> Keys;                    ///\r
+       typedef std::map<tstringi, Key *> Aliases;      /// key name aliases\r
+       ///\r
+       class Substitute\r
+       {\r
+       public:\r
+               ModifiedKey m_mkeyFrom;\r
+               ModifiedKey m_mkeyTo;\r
+       public:\r
+               Substitute(const ModifiedKey &i_mkeyFrom,\r
+                                  const ModifiedKey &i_mkeyTo)\r
+                               : m_mkeyFrom(i_mkeyFrom), m_mkeyTo(i_mkeyTo) {\r
+               }\r
+       };\r
+       typedef std::list<Substitute> Substitutes;      /// substitutes\r
+\r
+private:\r
+       Keys m_hashedKeys[HASHED_KEYS_SIZE];            ///\r
+       Aliases m_aliases;                              ///\r
+       Substitutes m_substitutes;                      ///\r
+       Key m_syncKey;                          /// key used to synchronize\r
+\r
+private:\r
+       ///\r
+       Mods m_mods[Modifier::Type_BASIC];\r
+\r
+public:\r
+       ///\r
+       class KeyIterator\r
+       {\r
+               ///\r
+               Keys *m_hashedKeys;\r
+               ///\r
+               size_t m_hashedKeysSize;\r
+               ///\r
+               Keys::iterator m_i;\r
+\r
+               ///\r
+               void next();\r
+\r
+       public:\r
+               ///\r
+               KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize);\r
+               ///\r
+               Key *operator *();\r
+               ///\r
+               void operator++() {\r
+                       next();\r
+               }\r
+       };\r
+\r
+private:\r
+       ///\r
+       Keys &getKeys(const Key &i_key);\r
+\r
+public:\r
+       /// add a key\r
+       void addKey(const Key &i_key);\r
+\r
+       /// add a key name alias\r
+       void addAlias(const tstringi &i_aliasName, Key *i_key);\r
+\r
+       /// add substitute\r
+       void addSubstitute(const ModifiedKey &i_mkeyFrom,\r
+                                          const ModifiedKey &i_mkeyTo);\r
+\r
+       /// get a sync key\r
+       Key *getSyncKey() {\r
+               return &m_syncKey;\r
+       }\r
+\r
+       /// add a modifier key\r
+       void addModifier(Modifier::Type i_mt, Key * i_key);\r
+\r
+       /// search a key\r
+       Key *searchKey(const Key &i_key);\r
+\r
+       /// search a key (of which the key's scan code is the prefix)\r
+       Key *searchPrefixKey(const Key &i_key);\r
+\r
+       /// search a key by name\r
+       Key *searchKey(const tstringi &i_name);\r
+\r
+       /// search a key by non-alias name\r
+       Key *searchKeyByNonAliasName(const tstringi &i_name);\r
+\r
+       /// search a substitute\r
+       ModifiedKey searchSubstitute(const ModifiedKey &i_mkey);\r
+\r
+       /// get modifiers\r
+       Mods &getModifiers(Modifier::Type i_mt) {\r
+               return m_mods[i_mt];\r
+       }\r
+\r
+       /// get key iterator\r
+       KeyIterator getKeyIterator() {\r
+               return KeyIterator(&m_hashedKeys[0], HASHED_KEYS_SIZE);\r
+       }\r
+};\r
+\r
+\r
+#endif // !_KEYBOARD_H\r