OSDN Git Service

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