OSDN Git Service

enable command notify on x64
[yamy/yamy.git] / engine.cpp
index fe7f959..f5dbd2c 100644 (file)
 // check focus window\r
 void Engine::checkFocusWindow()\r
 {\r
-  int count = 0;\r
-  \r
-  restart:\r
-  count ++;\r
-  \r
-  HWND hwndFore = GetForegroundWindow();\r
-  DWORD threadId = GetWindowThreadProcessId(hwndFore, NULL);\r
-\r
-  if (hwndFore)\r
-  {\r
-    {\r
-      Acquire a(&m_cs);\r
-      if (m_currentFocusOfThread &&\r
-         m_currentFocusOfThread->m_threadId == threadId &&\r
-         m_currentFocusOfThread->m_hwndFocus == m_hwndFocus)\r
-       return;\r
+       int count = 0;\r
 \r
-      m_emacsEditKillLine.reset();\r
-      \r
-      // erase dead thread\r
-      if (!m_detachedThreadIds.empty())\r
-      {\r
-       for (DetachedThreadIds::iterator i = m_detachedThreadIds.begin();\r
-            i != m_detachedThreadIds.end(); i ++)\r
-       {\r
-         FocusOfThreads::iterator j = m_focusOfThreads.find((*i));\r
-         if (j != m_focusOfThreads.end())\r
-         {\r
-           FocusOfThread *fot = &((*j).second);\r
-           Acquire a(&m_log, 1);\r
-           m_log << _T("RemoveThread") << std::endl;\r
-           m_log << _T("\tHWND:\t") << std::hex << (int)fot->m_hwndFocus\r
-                 << std::dec << std::endl;\r
-           m_log << _T("\tTHREADID:") << fot->m_threadId << std::endl;\r
-           m_log << _T("\tCLASS:\t") << fot->m_className << std::endl;\r
-           m_log << _T("\tTITLE:\t") << fot->m_titleName << std::endl;\r
-           m_log << std::endl;\r
-           m_focusOfThreads.erase(j);\r
-         }\r
+restart:\r
+       count ++;\r
+\r
+       HWND hwndFore = GetForegroundWindow();\r
+       DWORD threadId = GetWindowThreadProcessId(hwndFore, NULL);\r
+\r
+       if (hwndFore) {\r
+               {\r
+                       Acquire a(&m_cs);\r
+                       if (m_currentFocusOfThread &&\r
+                                       m_currentFocusOfThread->m_threadId == threadId &&\r
+                                       m_currentFocusOfThread->m_hwndFocus == m_hwndFocus)\r
+                               return;\r
+\r
+                       m_emacsEditKillLine.reset();\r
+\r
+                       // erase dead thread\r
+                       if (!m_detachedThreadIds.empty()) {\r
+                               for (DetachedThreadIds::iterator i = m_detachedThreadIds.begin();\r
+                                               i != m_detachedThreadIds.end(); i ++) {\r
+                                       FocusOfThreads::iterator j = m_focusOfThreads.find((*i));\r
+                                       if (j != m_focusOfThreads.end()) {\r
+                                               FocusOfThread *fot = &((*j).second);\r
+                                               Acquire a(&m_log, 1);\r
+                                               m_log << _T("RemoveThread") << std::endl;\r
+                                               m_log << _T("\tHWND:\t") << std::hex << (int)fot->m_hwndFocus\r
+                                               << std::dec << std::endl;\r
+                                               m_log << _T("\tTHREADID:") << fot->m_threadId << std::endl;\r
+                                               m_log << _T("\tCLASS:\t") << fot->m_className << std::endl;\r
+                                               m_log << _T("\tTITLE:\t") << fot->m_titleName << std::endl;\r
+                                               m_log << std::endl;\r
+                                               m_focusOfThreads.erase(j);\r
+                                       }\r
+                               }\r
+                               m_detachedThreadIds.erase\r
+                               (m_detachedThreadIds.begin(), m_detachedThreadIds.end());\r
+                       }\r
+\r
+                       FocusOfThreads::iterator i = m_focusOfThreads.find(threadId);\r
+                       if (i != m_focusOfThreads.end()) {\r
+                               m_currentFocusOfThread = &((*i).second);\r
+                               if (!m_currentFocusOfThread->m_isConsole || 2 <= count) {\r
+                                       if (m_currentFocusOfThread->m_keymaps.empty())\r
+                                               setCurrentKeymap(NULL);\r
+                                       else\r
+                                               setCurrentKeymap(*m_currentFocusOfThread->m_keymaps.begin());\r
+                                       m_hwndFocus = m_currentFocusOfThread->m_hwndFocus;\r
+                                       checkShow(m_hwndFocus);\r
+\r
+                                       Acquire a(&m_log, 1);\r
+                                       m_log << _T("FocusChanged") << std::endl;\r
+                                       m_log << _T("\tHWND:\t")\r
+                                       << std::hex << (int)m_currentFocusOfThread->m_hwndFocus\r
+                                       << std::dec << std::endl;\r
+                                       m_log << _T("\tTHREADID:")\r
+                                       << m_currentFocusOfThread->m_threadId << std::endl;\r
+                                       m_log << _T("\tCLASS:\t")\r
+                                       << m_currentFocusOfThread->m_className << std::endl;\r
+                                       m_log << _T("\tTITLE:\t")\r
+                                       << m_currentFocusOfThread->m_titleName << std::endl;\r
+                                       m_log << std::endl;\r
+                                       return;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               _TCHAR className[GANA_MAX_ATOM_LENGTH];\r
+               if (GetClassName(hwndFore, className, NUMBER_OF(className))) {\r
+                       if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0) {\r
+                               _TCHAR titleName[1024];\r
+                               if (GetWindowText(hwndFore, titleName, NUMBER_OF(titleName)) == 0)\r
+                                       titleName[0] = _T('\0');\r
+                               setFocus(hwndFore, threadId, className, titleName, true);\r
+                               Acquire a(&m_log, 1);\r
+                               m_log << _T("HWND:\t") << std::hex << reinterpret_cast<int>(hwndFore)\r
+                               << std::dec << std::endl;\r
+                               m_log << _T("THREADID:") << threadId << std::endl;\r
+                               m_log << _T("CLASS:\t") << className << std::endl;\r
+                               m_log << _T("TITLE:\t") << titleName << std::endl << std::endl;\r
+                               goto restart;\r
+                       }\r
+               }\r
        }\r
-       m_detachedThreadIds.erase\r
-         (m_detachedThreadIds.begin(), m_detachedThreadIds.end());\r
-      }\r
-      \r
-      FocusOfThreads::iterator i = m_focusOfThreads.find(threadId);\r
-      if (i != m_focusOfThreads.end())\r
-      {\r
-       m_currentFocusOfThread = &((*i).second);\r
-       if (!m_currentFocusOfThread->m_isConsole || 2 <= count)\r
-       {\r
-         if (m_currentFocusOfThread->m_keymaps.empty())\r
-           setCurrentKeymap(NULL);\r
-         else\r
-           setCurrentKeymap(*m_currentFocusOfThread->m_keymaps.begin());\r
-         m_hwndFocus = m_currentFocusOfThread->m_hwndFocus;\r
-         checkShow(m_hwndFocus);\r
-       \r
-         Acquire a(&m_log, 1);\r
-         m_log << _T("FocusChanged") << std::endl;\r
-         m_log << _T("\tHWND:\t")\r
-               << std::hex << (int)m_currentFocusOfThread->m_hwndFocus\r
-               << std::dec << std::endl;\r
-         m_log << _T("\tTHREADID:")\r
-               << m_currentFocusOfThread->m_threadId << std::endl;\r
-         m_log << _T("\tCLASS:\t")\r
-               << m_currentFocusOfThread->m_className << std::endl;\r
-         m_log << _T("\tTITLE:\t")\r
-               << m_currentFocusOfThread->m_titleName << std::endl;\r
-         m_log << std::endl;\r
-         return;\r
+\r
+       Acquire a(&m_cs);\r
+       if (m_globalFocus.m_keymaps.empty()) {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("NO GLOBAL FOCUS") << std::endl;\r
+               m_currentFocusOfThread = NULL;\r
+               setCurrentKeymap(NULL);\r
+       } else {\r
+               if (m_currentFocusOfThread != &m_globalFocus) {\r
+                       Acquire a(&m_log, 1);\r
+                       m_log << _T("GLOBAL FOCUS") << std::endl;\r
+                       m_currentFocusOfThread = &m_globalFocus;\r
+                       setCurrentKeymap(m_globalFocus.m_keymaps.front());\r
+               }\r
        }\r
-      }\r
-    }\r
-    \r
-    _TCHAR className[GANA_MAX_ATOM_LENGTH];\r
-    if (GetClassName(hwndFore, className, NUMBER_OF(className)))\r
-    {\r
-      if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)\r
-      {\r
-       _TCHAR titleName[1024];\r
-       if (GetWindowText(hwndFore, titleName, NUMBER_OF(titleName)) == 0)\r
-         titleName[0] = _T('\0');\r
-       setFocus(hwndFore, threadId, className, titleName, true);\r
-       Acquire a(&m_log, 1);\r
-       m_log << _T("HWND:\t") << std::hex << reinterpret_cast<int>(hwndFore)\r
-             << std::dec << std::endl;\r
-       m_log << _T("THREADID:") << threadId << std::endl;\r
-       m_log << _T("CLASS:\t") << className << std::endl;\r
-       m_log << _T("TITLE:\t") << titleName << std::endl << std::endl;\r
-       goto restart;\r
-      }\r
-    }\r
-  }\r
-  \r
-  Acquire a(&m_cs);\r
-  if (m_globalFocus.m_keymaps.empty())\r
-  {\r
-    Acquire a(&m_log, 1);\r
-    m_log << _T("NO GLOBAL FOCUS") << std::endl;\r
-    m_currentFocusOfThread = NULL;\r
-    setCurrentKeymap(NULL);\r
-  }\r
-  else\r
-  {\r
-    if (m_currentFocusOfThread != &m_globalFocus)\r
-    {\r
-      Acquire a(&m_log, 1);\r
-      m_log << _T("GLOBAL FOCUS") << std::endl;\r
-      m_currentFocusOfThread = &m_globalFocus;\r
-      setCurrentKeymap(m_globalFocus.m_keymaps.front());\r
-    }\r
-  }\r
-  m_hwndFocus = NULL;\r
+       m_hwndFocus = NULL;\r
 }\r
 \r
 \r
@@ -138,1579 +126,1523 @@ void Engine::checkFocusWindow()
 // is modifier pressed ?\r
 bool Engine::isPressed(Modifier::Type i_mt)\r
 {\r
-  const Keymap::ModAssignments &ma = m_currentKeymap->getModAssignments(i_mt);\r
-  for (Keymap::ModAssignments::const_iterator i = ma.begin();\r
-       i != ma.end(); ++ i)\r
-    if ((*i).m_key->m_isPressed)\r
-      return true;\r
-  return false;\r
+       const Keymap::ModAssignments &ma = m_currentKeymap->getModAssignments(i_mt);\r
+       for (Keymap::ModAssignments::const_iterator i = ma.begin();\r
+                       i != ma.end(); ++ i)\r
+               if ((*i).m_key->m_isPressed)\r
+                       return true;\r
+       return false;\r
 }\r
 \r
 \r
 // fix modifier key (if fixed, return true)\r
 bool Engine::fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am)\r
 {\r
-  // for all modifier ...\r
-  for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)\r
-  {\r
-    // get modifier assignments (list of modifier keys)\r
-    const Keymap::ModAssignments &ma =\r
-      m_currentKeymap->getModAssignments(static_cast<Modifier::Type>(i));\r
-    \r
-    for (Keymap::ModAssignments::const_iterator\r
-          j = ma.begin(); j != ma.end(); ++ j)\r
-      if (io_mkey->m_key == (*j).m_key) // is io_mkey a modifier ?\r
-      {\r
-       {\r
-         Acquire a(&m_log, 1);\r
-         m_log << _T("* Modifier Key") << std::endl;\r
+       // for all modifier ...\r
+       for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i) {\r
+               // get modifier assignments (list of modifier keys)\r
+               const Keymap::ModAssignments &ma =\r
+                       m_currentKeymap->getModAssignments(static_cast<Modifier::Type>(i));\r
+\r
+               for (Keymap::ModAssignments::const_iterator\r
+                               j = ma.begin(); j != ma.end(); ++ j)\r
+                       if (io_mkey->m_key == (*j).m_key) { // is io_mkey a modifier ?\r
+                               {\r
+                                       Acquire a(&m_log, 1);\r
+                                       m_log << _T("* Modifier Key") << std::endl;\r
+                               }\r
+                               // set dontcare for this modifier\r
+                               io_mkey->m_modifier.dontcare(static_cast<Modifier::Type>(i));\r
+                               *o_am = (*j).m_assignMode;\r
+                               return true;\r
+                       }\r
        }\r
-       // set dontcare for this modifier\r
-       io_mkey->m_modifier.dontcare(static_cast<Modifier::Type>(i));\r
-       *o_am = (*j).m_assignMode;\r
-       return true;\r
-      }\r
-  }\r
-  *o_am = Keymap::AM_notModifier;\r
-  return false;\r
+       *o_am = Keymap::AM_notModifier;\r
+       return false;\r
 }\r
 \r
 \r
 // output to m_log\r
 void Engine::outputToLog(const Key *i_key, const ModifiedKey &i_mkey,\r
-                        int i_debugLevel)\r
+                                                int i_debugLevel)\r
 {\r
-  size_t i;\r
-  Acquire a(&m_log, i_debugLevel);\r
-\r
-  // output scan codes\r
-  for (i = 0; i < i_key->getScanCodesSize(); ++ i)\r
-  {\r
-    if (i_key->getScanCodes()[i].m_flags & ScanCode::E0) m_log << _T("E0-");\r
-    if (i_key->getScanCodes()[i].m_flags & ScanCode::E1) m_log << _T("E1-");\r
-    if (!(i_key->getScanCodes()[i].m_flags & ScanCode::E0E1))\r
-      m_log << _T("   ");\r
-    m_log << _T("0x") << std::hex << std::setw(2) << std::setfill(_T('0'))\r
-         << static_cast<int>(i_key->getScanCodes()[i].m_scan)\r
-         << std::dec << _T(" ");\r
-  }\r
-  \r
-  if (!i_mkey.m_key) // key corresponds to no phisical key\r
-  {\r
-    m_log << std::endl;\r
-    return;\r
-  }\r
-  \r
-  m_log << _T("  ") << i_mkey << std::endl;\r
+       size_t i;\r
+       Acquire a(&m_log, i_debugLevel);\r
+\r
+       // output scan codes\r
+       for (i = 0; i < i_key->getScanCodesSize(); ++ i) {\r
+               if (i_key->getScanCodes()[i].m_flags & ScanCode::E0) m_log << _T("E0-");\r
+               if (i_key->getScanCodes()[i].m_flags & ScanCode::E1) m_log << _T("E1-");\r
+               if (!(i_key->getScanCodes()[i].m_flags & ScanCode::E0E1))\r
+                       m_log << _T("   ");\r
+               m_log << _T("0x") << std::hex << std::setw(2) << std::setfill(_T('0'))\r
+               << static_cast<int>(i_key->getScanCodes()[i].m_scan)\r
+               << std::dec << _T(" ");\r
+       }\r
+\r
+       if (!i_mkey.m_key) { // key corresponds to no phisical key\r
+               m_log << std::endl;\r
+               return;\r
+       }\r
+\r
+       m_log << _T("  ") << i_mkey << std::endl;\r
 }\r
 \r
 \r
 // describe bindings\r
 void Engine::describeBindings()\r
 {\r
-  Acquire a(&m_log, 0);\r
+       Acquire a(&m_log, 0);\r
 \r
-  Keymap::DescribeParam dp;\r
-  for (KeymapPtrList::iterator i = m_currentFocusOfThread->m_keymaps.begin();\r
-       i != m_currentFocusOfThread->m_keymaps.end(); ++ i)\r
-    (*i)->describe(m_log, &dp);\r
-  m_log << std::endl;\r
+       Keymap::DescribeParam dp;\r
+       for (KeymapPtrList::iterator i = m_currentFocusOfThread->m_keymaps.begin();\r
+                       i != m_currentFocusOfThread->m_keymaps.end(); ++ i)\r
+               (*i)->describe(m_log, &dp);\r
+       m_log << std::endl;\r
 }\r
 \r
 \r
 // update m_lastPressedKey\r
 void Engine::updateLastPressedKey(Key *i_key)\r
 {\r
-  m_lastPressedKey[1] = m_lastPressedKey[0];\r
-  m_lastPressedKey[0] = i_key;\r
+       m_lastPressedKey[1] = m_lastPressedKey[0];\r
+       m_lastPressedKey[0] = i_key;\r
 }\r
 \r
 // set current keymap\r
 void Engine::setCurrentKeymap(const Keymap *i_keymap, bool i_doesAddToHistory)\r
 {\r
-  if (i_doesAddToHistory)\r
-  {\r
-    m_keymapPrefixHistory.push_back(const_cast<Keymap *>(m_currentKeymap));\r
-    if (MAX_KEYMAP_PREFIX_HISTORY < m_keymapPrefixHistory.size())\r
-      m_keymapPrefixHistory.pop_front();\r
-  }\r
-  else\r
-    m_keymapPrefixHistory.clear();\r
-  m_currentKeymap = i_keymap;\r
+       if (i_doesAddToHistory) {\r
+               m_keymapPrefixHistory.push_back(const_cast<Keymap *>(m_currentKeymap));\r
+               if (MAX_KEYMAP_PREFIX_HISTORY < m_keymapPrefixHistory.size())\r
+                       m_keymapPrefixHistory.pop_front();\r
+       } else\r
+               m_keymapPrefixHistory.clear();\r
+       m_currentKeymap = i_keymap;\r
 }\r
 \r
 \r
 // get current modifiers\r
 Modifier Engine::getCurrentModifiers(Key *i_key, bool i_isPressed)\r
 {\r
-  Modifier cmods;\r
-  cmods.add(m_currentLock);\r
-\r
-  cmods.press(Modifier::Type_Shift  , isPressed(Modifier::Type_Shift  ));\r
-  cmods.press(Modifier::Type_Alt    , isPressed(Modifier::Type_Alt    ));\r
-  cmods.press(Modifier::Type_Control, isPressed(Modifier::Type_Control));\r
-  cmods.press(Modifier::Type_Windows, isPressed(Modifier::Type_Windows));\r
-  cmods.press(Modifier::Type_Up     , !i_isPressed);\r
-  cmods.press(Modifier::Type_Down   , i_isPressed);\r
-\r
-  cmods.press(Modifier::Type_Repeat , false);\r
-  if (m_lastPressedKey[0] == i_key)\r
-  {\r
-    if (i_isPressed)\r
-      cmods.press(Modifier::Type_Repeat, true);\r
-    else\r
-      if (m_lastPressedKey[1] == i_key)\r
-       cmods.press(Modifier::Type_Repeat, true);\r
-  }\r
-\r
-  for (int i = Modifier::Type_Mod0; i <= Modifier::Type_Mod9; ++ i)\r
-    cmods.press(static_cast<Modifier::Type>(i),\r
-               isPressed(static_cast<Modifier::Type>(i)));\r
-  \r
-  return cmods;\r
+       Modifier cmods;\r
+       cmods.add(m_currentLock);\r
+\r
+       cmods.press(Modifier::Type_Shift  , isPressed(Modifier::Type_Shift  ));\r
+       cmods.press(Modifier::Type_Alt    , isPressed(Modifier::Type_Alt    ));\r
+       cmods.press(Modifier::Type_Control, isPressed(Modifier::Type_Control));\r
+       cmods.press(Modifier::Type_Windows, isPressed(Modifier::Type_Windows));\r
+       cmods.press(Modifier::Type_Up     , !i_isPressed);\r
+       cmods.press(Modifier::Type_Down   , i_isPressed);\r
+\r
+       cmods.press(Modifier::Type_Repeat , false);\r
+       if (m_lastPressedKey[0] == i_key) {\r
+               if (i_isPressed)\r
+                       cmods.press(Modifier::Type_Repeat, true);\r
+               else\r
+                       if (m_lastPressedKey[1] == i_key)\r
+                               cmods.press(Modifier::Type_Repeat, true);\r
+       }\r
+\r
+       for (int i = Modifier::Type_Mod0; i <= Modifier::Type_Mod9; ++ i)\r
+               cmods.press(static_cast<Modifier::Type>(i),\r
+                                       isPressed(static_cast<Modifier::Type>(i)));\r
+\r
+       return cmods;\r
 }\r
 \r
 \r
 // generate keyboard event for a key\r
 void Engine::generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign)\r
 {\r
-  // check if key is event\r
-  bool isEvent = false;\r
-  for (Key **e = Event::events; *e; ++ e)\r
-    if (*e == i_key)\r
-    {\r
-      isEvent = true;\r
-      break;\r
-    }\r
-\r
-  bool isAlreadyReleased = false;\r
-    \r
-  if (!isEvent)\r
-  {\r
-    if (i_doPress && !i_key->m_isPressedOnWin32)\r
-      ++ m_currentKeyPressCountOnWin32;\r
-    else if (!i_doPress)\r
-    {\r
-      if (i_key->m_isPressedOnWin32)\r
-       -- m_currentKeyPressCountOnWin32;\r
-      else\r
-       isAlreadyReleased = true;\r
-    }\r
-    i_key->m_isPressedOnWin32 = i_doPress;\r
-    \r
-    if (i_isByAssign)\r
-      i_key->m_isPressedByAssign = i_doPress;\r
-\r
-    Key *sync = m_setting->m_keyboard.getSyncKey();\r
-    \r
-    if (!isAlreadyReleased || i_key == sync)\r
-    {\r
-      KEYBOARD_INPUT_DATA kid = { 0, 0, 0, 0, 0 };\r
-      const ScanCode *sc = i_key->getScanCodes();\r
-      for (size_t i = 0; i < i_key->getScanCodesSize(); ++ i)\r
-      {\r
-       kid.MakeCode = sc[i].m_scan;\r
-       kid.Flags = sc[i].m_flags;\r
-       if (!i_doPress)\r
-         kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
-#ifdef NO_DRIVER\r
-       injectInput(&kid, NULL);\r
-#else // !NO_DRIVER\r
-       DWORD len;\r
-       WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);\r
-       CHECK_TRUE( GetOverlappedResult(m_device, &m_ol, &len, TRUE) );\r
-#endif // !NO_DRIVER\r
-      }\r
-      \r
-      m_lastGeneratedKey = i_doPress ? i_key : NULL;\r
-    }\r
-  }\r
-  \r
-  {\r
-    Acquire a(&m_log, 1);\r
-    m_log << _T("\t\t    =>\t");\r
-    if (isAlreadyReleased)\r
-      m_log << _T("(already released) ");\r
-  }\r
-  ModifiedKey mkey(i_key);\r
-  mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);\r
-  mkey.m_modifier.on(Modifier::Type_Down, i_doPress);\r
-  outputToLog(i_key, mkey, 1);\r
+       // check if key is event\r
+       bool isEvent = false;\r
+       for (Key **e = Event::events; *e; ++ e)\r
+               if (*e == i_key) {\r
+                       isEvent = true;\r
+                       break;\r
+               }\r
+\r
+       bool isAlreadyReleased = false;\r
+\r
+       if (!isEvent) {\r
+               if (i_doPress && !i_key->m_isPressedOnWin32)\r
+                       ++ m_currentKeyPressCountOnWin32;\r
+               else if (!i_doPress) {\r
+                       if (i_key->m_isPressedOnWin32)\r
+                               -- m_currentKeyPressCountOnWin32;\r
+                       else\r
+                               isAlreadyReleased = true;\r
+               }\r
+               i_key->m_isPressedOnWin32 = i_doPress;\r
+\r
+               if (i_isByAssign)\r
+                       i_key->m_isPressedByAssign = i_doPress;\r
+\r
+               Key *sync = m_setting->m_keyboard.getSyncKey();\r
+\r
+               if (!isAlreadyReleased || i_key == sync) {\r
+                       KEYBOARD_INPUT_DATA kid = { 0, 0, 0, 0, 0 };\r
+                       const ScanCode *sc = i_key->getScanCodes();\r
+                       for (size_t i = 0; i < i_key->getScanCodesSize(); ++ i) {\r
+                               kid.MakeCode = sc[i].m_scan;\r
+                               kid.Flags = sc[i].m_flags;\r
+                               if (!i_doPress)\r
+                                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+                               injectInput(&kid, NULL);\r
+                       }\r
+\r
+                       m_lastGeneratedKey = i_doPress ? i_key : NULL;\r
+               }\r
+       }\r
+\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("\t\t    =>\t");\r
+               if (isAlreadyReleased)\r
+                       m_log << _T("(already released) ");\r
+       }\r
+       ModifiedKey mkey(i_key);\r
+       mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);\r
+       mkey.m_modifier.on(Modifier::Type_Down, i_doPress);\r
+       outputToLog(i_key, mkey, 1);\r
 }\r
 \r
 \r
 // genete event\r
 void Engine::generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event)\r
 {\r
-  // generate\r
-  i_c.m_keymap = i_keymap;\r
-  i_c.m_mkey.m_key = i_event;\r
-  if (const Keymap::KeyAssignment *keyAssign =\r
-      i_c.m_keymap->searchAssignment(i_c.m_mkey))\r
-  {\r
-    {\r
-      Acquire a(&m_log, 1);\r
-      m_log << std::endl << _T("           ")\r
-           << i_event->getName() << std::endl;\r
-    }\r
-    generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);\r
-  }\r
+       // generate\r
+       i_c.m_keymap = i_keymap;\r
+       i_c.m_mkey.m_key = i_event;\r
+       if (const Keymap::KeyAssignment *keyAssign =\r
+                               i_c.m_keymap->searchAssignment(i_c.m_mkey)) {\r
+               {\r
+                       Acquire a(&m_log, 1);\r
+                       m_log << std::endl << _T("           ")\r
+                       << i_event->getName() << std::endl;\r
+               }\r
+               generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);\r
+       }\r
 }\r
 \r
 \r
 // genete modifier events\r
 void Engine::generateModifierEvents(const Modifier &i_mod)\r
 {\r
-  {\r
-    Acquire a(&m_log, 1);\r
-    m_log << _T("* Gen Modifiers\t{") << std::endl;\r
-  }\r
-\r
-  for (int i = Modifier::Type_begin; i < Modifier::Type_BASIC; ++ i)\r
-  {\r
-    Keyboard::Mods &mods =\r
-      m_setting->m_keyboard.getModifiers(static_cast<Modifier::Type>(i));\r
-\r
-    if (i_mod.isDontcare(static_cast<Modifier::Type>(i)))\r
-      // no need to process\r
-      ;\r
-    else if (i_mod.isPressed(static_cast<Modifier::Type>(i)))\r
-      // we have to press this modifier\r
-    {\r
-      bool noneIsPressed = true;\r
-      bool noneIsPressedByAssign = true;\r
-      for (Keyboard::Mods::iterator i = mods.begin(); i != mods.end(); ++ i)\r
-      {\r
-       if ((*i)->m_isPressedOnWin32)\r
-         noneIsPressed = false;\r
-       if ((*i)->m_isPressedByAssign)\r
-         noneIsPressedByAssign = false;\r
-      }\r
-      if (noneIsPressed)\r
-      {\r
-       if (noneIsPressedByAssign)\r
-         generateKeyEvent(mods.front(), true, false);\r
-       else\r
-         for (Keyboard::Mods::iterator\r
-                i = mods.begin(); i != mods.end(); ++ i)\r
-           if ((*i)->m_isPressedByAssign)\r
-             generateKeyEvent((*i), true, false);\r
-      }\r
-    }\r
-\r
-    else\r
-      // we have to release this modifier\r
-    {\r
-      // avoid such sequences as  "Alt U-ALt" or "Windows U-Windows"\r
-      if (i == Modifier::Type_Alt || i == Modifier::Type_Windows)\r
-      {\r
-       for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)\r
-         if ((*j) == m_lastGeneratedKey)\r
-         {\r
-           Keyboard::Mods *mods =\r
-             &m_setting->m_keyboard.getModifiers(Modifier::Type_Shift);\r
-           if (mods->size() == 0)\r
-             mods = &m_setting->m_keyboard.getModifiers(\r
-               Modifier::Type_Control);\r
-           if (0 < mods->size())\r
-           {\r
-             generateKeyEvent(mods->front(), true, false);\r
-             generateKeyEvent(mods->front(), false, false);\r
-           }\r
-           break;\r
-         }\r
-      }\r
-      \r
-      for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)\r
-      {\r
-       if ((*j)->m_isPressedOnWin32)\r
-         generateKeyEvent((*j), false, false);\r
-      }\r
-    }\r
-  }\r
-  \r
-  {\r
-    Acquire a(&m_log, 1);\r
-    m_log << _T("\t\t}") << std::endl;\r
-  }\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("* Gen Modifiers\t{") << std::endl;\r
+       }\r
+\r
+       for (int i = Modifier::Type_begin; i < Modifier::Type_BASIC; ++ i) {\r
+               Keyboard::Mods &mods =\r
+                       m_setting->m_keyboard.getModifiers(static_cast<Modifier::Type>(i));\r
+\r
+               if (i_mod.isDontcare(static_cast<Modifier::Type>(i)))\r
+                       // no need to process\r
+                       ;\r
+               else if (i_mod.isPressed(static_cast<Modifier::Type>(i)))\r
+                       // we have to press this modifier\r
+               {\r
+                       bool noneIsPressed = true;\r
+                       bool noneIsPressedByAssign = true;\r
+                       for (Keyboard::Mods::iterator i = mods.begin(); i != mods.end(); ++ i) {\r
+                               if ((*i)->m_isPressedOnWin32)\r
+                                       noneIsPressed = false;\r
+                               if ((*i)->m_isPressedByAssign)\r
+                                       noneIsPressedByAssign = false;\r
+                       }\r
+                       if (noneIsPressed) {\r
+                               if (noneIsPressedByAssign)\r
+                                       generateKeyEvent(mods.front(), true, false);\r
+                               else\r
+                                       for (Keyboard::Mods::iterator\r
+                                                       i = mods.begin(); i != mods.end(); ++ i)\r
+                                               if ((*i)->m_isPressedByAssign)\r
+                                                       generateKeyEvent((*i), true, false);\r
+                       }\r
+               }\r
+\r
+               else\r
+                       // we have to release this modifier\r
+               {\r
+                       // avoid such sequences as  "Alt U-ALt" or "Windows U-Windows"\r
+                       if (i == Modifier::Type_Alt || i == Modifier::Type_Windows) {\r
+                               for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)\r
+                                       if ((*j) == m_lastGeneratedKey) {\r
+                                               Keyboard::Mods *mods =\r
+                                                       &m_setting->m_keyboard.getModifiers(Modifier::Type_Shift);\r
+                                               if (mods->size() == 0)\r
+                                                       mods = &m_setting->m_keyboard.getModifiers(\r
+                                                                          Modifier::Type_Control);\r
+                                               if (0 < mods->size()) {\r
+                                                       generateKeyEvent(mods->front(), true, false);\r
+                                                       generateKeyEvent(mods->front(), false, false);\r
+                                               }\r
+                                               break;\r
+                                       }\r
+                       }\r
+\r
+                       for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j) {\r
+                               if ((*j)->m_isPressedOnWin32)\r
+                                       generateKeyEvent((*j), false, false);\r
+                       }\r
+               }\r
+       }\r
+\r
+       {\r
+               Acquire a(&m_log, 1);\r
+               m_log << _T("\t\t}") << std::endl;\r
+       }\r
 }\r
 \r
 \r
 // generate keyboard events for action\r
 void Engine::generateActionEvents(const Current &i_c, const Action *i_a,\r
-                                 bool i_doPress)\r
+                                                                 bool i_doPress)\r
 {\r
-  switch (i_a->getType())\r
-  {\r
-    // key\r
-    case Action::Type_key:\r
-    {\r
-      const ModifiedKey &mkey\r
-       = reinterpret_cast<ActionKey *>(\r
-         const_cast<Action *>(i_a))->m_modifiedKey;\r
-\r
-      // release\r
-      if (!i_doPress &&\r
-         (mkey.m_modifier.isOn(Modifier::Type_Up) ||\r
-          mkey.m_modifier.isDontcare(Modifier::Type_Up)))\r
-       generateKeyEvent(mkey.m_key, false, true);\r
-\r
-      // press\r
-      else if (i_doPress &&\r
-              (mkey.m_modifier.isOn(Modifier::Type_Down) ||\r
-               mkey.m_modifier.isDontcare(Modifier::Type_Down)))\r
-      {\r
-       Modifier modifier = mkey.m_modifier;\r
-       modifier.add(i_c.m_mkey.m_modifier);\r
-       generateModifierEvents(modifier);\r
-       generateKeyEvent(mkey.m_key, true, true);\r
-      }\r
-      break;\r
-    }\r
-\r
-    // keyseq\r
-    case Action::Type_keySeq:\r
-    {\r
-      const ActionKeySeq *aks = reinterpret_cast<const ActionKeySeq *>(i_a);\r
-      generateKeySeqEvents(i_c, aks->m_keySeq,\r
-                          i_doPress ? Part_down : Part_up);\r
-      break;\r
-    }\r
-\r
-    // function\r
-    case Action::Type_function:\r
-    {\r
-      const ActionFunction *af = reinterpret_cast<const ActionFunction *>(i_a);\r
-      bool is_up = (!i_doPress &&\r
-                   (af->m_modifier.isOn(Modifier::Type_Up) ||\r
-                    af->m_modifier.isDontcare(Modifier::Type_Up)));\r
-      bool is_down = (i_doPress &&\r
-                     (af->m_modifier.isOn(Modifier::Type_Down) ||\r
-                      af->m_modifier.isDontcare(Modifier::Type_Down)));\r
-\r
-      if (!is_down && !is_up)\r
-       break;\r
-      \r
-      {\r
-       Acquire a(&m_log, 1);\r
-       m_log << _T("\t\t     >\t") << af->m_functionData;\r
-      }\r
-      \r
-      FunctionParam param;\r
-      param.m_isPressed = i_doPress;\r
-      param.m_hwnd = m_currentFocusOfThread->m_hwndFocus;\r
-      param.m_c = i_c;\r
-      param.m_doesNeedEndl = true;\r
-      param.m_af = af;\r
-      \r
-      param.m_c.m_mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);\r
-      param.m_c.m_mkey.m_modifier.on(Modifier::Type_Down, i_doPress);\r
-\r
-      af->m_functionData->exec(this, &param);\r
-      \r
-      if (param.m_doesNeedEndl)\r
-      {\r
-       Acquire a(&m_log, 1);\r
-       m_log << std::endl;\r
-      }\r
-      break;\r
-    }\r
-  }\r
+       switch (i_a->getType()) {\r
+               // key\r
+       case Action::Type_key: {\r
+               const ModifiedKey &mkey\r
+               = reinterpret_cast<ActionKey *>(\r
+                         const_cast<Action *>(i_a))->m_modifiedKey;\r
+\r
+               // release\r
+               if (!i_doPress &&\r
+                               (mkey.m_modifier.isOn(Modifier::Type_Up) ||\r
+                                mkey.m_modifier.isDontcare(Modifier::Type_Up)))\r
+                       generateKeyEvent(mkey.m_key, false, true);\r
+\r
+               // press\r
+               else if (i_doPress &&\r
+                                (mkey.m_modifier.isOn(Modifier::Type_Down) ||\r
+                                 mkey.m_modifier.isDontcare(Modifier::Type_Down))) {\r
+                       Modifier modifier = mkey.m_modifier;\r
+                       modifier.add(i_c.m_mkey.m_modifier);\r
+                       generateModifierEvents(modifier);\r
+                       generateKeyEvent(mkey.m_key, true, true);\r
+               }\r
+               break;\r
+       }\r
+\r
+       // keyseq\r
+       case Action::Type_keySeq: {\r
+               const ActionKeySeq *aks = reinterpret_cast<const ActionKeySeq *>(i_a);\r
+               generateKeySeqEvents(i_c, aks->m_keySeq,\r
+                                                        i_doPress ? Part_down : Part_up);\r
+               break;\r
+       }\r
+\r
+       // function\r
+       case Action::Type_function: {\r
+               const ActionFunction *af = reinterpret_cast<const ActionFunction *>(i_a);\r
+               bool is_up = (!i_doPress &&\r
+                                         (af->m_modifier.isOn(Modifier::Type_Up) ||\r
+                                          af->m_modifier.isDontcare(Modifier::Type_Up)));\r
+               bool is_down = (i_doPress &&\r
+                                               (af->m_modifier.isOn(Modifier::Type_Down) ||\r
+                                                af->m_modifier.isDontcare(Modifier::Type_Down)));\r
+\r
+               if (!is_down && !is_up)\r
+                       break;\r
+\r
+               {\r
+                       Acquire a(&m_log, 1);\r
+                       m_log << _T("\t\t     >\t") << af->m_functionData;\r
+               }\r
+\r
+               FunctionParam param;\r
+               param.m_isPressed = i_doPress;\r
+               param.m_hwnd = m_currentFocusOfThread->m_hwndFocus;\r
+               param.m_c = i_c;\r
+               param.m_doesNeedEndl = true;\r
+               param.m_af = af;\r
+\r
+               param.m_c.m_mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);\r
+               param.m_c.m_mkey.m_modifier.on(Modifier::Type_Down, i_doPress);\r
+\r
+               af->m_functionData->exec(this, &param);\r
+\r
+               if (param.m_doesNeedEndl) {\r
+                       Acquire a(&m_log, 1);\r
+                       m_log << std::endl;\r
+               }\r
+               break;\r
+       }\r
+       }\r
 }\r
 \r
 \r
 // generate keyboard events for keySeq\r
 void Engine::generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,\r
