OSDN Git Service

Modify type casting of arguments of CCommands::DoSetInputMethodOpenStatus
[xkeymacs/xkeymacs.git] / xkeymacsdll / xkeymacsdll.cpp
index afe819d..ae30ac1 100644 (file)
@@ -8,6 +8,7 @@
 #include <afxdllx.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,9 @@ 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 KeyName 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
@@ -135,6 +129,7 @@ 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
@@ -237,9 +232,7 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
        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
@@ -251,6 +244,9 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
        TCHAR   CXkeymacsDll::m_M_xTip[128] = "";\r
        CONFIG  CXkeymacsDll::m_Config = {0};\r
 #pragma data_seg()\r
+BOOL CXkeymacsDll::m_bRecordingMacro = FALSE;\r
+BOOL CXkeymacsDll::m_bDown[MAX_KEY] = {0};\r
+std::list<KbdMacro> CXkeymacsDll::m_Macro;\r
 \r
 //////////////////////////////////////////////////////////////////////\r
 // Construction/Destruction\r
@@ -421,7 +417,7 @@ LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lPara
        const MSG *msg = reinterpret_cast<MSG *>(lParam);\r
        if (msg->message == g_ImeManipulationMessage) {\r
                if (wParam)\r
-                       CCommands::DoSetInputMethodOpenStatus((INPUT_METHOD_OPEN_STATUS)msg->wParam, msg->lParam);\r
+                       CCommands::DoSetInputMethodOpenStatus(static_cast<INPUT_METHOD_OPEN_STATUS>(msg->wParam), static_cast<BOOL>(msg->lParam));\r
                return 1;\r
        }\r
        switch (msg->message) {\r
@@ -1005,13 +1001,6 @@ LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lPa
                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, FALSE);\r
        m_bRightAlt = IsDown(VK_RMENU, FALSE);\r
        m_bRightShift = IsDown(VK_RSHIFT, FALSE);\r
@@ -1046,44 +1035,11 @@ RECURSIVE_COMMAND:
 \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
+       if (m_bRecordingMacro && (!(lParam & BEING_RELEASED) || m_bDown[wParam])) {\r
+               KbdMacro m = { nCode, wParam, lParam, TRUE };\r
+               m_Macro.push_back(m);\r
+               m_bDown[wParam] |= !(lParam & BEING_RELEASED);\r
        }\r
-\r
        return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
 \r
 RECURSIVE:\r
@@ -1130,11 +1086,6 @@ void CXkeymacsDll::SetCommandID(int nApplicationID, int nCommandType, int nKey,
        m_Config.nCommandID[nApplicationID][nCommandType][nKey] = nCommandID;\r
 }\r
 \r
-void CXkeymacsDll::SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly)\r
-{\r
-       m_Config.bAtIbeamCursorOnly[nApplicationID][nCommandType][nKey] = bAtIbeamCursorOnly;\r
-}\r
-\r
 void CXkeymacsDll::SetKillRingMax(int nApplicationID, int nKillRingMax)\r
 {\r
        m_Config.nKillRingMax[nApplicationID] = nKillRingMax;\r
@@ -1151,7 +1102,6 @@ void CXkeymacsDll::Clear(int nApplicationID)
        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
@@ -1318,33 +1268,6 @@ void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)
        m_nKillRing += nKillRing;\r
 }\r
 \r
-// nobody use\r
-int CXkeymacsDll::GetMickey(int nDifferential, int nThreshold1, int nThreshold2, int nAcceleration, int nSpeed)\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
-}\r
-\r
 void CXkeymacsDll::SetSettingStyle(int nApplicationID, int nSettingStyle)\r
 {\r
        m_Config.nSettingStyle[nApplicationID] = nSettingStyle;\r
@@ -1370,101 +1293,40 @@ BOOL CXkeymacsDll::GetEnableCUA()
        return m_Config.bEnableCUA[m_nApplicationID];\r
 }\r
 \r
-void CXkeymacsDll::DefiningMacro(BOOL bDefiningMacro)\r
+void CXkeymacsDll::StartRecordMacro()\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
+       if (CCommands::bC_u())\r
+               CallMacro();\r
+       m_bRecordingMacro = TRUE;\r
+       m_Macro.erase(m_Macro.begin(), m_Macro.end());\r
+       ZeroMemory(m_bDown, MAX_KEY);\r
 }\r
 \r
-BOOL CXkeymacsDll::DefiningMacro()\r
+void CXkeymacsDll::EndRecordMacro()\r
 {\r
-       return m_bDefiningMacro;\r
+       m_bRecordingMacro = FALSE;\r
+       while (!m_Macro.empty()) { // remove not released push\r
+               const KbdMacro& m = m_Macro.back();\r
+               if (m.lParam & BEING_RELEASED)\r
+                       break;\r
+               m_Macro.pop_back();\r
+       }\r
 }\r
 \r
