OSDN Git Service

Stop setting an invalid value to the keyboard state to push the control key.
[xkeymacs/xkeymacs.git] / xkeymacsdll / xkeymacsdll.cpp
index f094391..fecf659 100644 (file)
@@ -1,13 +1,14 @@
 // xkeymacsdll.cpp : Defines the initialization routines for the DLL.\r
 //\r
 \r
-#include "stdafx.h"\r
-#include "resource.h"\r
+#include "xkeymacsdll.h"\r
 #include "Utils.h"\r
 #include "Commands.h"\r
-#include <afxdllx.h>\r
+#include "CmdTable.h"\r
+#include "../xkeymacs/resource.h"\r
 #include <math.h>\r
 #include <Imm.h>\r
+#include <vector>\r
 \r
 #ifdef _DEBUG\r
 #define new DEBUG_NEW\r
 static char THIS_FILE[] = __FILE__;\r
 #endif\r
 \r
-struct KbdMacro\r
-{\r
-       int nCode;\r
-       WPARAM wParam;\r
-       LPARAM lParam;\r
-       BOOL bOriginal;\r
-};\r
-\r
 struct Modifier {\r
        LPCTSTR name;\r
        int id;\r
@@ -39,8 +32,12 @@ static const Modifier Modifiers[] = {
        { _T("Alt+"), WIN_ALT },\r
        { _T("Win+"), WIN_WIN },\r
 };\r
+static const int MAX_MODIFIER = _countof(Modifiers);\r
 \r
-static const KeyName ControlCharacters[] = {\r
+static const struct {\r
+       BYTE bVk;\r
+       LPCTSTR name;\r
+} KeyNames[] = {\r
 //     { VK_LBUTTON,           _T("mouse-1") },                                // does not work well\r
 //     { VK_RBUTTON,           _T("mouse-3") },                                // does not work well\r
        { VK_CANCEL,            _T("break") },\r
@@ -89,7 +86,7 @@ static const KeyName ControlCharacters[] = {
        { VK_DECIMAL,           _T("kp-decimal") },\r
        { VK_DIVIDE,            _T("kp-divide") },\r
 //     { VK_F1,                        _T("f1") },                                             // FIXME\r
-//     { VK_F2,                        _T("f2") },                                             // Move at the end of definition of funcgtion keys to keep away confliction f1/f2 and f1?/f2? by _tcsncmp() i.e. strncmp()\r
+//     { VK_F2,                        _T("f2") },                                             // Move at the end of definition of function keys to keep away confliction f1/f2 and f1?/f2? by _tcsncmp() i.e. strncmp()\r
        { VK_F3,                        _T("f3") },\r
        { VK_F4,                        _T("f4") },\r
        { VK_F5,                        _T("f5") },\r
@@ -135,50 +132,18 @@ static const KeyName ControlCharacters[] = {
        { 0xb6,                         _T("launch-1") },                               // VK_LAUNCH_APP1\r
        { 0xb7,                         _T("launch-2") },                               // VK_LAUNCH_APP2\r
 };\r
+static const int MAX_KEYNAME = _countof(KeyNames);\r
 \r
 static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL };\r
 \r
-HINSTANCE g_hDllInst = NULL;\r
-UINT g_ImeManipulationMessage = 0;\r
-#pragma data_seg(".xkmcs")\r
-HHOOK g_hHookKeyboard = NULL;\r
-HHOOK g_hHookDummy = NULL;\r
-#pragma data_seg()\r
-\r
-inline bool IsWow64(HANDLE mod) {\r
-       typedef BOOL (WINAPI *pfnIsWow64Process_t)(HANDLE, PBOOL);\r
-       if (const pfnIsWow64Process_t IsWow64Process = (pfnIsWow64Process_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process")) {\r
-               BOOL b;\r
-               return IsWow64Process(mod, &b) && b;\r
-       }\r
-       return false;\r
-}\r
-\r
-inline bool Is64System() {\r
-       SYSTEM_INFO info;\r
-       GetNativeSystemInfo(&info);\r
-       return info.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL;\r
-}\r
-\r
-inline bool Is64Process(HANDLE mod) {\r
-       return Is64System() && !IsWow64(mod);\r
-}\r
-\r
-const bool IsDll64 = sizeof(void *) == 8;\r
-\r
-inline bool Is64ProcessHwnd(HWND hwnd) {\r
-       DWORD pid;\r
-       GetWindowThreadProcessId(hwnd, &pid);\r
-       HANDLE hmod = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);\r
-       bool b = Is64Process(hmod);\r
-       CloseHandle(hmod);\r
-       return b;\r
-}\r
+static HINSTANCE g_hDllInst = NULL;\r
+static DWORD g_TlsIndex = 0;\r
 \r
 extern "C" int APIENTRY\r
 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
 {\r
        g_hDllInst = hInstance;\r
+       LPVOID lpData;\r
        \r
        // Remove this if you use lpReserved\r
        UNREFERENCED_PARAMETER(lpReserved);\r
@@ -186,7 +151,6 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
        switch (dwReason) {\r
        case DLL_PROCESS_ATTACH:\r
                TRACE0("XKEYMACSDLL.DLL Initializing!\n");\r
-               g_ImeManipulationMessage = RegisterWindowMessage(_T("XkManipulateIME"));\r
 \r
                // Extension DLL one-time initialization\r
                if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) {\r
@@ -212,11 +176,27 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
                        e->Delete();\r
 //                     CUtils::Log("DllMain: 'new' threw an exception");\r
                }\r
+\r
+               if ((g_TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)\r
+                       return FALSE;\r
+               // fall through\r
+       case DLL_THREAD_ATTACH:\r
+               if ((lpData = LocalAlloc(LPTR, sizeof(HHOOK))) != NULL)\r
+                       TlsSetValue(g_TlsIndex, lpData);\r
                break;\r
        case DLL_PROCESS_DETACH:\r
                TRACE0("XKEYMACSDLL.DLL Terminating!\n");\r
                // Terminate the library before destructors are called\r
                AfxTermExtensionModule(XkeymacsdllDLL);\r
+               CXkeymacsDll::ReleaseKeyboardHook();\r
+               if ((lpData = TlsGetValue(g_TlsIndex)) != NULL)\r
+                       LocalFree(lpData);\r
+               TlsFree(g_TlsIndex);\r
+               break;\r
+       case DLL_THREAD_DETACH:\r
+               CXkeymacsDll::ReleaseKeyboardHook();\r
+               if ((lpData = TlsGetValue(g_TlsIndex)) != NULL)\r
+                       LocalFree(lpData);\r
                break;\r
        }\r
        return 1;   // ok\r
@@ -226,45 +206,31 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
 // CXkeymacsDll Class\r
 //////////////////////////////////////////////////////////////////////\r
 \r
-#include "xkeymacsDll.h"\r
 #pragma data_seg(".xkmcs")\r
-       BOOL    CXkeymacsDll::m_bHookAltRelease = FALSE;\r
-       HHOOK   CXkeymacsDll::m_hHookCallWnd = NULL;\r
-       HHOOK   CXkeymacsDll::m_hHookCallWndRet = NULL;\r
-       HHOOK   CXkeymacsDll::m_hHookGetMessage = NULL;\r
-       HHOOK   CXkeymacsDll::m_hHookShell = NULL;\r
-       BOOL    CXkeymacsDll::m_bRightControl   = FALSE;\r
-       BOOL    CXkeymacsDll::m_bRightAlt               = FALSE;\r
-       BOOL    CXkeymacsDll::m_bRightShift             = FALSE;\r
-       BOOL    CXkeymacsDll::m_bHook                   = TRUE;\r
-       BOOL    CXkeymacsDll::m_bDefiningMacro  = FALSE;\r
-       CList<CClipboardSnap *, CClipboardSnap *> CXkeymacsDll::m_oKillRing;\r
-       CObList CXkeymacsDll::m_Macro;\r
-       int             CXkeymacsDll::m_nKillRing = 0;\r
-       int             CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
-       int             CXkeymacsDll::m_nApplicationID = 0;\r
-       int             CXkeymacsDll::m_nAccelerate = 0;\r
-       int             CXkeymacsDll::m_nKeyboardSpeed = 31;\r
-       HCURSOR CXkeymacsDll::m_hCursor[MAX_STATUS] = {'\0'};\r
-       HCURSOR CXkeymacsDll::m_hCurrentCursor = NULL;\r
-       BOOL    CXkeymacsDll::m_bCursor = FALSE;\r
-       TCHAR   CXkeymacsDll::m_M_xTip[128] = "";\r
-       CONFIG  CXkeymacsDll::m_Config = {0};\r
+Config CXkeymacsDll::m_Config = {0};\r
+bool CXkeymacsDll::m_bEnableKeyboardHook = false;\r
+BOOL CXkeymacsDll::m_bHook = TRUE;\r
+DWORD CXkeymacsDll::m_nHookAltRelease = 0;\r
+BOOL CXkeymacsDll::m_bRightShift = FALSE;\r
+BOOL CXkeymacsDll::m_bRightControl = FALSE;\r
+BOOL CXkeymacsDll::m_bRightAlt = FALSE;\r
+TCHAR CXkeymacsDll::m_M_xTip[128] = "";\r
+BYTE CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
+int CXkeymacsDll::m_nAccelerate = 0;\r
+int CXkeymacsDll::m_nKeyboardSpeed = 31;\r
+HCURSOR CXkeymacsDll::m_hCurrentCursor = NULL;\r
+BOOL CXkeymacsDll::m_bCursor = FALSE;\r
+HCURSOR CXkeymacsDll::m_hCursor[MAX_STATUS] = {'\0'};\r
 #pragma data_seg()\r
 \r
-//////////////////////////////////////////////////////////////////////\r
-// Construction/Destruction\r
-//////////////////////////////////////////////////////////////////////\r
-\r
-CXkeymacsDll::CXkeymacsDll()\r
-{\r
-\r
-}\r
-\r
-CXkeymacsDll::~CXkeymacsDll()\r
-{\r
-\r
-}\r
+AppConfig* CXkeymacsDll::m_CurrentConfig = NULL;\r
+HHOOK CXkeymacsDll::m_hHookCallWnd = NULL;\r
+HHOOK CXkeymacsDll::m_hHookCallWndRet = NULL;\r
+HHOOK CXkeymacsDll::m_hHookGetMessage = NULL;\r
+HHOOK CXkeymacsDll::m_hHookShell = NULL;\r
+CList<CClipboardSnap *, CClipboardSnap *> CXkeymacsDll::m_oKillRing;\r
+int CXkeymacsDll::m_nKillRing = 0;\r
+KbdMacro* CXkeymacsDll::m_kbdMacro = NULL;\r
 \r
 BOOL CXkeymacsDll::SaveConfig()\r
 {\r
@@ -277,7 +243,7 @@ BOOL CXkeymacsDll::SaveConfig()
        if (hFile == INVALID_HANDLE_VALUE)\r
                return FALSE;\r
        DWORD written;\r
-       BOOL res = WriteFile(hFile, &m_Config, sizeof(m_Config), &written, NULL) || written != sizeof(m_Config);\r
+       BOOL res = WriteFile(hFile, &m_Config, sizeof(m_Config), &written, NULL) && written == sizeof(m_Config);\r
        CloseHandle(hFile);\r
        return res;\r
 }\r
@@ -298,27 +264,37 @@ BOOL CXkeymacsDll::LoadConfig()
        return res;\r
 }\r
 \r
-void CXkeymacsDll::SetHookAltRelease()\r
+void CXkeymacsDll::SetConfig(const Config& config)\r
 {\r
-       m_bHookAltRelease = TRUE;\r
+       m_Config = config;\r
 }\r
 \r
-// set hooks\r
-LRESULT WINAPI DummyProc(int code, WPARAM wp, LPARAM lp) {\r
-       return CallNextHookEx(0, code, wp, lp);\r
+void CXkeymacsDll::SetHooks()\r
+{\r
+       m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, g_hDllInst, 0);\r
+       m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndRetProc, g_hDllInst, 0);\r
+       m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hDllInst, 0);\r
+       m_hHookShell = SetWindowsHookEx(WH_SHELL, ShellProc, g_hDllInst, 0);\r
+       m_bEnableKeyboardHook = true;\r
 }\r
 \r
-void CXkeymacsDll::SetHooks()\r
+void CXkeymacsDll::SetKeyboardHook(DWORD threadId)\r
 {\r
-       m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);\r
-       m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);\r
-       m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);\r
-       m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);\r
-       g_hHookDummy = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)DummyProc, g_hDllInst, 0);\r
-       g_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, 0);\r
+       LPVOID lpData = TlsGetValue(g_TlsIndex);\r
+       if (!lpData) {\r
+               lpData = LocalAlloc(LPTR, sizeof(HHOOK));\r
+               if (!lpData)\r
+                       return;\r
+               if (!TlsSetValue(g_TlsIndex, lpData))\r
+                       return;\r
+       }\r
+       HHOOK *phHook = reinterpret_cast<HHOOK *>(lpData);\r
+       if (!*phHook)\r
+               *phHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hDllInst, threadId ? threadId : GetCurrentThreadId());\r
 }\r
 \r
