OSDN Git Service

abolish suppressing yamy on remote desktop
[yamy/yamy.git] / keyboard.cpp
index 98eb6d6..c7aa8e4 100644 (file)
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// setting.cpp
-
-
-#include "keyboard.h"
-
-#include <algorithm>
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Key
-
-
-// add a name or an alias of key
-void Key::addName(const tstringi &i_name)
-{
-  m_names.push_back(i_name);
-}
-
-
-// add a scan code
-void Key::addScanCode(const ScanCode &i_sc)
-{
-  ASSERT(m_scanCodesSize < MAX_SCAN_CODES_SIZE);
-  m_scanCodes[m_scanCodesSize ++] = i_sc;
-}
-
-
-// initializer
-Key &Key::initialize()
-{
-  m_names.clear();
-  m_isPressed = false;
-  m_isPressedOnWin32 = false;
-  m_isPressedByAssign = false;
-  m_scanCodesSize = 0;
-  return *this;
-}
-
-
-// equation by name
-bool Key::operator==(const tstringi &i_name) const
-{
-  return std::find(m_names.begin(), m_names.end(), i_name) != m_names.end();
-}
-
-  
-// is the scan code of this key ?
-bool Key::isSameScanCode(const Key &i_key) const
-{
-  if (m_scanCodesSize != i_key.m_scanCodesSize)
-    return false;
-  return isPrefixScanCode(i_key);
-}
-
-
-// is the key's scan code the prefix of this key's scan code ?
-bool Key::isPrefixScanCode(const Key &i_key) const
-{
-  for (size_t i = 0; i < i_key.m_scanCodesSize; ++ i)
-    if (m_scanCodes[i] != i_key.m_scanCodes[i])
-      return false;
-  return true;
-}
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, const Key &i_mk)
-{
-  return i_ost << i_mk.getName();
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Modifier
-
-
-Modifier::Modifier()
-  : m_modifiers(0),
-    m_dontcares(0)
-{
-  ASSERT(Type_end <= (sizeof(MODIFIERS) * 8));
-  static const Type defaultDontCare[] =
-  {
-    Type_Up, Type_Down, Type_Repeat,
-    Type_ImeLock, Type_ImeComp, Type_NumLock, Type_CapsLock, Type_ScrollLock,
-       Type_KanaLock,
-    Type_Maximized, Type_Minimized, Type_MdiMaximized, Type_MdiMinimized,
-    Type_Touchpad, Type_TouchpadSticky,
-    Type_Lock0, Type_Lock1, Type_Lock2, Type_Lock3, Type_Lock4,
-    Type_Lock5, Type_Lock6, Type_Lock7, Type_Lock8, Type_Lock9,
-  };
-  for (size_t i = 0; i < NUMBER_OF(defaultDontCare); ++ i)
-    dontcare(defaultDontCare[i]);
-}
-
-
-// add m's modifiers where this dontcare
-void Modifier::add(const Modifier &i_m)
-{
-  for (int i = 0; i < Type_end; ++ i)
-  {
-    if (isDontcare(static_cast<Modifier::Type>(i)))
-      if (!i_m.isDontcare(static_cast<Modifier::Type>(i)))
-       if (i_m.isPressed(static_cast<Modifier::Type>(i)))
-         press(static_cast<Modifier::Type>(i));
-       else
-         release(static_cast<Modifier::Type>(i));
-  }
-}
-
-// stream output
-tostream &operator<<(tostream &i_ost, const Modifier &i_m)
-{
-  struct Mods
-  {
-    Modifier::Type m_mt;
-    const _TCHAR *m_symbol;
-  };
-  
-  const static Mods mods[] =
-  {
-    { Modifier::Type_Up, _T("U-") }, { Modifier::Type_Down, _T("D-") },
-    { Modifier::Type_Shift, _T("S-") }, { Modifier::Type_Alt, _T("A-") },
-    { Modifier::Type_Control, _T("C-") }, { Modifier::Type_Windows, _T("W-") },
-    { Modifier::Type_Repeat, _T("R-") },
-    { Modifier::Type_ImeLock, _T("IL-") },
-    { Modifier::Type_ImeComp, _T("IC-") },
-    { Modifier::Type_ImeComp, _T("I-") },
-    { Modifier::Type_NumLock, _T("NL-") },
-    { Modifier::Type_CapsLock, _T("CL-") },
-    { Modifier::Type_ScrollLock, _T("SL-") },
-    { Modifier::Type_KanaLock, _T("KL-") },
-    { Modifier::Type_Maximized, _T("MAX-") },
-    { Modifier::Type_Minimized, _T("MIN-") },
-    { Modifier::Type_MdiMaximized, _T("MMAX-") },
-    { Modifier::Type_MdiMinimized, _T("MMIN-") },
-    { Modifier::Type_Touchpad, _T("T-") },
-    { Modifier::Type_TouchpadSticky, _T("TS-") },
-    { Modifier::Type_Mod0, _T("M0-") }, { Modifier::Type_Mod1, _T("M1-") },
-    { Modifier::Type_Mod2, _T("M2-") }, { Modifier::Type_Mod3, _T("M3-") },
-    { Modifier::Type_Mod4, _T("M4-") }, { Modifier::Type_Mod5, _T("M5-") },
-    { Modifier::Type_Mod6, _T("M6-") }, { Modifier::Type_Mod7, _T("M7-") },
-    { Modifier::Type_Mod8, _T("M8-") }, { Modifier::Type_Mod9, _T("M9-") },
-    { Modifier::Type_Lock0, _T("L0-") }, { Modifier::Type_Lock1, _T("L1-") },
-    { Modifier::Type_Lock2, _T("L2-") }, { Modifier::Type_Lock3, _T("L3-") },
-    { Modifier::Type_Lock4, _T("L4-") }, { Modifier::Type_Lock5, _T("L5-") },
-    { Modifier::Type_Lock6, _T("L6-") }, { Modifier::Type_Lock7, _T("L7-") },
-    { Modifier::Type_Lock8, _T("L8-") }, { Modifier::Type_Lock9, _T("L9-") },
-  };
-
-  for (size_t i = 0; i < NUMBER_OF(mods); ++ i)
-    if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))
-      i_ost << mods[i].m_symbol;
-#if 0
-    else if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))
-      i_ost << _T("~") << mods[i].m_symbol;
-    else
-      i_ost << _T("*") << mods[i].m_symbol;
-#endif
-
-  return i_ost;
-}
-
-
-/// stream output
-tostream &operator<<(tostream &i_ost, Modifier::Type i_type)
-{
-  const _TCHAR *modNames[] =
-  {
-    _T("Shift"), 
-    _T("Alt"), 
-    _T("Control"), 
-    _T("Windows"), 
-    _T("Up"), 
-    _T("Down"), 
-    _T("Repeat"), 
-    _T("ImeLock"), 
-    _T("ImeComp"), 
-    _T("NumLock"), 
-    _T("CapsLock"), 
-    _T("ScrollLock"), 
-    _T("KanaLock"), 
-    _T("Maximized"), 
-    _T("Minimized"), 
-    _T("MdiMaximized"), 
-    _T("MdiMinimized"), 
-    _T("Touchpad"), 
-    _T("TouchpadSticky"), 
-    _T("Mod0"), 
-    _T("Mod1"), 
-    _T("Mod2"), 
-    _T("Mod3"), 
-    _T("Mod4"), 
-    _T("Mod5"), 
-    _T("Mod6"), 
-    _T("Mod7"), 
-    _T("Mod8"), 
-    _T("Mod9"), 
-    _T("Lock0"), 
-    _T("Lock1"), 
-    _T("Lock2"), 
-    _T("Lock3"), 
-    _T("Lock4"), 
-    _T("Lock5"), 
-    _T("Lock6"), 
-    _T("Lock7"), 
-    _T("Lock8"), 
-    _T("Lock9"), 
-  };
-
-  int i = static_cast<int>(i_type);
-  if (0 <= i && i < NUMBER_OF(modNames))
-    i_ost << modNames[i];
-  
-  return i_ost;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// ModifiedKey
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk)
-{
-  if (i_mk.m_key)
-    i_ost << i_mk.m_modifier << *i_mk.m_key;
-  return i_ost;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Keyboard::KeyIterator
-
-
-Keyboard::KeyIterator::KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize)
-  : m_hashedKeys(i_hashedKeys),
-    m_hashedKeysSize(i_hashedKeysSize),
-    m_i((*m_hashedKeys).begin())
-{
-  if ((*m_hashedKeys).empty())
-  {
-    do
-    {
-      -- m_hashedKeysSize;
-      ++ m_hashedKeys;
-    } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());
-    if (0 < m_hashedKeysSize)
-      m_i = (*m_hashedKeys).begin();
-  }
-}
-
-
-void Keyboard::KeyIterator::next()
-{
-  if (m_hashedKeysSize == 0)
-    return;
-  ++ m_i;
-  if (m_i == (*m_hashedKeys).end())
-  {
-    do
-    {
-      -- m_hashedKeysSize;
-      ++ m_hashedKeys;
-    } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());
-    if (0 < m_hashedKeysSize)
-      m_i = (*m_hashedKeys).begin();
-  }
-}
-
-
-Key *Keyboard::KeyIterator::operator *()
-{
-  if (m_hashedKeysSize == 0)
-    return NULL;
-  return &*m_i;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Keyboard
-
-
-Keyboard::Keys &Keyboard::getKeys(const Key &i_key)
-{
-  ASSERT(1 <= i_key.getScanCodesSize());
-  return m_hashedKeys[i_key.getScanCodes()->m_scan % HASHED_KEYS_SIZE];
-}
-
-
-// add a key
-void Keyboard::addKey(const Key &i_key)
-{
-  getKeys(i_key).push_front(i_key);
-}
-
-
-// add a key name alias
-void Keyboard::addAlias(const tstringi &i_aliasName, Key *i_key)
-{
-  m_aliases.insert(Aliases::value_type(i_aliasName, i_key));
-}
-
-// add substitute
-void Keyboard::addSubstitute(const ModifiedKey &i_mkeyFrom,
-                            const ModifiedKey &i_mkeyTo)
-{
-  m_substitutes.push_front(Substitute(i_mkeyFrom, i_mkeyTo));
-}
-
-
-// add a modifier key
-void Keyboard::addModifier(Modifier::Type i_mt, Key *i_key)
-{
-  ASSERT((int)i_mt < (int)Modifier::Type_BASIC);
-  if (std::find(m_mods[i_mt].begin(), m_mods[i_mt].end(), i_key)
-      != m_mods[i_mt].end())
-    return; // already added
-  m_mods[i_mt].push_back(i_key);
-}
-
-
-// search a key
-Key *Keyboard::searchKey(const Key &i_key)
-{
-  Keys &keys = getKeys(i_key);
-  for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)
-    if ((*i).isSameScanCode(i_key))
-      return &*i;
-  return NULL;
-}
-
-
-// search a key (of which the key's scan code is the prefix)
-Key *Keyboard::searchPrefixKey(const Key &i_key)
-{
-  Keys &keys = getKeys(i_key);
-  for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)
-    if ((*i).isPrefixScanCode(i_key))
-      return &*i;
-  return NULL;
-}
-
-  
-// search a key by name
-Key *Keyboard::searchKey(const tstringi &i_name)
-{
-  Aliases::iterator i = m_aliases.find(i_name);
-  if (i != m_aliases.end())
-    return (*i).second;
-  return searchKeyByNonAliasName(i_name);
-}
-
-
-// search a key by non-alias name
-Key *Keyboard::searchKeyByNonAliasName(const tstringi &i_name)
-{
-  for (int j = 0; j < HASHED_KEYS_SIZE; ++ j)
-  {
-    Keys &keys = m_hashedKeys[j];
-    Keys::iterator i = std::find(keys.begin(), keys.end(), i_name);
-    if (i != keys.end())
-      return &*i;
-  }
-  return NULL;
-}
-
-/// search a substitute
-ModifiedKey Keyboard::searchSubstitute(const ModifiedKey &i_mkey)
-{
-  for (Substitutes::const_iterator
-        i = m_substitutes.begin(); i != m_substitutes.end(); ++ i)
-    if (i->m_mkeyFrom.m_key == i_mkey.m_key &&
-       i->m_mkeyFrom.m_modifier.doesMatch(i_mkey.m_modifier))
-      return i->m_mkeyTo;
-  return ModifiedKey();                                // not found (.m_mkey is NULL)
-}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// setting.cpp\r
+\r
+\r
+#include "keyboard.h"\r
+\r
+#include <algorithm>\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Key\r
+\r
+\r
+// add a name or an alias of key\r
+void Key::addName(const tstringi &i_name)\r
+{\r
+       m_names.push_back(i_name);\r
+}\r
+\r
+\r
+// add a scan code\r
+void Key::addScanCode(const ScanCode &i_sc)\r
+{\r
+       ASSERT(m_scanCodesSize < MAX_SCAN_CODES_SIZE);\r
+       m_scanCodes[m_scanCodesSize ++] = i_sc;\r
+}\r
+\r
+\r
+// initializer\r
+Key &Key::initialize()\r
+{\r
+       m_names.clear();\r
+       m_isPressed = false;\r
+       m_isPressedOnWin32 = false;\r
+       m_isPressedByAssign = false;\r
+       m_scanCodesSize = 0;\r
+       return *this;\r
+}\r
+\r
+\r
+// equation by name\r
+bool Key::operator==(const tstringi &i_name) const\r
+{\r
+       return std::find(m_names.begin(), m_names.end(), i_name) != m_names.end();\r
+}\r
+\r
+\r
+// is the scan code of this key ?\r
+bool Key::isSameScanCode(const Key &i_key) const\r
+{\r
+       if (m_scanCodesSize != i_key.m_scanCodesSize)\r
+               return false;\r
+       return isPrefixScanCode(i_key);\r
+}\r
+\r
+\r
+// is the key's scan code the prefix of this key's scan code ?\r
+bool Key::isPrefixScanCode(const Key &i_key) const\r
+{\r
+       for (size_t i = 0; i < i_key.m_scanCodesSize; ++ i)\r
+               if (m_scanCodes[i] != i_key.m_scanCodes[i])\r
+                       return false;\r
+       return true;\r
+}\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const Key &i_mk)\r
+{\r
+       return i_ost << i_mk.getName();\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Modifier\r
+\r
+\r
+Modifier::Modifier()\r
+               : m_modifiers(0),\r
+               m_dontcares(0)\r
+{\r
+       ASSERT(Type_end <= (sizeof(MODIFIERS) * 8));\r
+       static const Type defaultDontCare[] = {\r
+               Type_Up, Type_Down, Type_Repeat,\r
+               Type_ImeLock, Type_ImeComp, Type_NumLock, Type_CapsLock, Type_ScrollLock,\r
+               Type_KanaLock,\r
+               Type_Maximized, Type_Minimized, Type_MdiMaximized, Type_MdiMinimized,\r
+               Type_Touchpad, Type_TouchpadSticky,\r
+               Type_Lock0, Type_Lock1, Type_Lock2, Type_Lock3, Type_Lock4,\r
+               Type_Lock5, Type_Lock6, Type_Lock7, Type_Lock8, Type_Lock9,\r
+       };\r
+       for (size_t i = 0; i < NUMBER_OF(defaultDontCare); ++ i)\r
+               dontcare(defaultDontCare[i]);\r
+}\r
+\r
+\r
+// add m's modifiers where this dontcare\r
+void Modifier::add(const Modifier &i_m)\r
+{\r
+       for (int i = 0; i < Type_end; ++ i) {\r
+               if (isDontcare(static_cast<Modifier::Type>(i)))\r
+                       if (!i_m.isDontcare(static_cast<Modifier::Type>(i)))\r
+                               if (i_m.isPressed(static_cast<Modifier::Type>(i)))\r
+                                       press(static_cast<Modifier::Type>(i));\r
+                               else\r
+                                       release(static_cast<Modifier::Type>(i));\r
+       }\r
+}\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const Modifier &i_m)\r
+{\r
+       struct Mods {\r
+               Modifier::Type m_mt;\r
+               const _TCHAR *m_symbol;\r
+       };\r
+\r
+       const static Mods mods[] = {\r
+               { Modifier::Type_Up, _T("U-") }, { Modifier::Type_Down, _T("D-") },\r
+               { Modifier::Type_Shift, _T("S-") }, { Modifier::Type_Alt, _T("A-") },\r
+               { Modifier::Type_Control, _T("C-") }, { Modifier::Type_Windows, _T("W-") },\r
+               { Modifier::Type_Repeat, _T("R-") },\r
+               { Modifier::Type_ImeLock, _T("IL-") },\r
+               { Modifier::Type_ImeComp, _T("IC-") },\r
+               { Modifier::Type_ImeComp, _T("I-") },\r
+               { Modifier::Type_NumLock, _T("NL-") },\r
+               { Modifier::Type_CapsLock, _T("CL-") },\r
+               { Modifier::Type_ScrollLock, _T("SL-") },\r
+               { Modifier::Type_KanaLock, _T("KL-") },\r
+               { Modifier::Type_Maximized, _T("MAX-") },\r
+               { Modifier::Type_Minimized, _T("MIN-") },\r
+               { Modifier::Type_MdiMaximized, _T("MMAX-") },\r
+               { Modifier::Type_MdiMinimized, _T("MMIN-") },\r
+               { Modifier::Type_Touchpad, _T("T-") },\r
+               { Modifier::Type_TouchpadSticky, _T("TS-") },\r
+               { Modifier::Type_Mod0, _T("M0-") }, { Modifier::Type_Mod1, _T("M1-") },\r
+               { Modifier::Type_Mod2, _T("M2-") }, { Modifier::Type_Mod3, _T("M3-") },\r
+               { Modifier::Type_Mod4, _T("M4-") }, { Modifier::Type_Mod5, _T("M5-") },\r
+               { Modifier::Type_Mod6, _T("M6-") }, { Modifier::Type_Mod7, _T("M7-") },\r
+               { Modifier::Type_Mod8, _T("M8-") }, { Modifier::Type_Mod9, _T("M9-") },\r
+               { Modifier::Type_Lock0, _T("L0-") }, { Modifier::Type_Lock1, _T("L1-") },\r
+               { Modifier::Type_Lock2, _T("L2-") }, { Modifier::Type_Lock3, _T("L3-") },\r
+               { Modifier::Type_Lock4, _T("L4-") }, { Modifier::Type_Lock5, _T("L5-") },\r
+               { Modifier::Type_Lock6, _T("L6-") }, { Modifier::Type_Lock7, _T("L7-") },\r
+               { Modifier::Type_Lock8, _T("L8-") }, { Modifier::Type_Lock9, _T("L9-") },\r
+       };\r
+\r
+       for (size_t i = 0; i < NUMBER_OF(mods); ++ i)\r
+               if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))\r
+                       i_ost << mods[i].m_symbol;\r
+#if 0\r
+               else if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))\r
+                       i_ost << _T("~") << mods[i].m_symbol;\r
+               else\r
+                       i_ost << _T("*") << mods[i].m_symbol;\r
+#endif\r
+\r
+       return i_ost;\r
+}\r
+\r
+\r
+/// stream output\r
+tostream &operator<<(tostream &i_ost, Modifier::Type i_type)\r
+{\r
+       const _TCHAR *modNames[] = {\r
+               _T("Shift"),\r
+               _T("Alt"),\r
+               _T("Control"),\r
+               _T("Windows"),\r
+               _T("Up"),\r
+               _T("Down"),\r
+               _T("Repeat"),\r
+               _T("ImeLock"),\r
+               _T("ImeComp"),\r
+               _T("NumLock"),\r
+               _T("CapsLock"),\r
+               _T("ScrollLock"),\r
+               _T("KanaLock"),\r
+               _T("Maximized"),\r
+               _T("Minimized"),\r
+               _T("MdiMaximized"),\r
+               _T("MdiMinimized"),\r
+               _T("Touchpad"),\r
+               _T("TouchpadSticky"),\r
+               _T("Mod0"),\r
+               _T("Mod1"),\r
+               _T("Mod2"),\r
+               _T("Mod3"),\r
+               _T("Mod4"),\r
+               _T("Mod5"),\r
+               _T("Mod6"),\r
+               _T("Mod7"),\r
+               _T("Mod8"),\r
+               _T("Mod9"),\r
+               _T("Lock0"),\r
+               _T("Lock1"),\r
+               _T("Lock2"),\r
+               _T("Lock3"),\r
+               _T("Lock4"),\r
+               _T("Lock5"),\r
+               _T("Lock6"),\r
+               _T("Lock7"),\r
+               _T("Lock8"),\r
+               _T("Lock9"),\r
+       };\r
+\r
+       int i = static_cast<int>(i_type);\r
+       if (0 <= i && i < NUMBER_OF(modNames))\r
+               i_ost << modNames[i];\r
+\r
+       return i_ost;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// ModifiedKey\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk)\r
+{\r
+       if (i_mk.m_key)\r
+               i_ost << i_mk.m_modifier << *i_mk.m_key;\r
+       return i_ost;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Keyboard::KeyIterator\r
+\r
+\r
+Keyboard::KeyIterator::KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize)\r
+               : m_hashedKeys(i_hashedKeys),\r
+               m_hashedKeysSize(i_hashedKeysSize),\r
+               m_i((*m_hashedKeys).begin())\r
+{\r
+       if ((*m_hashedKeys).empty()) {\r
+               do {\r
+                       -- m_hashedKeysSize;\r
+                       ++ m_hashedKeys;\r
+               } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());\r
+               if (0 < m_hashedKeysSize)\r
+                       m_i = (*m_hashedKeys).begin();\r
+       }\r
+}\r
+\r
+\r
+void Keyboard::KeyIterator::next()\r
+{\r
+       if (m_hashedKeysSize == 0)\r
+               return;\r
+       ++ m_i;\r
+       if (m_i == (*m_hashedKeys).end()) {\r
+               do {\r
+                       -- m_hashedKeysSize;\r
+                       ++ m_hashedKeys;\r
+               } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());\r
+               if (0 < m_hashedKeysSize)\r
+                       m_i = (*m_hashedKeys).begin();\r
+       }\r
+}\r
+\r
+\r
+Key *Keyboard::KeyIterator::operator *()\r
+{\r
+       if (m_hashedKeysSize == 0)\r
+               return NULL;\r
+       return &*m_i;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Keyboard\r
+\r
+\r
+Keyboard::Keys &Keyboard::getKeys(const Key &i_key)\r
+{\r
+       ASSERT(1 <= i_key.getScanCodesSize());\r
+       return m_hashedKeys[i_key.getScanCodes()->m_scan % HASHED_KEYS_SIZE];\r
+}\r
+\r
+\r
+// add a key\r
+void Keyboard::addKey(const Key &i_key)\r
+{\r
+       getKeys(i_key).push_front(i_key);\r
+}\r
+\r
+\r
+// add a key name alias\r
+void Keyboard::addAlias(const tstringi &i_aliasName, Key *i_key)\r
+{\r
+       m_aliases.insert(Aliases::value_type(i_aliasName, i_key));\r
+}\r
+\r
+// add substitute\r
+void Keyboard::addSubstitute(const ModifiedKey &i_mkeyFrom,\r
+                                                        const ModifiedKey &i_mkeyTo)\r
+{\r
+       m_substitutes.push_front(Substitute(i_mkeyFrom, i_mkeyTo));\r
+}\r
+\r
+\r
+// add a modifier key\r
+void Keyboard::addModifier(Modifier::Type i_mt, Key *i_key)\r
+{\r
+       ASSERT((int)i_mt < (int)Modifier::Type_BASIC);\r
+       if (std::find(m_mods[i_mt].begin(), m_mods[i_mt].end(), i_key)\r
+                       != m_mods[i_mt].end())\r
+               return; // already added\r
+       m_mods[i_mt].push_back(i_key);\r
+}\r
+\r
+\r
+// search a key\r
+Key *Keyboard::searchKey(const Key &i_key)\r
+{\r
+       Keys &keys = getKeys(i_key);\r
+       for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)\r
+               if ((*i).isSameScanCode(i_key))\r
+                       return &*i;\r
+       return NULL;\r
+}\r
+\r
+\r
+// search a key (of which the key's scan code is the prefix)\r
+Key *Keyboard::searchPrefixKey(const Key &i_key)\r
+{\r
+       Keys &keys = getKeys(i_key);\r
+       for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)\r
+               if ((*i).isPrefixScanCode(i_key))\r
+                       return &*i;\r
+       return NULL;\r
+}\r
+\r
+\r
+// search a key by name\r
+Key *Keyboard::searchKey(const tstringi &i_name)\r
+{\r
+       Aliases::iterator i = m_aliases.find(i_name);\r
+       if (i != m_aliases.end())\r
+               return (*i).second;\r
+       return searchKeyByNonAliasName(i_name);\r
+}\r
+\r
+\r
+// search a key by non-alias name\r
+Key *Keyboard::searchKeyByNonAliasName(const tstringi &i_name)\r
+{\r
+       for (int j = 0; j < HASHED_KEYS_SIZE; ++ j) {\r
+               Keys &keys = m_hashedKeys[j];\r
+               Keys::iterator i = std::find(keys.begin(), keys.end(), i_name);\r
+               if (i != keys.end())\r
+                       return &*i;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+/// search a substitute\r
+ModifiedKey Keyboard::searchSubstitute(const ModifiedKey &i_mkey)\r
+{\r
+       for (Substitutes::const_iterator\r
+                       i = m_substitutes.begin(); i != m_substitutes.end(); ++ i)\r
+               if (i->m_mkeyFrom.m_key == i_mkey.m_key &&\r
+                               i->m_mkeyFrom.m_modifier.doesMatch(i_mkey.m_modifier))\r
+                       return i->m_mkeyTo;\r
+       return ModifiedKey();                           // not found (.m_mkey is NULL)\r
+}\r