-                                 Part i_part)\r
+                                                                 Part i_part)\r
 {\r
-  const KeySeq::Actions &actions = i_keySeq->getActions();\r
-  if (actions.empty())\r
-    return;\r
-  if (i_part == Part_up)\r
-    generateActionEvents(i_c, actions[actions.size() - 1], false);\r
-  else\r
-  {\r
-    size_t i;\r
-    for (i = 0 ; i < actions.size() - 1; ++ i)\r
-    {\r
-      generateActionEvents(i_c, actions[i], true);\r
-      generateActionEvents(i_c, actions[i], false);\r
-    }\r
-    generateActionEvents(i_c, actions[i], true);\r
-    if (i_part == Part_all)\r
-      generateActionEvents(i_c, actions[i], false);\r
-  }\r
+       const KeySeq::Actions &actions = i_keySeq->getActions();\r
+       if (actions.empty())\r
+               return;\r
+       if (i_part == Part_up)\r
+               generateActionEvents(i_c, actions[actions.size() - 1], false);\r
+       else {\r
+               size_t i;\r
+               for (i = 0 ; i < actions.size() - 1; ++ i) {\r
+                       generateActionEvents(i_c, actions[i], true);\r
+                       generateActionEvents(i_c, actions[i], false);\r
+               }\r
+               generateActionEvents(i_c, actions[i], true);\r
+               if (i_part == Part_all)\r
+                       generateActionEvents(i_c, actions[i], false);\r
+       }\r
 }\r
 \r
 \r
 // generate keyboard events for current key\r
 void Engine::generateKeyboardEvents(const Current &i_c)\r
 {\r
-  if (++ m_generateKeyboardEventsRecursionGuard ==\r
-      MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT)\r
-  {\r
-    Acquire a(&m_log);\r
-    m_log << _T("error: too deep keymap recursion.  there may be a loop.")\r
-         << std::endl;\r
-    return;\r
-  }\r
-\r
-  const Keymap::KeyAssignment *keyAssign\r
-    = i_c.m_keymap->searchAssignment(i_c.m_mkey);\r
-  if (!keyAssign)\r
-  {\r
-    const KeySeq *keySeq = i_c.m_keymap->getDefaultKeySeq();\r
-    ASSERT( keySeq );\r
-    generateKeySeqEvents(i_c, keySeq, i_c.isPressed() ? Part_down : Part_up);\r
-  }\r
-  else\r
-  {\r
-    if (keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Up) ||\r
-       keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Down))\r
-      generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);\r
-    else\r
-      generateKeySeqEvents(i_c, keyAssign->m_keySeq,\r
-                          i_c.isPressed() ? Part_down : Part_up);\r
-  }\r
-  m_generateKeyboardEventsRecursionGuard --;\r
+       if (++ m_generateKeyboardEventsRecursionGuard ==\r
+                       MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT) {\r
+               Acquire a(&m_log);\r
+               m_log << _T("error: too deep keymap recursion.  there may be a loop.")\r
+               << std::endl;\r
+               return;\r
+       }\r
+\r
+       const Keymap::KeyAssignment *keyAssign\r
+       = i_c.m_keymap->searchAssignment(i_c.m_mkey);\r
+       if (!keyAssign) {\r
+               const KeySeq *keySeq = i_c.m_keymap->getDefaultKeySeq();\r
+               ASSERT( keySeq );\r
+               generateKeySeqEvents(i_c, keySeq, i_c.isPressed() ? Part_down : Part_up);\r
+       } else {\r
+               if (keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Up) ||\r
+                               keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Down))\r
+                       generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);\r
+               else\r
+                       generateKeySeqEvents(i_c, keyAssign->m_keySeq,\r
+                                                                i_c.isPressed() ? Part_down : Part_up);\r
+       }\r
+       m_generateKeyboardEventsRecursionGuard --;\r
 }\r
 \r
 \r
 // generate keyboard events for current key\r
 void Engine::beginGeneratingKeyboardEvents(\r
-  const Current &i_c, bool i_isModifier)\r
+       const Current &i_c, bool i_isModifier)\r
 {\r
-  //             (1)             (2)             (3)  (4)   (1)\r
-  // up/down:    D-              U-              D-   U-    D-\r
-  // keymap:     m_currentKeymap m_currentKeymap X    X     m_currentKeymap\r
-  // memo:       &Prefix(X)      ...             ...  ...   ...\r
-  // m_isPrefix: false           true            true false false\r
-\r
-  Current cnew(i_c);\r
-\r
-  bool isPhysicallyPressed\r
-    = cnew.m_mkey.m_modifier.isPressed(Modifier::Type_Down);\r
-  \r
-  // substitute\r
-  ModifiedKey mkey = m_setting->m_keyboard.searchSubstitute(cnew.m_mkey);\r
-  if (mkey.m_key)\r
-  {\r
-    cnew.m_mkey = mkey;\r
-    if (isPhysicallyPressed)\r
-    {\r
-      cnew.m_mkey.m_modifier.off(Modifier::Type_Up);\r
-      cnew.m_mkey.m_modifier.on(Modifier::Type_Down);\r
-    }\r
-    else\r
-    {\r
-      cnew.m_mkey.m_modifier.on(Modifier::Type_Up);\r
-      cnew.m_mkey.m_modifier.off(Modifier::Type_Down);\r
-    }\r
-    for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)\r
-    {\r
-      Modifier::Type type = static_cast<Modifier::Type>(i);\r
-      if (cnew.m_mkey.m_modifier.isDontcare(type) &&\r
-         !i_c.m_mkey.m_modifier.isDontcare(type))\r
-       cnew.m_mkey.m_modifier.press(\r
-         type, i_c.m_mkey.m_modifier.isPressed(type));\r
-    }\r
-    \r
-    {\r
-      Acquire a(&m_log, 1);\r
-      m_log << _T("* substitute") << std::endl;\r
-    }\r
-    outputToLog(mkey.m_key, cnew.m_mkey, 1);\r
-  }\r
-  \r
-  // for prefix key\r
-  const Keymap *tmpKeymap = m_currentKeymap;\r
-  if (i_isModifier || !m_isPrefix) ; \r
-  else if (isPhysicallyPressed)                        // when (3)\r
-    m_isPrefix = false;\r
-  else if (!isPhysicallyPressed)               // when (2)\r
-    m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();\r
-  \r
-  // for m_emacsEditKillLine function\r
-  m_emacsEditKillLine.m_doForceReset = !i_isModifier;\r
-\r
-  // generate key event !\r
-  m_generateKeyboardEventsRecursionGuard = 0;\r
-  if (isPhysicallyPressed)\r
-    generateEvents(cnew, cnew.m_keymap, &Event::before_key_down);\r
-  generateKeyboardEvents(cnew);\r
-  if (!isPhysicallyPressed)\r
-    generateEvents(cnew, cnew.m_keymap, &Event::after_key_up);\r
-      \r
-  // for m_emacsEditKillLine function\r
-  if (m_emacsEditKillLine.m_doForceReset)\r
-    m_emacsEditKillLine.reset();\r
-\r
-  // for prefix key\r
-  if (i_isModifier)\r
-    ;\r
-  else if (!m_isPrefix)                                // when (1), (4)\r
-    m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();\r
-  else if (!isPhysicallyPressed)               // when (2)\r
-    m_currentKeymap = tmpKeymap;\r
+       //             (1)             (2)             (3)  (4)   (1)\r
+       // up/down:    D-              U-              D-   U-    D-\r
+       // keymap:     m_currentKeymap m_currentKeymap X    X     m_currentKeymap\r
+       // memo:       &Prefix(X)      ...             ...  ...   ...\r
+       // m_isPrefix: false           true            true false false\r
+\r
+       Current cnew(i_c);\r
+\r
+       bool isPhysicallyPressed\r
+       = cnew.m_mkey.m_modifier.isPressed(Modifier::Type_Down);\r
+\r
+       // substitute\r
+       ModifiedKey mkey = m_setting->m_keyboard.searchSubstitute(cnew.m_mkey);\r
+       if (mkey.m_key) {\r
+               cnew.m_mkey = mkey;\r
+               if (isPhysicallyPressed) {\r
+                       cnew.m_mkey.m_modifier.off(Modifier::Type_Up);\r
+                       cnew.m_mkey.m_modifier.on(Modifier::Type_Down);\r
+               } else {\r
+                       cnew.m_mkey.m_modifier.on(Modifier::Type_Up);\r
+                       cnew.m_mkey.m_modifier.off(Modifier::Type_Down);\r
+               }\r
+               for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i) {\r
+                       Modifier::Type type = static_cast<Modifier::Type>(i);\r
+                       if (cnew.m_mkey.m_modifier.isDontcare(type) &&\r
+                                       !i_c.m_mkey.m_modifier.isDontcare(type))\r
+                               cnew.m_mkey.m_modifier.press(\r
+                                       type, i_c.m_mkey.m_modifier.isPressed(type));\r
+               }\r
+\r
+               {\r
+                       Acquire a(&m_log, 1);\r
+                       m_log << _T("* substitute") << std::endl;\r
+               }\r
+               outputToLog(mkey.m_key, cnew.m_mkey, 1);\r
+       }\r
+\r
+       // for prefix key\r
+       const Keymap *tmpKeymap = m_currentKeymap;\r
+       if (i_isModifier || !m_isPrefix) ;\r
+       else if (isPhysicallyPressed)                   // when (3)\r
+               m_isPrefix = false;\r
+       else if (!isPhysicallyPressed)          // when (2)\r
+               m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();\r
+\r
+       // for m_emacsEditKillLine function\r
+       m_emacsEditKillLine.m_doForceReset = !i_isModifier;\r
+\r
+       // generate key event !\r
+       m_generateKeyboardEventsRecursionGuard = 0;\r
+       if (isPhysicallyPressed)\r
+               generateEvents(cnew, cnew.m_keymap, &Event::before_key_down);\r
+       generateKeyboardEvents(cnew);\r
+       if (!isPhysicallyPressed)\r
+               generateEvents(cnew, cnew.m_keymap, &Event::after_key_up);\r
+\r
+       // for m_emacsEditKillLine function\r
+       if (m_emacsEditKillLine.m_doForceReset)\r
+               m_emacsEditKillLine.reset();\r
+\r
+       // for prefix key\r
+       if (i_isModifier)\r
+               ;\r
+       else if (!m_isPrefix)                           // when (1), (4)\r
+               m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();\r
+       else if (!isPhysicallyPressed)          // when (2)\r
+               m_currentKeymap = tmpKeymap;\r
 }\r
 \r
 \r