-inline void unhook(HHOOK &hh) {\r
+inline void unhook(HHOOK &hh)\r
+{\r
        if (hh)\r
                UnhookWindowsHookEx(hh);\r
        hh = NULL;\r
@@ -330,21 +306,36 @@ void CXkeymacsDll::ResetHooks()
        SetHooks();\r
 }\r
 \r
-// release hooks\r
 void CXkeymacsDll::ReleaseHooks()\r
 {\r
        unhook(m_hHookCallWnd);\r
        unhook(m_hHookCallWndRet);\r
        unhook(m_hHookGetMessage);\r
        unhook(m_hHookShell);\r
-       unhook(g_hHookKeyboard);\r
-       unhook(g_hHookDummy);\r
+       m_bEnableKeyboardHook = false;\r
+}\r
+\r
+void CXkeymacsDll::ReleaseKeyboardHook()\r
+{\r
+       HHOOK *phHook = reinterpret_cast<HHOOK *>(TlsGetValue(g_TlsIndex));\r
+       if (phHook)\r
+               unhook(*phHook);\r
+}\r
+\r
+void CXkeymacsDll::ToggleKeyboardHookState()\r
+{\r
+       m_bHook = !m_bHook;\r
+       ShowKeyboardHookState();\r
 }\r
 \r
-void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)\r
+BOOL CXkeymacsDll::IsKeyboardHook()\r
+{\r
+       return m_bHook;\r
+}\r
+\r
+void CXkeymacsDll::ShowKeyboardHookState()\r
 {\r
-       m_bHook = bFlag;\r
-       ICONMSG msg = {MAIN_ICON,};\r
+       IconMsg msg = {MAIN_ICON,};\r
        if (m_bHook) {\r
                if (CCommands::IsTemporarilyDisableXKeymacs()) {\r
                        msg.nState = STATUS_DISABLE_TMP;\r
@@ -356,8 +347,8 @@ void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)
        } else {\r
                msg.nState = STATUS_DISABLE_WOCQ;\r
        }\r
-       if (m_Config.nSettingStyle[m_nApplicationID] == SETTING_DISABLE\r
-        || (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default"))\r
+       if (m_CurrentConfig->SettingStyle == SETTING_DISABLE\r
+        || (!_tcsicmp(m_CurrentConfig->AppName, _T("Default"))\r
          && CUtils::IsDefaultIgnoreApplication())) {\r
                msg.nState = STATUS_DISABLE;\r
                m_hCurrentCursor = m_hCursor[STATUS_DISABLE];\r
@@ -366,407 +357,118 @@ void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)
        DoSetCursor();\r
 }\r
 \r
-// if be keyboard hook, return TRUE\r
-BOOL CXkeymacsDll::IsKeyboardHook()\r
-{\r
-       if (m_bHook) {\r
-               return TRUE;\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void CXkeymacsDll::LogCallWndProcMessage(WPARAM wParam, LPARAM lParam)\r
-{\r
-       CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
-\r
-       switch (cwps.message) {\r
-       case WM_PAINT:                                  // 0x000F\r
-       case WM_MDIGETACTIVE:                   // 0x0229\r
-       case 0x0403:\r
-       case 0x0407:\r
-       case 0x0418:\r
-       case 0x043F:\r
-       case 0x0440:\r
-               break;\r
-       case WM_CREATE:                                 // 0x0001\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_CREATE"));\r
-               break;\r
-       case WM_DESTROY:                                // 0x0002\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_DESTROY"));\r
-               break;\r
-       case WM_MOVE:                                   // 0x0003\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_MOVE");)\r
-               break;\r
-       case WM_SIZE:                                   // 0x0005\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_SIZE"));\r
-               break;\r
-       case WM_GETTEXT:                                // 0x000D\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_GETTEXT"));\r
-               break;\r
-       case WM_ERASEBKGND:                             // 0x0014\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_ERASEBKGND"));\r
-               break;\r
-       case WM_WINDOWPOSCHANGING:              // 0x0046\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGING"));\r
-               break;\r
-       case WM_WINDOWPOSCHANGED:               // 0x0047\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGED"));\r
-               break;\r
-       case WM_COPYDATA:                               // 0x004A\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_COPYDATA"));\r
-               break;\r
-       case WM_NCCREATE:                               // 0x0081\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCREATE"));\r
-               break;\r
-       case WM_NCDESTROY:                              // 0x0082\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_NCDESTROY"));\r
-               break;\r
-       case WM_NCCALCSIZE:                             // 0x0083\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCALCSIZE"));\r
-               break;\r
-       case WM_NCPAINT:                                // 0x0085\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_NCPAINT"));\r
-               break;\r
-       case WM_IME_STARTCOMPOSITION:   // 0x010D\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_STARTCOMPOSITION"));\r
-               break;\r
-       case WM_IME_ENDCOMPOSITION:             // 0x010E\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_ENDCOMPOSITION"));\r
-               break;\r
-       case WM_IME_KEYLAST:                    // 0x010F\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_KEYLAST"));\r
-               break;\r
-       case WM_COMMAND:                                // 0x0111\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_COMMAND"));\r
-               break;\r
-       case WM_CTLCOLOREDIT:                   // 0x0133\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_CTLCOLOREDIT"));\r
-               break;\r
-       case WM_POWERBROADCAST:                 // 0x0218\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_POWERBROADCAST"));\r
-               switch (wParam) {\r
-               case PBT_APMQUERYSUSPEND:               // 0x0000\r
-//                     CUtils::Log(_T("PBT_APMQUERYSUSPEND"));\r
-                       break;\r
-               case PBT_APMQUERYSTANDBY:               // 0x0001\r
-//                     CUtils::Log(_T("PBT_APMQUERYSTANDBY"));\r
-                       break;\r
-               case PBT_APMQUERYSUSPENDFAILED: // 0x0002\r
-//                     CUtils::Log(_T("PBT_APMQUERYSUSPENDFAILED"));\r
-                       break;\r
-               case PBT_APMQUERYSTANDBYFAILED: // 0x0003\r
-//                     CUtils::Log(_T("PBT_APMQUERYSTANDBYFAILED"));\r
-                       break;\r
-               case PBT_APMSUSPEND:                    // 0x0004\r
-//                     CUtils::Log(_T("PBT_APMSUSPEND"));\r
-                       break;\r
-               case PBT_APMSTANDBY:                    // 0x0005\r
-//                     CUtils::Log(_T("PBT_APMSTANDBY"));\r
-                       break;\r
-               case PBT_APMRESUMECRITICAL:             // 0x0006\r
-//                     CUtils::Log(_T("PBT_APMRESUMECRITICAL"));\r
-                       break;\r
-               case PBT_APMRESUMESUSPEND:              // 0x0007\r
-//                     CUtils::Log(_T("PBT_APMRESUMESUSPEND"));\r
-                       break;\r
-               case PBT_APMRESUMESTANDBY:              // 0x0008\r
-//                     CUtils::Log(_T("PBT_APMRESUMESTANDBY"));\r
-                       break;\r
-               case PBT_APMBATTERYLOW:                 // 0x0009\r
-//                     CUtils::Log(_T("PBT_APMBATTERYLOW"));\r
-                       break;\r
-               case PBT_APMPOWERSTATUSCHANGE:  // 0x000A\r
-//                     CUtils::Log(_T("PBT_APMPOWERSTATUSCHANGE"));\r
-                       break;\r
-               case PBT_APMOEMEVENT:                   // 0x000B\r
-//                     CUtils::Log(_T("PBT_APMOEMEVENT"));\r
-                       break;\r
-               case PBT_APMRESUMEAUTOMATIC:    // 0x0012\r
-//                     CUtils::Log(_T("PBT_APMRESUMEAUTOMATIC"));\r
-                       break;\r
-               default:\r
-//                     CUtils::Log(_T("PBT_OTHERS: %d"), wParam);\r
-                       break;\r
-               }\r
-               break;\r
-       case WM_IME_NOTIFY:                             // 0x0282\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_NOTIFY"));\r
-               break;\r
-       default:\r
-//             CUtils::Log(_T("CallWndProc: cwps.message = 0x%04X"), cwps.message);\r
-               break;\r
-       }\r
-}\r
-\r
 LRESULT CALLBACK CXkeymacsDll::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
-//     LogCallWndProcMessage(wParam, lParam);\r
-\r
-       if (0 <= nCode) {\r
-               CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
-               switch (cwps.message) {\r
+       SetKeyboardHook();\r
+       if (nCode >= 0) {\r
+               const CWPSTRUCT *cwps = reinterpret_cast<CWPSTRUCT *>(lParam);\r
+               switch (cwps->message) {\r
                case WM_IME_STARTCOMPOSITION:\r
-                       InitKeyboardProc(TRUE);\r
+                       InitKeyboardProc(true);\r
                        break;\r
                case WM_IME_ENDCOMPOSITION:\r
-                       InitKeyboardProc(FALSE);\r
+                       InitKeyboardProc(false);\r
                        break;\r
                case WM_SETFOCUS:\r
-                       if (cwps.hwnd == GetForegroundWindow()) {\r
-                               InitKeyboardProc(FALSE);\r
-                               SetKeyboardHookFlag(m_bHook);\r
+                       if (cwps->hwnd == GetForegroundWindow()) {\r
+                               InitKeyboardProc(false);\r
+                               ShowKeyboardHookState();\r
                        }\r
                        break;\r
                case WM_NCACTIVATE:\r
-                       if (cwps.wParam) {\r
-                               if (cwps.hwnd == GetForegroundWindow()) {\r
-                                       InitKeyboardProc(FALSE);\r
-                                       SetKeyboardHookFlag(m_bHook);\r
-                               }\r
-                       }\r
-                       break;\r
-               case WM_POWERBROADCAST:\r
-                       switch (wParam) {\r
-                       case PBT_APMRESUMECRITICAL: // 0x0006\r
-                       case PBT_APMRESUMESUSPEND:  // 0x0007\r
-                       case PBT_APMRESUMESTANDBY:  // 0x0008\r
-                               ReleaseHooks();\r
-                               SetHooks();\r
-                               break;\r
-                       default:\r
-                               break;\r
+                       if (cwps->wParam && cwps->hwnd == GetForegroundWindow()) {\r
+                               InitKeyboardProc(false);\r
+                               ShowKeyboardHookState();\r
                        }\r
                        break;\r
-               default:\r
-                       break;\r
                }\r
        }\r
-       return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);\r
+       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
 }\r
 \r
 LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
-       if (0 <= nCode) {\r
-               CWPRETSTRUCT &cwprets = *(CWPRETSTRUCT *)lParam;\r
-               switch (cwprets.message) {\r
+       SetKeyboardHook();\r
+       if (nCode >= 0) {\r
+               const CWPRETSTRUCT *cwprets = reinterpret_cast<CWPRETSTRUCT *>(lParam);\r
+               switch (cwprets->message) {\r
                case WM_SETTEXT:\r
-                       if (cwprets.hwnd == GetForegroundWindow()) {\r
-                               InitKeyboardProc(FALSE);\r
-                       }\r
+                       if (cwprets->hwnd == GetForegroundWindow())\r
+                               InitKeyboardProc(false);\r
                        break;\r
                case WM_SETCURSOR:\r
                        DoSetCursor();\r
                        break;\r
-               default:\r
-                       break;\r
                }\r
        }\r
-       return CallNextHookEx(m_hHookCallWndRet, nCode, wParam, lParam);\r
+       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
 }\r
 \r
 LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
-       MSG &msg = (*(MSG *)lParam);\r
-       if (msg.message == g_ImeManipulationMessage) {\r
-               if (wParam)\r
-                       CCommands::DoSetInputMethodOpenStatus((INPUT_METHOD_OPEN_STATUS)msg.wParam, msg.lParam);\r
-               return 1;\r
-       }\r
-       switch (msg.message) {\r
-       case WM_IME_STARTCOMPOSITION:\r
-               InitKeyboardProc(TRUE);\r
-               break;\r
-       case WM_IME_ENDCOMPOSITION:\r
-               InitKeyboardProc(FALSE);\r
-               break;\r
+       SetKeyboardHook();\r
+       if (nCode >= 0) {\r
+               const MSG *msg = reinterpret_cast<MSG *>(lParam);\r
+               switch (msg->message) {\r
+               case WM_IME_STARTCOMPOSITION:\r
+                       InitKeyboardProc(true);\r
+                       break;\r
+               case WM_IME_ENDCOMPOSITION:\r
+                       InitKeyboardProc(false);\r
+                       break;\r
+               }\r
        }\r
-       return CallNextHookEx(m_hHookGetMessage, nCode, wParam, lParam);\r
+       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
 }\r
 \r
 LRESULT CALLBACK CXkeymacsDll::ShellProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
-       switch (nCode) {\r
-       case HSHELL_WINDOWACTIVATED:\r
-       {\r
-               TCHAR className[256];\r
-               ::GetClassName((HWND)wParam, className, 255);\r
+       if (nCode == HSHELL_WINDOWACTIVATED) {\r
+               SetKeyboardHook(GetWindowThreadProcessId(reinterpret_cast<HWND>(wParam), NULL));\r
+               TCHAR className[CLASS_NAME_LENGTH];\r
+               GetClassName(reinterpret_cast<HWND>(wParam), className, CLASS_NAME_LENGTH);\r
                if (!_tcsicmp(className, _T("ConsoleWindowClass"))) {\r
-                       InitKeyboardProc(FALSE);\r
-                       SetKeyboardHookFlag(m_bHook);\r
-               }\r
-               break;\r
-       }\r
-       default:\r
-               break;\r
-       }\r
-       return CallNextHookEx( m_hHookShell, nCode, wParam, lParam );\r
-}\r
-\r
-// return true if the key is down\r
-BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)\r
-{\r
-       if (bPhysicalKey) {\r
-               return GetKeyState(bVk) < 0;\r
-       } else {\r
-               return GetAsyncKeyState(bVk) < 0;\r
-       }\r
-}\r
-\r
-// Do keybd_event\r
-void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)\r
-{\r
-       // Set KEYEVENTF_EXTENDEDKEY if needed\r
-       switch (bVk) {\r
-       case VK_CONTROL:\r
-               if (m_bRightControl) {          // Right Ctrl\r
-                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-               }\r
-               break;\r
-\r
-       case VK_MENU:\r
-               if (m_bRightAlt) {                      // Right Alt\r
-                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-//                     CUtils::Log("Right Alt %d", dwFlags);\r
-//             } else {\r
-//                     CUtils::Log("Left Alt %d", dwFlags);\r
-               }\r
-               break;\r
-\r
-       case VK_SHIFT:\r
-               if (m_bRightShift) {            // Right Shift\r
-                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-               }\r
-               break;\r
-\r
-       case VK_PAUSE:\r
-               if (IsDown(VK_CONTROL)) {       // Break\r
-                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-               }\r
-               break;\r
-\r
-       case VK_INSERT:\r
-       case VK_DELETE:\r
-       case VK_HOME:\r
-       case VK_END:\r
-       case VK_NEXT:\r
-       case VK_PRIOR:\r
-       case VK_UP:\r
-       case VK_DOWN:\r
-       case VK_RIGHT:\r
-       case VK_LEFT:\r
-       case VK_NUMLOCK:\r
-       case VK_PRINT:\r
-               dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
-               break;\r
-\r
-       default:\r
-               break;\r
-       }\r
-\r
-//     CUtils::Log(_T("b: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
-       keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());\r
-//     CUtils::Log(_T("a: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
-}\r
-\r
-// the key is being depressed\r
-void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal)        // bVk is virtual-key code, MSDN said\r
-{\r
-       if (bOriginal) {\r
-//             CUtils::Log(_T("i: %x, %d, %d, %d, %d, %d, %d, %d, %d"), bVk,\r
-//                     IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
-//                     IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
-\r
-               int nCommandType = NONE;\r
-               if (IsDown(VK_CONTROL, FALSE)) {\r
-                       nCommandType |= CONTROL;\r
-               }\r
-               if (IsDown(VK_MENU, FALSE)) {\r
-                       nCommandType |= META;\r
-               }\r
-               Original(nCommandType, bVk, 1);\r
-       }\r
-\r
-       DoKeybd_event(bVk, 0);\r
-}\r
-\r
-// the key is being released\r
-void CXkeymacsDll::ReleaseKey(BYTE bVk)        // bVk is virtual-key code, MSDN said\r
-{\r
-       DoKeybd_event(bVk, KEYEVENTF_KEYUP);\r
-}\r
-\r
-// bVk down, bVk up\r
-void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)\r
-{\r
-       while (n--) {\r
-               DepressKey(bVk, bOriginal);\r
-               ReleaseKey(bVk);\r
-       }\r
-}\r
-\r
-void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)\r
-{\r
-       if (CUtils::IsFindDialog()) {\r
-               static BOOL bImeCompositionOld = FALSE;\r
-               if (!bImeComposition\r
-                && bImeCompositionOld) {\r
-                       DepressKey(VK_END);\r
-                       ReleaseKey(VK_END);\r
-               }\r
-               bImeCompositionOld = bImeComposition;\r
-       }\r
-\r
-       CUtils::SetApplicationName(bImeComposition);\r
-\r
-       if (_tcsnicmp(m_Config.szSpecialApp[m_nApplicationID], CUtils::GetApplicationName(), 0xF) || !IsMatchWindowText(m_Config.szWindowText[m_nApplicationID])) {     // PROCESSENTRY32 has only 0xF bytes of Name\r
-               m_nApplicationID = -1;\r
-\r
-               for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
-                       if (!_tcsnicmp(m_Config.szSpecialApp[nApplicationID], CUtils::GetApplicationName(), 0xF) && IsMatchWindowText(m_Config.szWindowText[nApplicationID])) {\r
-\r
-                               if (m_nApplicationID < 0\r
-                                || CUtils::GetWindowTextType(m_Config.szWindowText[m_nApplicationID]) < CUtils::GetWindowTextType(m_Config.szWindowText[nApplicationID])\r
-                                || CUtils::GetWindowTextType(m_Config.szWindowText[m_nApplicationID]) == CUtils::GetWindowTextType(m_Config.szWindowText[nApplicationID])\r
-                                && _tcscmp(m_Config.szWindowText[m_nApplicationID], m_Config.szWindowText[nApplicationID]) <= 0) {\r
-                                       m_nApplicationID = nApplicationID;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               if (m_nApplicationID < 0) {\r
-                       for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
-                               if (!_tcsicmp(m_Config.szSpecialApp[nApplicationID], _T("Default"))) {\r
-                                       m_nApplicationID = nApplicationID;\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       if (m_nApplicationID < 0) {\r
-                               m_nApplicationID = 0;\r
+                       InitKeyboardProc(false);\r
+                       ShowKeyboardHookState();\r
+               }\r
+       }\r
+       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
+}\r
+\r
+void CXkeymacsDll::InitKeyboardProc(bool imeState)\r
+{\r
+       AppName::Init();\r
+       AppName::SetIMEState(imeState);\r
+\r
+       if (m_CurrentConfig == NULL ||\r
+                       _tcsnicmp(m_CurrentConfig->AppName, AppName::GetAppName(), 0xF) ||      // PROCESSENTRY32 has only 0xF bytes of Name\r
+                       !CUtils::IsMatchWindowText(m_CurrentConfig->WindowText)) {\r
+               m_CurrentConfig = NULL;\r
+               for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
+                       AppConfig* appConfig = m_Config.AppConfig + nAppID;\r
+                       if (_tcsnicmp(appConfig->AppName, AppName::GetAppName(), 0xF) || !CUtils::IsMatchWindowText(appConfig->WindowText))\r
+                               continue;\r
+                       if (m_CurrentConfig == NULL)\r
+                               m_CurrentConfig = appConfig;\r
+                       else {\r
+                               LPCTSTR curText = m_CurrentConfig->WindowText;\r
+                               LPCTSTR newText = appConfig->WindowText;\r
+                               int curType = CUtils::GetWindowTextType(curText);\r
+                               int newType = CUtils::GetWindowTextType(newText);\r
+                               if (curType < newType || curType == newType && _tcscmp(curText, newText) <= 0)\r
+                                       m_CurrentConfig = appConfig;\r
                        }\r
                }\r
+               if (m_CurrentConfig == NULL)\r
+                       m_CurrentConfig = GetAppConfig(_T("Default"), m_Config.AppConfig);\r
        }\r
-\r
-       if (m_Config.nSettingStyle[m_nApplicationID] != SETTING_DISABLE\r
-        && (_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default")) || !CUtils::IsDefaultIgnoreApplication())\r
-        && !bImeComposition\r
-        && CUtils::IsDialog()) {\r
+       if (m_CurrentConfig->SettingStyle != SETTING_DISABLE &&\r
+                       (_tcsicmp(m_CurrentConfig->AppName, _T("Default")) || !CUtils::IsDefaultIgnoreApplication()) &&\r
+                       !imeState && CUtils::IsDialog() && m_CurrentConfig->UseDialogSetting)\r
                // Use Dialog Setting\r
-               if (m_Config.bUseDialogSetting[m_nApplicationID]) {\r
-                       int nOriginalApplicationID = m_nApplicationID;\r
-                       for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {\r
-                               if (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Dialog"))) {\r
-                                       break;\r
-                               }\r
-                       }\r
-                       if (m_nApplicationID == MAX_APP) {\r
-                               m_nApplicationID = nOriginalApplicationID;\r
-                       }\r
-               }\r
-       }\r
+               m_CurrentConfig = GetAppConfig(_T("Dialog"), m_CurrentConfig);\r
 \r
-       ICONMSG msg[3] = {\r
+       IconMsg msg[3] = {\r
                {CX_ICON, OFF_ICON, ""},\r
                {MX_ICON, OFF_ICON, ""},\r
                {META_ICON, OFF_ICON, ""}\r
@@ -777,103 +479,84 @@ void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)
        CCommands::Reset();\r
 }\r
 \r
-// emulate emacs       // cf virtual-key code\r
-LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)\r
+AppConfig* CXkeymacsDll::GetAppConfig(LPCTSTR name, AppConfig* fallback)\r
 {\r
-       ASSERT(0 <= wParam && wParam <= UCHAR_MAX);\r
+       for (int i = 0; i < MAX_APP; ++i)\r
+               if (!_tcsicmp(m_Config.AppConfig[i].AppName, name))\r
+                       return m_Config.AppConfig + i;\r
+       return fallback;\r
+}\r
 \r
-       int nCommandType = NONE;\r
-       BYTE nKey = (BYTE)wParam;\r
+LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)\r
+{\r
+       BYTE nOrigKey = static_cast<BYTE>(wParam);\r
+       bool bRelease = (HIWORD(lParam) & KF_UP) != 0;\r
+       bool bExtended = (HIWORD(lParam) & KF_EXTENDED) != 0;\r
+       BYTE nKey = nOrigKey;\r
 \r
        static BOOL bLocked = FALSE;\r
        static const BYTE RECURSIVE_KEY = 0x07;\r
-       static int (*fCommand)() = NULL;\r
+       static int (*fLastCommand)() = NULL;\r
        static BYTE nOneShotModifier[MAX_KEY] = {'\0'};\r
        static BOOL bCherryOneShotModifier = FALSE;\r
 \r
-//     CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %p, %d, %d"), nCode, nKey, lParam, IsDll64, Is64ProcessHwnd(GetForegroundWindow()));\r
+//     CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nOrigKey, lParam);\r
 \r
-       if (Is64ProcessHwnd(GetForegroundWindow()) != IsDll64 || CUtils::IsXkeymacs())\r
-               return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
+       if (!m_bEnableKeyboardHook || m_CurrentConfig == NULL || CUtils::IsXkeymacs() ||\r
+                       nCode < 0 || nCode == HC_NOREMOVE)\r
+               return CallNextHookEx(NULL, nCode, wParam, lParam);\r
 \r
-       if (nCode < 0 || nCode == HC_NOREMOVE) {\r
-               goto DO_NOTHING;\r
-       }\r
+//     CUtils::Log(_T("nKey = %#x, ext = %d, rel = %d, pre = %d, %#hx, %#hx"), nOrigKey,\r
+//             (HIWORD(lParam) & KF_EXTENDED) ? 1 : 0, (HIWORD(lParam) & KF_UP) ? 1 : 0, (HIWORD(lParam) & KF_REPEAT) ? 1 : 0,\r
+//             GetKeyState(nOrigKey), GetAsyncKeyState(nOrigKey));\r
 \r
-       if (nKey == RECURSIVE_KEY) {\r
-               if (lParam & BEING_RELEASED) {\r
+       if (nOrigKey == RECURSIVE_KEY) {\r
+               if (bRelease)\r
                        goto HOOK_RECURSIVE_KEY;\r
-               } else {\r
+               else\r
                        goto RECURSIVE_COMMAND;\r
-               }\r
        }\r
 \r
-       {\r
-               static BOOL bShift = FALSE;\r
-               if (IsDepressedShiftKeyOnly(nKey)) {\r
-                       if (lParam & BEING_RELEASED) {\r
-                               if (bShift) {\r
-                                       CCommands::SetMark(FALSE);\r
-                               }\r
-                       } else {\r
-                               bShift = TRUE;\r
-                       }\r
-               } else {\r
-                       bShift = FALSE;\r
-               }\r
-       }\r
+       CancelMarkWithShift(nOrigKey, bRelease);\r
 \r
        switch (nKey) {\r
        case VK_CONTROL:\r
-               if (lParam & EXTENDED_KEY) {\r
-                       nKey = VK_RCONTROL;\r
-               } else {\r
-                       nKey = VK_LCONTROL;\r
-               }\r
+               nKey = bExtended ? VK_RCONTROL : VK_LCONTROL;\r
                break;\r
        case VK_MENU:\r
-               if (lParam & EXTENDED_KEY) {\r
-                       nKey = VK_RMENU;\r
-               } else {\r
-                       nKey = VK_LMENU;\r
-               }\r
+               nKey = bExtended ? VK_RMENU : VK_LMENU;\r
                break;\r
        case VK_SHIFT:\r
-               if (lParam & EXTENDED_KEY) {\r
-                       nKey = VK_RSHIFT;\r
-               } else {\r
-                       nKey = VK_LSHIFT;\r
-               }\r
-               break;\r
-       default:\r
+               nKey = bExtended ? VK_RSHIFT : VK_LSHIFT;\r
                break;\r
        }\r
 \r
-       if (lParam & BEING_RELEASED) {\r
-               BOOL bAlt = FALSE;\r
-               switch (nKey) {\r
+#define fCommand(nType) (CmdTable::Command(m_CurrentConfig->CmdID[(nType)][nKey]))\r
+#define FuncID (m_CurrentConfig->FuncID[nType][nKey])\r
+\r
+       if (bRelease) {\r
+               switch (nOrigKey) {\r
                case VK_MENU:\r
-               case VK_LMENU:\r
-               case VK_RMENU:\r
-                       bAlt = TRUE;\r
-                       if (m_bHookAltRelease) {\r
-                               m_bHookAltRelease = FALSE;\r
+                       if (m_nHookAltRelease) {\r
+                               if (m_nHookAltRelease & ~HOOK_ALT_LATER)\r
+                                       m_nHookAltRelease--;\r
+                               else if (m_nHookAltRelease & HOOK_ALT_LATER)\r
+                                       m_nHookAltRelease = 0;\r
                                goto HOOK;\r
                        }\r
                        // pass through\r
                case VK_LWIN:\r
                case VK_RWIN:\r
                case VK_APPS:\r
-                       for (int i = 0; i < MAX_COMMAND_TYPE; i++) {\r
-                               int (*func)() = Commands[m_Config.nCommandID[m_nApplicationID][i][nKey]].fCommand;\r
-                               if (func && !(bAlt && func == CCommands::MetaAlt))\r
+                       for (int i = 0; i < MAX_COMMAND_TYPE; ++i) {\r
+                               int (*fCommand)() = fCommand(i);\r
+                               if (fCommand && !(nOrigKey == VK_MENU && fCommand == CCommands::MetaAlt))\r
                                        goto HOOK;\r
                        }\r
                }\r
                if (nOneShotModifier[nKey]) {\r
                        ReleaseKey(nOneShotModifier[nKey]);\r
                        nOneShotModifier[nKey] = 0;\r
-\r
                        if (bCherryOneShotModifier) {\r
                                bCherryOneShotModifier = FALSE;\r
                                Kdu(nKey);\r
@@ -882,15 +565,12 @@ LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lPa
                goto DO_NOTHING;\r
        }\r
 \r
-       if (m_Config.nSettingStyle[m_nApplicationID] == SETTING_DISABLE) {\r
+       if (m_CurrentConfig->SettingStyle == SETTING_DISABLE)\r
                goto DO_NOTHING;\r
-       }\r
 \r
        // Do Nothing for Meadow, Mule for Win32, ... if those use default setting.\r
-       if (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default"))\r
-        && CUtils::IsDefaultIgnoreApplication()) {\r
+       if (!_tcsicmp(m_CurrentConfig->AppName, _T("Default")) && CUtils::IsDefaultIgnoreApplication())\r
                goto DO_NOTHING;\r
-       }\r
 \r
        switch (IsPassThrough(nKey)) {\r
        case GOTO_DO_NOTHING:\r
@@ -899,359 +579,216 @@ LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lPa
                goto HOOK;\r
        case CONTINUE:\r
                break;\r
-       default:\r
-               ASSERT(0);\r
-               break;\r
        }\r
 \r
        // set command type\r
-       {\r
-               nCommandType = NONE;\r
-               if (IsDown(VK_SHIFT, FALSE)) {\r
-                       nCommandType |= SHIFT;\r
-               }\r
-               if (IsControl()) {\r
-                       nCommandType |= CONTROL;\r
-               }\r
-               if (IsMeta()) {\r
-                       nCommandType |= META;\r
-               }\r
-               if (CCommands::bC_x()) {\r
-                       nCommandType |= CONTROLX;\r
-               }\r
-\r
-               // Ignore undefined C-x ?\r
-               if (nCommandType & CONTROLX) {\r
-                       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
-                        && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
-                               if (m_Config.bIgnoreUndefinedC_x[m_nApplicationID]) {\r
-                                       CCommands::Reset(GOTO_HOOK);\r
-                                       goto HOOK;\r
-                               }\r
-                               nCommandType &= ~CONTROLX;\r
-                       }\r
+       int nType = IsDown(VK_SHIFT) * SHIFT | IsControl() * CONTROL | IsMeta() * META | CCommands::bC_x() * CONTROLX;\r
+       // Ignore undefined C-x ?\r
+       if (nType & CONTROLX && fCommand(nType) == NULL && FuncID < 0) {\r
+               if (m_CurrentConfig->IgnoreUndefC_x) {\r
+                       CCommands::Reset(GOTO_HOOK);\r
+                       goto HOOK;\r
                }\r
-\r
-               // Ignore undefined Meta Ctrl+?\r
-               if (CCommands::bM_() && (nCommandType & CONTROL)) {\r
-                       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
-                        && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
-                               if (m_Config.bIgnoreUndefinedMetaCtrl[m_nApplicationID]) {\r
-                                       if (Original(CONTROL, nKey)) {\r
-                                               Original(CONTROL, nKey, -1);\r
-                                               goto DO_NOTHING;\r
-                                       }\r
-                                       CCommands::Reset(GOTO_HOOK);\r
-                                       goto HOOK;\r
-                               }\r
-                               nCommandType &= ~META;\r
+               nType &= ~CONTROLX;\r
+       }\r
+       // Ignore undefined Meta Ctrl+?\r
+       if (CCommands::bM_() && nType & CONTROL) {\r
+               if (fCommand(nType) == NULL && FuncID < 0) {\r
+                       if (m_CurrentConfig->IgnoreUndefMetaCtrl) {\r
+                               if (CheckOriginal(CONTROL, nKey))\r
+                                       goto DO_NOTHING;\r
+                               CCommands::Reset(GOTO_HOOK);\r
+                               goto HOOK;\r
                        }\r
+                       nType &= ~META;\r
                }\r
        }\r
 \r
-       {\r
-//             CUtils::Log(_T("o: %x, %d, %d, %d, %d, %d, %d, %d, %d"), (BYTE)wParam,\r
-//                     IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
-//                     IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
-\r
-               BYTE nKey = (BYTE)wParam; // VK_CONTROL is needed instead of VK_RCONTROL and VK_LCONTROL in this block just for Original()\r
-               int nVirtualCommandType = NONE;\r
-               if (IsDown(VK_CONTROL) && nKey != VK_CONTROL) {\r
-                       nVirtualCommandType |= CONTROL;\r
-               }\r
-               if (IsDown(VK_MENU) && nKey != VK_MENU) {\r
-                       nVirtualCommandType |= META;\r
-               }\r
-               if (Original(nVirtualCommandType, nKey)) {\r
-                       Original(nVirtualCommandType, nKey, -1);\r
-                       goto DO_NOTHING;\r
-               }\r
-       }\r
+       int nVirtualType = GetModifierState(FALSE);\r
+       if (nOrigKey == VK_CONTROL)\r
+               nVirtualType &= ~CONTROL;\r
+       if (nOrigKey == VK_MENU)\r
+               nVirtualType &= ~META;\r
+       if (CheckOriginal(nVirtualType, nOrigKey))\r
+               goto DO_NOTHING;\r
 \r
-       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableOrDisableXKeymacs) {\r
-               SetKeyboardHookFlag(!m_bHook);\r
+       int (*fCommand)() = fCommand(nType);\r
+       if (fCommand == CCommands::EnableOrDisableXKeymacs) {\r
+               ToggleKeyboardHookState();\r
                goto HOOK;\r
        }\r
-       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableXKeymacs) {\r
-               if (!m_bHook) {\r
-                       SetKeyboardHookFlag(!m_bHook);\r
-               }\r
+       if (fCommand == CCommands::EnableXKeymacs) {\r
+               if (!m_bHook)\r
+                       ToggleKeyboardHookState();\r
                goto HOOK;\r
        }\r
-       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DisableXKeymacs) {\r
-               if (m_bHook) {\r
-                       SetKeyboardHookFlag(!m_bHook);\r
-               }\r
+       if (fCommand == CCommands::DisableXKeymacs) {\r
+               if (m_bHook)\r
+                       ToggleKeyboardHookState();\r
                goto HOOK;\r
        }\r
-       if (!m_bHook) {\r
+       if (!m_bHook)\r
                goto DO_NOTHING;\r
-       }\r
 \r
-       if (CCommands::bM_x()) {\r
-               static unsigned int index = 0;\r
+       if (CCommands::bM_x() && !bRelease) {\r
+               static size_t index = 0;\r
                static TCHAR szPath[MAX_PATH] = {'\0'};\r
-\r
-               if (lParam & BEING_RELEASED) {\r
-                       // ignore\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BackwardChar) {\r
-                       if (index) {\r
+               if (fCommand == CCommands::BackwardChar) {\r
+                       if (index)\r
                                --index;\r
-                       }\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BeginningOfLine) {\r
+               } else if (fCommand == CCommands::BeginningOfLine) {\r
                        index = 0;\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteBackwardChar) {\r
+               } else if (fCommand == CCommands::DeleteBackwardChar) {\r
                        if (index) {\r
                                --index;\r
-                               memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
+                               memmove(szPath + index, szPath + index + 1, MAX_PATH - index);\r
                                SetM_xTip(szPath);\r
                        }\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteChar) {\r
+               } else if (fCommand == CCommands::DeleteChar) {\r
                        if (index < _tcslen(szPath)) {\r
-                               memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
+                               memmove(szPath + index, szPath + index + 1, MAX_PATH - index);\r
                                SetM_xTip(szPath);\r
                        }\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EndOfLine) {\r
+               } else if (fCommand == CCommands::EndOfLine) {\r
                        index = _tcslen(szPath);\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::ForwardChar) {\r
-                       if (index < _tcslen(szPath)) {\r
+               } else if (fCommand == CCommands::ForwardChar) {\r
+                       if (index < _tcslen(szPath))\r
                                ++index;\r
-                       }\r
                        goto HOOKX;\r
-               } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::KeyboardQuit) {\r
+               } else if (fCommand == CCommands::KeyboardQuit) {\r
                        CCommands::bM_x(FALSE);\r
                        index = 0;\r
                        memset(szPath, 0, sizeof(szPath));\r
                        goto HOOK;\r
-               } else if (nKey == VK_RETURN\r
-                               || Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::Newline) {\r
+               } else if (nKey == VK_RETURN || fCommand == CCommands::Newline) {\r
                        InvokeM_x(szPath);\r
-\r
                        CCommands::bM_x(FALSE);\r
                        index = 0;\r
                        memset(szPath, 0, sizeof(szPath));\r
                        goto HOOK;\r
-               } else if (index < MAX_PATH - 1) {\r
-                       const BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
-                       for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
-                               if (nKey != 0 && a2v(nAscii) == nKey && bIsShiftDown == IsShift(nAscii)) {\r
-//                                     CUtils::Log("M-x: %#X (%c), %#X (%c)", nKey, nKey, nAscii, nAscii);\r
-                                       if (index < _tcslen(szPath)) {\r
-                                               memmove(&szPath[index + 1], &szPath[index], __min(_tcslen(szPath) - index, MAX_PATH - (index + 1) - 1));\r
-                                       }\r
-                                       szPath[index++] = nAscii;\r
-//                                     CUtils::Log("M-x: %c(%#04x)", nAscii, nAscii);\r
-                                       SetM_xTip(szPath);\r
-                                       goto HOOKX;\r
-                               }\r
+               } else if (nKey && index < MAX_PATH - 1) {\r
+                       if (SHORT ascii = ConvVkey(nKey | (static_cast<BYTE>(IsDown(VK_SHIFT, FALSE)) << 8), 1)) {\r
+//                             CUtils::Log("M-x: %#X (%c), %#X (%c)", nKey, nKey, ascii, ascii);\r
+                               if (index < _tcslen(szPath))\r
+                                       memmove(szPath + index + 1, szPath + index, MAX_PATH - index - 1);\r
+                               szPath[index++] = static_cast<TCHAR>(ascii);\r
+//                             CUtils::Log("M-x: %c(%#04x)", ascii, ascii);\r
+                               SetM_xTip(szPath);\r
+                               goto HOOKX;\r
                        }\r
                }\r
        }\r
 \r
-       if (CCommands::bC_u()) {\r
-               if ((nCommandType == NONE) && ('0' <= nKey) && (nKey <= '9')) {\r
+       if (CCommands::bC_u() && nType == NONE) {\r
+               if ('0' <= nKey && nKey <= '9') {\r
                        CCommands::NumericArgument(nKey - '0');\r
                        goto HOOK0_9;\r
                }\r
-               if ((nCommandType == NONE) && (nKey == 0xBD)) {\r
+               if (nKey == VK_OEM_MINUS) {\r
                        CCommands::NumericArgumentMinus();\r
                        goto HOOK0_9;\r
                }\r
        }\r
 \r
-       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrl) {\r
-               nOneShotModifier[nKey] = VK_LCONTROL;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
-               nOneShotModifier[nKey] = VK_LCONTROL;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
-               ReleaseKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = FALSE;\r
-               Kdu(nKey);\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAlt) {\r
-               nOneShotModifier[nKey] = VK_LMENU;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
-               nOneShotModifier[nKey] = VK_LMENU;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
-               ReleaseKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = FALSE;\r
-               Kdu(nKey);\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShift) {\r
-               nOneShotModifier[nKey] = VK_SHIFT;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
-               nOneShotModifier[nKey] = VK_SHIFT;\r
-               DepressKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = TRUE;\r
-               goto HOOK;\r
-       } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
-               ReleaseKey(nOneShotModifier[nKey]);\r
-               bCherryOneShotModifier = FALSE;\r
-               Kdu(nKey);\r
-               goto HOOK;\r
-       } else {\r
-               for (int i = 0; i < MAX_KEY; ++i) {\r
-                       if (nOneShotModifier[i] == nKey) {\r
-                               break;\r
-                       }\r
-               }\r
-               if (i == MAX_KEY) {\r
-                       bCherryOneShotModifier = FALSE;\r
-               }\r
+#define OneShotModifier(type, vk, mod) \\r
+       if (fCommand(nType & ~type) == CCommands::OneShotModifier ## mod || \\r
+                       fCommand(nType) == CCommands::OneShotModifier ## mod ## Repeat) { \\r
+               nOneShotModifier[nKey] = vk; \\r
+               DepressKey(vk); \\r
+               bCherryOneShotModifier = TRUE; \\r
+               goto HOOK; \\r
+       } else if (fCommand(nType & ~CONTROL) == CCommands::OneShotModifier ## mod ## Repeat) { \\r
+               ReleaseKey(vk); \\r
+               bCherryOneShotModifier = FALSE; \\r
+               Kdu(nKey); \\r
+               goto HOOK; \\r
        }\r
 \r
-       if (0 <= m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]\r
-        && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < MAX_FUNCTION\r
-        && _tcslen(m_Config.szFunctionDefinition[m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]])) {\r
-               CallFunction(m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]);\r
+       OneShotModifier(CONTROL, VK_CONTROL, Ctrl);\r
+       OneShotModifier(META, VK_MENU, Alt);\r
+       OneShotModifier(SHIFT, VK_SHIFT, Shift);\r
+       int i;\r
+       for (i = 0; i < MAX_KEY; ++i)\r
+               if (nOneShotModifier[i] == nOrigKey)\r
+                       break;\r
+       if (i == MAX_KEY)\r
+               bCherryOneShotModifier = FALSE;\r
+\r
+       if (0 <= FuncID && FuncID < MAX_FUNCTION && m_Config.FuncDef[FuncID][0]) {\r
+               CallFunction(FuncID);\r
                CCommands::Reset(GOTO_HOOK);\r
                goto HOOK;\r
        }\r
+#undef fCommand\r
+#undef FuncID\r
 \r
-       if (!Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand) {\r
-               if (nKey == VK_CONTROL\r
-                || nKey == VK_LCONTROL\r
-                || nKey == VK_RCONTROL\r
-                || nKey == VK_MENU\r
-                || nKey == VK_LMENU\r
-                || nKey == VK_RMENU\r
-                || nKey == VK_SHIFT\r
-                || nKey == VK_LSHIFT\r
-                || nKey == VK_RSHIFT) {\r
+       if (!fCommand) {\r
+               if (nOrigKey == VK_CONTROL || nOrigKey == VK_MENU || nOrigKey == VK_SHIFT)\r
                        goto DO_NOTHING;\r
-               }\r
-\r
-               if (!(nCommandType & SHIFT)) {\r
+               if (!(nType & SHIFT)) {\r
                        if (CCommands::IsSetMark()) {\r
-                               if (CCommands::MoveCaret(nKey, nCommandType & CONTROL) != CONTINUE) {\r
+                               if (CCommands::MoveCaret(nKey, nType & CONTROL) != CONTINUE) {\r
                                        CCommands::ClearNumericArgument();\r
                                        goto HOOK;\r
                                }\r
                                CCommands::SetMark(FALSE);\r
                        }\r
                }\r
-\r
                if (1 < CCommands::GetNumericArgument()) {\r
                        Kdu(nKey, CCommands::GetNumericArgument());\r
                        CCommands::ClearNumericArgument();\r
                        goto HOOK;\r
                }\r
-\r
                goto DO_NOTHING;\r
        }\r
 \r
-       if (CCommands::IsTemporarilyDisableXKeymacs()\r
-        && Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand != CCommands::KeyboardQuit) {\r
+       if (CCommands::IsTemporarilyDisableXKeymacs()  && fCommand != CCommands::KeyboardQuit) {\r
                CCommands::SetTemporarilyDisableXKeymacs(FALSE);\r
                goto DO_NOTHING;\r
        }\r
 \r
-       if (m_Config.bAtIbeamCursorOnly[m_nApplicationID][nCommandType][nKey]) {\r
-               CURSORINFO cursorinfo = { sizeof(cursorinfo) };\r
-               if (GetCursorInfo(&cursorinfo) && cursorinfo.flags && cursorinfo.hCursor != LoadCursor(NULL, IDC_IBEAM)) {\r
-                       goto DO_NOTHING;\r
-               }\r
-       }\r
-\r
-       m_bRightControl = IsDown(VK_RCONTROL);\r
-       m_bRightAlt             = IsDown(VK_RMENU);\r
-       m_bRightShift   = IsDown(VK_RSHIFT);\r
+       m_bRightControl = IsDown(VK_RCONTROL, FALSE);\r
+       m_bRightAlt = IsDown(VK_RMENU, FALSE);\r
+       m_bRightShift = IsDown(VK_RSHIFT, FALSE);\r
 \r
-       if (!bLocked) {\r
-               bLocked = TRUE;\r
-               fCommand = Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand;\r
-RECURSIVE_COMMAND:\r
-               switch (fCommand()) {\r
-               case GOTO_DO_NOTHING:\r
-                       bLocked = FALSE;\r
-                       goto DO_NOTHING;\r
-               case GOTO_HOOK:\r
-                       bLocked = FALSE;\r
-                       goto HOOK;\r
-               case GOTO_RECURSIVE:\r
-                       goto RECURSIVE;\r
-               case GOTO_HOOKX:\r
-                       bLocked = FALSE;\r
-                       goto HOOKX;\r
-               case GOTO_HOOK0_9:\r
-                       bLocked = FALSE;\r
-                       goto HOOK0_9;\r
-               default:\r
-                       ASSERT(0);\r
-                       bLocked = FALSE;\r
-                       goto DO_NOTHING;\r
-               }\r
-       } else {\r
+       if (bLocked)\r
                goto HOOK_RECURSIVE_KEY;\r
+       bLocked = TRUE;\r
+       fLastCommand = fCommand;\r
+RECURSIVE_COMMAND:\r
+       switch (fLastCommand()) {\r
+       case GOTO_DO_NOTHING:\r
+               bLocked = FALSE;\r
+               goto DO_NOTHING;\r
+       case GOTO_HOOK:\r
+               bLocked = FALSE;\r
+               goto HOOK;\r
+       case GOTO_RECURSIVE:\r
+               goto RECURSIVE;\r
+       case GOTO_HOOKX:\r
+               bLocked = FALSE;\r
+               goto HOOKX;\r
+       case GOTO_HOOK0_9:\r
+               bLocked = FALSE;\r
+               goto HOOK0_9;\r
        }\r
 \r
 DO_NOTHING:\r
        SetModifierIcons();\r
-       {\r
-               static BOOL bDefiningMacro = FALSE;\r
-               if (m_bDefiningMacro) {\r
-                       static BOOL bDown[MAX_KEY] = {'\0'};\r
-\r
-                       if (!bDefiningMacro) {\r
-                               while (m_Macro.GetHeadPosition()) {\r
-                                       void *p = m_Macro.GetAt(m_Macro.GetHeadPosition());\r
-                                       m_Macro.RemoveHead();\r
-                                       delete p;\r
-                                       p = NULL;\r
-                               }\r
-                               memset(bDown, 0, sizeof(bDown));\r
-                       }\r
-\r
-                       if ((!(lParam & BEING_RELEASED)) || bDown[wParam]) {\r
-                               try {\r
-                                       KbdMacro *pKbdMacro = new KbdMacro;\r
-                                       if (pKbdMacro) {\r
-                                               pKbdMacro->nCode = nCode;\r
-                                               pKbdMacro->wParam = wParam;\r
-                                               pKbdMacro->lParam = lParam;\r
-                                               pKbdMacro->bOriginal = TRUE;\r
-                                               m_Macro.AddTail((CObject *)pKbdMacro);\r
-                                       }\r
-                               }\r
-                               catch (CMemoryException* e) {\r
-                                       e->Delete();\r
-//                                     CUtils::Log("KeyboardProc: 'new' threw an exception");\r
-                               }\r
-                               if (!(lParam & BEING_RELEASED)) {\r
-                                       bDown[wParam] = TRUE;\r
-                               }\r
-                       }\r
-               }\r
-               bDefiningMacro = m_bDefiningMacro;\r
-       }\r
-\r
-       return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
+       if (m_kbdMacro)\r
+               m_kbdMacro->Record(nKey, bRelease);\r
+       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
 \r
 RECURSIVE:\r
        Kdu(RECURSIVE_KEY, 1, FALSE);\r
        goto HOOKX;\r
 HOOK:\r
-       CCommands::SetLastCommand(fCommand);\r
+       CCommands::SetLastCommand(fLastCommand);\r
 HOOK0_9:\r
 HOOKX:\r
        SetModifierIcons();\r
@@ -1259,135 +796,251 @@ HOOK_RECURSIVE_KEY:
        return TRUE;\r
 }\r
 \r
-void CXkeymacsDll::SetModifierIcons()\r
+void CXkeymacsDll::CancelMarkWithShift(BYTE nKey, bool bRelease)\r
 {\r
-#define IconState(x) ((x) ? ON_ICON : OFF_ICON)\r
-       ICONMSG msg[6] = {\r
-               {MX_ICON, IconState(CCommands::bM_x()), ""},\r
-               {CX_ICON, IconState(CCommands::bC_x()), ""},\r
-               {META_ICON, IconState(CCommands::bM_()), ""},\r
-               {SHIFT_ICON, IconState(IsDown(VK_SHIFT)), ""},\r
-               {CTRL_ICON, IconState(IsControl()), ""},\r
-               {ALT_ICON, IconState(IsDown(VK_MENU)), ""}\r
-       };\r
-       _tcscpy_s(msg[0].szTip, m_M_xTip);\r
-       SendIconMessage(msg, 6);\r
+       static bool bShift;\r
+       if (nKey != VK_SHIFT)\r
+               goto exit;\r
+       BYTE bVk = 0;\r
+       do {\r
+               if (bVk == VK_SHIFT || VK_LSHIFT || VK_RSHIFT)\r
+                       continue;\r
+               if (IsDown(bVk, FALSE))\r
+                       goto exit;\r
+       } while (++bVk);\r
+       if (!bRelease) {\r
+               bShift = true;\r
+               return;\r
+       }\r
+       if (bShift)\r
+               CCommands::SetMark(FALSE);\r
+exit:\r
+       bShift = false;\r
+       return;\r
 }\r
 \r
-void CXkeymacsDll::SetApplicationName(int nApplicationID, CString szApplicationName)\r
+int CXkeymacsDll::IsPassThrough(BYTE nKey)\r
 {\r
-       ZeroMemory(m_Config.szSpecialApp[nApplicationID], CLASS_NAME_LENGTH);\r
-       _tcsncpy_s(m_Config.szSpecialApp[nApplicationID], szApplicationName, _TRUNCATE);\r
+       BYTE bVk = 0;\r
+       const BYTE *pnID = m_CurrentConfig->CmdID[NONE]; \r
+       do {\r
+               if (IsDown(bVk) && CmdTable::Command(pnID[bVk]) == CCommands::PassThrough) {\r
+                       if (bVk == nKey)\r
+                               return GOTO_HOOK;\r
+                       return GOTO_DO_NOTHING;\r
+               }\r
+       } while (++bVk);\r
+       return CONTINUE;\r
 }\r
 \r
-void CXkeymacsDll::SetWindowText(int nApplicationID, CString szWindowText)\r
+void CXkeymacsDll::InvokeM_x(LPCTSTR szPath)\r
 {\r
-       ZeroMemory(m_Config.szWindowText[nApplicationID], WINDOW_TEXT_LENGTH);\r
-       _tcsncpy_s(m_Config.szWindowText[nApplicationID], szWindowText, _TRUNCATE);\r
+//     CUtils::Log("M-x: szPath=_%s_", szPath);\r
+       int (*fCommand)() = NULL;\r
+       for (int i = 0; i < MAX_COMMAND; ++i)\r
+               if (_tcsicmp(szPath, CmdTable::Name(i)) == 0) {\r
+                       fCommand = CmdTable::Command(i);\r
+                       break;\r
+               }\r
+       if (fCommand) {\r
+//             CUtils::Log("M-x: Command: _%s_", Commands[i].szCommandName);\r
+               fCommand();\r
+       } else {\r
+//             CUtils::Log("M-x: Path: _%s_", szPath);\r
+               ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);\r
+       }\r
 }\r
 \r
-void CXkeymacsDll::SetCommandID(int nApplicationID, int nCommandType, int nKey, int nCommandID)\r
+void CXkeymacsDll::SetModifierIcons()\r
 {\r
-       m_Config.nCommandID[nApplicationID][nCommandType][nKey] = nCommandID;\r
+       IconMsg msg[6] = {\r
+               {MX_ICON, CCommands::bM_x(), ""},\r
+               {CX_ICON, CCommands::bC_x(), ""},\r
+               {META_ICON, CCommands::bM_(), ""},\r
+               {SHIFT_ICON, IsDown(VK_SHIFT, FALSE), ""},\r
+               {CTRL_ICON, IsControl(), ""},\r
+               {ALT_ICON, IsDown(VK_MENU, FALSE), ""}\r
+       };\r
+       _tcscpy_s(msg[0].szTip, m_M_xTip);\r
+       SendIconMessage(msg, 6);\r
 }\r
 \r
-void CXkeymacsDll::SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly)\r
+void CXkeymacsDll::SetM_xTip(LPCTSTR szPath)\r
 {\r
-       m_Config.bAtIbeamCursorOnly[nApplicationID][nCommandType][nKey] = bAtIbeamCursorOnly;\r
+       _tcscpy_s(m_M_xTip, "M-x LED");\r
+       if (szPath && _tcslen(szPath) < 128 - 5)\r
+               _stprintf_s(m_M_xTip, "M-x %s", szPath);\r
 }\r
 \r
-void CXkeymacsDll::SetKillRingMax(int nApplicationID, int nKillRingMax)\r
+BOOL CXkeymacsDll::SendIconMessage(IconMsg *pMsg, DWORD num)\r
 {\r
-       m_Config.nKillRingMax[nApplicationID] = nKillRingMax;\r
+       DWORD ack, read;\r
+       return CallNamedPipe(ICON_PIPE, pMsg, sizeof(IconMsg) * num, &ack, sizeof(DWORD), &read, NMPWAIT_NOWAIT) && read == sizeof(DWORD);\r
 }\r
 \r
-void CXkeymacsDll::SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting)\r
+void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)\r
 {\r
-       m_Config.bUseDialogSetting[nApplicationID] = bUseDialogSetting;\r
+       while (n--) {\r
+               DepressKey(bVk, bOriginal);\r
+               ReleaseKey(bVk);\r
+       }\r
 }\r
 \r
-// Clear data of nApplicationID\r
-void CXkeymacsDll::Clear(int nApplicationID)\r
+void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal)        // bVk is virtual-key code, MSDN said\r
 {\r
-       if (0 <= nApplicationID && nApplicationID < MAX_APP) {\r
-               ZeroMemory(m_Config.szSpecialApp[nApplicationID], sizeof(m_Config.szSpecialApp[nApplicationID]));\r
-               ZeroMemory(m_Config.nCommandID[nApplicationID], sizeof(m_Config.nCommandID[nApplicationID]));\r
-               ZeroMemory(m_Config.bAtIbeamCursorOnly[nApplicationID], sizeof(m_Config.bAtIbeamCursorOnly[nApplicationID]));\r
-               m_Config.nKillRingMax[nApplicationID] = 0;\r
-               m_Config.bUseDialogSetting[nApplicationID] = FALSE;\r
-               m_Config.nSettingStyle[nApplicationID] = 0;\r
-       } else {\r
-               ASSERT(0);\r
+       if (bOriginal) {\r
+//             CUtils::Log(_T("i: %x, %d, %d, %d, %d, %d, %d, %d, %d"), bVk,\r
+//                     IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
+//                     IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
+               SetOriginal(GetModifierState(), bVk);\r
        }\r
+       DoKeybd_event(bVk, 0);\r
 }\r
 \r
-BOOL CXkeymacsDll::IsValidKey(BYTE bVk)\r
+void CXkeymacsDll::ReleaseKey(BYTE bVk)        // bVk is virtual-key code, MSDN said\r
 {\r
-       if (bVk == 0xf0) {      // 0xf0: Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.\r
-               return FALSE;\r
-       }\r
+       DoKeybd_event(bVk, KEYEVENTF_KEYUP);\r
+}\r
 \r
+void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)\r
+{\r
        switch (bVk) {\r
        case VK_CONTROL:\r
+               if (m_bRightControl)\r
+                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
+               break;\r
+\r
        case VK_MENU:\r
+               if (m_bRightAlt)\r
+                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
+               break;\r
+\r
        case VK_SHIFT:\r
-               return FALSE;\r
-       default:\r
+               if (m_bRightShift)\r
+                       bVk = VK_RSHIFT;\r
+               break;\r
+       case VK_PAUSE:\r
+               if (IsDown(VK_CONTROL, FALSE)) // Break\r
+                       dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
+               break;\r
+       case VK_INSERT:\r
+       case VK_DELETE:\r
+       case VK_HOME:\r
+       case VK_END:\r
+       case VK_NEXT:\r
+       case VK_PRIOR:\r
+       case VK_UP:\r
+       case VK_DOWN:\r
+       case VK_RIGHT:\r
+       case VK_LEFT:\r
+       case VK_NUMLOCK:\r
+       case VK_PRINT:\r
+               dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
                break;\r
        }\r
+//     CUtils::Log(_T("b: %x, %x, %x, %#hx, %#hx"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
+       keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());\r
+//     CUtils::Log(_T("a: %x, %x, %x, %#hx, %#hx"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
+}\r
 \r
-       return TRUE;\r
+void CXkeymacsDll::SetOriginal(UINT nType, BYTE bVk)\r
+{\r
+       m_nOriginal[nType & ~SHIFT][bVk]++;\r
 }\r
 \r
-BOOL CXkeymacsDll::IsDepressedModifier(int (__cdecl *Modifier)(void), BOOL bPhysicalKey)\r
+int CXkeymacsDll::CheckOriginal(UINT nType, BYTE bVk)\r
 {\r
-       BYTE bVk = 0;\r
-       do {\r
-               if (IsValidKey(bVk)\r
-                && IsDown(bVk, bPhysicalKey)\r
-                && Commands[m_Config.nCommandID[m_nApplicationID][NONE][bVk]].fCommand == Modifier) {\r
-                       return TRUE;\r
-               }\r
-       } while (++bVk);\r
-       return FALSE;\r
+       nType &= ~SHIFT;\r
+       if (m_nOriginal[nType][bVk])\r
+               return m_nOriginal[nType][bVk]--;\r
+       return 0;\r
 }\r
 \r
-BOOL CXkeymacsDll::IsDepressedShiftKeyOnly(BYTE nKey)\r
+UINT CXkeymacsDll::GetModifierState(BOOL bPhysicalKey)\r
 {\r
-       if (nKey != VK_SHIFT\r
-        && nKey != VK_LSHIFT\r
-        && nKey != VK_RSHIFT) {\r
-               return FALSE;\r
+       UINT result = 0;\r
+       if (IsDown(VK_SHIFT, bPhysicalKey))\r
+               result |= SHIFT;\r
+       if (IsDown(VK_CONTROL, bPhysicalKey))\r
+               result |= CONTROL;\r
+       if (IsDown(VK_MENU, bPhysicalKey))\r
+               result |= META;\r
+       return result;\r
+}\r
+\r
+void CXkeymacsDll::SetModifierState(UINT after, UINT before)\r
+{\r
+       if (after & SHIFT && !(before & SHIFT))\r
+               DepressKey(VK_SHIFT);\r
+       else if (!(after & SHIFT) && before & SHIFT)\r
+               ReleaseKey(VK_SHIFT);\r
+\r
+       if (after & CONTROL && !(before & CONTROL))\r
+               DepressKey(VK_CONTROL);\r
+       else if (!(after & CONTROL) && before & CONTROL) {\r
+               ReleaseKey(VK_CONTROL);\r
+               UpdateKeyboardState(VK_CONTROL, 0);\r
        }\r
 \r
-       BYTE bVk = 0;\r
-       do {\r
-               if (bVk == VK_SHIFT\r
-                || bVk == VK_LSHIFT\r
-                || bVk == VK_RSHIFT) {\r
-                       continue;\r
-               }\r
+       BOOL bHookApp =\r
+               CUtils::IsVisualCpp() ||  CUtils::IsVisualStudio() ||\r
+               CUtils::IsInternetExplorer() || CUtils::IsFirefox() || CUtils::IsChrome();\r
+       if (after & META && !(before & META)) {\r
+               if (bHookApp)\r
+                       m_nHookAltRelease |= HOOK_ALT_LATER;\r
+               DepressKey(VK_MENU);\r
+       } else if (!(after & META) && before & META) {\r
+               if (bHookApp)\r
+                       ++m_nHookAltRelease;\r
+               ReleaseKey(VK_MENU);\r
+       }\r
+}\r
 \r
-               if (IsDown(bVk)) {\r
-                       return FALSE;\r
-               }\r
-       } while (++bVk);\r
-       return TRUE;\r
+BOOL CXkeymacsDll::UpdateKeyboardState(BYTE bVk, BYTE bState)\r
+{\r
+       BYTE ks[256] = {'\0'};\r
+       if (!GetKeyboardState(ks))\r
+               return FALSE;\r
+       ks[bVk] = bState;\r
+       return SetKeyboardState(ks);\r
 }\r
 \r
 BOOL CXkeymacsDll::IsControl()\r
 {\r
-       return CCommands::bC_() || IsDepressedModifier(CCommands::C_, FALSE);\r
+       return CCommands::bC_() || IsDepressedModifier(CCommands::C_);\r
 }\r
 \r
 BOOL CXkeymacsDll::IsMeta()\r
 {\r
-       return CCommands::bM_() || IsDepressedModifier(CCommands::MetaAlt, FALSE);\r
+       return CCommands::bM_() || IsDepressedModifier(CCommands::MetaAlt);\r
+}\r
+\r
+BOOL CXkeymacsDll::IsDepressedModifier(int (__cdecl *Modifier)(void), BOOL bPhysicalKey)\r
+{\r
+       BYTE bVk = 0;\r
+       const BYTE *pnID = m_CurrentConfig->CmdID[NONE];\r
+       do {\r
+               switch (bVk) {\r
+               case VK_SHIFT:\r
+               case VK_CONTROL:\r
+               case VK_MENU:\r
+               case 0xf0: // Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.\r
+                       continue;\r
+               }\r
+               if (IsDown(bVk, bPhysicalKey) && CmdTable::Command(pnID[bVk]) == Modifier)\r
+                       return TRUE;\r
+       } while (++bVk);\r
+       return FALSE;\r
+}\r
+\r
+BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)\r
+{\r
+       return bPhysicalKey ? GetAsyncKeyState(bVk) < 0 : GetKeyState(bVk) < 0;\r
 }\r
 \r
 void CXkeymacsDll::AddKillRing(BOOL bNewData)\r
 {\r
-       if (m_Config.nKillRingMax[m_nApplicationID] == 0) {\r
+       if (m_CurrentConfig->KillRingMax == 0) {\r
                return;\r
        }\r
 \r
@@ -1404,7 +1057,8 @@ void CXkeymacsDll::AddKillRing(BOOL bNewData)
                        if (m_oKillRing.IsEmpty()) {\r
                                m_oKillRing.AddHead(pSnap);\r
                        } else {\r
-                               for (CClipboardSnap *pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {\r
+                               CClipboardSnap *pParent;\r
+                               for (pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {\r
                                        ;\r
                                }\r
                                pParent->SetNext(pSnap);\r
@@ -1417,7 +1071,7 @@ void CXkeymacsDll::AddKillRing(BOOL bNewData)
 \r
        m_nKillRing = 0;\r
 \r
-       if (m_Config.nKillRingMax[m_nApplicationID] < m_oKillRing.GetCount()) {\r
+       if (m_CurrentConfig->KillRingMax < m_oKillRing.GetCount()) {\r
                CClipboardSnap *pSnap = m_oKillRing.GetTail();\r
                delete pSnap;\r
                pSnap = NULL;\r
@@ -1429,7 +1083,7 @@ void CXkeymacsDll::AddKillRing(BOOL bNewData)
 // Return FALSE if there is no more data\r
 CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)\r
 {\r
-       if (m_Config.nKillRingMax[m_nApplicationID] == 0) {\r
+       if (m_CurrentConfig->KillRingMax == 0) {\r
                return NULL;\r
        }\r
 \r
@@ -1463,652 +1117,185 @@ CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)
        return pSnap->GetNext();\r
 }\r
 \r
-void CXkeymacsDll::Original(int nCommandType, BYTE bVk, int nOriginal)\r
-{\r
-       nCommandType &= ~SHIFT;\r
-\r
-       switch (bVk) {\r
-       case VK_CONTROL:\r
-               bVk = VK_LCONTROL;\r
-               break;\r
-       case VK_MENU:\r
-               bVk = VK_LMENU;\r
-               break;\r
-       case VK_SHIFT:\r
-               bVk = VK_LSHIFT;\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       m_nOriginal[nCommandType][bVk] += nOriginal;\r
-}\r
-\r
-int CXkeymacsDll::Original(int nCommandType, BYTE bVk)\r
-{\r
-       nCommandType &= ~SHIFT;\r
-\r
-       switch (bVk) {\r
-       case VK_CONTROL:\r
-               bVk = VK_LCONTROL;\r
-               break;\r
-       case VK_MENU:\r
-               bVk = VK_LMENU;\r
-               break;\r
-       case VK_SHIFT:\r
-               bVk = VK_LSHIFT;\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       return m_nOriginal[nCommandType][bVk];\r
-}\r
-\r
 void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)\r
 {\r
        m_nKillRing += nKillRing;\r
 }\r
 \r
-// nobody use\r
-int CXkeymacsDll::GetMickey(int nDifferential, int nThreshold1, int nThreshold2, int nAcceleration, int nSpeed)\r
+bool CXkeymacsDll::GetEnableCUA()\r
 {\r
-       nDifferential = nDifferential * 10 / nSpeed;\r
-\r
-       switch (nAcceleration) {\r
-       case 2:\r
-               if (nThreshold2 < fabs((double)(nDifferential / 4))) {\r
-                       nDifferential /= 4;\r
-                       break;\r
-               }\r
-               // Do NOT write break; here.\r
-       case 1:\r
-               if (nThreshold1 < fabs((double)(nDifferential / 2))) {\r
-                       nDifferential /= 2;\r
-               }\r
-               break;\r
-       case 0:\r
-               break;\r
-       default:\r
-               ASSERT(0);\r
-               break;\r
-       }\r
-\r
-       return nDifferential;\r
+       return m_CurrentConfig->EnableCUA;\r
 }\r
 \r
-void CXkeymacsDll::SetSettingStyle(int nApplicationID, int nSettingStyle)\r
+bool CXkeymacsDll::Get326Compatible()\r
 {\r
-       m_Config.nSettingStyle[nApplicationID] = nSettingStyle;\r
+       return m_CurrentConfig->Is326Compatible;\r
 }\r
 \r
-void CXkeymacsDll::SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl)\r
+bool CXkeymacsDll::Is106Keyboard()\r
 {\r
-       m_Config.bIgnoreUndefinedMetaCtrl[nApplicationID] = bIgnoreUndefinedMetaCtrl;\r
+       return m_Config.Is106Keyboard;\r
 }\r
 \r
-void CXkeymacsDll::SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x)\r
+void CXkeymacsDll::SetKbMacro(KbdMacro* kbdMacro)\r
 {\r
-       m_Config.bIgnoreUndefinedC_x[nApplicationID] = bIgnoreUndefinedC_x;\r
-}\r
-\r
-void CXkeymacsDll::SetEnableCUA(int nApplicationID, BOOL bEnableCUA)\r
-{\r
-       m_Config.bEnableCUA[nApplicationID] = bEnableCUA;\r
-}\r
-\r
-BOOL CXkeymacsDll::GetEnableCUA()\r
-{\r
-       return m_Config.bEnableCUA[m_nApplicationID];\r
-}\r
-\r
-void CXkeymacsDll::DefiningMacro(BOOL bDefiningMacro)\r
-{\r
-       m_bDefiningMacro = bDefiningMacro;\r
-\r
-       if (bDefiningMacro) {   // start-kbd-macro\r
-               if (CCommands::bC_u()) {\r
-                       ReleaseKey(VK_SHIFT);\r
-                       CallMacro();\r
-               }\r
-       } else {                                // end-kbd-macro\r
-               while (!m_Macro.IsEmpty()) {\r
-                       KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetTail();\r
-                       if (pKbdMacro->lParam & BEING_RELEASED) {\r
-                               break;\r
-                       } else {\r
-                               m_Macro.RemoveTail();\r
-                               delete pKbdMacro;\r
-                               pKbdMacro = NULL;\r
-                       }\r
-               }\r
-\r
-//             CUtils::Log(_T("Macro MemMap: start"));\r
-               if (!m_Macro.IsEmpty()) {\r
-                       static HANDLE hMacro = NULL;\r
-                       if (!hMacro) {\r
-                               hMacro = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x3000, _T("macro"));\r
-                       }\r
-                       if (hMacro) {\r
-//                             CUtils::Log(_T("Macro MemMap: 1"));\r
-                               PVOID pView = MapViewOfFile(hMacro, FILE_MAP_ALL_ACCESS, 0, 0, 0);\r
-//                             CUtils::Log(_T("Macro MemMap: 2"));\r
-                               if (pView) {\r
-//                                     CUtils::Log(_T("Macro MemMap: 2.5"));\r
-                                       for (int i = 0; i < m_Macro.GetCount(); ++i) {\r
-//                                             CUtils::Log(_T("Macro MemMap: 3-1 %d"), i);\r
-                                               KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetAt(m_Macro.FindIndex(i));\r
-//                                             CUtils::Log(_T("Macro MemMap: 3-2 %d"), i);\r
-                                               memcpy((LPTSTR) pView + i * sizeof(KbdMacro), pKbdMacro, sizeof(KbdMacro));\r
-//                                             CUtils::Log(_T("Macro MemMap: 3-3 %d"), i);\r
-                                       }\r
-//                                     CUtils::Log(_T("Macro MemMap: 4"));\r
-                                       UnmapViewOfFile(pView);\r
-//                                     CUtils::Log(_T("Macro MemMap: 5"));\r
-                               } else {\r
-//                                     CUtils::Log(_T("Macro MemMpa: error: %d"), GetLastError());\r
-                               }\r
-                       } else {\r
-//                             CUtils::Log(_T("Macro MemMap: 6"));\r
-                               ASSERT(0);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-BOOL CXkeymacsDll::DefiningMacro()\r
-{\r
-       return m_bDefiningMacro;\r
-}\r
-\r
-/**/ \r
-void CXkeymacsDll::CallMacro()\r
-{\r
-       BOOL bIsCtrlDown = IsDown(VK_CONTROL);\r
-       if (bIsCtrlDown) {\r
-               ReleaseKey(VK_CONTROL);\r
-       }\r
-       BOOL bIsAltDown = IsDown(VK_MENU);\r
-       if (bIsAltDown) {\r
-               ReleaseKey(VK_MENU);\r
-       }\r
-       BOOL bIsShiftDown = IsDown(VK_SHIFT);\r
-       if (bIsShiftDown) {\r
-               ReleaseKey(VK_SHIFT);\r
-       }\r
-\r
-       for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
-               KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetNext(pos);\r
-               if (pKbdMacro->lParam & BEING_RELEASED) {\r
-                       ReleaseKey((BYTE)pKbdMacro->wParam);\r
-               } else {\r
-                       DepressKey((BYTE)pKbdMacro->wParam, pKbdMacro->bOriginal);\r
-               }\r
-       }\r
-\r
-       if (bIsCtrlDown) {\r
-               DepressKey(VK_CONTROL);\r
-       }\r
-       if (bIsAltDown) {\r
-               DepressKey(VK_MENU);\r
-       }\r
-       if (bIsShiftDown) {\r
-               DepressKey(VK_SHIFT);\r
-       }\r
-}\r
-\r
-/*\r
-void CXkeymacsDll::CallMacro() // for debug\r
-{\r
-       CString sz;\r
-       for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
-               KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetNext(pos);\r
-               if (pKbdMacro->lParam & BEING_RELEASED) {\r
-                       CString t;\r
-                       t.Format(_T("0x%xu "), pKbdMacro->wParam);\r
-                       sz += t;\r
-               } else {\r
-                       CString t;\r
-                       t.Format(_T("0x%xd "), pKbdMacro->wParam);\r
-                       sz += t;\r
-               }\r
-       }\r
-//     CUtils::Log(sz);\r
-}\r
-*/\r
-\r
-void CXkeymacsDll::Set106Keyboard(BOOL b106Keyboard)\r
-{\r
-       m_Config.b106Keyboard = b106Keyboard;\r
-}\r
-\r
-BOOL CXkeymacsDll::Is106Keyboard()\r
-{\r
-       return m_Config.b106Keyboard;\r
-}\r
-\r
-int CXkeymacsDll::IsPassThrough(BYTE nKey)\r
-{\r
-       BYTE bVk = 0;\r
-       do {\r
-               if (IsDown(bVk)\r
-                && (Commands[m_Config.nCommandID[m_nApplicationID][NONE][bVk]].fCommand == CCommands::PassThrough)) {\r
-                       if (bVk == nKey) {\r
-                               return GOTO_HOOK;\r
-                       }\r
-\r
-                       return GOTO_DO_NOTHING;\r
-               }\r
-       } while (++bVk);\r
-       return CONTINUE;\r
-}\r
-\r
-void CXkeymacsDll::SetKeyboardHookFlag()\r
-{\r
-       SetKeyboardHookFlag(m_bHook);\r
-}\r
-\r
-void CXkeymacsDll::SetFunctionKey(int nFunctionID, int nApplicationID, int nCommandType, int nKey)\r
-{\r
-       if (nApplicationID      < 0 || MAX_APP                  <= nApplicationID\r
-        || nCommandType        < 0 || MAX_COMMAND_TYPE <= nCommandType\r
-        || nKey                        < 0 || MAX_KEY                  <= nKey) {\r
-               return;\r
-       }\r
-\r
-       m_Config.nFunctionID[nApplicationID][nCommandType][nKey] = nFunctionID;\r
-}\r
-\r
-void CXkeymacsDll::ClearFunctionDefinition()\r
-{\r
-       memset(m_Config.nFunctionID, -1, sizeof(m_Config.nFunctionID));\r
-       memset(m_Config.szFunctionDefinition, 0, sizeof(m_Config.szFunctionDefinition));\r
-}\r
-\r
-void CXkeymacsDll::SetFunctionDefinition(int nFunctionID, CString szDefinition)\r
-{\r
-       if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID) {\r
-               return;\r
-       }\r
-\r
-       memset(m_Config.szFunctionDefinition[nFunctionID], 0, sizeof(m_Config.szFunctionDefinition[nFunctionID]));\r
-       _stprintf_s(m_Config.szFunctionDefinition[nFunctionID], _T("%s"), szDefinition);\r
-\r
-       return;\r
-\r
+       m_kbdMacro = kbdMacro;\r
 }\r
 \r
 // call an original command which is defined in dot.xkeymacs\r
-void CXkeymacsDll::CallFunction(int nFunctionID)\r
+void CXkeymacsDll::CallFunction(int FuncID)\r
 {\r
-       CArray<KeyBind, KeyBind> keybinds;\r
-\r
-       if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID || !_tcslen(m_Config.szFunctionDefinition[nFunctionID])) {\r
+       if (FuncID < 0 || FuncID >= MAX_FUNCTION)\r
                return;\r
-       }\r
-\r
-       BOOL bIsCtrlDown = CXkeymacsDll::IsDown(VK_CONTROL);\r
-       BOOL bIsAltDown = CXkeymacsDll::IsDown(VK_MENU);\r
-       BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
-\r
-       if (m_Config.szFunctionDefinition[nFunctionID][0] == _T('"') && m_Config.szFunctionDefinition[nFunctionID][_tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1] == _T('"')) {\r
-               for (unsigned int i = 1; i < _tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1; ++i) {    // skip '"'\r
-                       keybinds.Add(ParseKey(nFunctionID, i));\r
-               }\r
-       } else if (m_Config.szFunctionDefinition[nFunctionID][0] == _T('[') && m_Config.szFunctionDefinition[nFunctionID][_tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1] == _T(']')) {\r
-               for (unsigned int i = 1; i < _tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1; ++i) {    // skip '[' and ']'\r
-                       if (m_Config.szFunctionDefinition[nFunctionID][i] == _T('?')) { // [?f ?o ?o]\r
-                               ++i;\r
-                               keybinds.Add(ParseKey(nFunctionID, i));\r
-                       } else {                                                                                                // [ControlCharacter]\r
-                               for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
-                                       if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
-                                               KeyBind keybind = {NONE, ControlCharacters[nKeyID].bVk};\r
-                                               keybinds.Add(keybind);\r
-                                               i += _tcslen(ControlCharacters[nKeyID].name);\r
-                                               break;\r
-                                       }\r
+       LPCTSTR def = m_Config.FuncDef[FuncID];\r
+       if (!def[0])\r
+               return;\r
+       std::vector<KeyBind> keybinds;\r
+       LPCTSTR last = def + _tcslen(def) - 1;\r
+       if (*def == _T('"') && *last == _T('"')) {\r
+               ++def; // skip '"'\r
+               while (def < last)\r
+                       keybinds.push_back(ParseKey(def));\r
+       } else if (*def == _T('[') && *last == _T(']')) {\r
+               while (++def < last) { // skip '[', ']', and ' '\r
+                       if (*def == _T('?')) { // [?f ?o ?o]\r
+                               keybinds.push_back(ParseKey(++def));\r
+                               continue;\r
+                       }\r
+                       // [VK]\r
+                       for (int i = 0; i < MAX_KEYNAME; ++i) {\r
+                               size_t keylen = _tcslen(KeyNames[i].name);\r
+                               if (!_tcsncmp(def, KeyNames[i].name, keylen)) {\r
+                                       KeyBind keybind = {NONE, KeyNames[i].bVk};\r
+                                       keybinds.push_back(keybind);\r
+                                       def += keylen;\r
+                                       break;\r
                                }\r
                        }\r
                }\r
-       } else {\r
+       } else\r
                return;\r
-       }\r
 \r
        BOOL bM_x = FALSE;\r
        TCHAR szPath[MAX_PATH] = {'\0'};\r
        unsigned int index = 0;\r
        BOOL bInitialized = FALSE;\r
-\r
-       for (int i = 0; i < keybinds.GetSize(); ++i) {\r
-               const int nCommandType = keybinds.GetAt(i).nCommandType;\r
-               const BYTE bVk = keybinds.GetAt(i).bVk;\r
-\r
-               if (nCommandType < MAX_COMMAND_TYPE && Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand) {\r
-                       if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand == CCommands::ExecuteExtendedCommand) {\r
+       UINT before = GetModifierState(FALSE);\r
+\r
+       for (std::vector<KeyBind>::const_iterator p = keybinds.begin(); p != keybinds.end(); ++p) {\r
+               int nType = p->nType;\r
+               BYTE bVk = p->bVk;\r
+               int (*fCommand)() = nType < MAX_COMMAND_TYPE ? CmdTable::Command(m_CurrentConfig->CmdID[nType][bVk]) : NULL;\r
+               if (fCommand) {\r
+                       if (fCommand == CCommands::ExecuteExtendedCommand)\r
                                bM_x = TRUE;\r
-                       } else if (!bInitialized) {\r
-                               if (bIsCtrlDown) {\r
-                                       CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
-                                       ReleaseKey(VK_CONTROL);\r
-                               }\r
-\r
-                               if (bIsAltDown) {\r
-                                       ReleaseKey(VK_MENU);\r
-                               }\r
-\r
-                               if (bIsShiftDown) {\r
-                                       ReleaseKey(VK_SHIFT);\r
-                               }\r
-\r
+                       else if (!bInitialized) {\r
+                               SetModifierState(0, before);\r
                                bInitialized = TRUE;\r
                        }\r
-//                     CUtils::Log("CallFunction: Command Name: %s", Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].szCommandName);\r
-                       while (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand() == GOTO_RECURSIVE) {\r
+//                     CUtils::Log("CallFunction: Command Name: %s", Commands[m_CurrentConfig->CmdID[nType][bVk]].szCommandName);\r
+                       while (fCommand() == GOTO_RECURSIVE)\r
                                ;\r
-                       }\r
-               } else if (bM_x) {\r
-                       if (bVk == VK_RETURN) {\r
-                               InvokeM_x(szPath);\r
-                       } else {\r
-                               for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
-                                       if (bVk != 0 && a2v(nAscii) == bVk && ((nCommandType & SHIFT) != 0) == IsShift(nAscii)) {\r
-//                                             CUtils::Log("M-x: %#X (%c), %#X (%c)", bVk, bVk, nAscii, nAscii);\r
-                                               szPath[index++] = nAscii;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-               } else {\r
-                       if (!bInitialized) {\r
-                               if (bIsCtrlDown) {\r
-                                       CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
-                                       ReleaseKey(VK_CONTROL);\r
-                               }\r
-\r
-                               if (bIsAltDown) {\r
-                                       ReleaseKey(VK_MENU);\r
-                               }\r
-\r
-                               if (bIsShiftDown) {\r
-                                       ReleaseKey(VK_SHIFT);\r
-                               }\r
-\r
-                               bInitialized = TRUE;\r
-                       }\r
-                       if (nCommandType & WIN_WIN) {\r
-                               DepressKey(VK_LWIN);\r
-                       }\r
-                       if (nCommandType & WIN_CTRL) {\r
-                               DepressKey(VK_CONTROL);\r
-                       }\r
-                       if (nCommandType & WIN_ALT) {\r
-                               DepressKey(VK_MENU);\r
-                       }\r
-                       if (nCommandType & SHIFT) {\r
-                               DepressKey(VK_SHIFT);\r
-                       }\r
-\r
-                       Kdu(bVk);\r
-\r
-                       if (nCommandType & SHIFT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & SHIFT))) {\r
-                               ReleaseKey(VK_SHIFT);\r
-                       }\r
-                       if (nCommandType & WIN_ALT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_ALT))) {\r
-                               ReleaseKey(VK_MENU);\r
-                       }\r
-                       if (nCommandType & WIN_CTRL && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_CTRL))) {\r
-                               ReleaseKey(VK_CONTROL);\r
-                       }\r
-                       if (nCommandType & WIN_WIN && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_WIN))) {\r
-                               ReleaseKey(VK_LWIN);\r
-                       }\r
+                       continue;\r
                }\r
-       }\r
-\r
-       keybinds.RemoveAll();\r
-\r
-       if (bInitialized) {\r
-               // If these lines are invoked at M-x, a window transition does not work well.\r
-\r
-               if (bIsShiftDown) {\r
-                       DepressKey(VK_SHIFT);\r
+               if (bM_x) {\r
+                       if (bVk == VK_RETURN)\r
+                               InvokeM_x(szPath);\r
+                       else if (bVk != 0)\r
+                               szPath[index++] = static_cast<TCHAR>(ConvVkey((bVk | (nType << 8)) & 0x7ff /* drop CONTROLX */, 1));\r
+                       continue;\r
                }\r
-\r
-               if (bIsAltDown) {\r
-                       DepressKey(VK_MENU);\r
+               if (!bInitialized) {\r
+                       SetModifierState(0, before);\r
+                       bInitialized = TRUE;\r
                }\r
-\r
-               if (bIsCtrlDown) {\r
+               if (nType & WIN_WIN)\r
+                       DepressKey(VK_LWIN);\r
+               if (nType & WIN_CTRL)\r
                        DepressKey(VK_CONTROL);\r
-                       CUtils::UpdateKeyboardState(VK_CONTROL, 1);\r
-               }\r
+               if (nType & WIN_ALT)\r
+                       DepressKey(VK_MENU);\r
+               if (nType & SHIFT)\r
+                       DepressKey(VK_SHIFT);\r
+               Kdu(bVk);\r
+               int nNextType = (p + 1) != keybinds.end() ? (p + 1)->nType : 0;\r
+               if (nType & SHIFT && !(nNextType & SHIFT))\r
+                       ReleaseKey(VK_SHIFT);\r
+               if (nType & WIN_ALT && !(nNextType & WIN_ALT))\r
+                       ReleaseKey(VK_MENU);\r
+               if (nType & WIN_CTRL && !(nNextType & WIN_CTRL))\r
+                       ReleaseKey(VK_CONTROL);\r
+               if (nType & WIN_WIN && !(nNextType & WIN_WIN))\r
+                       ReleaseKey(VK_LWIN);\r
        }\r
+\r
+       if (bInitialized)\r
+               // If this lines is invoked on M-x, a window transition does not work well.\r
+               SetModifierState(before, 0);\r
        return;\r
 }\r
 \r
-KeyBind CXkeymacsDll::ParseKey(const int nFunctionID, unsigned int &i)\r
+KeyBind CXkeymacsDll::ParseKey(LPCTSTR& def)\r
 {\r
        KeyBind keybind = {NONE};\r
-\r
-       if (m_Config.szFunctionDefinition[nFunctionID][i] == _T('\\')) {\r
-               ++i;\r
-               BOOL bFound = FALSE;\r
-               do {\r
-                       bFound = FALSE;\r
-                       for (int ModifierID = 0; ModifierID < sizeof(Modifiers) / sizeof(Modifiers[0]); ++ModifierID) {\r
-                               if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, Modifiers[ModifierID].name, _tcslen(Modifiers[ModifierID].name))\r
-                                && _tcslen(Modifiers[ModifierID].name) < _tcslen(m_Config.szFunctionDefinition[nFunctionID] + i)) {\r
-                                       keybind.nCommandType |= Modifiers[ModifierID].id;\r
-                                       i+= _tcslen(Modifiers[ModifierID].name);\r
-                                       bFound = TRUE;\r
-                               }\r
+       if (*def == _T('\\')) { // set modifiers\r
+               ++def;\r
+       LOOP:\r
+               for (int i = 0; i < MAX_MODIFIER; ++i) {\r
+                       size_t len = _tcslen(Modifiers[i].name);\r
+                       if (!_tcsncmp(def, Modifiers[i].name, len)) {\r
+                               keybind.nType |= Modifiers[i].id;\r
+                               def += len;\r
+                               goto LOOP;\r
                        }\r
-               } while (bFound);\r
-       }\r
-       if (IsShift(m_Config.szFunctionDefinition[nFunctionID][i]) && !(keybind.nCommandType & (WIN_CTRL | WIN_ALT | WIN_WIN))) {\r
-               keybind.nCommandType |= SHIFT;\r
+               }\r
        }\r
-\r
-       for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
-               if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
-                       i += _tcslen(ControlCharacters[nKeyID].name);\r
+       int i = 0;\r
+       for (; i < MAX_KEYNAME; ++i) {\r
+               size_t len = _tcslen(KeyNames[i].name);\r
+               if (!_tcsncmp(def, KeyNames[i].name, len)) {\r
+                       def += len;\r
                        break;\r
                }\r
        }\r
-       if (nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0])) {\r
-               keybind.bVk = ControlCharacters[nKeyID].bVk;\r
-       } else {\r
-               keybind.bVk = a2v(m_Config.szFunctionDefinition[nFunctionID][i]);\r
+       if (i < MAX_KEYNAME) {\r
+               keybind.bVk = KeyNames[i].bVk;\r
+               return keybind;\r
        }\r
-\r
+       SHORT r = ConvVkey(*def++, 0);\r
+       if (r & (1 << 8) && !(keybind.nType & (WIN_CTRL | WIN_ALT | WIN_WIN)))\r
+               keybind.nType |= SHIFT;\r
+       keybind.bVk = static_cast<BYTE>(r);\r
        return keybind;\r
 }\r
 \r
-BOOL CXkeymacsDll::IsShift(TCHAR nAscii)\r
-{\r
-       switch (nAscii) {\r
-       case _T(' '):\r
-               return FALSE;\r
-       case _T('!'):\r
-       case _T('"'):\r
-       case _T('#'):\r
-       case _T('$'):\r
-       case _T('%'):\r
-       case _T('&'):\r
-               return TRUE;\r
-       case _T('\''):\r
-               return m_Config.b106Keyboard;\r
-       case _T('('):\r
-       case _T(')'):\r
-       case _T('*'):\r
-       case _T('+'):\r
-               return TRUE;\r
-       case _T(','):\r
-       case _T('-'):\r
-       case _T('.'):\r
-       case _T('/'):\r
-       case _T('0'): case _T('1'): case _T('2'): case _T('3'): case _T('4'): case _T('5'): case _T('6'): case _T('7'): case _T('8'): case _T('9'):\r
-               return FALSE;\r
-       case _T(':'):\r
-               return !m_Config.b106Keyboard;\r
-       case _T(';'):\r
-               return FALSE;\r
-       case _T('<'):\r
-               return TRUE;\r
-       case _T('='):\r
-               return m_Config.b106Keyboard;\r
-       case _T('>'):\r
-       case _T('?'):\r
-               return TRUE;\r
-       case _T('@'):\r
-               return !m_Config.b106Keyboard;\r
-       case _T('A'): case _T('B'): case _T('C'): case _T('D'): case _T('E'): case _T('F'): case _T('G'): case _T('H'): case _T('I'): case _T('J'): \r
-       case _T('K'): case _T('L'): case _T('M'): case _T('N'): case _T('O'): case _T('P'): case _T('Q'): case _T('R'): case _T('S'): case _T('T'): \r
-       case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
-               return TRUE;\r
-       case _T('['):\r
-       case _T('\\'):\r
-       case _T(']'):\r
-               return FALSE;\r
-       case _T('^'):\r
-               return !m_Config.b106Keyboard;\r
-       case _T('_'):\r
-               return TRUE;\r
-       case _T('`'):\r
-               return m_Config.b106Keyboard;\r
-       case _T('a'): case _T('b'): case _T('c'): case _T('d'): case _T('e'): case _T('f'): case _T('g'): case _T('h'): case _T('i'): case _T('j'): \r
-       case _T('k'): case _T('l'): case _T('m'): case _T('n'): case _T('o'): case _T('p'): case _T('q'): case _T('r'): case _T('s'): case _T('t'): \r
-       case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
-               return FALSE;\r
-       case _T('{'):\r
-       case _T('|'):\r
-       case _T('}'):\r
-       case _T('~'):\r
-               return TRUE;\r
-       default:\r
-               return FALSE;\r
-       }\r
-}\r
-\r
-BYTE CXkeymacsDll::a2v(TCHAR nAscii)\r
+SHORT CXkeymacsDll::ConvVkey(SHORT in, int mode)\r
 {\r
-       switch (nAscii) {\r
-       case _T(' '):\r
-               return VK_SPACE;\r
-       case _T('!'):\r
-               return '1';\r
-       case _T('"'):\r
-               return m_Config.b106Keyboard ? '2' : (BYTE) 0xde;       // VK_OEM_7\r
-       case _T('#'):\r
-               return '3';\r
-       case _T('$'):\r
-               return '4';\r
-       case _T('%'):\r
-               return '5';\r
-       case _T('&'):\r
-               return m_Config.b106Keyboard ? '6' : '7';\r
-       case _T('\''):\r
-               return m_Config.b106Keyboard ? '7' : (BYTE) 0xde;       // VK_OEM_7\r
-       case _T('('):\r
-               return m_Config.b106Keyboard ? '8' : '9';\r
-       case _T(')'):\r
-               return m_Config.b106Keyboard ? '9' : '0';\r
-       case _T('*'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xba : '8';       // VK_OEM_1\r
-       case _T('+'):\r
-               return 0xbb;    // VK_OEM_PLUS\r
-       case _T(','):\r
-               return 0xbc;    // VK_OEM_COMMA\r
-       case _T('-'):\r
-               return 0xbd;    // VK_OEM_MINUS\r
-       case _T('.'):\r
-               return 0xbe;    // VK_OEM_PERIOD\r
-       case _T('/'):\r
-               return 0xbf;    // VK_OEM_2\r
-       case _T('0'): case _T('1'): case _T('2'): case _T('3'): case _T('4'): case _T('5'): case _T('6'): case _T('7'): case _T('8'): case _T('9'):\r
-               return nAscii;\r
-       case _T(':'):\r
-               return 0xba;    // VK_OEM_1\r
-       case _T(';'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xbb : (BYTE) 0xba;       // VK_OEM_PLUS  VK_OEM_1\r
-       case _T('<'):\r
-               return 0xbc;    // VK_OEM_COMMA\r
-       case _T('='):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xbd : (BYTE) 0xbb;       // VK_OEM_MINUS VK_OEM_PLUS\r
-       case _T('>'):\r
-               return 0xbe;    // VK_OEM_PERIOD\r
-       case _T('?'):\r
-               return 0xbf;    // VK_OEM_2\r
-       case _T('@'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xc0 : '2';\r
-       case _T('A'): case _T('B'): case _T('C'): case _T('D'): case _T('E'): case _T('F'): case _T('G'): case _T('H'): case _T('I'): case _T('J'): \r
-       case _T('K'): case _T('L'): case _T('M'): case _T('N'): case _T('O'): case _T('P'): case _T('Q'): case _T('R'): case _T('S'): case _T('T'): \r
-       case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
-               return nAscii;\r
-       case _T('['):\r
-               return 0xdb;    // VK_OEM_4\r
-       case _T('\\'):\r
-               return 0xdc;    // VK_OEM_5\r
-       case _T(']'):\r
-               return 0xdd;    // VK_OEM_6\r
-       case _T('^'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xde : '6';       // VK_OEM_7\r
-       case _T('_'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xe2 : (BYTE) 0xbd;       // VK_OEM_102   VK_OEM_MINUS\r
-       case _T('`'):\r
-               return 0xc0;    // VK_OEM_3\r
-       case _T('a'): case _T('b'): case _T('c'): case _T('d'): case _T('e'): case _T('f'): case _T('g'): case _T('h'): case _T('i'): case _T('j'): \r
-       case _T('k'): case _T('l'): case _T('m'): case _T('n'): case _T('o'): case _T('p'): case _T('q'): case _T('r'): case _T('s'): case _T('t'): \r
-       case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
-               return (BYTE) (nAscii - (_T('a') - _T('A')));\r
-       case _T('{'):\r
-               return 0xdb;    // VK_OEM_4\r
-       case _T('|'):\r
-               return 0xdc;    // VK_OEM_5\r
-       case _T('}'):\r
-               return 0xdd;    // VK_OEM_6\r
-       case _T('~'):\r
-               return m_Config.b106Keyboard ? (BYTE) 0xde : (BYTE) 0xc0;       // VK_OEM_7     VK_OEM_3\r
-       default:\r
+       HKL h = GetKeyboardLayout(0);\r
+       if (mode == 0) { // ASCII to VKey and state\r
+               SHORT r = VkKeyScanEx(static_cast<TCHAR>(in), h);\r
+               if (r < 0) // no key correcpont to the char\r
+                       return 0;\r
+               return r & 0x7ff; // drop state flags of Hankaku and others\r
+       }\r
+       // VKey and state to ASCII\r
+       const BYTE down = 0x80;\r
+       BYTE state[256] = {0};\r
+       if (in & (1 << 8))\r
+               state[VK_SHIFT] = down;\r
+       if (in & (2 << 8))\r
+               state[VK_CONTROL] = down;\r
+       if (in & (4 << 8))\r
+               state[VK_MENU] = down;\r
+       UINT vkey = in & 0xff;\r
+       state[vkey] = down;\r
+       WORD word = 0;\r
+       int r = ToAsciiEx(vkey, MapVirtualKeyEx(vkey, MAPVK_VK_TO_VSC, h), state, &word, 0, h);\r
+       if (r == 0)\r
                return 0;\r
-       }\r
-}\r
-\r
-BOOL CXkeymacsDll::IsMatchWindowText(CString szWindowText)\r
-{\r
-       BOOL bIsMatchWindowText = TRUE;\r
-\r
-       TCHAR szCurrentWindowText[WINDOW_TEXT_LENGTH] = {'\0'};\r
-       GetWindowText(GetForegroundWindow(), szCurrentWindowText, sizeof(szCurrentWindowText));\r
-\r
-       switch (CUtils::GetWindowTextType(szWindowText)) {\r
-       case IDS_WINDOW_TEXT_MATCH:                                                             // *foo*\r
-               szWindowText.Delete(0);                                                         // Delete first '*'\r
-               szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
-               bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText);\r
-               break;\r
-       case IDS_WINDOW_TEXT_MATCH_FORWARD:                                             // foo*\r
-               szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
-               bIsMatchWindowText = 0 == CString(szCurrentWindowText).Find(szWindowText);\r
-               break;\r
-       case IDS_WINDOW_TEXT_MATCH_BACKWARD:                                    // *foo\r
-               szWindowText.Delete(0);                                                         // Delete first '*'\r
-               bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText, CString(szCurrentWindowText).GetLength() - szWindowText.GetLength());\r
-               break;\r
-       case IDS_WINDOW_TEXT_MATCH_FULL:                                                // foo\r
-               bIsMatchWindowText = szWindowText == CString(szCurrentWindowText);\r
-               break;\r
-       case IDS_WINDOW_TEXT_IGNORE:                                                    // *\r
-               bIsMatchWindowText = TRUE;\r
-               break;\r
-       default:\r
-               ASSERT(0);\r
-               break;\r
-       }\r
-\r
-//     CUtils::Log(_T("IsMatchWindowText: %d, _%s_, _%s_"), bIsMatchWindowText, szCurrentWindowText, szWindowText);\r
-       return bIsMatchWindowText;\r
+       if (r == 1)\r
+               return static_cast<SHORT>(word);\r
+       return static_cast<SHORT>(word >> 8); // drop a dead key\r
 }\r
 \r
 void CXkeymacsDll::SetAccelerate(int nAccelerate)\r
@@ -2147,51 +1334,6 @@ void CXkeymacsDll::SetCursorData(HCURSOR hEnable, HCURSOR hDisableTMP, HCURSOR h
 \r
 void CXkeymacsDll::DoSetCursor()\r
 {\r
-       if (m_bCursor && m_hCurrentCursor) {\r
+       if (m_bCursor && m_hCurrentCursor)\r
                ::SetCursor(m_hCurrentCursor);\r
-       }\r
-}\r
-\r
-void CXkeymacsDll::Set326Compatible(int nApplicationID, BOOL b326Compatible)\r
-{\r
-       m_Config.b326Compatible[nApplicationID] = b326Compatible;\r
-}\r
-\r
-BOOL CXkeymacsDll::Get326Compatible()\r
-{\r
-       return m_Config.b326Compatible[m_nApplicationID];\r
-}\r
-\r
-void CXkeymacsDll::InvokeM_x(const TCHAR *const szPath)\r
-{\r
-//     CUtils::Log("M-x: szPath=_%s_", szPath);\r
-       int (*fCommand)() = NULL;\r
-\r
-       for (int i = 0; i < MAX_COMMAND; ++i) {\r
-               if (_tcsicmp(szPath, Commands[i].szCommandName) == 0) {\r
-                       fCommand = Commands[i].fCommand;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if (fCommand) {\r
-//             CUtils::Log("M-x: Command: _%s_", Commands[i].szCommandName);\r
-               fCommand();\r
-       } else {\r
-//             CUtils::Log("M-x: Path: _%s_", szPath);\r
-               ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);\r
-       }\r
-}\r
-\r
-void CXkeymacsDll::SetM_xTip(const TCHAR *const szPath)\r
-{\r
-       _tcscpy_s(m_M_xTip, "M-x LED");\r
-       if (szPath && _tcslen(szPath) < 128 - 5)\r
-               _stprintf_s(m_M_xTip, "M-x %s", szPath);\r
-}\r
-\r
-BOOL CXkeymacsDll::SendIconMessage(ICONMSG *pMsg, DWORD num)\r
-{\r
-       DWORD ack, read;\r
-       return CallNamedPipe(ICON_PIPE, pMsg, sizeof(ICONMSG) * num, &ack, sizeof(DWORD), &read, NMPWAIT_NOWAIT);\r
 }\r