-/**/ \r
 void CXkeymacsDll::CallMacro()\r
 {\r
+       if (m_bRecordingMacro)\r
+               m_bRecordingMacro = FALSE;\r
        UINT before = GetModifierState(FALSE);\r
        SetModifierState(0, before);\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
+       for (auto m = m_Macro.begin(); m != m_Macro.end(); m++)\r
+               if (m->lParam & BEING_RELEASED)\r
+                       ReleaseKey(static_cast<BYTE>(m->wParam));\r
+               else\r
+                       DepressKey(static_cast<BYTE>(m->wParam), m->bOriginal);\r
        SetModifierState(before, 0);\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
@@ -1510,154 +1372,140 @@ void CXkeymacsDll::ClearFunctionDefinition()
 \r
 void CXkeymacsDll::SetFunctionDefinition(int nFunctionID, CString szDefinition)\r
 {\r
-       if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID) {\r
+       if (nFunctionID < 0 || nFunctionID >= MAX_FUNCTION)\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
+       _tcscpy_s(m_Config.szFunctionDefinition[nFunctionID], szDefinition);\r
        return;\r
-\r
 }\r
 \r
 // call an original command which is defined in dot.xkeymacs\r
 void CXkeymacsDll::CallFunction(int nFunctionID)\r
 {\r
-       CArray<KeyBind, KeyBind> keybinds;\r
-\r
-       if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID || !_tcslen(m_Config.szFunctionDefinition[nFunctionID])) {\r
+       if (nFunctionID < 0 || nFunctionID >= MAX_FUNCTION)\r
                return;\r
-       }\r
-\r
-       UINT before = GetModifierState(FALSE);\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.szFunctionDefinition[nFunctionID];\r
+       if (!def[0])\r
+               return;\r
+       std::vector<KeyBind> keybinds;\r
+       const 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
+       UINT before = GetModifierState(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
+       for (auto p = keybinds.begin(); p != keybinds.end(); p++) {\r
+               const int nCommandType = p->nCommandType;\r
+               const BYTE bVk = p->bVk;\r
+               int (*fCommand)() = nCommandType < MAX_COMMAND_TYPE ? Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand : NULL;\r
+               if (fCommand) {\r
+                       if (fCommand == CCommands::ExecuteExtendedCommand)\r
                                bM_x = TRUE;\r
-                       else if (!bInitialized) {\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
+                       while (fCommand() == GOTO_RECURSIVE)\r
                                ;\r
-                       }\r
-               } else if (bM_x) {\r
-                       if (bVk == VK_RETURN) {\r
+                       continue;\r
+               }\r
+               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
+                       else if (bVk != 0) {\r
+                               TCHAR nAscii = 0;\r
+                               do { // 1-127\r
+                                       if (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
-                               SetModifierState(0, before);\r
-                               bInitialized = TRUE;\r
+                               } while (nAscii != 127);\r
                        }\r
-                       if (nCommandType & WIN_WIN)\r
-                               DepressKey(VK_LWIN);\r
-                       if (nCommandType & WIN_CTRL)\r
-                               DepressKey(VK_CONTROL);\r
-                       if (nCommandType & WIN_ALT)\r
-                               DepressKey(VK_MENU);\r
-                       if (nCommandType & SHIFT)\r
-                               DepressKey(VK_SHIFT);\r
-\r
-                       Kdu(bVk);\r
-\r
-                       if (nCommandType & SHIFT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & SHIFT)))\r
-                               ReleaseKey(VK_SHIFT);\r
-                       if (nCommandType & WIN_ALT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_ALT)))\r
-                               ReleaseKey(VK_MENU);\r
-                       if (nCommandType & WIN_CTRL && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_CTRL)))\r
-                               ReleaseKey(VK_CONTROL);\r
-                       if (nCommandType & WIN_WIN && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_WIN)))\r
-                               ReleaseKey(VK_LWIN);\r
+                       continue;\r
+               }\r
+               if (!bInitialized) {\r
+                       SetModifierState(0, before);\r
+                       bInitialized = TRUE;\r
                }\r
+               if (nCommandType & WIN_WIN)\r
+                       DepressKey(VK_LWIN);\r
+               if (nCommandType & WIN_CTRL)\r
+                       DepressKey(VK_CONTROL);\r
+               if (nCommandType & WIN_ALT)\r
+                       DepressKey(VK_MENU);\r
+               if (nCommandType & SHIFT)\r
+                       DepressKey(VK_SHIFT);\r
+               Kdu(bVk);\r
+               const int nNextType = (p + 1) != keybinds.end() ? (p + 1)->nCommandType : 0;\r
+               if (nCommandType & SHIFT && !(nNextType & SHIFT))\r
+                       ReleaseKey(VK_SHIFT);\r
+               if (nCommandType & WIN_ALT && !(nNextType & WIN_ALT))\r
+                       ReleaseKey(VK_MENU);\r
+               if (nCommandType & WIN_CTRL && !(nNextType & WIN_CTRL))\r
+                       ReleaseKey(VK_CONTROL);\r
+               if (nCommandType & WIN_WIN && !(nNextType & WIN_WIN))\r
+                       ReleaseKey(VK_LWIN);\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
+               // 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.nCommandType |= Modifiers[i].id;\r
+                               def += len;\r
+                               goto LOOP;\r
                        }\r
-               } while (bFound);\r
+               }\r
        }\r
-       if (IsShift(m_Config.szFunctionDefinition[nFunctionID][i]) && !(keybind.nCommandType & (WIN_CTRL | WIN_ALT | WIN_WIN))) {\r
+       if (IsShift(*def) && !(keybind.nCommandType & (WIN_CTRL | WIN_ALT | WIN_WIN)))\r
                keybind.nCommandType |= SHIFT;\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
-       }\r
-\r
+       keybind.bVk = i < MAX_KEYNAME ? KeyNames[i].bVk : a2v(*def++);\r
        return keybind;\r
 }\r
 \r