-#ifdef NO_DRIVER\r
 unsigned int Engine::injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw)\r
 {\r
-  INPUT kid;\r
-  kid.type = INPUT_KEYBOARD;\r
-  kid.ki.wVk = 0;\r
-  kid.ki.wScan = i_kid->MakeCode;\r
-  kid.ki.dwFlags = KEYEVENTF_SCANCODE;\r
-  kid.ki.time = i_kidRaw ? i_kidRaw->time : 0;\r
-  kid.ki.dwExtraInfo = i_kidRaw ? i_kidRaw->dwExtraInfo : 0;\r
-  if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK)\r
-  {\r
-    kid.ki.dwFlags |= KEYEVENTF_KEYUP;\r
-  }\r
-  if (i_kid->Flags & KEYBOARD_INPUT_DATA::E0)\r
-  {\r
-    kid.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-  }\r
-  SendInput(1, &kid, sizeof(kid));\r
-  return 1;\r
+       if (i_kid->Flags & KEYBOARD_INPUT_DATA::E1) {\r
+               INPUT kid[2];\r
+               int count = 1;\r
+\r
+               kid[0].type = INPUT_MOUSE;\r
+               kid[0].mi.dx = 0;\r
+               kid[0].mi.dy = 0;\r
+               kid[0].mi.time = 0;\r
+               kid[0].mi.mouseData = 0;\r
+               kid[0].mi.dwExtraInfo = 0;\r
+               switch (i_kid->MakeCode) {\r
+               case 1:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;\r
+                       } else {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;\r
+                       }\r
+                       break;\r
+               case 2:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_RIGHTUP;\r
+                       } else {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;\r
+                       }\r
+                       break;\r
+               case 3:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_MIDDLEUP;\r
+                       } else {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;\r
+                       }\r
+                       break;\r
+               case 4:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               return 1;\r
+                       } else {\r
+                               kid[0].mi.mouseData = WHEEL_DELTA;\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_WHEEL;\r
+                       }\r
+                       break;\r
+               case 5:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               return 1;\r
+                       } else {\r
+                               kid[0].mi.mouseData = -WHEEL_DELTA;\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_WHEEL;\r
+                       }\r
+                       break;\r
+               case 6:\r
+                       kid[0].mi.mouseData = XBUTTON1;\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_XUP;\r
+                       } else {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_XDOWN;\r
+                       }\r
+                       break;\r
+               case 7:\r
+                       kid[0].mi.mouseData = XBUTTON2;\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_XUP;\r
+                       } else {\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_XDOWN;\r
+                       }\r
+                       break;\r
+               case 8:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               return 1;\r
+                       } else {\r
+                               kid[0].mi.mouseData = WHEEL_DELTA;\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_HWHEEL;\r
+                       }\r
+                       break;\r
+               case 9:\r
+                       if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                               return 1;\r
+                       } else {\r
+                               kid[0].mi.mouseData = -WHEEL_DELTA;\r
+                               kid[0].mi.dwFlags = MOUSEEVENTF_HWHEEL;\r
+                       }\r
+                       break;\r
+               default:\r
+                       return 1;\r
+                       break;\r
+               }\r
+               if (!(i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) &&\r
+                       i_kid->MakeCode != 4 && i_kid->MakeCode != 5 &&\r
+                       i_kid->MakeCode != 8 && i_kid->MakeCode != 9) {\r
+                       HWND hwnd;\r
+                       POINT pt;\r
+\r
+                       if (GetCursorPos(&pt) && (hwnd = WindowFromPoint(pt))) {\r
+                               _TCHAR className[GANA_MAX_ATOM_LENGTH];\r
+                               if (GetClassName(hwnd, className, NUMBER_OF(className))) {\r
+                                       if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0) {\r
+                                               SetForegroundWindow(hwnd);\r
+                                       }\r
+                               }\r
+                       }\r
+                       if (m_dragging) {\r
+                               kid[0].mi.dx = 65535 * m_msllHookCurrent.pt.x / GetSystemMetrics(SM_CXVIRTUALSCREEN);\r
+                               kid[0].mi.dy = 65535 * m_msllHookCurrent.pt.y / GetSystemMetrics(SM_CYVIRTUALSCREEN);\r
+                               kid[0].mi.dwFlags |= MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK;\r
+\r
+                               kid[1].type = INPUT_MOUSE;\r
+                               kid[1].mi.dx = 65535 * pt.x / GetSystemMetrics(SM_CXVIRTUALSCREEN);\r
+                               kid[1].mi.dy = 65535 * pt.y / GetSystemMetrics(SM_CYVIRTUALSCREEN);\r
+                               kid[1].mi.time = 0;\r
+                               kid[1].mi.mouseData = 0;\r
+                               kid[1].mi.dwExtraInfo = 0;\r
+                               kid[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK;\r
+\r
+                               count = 2;\r
+                       }\r
+               }\r
+               SendInput(count, &kid[0], sizeof(kid[0]));\r
+       } else {\r
+               INPUT kid;\r
+\r
+               kid.type = INPUT_KEYBOARD;\r
+               kid.ki.wVk = 0;\r
+               kid.ki.wScan = i_kid->MakeCode;\r
+               kid.ki.dwFlags = KEYEVENTF_SCANCODE;\r
+               kid.ki.time = i_kidRaw ? i_kidRaw->time : 0;\r
+               kid.ki.dwExtraInfo = i_kidRaw ? i_kidRaw->dwExtraInfo : 0;\r
+               if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                       kid.ki.dwFlags |= KEYEVENTF_KEYUP;\r
+               }\r
+               if (i_kid->Flags & KEYBOARD_INPUT_DATA::E0) {\r
+                       kid.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
+               }\r
+               SendInput(1, &kid, sizeof(kid));\r
+       }\r
+       return 1;\r
 }\r
-#endif // NO_DRIVER\r
 \r
 \r
 // pop all pressed key on win32\r
 void Engine::keyboardResetOnWin32()\r
 {\r
-  for (Keyboard::KeyIterator\r
-        i = m_setting->m_keyboard.getKeyIterator();  *i; ++ i)\r
-  {\r
-    if ((*i)->m_isPressedOnWin32)\r
-      generateKeyEvent((*i), false, true);\r
-  }\r
+       for (Keyboard::KeyIterator\r
+                       i = m_setting->m_keyboard.getKeyIterator();  *i; ++ i) {\r
+               if ((*i)->m_isPressedOnWin32)\r
+                       generateKeyEvent((*i), false, true);\r
+       }\r
 }\r
 \r
 \r
-#ifdef NO_DRIVER\r
-unsigned int WINAPI Engine::keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid)\r
+unsigned int WINAPI Engine::keyboardDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam)\r
 {\r
-  return i_this->keyboardDetour(i_kid);\r
+       return i_this->keyboardDetour(reinterpret_cast<KBDLLHOOKSTRUCT*>(i_lParam));\r
 }\r
 \r
 unsigned int Engine::keyboardDetour(KBDLLHOOKSTRUCT *i_kid)\r
 {\r
 #if 0\r
-  Acquire a(&m_log, 1);\r
-  m_log << std::hex\r
+       Acquire a(&m_log, 1);\r
+       m_log << std::hex\r
        << _T("keyboardDetour: vkCode=") << i_kid->vkCode\r
        << _T(" scanCode=") << i_kid->scanCode\r
        << _T(" flags=") << i_kid->flags << std::endl;\r
 #endif\r
-  if (i_kid->flags & LLKHF_INJECTED)\r
-  {\r
-    return 0;\r
-  }\r
-  else\r
-  {\r
-    Key key;\r
-    KEYBOARD_INPUT_DATA kid;\r
-\r
-    kid.UnitId = 0;\r
-    kid.MakeCode = i_kid->scanCode;\r
-    kid.Flags = 0;\r
-    if (i_kid->flags & LLKHF_UP)\r
-    {\r
-      kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
-    }\r
-    if (i_kid->flags & LLKHF_EXTENDED)\r
-    {\r
-         kid.Flags |= KEYBOARD_INPUT_DATA::E0;\r
-    }\r
-    kid.Reserved = 0;\r
-    kid.ExtraInformation = 0;\r
-\r
-    Acquire a(&m_cskidq);\r
-    m_kidq.push_back(kid);\r
-    SetEvent(m_readEvent);\r
-    return 1;\r
-  }\r
+       if ((i_kid->flags & LLKHF_INJECTED) || !m_isEnabled) {\r
+               return 0;\r
+       } else {\r
+               Key key;\r
+               KEYBOARD_INPUT_DATA kid;\r
+\r
+               kid.UnitId = 0;\r
+               kid.MakeCode = i_kid->scanCode;\r
+               kid.Flags = 0;\r
+               if (i_kid->flags & LLKHF_UP) {\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+               }\r
+               if (i_kid->flags & LLKHF_EXTENDED) {\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::E0;\r
+               }\r
+               kid.Reserved = 0;\r
+               kid.ExtraInformation = 0;\r
+\r
+               WaitForSingleObject(m_queueMutex, INFINITE);\r
+               m_inputQueue->push_back(kid);\r
+               SetEvent(m_readEvent);\r
+               ReleaseMutex(m_queueMutex);\r
+               return 1;\r
+       }\r
 }\r
-#endif // NO_DRIVER\r
 \r
-// keyboard handler thread\r
-unsigned int WINAPI Engine::keyboardHandler(void *i_this)\r
+unsigned int WINAPI Engine::mouseDetour(Engine *i_this, WPARAM i_wParam, LPARAM i_lParam)\r
 {\r
-  reinterpret_cast<Engine *>(i_this)->keyboardHandler();\r
-  _endthreadex(0);\r
-  return 0;\r
+       return i_this->mouseDetour(i_wParam, reinterpret_cast<MSLLHOOKSTRUCT*>(i_lParam));\r
 }\r
-void Engine::keyboardHandler()\r
+\r
+unsigned int Engine::mouseDetour(WPARAM i_message, MSLLHOOKSTRUCT *i_mid)\r
 {\r
-  // initialize ok\r
-  CHECK_TRUE( SetEvent(m_threadEvent) );\r
-    \r
-  // loop\r
-  Key key;\r
-  while (!m_doForceTerminate)\r
-  {\r
-    KEYBOARD_INPUT_DATA kid;\r
-    \r
-#ifndef NO_DRIVER\r
-    DWORD len;\r
-#endif // !NO_DRIVER\r
-    {\r
-      Acquire a(&m_log, 1);\r
-      m_log << _T("begin ReadFile();") << std::endl;\r
-    }\r
-#ifdef NO_DRIVER\r
-    if (1)\r
-    {\r
-#else // !NO_DRIVER\r
-    if (!ReadFile(m_device, &kid, sizeof(kid), &len, &m_ol))\r
-    {\r
-      if (GetLastError() != ERROR_IO_PENDING)\r
-       continue;\r
-#endif // !NO_DRIVER\r
-      \r
-      HANDLE handles[] = { m_readEvent, m_interruptThreadEvent };\r
-    rewait:\r
-      switch (MsgWaitForMultipleObjects(NUMBER_OF(handles), &handles[0],\r
-                                    FALSE, INFINITE, QS_POSTMESSAGE))\r
-      {\r
-       case WAIT_OBJECT_0:                     // m_readEvent\r
-#ifdef NO_DRIVER\r
-       {\r
-         Acquire a(&m_cskidq);\r
-         if (m_kidq.empty())\r
-         {\r
-           goto rewait;\r
-         }\r
-         kid = m_kidq.front();\r
-         m_kidq.pop_front();\r
-         if (!m_kidq.empty())\r
-         {\r
-           SetEvent(m_readEvent);\r
-         }\r
-       }\r
-#else // !NO_DRIVER\r
-         if (!GetOverlappedResult(m_device, &m_ol, &len, FALSE))\r
-           continue;\r
-#endif // !NO_DRIVER\r
-         break;\r
-         \r
-       case WAIT_OBJECT_0 + 1:                 // m_interruptThreadEvent\r
-         CancelIo(m_device);\r
-         switch (m_interruptThreadReason) {\r
-           default: {\r
-             ASSERT( false );\r
-             Acquire a(&m_log, 0);\r
-             m_log << _T("internal error: m_interruptThreadReason == ")\r
-                   << m_interruptThreadReason << std::endl;\r
-             break;\r
-           }\r
-             \r
-           case InterruptThreadReason_Terminate:\r
-             goto break_while;\r
-             \r
-           case InterruptThreadReason_Pause: {\r
-             CHECK_TRUE( SetEvent(m_threadEvent) );\r
-             while (WaitForMultipleObjects(1, &m_interruptThreadEvent,\r
-                                           FALSE, INFINITE) != WAIT_OBJECT_0)\r
-               ;\r
-             switch (m_interruptThreadReason) {\r
-               case InterruptThreadReason_Terminate:\r
-                 goto break_while;\r
+       if (i_mid->flags & LLMHF_INJECTED || !m_isEnabled || !m_setting || !m_setting->m_mouseEvent) {\r
+               return 0;\r
+       } else {\r
+               KEYBOARD_INPUT_DATA kid;\r
+\r
+               kid.UnitId = 0;\r
+               kid.Flags = KEYBOARD_INPUT_DATA::E1;\r
+               kid.Reserved = 0;\r
+               kid.ExtraInformation = 0;\r
+               switch (i_message) {\r
+               case WM_LBUTTONUP:\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+               case WM_LBUTTONDOWN:\r
+                       kid.MakeCode = 1;\r
+                       break;\r
+               case WM_RBUTTONUP:\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+               case WM_RBUTTONDOWN:\r
+                       kid.MakeCode = 2;\r
+                       break;\r
+               case WM_MBUTTONUP:\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+               case WM_MBUTTONDOWN:\r
+                       kid.MakeCode = 3;\r
+                       break;\r
+               case WM_MOUSEWHEEL:\r
+                       if (i_mid->mouseData & (1<<31)) {\r
+                               kid.MakeCode = 5;\r
+                       } else {\r
+                               kid.MakeCode = 4;\r
+                       }\r
+                       break;\r
+               case WM_XBUTTONUP:\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+               case WM_XBUTTONDOWN:\r
+                       switch ((i_mid->mouseData >> 16) & 0xFFFFU) {\r
+                       case XBUTTON1:\r
+                               kid.MakeCode = 6;\r
+                               break;\r
+                       case XBUTTON2:\r
+                               kid.MakeCode = 7;\r
+                               break;\r
+                       default:\r
+                               return 0;\r
+                               break;\r
+                       }\r
+                       break;\r
+               case WM_MOUSEHWHEEL:\r
+                       if (i_mid->mouseData & (1<<31)) {\r
+                               kid.MakeCode = 9;\r
+                       } else {\r
+                               kid.MakeCode = 8;\r
+                       }\r
+                       break;\r
+               case WM_MOUSEMOVE: {\r
+                       LONG dx = i_mid->pt.x - g_hookData->m_mousePos.x;\r
+                       LONG dy = i_mid->pt.y - g_hookData->m_mousePos.y;\r
+                       HWND target = reinterpret_cast<HWND>(g_hookData->m_hwndMouseHookTarget);\r
+\r
+                       LONG dr = 0;\r
+                       dr += (i_mid->pt.x - m_msllHookCurrent.pt.x) * (i_mid->pt.x - m_msllHookCurrent.pt.x);\r
+                       dr += (i_mid->pt.y - m_msllHookCurrent.pt.y) * (i_mid->pt.y - m_msllHookCurrent.pt.y);\r
+                       if (m_buttonPressed && !m_dragging && m_setting->m_dragThreshold &&\r
+                               (m_setting->m_dragThreshold * m_setting->m_dragThreshold < dr)) {\r
+                               kid.MakeCode = 0;\r
+                               WaitForSingleObject(m_queueMutex, INFINITE);\r
+                               m_dragging = true;\r
+                               m_inputQueue->push_back(kid);\r
+                               SetEvent(m_readEvent);\r
+                               ReleaseMutex(m_queueMutex);\r
+                       }\r
+\r
+                       switch (g_hookData->m_mouseHookType) {\r
+                       case MouseHookType_Wheel:\r
+                               // For this type, g_hookData->m_mouseHookParam means\r
+                               // translate rate mouse move to wheel.\r
+                               mouse_event(MOUSEEVENTF_WHEEL, 0, 0,\r
+                                                       g_hookData->m_mouseHookParam * dy, 0);\r
+                               return 1;\r
+                               break;\r
+                       case MouseHookType_WindowMove: {\r
+                               RECT curRect;\r
+\r
+                               if (!GetWindowRect(target, &curRect))\r
+                                       return 0;\r
+\r
+                               // g_hookData->m_mouseHookParam < 0 means\r
+                               // target window to move is MDI.\r
+                               if (g_hookData->m_mouseHookParam < 0) {\r
+                                       HWND parent = GetParent(target);\r
+                                       POINT p = {curRect.left, curRect.top};\r
+\r
+                                       if (parent == NULL || !ScreenToClient(parent, &p))\r
+                                               return 0;\r
+\r
+                                       curRect.left = p.x;\r
+                                       curRect.top = p.y;\r
+                               }\r
+\r
+                               SetWindowPos(target, NULL,\r
+                                                        curRect.left + dx,\r
+                                                        curRect.top + dy,\r
+                                                        0, 0,\r
+                                                        SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE |\r
+                                                        SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);\r
+                               g_hookData->m_mousePos = i_mid->pt;\r
+                               return 0;\r
+                               break;\r
+                       }\r
+                       case MouseHookType_None:\r
+                       default:\r
+                               return 0;\r
+                               break;\r
+                       }\r
+               }\r
+               case WM_LBUTTONDBLCLK:\r
+               case WM_RBUTTONDBLCLK:\r
+               case WM_MBUTTONDBLCLK:\r
+               case WM_XBUTTONDBLCLK:\r
+               default:\r
+                       return 0;\r
+                       break;\r
+               }\r
 \r
-               case InterruptThreadReason_Resume:\r
-                 break;\r
+               WaitForSingleObject(m_queueMutex, INFINITE);\r
+\r
+               if (kid.Flags & KEYBOARD_INPUT_DATA::BREAK) {\r
+                       m_buttonPressed = false;\r
+                       if (m_dragging) {\r
+                               KEYBOARD_INPUT_DATA kid2;\r
+\r
+                               m_dragging = false;\r
+                               kid2.UnitId = 0;\r
+                               kid2.Flags = KEYBOARD_INPUT_DATA::E1 | KEYBOARD_INPUT_DATA::BREAK;\r
+                               kid2.Reserved = 0;\r
+                               kid2.ExtraInformation = 0;\r
+                               kid2.MakeCode = 0;\r
+                               m_inputQueue->push_back(kid2);\r
+                       }\r
+               } else if (i_message != WM_MOUSEWHEEL && i_message != WM_MOUSEHWHEEL) {\r
+                       m_buttonPressed = true;\r
+                       m_msllHookCurrent = *i_mid;\r
+               }\r
 \r
-               default:\r
-                 ASSERT( false );\r
-                 break;\r
-             }\r
-             CHECK_TRUE( SetEvent(m_threadEvent) );\r
-             break;\r
-           }\r
-         }\r
-         break;\r
-         \r
-        case WAIT_OBJECT_0 + NUMBER_OF(handles):\r
-       {\r
-         MSG message;\r
-\r
-         while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))\r
-         {\r
-           switch (message.message)\r
-           {\r
-             case WM_APP + 201:\r
-             {\r
-               if (message.wParam)\r
-               {\r
-                 m_currentLock.on(Modifier::Type_Touchpad);\r
-                 m_currentLock.on(Modifier::Type_TouchpadSticky);\r
+               m_inputQueue->push_back(kid);\r
+\r
+               if (i_message == WM_MOUSEWHEEL || i_message == WM_MOUSEHWHEEL) {\r
+                       kid.UnitId = 0;\r
+                       kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;\r
+                       kid.Reserved = 0;\r
+                       kid.ExtraInformation = 0;\r
+                       m_inputQueue->push_back(kid);\r
                }\r
-               else\r
-                 m_currentLock.off(Modifier::Type_Touchpad);\r
-               Acquire a(&m_log, 1);\r
-               m_log << _T("touchpad: ") << message.wParam\r
-                     << _T(".") << (message.lParam & 0xffff)\r
-                     << _T(".") << (message.lParam >> 16 & 0xffff)\r
-                     << std::endl;\r
-               break;\r
-             }\r
-             default:\r
-               break;\r
-           }\r
-         }\r
-         goto rewait;\r
-       }\r
 \r
-       default:\r
-         ASSERT( false );\r
-         continue;\r
-      }\r
-    }\r
-    {\r
-      Acquire a(&m_log, 1);\r
-      m_log << _T("end ReadFile();") << std::endl;\r
-    }\r
-\r
-    checkFocusWindow();\r
-\r
-    if (!m_setting ||  // m_setting has not been loaded\r
-       !m_isEnabled)   // disabled\r
-    {\r
-      if (m_isLogMode)\r
-      {\r
-       Key key;\r
-       key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));\r
-       outputToLog(&key, ModifiedKey(), 0);\r
-      }\r
-      else\r
-      {\r
-#ifdef NO_DRIVER\r
-       injectInput(&kid, NULL);\r
-#else // !NO_DRIVER\r
-       WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);\r
-       GetOverlappedResult(m_device, &m_ol, &len, TRUE);\r
-#endif // !NO_DRIVER\r
-      }\r
-      updateLastPressedKey(NULL);\r
-      continue;\r
-    }\r
-    \r
-    Acquire a(&m_cs);\r
-\r
-    if (!m_currentFocusOfThread ||\r
-       !m_currentKeymap)\r
-    {\r
-#ifndef NO_DRIVER\r
-      WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);\r
-      GetOverlappedResult(m_device, &m_ol, &len, TRUE);\r
-#endif // !NO_DRIVER\r
-      Acquire a(&m_log, 0);\r
-      if (!m_currentFocusOfThread)\r
-       m_log << _T("internal error: m_currentFocusOfThread == NULL")\r
-             << std::endl;\r
-      if (!m_currentKeymap)\r
-       m_log << _T("internal error: m_currentKeymap == NULL")\r
-             << std::endl;\r
-      updateLastPressedKey(NULL);\r
-      continue;\r
-    }\r
-    \r
-    Current c;\r
-    c.m_keymap = m_currentKeymap;\r
-    c.m_i = m_currentFocusOfThread->m_keymaps.begin();\r
-    \r
-    // search key\r
-    key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));\r
-    c.m_mkey = m_setting->m_keyboard.searchKey(key);\r
-    if (!c.m_mkey.m_key)\r
-    {\r
-      c.m_mkey.m_key = m_setting->m_keyboard.searchPrefixKey(key);\r
-      if (c.m_mkey.m_key)\r
-       continue;\r
-    }\r
-\r
-    // press the key and update counter\r
-    bool isPhysicallyPressed\r
-      = !(key.getScanCodes()[0].m_flags & ScanCode::BREAK);\r
-    if (c.m_mkey.m_key)\r
-    {\r
-      if (!c.m_mkey.m_key->m_isPressed && isPhysicallyPressed)\r
-       ++ m_currentKeyPressCount;\r
-      else if (c.m_mkey.m_key->m_isPressed && !isPhysicallyPressed)\r
-       -- m_currentKeyPressCount;\r
-      c.m_mkey.m_key->m_isPressed = isPhysicallyPressed;\r
-    }\r
-    \r
-    // create modifiers\r
-    c.m_mkey.m_modifier = getCurrentModifiers(c.m_mkey.m_key,\r
-                                             isPhysicallyPressed);\r
-    Keymap::AssignMode am;\r
-    bool isModifier = fixModifierKey(&c.m_mkey, &am);\r
-    if (m_isPrefix)\r
-    {\r
-      if (isModifier && m_doesIgnoreModifierForPrefix)\r
-       am = Keymap::AM_true;\r
-      if (m_doesEditNextModifier)\r
-      {\r
-       Modifier modifier = m_modifierForNextKey;\r
-       modifier.add(c.m_mkey.m_modifier);\r
-       c.m_mkey.m_modifier = modifier;\r
-      }\r
-    }\r
-    \r
-    if (m_isLogMode)\r
-      outputToLog(&key, c.m_mkey, 0);\r
-    else if (am == Keymap::AM_true)\r
-    {\r
-      {\r
-       Acquire a(&m_log, 1);\r
-       m_log << _T("* true modifier") << std::endl;\r
-      }\r
-      // true modifier doesn't generate scan code\r
-      outputToLog(&key, c.m_mkey, 1);\r
-    }\r
-    else if (am == Keymap::AM_oneShot || am == Keymap::AM_oneShotRepeatable)\r
-    {\r
-      {\r
-       Acquire a(&m_log, 1);\r
-       if (am == Keymap::AM_oneShot)\r
-         m_log << _T("* one shot modifier") << std::endl;\r
-       else\r
-         m_log << _T("* one shot repeatable modifier") << std::endl;\r
-      }\r
-      // oneShot modifier doesn't generate scan code\r
-      outputToLog(&key, c.m_mkey, 1);\r
-      if (isPhysicallyPressed)\r
-      {\r
-       if (am == Keymap::AM_oneShotRepeatable  // the key is repeating\r
-           && m_oneShotKey.m_key == c.m_mkey.m_key)\r
-       {\r
-         if (m_oneShotRepeatableRepeatCount <\r
-             m_setting->m_oneShotRepeatableDelay) {\r
-           ; // delay\r
-         } else {\r
-           Current cnew = c;\r
-           beginGeneratingKeyboardEvents(cnew, false);\r
-         }\r
-         ++ m_oneShotRepeatableRepeatCount;\r
-       } else {\r
-         m_oneShotKey = c.m_mkey;\r
-         m_oneShotRepeatableRepeatCount = 0;\r
-       }\r
-      }\r
-      else\r
-      {\r
-       if (m_oneShotKey.m_key)\r
-       {\r
-         Current cnew = c;\r
-         cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;\r
-         cnew.m_mkey.m_modifier.off(Modifier::Type_Up);\r
-         cnew.m_mkey.m_modifier.on(Modifier::Type_Down);\r
-         beginGeneratingKeyboardEvents(cnew, false);\r
-         \r
-         cnew = c;\r
-         cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;\r
-         cnew.m_mkey.m_modifier.on(Modifier::Type_Up);\r
-         cnew.m_mkey.m_modifier.off(Modifier::Type_Down);\r
-         beginGeneratingKeyboardEvents(cnew, false);\r
+               SetEvent(m_readEvent);\r
+               ReleaseMutex(m_queueMutex);\r
+\r
+               return 1;\r
        }\r
-       m_oneShotKey.m_key = NULL;\r
-       m_oneShotRepeatableRepeatCount = 0;\r
-      }\r
-    }\r
-    else if (c.m_mkey.m_key)\r
-      // normal key\r
-    {\r
-      outputToLog(&key, c.m_mkey, 1);\r
-      if (isPhysicallyPressed)\r
-       m_oneShotKey.m_key = NULL;\r
-      beginGeneratingKeyboardEvents(c, isModifier);\r
-    }\r
-    \r
-    // if counter is zero, reset modifiers and keys on win32\r
-    if (m_currentKeyPressCount <= 0)\r
-    {\r
-      {\r
-       Acquire a(&m_log, 1);\r
-       m_log << _T("* No key is pressed") << std::endl;\r
-      }\r
-      generateModifierEvents(Modifier());\r
-      if (0 < m_currentKeyPressCountOnWin32)\r
-       keyboardResetOnWin32();\r
-      m_currentKeyPressCount = 0;\r
-      m_currentKeyPressCountOnWin32 = 0;\r
-      m_oneShotKey.m_key = NULL;\r
-      if (m_currentLock.isOn(Modifier::Type_Touchpad) == false)\r
-       m_currentLock.off(Modifier::Type_TouchpadSticky);\r
-    }\r
-    \r
-    key.initialize();\r
-    updateLastPressedKey(isPhysicallyPressed ? c.m_mkey.m_key : NULL);\r
-  }\r
-  break_while:\r
-  CHECK_TRUE( SetEvent(m_threadEvent) );\r
 }\r
-  \r
 \r
-Engine::Engine(tomsgstream &i_log)\r
-  : m_hwndAssocWindow(NULL),\r
-    m_setting(NULL),\r
-    m_device(INVALID_HANDLE_VALUE),\r
-    m_didMayuStartDevice(false),\r
-    m_threadEvent(NULL),\r
-    m_mayudVersion(_T("unknown")),\r
-    m_readEvent(NULL),\r
-    m_interruptThreadEvent(NULL),\r
-    m_sts4mayu(NULL),\r
-    m_cts4mayu(NULL),\r
-    m_doForceTerminate(false),\r
-    m_isLogMode(false),\r
-    m_isEnabled(true),\r
-    m_isSynchronizing(false),\r
-    m_eSync(NULL),\r
-    m_generateKeyboardEventsRecursionGuard(0),\r
-    m_currentKeyPressCount(0),\r
-    m_currentKeyPressCountOnWin32(0),\r
-    m_lastGeneratedKey(NULL),\r
-    m_oneShotRepeatableRepeatCount(0),\r
-    m_isPrefix(false),\r
-    m_currentKeymap(NULL),\r
-    m_currentFocusOfThread(NULL),\r
-    m_hwndFocus(NULL),\r
-    m_afShellExecute(NULL),\r
-    m_variable(0),\r
-    m_log(i_log)\r
+// keyboard handler thread\r
+unsigned int WINAPI Engine::keyboardHandler(void *i_this)\r
 {\r
-  for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)\r
-    m_lastPressedKey[i] = NULL;\r
-    \r
-  // set default lock state\r
-  for (int i = 0; i < Modifier::Type_end; ++ i)\r
-    m_currentLock.dontcare(static_cast<Modifier::Type>(i));\r
-  for (int i = Modifier::Type_Lock0; i <= Modifier::Type_Lock9; ++ i)\r
-    m_currentLock.release(static_cast<Modifier::Type>(i));\r
-\r
-#ifndef NO_DRIVER\r
-  if (!open()) {\r
-      throw ErrorMessage() << loadString(IDS_driverNotInstalled);\r
-  }\r
-#endif // !NO_DRIVER\r
-  \r
-#ifndef NO_DRIVER\r
-  {\r
-    TCHAR versionBuf[256];\r
-    DWORD length = 0;\r
-\r
-    if (DeviceIoControl(m_device, IOCTL_MAYU_GET_VERSION, NULL, 0,\r
-                       versionBuf, sizeof(versionBuf), &length, NULL)\r
-       && length\r
-       && length < sizeof(versionBuf))                 // fail safe\r
-       m_mayudVersion = tstring(versionBuf, length / 2);\r
-  }\r
-#endif // !NO_DRIVER\r
-  // create event for sync\r
-  CHECK_TRUE( m_eSync = CreateEvent(NULL, FALSE, FALSE, NULL) );\r
-  // create named pipe for &SetImeString\r
-  m_hookPipe = CreateNamedPipe(addSessionId(HOOK_PIPE_NAME).c_str(),\r
-                              PIPE_ACCESS_OUTBOUND,\r
-                              PIPE_TYPE_BYTE, 1,\r
-                              0, 0, 0, NULL);\r
-  StrExprArg::setEngine(this);\r
+       reinterpret_cast<Engine *>(i_this)->keyboardHandler();\r
+       _endthreadex(0);\r
+       return 0;\r
 }\r
+void Engine::keyboardHandler()\r
+{\r
+       // loop\r
+       Key key;\r
+       while (1) {\r
+               KEYBOARD_INPUT_DATA kid;\r
 \r
+               WaitForSingleObject(m_queueMutex, INFINITE);\r
+               while (SignalObjectAndWait(m_queueMutex, m_readEvent, INFINITE, true) == WAIT_OBJECT_0) {\r
+                       if (m_inputQueue == NULL) {\r
+                               ReleaseMutex(m_queueMutex);\r
+                               return;\r
+                       }\r
 \r
-// open mayu device\r
-bool Engine::open()\r
-{\r
-  // open mayu m_device\r
-#ifndef NO_DRIVER\r
-  m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,\r
-                       0, NULL, OPEN_EXISTING,\r
-                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);\r
-#endif // !NO_DRIVER\r
-\r
-  if (m_device != INVALID_HANDLE_VALUE) {\r
-    return true;\r
-  }\r
-\r
-#ifndef NO_DRIVER\r
-  // start mayud\r
-  SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);\r
-  if (hscm)\r
-  {\r
-    SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_START);\r
-    if (hs)\r
-    {\r
-      StartService(hs, 0, NULL);\r
-      CloseServiceHandle(hs);\r
-      m_didMayuStartDevice = true;\r
-    }\r
-    CloseServiceHandle(hscm);\r
-  }\r
-  \r
-  // open mayu m_device\r
-  m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,\r
-                       0, NULL, OPEN_EXISTING,\r
-                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);\r
-#endif // !NO_DRIVER\r
-  return (m_device != INVALID_HANDLE_VALUE);\r
-}\r
+                       if (m_inputQueue->empty()) {\r
+                               ResetEvent(m_readEvent);\r
+                               continue;\r
+                       }\r
 \r
+                       kid = m_inputQueue->front();\r
+                       m_inputQueue->pop_front();\r
+                       if (m_inputQueue->empty()) {\r
+                               ResetEvent(m_readEvent);\r
+                       }\r
 \r
-// close mayu device\r
-void Engine::close()\r
-{\r
-  if (m_device != INVALID_HANDLE_VALUE) {\r
-#ifndef NO_DRIVER\r
-    CHECK_TRUE( CloseHandle(m_device) );\r
-#endif // !NO_DRIVER\r
-  }\r
-  m_device = INVALID_HANDLE_VALUE;\r
-}\r
+                       break;\r
 \r
+#if 0\r
+                       case WAIT_OBJECT_0 + NUMBER_OF(handles): {\r
+                               MSG message;\r
+\r
+                               while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {\r
+                                       switch (message.message) {\r
+                                       case WM_APP + 201: {\r
+                                               if (message.wParam) {\r
+                                                       m_currentLock.on(Modifier::Type_Touchpad);\r
+                                                       m_currentLock.on(Modifier::Type_TouchpadSticky);\r
+                                               } else\r
+                                                       m_currentLock.off(Modifier::Type_Touchpad);\r
+                                               Acquire a(&m_log, 1);\r
+                                               m_log << _T("touchpad: ") << message.wParam\r
+                                               << _T(".") << (message.lParam & 0xffff)\r
+                                               << _T(".") << (message.lParam >> 16 & 0xffff)\r
+                                               << std::endl;\r
+                                               break;\r
+                                       }\r
+                                       default:\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               goto rewait;\r
+                       }\r
+#endif\r
+               }\r
+               ReleaseMutex(m_queueMutex);\r
+\r
+               checkFocusWindow();\r
+\r
+               if (!m_setting ||       // m_setting has not been loaded\r
+                               !m_isEnabled) { // disabled\r
+                       if (m_isLogMode) {\r
+                               Key key;\r
+                               key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));\r
+                               outputToLog(&key, ModifiedKey(), 0);\r
+                               if (kid.Flags & KEYBOARD_INPUT_DATA::E1) {\r
+                                       // through mouse event even if log mode\r
+                                       injectInput(&kid, NULL);\r
+                               }\r
+                       } else {\r
+                               injectInput(&kid, NULL);\r
+                       }\r
+                       updateLastPressedKey(NULL);\r
+                       continue;\r
+               }\r
 \r
-// start keyboard handler thread\r
-void Engine::start()\r
-{\r
-  CHECK_TRUE( m_threadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );\r
-  \r
-  CHECK_TRUE( m_readEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );\r
-  CHECK_TRUE( m_interruptThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );\r
-  m_ol.Offset = 0;\r
-  m_ol.OffsetHigh = 0;\r
-  m_ol.hEvent = m_readEvent;\r
-  \r
-  CHECK_TRUE( m_threadHandle = (HANDLE)_beginthreadex(NULL, 0, keyboardHandler, this, 0, &m_threadId) );\r
-  CHECK( WAIT_OBJECT_0 ==, WaitForSingleObject(m_threadEvent, INFINITE) );\r
+               Acquire a(&m_cs);\r
+\r
+               if (!m_currentFocusOfThread ||\r
+                               !m_currentKeymap) {\r
+                       injectInput(&kid, NULL);\r
+                       Acquire a(&m_log, 0);\r
+                       if (!m_currentFocusOfThread)\r
+                               m_log << _T("internal error: m_currentFocusOfThread == NULL")\r
+                               << std::endl;\r
+                       if (!m_currentKeymap)\r
+                               m_log << _T("internal error: m_currentKeymap == NULL")\r
+                               << std::endl;\r
+                       updateLastPressedKey(NULL);\r
+                       continue;\r
+               }\r
+\r
+               Current c;\r
+               c.m_keymap = m_currentKeymap;\r
+               c.m_i = m_currentFocusOfThread->m_keymaps.begin();\r
+\r
+               // search key\r
+               key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));\r
+               c.m_mkey = m_setting->m_keyboard.searchKey(key);\r
+               if (!c.m_mkey.m_key) {\r
+                       c.m_mkey.m_key = m_setting->m_keyboard.searchPrefixKey(key);\r
+                       if (c.m_mkey.m_key)\r
+                               continue;\r
+               }\r
+\r
+               // press the key and update counter\r
+               bool isPhysicallyPressed\r
+               = !(key.getScanCodes()[0].m_flags & ScanCode::BREAK);\r
+               if (c.m_mkey.m_key) {\r
+                       if (!c.m_mkey.m_key->m_isPressed && isPhysicallyPressed)\r
+                               ++ m_currentKeyPressCount;\r
+                       else if (c.m_mkey.m_key->m_isPressed && !isPhysicallyPressed)\r
+                               -- m_currentKeyPressCount;\r
+                       c.m_mkey.m_key->m_isPressed = isPhysicallyPressed;\r
+               }\r
+\r
+               // create modifiers\r
+               c.m_mkey.m_modifier = getCurrentModifiers(c.m_mkey.m_key,\r
+                                                         isPhysicallyPressed);\r
+               Keymap::AssignMode am;\r
+               bool isModifier = fixModifierKey(&c.m_mkey, &am);\r
+               if (m_isPrefix) {\r
+                       if (isModifier && m_doesIgnoreModifierForPrefix)\r
+                               am = Keymap::AM_true;\r
+                       if (m_doesEditNextModifier) {\r
+                               Modifier modifier = m_modifierForNextKey;\r
+                               modifier.add(c.m_mkey.m_modifier);\r
+                               c.m_mkey.m_modifier = modifier;\r
+                       }\r
+               }\r
+\r
+               if (m_isLogMode) {\r
+                       outputToLog(&key, c.m_mkey, 0);\r
+                       if (kid.Flags & KEYBOARD_INPUT_DATA::E1) {\r
+                               // through mouse event even if log mode\r
+                               injectInput(&kid, NULL);\r
+                       }\r
+               } else if (am == Keymap::AM_true) {\r
+                       {\r
+                               Acquire a(&m_log, 1);\r
+                               m_log << _T("* true modifier") << std::endl;\r
+                       }\r
+                       // true modifier doesn't generate scan code\r
+                       outputToLog(&key, c.m_mkey, 1);\r
+               } else if (am == Keymap::AM_oneShot || am == Keymap::AM_oneShotRepeatable) {\r
+                       {\r
+                               Acquire a(&m_log, 1);\r
+                               if (am == Keymap::AM_oneShot)\r
+                                       m_log << _T("* one shot modifier") << std::endl;\r
+                               else\r
+                                       m_log << _T("* one shot repeatable modifier") << std::endl;\r
+                       }\r
+                       // oneShot modifier doesn't generate scan code\r
+                       outputToLog(&key, c.m_mkey, 1);\r
+                       if (isPhysicallyPressed) {\r
+                               if (am == Keymap::AM_oneShotRepeatable  // the key is repeating\r
+                                               && m_oneShotKey.m_key == c.m_mkey.m_key) {\r
+                                       if (m_oneShotRepeatableRepeatCount <\r
+                                                       m_setting->m_oneShotRepeatableDelay) {\r
+                                               ; // delay\r
+                                       } else {\r
+                                               Current cnew = c;\r
+                                               beginGeneratingKeyboardEvents(cnew, false);\r
+                                       }\r
+                                       ++ m_oneShotRepeatableRepeatCount;\r
+                               } else {\r
+                                       m_oneShotKey = c.m_mkey;\r
+                                       m_oneShotRepeatableRepeatCount = 0;\r
+                               }\r
+                       } else {\r
+                               if (m_oneShotKey.m_key) {\r
+                                       Current cnew = c;\r
+                                       cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;\r
+                                       cnew.m_mkey.m_modifier.off(Modifier::Type_Up);\r
+                                       cnew.m_mkey.m_modifier.on(Modifier::Type_Down);\r
+                                       beginGeneratingKeyboardEvents(cnew, false);\r
+\r
+                                       cnew = c;\r
+                                       cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;\r
+                                       cnew.m_mkey.m_modifier.on(Modifier::Type_Up);\r
+                                       cnew.m_mkey.m_modifier.off(Modifier::Type_Down);\r
+                                       beginGeneratingKeyboardEvents(cnew, false);\r
+                               }\r
+                               m_oneShotKey.m_key = NULL;\r
+                               m_oneShotRepeatableRepeatCount = 0;\r
+                       }\r
+               } else if (c.m_mkey.m_key) {\r
+                       // normal key\r
+                       outputToLog(&key, c.m_mkey, 1);\r
+                       if (isPhysicallyPressed)\r
+                               m_oneShotKey.m_key = NULL;\r
+                       beginGeneratingKeyboardEvents(c, isModifier);\r
+               } else {\r
+                       // undefined key\r
+                       if (kid.Flags & KEYBOARD_INPUT_DATA::E1) {\r
+                               // through mouse event even if undefined for fail safe\r
+                               injectInput(&kid, NULL);\r
+                       }\r
+               }\r
+\r
+               // if counter is zero, reset modifiers and keys on win32\r
+               if (m_currentKeyPressCount <= 0) {\r
+                       {\r
+                               Acquire a(&m_log, 1);\r
+                               m_log << _T("* No key is pressed") << std::endl;\r
+                       }\r
+                       generateModifierEvents(Modifier());\r
+                       if (0 < m_currentKeyPressCountOnWin32)\r
+                               keyboardResetOnWin32();\r
+                       m_currentKeyPressCount = 0;\r
+                       m_currentKeyPressCountOnWin32 = 0;\r
+                       m_oneShotKey.m_key = NULL;\r
+                       if (m_currentLock.isOn(Modifier::Type_Touchpad) == false)\r
+                               m_currentLock.off(Modifier::Type_TouchpadSticky);\r
+               }\r
+\r
+               key.initialize();\r
+               updateLastPressedKey(isPhysicallyPressed ? c.m_mkey.m_key : NULL);\r
+       }\r
 }\r
 \r
 \r
-// stop keyboard handler thread\r
-void Engine::stop()\r
-{\r
-  if (m_threadEvent)\r
-  {\r
-    m_doForceTerminate = true;\r
-    do\r
-    {\r
-      m_interruptThreadReason = InterruptThreadReason_Terminate;\r
-      SetEvent(m_interruptThreadEvent);\r
-      //DWORD buf;\r
-      //M_DeviceIoControl(m_device, IOCTL_MAYU_DETOUR_CANCEL,\r
-      //                &buf, sizeof(buf), &buf, sizeof(buf), &buf, NULL);\r
-      \r
-      // wait for message handler thread terminate\r
-    } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);\r
-    CHECK_TRUE( CloseHandle(m_threadEvent) );\r
-    m_threadEvent = NULL;\r
-    WaitForSingleObject(m_threadHandle, 100);\r
-    CHECK_TRUE( CloseHandle(m_threadHandle) );\r
-    m_threadHandle = NULL;\r
-\r
-    // stop mayud\r
-    if (m_didMayuStartDevice)\r
-    {\r
-      SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);\r
-      if (hscm)\r
-      {\r
-       SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_STOP);\r
-       if (hs)\r
-       {\r
-         SERVICE_STATUS ss;\r
-         ControlService(hs, SERVICE_CONTROL_STOP, &ss);\r
-         CloseServiceHandle(hs);\r
+Engine::Engine(tomsgstream &i_log)\r
+               : m_hwndAssocWindow(NULL),\r
+               m_setting(NULL),\r
+               m_buttonPressed(false),\r
+               m_dragging(false),\r
+               m_keyboardHandler(installKeyboardHook, Engine::keyboardDetour),\r
+               m_mouseHandler(installMouseHook, Engine::mouseDetour),\r
+               m_inputQueue(NULL),\r
+               m_readEvent(NULL),\r
+               m_queueMutex(NULL),\r
+               m_sts4mayu(NULL),\r
+               m_cts4mayu(NULL),\r
+               m_isLogMode(false),\r
+               m_isEnabled(true),\r
+               m_isSynchronizing(false),\r
+               m_eSync(NULL),\r
+               m_generateKeyboardEventsRecursionGuard(0),\r
+               m_currentKeyPressCount(0),\r
+               m_currentKeyPressCountOnWin32(0),\r
+               m_lastGeneratedKey(NULL),\r
+               m_oneShotRepeatableRepeatCount(0),\r
+               m_isPrefix(false),\r
+               m_currentKeymap(NULL),\r
+               m_currentFocusOfThread(NULL),\r
+               m_hwndFocus(NULL),\r
+               m_afShellExecute(NULL),\r
+               m_variable(0),\r
+               m_log(i_log) {\r
+       BOOL (WINAPI *pChangeWindowMessageFilter)(UINT, DWORD) =\r
+               reinterpret_cast<BOOL (WINAPI*)(UINT, DWORD)>(GetProcAddress(GetModuleHandle(_T("user32.dll")), "ChangeWindowMessageFilter"));\r
+\r
+       if(pChangeWindowMessageFilter != NULL) {\r
+               pChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD);\r
        }\r
-       CloseServiceHandle(hscm);\r
-      }\r
-    }\r
-    \r
-    CHECK_TRUE( CloseHandle(m_readEvent) );\r
-    m_readEvent = NULL;\r
-    CHECK_TRUE( CloseHandle(m_interruptThreadEvent) );\r
-    m_interruptThreadEvent = NULL;\r
-  }\r
+\r
+       for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)\r
+               m_lastPressedKey[i] = NULL;\r
+\r
+       // set default lock state\r
+       for (int i = 0; i < Modifier::Type_end; ++ i)\r
+               m_currentLock.dontcare(static_cast<Modifier::Type>(i));\r
+       for (int i = Modifier::Type_Lock0; i <= Modifier::Type_Lock9; ++ i)\r
+               m_currentLock.release(static_cast<Modifier::Type>(i));\r
+\r
+       // create event for sync\r
+       CHECK_TRUE( m_eSync = CreateEvent(NULL, FALSE, FALSE, NULL) );\r
+       // create named pipe for &SetImeString\r
+       m_hookPipe = CreateNamedPipe(addSessionId(HOOK_PIPE_NAME).c_str(),\r
+                                                                PIPE_ACCESS_OUTBOUND,\r
+                                                                PIPE_TYPE_BYTE, 1,\r
+                                                                0, 0, 0, NULL);\r
+       StrExprArg::setEngine(this);\r
+\r
+       m_msllHookCurrent.pt.x = 0;\r
+       m_msllHookCurrent.pt.y = 0;\r
+       m_msllHookCurrent.mouseData = 0;\r
+       m_msllHookCurrent.flags = 0;\r
+       m_msllHookCurrent.time = 0;\r
+       m_msllHookCurrent.dwExtraInfo = 0;\r
 }\r
 \r
-bool Engine::pause()\r
-{\r
-  if (m_device != INVALID_HANDLE_VALUE) {\r
-    do {\r
-      m_interruptThreadReason = InterruptThreadReason_Pause;\r
-      SetEvent(m_interruptThreadEvent);\r
-    } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);\r
-#ifndef NO_DRIVER\r
-    close();\r
-#endif // !NO_DRIVER\r
-  }\r
-  return true;\r
+\r
+\r
+\r
+// start keyboard handler thread\r
+void Engine::start() {\r
+       m_keyboardHandler.start(this);\r
+       m_mouseHandler.start(this);\r
+\r
+       CHECK_TRUE( m_inputQueue = new std::deque<KEYBOARD_INPUT_DATA> );\r
+       CHECK_TRUE( m_queueMutex = CreateMutex(NULL, FALSE, NULL) );\r
+       CHECK_TRUE( m_readEvent = CreateEvent(NULL, TRUE, FALSE, NULL) );\r
+       m_ol.Offset = 0;\r
+       m_ol.OffsetHigh = 0;\r
+       m_ol.hEvent = m_readEvent;\r
+\r
+       CHECK_TRUE( m_threadHandle = (HANDLE)_beginthreadex(NULL, 0, keyboardHandler, this, 0, &m_threadId) );\r
 }\r
 \r
 \r
-bool Engine::resume()\r
-{\r
-  if (m_device == INVALID_HANDLE_VALUE) {\r
-#ifndef NO_DRIVER\r
-    if (!open()) {\r
-      return false;                            // FIXME\r
-    }\r
-#endif // !NO_DRIVER\r
-    do {\r
-      m_interruptThreadReason = InterruptThreadReason_Resume;\r
-      SetEvent(m_interruptThreadEvent);\r
-    } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);\r
-  }\r
-  return true;\r
+// stop keyboard handler thread\r
+void Engine::stop() {\r
+       m_mouseHandler.stop();\r
+       m_keyboardHandler.stop();\r
+\r
+       WaitForSingleObject(m_queueMutex, INFINITE);\r
+       delete m_inputQueue;\r
+       m_inputQueue = NULL;\r
+       SetEvent(m_readEvent);\r
+       ReleaseMutex(m_queueMutex);\r
+\r
+       WaitForSingleObject(m_threadHandle, 2000);\r
+       CHECK_TRUE( CloseHandle(m_threadHandle) );\r
+       m_threadHandle = NULL;\r
+\r
+       CHECK_TRUE( CloseHandle(m_readEvent) );\r
+       m_readEvent = NULL;\r
 }\r
 \r
 \r
-bool Engine::prepairQuit()\r
-{\r
-  // terminate and unload DLL for ThumbSense support if loaded\r
-  manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),\r
-               false, &m_sts4mayu);\r
-  manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),\r
-               false, &m_cts4mayu);\r
-  return true;\r
+bool Engine::prepairQuit() {\r
+       // terminate and unload DLL for ThumbSense support if loaded\r
+       manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),\r
+                                 false, &m_sts4mayu);\r
+       manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),\r
+                                 false, &m_cts4mayu);\r
+       return true;\r
 }\r
 \r
 \r
-Engine::~Engine()\r
-{\r
-  stop();\r
-  CHECK_TRUE( CloseHandle(m_eSync) );\r
-  \r
-  // close m_device\r
-#ifndef NO_DRIVER\r
-  close();\r
-#endif // !NO_DRIVER\r
-  // destroy named pipe for &SetImeString\r
-  if (m_hookPipe && m_hookPipe != INVALID_HANDLE_VALUE)\r
-  {\r
-    DisconnectNamedPipe(m_hookPipe);\r
-    CHECK_TRUE( CloseHandle(m_hookPipe) );\r
-  }\r
+Engine::~Engine() {\r
+       CHECK_TRUE( CloseHandle(m_eSync) );\r
+\r
+       // destroy named pipe for &SetImeString\r
+       if (m_hookPipe && m_hookPipe != INVALID_HANDLE_VALUE) {\r
+               DisconnectNamedPipe(m_hookPipe);\r
+               CHECK_TRUE( CloseHandle(m_hookPipe) );\r
+       }\r
 }\r
 \r
 \r
 void Engine::manageTs4mayu(TCHAR *i_ts4mayuDllName,\r
-                          TCHAR *i_dependDllName,\r
-                          bool i_load, HMODULE *i_pTs4mayu)\r
-{\r
-  Acquire a(&m_log, 0);\r
-\r
-  if (i_load == false)\r
-  {\r
-    if (*i_pTs4mayu)\r
-    {\r
-      bool (WINAPI *pTs4mayuTerm)();\r
-\r
-      pTs4mayuTerm = (bool (WINAPI*)())GetProcAddress(*i_pTs4mayu, "ts4mayuTerm");\r
-      if (pTs4mayuTerm() == true)\r
-       FreeLibrary(*i_pTs4mayu);\r
-      *i_pTs4mayu = NULL;\r
-      m_log << i_ts4mayuDllName <<_T(" unloaded") << std::endl;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    if (*i_pTs4mayu)\r
-    {\r
-      m_log << i_ts4mayuDllName << _T(" already loaded") << std::endl;\r
-    }\r
-    else\r
-    {\r
-      if (SearchPath(NULL, i_dependDllName, NULL, 0, NULL, NULL) == 0)\r
-      {\r
-       m_log << _T("load ") << i_ts4mayuDllName\r
-             << _T(" failed: can't find ") << i_dependDllName\r
-             << std::endl;\r
-      }\r
-      else\r
-      {\r
-       *i_pTs4mayu = LoadLibrary(i_ts4mayuDllName);\r
-       if (*i_pTs4mayu == NULL)\r
-       {\r
-         m_log << _T("load ") << i_ts4mayuDllName\r
-               << _T(" failed: can't find it") << std::endl;\r
-       }\r
-       else\r
-       {\r
-         bool (WINAPI *pTs4mayuInit)(UINT);    \r
-\r
-         pTs4mayuInit = (bool (WINAPI*)(UINT))GetProcAddress(*i_pTs4mayu, "ts4mayuInit");\r
-         if (pTs4mayuInit(m_threadId) == true)\r
-           m_log << i_ts4mayuDllName <<_T(" loaded") << std::endl;\r
-         else\r
-           m_log << i_ts4mayuDllName\r
-                 <<_T(" load failed: can't initialize") << std::endl;\r
+                                                  TCHAR *i_dependDllName,\r
+                                                  bool i_load, HMODULE *i_pTs4mayu) {\r
+       Acquire a(&m_log, 0);\r
+\r
+       if (i_load == false) {\r
+               if (*i_pTs4mayu) {\r
+                       bool (WINAPI *pTs4mayuTerm)();\r
+\r
+                       pTs4mayuTerm = (bool (WINAPI*)())GetProcAddress(*i_pTs4mayu, "ts4mayuTerm");\r
+                       if (pTs4mayuTerm() == true)\r
+                               FreeLibrary(*i_pTs4mayu);\r
+                       *i_pTs4mayu = NULL;\r
+                       m_log << i_ts4mayuDllName <<_T(" unloaded") << std::endl;\r
+               }\r
+       } else {\r
+               if (*i_pTs4mayu) {\r
+                       m_log << i_ts4mayuDllName << _T(" already loaded") << std::endl;\r
+               } else {\r
+                       if (SearchPath(NULL, i_dependDllName, NULL, 0, NULL, NULL) == 0) {\r
+                               m_log << _T("load ") << i_ts4mayuDllName\r
+                               << _T(" failed: can't find ") << i_dependDllName\r
+                               << std::endl;\r
+                       } else {\r
+                               *i_pTs4mayu = LoadLibrary(i_ts4mayuDllName);\r
+                               if (*i_pTs4mayu == NULL) {\r
+                                       m_log << _T("load ") << i_ts4mayuDllName\r
+                                       << _T(" failed: can't find it") << std::endl;\r
+                               } else {\r
+                                       bool (WINAPI *pTs4mayuInit)(UINT);\r
+\r
+                                       pTs4mayuInit = (bool (WINAPI*)(UINT))GetProcAddress(*i_pTs4mayu, "ts4mayuInit");\r
+                                       if (pTs4mayuInit(m_threadId) == true)\r
+                                               m_log << i_ts4mayuDllName <<_T(" loaded") << std::endl;\r
+                                       else\r
+                                               m_log << i_ts4mayuDllName\r
+                                               <<_T(" load failed: can't initialize") << std::endl;\r
+                               }\r
+                       }\r
+               }\r
        }\r
-      }\r
-    }\r
-  }\r
 }\r
 \r
 \r
 // set m_setting\r
-bool Engine::setSetting(Setting *i_setting)\r
-{\r
-  Acquire a(&m_cs);\r
-  if (m_isSynchronizing)\r
-    return false;\r
-\r
-  if (m_setting)\r
-  {\r
-    for (Keyboard::KeyIterator i = m_setting->m_keyboard.getKeyIterator();\r
-        *i; ++ i)\r
-    {\r
-      Key *key = i_setting->m_keyboard.searchKey(*(*i));\r
-      if (key)\r
-      {\r
-       key->m_isPressed = (*i)->m_isPressed;\r
-       key->m_isPressedOnWin32 = (*i)->m_isPressedOnWin32;\r
-       key->m_isPressedByAssign = (*i)->m_isPressedByAssign;\r
-      }\r
-    }\r
-    if (m_lastGeneratedKey)\r
-      m_lastGeneratedKey =\r
-       i_setting->m_keyboard.searchKey(*m_lastGeneratedKey);\r
-    for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)\r
-      if (m_lastPressedKey[i])\r
-       m_lastPressedKey[i] =\r
-         i_setting->m_keyboard.searchKey(*m_lastPressedKey[i]);\r
-  }\r
-  \r
-  m_setting = i_setting;\r
-\r
-  manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),\r
-               m_setting->m_sts4mayu, &m_sts4mayu);\r
-  manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),\r
-               m_setting->m_cts4mayu, &m_cts4mayu);\r
-\r
-  g_hookData->m_correctKanaLockHandling = m_setting->m_correctKanaLockHandling;\r
-  if (m_currentFocusOfThread)\r
-  {\r
-    for (FocusOfThreads::iterator i = m_focusOfThreads.begin();\r
-        i != m_focusOfThreads.end(); i ++)\r
-    {\r
-      FocusOfThread *fot = &(*i).second;\r
-      m_setting->m_keymaps.searchWindow(&fot->m_keymaps,\r
-                                       fot->m_className, fot->m_titleName);\r
-    }\r
-  }\r
-  m_setting->m_keymaps.searchWindow(&m_globalFocus.m_keymaps, _T(""), _T(""));\r
-  if (m_globalFocus.m_keymaps.empty())\r
-  {\r
-    Acquire a(&m_log, 0);\r
-    m_log << _T("internal error: m_globalFocus.m_keymap is empty")\r
-         << std::endl;\r
-  }\r
-  m_currentFocusOfThread = &m_globalFocus;\r
-  setCurrentKeymap(m_globalFocus.m_keymaps.front());\r
-  m_hwndFocus = NULL;\r
-  return true;\r
+bool Engine::setSetting(Setting *i_setting) {\r
+       Acquire a(&m_cs);\r
+       if (m_isSynchronizing)\r
+               return false;\r
+\r
+       if (m_setting) {\r
+               for (Keyboard::KeyIterator i = m_setting->m_keyboard.getKeyIterator();\r
+                               *i; ++ i) {\r
+                       Key *key = i_setting->m_keyboard.searchKey(*(*i));\r
+                       if (key) {\r
+                               key->m_isPressed = (*i)->m_isPressed;\r
+                               key->m_isPressedOnWin32 = (*i)->m_isPressedOnWin32;\r
+                               key->m_isPressedByAssign = (*i)->m_isPressedByAssign;\r
+                       }\r
+               }\r
+               if (m_lastGeneratedKey)\r
+                       m_lastGeneratedKey =\r
+                               i_setting->m_keyboard.searchKey(*m_lastGeneratedKey);\r
+               for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)\r
+                       if (m_lastPressedKey[i])\r
+                               m_lastPressedKey[i] =\r
+                                       i_setting->m_keyboard.searchKey(*m_lastPressedKey[i]);\r
+       }\r
+\r
+       m_setting = i_setting;\r
+\r
+       manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),\r
+                                 m_setting->m_sts4mayu, &m_sts4mayu);\r
+       manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),\r
+                                 m_setting->m_cts4mayu, &m_cts4mayu);\r
+\r
+       g_hookData->m_correctKanaLockHandling = m_setting->m_correctKanaLockHandling;\r
+       if (m_currentFocusOfThread) {\r
+               for (FocusOfThreads::iterator i = m_focusOfThreads.begin();\r
+                               i != m_focusOfThreads.end(); i ++) {\r
+                       FocusOfThread *fot = &(*i).second;\r
+                       m_setting->m_keymaps.searchWindow(&fot->m_keymaps,\r
+                                                                                         fot->m_className, fot->m_titleName);\r
+               }\r
+       }\r
+       m_setting->m_keymaps.searchWindow(&m_globalFocus.m_keymaps, _T(""), _T(""));\r
+       if (m_globalFocus.m_keymaps.empty()) {\r
+               Acquire a(&m_log, 0);\r
+               m_log << _T("internal error: m_globalFocus.m_keymap is empty")\r
+               << std::endl;\r
+       }\r
+       m_currentFocusOfThread = &m_globalFocus;\r
+       setCurrentKeymap(m_globalFocus.m_keymaps.front());\r
+       m_hwndFocus = NULL;\r
+       return true;\r
 }\r
 \r
 \r
-void Engine::checkShow(HWND i_hwnd)\r
-{\r
-  // update show style of window\r
-  // this update should be done in hook DLL, but to\r
-  // avoid update-loss for some applications(such as\r
-  // cmd.exe), we update here.\r
-  bool isMaximized = false;\r
-  bool isMinimized = false;\r
-  bool isMDIMaximized = false;\r
-  bool isMDIMinimized = false;\r
-  while (i_hwnd)\r
-  {\r
+void Engine::checkShow(HWND i_hwnd) {\r
+       // update show style of window\r
+       // this update should be done in hook DLL, but to\r
+       // avoid update-loss for some applications(such as\r
+       // cmd.exe), we update here.\r
+       bool isMaximized = false;\r
+       bool isMinimized = false;\r
+       bool isMDIMaximized = false;\r
+       bool isMDIMinimized = false;\r
+       while (i_hwnd) {\r
 #ifdef MAYU64\r
-    LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);\r
+               LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);\r
 #else\r
-    LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);\r
+               LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);\r
 #endif\r
-    if (exStyle & WS_EX_MDICHILD)\r
-    {\r
-      WINDOWPLACEMENT placement;\r
-      placement.length = sizeof(WINDOWPLACEMENT);\r
-      if (GetWindowPlacement(i_hwnd, &placement))\r
-      {\r
-        switch (placement.showCmd)\r
-        {\r
-          case SW_SHOWMAXIMIZED:\r
-            isMDIMaximized = true;\r
-            break;\r
-          case SW_SHOWMINIMIZED:\r
-            isMDIMinimized = true;\r
-            break;\r
-          case SW_SHOWNORMAL:\r
-          default:\r
-            break;\r
-        }\r
-      }\r
-    }\r
+               if (exStyle & WS_EX_MDICHILD) {\r
+                       WINDOWPLACEMENT placement;\r
+                       placement.length = sizeof(WINDOWPLACEMENT);\r
+                       if (GetWindowPlacement(i_hwnd, &placement)) {\r
+                               switch (placement.showCmd) {\r
+                               case SW_SHOWMAXIMIZED:\r
+                                       isMDIMaximized = true;\r
+                                       break;\r
+                               case SW_SHOWMINIMIZED:\r
+                                       isMDIMinimized = true;\r
+                                       break;\r
+                               case SW_SHOWNORMAL:\r
+                               default:\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
 \r
 #ifdef MAYU64\r
-    LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);\r
+               LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);\r
 #else\r
-    LONG style = GetWindowLong(i_hwnd, GWL_STYLE);\r
+               LONG style = GetWindowLong(i_hwnd, GWL_STYLE);\r
 #endif\r
-    if ((style & WS_CHILD) == 0)\r
-    {\r
-      WINDOWPLACEMENT placement;\r
-      placement.length = sizeof(WINDOWPLACEMENT);\r
-      if (GetWindowPlacement(i_hwnd, &placement))\r
-      {\r
-        switch (placement.showCmd)\r
-        {\r
-          case SW_SHOWMAXIMIZED:\r
-            isMaximized = true;\r
-            break;\r
-          case SW_SHOWMINIMIZED:\r
-            isMinimized = true;\r
-            break;\r
-          case SW_SHOWNORMAL:\r
-          default:\r
-            break;\r
-        }\r
-      }\r
-    }  \r
-    i_hwnd = GetParent(i_hwnd);\r
-  }\r
-  setShow(isMDIMaximized, isMDIMinimized, true);\r
-  setShow(isMaximized, isMinimized, false);\r
+               if ((style & WS_CHILD) == 0) {\r
+                       WINDOWPLACEMENT placement;\r
+                       placement.length = sizeof(WINDOWPLACEMENT);\r
+                       if (GetWindowPlacement(i_hwnd, &placement)) {\r
+                               switch (placement.showCmd) {\r
+                               case SW_SHOWMAXIMIZED:\r
+                                       isMaximized = true;\r
+                                       break;\r
+                               case SW_SHOWMINIMIZED:\r
+                                       isMinimized = true;\r
+                                       break;\r
+                               case SW_SHOWNORMAL:\r
+                               default:\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               i_hwnd = GetParent(i_hwnd);\r
+       }\r
+       setShow(isMDIMaximized, isMDIMinimized, true);\r
+       setShow(isMaximized, isMinimized, false);\r
 }\r
 \r
 \r
 // focus\r
-bool Engine::setFocus(HWND i_hwndFocus, DWORD i_threadId, \r
-                     const tstringi &i_className, const tstringi &i_titleName,\r
-                     bool i_isConsole)\r
-{\r
-  Acquire a(&m_cs);\r
-  if (m_isSynchronizing)\r
-    return false;\r
-  if (i_hwndFocus == NULL)\r
-    return true;\r
-\r
-  // remove newly created thread's id from m_detachedThreadIds\r
-  if (!m_detachedThreadIds.empty())\r
-  {\r
-    DetachedThreadIds::iterator i;\r
-    bool retry;\r
-    do\r
-    {\r
-      retry = false;\r
-      for (i = m_detachedThreadIds.begin();\r
-          i != m_detachedThreadIds.end(); ++ i)\r
-       if (*i == i_threadId)\r
-       {\r
-         m_detachedThreadIds.erase(i);\r
-         retry = true;\r
-         break;\r
+bool Engine::setFocus(HWND i_hwndFocus, DWORD i_threadId,\r
+                                         const tstringi &i_className, const tstringi &i_titleName,\r
+                                         bool i_isConsole) {\r
+       Acquire a(&m_cs);\r
+       if (m_isSynchronizing)\r
+               return false;\r
+       if (i_hwndFocus == NULL)\r
+               return true;\r
+\r
+       // remove newly created thread's id from m_detachedThreadIds\r
+       if (!m_detachedThreadIds.empty()) {\r
+               DetachedThreadIds::iterator i;\r
+               bool retry;\r
+               do {\r
+                       retry = false;\r
+                       for (i = m_detachedThreadIds.begin();\r
+                                       i != m_detachedThreadIds.end(); ++ i)\r
+                               if (*i == i_threadId) {\r
+                                       m_detachedThreadIds.erase(i);\r
+                                       retry = true;\r
+                                       break;\r
+                               }\r
+               } while (retry);\r
        }\r
-    } while (retry);\r
-  }\r
-  \r
-  FocusOfThread *fot;\r
-  FocusOfThreads::iterator i = m_focusOfThreads.find(i_threadId);\r
-  if (i != m_focusOfThreads.end())\r
-  {\r
-    fot = &(*i).second;\r
-    if (fot->m_hwndFocus == i_hwndFocus &&\r
-       fot->m_isConsole == i_isConsole &&\r
-       fot->m_className == i_className &&\r
-       fot->m_titleName == i_titleName)\r
-      return true;\r
-  }\r
-  else\r
-  {\r
-    i = m_focusOfThreads.insert(\r
-      FocusOfThreads::value_type(i_threadId, FocusOfThread())).first;\r
-    fot = &(*i).second;\r
-    fot->m_threadId = i_threadId;\r
-  }\r
-  fot->m_hwndFocus = i_hwndFocus;\r
-  fot->m_isConsole = i_isConsole;\r
-  fot->m_className = i_className;\r
-  fot->m_titleName = i_titleName;\r
-  \r
-  if (m_setting)\r
-  {\r
-    m_setting->m_keymaps.searchWindow(&fot->m_keymaps,\r
-                                     i_className, i_titleName);\r
-    ASSERT(0 < fot->m_keymaps.size());\r
-  }\r
-  else\r
-    fot->m_keymaps.clear();\r
-  checkShow(i_hwndFocus);\r
-  return true;\r
+\r
+       FocusOfThread *fot;\r
+       FocusOfThreads::iterator i = m_focusOfThreads.find(i_threadId);\r
+       if (i != m_focusOfThreads.end()) {\r
+               fot = &(*i).second;\r
+               if (fot->m_hwndFocus == i_hwndFocus &&\r
+                               fot->m_isConsole == i_isConsole &&\r
+                               fot->m_className == i_className &&\r
+                               fot->m_titleName == i_titleName)\r
+                       return true;\r
+       } else {\r
+               i = m_focusOfThreads.insert(\r
+                               FocusOfThreads::value_type(i_threadId, FocusOfThread())).first;\r
+               fot = &(*i).second;\r
+               fot->m_threadId = i_threadId;\r
+       }\r
+       fot->m_hwndFocus = i_hwndFocus;\r
+       fot->m_isConsole = i_isConsole;\r
+       fot->m_className = i_className;\r
+       fot->m_titleName = i_titleName;\r
+\r
+       if (m_setting) {\r
+               m_setting->m_keymaps.searchWindow(&fot->m_keymaps,\r
+                                                                                 i_className, i_titleName);\r
+               ASSERT(0 < fot->m_keymaps.size());\r
+       } else\r
+               fot->m_keymaps.clear();\r
+       checkShow(i_hwndFocus);\r
+       return true;\r
 }\r
 \r
 \r
 // lock state\r
 bool Engine::setLockState(bool i_isNumLockToggled,\r
-                         bool i_isCapsLockToggled,\r
-                         bool i_isScrollLockToggled,\r
-                         bool i_isKanaLockToggled,\r
-                         bool i_isImeLockToggled,\r
-                         bool i_isImeCompToggled)\r
-{\r
-  Acquire a(&m_cs);\r
-  if (m_isSynchronizing)\r
-    return false;\r
-  m_currentLock.on(Modifier::Type_NumLock, i_isNumLockToggled);\r
-  m_currentLock.on(Modifier::Type_CapsLock, i_isCapsLockToggled);\r
-  m_currentLock.on(Modifier::Type_ScrollLock, i_isScrollLockToggled);\r
-  m_currentLock.on(Modifier::Type_KanaLock, i_isKanaLockToggled);\r
-  m_currentLock.on(Modifier::Type_ImeLock, i_isImeLockToggled);\r
-  m_currentLock.on(Modifier::Type_ImeComp, i_isImeCompToggled);\r
-  return true;\r
+                                                 bool i_isCapsLockToggled,\r
+                                                 bool i_isScrollLockToggled,\r
+                                                 bool i_isKanaLockToggled,\r
+                                                 bool i_isImeLockToggled,\r
+                                                 bool i_isImeCompToggled) {\r
+       Acquire a(&m_cs);\r
+       if (m_isSynchronizing)\r
+               return false;\r
+       m_currentLock.on(Modifier::Type_NumLock, i_isNumLockToggled);\r
+       m_currentLock.on(Modifier::Type_CapsLock, i_isCapsLockToggled);\r
+       m_currentLock.on(Modifier::Type_ScrollLock, i_isScrollLockToggled);\r
+       m_currentLock.on(Modifier::Type_KanaLock, i_isKanaLockToggled);\r
+       m_currentLock.on(Modifier::Type_ImeLock, i_isImeLockToggled);\r
+       m_currentLock.on(Modifier::Type_ImeComp, i_isImeCompToggled);\r
+       return true;\r
 }\r
 \r
 \r
 // show\r
 bool Engine::setShow(bool i_isMaximized, bool i_isMinimized,\r
-                    bool i_isMDI)\r
-{\r
-  Acquire a(&m_cs);\r
-  if (m_isSynchronizing)\r
-    return false;\r
-  Acquire b(&m_log, 1);\r
-  Modifier::Type max, min;\r
-  if (i_isMDI == true) {\r
-    max = Modifier::Type_MdiMaximized;\r
-    min = Modifier::Type_MdiMinimized;\r
-  }\r
-  else\r
-  {\r
-    max = Modifier::Type_Maximized;\r
-    min = Modifier::Type_Minimized;\r
-  }\r
-  m_currentLock.on(max, i_isMaximized);\r
-  m_currentLock.on(min, i_isMinimized);\r
-  m_log << _T("Set show to ") << (i_isMaximized ? _T("Maximized") :\r
-                                 i_isMinimized ? _T("Minimized") : _T("Normal"));\r
-  if (i_isMDI == true)\r
-  {\r
-    m_log << _T(" (MDI)");\r
-  }\r
-  m_log << std::endl;\r
-  return true;\r
+                                        bool i_isMDI) {\r
+       Acquire a(&m_cs);\r
+       if (m_isSynchronizing)\r
+               return false;\r
+       Acquire b(&m_log, 1);\r
+       Modifier::Type max, min;\r
+       if (i_isMDI == true) {\r
+               max = Modifier::Type_MdiMaximized;\r
+               min = Modifier::Type_MdiMinimized;\r
+       } else {\r
+               max = Modifier::Type_Maximized;\r
+               min = Modifier::Type_Minimized;\r
+       }\r
+       m_currentLock.on(max, i_isMaximized);\r
+       m_currentLock.on(min, i_isMinimized);\r
+       m_log << _T("Set show to ") << (i_isMaximized ? _T("Maximized") :\r
+                                                                       i_isMinimized ? _T("Minimized") : _T("Normal"));\r
+       if (i_isMDI == true) {\r
+               m_log << _T(" (MDI)");\r
+       }\r
+       m_log << std::endl;\r
+       return true;\r
 }\r
 \r
 \r
 // sync\r
-bool Engine::syncNotify()\r
-{\r
-  Acquire a(&m_cs);\r
-  if (!m_isSynchronizing)\r
-    return false;\r
-  CHECK_TRUE( SetEvent(m_eSync) );\r
-  return true;\r
+bool Engine::syncNotify() {\r
+       Acquire a(&m_cs);\r
+       if (!m_isSynchronizing)\r
+               return false;\r
+       CHECK_TRUE( SetEvent(m_eSync) );\r
+       return true;\r
 }\r
 \r
 \r
 // thread detach notify\r
-bool Engine::threadDetachNotify(DWORD i_threadId)\r
-{\r
-  Acquire a(&m_cs);\r
-  m_detachedThreadIds.push_back(i_threadId);\r
-  return true;\r
+bool Engine::threadDetachNotify(DWORD i_threadId) {\r
+       Acquire a(&m_cs);\r
+       m_detachedThreadIds.push_back(i_threadId);\r
+       return true;\r
 }\r
 \r
 \r
 // get help message\r
-void Engine::getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle)\r
+void Engine::getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle) {\r
+       Acquire a(&m_cs);\r
+       *o_helpMessage = m_helpMessage;\r
+       *o_helpTitle = m_helpTitle;\r
+}\r
+\r
+\r
+unsigned int WINAPI Engine::InputHandler::run(void *i_this)\r
 {\r
-  Acquire a(&m_cs);\r
-  *o_helpMessage = m_helpMessage;\r
-  *o_helpTitle = m_helpTitle;\r
+       reinterpret_cast<InputHandler*>(i_this)->run();\r
+       _endthreadex(0);\r
+       return 0;\r
 }\r
 \r
+Engine::InputHandler::InputHandler(INSTALL_HOOK i_installHook, INPUT_DETOUR i_inputDetour)\r
+       : m_installHook(i_installHook), m_inputDetour(i_inputDetour)\r
+{\r
+       CHECK_TRUE(m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL));\r
+       CHECK_TRUE(m_hThread = (HANDLE)_beginthreadex(NULL, 0, run, this, CREATE_SUSPENDED, &m_threadId));\r
+}\r
 \r
-// command notify\r
-void Engine::commandNotify(\r
-  HWND i_hwnd, UINT i_message, WPARAM i_wParam, LPARAM i_lParam)\r
+Engine::InputHandler::~InputHandler()\r
 {\r
-  Acquire b(&m_log, 0);\r
-  HWND hf = m_hwndFocus;\r
-  if (!hf)\r
-    return;\r
-\r
-  if (GetWindowThreadProcessId(hf, NULL) == \r
-      GetWindowThreadProcessId(m_hwndAssocWindow, NULL))\r
-    return;    // inhibit the investigation of MADO TSUKAI NO YUUTSU\r
-\r
-  const _TCHAR *target = NULL;\r
-  int number_target = 0;\r
-  \r
-  if (i_hwnd == hf)\r
-    target = _T("ToItself");\r
-  else if (i_hwnd == GetParent(hf))\r
-    target = _T("ToParentWindow");\r
-  else\r
-  {\r
-    // Function::toMainWindow\r
-    HWND h = hf;\r
-    while (true)\r
-    {\r
-      HWND p = GetParent(h);\r
-      if (!p)\r
-       break;\r
-      h = p;\r
-    }\r
-    if (i_hwnd == h)\r
-      target = _T("ToMainWindow");\r
-    else\r
-    {\r
-      // Function::toOverlappedWindow\r
-      HWND h = hf;\r
-      while (h)\r
-      {\r
-#ifdef MAYU64\r
-       LONG_PTR style = GetWindowLongPtr(h, GWL_STYLE);\r
-#else\r
-       LONG style = GetWindowLong(h, GWL_STYLE);\r
-#endif\r
-       if ((style & WS_CHILD) == 0)\r
-         break;\r
-       h = GetParent(h);\r
-      }\r
-      if (i_hwnd == h)\r
-       target = _T("ToOverlappedWindow");\r
-      else\r
-      {\r
-       // number\r
-       HWND h = hf;\r
-       for (number_target = 0; h; number_target ++, h = GetParent(h))\r
-         if (i_hwnd == h)\r
-           break;\r
+       CloseHandle(m_hEvent);\r
+}\r
+\r
+void Engine::InputHandler::run()\r
+{\r
+       MSG msg;\r
+\r
+       CHECK_FALSE(m_installHook(m_inputDetour, m_engine, true));\r
+       PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);\r
+       SetEvent(m_hEvent);\r
+\r
+       while (GetMessage(&msg, NULL, 0, 0)) {\r
+               // nothing to do...\r
+       }\r
+\r
+       CHECK_FALSE(m_installHook(m_inputDetour, m_engine, false));\r
+\r
        return;\r
-      }\r
-    }\r
-  }\r
-\r
-  m_log << _T("&PostMessage(");\r
-  if (target)\r
-    m_log << target;\r
-  else\r
-    m_log << number_target;\r
-  m_log << _T(", ") << i_message\r
-       << _T(", 0x") << std::hex << i_wParam\r
-       << _T(", 0x") << i_lParam << _T(") # hwnd = ")\r
-       << reinterpret_cast<int>(i_hwnd) << _T(", ")\r
-       << _T("message = ") << std::dec;\r
-  if (i_message == WM_COMMAND)\r
-    m_log << _T("WM_COMMAND, ");\r
-  else if (i_message == WM_SYSCOMMAND)\r
-    m_log << _T("WM_SYSCOMMAND, ");\r
-  else\r
-    m_log << i_message << _T(", ");\r
-  m_log << _T("wNotifyCode = ") << HIWORD(i_wParam) << _T(", ")\r
-       << _T("wID = ") << LOWORD(i_wParam) << _T(", ")\r
-       << _T("hwndCtrl = 0x") << std::hex << i_lParam << std::dec << std::endl;\r
+}\r
+\r
+int Engine::InputHandler::start(Engine *i_engine)\r
+{\r
+       m_engine = i_engine;\r
+       ResumeThread(m_hThread);\r
+       WaitForSingleObject(m_hEvent, INFINITE);\r
+       return 0;\r
+}\r
+\r
+int Engine::InputHandler::stop()\r
+{\r
+       PostThreadMessage(m_threadId, WM_QUIT, 0, 0);\r
+       WaitForSingleObject(m_hThread, INFINITE);\r
+       return 0;\r
 }\r