OSDN Git Service

Remove support for Win9x/Me and NT4.0.
[xkeymacs/xkeymacs.git] / xkeymacsdll / xkeymacsdll.cpp
1 // xkeymacsdll.cpp : Defines the initialization routines for the DLL.\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "resource.h"\r
6 #include "Utils.h"\r
7 #include "Commands.h"\r
8 #include <afxdllx.h>\r
9 #include <math.h>\r
10 #include <Imm.h>\r
11 \r
12 #ifdef _DEBUG\r
13 #define new DEBUG_NEW\r
14 #undef THIS_FILE\r
15 static char THIS_FILE[] = __FILE__;\r
16 #endif\r
17 \r
18 struct KbdMacro\r
19 {\r
20         int nCode;\r
21         WPARAM wParam;\r
22         LPARAM lParam;\r
23         BOOL bOriginal;\r
24 };\r
25 \r
26 struct Modifier {\r
27         LPCTSTR name;\r
28         int id;\r
29 };\r
30 \r
31 static const Modifier Modifiers[] = {\r
32 //      { _T("A-"), ALT },\r
33         { _T("C-"), CONTROL},\r
34 //      { _T("H-"), HYPER },\r
35         { _T("M-"), META },\r
36         { _T("S-"), SHIFT },\r
37 //      { _T("s-"), SUPER },\r
38         { _T("Ctrl+"), WIN_CTRL },\r
39         { _T("Alt+"), WIN_ALT },\r
40         { _T("Win+"), WIN_WIN },\r
41 };\r
42 \r
43 static const KeyName ControlCharacters[] = {\r
44 //      { VK_LBUTTON,           _T("mouse-1") },                                // does not work well\r
45 //      { VK_RBUTTON,           _T("mouse-3") },                                // does not work well\r
46         { VK_CANCEL,            _T("break") },\r
47 //      { VK_MBUTTON,           _T("mouse-2") },                                // does not work well\r
48         { VK_BACK,                      _T("backspace") },\r
49         { VK_TAB,                       _T("tab") },\r
50         { VK_RETURN,            _T("return") },\r
51         { VK_CAPITAL,           _T("capslock") },\r
52         { VK_KANA,                      _T("kana") },\r
53         { VK_KANJI,                     _T("kanji") },\r
54         { VK_ESCAPE,            _T("escape") },\r
55         { VK_CONVERT,           _T("convert") },\r
56         { VK_NONCONVERT,        _T("nonconvert") },\r
57 //      { VK_SPACE,                     _T("SPC") },                                    // [? ]\r
58         { VK_PRIOR,                     _T("prior") },\r
59         { VK_NEXT,                      _T("next") },\r
60         { VK_END,                       _T("end") },\r
61         { VK_HOME,                      _T("home") },\r
62         { VK_LEFT,                      _T("left") },\r
63         { VK_UP,                        _T("up") },\r
64         { VK_RIGHT,                     _T("right") },\r
65         { VK_DOWN,                      _T("down") },\r
66         { VK_SELECT,            _T("select") },\r
67         { VK_PRINT,                     _T("print") },\r
68         { VK_EXECUTE,           _T("execute") },\r
69         { VK_SNAPSHOT,          _T("printscreen") },                    // work as print\r
70         { VK_INSERT,            _T("insert") },\r
71         { VK_DELETE,            _T("delete") },\r
72         { VK_LWIN,                      _T("lwindow") },\r
73         { VK_RWIN,                      _T("rwindow") },\r
74         { VK_APPS,                      _T("apps") },\r
75         { VK_SLEEP,                     _T("sleep") },\r
76         { VK_NUMPAD0,           _T("kp-0") },\r
77         { VK_NUMPAD1,           _T("kp-1") },\r
78         { VK_NUMPAD2,           _T("kp-2") },\r
79         { VK_NUMPAD3,           _T("kp-3") },\r
80         { VK_NUMPAD4,           _T("kp-4") },\r
81         { VK_NUMPAD5,           _T("kp-5") },\r
82         { VK_NUMPAD6,           _T("kp-6") },\r
83         { VK_NUMPAD7,           _T("kp-7") },\r
84         { VK_NUMPAD8,           _T("kp-8") },\r
85         { VK_NUMPAD9,           _T("kp-9") },\r
86         { VK_MULTIPLY,          _T("kp-multiply") },\r
87         { VK_ADD,                       _T("kp-add") },\r
88         { VK_SUBTRACT,          _T("kp-subtract") },\r
89         { VK_DECIMAL,           _T("kp-decimal") },\r
90         { VK_DIVIDE,            _T("kp-divide") },\r
91 //      { VK_F1,                        _T("f1") },                                             // FIXME\r
92 //      { 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
93         { VK_F3,                        _T("f3") },\r
94         { VK_F4,                        _T("f4") },\r
95         { VK_F5,                        _T("f5") },\r
96         { VK_F6,                        _T("f6") },\r
97         { VK_F7,                        _T("f7") },\r
98         { VK_F8,                        _T("f8") },\r
99         { VK_F9,                        _T("f9") },\r
100         { VK_F10,                       _T("f10") },\r
101         { VK_F11,                       _T("f11") },\r
102         { VK_F12,                       _T("f12") },\r
103         { VK_F13,                       _T("f13") },\r
104         { VK_F14,                       _T("f14") },\r
105         { VK_F15,                       _T("f15") },\r
106         { VK_F16,                       _T("f16") },\r
107         { VK_F17,                       _T("f17") },\r
108         { VK_F18,                       _T("f18") },\r
109         { VK_F19,                       _T("f19") },\r
110         { VK_F20,                       _T("f20") },\r
111         { VK_F21,                       _T("f21") },\r
112         { VK_F22,                       _T("f22") },\r
113         { VK_F23,                       _T("f23") },\r
114         { VK_F24,                       _T("f24") },\r
115         { VK_F1,                        _T("f1") },\r
116         { VK_F2,                        _T("f2") },\r
117         { VK_NUMLOCK,           _T("kp-numlock") },\r
118         { VK_SCROLL,            _T("scroll") },\r
119         { 0xa6,                         _T("browser-back") },                   // VK_BROWSER_BACK\r
120         { 0xa7,                         _T("browser-forward") },                // VK_BROWSER_FORWARD\r
121         { 0xa8,                         _T("browser-refresh") },                // VK_BROWSER_REFRESH\r
122         { 0xa9,                         _T("browser-stop") },                   // VK_BROWSER_STOP\r
123         { 0xaa,                         _T("browser-search") },                 // VK_BROWSER_SEARCH\r
124         { 0xab,                         _T("browser-favorites") },              // VK_BROWSER_FAVORITES\r
125         { 0xac,                         _T("browser-home") },                   // VK_BROWSER_HOME\r
126         { 0xad,                         _T("volume-mute") },                    // VK_VOLUME_MUTE\r
127         { 0xae,                         _T("volume-down") },                    // VK_VOLUME_DOWN\r
128         { 0xaf,                         _T("volume-up") },                              // VK_VOLUME_UP\r
129         { 0xb0,                         _T("media-next-track") },               // VK_MEDIA_NEXT_TRACK\r
130         { 0xb1,                         _T("media-prev-track") },               // VK_MEDIA_PREV_TRACK\r
131         { 0xb2,                         _T("media-stop") },                             // VK_MEDIA_STOP\r
132         { 0xb3,                         _T("media-play-pause") },               // VK_MEDIA_PLAY_PAUSE\r
133         { 0xb4,                         _T("launch-mail") },                    // VK_LAUNCH_MAIL\r
134         { 0xb5,                         _T("launch-media-select") },    // VK_LAUNCH_MEDIA_SELECT\r
135         { 0xb6,                         _T("launch-1") },                               // VK_LAUNCH_APP1\r
136         { 0xb7,                         _T("launch-2") },                               // VK_LAUNCH_APP2\r
137 };\r
138 \r
139 static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL };\r
140 \r
141 static __declspec(thread) HINSTANCE g_hDllInst = NULL;\r
142 static __declspec(thread) HHOOK g_hHookKeyboard = NULL;\r
143 \r
144 extern "C" int APIENTRY\r
145 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
146 {\r
147         g_hDllInst = hInstance;\r
148         \r
149         // Remove this if you use lpReserved\r
150         UNREFERENCED_PARAMETER(lpReserved);\r
151 \r
152         switch (dwReason) {\r
153         case DLL_PROCESS_ATTACH:\r
154                 TRACE0("XKEYMACSDLL.DLL Initializing!\n");\r
155                 \r
156                 // Extension DLL one-time initialization\r
157                 if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) {\r
158                         return 0;\r
159                 }\r
160 \r
161                 // Insert this DLL into the resource chain\r
162                 // NOTE: If this Extension DLL is being implicitly linked to by\r
163                 //  an MFC Regular DLL (such as an ActiveX Control)\r
164                 //  instead of an MFC application, then you will want to\r
165                 //  remove this line from DllMain and put it in a separate\r
166                 //  function exported from this Extension DLL.  The Regular DLL\r
167                 //  that uses this Extension DLL should then explicitly call that\r
168                 //  function to initialize this Extension DLL.  Otherwise,\r
169                 //  the CDynLinkLibrary object will not be attached to the\r
170                 //  Regular DLL's resource chain, and serious problems will\r
171                 //  result.\r
172 \r
173                 try {\r
174                         new CDynLinkLibrary(XkeymacsdllDLL);\r
175                 }\r
176                 catch (CMemoryException* e) {\r
177                         e->Delete();\r
178 //                      CUtils::Log("DllMain: 'new' threw an exception");\r
179                 }\r
180         case DLL_THREAD_ATTACH:\r
181                 CXkeymacsDll::SetKeyboardHook();\r
182                 break;\r
183         case DLL_PROCESS_DETACH:\r
184                 TRACE0("XKEYMACSDLL.DLL Terminating!\n");\r
185                 // Terminate the library before destructors are called\r
186                 AfxTermExtensionModule(XkeymacsdllDLL);\r
187         case DLL_THREAD_DETACH:\r
188                 CXkeymacsDll::ReleaseKeyboardHook();\r
189         }\r
190         return 1;   // ok\r
191 }\r
192 \r
193 //////////////////////////////////////////////////////////////////////\r
194 // CXkeymacsDll Class\r
195 //////////////////////////////////////////////////////////////////////\r
196 \r
197 #include "xkeymacsDll.h"\r
198 #pragma data_seg(".xkmcs")\r
199         BOOL    CXkeymacsDll::m_bEnableKeyboardHook = FALSE;\r
200         HHOOK   CXkeymacsDll::m_hHookCallWnd = NULL;\r
201         HHOOK   CXkeymacsDll::m_hHookCallWndRet = NULL;\r
202         HHOOK   CXkeymacsDll::m_hHookGetMessage = NULL;\r
203         HHOOK   CXkeymacsDll::m_hHookShell = NULL;\r
204         int             CXkeymacsDll::m_nCommandID[MAX_APP][MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
205         BOOL    CXkeymacsDll::m_bAtIbeamCursorOnly[MAX_APP][MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
206         int             CXkeymacsDll::m_nFunctionID[MAX_APP][MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
207         TCHAR   CXkeymacsDll::m_szSpecialApp[MAX_APP][CLASS_NAME_LENGTH] = {'\0'};\r
208         TCHAR   CXkeymacsDll::m_szWindowText[MAX_APP][WINDOW_TEXT_LENGTH] = {'\0'};\r
209         BOOL    CXkeymacsDll::m_bRightControl   = FALSE;\r
210         BOOL    CXkeymacsDll::m_bRightAlt               = FALSE;\r
211         BOOL    CXkeymacsDll::m_bRightShift             = FALSE;\r
212         BOOL    CXkeymacsDll::m_bHook                   = TRUE;\r
213         BOOL    CXkeymacsDll::m_bDefiningMacro  = FALSE;\r
214         DWORD   CXkeymacsDll::m_dwOldMessage[MAX_ICON_TYPE] = {'\0'};\r
215         NOTIFYICONDATA CXkeymacsDll::m_stNtfyIcon[MAX_ICON_TYPE] = {'\0'};\r
216         NOTIFYICONDATA CXkeymacsDll::m_stOldNtfyIcon[MAX_ICON_TYPE] = {'\0'};\r
217         HICON   CXkeymacsDll::m_hIcon[MAX_ICON_TYPE][MAX_STATUS] = {'\0'};\r
218         BOOL    CXkeymacsDll::m_bIcon[MAX_ICON_TYPE] = {'\0'};\r
219         int             CXkeymacsDll::m_nKillRingMax[MAX_APP] = {'\0'};\r
220         BOOL    CXkeymacsDll::m_bUseDialogSetting[MAX_APP] = {'\0'};\r
221         CList<CClipboardSnap *, CClipboardSnap *> CXkeymacsDll::m_oKillRing;\r
222         CObList CXkeymacsDll::m_Macro;\r
223         int             CXkeymacsDll::m_nKillRing = 0;\r
224         int             CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
225         int             CXkeymacsDll::m_nApplicationID = 0;\r
226         int             CXkeymacsDll::m_nSettingStyle[MAX_APP] = {'\0'};\r
227         BOOL    CXkeymacsDll::m_bIgnoreUndefinedMetaCtrl[MAX_APP] = {'\0'};\r
228         BOOL    CXkeymacsDll::m_bIgnoreUndefinedC_x[MAX_APP] = {'\0'};\r
229 //      int             CXkeymacsDll::m_nPassThrough = 0;\r
230         TCHAR   CXkeymacsDll::m_szApplicationName[MAX_PATH] = {'\0'};\r
231         TCHAR   CXkeymacsDll::m_szOldApplicationName[MAX_PATH] = {'\0'};\r
232         BOOL    CXkeymacsDll::m_bEnableCUA[MAX_APP] = {'\0'};\r
233         TCHAR   CXkeymacsDll::m_szFunctionDefinition[MAX_FUNCTION][MAX_DEFINITION] = {'\0'};\r
234         int             CXkeymacsDll::m_nAccelerate = 0;\r
235         int             CXkeymacsDll::m_nKeyboardSpeed = 31;\r
236         HCURSOR CXkeymacsDll::m_hCursor[MAX_STATUS] = {'\0'};\r
237         HCURSOR CXkeymacsDll::m_hCurrentCursor = NULL;\r
238         BOOL    CXkeymacsDll::m_bCursor = FALSE;\r
239         BOOL    CXkeymacsDll::m_b326Compatible[MAX_APP] = {'\0'};\r
240 \r
241         BOOL    CXkeymacsData::m_b106Keyboard = FALSE;\r
242 #pragma data_seg()\r
243 \r
244 //////////////////////////////////////////////////////////////////////\r
245 // Construction/Destruction\r
246 //////////////////////////////////////////////////////////////////////\r
247 \r
248 CXkeymacsDll::CXkeymacsDll()\r
249 {\r
250         CUtils::InitCUtils();\r
251 }\r
252 \r
253 CXkeymacsDll::~CXkeymacsDll()\r
254 {\r
255 \r
256 }\r
257 \r
258 int CXkeymacsDll::ModifyShell_NotifyIcon(ICON_TYPE icon, BOOL bNewStatus, BOOL bForce)\r
259 {\r
260         if (m_stNtfyIcon[icon].hIcon == (bNewStatus ? m_hIcon[icon][ON_ICON] : m_hIcon[icon][OFF_ICON])) {\r
261                 if (!bForce) {\r
262                         return TRUE;\r
263                 }\r
264         } else {\r
265                 m_stNtfyIcon[icon].hIcon = (bNewStatus ? m_hIcon[icon][ON_ICON] : m_hIcon[icon][OFF_ICON]);\r
266         }\r
267         return DoShell_NotifyIcon(icon, NIM_MODIFY);\r
268 }\r
269 \r
270 void CXkeymacsDll::SetNotifyIconData(ICON_TYPE icon, NOTIFYICONDATA stNtfyIcon, HICON hEnable, HICON hDisableTMP, HICON hDisableWOCQ, HICON hDisable, BOOL bEnable)\r
271 {\r
272         m_hIcon[icon][STATUS_ENABLE] = hEnable;\r
273         m_hIcon[icon][STATUS_DISABLE_TMP] = hDisableTMP;\r
274         m_hIcon[icon][STATUS_DISABLE_WOCQ] = hDisableWOCQ;\r
275         m_hIcon[icon][STATUS_DISABLE] = hDisable;\r
276         m_bIcon[icon] = bEnable;\r
277         m_stNtfyIcon[icon] = stNtfyIcon;\r
278         AddShell_NotifyIcon(icon);\r
279 }\r
280 \r
281 void CXkeymacsDll::SetNotifyIconData(ICON_TYPE icon, NOTIFYICONDATA stNtfyIcon, HICON hOn, HICON hOff, BOOL bEnable)\r
282 {\r
283         m_hIcon[icon][ON_ICON] = hOn;\r
284         m_hIcon[icon][OFF_ICON] = hOff;\r
285         m_bIcon[icon] = bEnable;\r
286         m_stNtfyIcon[icon] = stNtfyIcon;\r
287         AddShell_NotifyIcon(icon);\r
288 }\r
289 \r
290 void CXkeymacsDll::EnableShell_NotifyIcon(ICON_TYPE icon, BOOL bEnable)\r
291 {\r
292         DeleteShell_NotifyIcon(icon);\r
293         m_bIcon[icon] = bEnable;\r
294         AddShell_NotifyIcon(icon);\r
295 }\r
296 \r
297 \r
298 BOOL CXkeymacsDll::DoShell_NotifyIcon(ICON_TYPE icon, DWORD dwMessage)\r
299 {\r
300         if (m_bIcon[icon]\r
301          &&     (m_dwOldMessage[icon] != dwMessage\r
302           || memcmp(&m_stOldNtfyIcon[icon], &m_stNtfyIcon[icon], sizeof(m_stNtfyIcon[icon])))) {\r
303                 m_dwOldMessage[icon] = dwMessage;\r
304                 m_stOldNtfyIcon[icon] = m_stNtfyIcon[icon];\r
305 \r
306                 BOOL rc = FALSE;\r
307                 for (int retry_count = 0; retry_count < 20; ++retry_count) { // retry for timeout\r
308                         rc = Shell_NotifyIcon(dwMessage, &m_stNtfyIcon[icon]);\r
309                         if (dwMessage != NIM_ADD || rc || (GetLastError() != ERROR_TIMEOUT && 5 < retry_count)) {\r
310                                 break;\r
311                         }\r
312                         Sleep(1000); // 1sec\r
313                         if ((rc = Shell_NotifyIcon(NIM_MODIFY, &m_stNtfyIcon[icon])) != FALSE) {\r
314                                 break; // ERROR_TIMEOUT was returned but the icon was also added.\r
315                         }\r
316                 }\r
317                 return rc;\r
318         } else {\r
319                 return TRUE;\r
320         }\r
321 }\r
322 \r
323 void CXkeymacsDll::AddShell_NotifyIcon(ICON_TYPE icon)\r
324 {\r
325         DoShell_NotifyIcon(icon, NIM_ADD);\r
326 }\r
327 \r
328 void CXkeymacsDll::DeleteShell_NotifyIcon(ICON_TYPE icon)\r
329 {\r
330         DoShell_NotifyIcon(icon, NIM_DELETE);\r
331 }\r
332 \r
333 // set hooks\r
334 void CXkeymacsDll::SetHooks()\r
335 {\r
336         m_bEnableKeyboardHook = TRUE;\r
337         m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);\r
338         m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);\r
339         m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);\r
340         m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);\r
341 }\r
342 \r
343 void CXkeymacsDll::SetKeyboardHook()\r
344 {\r
345         if (!g_hHookKeyboard)\r
346                 SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, GetCurrentThreadId());\r
347 }\r
348 \r
349 // release hooks\r
350 void CXkeymacsDll::ReleaseHooks()\r
351 {\r
352         m_bEnableKeyboardHook = FALSE;\r
353         if (m_hHookCallWnd)\r
354                 UnhookWindowsHookEx(m_hHookCallWnd);\r
355         m_hHookCallWnd = NULL;\r
356         if (m_hHookCallWndRet)\r
357                 UnhookWindowsHookEx(m_hHookCallWndRet);\r
358         m_hHookCallWndRet = NULL;\r
359         if (m_hHookGetMessage)\r
360                 UnhookWindowsHookEx(m_hHookGetMessage);\r
361         m_hHookGetMessage = NULL;\r
362         if (m_hHookShell)\r
363                 UnhookWindowsHookEx(m_hHookShell);\r
364         m_hHookShell = NULL;\r
365 }\r
366 \r
367 void CXkeymacsDll::ReleaseKeyboardHook()\r
368 {\r
369         if (g_hHookKeyboard)\r
370                 UnhookWindowsHookEx(g_hHookKeyboard);\r
371         g_hHookKeyboard = NULL;\r
372 }\r
373 \r
374 void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)\r
375 {\r
376         m_bHook = bFlag;\r
377 \r
378         if (m_bHook) {\r
379                 if (CCommands::IsTemporarilyDisableXKeymacs()) {\r
380                         m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE_TMP];\r
381                         m_hCurrentCursor = m_hCursor[STATUS_DISABLE_TMP];\r
382                 } else {\r
383                         m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_ENABLE];\r
384                         m_hCurrentCursor = m_hCursor[STATUS_ENABLE];\r
385                 }\r
386         } else {\r
387                 m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE_WOCQ];\r
388                 m_hCurrentCursor = m_hCursor[STATUS_DISABLE_WOCQ];\r
389         }\r
390         if (m_nSettingStyle[m_nApplicationID] == SETTING_DISABLE\r
391          || (!_tcsicmp(m_szSpecialApp[m_nApplicationID], _T("Default"))\r
392           && CUtils::IsDefaultIgnoreApplication())) {\r
393                 m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE];\r
394                 m_hCurrentCursor = m_hCursor[STATUS_DISABLE];\r
395         }\r
396         DoShell_NotifyIcon(MAIN_ICON, NIM_MODIFY);\r
397         DoSetCursor();\r
398 }\r
399 \r
400 // if be keyboard hook, return TRUE\r
401 BOOL CXkeymacsDll::IsKeyboardHook()\r
402 {\r
403         if (m_bHook) {\r
404                 return TRUE;\r
405         }\r
406 \r
407         return FALSE;\r
408 }\r
409 \r
410 void CXkeymacsDll::LogCallWndProcMessage(WPARAM wParam, LPARAM lParam)\r
411 {\r
412         CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
413 \r
414         switch (cwps.message) {\r
415         case WM_PAINT:                                  // 0x000F\r
416         case WM_MDIGETACTIVE:                   // 0x0229\r
417         case 0x0403:\r
418         case 0x0407:\r
419         case 0x0418:\r
420         case 0x043F:\r
421         case 0x0440:\r
422                 break;\r
423         case WM_CREATE:                                 // 0x0001\r
424 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_CREATE"));\r
425                 break;\r
426         case WM_DESTROY:                                // 0x0002\r
427 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_DESTROY"));\r
428                 break;\r
429         case WM_MOVE:                                   // 0x0003\r
430 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_MOVE");)\r
431                 break;\r
432         case WM_SIZE:                                   // 0x0005\r
433 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_SIZE"));\r
434                 break;\r
435         case WM_GETTEXT:                                // 0x000D\r
436 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_GETTEXT"));\r
437                 break;\r
438         case WM_ERASEBKGND:                             // 0x0014\r
439 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_ERASEBKGND"));\r
440                 break;\r
441         case WM_WINDOWPOSCHANGING:              // 0x0046\r
442 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGING"));\r
443                 break;\r
444         case WM_WINDOWPOSCHANGED:               // 0x0047\r
445 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGED"));\r
446                 break;\r
447         case WM_COPYDATA:                               // 0x004A\r
448 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_COPYDATA"));\r
449                 break;\r
450         case WM_NCCREATE:                               // 0x0081\r
451 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCREATE"));\r
452                 break;\r
453         case WM_NCDESTROY:                              // 0x0082\r
454 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCDESTROY"));\r
455                 break;\r
456         case WM_NCCALCSIZE:                             // 0x0083\r
457 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCALCSIZE"));\r
458                 break;\r
459         case WM_NCPAINT:                                // 0x0085\r
460 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCPAINT"));\r
461                 break;\r
462         case WM_IME_STARTCOMPOSITION:   // 0x010D\r
463 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_STARTCOMPOSITION"));\r
464                 break;\r
465         case WM_IME_ENDCOMPOSITION:             // 0x010E\r
466 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_ENDCOMPOSITION"));\r
467                 break;\r
468         case WM_IME_KEYLAST:                    // 0x010F\r
469 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_KEYLAST"));\r
470                 break;\r
471         case WM_COMMAND:                                // 0x0111\r
472 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_COMMAND"));\r
473                 break;\r
474         case WM_CTLCOLOREDIT:                   // 0x0133\r
475 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_CTLCOLOREDIT"));\r
476                 break;\r
477         case WM_POWERBROADCAST:                 // 0x0218\r
478 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_POWERBROADCAST"));\r
479                 switch (wParam) {\r
480                 case PBT_APMQUERYSUSPEND:               // 0x0000\r
481 //                      CUtils::Log(_T("PBT_APMQUERYSUSPEND"));\r
482                         break;\r
483                 case PBT_APMQUERYSTANDBY:               // 0x0001\r
484 //                      CUtils::Log(_T("PBT_APMQUERYSTANDBY"));\r
485                         break;\r
486                 case PBT_APMQUERYSUSPENDFAILED: // 0x0002\r
487 //                      CUtils::Log(_T("PBT_APMQUERYSUSPENDFAILED"));\r
488                         break;\r
489                 case PBT_APMQUERYSTANDBYFAILED: // 0x0003\r
490 //                      CUtils::Log(_T("PBT_APMQUERYSTANDBYFAILED"));\r
491                         break;\r
492                 case PBT_APMSUSPEND:                    // 0x0004\r
493 //                      CUtils::Log(_T("PBT_APMSUSPEND"));\r
494                         break;\r
495                 case PBT_APMSTANDBY:                    // 0x0005\r
496 //                      CUtils::Log(_T("PBT_APMSTANDBY"));\r
497                         break;\r
498                 case PBT_APMRESUMECRITICAL:             // 0x0006\r
499 //                      CUtils::Log(_T("PBT_APMRESUMECRITICAL"));\r
500                         break;\r
501                 case PBT_APMRESUMESUSPEND:              // 0x0007\r
502 //                      CUtils::Log(_T("PBT_APMRESUMESUSPEND"));\r
503                         break;\r
504                 case PBT_APMRESUMESTANDBY:              // 0x0008\r
505 //                      CUtils::Log(_T("PBT_APMRESUMESTANDBY"));\r
506                         break;\r
507                 case PBT_APMBATTERYLOW:                 // 0x0009\r
508 //                      CUtils::Log(_T("PBT_APMBATTERYLOW"));\r
509                         break;\r
510                 case PBT_APMPOWERSTATUSCHANGE:  // 0x000A\r
511 //                      CUtils::Log(_T("PBT_APMPOWERSTATUSCHANGE"));\r
512                         break;\r
513                 case PBT_APMOEMEVENT:                   // 0x000B\r
514 //                      CUtils::Log(_T("PBT_APMOEMEVENT"));\r
515                         break;\r
516                 case PBT_APMRESUMEAUTOMATIC:    // 0x0012\r
517 //                      CUtils::Log(_T("PBT_APMRESUMEAUTOMATIC"));\r
518                         break;\r
519                 default:\r
520 //                      CUtils::Log(_T("PBT_OTHERS: %d"), wParam);\r
521                         break;\r
522                 }\r
523                 break;\r
524         case WM_IME_NOTIFY:                             // 0x0282\r
525 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_NOTIFY"));\r
526                 break;\r
527         default:\r
528 //              CUtils::Log(_T("CallWndProc: cwps.message = 0x%04X"), cwps.message);\r
529                 break;\r
530         }\r
531 }\r
532 \r
533 LRESULT CALLBACK CXkeymacsDll::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)\r
534 {\r
535 //      LogCallWndProcMessage(wParam, lParam);\r
536 \r
537         if (0 <= nCode) {\r
538                 CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
539                 switch (cwps.message) {\r
540                 case WM_IME_STARTCOMPOSITION:\r
541                         InitKeyboardProc(TRUE);\r
542                         break;\r
543                 case WM_IME_ENDCOMPOSITION:\r
544                         InitKeyboardProc(FALSE);\r
545                         break;\r
546                 case WM_SETFOCUS:\r
547                         if (cwps.hwnd == GetForegroundWindow()) {\r
548                                 InitKeyboardProc(FALSE);\r
549                                 SetKeyboardHookFlag(m_bHook);\r
550                         }\r
551                         break;\r
552                 case WM_NCACTIVATE:\r
553                         if (cwps.wParam) {\r
554                                 if (cwps.hwnd == GetForegroundWindow()) {\r
555                                         InitKeyboardProc(FALSE);\r
556                                         SetKeyboardHookFlag(m_bHook);\r
557                                 }\r
558                         }\r
559                         break;\r
560                 case WM_POWERBROADCAST:\r
561                         switch (wParam) {\r
562                         case PBT_APMRESUMECRITICAL: // 0x0006\r
563                         case PBT_APMRESUMESUSPEND:  // 0x0007\r
564                         case PBT_APMRESUMESTANDBY:  // 0x0008\r
565                                 ReleaseHooks();\r
566                                 SetHooks();\r
567                                 break;\r
568                         default:\r
569                                 break;\r
570                         }\r
571                         break;\r
572                 default:\r
573                         break;\r
574                 }\r
575         }\r
576         return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);\r
577 }\r
578 \r
579 LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)\r
580 {\r
581         if (0 <= nCode) {\r
582                 CWPRETSTRUCT &cwprets = *(CWPRETSTRUCT *)lParam;\r
583                 switch (cwprets.message) {\r
584                 case WM_SETTEXT:\r
585                         if (cwprets.hwnd == GetForegroundWindow()) {\r
586                                 InitKeyboardProc(FALSE);\r
587                         }\r
588                         break;\r
589                 case WM_SETCURSOR:\r
590                         DoSetCursor();\r
591                         break;\r
592                 default:\r
593                         break;\r
594                 }\r
595         }\r
596         return CallNextHookEx(m_hHookCallWndRet, nCode, wParam, lParam);\r
597 }\r
598 \r
599 LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)\r
600 {\r
601         MSG &msg = (*(MSG *)lParam);\r
602 \r
603         switch (msg.message) {\r
604         case WM_IME_STARTCOMPOSITION:\r
605                 InitKeyboardProc(TRUE);\r
606                 break;\r
607         case WM_IME_ENDCOMPOSITION:\r
608                 InitKeyboardProc(FALSE);\r
609                 break;\r
610         }\r
611         return CallNextHookEx(m_hHookGetMessage, nCode, wParam, lParam);\r
612 }\r
613 \r
614 LRESULT CALLBACK CXkeymacsDll::ShellProc(int nCode, WPARAM wParam, LPARAM lParam)\r
615 {\r
616         switch (nCode) {\r
617         case HSHELL_WINDOWACTIVATED:\r
618         {\r
619                 TCHAR className[256];\r
620                 ::GetClassName((HWND)wParam, className, 255);\r
621                 if (!_tcsicmp(className, _T("ConsoleWindowClass"))) {\r
622                         InitKeyboardProc(FALSE);\r
623                         SetKeyboardHookFlag(m_bHook);\r
624                 }\r
625                 break;\r
626         }\r
627         default:\r
628                 break;\r
629         }\r
630         return CallNextHookEx( m_hHookShell, nCode, wParam, lParam );\r
631 }\r
632 \r
633 // return true if the key is down\r
634 BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)\r
635 {\r
636         if (bPhysicalKey) {\r
637                 return GetKeyState(bVk) < 0;\r
638         } else {\r
639                 return GetAsyncKeyState(bVk) < 0;\r
640         }\r
641 }\r
642 \r
643 // Do keybd_event\r
644 void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)\r
645 {\r
646         // Set KEYEVENTF_EXTENDEDKEY if needed\r
647         switch (bVk) {\r
648         case VK_CONTROL:\r
649                 if (m_bRightControl) {          // Right Ctrl\r
650                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
651                 }\r
652                 break;\r
653 \r
654         case VK_MENU:\r
655                 if (m_bRightAlt) {                      // Right Alt\r
656                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
657 //                      CUtils::Log("Right Alt %d", dwFlags);\r
658 //              } else {\r
659 //                      CUtils::Log("Left Alt %d", dwFlags);\r
660                 }\r
661                 break;\r
662 \r
663         case VK_SHIFT:\r
664                 if (m_bRightShift) {            // Right Shift\r
665                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
666                 }\r
667                 break;\r
668 \r
669         case VK_PAUSE:\r
670                 if (IsDown(VK_CONTROL)) {       // Break\r
671                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
672                 }\r
673                 break;\r
674 \r
675         case VK_INSERT:\r
676         case VK_DELETE:\r
677         case VK_HOME:\r
678         case VK_END:\r
679         case VK_NEXT:\r
680         case VK_PRIOR:\r
681         case VK_UP:\r
682         case VK_DOWN:\r
683         case VK_RIGHT:\r
684         case VK_LEFT:\r
685         case VK_NUMLOCK:\r
686         case VK_PRINT:\r
687                 dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
688                 break;\r
689 \r
690         default:\r
691                 break;\r
692         }\r
693 \r
694 //      CUtils::Log(_T("b: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
695         keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());\r
696 //      CUtils::Log(_T("a: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
697 }\r
698 \r
699 // the key is being depressed\r
700 void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal) // bVk is virtual-key code, MSDN said\r
701 {\r
702         if (bOriginal) {\r
703 //              CUtils::Log(_T("i: %x, %d, %d, %d, %d, %d, %d, %d, %d"), bVk,\r
704 //                      IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
705 //                      IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
706 \r
707                 int nCommandType = NONE;\r
708                 if (IsDown(VK_CONTROL, FALSE)) {\r
709                         nCommandType |= CONTROL;\r
710                 }\r
711                 if (IsDown(VK_MENU, FALSE)) {\r
712                         nCommandType |= META;\r
713                 }\r
714                 Original(nCommandType, bVk, 1);\r
715         }\r
716 \r
717         DoKeybd_event(bVk, 0);\r
718 }\r
719 \r
720 // the key is being released\r
721 void CXkeymacsDll::ReleaseKey(BYTE bVk) // bVk is virtual-key code, MSDN said\r
722 {\r
723         DoKeybd_event(bVk, KEYEVENTF_KEYUP);\r
724 }\r
725 \r
726 // bVk down, bVk up\r
727 void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)\r
728 {\r
729         while (n--) {\r
730                 DepressKey(bVk, bOriginal);\r
731                 ReleaseKey(bVk);\r
732         }\r
733 }\r
734 \r
735 void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)\r
736 {\r
737         if (CUtils::IsFindDialog()) {\r
738                 static BOOL bImeCompositionOld = FALSE;\r
739                 if (!bImeComposition\r
740                  && bImeCompositionOld) {\r
741                         DepressKey(VK_END);\r
742                         ReleaseKey(VK_END);\r
743                 }\r
744                 bImeCompositionOld = bImeComposition;\r
745         }\r
746 \r
747         CUtils::SetApplicationName(bImeComposition);\r
748 \r
749         if (_tcsnicmp(m_szSpecialApp[m_nApplicationID], CUtils::GetApplicationName(), 0xF) || !IsMatchWindowText(m_szWindowText[m_nApplicationID])) {   // PROCESSENTRY32 has only 0xF bytes of Name\r
750                 m_nApplicationID = -1;\r
751 \r
752                 for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
753                         if (!_tcsnicmp(m_szSpecialApp[nApplicationID], CUtils::GetApplicationName(), 0xF) && IsMatchWindowText(m_szWindowText[nApplicationID])) {\r
754 \r
755                                 if (m_nApplicationID < 0\r
756                                  || CUtils::GetWindowTextType(m_szWindowText[m_nApplicationID]) < CUtils::GetWindowTextType(m_szWindowText[nApplicationID])\r
757                                  || CUtils::GetWindowTextType(m_szWindowText[m_nApplicationID]) == CUtils::GetWindowTextType(m_szWindowText[nApplicationID])\r
758                                  && _tcscmp(m_szWindowText[m_nApplicationID], m_szWindowText[nApplicationID]) <= 0) {\r
759                                         m_nApplicationID = nApplicationID;\r
760                                 }\r
761                         }\r
762                 }\r
763 \r
764                 if (m_nApplicationID < 0) {\r
765                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
766                                 if (!_tcsicmp(m_szSpecialApp[nApplicationID], _T("Default"))) {\r
767                                         m_nApplicationID = nApplicationID;\r
768                                         break;\r
769                                 }\r
770                         }\r
771 \r
772                         if (m_nApplicationID < 0) {\r
773                                 m_nApplicationID = 0;\r
774                         }\r
775                 }\r
776         }\r
777 \r
778         if (m_nSettingStyle[m_nApplicationID] != SETTING_DISABLE\r
779          && (_tcsicmp(m_szSpecialApp[m_nApplicationID], _T("Default")) || !CUtils::IsDefaultIgnoreApplication())\r
780          && !bImeComposition\r
781          && CUtils::IsDialog()) {\r
782                 // Use Dialog Setting\r
783                 if (m_bUseDialogSetting[m_nApplicationID]) {\r
784                         int nOriginalApplicationID = m_nApplicationID;\r
785                         for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {\r
786                                 if (!_tcsicmp(m_szSpecialApp[m_nApplicationID], _T("Dialog"))) {\r
787                                         break;\r
788                                 }\r
789                         }\r
790                         if (m_nApplicationID == MAX_APP) {\r
791                                 m_nApplicationID = nOriginalApplicationID;\r
792                         }\r
793                 }\r
794         }\r
795 \r
796         ModifyShell_NotifyIcon(CX_ICON, FALSE);\r
797         ModifyShell_NotifyIcon(MX_ICON, FALSE);\r
798         ModifyShell_NotifyIcon(META_ICON, FALSE);\r
799         CCommands::SetMark(FALSE);\r
800         CCommands::SetTemporarilyDisableXKeymacs(FALSE);\r
801         CCommands::Reset();\r
802 }\r
803 \r
804 // emulate emacs        // cf virtual-key code\r
805 LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)\r
806 {\r
807         ASSERT(0 <= wParam && wParam <= UCHAR_MAX);\r
808 \r
809         int nCommandType = NONE;\r
810         BYTE nKey = (BYTE)wParam;\r
811 \r
812         static BOOL bLocked = FALSE;\r
813         static const BYTE RECURSIVE_KEY = 0x07;\r
814         static int (*fCommand)() = NULL;\r
815         static BYTE nOneShotModifier[MAX_KEY] = {'\0'};\r
816         static BOOL bCherryOneShotModifier = FALSE;\r
817 \r
818 //      CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nKey, lParam);\r
819 \r
820         if (!m_bEnableKeyboardHook)\r
821                 return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
822 \r
823         if (nCode < 0 || nCode == HC_NOREMOVE) {\r
824                 goto DO_NOTHING;\r
825         }\r
826 \r
827         if (nKey == RECURSIVE_KEY) {\r
828                 if (lParam & BEING_RELEASED) {\r
829                         goto HOOK_RECURSIVE_KEY;\r
830                 } else {\r
831                         goto RECURSIVE_COMMAND;\r
832                 }\r
833         }\r
834 \r
835         {\r
836                 static BOOL bShift = FALSE;\r
837                 if (IsDepressedShiftKeyOnly(nKey)) {\r
838                         if (lParam & BEING_RELEASED) {\r
839                                 if (bShift) {\r
840                                         CCommands::SetMark(FALSE);\r
841                                 }\r
842                         } else {\r
843                                 bShift = TRUE;\r
844                         }\r
845                 } else {\r
846                         bShift = FALSE;\r
847                 }\r
848         }\r
849 \r
850         switch (nKey) {\r
851         case VK_CONTROL:\r
852                 if (lParam & EXTENDED_KEY) {\r
853                         nKey = VK_RCONTROL;\r
854                 } else {\r
855                         nKey = VK_LCONTROL;\r
856                 }\r
857                 break;\r
858         case VK_MENU:\r
859                 if (lParam & EXTENDED_KEY) {\r
860                         nKey = VK_RMENU;\r
861                 } else {\r
862                         nKey = VK_LMENU;\r
863                 }\r
864                 break;\r
865         case VK_SHIFT:\r
866                 if (lParam & EXTENDED_KEY) {\r
867                         nKey = VK_RSHIFT;\r
868                 } else {\r
869                         nKey = VK_LSHIFT;\r
870                 }\r
871                 break;\r
872         default:\r
873                 break;\r
874         }\r
875 \r
876         if (lParam & BEING_RELEASED) {\r
877                 if (nKey == VK_MENU\r
878                  || nKey == VK_LWIN\r
879                  || nKey == VK_RWIN\r
880                  || nKey == VK_APPS\r
881                  || nKey == VK_LMENU\r
882                  || nKey == VK_RMENU) {\r
883                         for (int i = 0; i < MAX_COMMAND_TYPE; ++i) {\r
884                                 if (Commands[m_nCommandID[m_nApplicationID][i][nKey]].fCommand\r
885                                  && (Commands[m_nCommandID[m_nApplicationID][i][nKey]].fCommand != CCommands::MetaAlt\r
886                                   || nKey != VK_MENU && nKey != VK_LMENU && nKey != VK_RMENU)) {\r
887                                         goto HOOK;\r
888                                 }\r
889                         }\r
890                 }\r
891 \r
892                 if (nOneShotModifier[nKey]) {\r
893                         ReleaseKey(nOneShotModifier[nKey]);\r
894                         nOneShotModifier[nKey] = 0;\r
895 \r
896                         if (bCherryOneShotModifier) {\r
897                                 bCherryOneShotModifier = FALSE;\r
898                                 Kdu(nKey);\r
899                         }\r
900                 }\r
901 \r
902                 goto DO_NOTHING;\r
903         }\r
904 \r
905         if (m_nSettingStyle[m_nApplicationID] == SETTING_DISABLE) {\r
906                 goto DO_NOTHING;\r
907         }\r
908 \r
909         // Do Nothing for Meadow, Mule for Win32, ... if those use default setting.\r
910         if (!_tcsicmp(m_szSpecialApp[m_nApplicationID], _T("Default"))\r
911          && CUtils::IsDefaultIgnoreApplication()) {\r
912                 goto DO_NOTHING;\r
913         }\r
914 \r
915         switch (IsPassThrough(nKey)) {\r
916         case GOTO_DO_NOTHING:\r
917                 goto DO_NOTHING;\r
918         case GOTO_HOOK:\r
919                 goto HOOK;\r
920         case CONTINUE:\r
921                 break;\r
922         default:\r
923                 ASSERT(0);\r
924                 break;\r
925         }\r
926 \r
927         // set command type\r
928         {\r
929                 nCommandType = NONE;\r
930                 if (IsDown(VK_SHIFT, FALSE)) {\r
931                         nCommandType |= SHIFT;\r
932                 }\r
933                 if (IsControl()) {\r
934                         nCommandType |= CONTROL;\r
935                 }\r
936                 if (IsMeta()) {\r
937                         nCommandType |= META;\r
938                 }\r
939                 if (CCommands::bC_x()) {\r
940                         nCommandType |= CONTROLX;\r
941                 }\r
942 \r
943                 // Ignore undefined C-x ?\r
944                 if (nCommandType & CONTROLX) {\r
945                         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
946                          && m_nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
947                                 if (m_bIgnoreUndefinedC_x[m_nApplicationID]) {\r
948                                         CCommands::Reset(GOTO_HOOK);\r
949                                         goto HOOK;\r
950                                 }\r
951                                 nCommandType &= ~CONTROLX;\r
952                         }\r
953                 }\r
954 \r
955                 // Ignore undefined Meta Ctrl+?\r
956                 if (CCommands::bM_() && (nCommandType & CONTROL)) {\r
957                         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
958                          && m_nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
959                                 if (m_bIgnoreUndefinedMetaCtrl[m_nApplicationID]) {\r
960                                         if (Original(CONTROL, nKey)) {\r
961                                                 Original(CONTROL, nKey, -1);\r
962                                                 goto DO_NOTHING;\r
963                                         }\r
964                                         CCommands::Reset(GOTO_HOOK);\r
965                                         goto HOOK;\r
966                                 }\r
967                                 nCommandType &= ~META;\r
968                         }\r
969                 }\r
970         }\r
971 \r
972         {\r
973 //              CUtils::Log(_T("o: %x, %d, %d, %d, %d, %d, %d, %d, %d"), (BYTE)wParam,\r
974 //                      IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
975 //                      IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
976 \r
977                 BYTE nKey = (BYTE)wParam; // VK_CONTROL is needed instead of VK_RCONTROL and VK_LCONTROL in this block just for Original()\r
978                 int nVirtualCommandType = NONE;\r
979                 if (IsDown(VK_CONTROL) && nKey != VK_CONTROL) {\r
980                         nVirtualCommandType |= CONTROL;\r
981                 }\r
982                 if (IsDown(VK_MENU) && nKey != VK_MENU) {\r
983                         nVirtualCommandType |= META;\r
984                 }\r
985                 if (Original(nVirtualCommandType, nKey)) {\r
986                         Original(nVirtualCommandType, nKey, -1);\r
987                         goto DO_NOTHING;\r
988                 }\r
989         }\r
990 \r
991         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableOrDisableXKeymacs) {\r
992                 SetKeyboardHookFlag(!m_bHook);\r
993                 goto HOOK;\r
994         }\r
995         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableXKeymacs) {\r
996                 if (!m_bHook) {\r
997                         SetKeyboardHookFlag(!m_bHook);\r
998                 }\r
999                 goto HOOK;\r
1000         }\r
1001         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DisableXKeymacs) {\r
1002                 if (m_bHook) {\r
1003                         SetKeyboardHookFlag(!m_bHook);\r
1004                 }\r
1005                 goto HOOK;\r
1006         }\r
1007         if (!m_bHook) {\r
1008                 goto DO_NOTHING;\r
1009         }\r
1010 \r
1011         if (CCommands::bM_x()) {\r
1012                 static unsigned int index = 0;\r
1013                 static TCHAR szPath[MAX_PATH] = {'\0'};\r
1014 \r
1015                 if (lParam & BEING_RELEASED) {\r
1016                         // ignore\r
1017                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BackwardChar) {\r
1018                         if (index) {\r
1019                                 --index;\r
1020                         }\r
1021                         goto HOOKX;\r
1022                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BeginningOfLine) {\r
1023                         index = 0;\r
1024                         goto HOOKX;\r
1025                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteBackwardChar) {\r
1026                         if (index) {\r
1027                                 --index;\r
1028                                 memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
1029                                 ModifyM_xTip(szPath);\r
1030                         }\r
1031                         goto HOOKX;\r
1032                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteChar) {\r
1033                         if (index < _tcslen(szPath)) {\r
1034                                 memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
1035                                 ModifyM_xTip(szPath);\r
1036                         }\r
1037                         goto HOOKX;\r
1038                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EndOfLine) {\r
1039                         index = _tcslen(szPath);\r
1040                         goto HOOKX;\r
1041                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::ForwardChar) {\r
1042                         if (index < _tcslen(szPath)) {\r
1043                                 ++index;\r
1044                         }\r
1045                         goto HOOKX;\r
1046                 } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::KeyboardQuit) {\r
1047                         CCommands::bM_x(FALSE);\r
1048                         index = 0;\r
1049                         memset(szPath, 0, sizeof(szPath));\r
1050                         goto HOOK;\r
1051                 } else if (nKey == VK_RETURN\r
1052                                 || Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::Newline) {\r
1053                         InvokeM_x(szPath);\r
1054 \r
1055                         CCommands::bM_x(FALSE);\r
1056                         index = 0;\r
1057                         memset(szPath, 0, sizeof(szPath));\r
1058                         goto HOOK;\r
1059                 } else if (index < MAX_PATH - 1) {\r
1060                         const BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
1061                         for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
1062                                 if (nKey != 0 && a2v(nAscii) == nKey && bIsShiftDown == IsShift(nAscii)) {\r
1063 //                                      CUtils::Log("M-x: %#X (%c), %#X (%c)", nKey, nKey, nAscii, nAscii);\r
1064                                         if (index < _tcslen(szPath)) {\r
1065                                                 memmove(&szPath[index + 1], &szPath[index], __min(_tcslen(szPath) - index, MAX_PATH - (index + 1) - 1));\r
1066                                         }\r
1067                                         szPath[index++] = nAscii;\r
1068 //                                      CUtils::Log("M-x: %c(%#04x)", nAscii, nAscii);\r
1069                                         ModifyM_xTip(szPath);\r
1070                                         goto HOOKX;\r
1071                                 }\r
1072                         }\r
1073                 }\r
1074         }\r
1075 \r
1076         if (CCommands::bC_u()) {\r
1077                 if ((nCommandType == NONE) && ('0' <= nKey) && (nKey <= '9')) {\r
1078                         CCommands::NumericArgument(nKey - '0');\r
1079                         goto HOOK0_9;\r
1080                 }\r
1081                 if ((nCommandType == NONE) && (nKey == 0xBD)) {\r
1082                         CCommands::NumericArgumentMinus();\r
1083                         goto HOOK0_9;\r
1084                 }\r
1085         }\r
1086 \r
1087         if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrl) {\r
1088                 nOneShotModifier[nKey] = VK_LCONTROL;\r
1089                 DepressKey(nOneShotModifier[nKey]);\r
1090                 bCherryOneShotModifier = TRUE;\r
1091                 goto HOOK;\r
1092         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
1093                 nOneShotModifier[nKey] = VK_LCONTROL;\r
1094                 DepressKey(nOneShotModifier[nKey]);\r
1095                 bCherryOneShotModifier = TRUE;\r
1096                 goto HOOK;\r
1097         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
1098                 ReleaseKey(nOneShotModifier[nKey]);\r
1099                 bCherryOneShotModifier = FALSE;\r
1100                 Kdu(nKey);\r
1101                 goto HOOK;\r
1102         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAlt) {\r
1103                 nOneShotModifier[nKey] = VK_LMENU;\r
1104                 DepressKey(nOneShotModifier[nKey]);\r
1105                 bCherryOneShotModifier = TRUE;\r
1106                 goto HOOK;\r
1107         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
1108                 nOneShotModifier[nKey] = VK_LMENU;\r
1109                 DepressKey(nOneShotModifier[nKey]);\r
1110                 bCherryOneShotModifier = TRUE;\r
1111                 goto HOOK;\r
1112         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
1113                 ReleaseKey(nOneShotModifier[nKey]);\r
1114                 bCherryOneShotModifier = FALSE;\r
1115                 Kdu(nKey);\r
1116                 goto HOOK;\r
1117         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShift) {\r
1118                 nOneShotModifier[nKey] = VK_SHIFT;\r
1119                 DepressKey(nOneShotModifier[nKey]);\r
1120                 bCherryOneShotModifier = TRUE;\r
1121                 goto HOOK;\r
1122         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
1123                 nOneShotModifier[nKey] = VK_SHIFT;\r
1124                 DepressKey(nOneShotModifier[nKey]);\r
1125                 bCherryOneShotModifier = TRUE;\r
1126                 goto HOOK;\r
1127         } else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
1128                 ReleaseKey(nOneShotModifier[nKey]);\r
1129                 bCherryOneShotModifier = FALSE;\r
1130                 Kdu(nKey);\r
1131                 goto HOOK;\r
1132         } else {\r
1133                 for (int i = 0; i < MAX_KEY; ++i) {\r
1134                         if (nOneShotModifier[i] == nKey) {\r
1135                                 break;\r
1136                         }\r
1137                 }\r
1138                 if (i == MAX_KEY) {\r
1139                         bCherryOneShotModifier = FALSE;\r
1140                 }\r
1141         }\r
1142 \r
1143         if (0 <= m_nFunctionID[m_nApplicationID][nCommandType][nKey]\r
1144          && m_nFunctionID[m_nApplicationID][nCommandType][nKey] < MAX_FUNCTION\r
1145          && _tcslen(m_szFunctionDefinition[m_nFunctionID[m_nApplicationID][nCommandType][nKey]])) {\r
1146                 CallFunction(m_nFunctionID[m_nApplicationID][nCommandType][nKey]);\r
1147                 CCommands::Reset(GOTO_HOOK);\r
1148                 goto HOOK;\r
1149         }\r
1150 \r
1151         if (!Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand) {\r
1152                 if (nKey == VK_CONTROL\r
1153                  || nKey == VK_LCONTROL\r
1154                  || nKey == VK_RCONTROL\r
1155                  || nKey == VK_MENU\r
1156                  || nKey == VK_LMENU\r
1157                  || nKey == VK_RMENU\r
1158                  || nKey == VK_SHIFT\r
1159                  || nKey == VK_LSHIFT\r
1160                  || nKey == VK_RSHIFT) {\r
1161                         goto DO_NOTHING;\r
1162                 }\r
1163 \r
1164                 if (!(nCommandType & SHIFT)) {\r
1165                         if (CCommands::IsSetMark()) {\r
1166                                 if (CCommands::MoveCaret(nKey, nCommandType & CONTROL) != CONTINUE) {\r
1167                                         CCommands::ClearNumericArgument();\r
1168                                         goto HOOK;\r
1169                                 }\r
1170                                 CCommands::SetMark(FALSE);\r
1171                         }\r
1172                 }\r
1173 \r
1174                 if (1 < CCommands::GetNumericArgument()) {\r
1175                         Kdu(nKey, CCommands::GetNumericArgument());\r
1176                         CCommands::ClearNumericArgument();\r
1177                         goto HOOK;\r
1178                 }\r
1179 \r
1180                 goto DO_NOTHING;\r
1181         }\r
1182 \r
1183         if (CCommands::IsTemporarilyDisableXKeymacs()\r
1184          && Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand != CCommands::KeyboardQuit) {\r
1185                 CCommands::SetTemporarilyDisableXKeymacs(FALSE);\r
1186                 goto DO_NOTHING;\r
1187         }\r
1188 \r
1189         if (m_bAtIbeamCursorOnly[m_nApplicationID][nCommandType][nKey]) {\r
1190                 CURSORINFO cursorinfo = { sizeof(cursorinfo) };\r
1191                 if (GetCursorInfo(&cursorinfo) && cursorinfo.flags && cursorinfo.hCursor != LoadCursor(NULL, IDC_IBEAM)) {\r
1192                         goto DO_NOTHING;\r
1193                 }\r
1194         }\r
1195 \r
1196         m_bRightControl = IsDown(VK_RCONTROL);\r
1197         m_bRightAlt             = IsDown(VK_RMENU);\r
1198         m_bRightShift   = IsDown(VK_RSHIFT);\r
1199 \r
1200         if (!bLocked) {\r
1201                 bLocked = TRUE;\r
1202                 fCommand = Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand;\r
1203 RECURSIVE_COMMAND:\r
1204                 switch (fCommand()) {\r
1205                 case GOTO_DO_NOTHING:\r
1206                         bLocked = FALSE;\r
1207                         goto DO_NOTHING;\r
1208                 case GOTO_HOOK:\r
1209                         bLocked = FALSE;\r
1210                         goto HOOK;\r
1211                 case GOTO_RECURSIVE:\r
1212                         goto RECURSIVE;\r
1213                 case GOTO_HOOKX:\r
1214                         bLocked = FALSE;\r
1215                         goto HOOKX;\r
1216                 case GOTO_HOOK0_9:\r
1217                         bLocked = FALSE;\r
1218                         goto HOOK0_9;\r
1219                 default:\r
1220                         ASSERT(0);\r
1221                         bLocked = FALSE;\r
1222                         goto DO_NOTHING;\r
1223                 }\r
1224         } else {\r
1225                 goto HOOK_RECURSIVE_KEY;\r
1226         }\r
1227 \r
1228 DO_NOTHING:\r
1229         ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT));\r
1230         ModifyShell_NotifyIcon(CTRL_ICON, IsControl());\r
1231         ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU));\r
1232 \r
1233         {\r
1234                 static BOOL bDefiningMacro = FALSE;\r
1235                 if (m_bDefiningMacro) {\r
1236                         static BOOL bDown[MAX_KEY] = {'\0'};\r
1237 \r
1238                         if (!bDefiningMacro) {\r
1239                                 while (m_Macro.GetHeadPosition()) {\r
1240                                         void *p = m_Macro.GetAt(m_Macro.GetHeadPosition());\r
1241                                         m_Macro.RemoveHead();\r
1242                                         delete p;\r
1243                                         p = NULL;\r
1244                                 }\r
1245                                 memset(bDown, 0, sizeof(bDown));\r
1246                         }\r
1247 \r
1248                         if ((!(lParam & BEING_RELEASED)) || bDown[wParam]) {\r
1249                                 try {\r
1250                                         KbdMacro *pKbdMacro = new KbdMacro;\r
1251                                         if (pKbdMacro) {\r
1252                                                 pKbdMacro->nCode = nCode;\r
1253                                                 pKbdMacro->wParam = wParam;\r
1254                                                 pKbdMacro->lParam = lParam;\r
1255                                                 pKbdMacro->bOriginal = TRUE;\r
1256                                                 m_Macro.AddTail((CObject *)pKbdMacro);\r
1257                                         }\r
1258                                 }\r
1259                                 catch (CMemoryException* e) {\r
1260                                         e->Delete();\r
1261 //                                      CUtils::Log("KeyboardProc: 'new' threw an exception");\r
1262                                 }\r
1263                                 if (!(lParam & BEING_RELEASED)) {\r
1264                                         bDown[wParam] = TRUE;\r
1265                                 }\r
1266                         }\r
1267                 }\r
1268                 bDefiningMacro = m_bDefiningMacro;\r
1269         }\r
1270 \r
1271         return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
1272 \r
1273 RECURSIVE:\r
1274         Kdu(RECURSIVE_KEY, 1, FALSE);\r
1275         ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT));\r
1276         ModifyShell_NotifyIcon(CTRL_ICON, IsControl());\r
1277         ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU));\r
1278         return TRUE;\r
1279 \r
1280 HOOK:\r
1281         CCommands::SetLastCommand(fCommand);\r
1282 HOOK0_9:\r
1283 HOOKX:\r
1284         ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT));\r
1285         ModifyShell_NotifyIcon(CTRL_ICON, IsControl());\r
1286         ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU));\r
1287 HOOK_RECURSIVE_KEY:\r
1288         return TRUE;\r
1289 }\r
1290 \r
1291 //////////////////////////////////////////////////////////////////////\r
1292 // CXkeymacsData Class\r
1293 //////////////////////////////////////////////////////////////////////\r
1294 \r
1295 //////////////////////////////////////////////////////////////////////\r
1296 // Construction/Destruction\r
1297 //////////////////////////////////////////////////////////////////////\r
1298 \r
1299 CXkeymacsData::CXkeymacsData()\r
1300 {\r
1301         ClearAll();\r
1302 }\r
1303 \r
1304 CXkeymacsData::~CXkeymacsData()\r
1305 {\r
1306 \r
1307 }\r
1308 \r
1309 // set application name\r
1310 void CXkeymacsData::SetApplicationName(LPCTSTR lpszApplicationName)\r
1311 {\r
1312         m_strApplicationName.Format(lpszApplicationName);\r
1313 }\r
1314 \r
1315 // return application name\r
1316 CString CXkeymacsData::GetApplicationName()\r
1317 {\r
1318         return m_strApplicationName;\r
1319 }\r
1320 \r
1321 // set hook or not\r
1322 void CXkeymacsData::SetCommandID(int nCommandType, int nKey, int nCommandID)\r
1323 {\r
1324         ASSERT(0 <= nCommandType        || nCommandType < MAX_COMMAND_TYPE);\r
1325         ASSERT(0 <= nKey                        || nKey                 < MAX_KEY);\r
1326 \r
1327         m_nCommandID[nCommandType][nKey] = nCommandID;\r
1328 }\r
1329 \r
1330 // return hook or not\r
1331 int CXkeymacsData::GetCommandID(int nCommandType, int nKey)\r
1332 {\r
1333         ASSERT(0 <= nCommandType        || nCommandType < MAX_COMMAND_TYPE);\r
1334         ASSERT(0 <= nKey                        || nKey                 < MAX_KEY);\r
1335 \r
1336         return m_nCommandID[nCommandType][nKey];\r
1337 }\r
1338 \r
1339 // set hook at ibeam cursor only or not\r
1340 void CXkeymacsData::SetAtIbeamCursorOnly(int nCommandType, int nKey, BOOL bAtIbeamCursorOnly)\r
1341 {\r
1342         ASSERT(0 <= nCommandType        || nCommandType < MAX_COMMAND_TYPE);\r
1343         ASSERT(0 <= nKey                        || nKey                 < MAX_KEY);\r
1344 \r
1345         m_bAtIbeamCursorOnly[nCommandType][nKey] = bAtIbeamCursorOnly;\r
1346 }\r
1347 \r
1348 // get hook at ibeam cursor only or not\r
1349 BOOL CXkeymacsData::GetAtIbeamCursorOnly(int nCommandType, int nKey)\r
1350 {\r
1351         ASSERT(0 <= nCommandType        || nCommandType < MAX_COMMAND_TYPE);\r
1352         ASSERT(0 <= nKey                        || nKey                 < MAX_KEY);\r
1353 \r
1354         return m_bAtIbeamCursorOnly[nCommandType][nKey];\r
1355 }\r
1356 \r
1357 // clear all data\r
1358 void CXkeymacsData::ClearAll()\r
1359 {\r
1360         ZeroMemory(m_nCommandID, sizeof(m_nCommandID));\r
1361         ZeroMemory(m_bAtIbeamCursorOnly, sizeof(m_bAtIbeamCursorOnly));\r
1362         m_strApplicationName.Empty();\r
1363 }\r
1364 \r
1365 void CXkeymacsDll::SetApplicationName(int nApplicationID, CString szApplicationName)\r
1366 {\r
1367         ZeroMemory(m_szSpecialApp[nApplicationID], sizeof(m_szSpecialApp[nApplicationID]));\r
1368         _tcsncpy(m_szSpecialApp[nApplicationID], szApplicationName, sizeof(m_szSpecialApp[nApplicationID]));\r
1369 }\r
1370 \r
1371 void CXkeymacsDll::SetWindowText(int nApplicationID, CString szWindowText)\r
1372 {\r
1373         ZeroMemory(m_szWindowText[nApplicationID], sizeof(m_szWindowText[nApplicationID]));\r
1374         _tcsncpy(m_szWindowText[nApplicationID], szWindowText, sizeof(m_szWindowText[nApplicationID]));\r
1375 }\r
1376 \r
1377 void CXkeymacsDll::SetCommandID(int nApplicationID, int nCommandType, int nKey, int nCommandID)\r
1378 {\r
1379         m_nCommandID[nApplicationID][nCommandType][nKey] = nCommandID;\r
1380 }\r
1381 \r
1382 void CXkeymacsDll::SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly)\r
1383 {\r
1384         m_bAtIbeamCursorOnly[nApplicationID][nCommandType][nKey] = bAtIbeamCursorOnly;\r
1385 }\r
1386 \r
1387 void CXkeymacsDll::SetKillRingMax(int nApplicationID, int nKillRingMax)\r
1388 {\r
1389         m_nKillRingMax[nApplicationID] = nKillRingMax;\r
1390 }\r
1391 \r
1392 void CXkeymacsDll::SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting)\r
1393 {\r
1394         m_bUseDialogSetting[nApplicationID] = bUseDialogSetting;\r
1395 }\r
1396 \r
1397 // Clear data of nApplicationID\r
1398 void CXkeymacsDll::Clear(int nApplicationID)\r
1399 {\r
1400         if (0 <= nApplicationID && nApplicationID < MAX_APP) {\r
1401                 ZeroMemory(m_szSpecialApp[nApplicationID], sizeof(m_szSpecialApp[nApplicationID]));\r
1402                 ZeroMemory(m_nCommandID[nApplicationID], sizeof(m_nCommandID[nApplicationID]));\r
1403                 ZeroMemory(m_bAtIbeamCursorOnly[nApplicationID], sizeof(m_bAtIbeamCursorOnly[nApplicationID]));\r
1404                 m_nKillRingMax[nApplicationID] = 0;\r
1405                 m_bUseDialogSetting[nApplicationID] = FALSE;\r
1406                 m_nSettingStyle[nApplicationID] = 0;\r
1407         } else {\r
1408                 ASSERT(0);\r
1409         }\r
1410 }\r
1411 \r
1412 void CXkeymacsData::SetApplicationTitle(LPCTSTR lpszApplicationTitle)\r
1413 {\r
1414         m_strApplicationTitle.Format(lpszApplicationTitle);\r
1415 \r
1416         // delete white space at the end of the application title.\r
1417         while (!m_strApplicationTitle.IsEmpty()\r
1418                 && _istspace(m_strApplicationTitle.GetAt(m_strApplicationTitle.GetLength() - 1))) {\r
1419                 m_strApplicationTitle.Delete(m_strApplicationTitle.GetLength() - 1);\r
1420         }\r
1421 }\r
1422 \r
1423 CString CXkeymacsData::GetApplicationTitle()\r
1424 {\r
1425         return m_strApplicationTitle;\r
1426 }\r
1427 \r
1428 void CXkeymacsData::SetKillRingMax(int nKillRingMax)\r
1429 {\r
1430         m_nKillRingMax = nKillRingMax;\r
1431 }\r
1432 \r
1433 int CXkeymacsData::GetKillRingMax()\r
1434 {\r
1435         return m_nKillRingMax;\r
1436 }\r
1437 \r
1438 BOOL CXkeymacsDll::IsValidKey(BYTE bVk)\r
1439 {\r
1440         if (bVk == 0xf0) {      // 0xf0: Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.\r
1441                 return FALSE;\r
1442         }\r
1443 \r
1444         switch (bVk) {\r
1445         case VK_CONTROL:\r
1446         case VK_MENU:\r
1447         case VK_SHIFT:\r
1448                 return FALSE;\r
1449         default:\r
1450                 break;\r
1451         }\r
1452 \r
1453         return TRUE;\r
1454 }\r
1455 \r
1456 BOOL CXkeymacsDll::IsDepressedModifier(int (__cdecl *Modifier)(void), BOOL bPhysicalKey)\r
1457 {\r
1458         BYTE bVk = 0;\r
1459         do {\r
1460                 if (IsValidKey(bVk)\r
1461                  && IsDown(bVk, bPhysicalKey)\r
1462                  && Commands[m_nCommandID[m_nApplicationID][NONE][bVk]].fCommand == Modifier) {\r
1463                         return TRUE;\r
1464                 }\r
1465         } while (++bVk);\r
1466         return FALSE;\r
1467 }\r
1468 \r
1469 BOOL CXkeymacsDll::IsDepressedShiftKeyOnly(BYTE nKey)\r
1470 {\r
1471         if (nKey != VK_SHIFT\r
1472          && nKey != VK_LSHIFT\r
1473          && nKey != VK_RSHIFT) {\r
1474                 return FALSE;\r
1475         }\r
1476 \r
1477         BYTE bVk = 0;\r
1478         do {\r
1479                 if (bVk == VK_SHIFT\r
1480                  || bVk == VK_LSHIFT\r
1481                  || bVk == VK_RSHIFT) {\r
1482                         continue;\r
1483                 }\r
1484 \r
1485                 if (IsDown(bVk)) {\r
1486                         return FALSE;\r
1487                 }\r
1488         } while (++bVk);\r
1489         return TRUE;\r
1490 }\r
1491 \r
1492 BOOL CXkeymacsDll::IsControl()\r
1493 {\r
1494         return CCommands::bC_() || IsDepressedModifier(CCommands::C_, FALSE);\r
1495 }\r
1496 \r
1497 BOOL CXkeymacsDll::IsMeta()\r
1498 {\r
1499         return CCommands::bM_() || IsDepressedModifier(CCommands::MetaAlt, FALSE);\r
1500 }\r
1501 \r
1502 void CXkeymacsDll::AddKillRing(BOOL bNewData)\r
1503 {\r
1504         if (m_nKillRingMax[m_nApplicationID] == 0) {\r
1505                 return;\r
1506         }\r
1507 \r
1508         CClipboardSnap *pSnap = new CClipboardSnap;\r
1509         if( !pSnap ) return;\r
1510 \r
1511         BOOL bCapture = pSnap->Capture();\r
1512         bCapture = pSnap->Capture();    // for "office drawing shape format". Can CClipboardSnap care this problem?\r
1513 \r
1514         if( bCapture ) {\r
1515                 if (bNewData) {\r
1516                         m_oKillRing.AddHead(pSnap);\r
1517                 } else {\r
1518                         if (m_oKillRing.IsEmpty()) {\r
1519                                 m_oKillRing.AddHead(pSnap);\r
1520                         } else {\r
1521                                 for (CClipboardSnap *pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {\r
1522                                         ;\r
1523                                 }\r
1524                                 pParent->SetNext(pSnap);\r
1525                         }\r
1526                 }\r
1527         } else {\r
1528                 delete pSnap;\r
1529                 pSnap = NULL;\r
1530         }\r
1531 \r
1532         m_nKillRing = 0;\r
1533 \r
1534         if (m_nKillRingMax[m_nApplicationID] < m_oKillRing.GetCount()) {\r
1535                 CClipboardSnap *pSnap = m_oKillRing.GetTail();\r
1536                 delete pSnap;\r
1537                 pSnap = NULL;\r
1538                 m_oKillRing.RemoveTail();\r
1539         }\r
1540 }\r
1541 \r
1542 // Return TRUE if there is another data\r
1543 // Return FALSE if there is no more data\r
1544 CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)\r
1545 {\r
1546         if (m_nKillRingMax[m_nApplicationID] == 0) {\r
1547                 return NULL;\r
1548         }\r
1549 \r
1550         if (m_oKillRing.IsEmpty()) {\r
1551                 return NULL;\r
1552         }\r
1553 \r
1554         m_nKillRing %= m_oKillRing.GetCount();\r
1555 \r
1556         if (!bForce) {\r
1557                 CClipboardSnap oCurrentSnap;\r
1558                 oCurrentSnap.Capture();\r
1559 \r
1560                 CClipboardSnap *pKillRing = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));\r
1561                 if (!pKillRing) {\r
1562                         return NULL;\r
1563                 }\r
1564                 for (; pKillRing->GetNext(); pKillRing = pKillRing->GetNext()) {\r
1565                         ;\r
1566                 }\r
1567                 if (*pKillRing != oCurrentSnap) {\r
1568                         return NULL;\r
1569                 }\r
1570         }\r
1571 \r
1572         if (!pSnap) {\r
1573                 pSnap = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));\r
1574         }\r
1575         pSnap->Restore();\r
1576 \r
1577         return pSnap->GetNext();\r
1578 }\r
1579 \r
1580 void CXkeymacsDll::Original(int nCommandType, BYTE bVk, int nOriginal)\r
1581 {\r
1582         nCommandType &= ~SHIFT;\r
1583 \r
1584         switch (bVk) {\r
1585         case VK_CONTROL:\r
1586                 bVk = VK_LCONTROL;\r
1587                 break;\r
1588         case VK_MENU:\r
1589                 bVk = VK_LMENU;\r
1590                 break;\r
1591         case VK_SHIFT:\r
1592                 bVk = VK_LSHIFT;\r
1593                 break;\r
1594         default:\r
1595                 break;\r
1596         }\r
1597 \r
1598         m_nOriginal[nCommandType][bVk] += nOriginal;\r
1599 }\r
1600 \r
1601 int CXkeymacsDll::Original(int nCommandType, BYTE bVk)\r
1602 {\r
1603         nCommandType &= ~SHIFT;\r
1604 \r
1605         switch (bVk) {\r
1606         case VK_CONTROL:\r
1607                 bVk = VK_LCONTROL;\r
1608                 break;\r
1609         case VK_MENU:\r
1610                 bVk = VK_LMENU;\r
1611                 break;\r
1612         case VK_SHIFT:\r
1613                 bVk = VK_LSHIFT;\r
1614                 break;\r
1615         default:\r
1616                 break;\r
1617         }\r
1618 \r
1619         return m_nOriginal[nCommandType][bVk];\r
1620 }\r
1621 \r
1622 void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)\r
1623 {\r
1624         m_nKillRing += nKillRing;\r
1625 }\r
1626 \r
1627 // move CCommands\r
1628 CString CXkeymacsData::GetCommandName(int nCommandID)\r
1629 {\r
1630         CString szCommandName(Commands[nCommandID].szCommandName);\r
1631         return szCommandName;\r
1632 }\r
1633 \r
1634 // move CCommands\r
1635 int CXkeymacsData::GetDefaultCommandType(int nCommandID, int nIndex)\r
1636 {\r
1637         if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID\r
1638          || nIndex < 0 || MAX_KEY_BIND <= nIndex) {\r
1639                 ASSERT(0);\r
1640                 return NONE;\r
1641         }\r
1642 \r
1643         int nCommandType        = Commands[nCommandID].keybind[nIndex].nCommandType;\r
1644         int bVk                         = Commands[nCommandID].keybind[nIndex].bVk;\r
1645 \r
1646         if (m_b106Keyboard) {\r
1647                 if (nCommandType & SHIFT) {     // Shift\r
1648                         switch (bVk) {\r
1649                         case '2':\r
1650                         case '6':\r
1651                         case 0xBA:              // VK_OEM_1             Used for miscellaneous characters; it can vary by keyboard. \r
1652                                                         //                              Windows 2000/XP: For the US standard keyboard, the ';:' key\r
1653                                 nCommandType &= ~SHIFT;\r
1654                                 break;\r
1655                         default:\r
1656                                 break;\r
1657                         }\r
1658                 } else {                                        // Normal\r
1659                         switch (bVk) {\r
1660                         case 0xBB:              // VK_OEM_PLUS  Windows 2000/XP: For any country/region, the '+' key\r
1661                         case 0xC0:              // VK_OEM_3             Used for miscellaneous characters; it can vary by keyboard. \r
1662                                                         //                              Windows 2000/XP: For the US standard keyboard, the '`~' key\r
1663                         case 0xDE:              // VK_OEM_7             Used for miscellaneous characters; it can vary by keyboard. \r
1664                                                         //                              Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key\r
1665                                 nCommandType |= SHIFT;\r
1666                                 break;\r
1667                         default:\r
1668                                 break;\r
1669                         }\r
1670                 }\r
1671         }\r
1672 \r
1673         return nCommandType;\r
1674 }\r
1675 \r
1676 // move CCommands\r
1677 int CXkeymacsData::GetDefaultCommandKey(int nCommandID, int nIndex)\r
1678 {\r
1679         if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID\r
1680          || nIndex < 0 || MAX_KEY_BIND <= nIndex) {\r
1681                 ASSERT(0);\r
1682                 return 0;\r
1683         }\r
1684 \r
1685         int nCommandType        = Commands[nCommandID].keybind[nIndex].nCommandType;\r
1686         int bVk                         = Commands[nCommandID].keybind[nIndex].bVk;\r
1687 \r
1688         if (m_b106Keyboard) {\r
1689                 if (nCommandType & SHIFT) {     // Shift\r
1690                         switch (bVk) {\r
1691                         case '0':\r
1692                                 bVk = '9';\r
1693                                 break;\r
1694                         case '2':\r
1695                                 bVk = 0xC0;     // VK_OEM_3             Used for miscellaneous characters; it can vary by keyboard. \r
1696                                                         //                              Windows 2000/XP: For the US standard keyboard, the '`~' key\r
1697                                 break;\r
1698                         case '6':\r
1699                                 bVk = 0xDE;     // VK_OEM_7             Used for miscellaneous characters; it can vary by keyboard. \r
1700                                                         //                              Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key\r
1701                                 break;\r
1702                         case '7':\r
1703                                 bVk = '6';\r
1704                                 break;\r
1705                         case '8':\r
1706                                 bVk = 0xBA;     // VK_OEM_1             Used for miscellaneous characters; it can vary by keyboard. \r
1707                                                         //                              Windows 2000/XP: For the US standard keyboard, the ';:' key\r
1708                                 break;\r
1709                         case '9':\r
1710                                 bVk = '8';\r
1711                                 break;\r
1712                         case 0xBD:              // VK_OEM_MINUS Windows 2000/XP: For any country/region, the '-' key\r
1713                                 bVk = 0xE2;     // VK_OEM_102   Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard\r
1714                                 break;\r
1715                         case 0xC0:\r
1716                                 bVk = 0xDE;     // VK_OEM_7             Used for miscellaneous characters; it can vary by keyboard. \r
1717                                                         //                              Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key\r
1718                                 break;\r
1719                         case 0xDE:              // VK_OEM_7             Used for miscellaneous characters; it can vary by keyboard. \r
1720                                                         //                              Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key\r
1721                                 bVk = '2';\r
1722                                 break;\r
1723                         default:\r
1724                                 break;\r
1725                         }\r
1726                 } else {                                        // Normal\r
1727                         switch (bVk) {\r
1728                         case 0xBA:              // VK_OEM_1             Used for miscellaneous characters; it can vary by keyboard. \r
1729                                                         //                              Windows 2000/XP: For the US standard keyboard, the ';:' key\r
1730                                 bVk = 0xBB;     // VK_OEM_PLUS  Windows 2000/XP: For any country/region, the '+' key\r
1731                                 break;\r
1732                         case 0xBB:              // VK_OEM_PLUS  Windows 2000/XP: For any country/region, the '+' key\r
1733                                 bVk = 0xBD;     // VK_OEM_MINUS Windows 2000/XP: For any country/region, the '-' key\r
1734                                 break;\r
1735                         case 0xDE:              // VK_OEM_7             Used for miscellaneous characters; it can vary by keyboard. \r
1736                                                         //                              Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key\r
1737                                 bVk = '7';\r
1738                                 break;\r
1739                         default:\r
1740                                 break;\r
1741                         }\r
1742                 }\r
1743         }\r
1744 \r
1745         return bVk;\r
1746 }\r
1747 \r
1748 // move CCommands\r
1749 int CXkeymacsData::GetDefaultControlID(int nCommandID, int nIndex)\r
1750 {\r
1751         if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID\r
1752          || nIndex < 0 || MAX_KEY_BIND <= nIndex) {\r
1753                 ASSERT(0);\r
1754                 return 0;\r
1755         }\r
1756 \r
1757         return Commands[nCommandID].keybind[nIndex].nControlID;\r
1758 }\r
1759 \r
1760 // nobody use\r
1761 int CXkeymacsDll::GetMickey(int nDifferential, int nThreshold1, int nThreshold2, int nAcceleration, int nSpeed)\r
1762 {\r
1763         nDifferential = nDifferential * 10 / nSpeed;\r
1764 \r
1765         switch (nAcceleration) {\r
1766         case 2:\r
1767                 if (nThreshold2 < fabs((double)(nDifferential / 4))) {\r
1768                         nDifferential /= 4;\r
1769                         break;\r
1770                 }\r
1771                 // Do NOT write break; here.\r
1772         case 1:\r
1773                 if (nThreshold1 < fabs((double)(nDifferential / 2))) {\r
1774                         nDifferential /= 2;\r
1775                 }\r
1776                 break;\r
1777         case 0:\r
1778                 break;\r
1779         default:\r
1780                 ASSERT(0);\r
1781                 break;\r
1782         }\r
1783 \r
1784         return nDifferential;\r
1785 }\r
1786 \r
1787 \r
1788 int CXkeymacsData::GetSettingStyle()\r
1789 {\r
1790         return m_nSettingStyle;\r
1791 }\r
1792 \r
1793 void CXkeymacsData::SetSettingStyle(int nSettingStyle)\r
1794 {\r
1795         m_nSettingStyle = nSettingStyle;\r
1796 }\r
1797 \r
1798 void CXkeymacsDll::SetSettingStyle(int nApplicationID, int nSettingStyle)\r
1799 {\r
1800         m_nSettingStyle[nApplicationID] = nSettingStyle;\r
1801 }\r
1802 \r
1803 int CXkeymacsData::GetCategoryID(int nCommandID)\r
1804 {\r
1805         return Commands[nCommandID].nCategoryID;\r
1806 }\r
1807 \r
1808 void CXkeymacsData::SetIgnoreUndefinedMetaCtrl(BOOL bIgnoreUndefinedMetaCtrl)\r
1809 {\r
1810         m_bIgnoreUndefinedMetaCtrl = bIgnoreUndefinedMetaCtrl;\r
1811 }\r
1812 \r
1813 BOOL CXkeymacsData::GetIgnoreUndefinedMetaCtrl()\r
1814 {\r
1815         return m_bIgnoreUndefinedMetaCtrl;\r
1816 }\r
1817 \r
1818 void CXkeymacsDll::SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl)\r
1819 {\r
1820         m_bIgnoreUndefinedMetaCtrl[nApplicationID] = bIgnoreUndefinedMetaCtrl;\r
1821 }\r
1822 \r
1823 void CXkeymacsData::SetIgnoreUndefinedC_x(BOOL bIgnoreUndefinedC_x)\r
1824 {\r
1825         m_bIgnoreUndefinedC_x = bIgnoreUndefinedC_x;\r
1826 }\r
1827 \r
1828 BOOL CXkeymacsData::GetIgnoreUndefinedC_x()\r
1829 {\r
1830         return m_bIgnoreUndefinedC_x;\r
1831 }\r
1832 \r
1833 void CXkeymacsDll::SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x)\r
1834 {\r
1835         m_bIgnoreUndefinedC_x[nApplicationID] = bIgnoreUndefinedC_x;\r
1836 }\r
1837 \r
1838 void CXkeymacsData::SetEnableCUA(BOOL bEnableCUA)\r
1839 {\r
1840         m_bEnableCUA = bEnableCUA;\r
1841 }\r
1842 \r
1843 BOOL CXkeymacsData::GetEnableCUA()\r
1844 {\r
1845         return m_bEnableCUA;\r
1846 }\r
1847 \r
1848 void CXkeymacsDll::SetEnableCUA(int nApplicationID, BOOL bEnableCUA)\r
1849 {\r
1850         m_bEnableCUA[nApplicationID] = bEnableCUA;\r
1851 }\r
1852 \r
1853 BOOL CXkeymacsDll::GetEnableCUA()\r
1854 {\r
1855         return m_bEnableCUA[m_nApplicationID];\r
1856 }\r
1857 \r
1858 void CXkeymacsData::SetUseDialogSetting(BOOL bUseDialogSetting)\r
1859 {\r
1860         m_bUseDialogSetting = bUseDialogSetting;\r
1861 }\r
1862 \r
1863 BOOL CXkeymacsData::GetUseDialogSetting()\r
1864 {\r
1865         return m_bUseDialogSetting;\r
1866 }\r
1867 \r
1868 int CXkeymacsData::GetDescriptionID(int nCommandID)\r
1869 {\r
1870         return Commands[nCommandID].nDescriptionID;\r
1871 }\r
1872 \r
1873 int CXkeymacsData::GetToolTipID(int nCommandID)\r
1874 {\r
1875         return Commands[nCommandID].nToolTipID;\r
1876 }\r
1877 \r
1878 void CXkeymacsDll::DefiningMacro(BOOL bDefiningMacro)\r
1879 {\r
1880         m_bDefiningMacro = bDefiningMacro;\r
1881 \r
1882         if (bDefiningMacro) {   // start-kbd-macro\r
1883                 if (CCommands::bC_u()) {\r
1884                         ReleaseKey(VK_SHIFT);\r
1885                         CallMacro();\r
1886                 }\r
1887         } else {                                // end-kbd-macro\r
1888                 while (!m_Macro.IsEmpty()) {\r
1889                         KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetTail();\r
1890                         if (pKbdMacro->lParam & BEING_RELEASED) {\r
1891                                 break;\r
1892                         } else {\r
1893                                 m_Macro.RemoveTail();\r
1894                                 delete pKbdMacro;\r
1895                                 pKbdMacro = NULL;\r
1896                         }\r
1897                 }\r
1898 \r
1899 //              CUtils::Log(_T("Macro MemMap: start"));\r
1900                 if (!m_Macro.IsEmpty()) {\r
1901                         static HANDLE hMacro = NULL;\r
1902                         if (!hMacro) {\r
1903                                 hMacro = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x3000, _T("macro"));\r
1904                         }\r
1905                         if (hMacro) {\r
1906 //                              CUtils::Log(_T("Macro MemMap: 1"));\r
1907                                 PVOID pView = MapViewOfFile(hMacro, FILE_MAP_ALL_ACCESS, 0, 0, 0);\r
1908 //                              CUtils::Log(_T("Macro MemMap: 2"));\r
1909                                 if (pView) {\r
1910 //                                      CUtils::Log(_T("Macro MemMap: 2.5"));\r
1911                                         for (int i = 0; i < m_Macro.GetCount(); ++i) {\r
1912 //                                              CUtils::Log(_T("Macro MemMap: 3-1 %d"), i);\r
1913                                                 KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetAt(m_Macro.FindIndex(i));\r
1914 //                                              CUtils::Log(_T("Macro MemMap: 3-2 %d"), i);\r
1915                                                 memcpy((LPTSTR) pView + i * sizeof(KbdMacro), pKbdMacro, sizeof(KbdMacro));\r
1916 //                                              CUtils::Log(_T("Macro MemMap: 3-3 %d"), i);\r
1917                                         }\r
1918 //                                      CUtils::Log(_T("Macro MemMap: 4"));\r
1919                                         UnmapViewOfFile(pView);\r
1920 //                                      CUtils::Log(_T("Macro MemMap: 5"));\r
1921                                 } else {\r
1922 //                                      CUtils::Log(_T("Macro MemMpa: error: %d"), GetLastError());\r
1923                                 }\r
1924                         } else {\r
1925 //                              CUtils::Log(_T("Macro MemMap: 6"));\r
1926                                 ASSERT(0);\r
1927                         }\r
1928                 }\r
1929         }\r
1930 }\r
1931 \r
1932 BOOL CXkeymacsDll::DefiningMacro()\r
1933 {\r
1934         return m_bDefiningMacro;\r
1935 }\r
1936 \r
1937 /**/ \r
1938 void CXkeymacsDll::CallMacro()\r
1939 {\r
1940         BOOL bIsCtrlDown = IsDown(VK_CONTROL);\r
1941         if (bIsCtrlDown) {\r
1942                 ReleaseKey(VK_CONTROL);\r
1943         }\r
1944         BOOL bIsAltDown = IsDown(VK_MENU);\r
1945         if (bIsAltDown) {\r
1946                 ReleaseKey(VK_MENU);\r
1947         }\r
1948         BOOL bIsShiftDown = IsDown(VK_SHIFT);\r
1949         if (bIsShiftDown) {\r
1950                 ReleaseKey(VK_SHIFT);\r
1951         }\r
1952 \r
1953         for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
1954                 KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetNext(pos);\r
1955                 if (pKbdMacro->lParam & BEING_RELEASED) {\r
1956                         ReleaseKey((BYTE)pKbdMacro->wParam);\r
1957                 } else {\r
1958                         DepressKey((BYTE)pKbdMacro->wParam, pKbdMacro->bOriginal);\r
1959                 }\r
1960         }\r
1961 \r
1962         if (bIsCtrlDown) {\r
1963                 DepressKey(VK_CONTROL);\r
1964         }\r
1965         if (bIsAltDown) {\r
1966                 DepressKey(VK_MENU);\r
1967         }\r
1968         if (bIsShiftDown) {\r
1969                 DepressKey(VK_SHIFT);\r
1970         }\r
1971 }\r
1972 \r
1973 /*\r
1974 void CXkeymacsDll::CallMacro()  // for debug\r
1975 {\r
1976         CString sz;\r
1977         for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
1978                 KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetNext(pos);\r
1979                 if (pKbdMacro->lParam & BEING_RELEASED) {\r
1980                         CString t;\r
1981                         t.Format(_T("0x%xu "), pKbdMacro->wParam);\r
1982                         sz += t;\r
1983                 } else {\r
1984                         CString t;\r
1985                         t.Format(_T("0x%xd "), pKbdMacro->wParam);\r
1986                         sz += t;\r
1987                 }\r
1988         }\r
1989 //      CUtils::Log(sz);\r
1990 }\r
1991 */\r
1992 \r
1993 void CXkeymacsData::Set106Keyboard(BOOL b106Keyboard)\r
1994 {\r
1995         m_b106Keyboard = b106Keyboard;\r
1996 }\r
1997 \r
1998 BOOL CXkeymacsData::Is106Keyboard()\r
1999 {\r
2000         return m_b106Keyboard;\r
2001 }\r
2002 \r
2003 int CXkeymacsDll::IsPassThrough(BYTE nKey)\r
2004 {\r
2005         BYTE bVk = 0;\r
2006         do {\r
2007                 if (IsDown(bVk)\r
2008                  && (Commands[m_nCommandID[m_nApplicationID][NONE][bVk]].fCommand == CCommands::PassThrough)) {\r
2009                         if (bVk == nKey) {\r
2010                                 return GOTO_HOOK;\r
2011                         }\r
2012 \r
2013                         return GOTO_DO_NOTHING;\r
2014                 }\r
2015         } while (++bVk);\r
2016         return CONTINUE;\r
2017 }\r
2018 \r
2019 void CXkeymacsDll::SetKeyboardHookFlag()\r
2020 {\r
2021         SetKeyboardHookFlag(m_bHook);\r
2022 }\r
2023 \r
2024 void CXkeymacsDll::SetFunctionKey(int nFunctionID, int nApplicationID, int nCommandType, int nKey)\r
2025 {\r
2026         if (nApplicationID      < 0 || MAX_APP                  <= nApplicationID\r
2027          || nCommandType        < 0 || MAX_COMMAND_TYPE <= nCommandType\r
2028          || nKey                        < 0 || MAX_KEY                  <= nKey) {\r
2029                 return;\r
2030         }\r
2031 \r
2032         m_nFunctionID[nApplicationID][nCommandType][nKey] = nFunctionID;\r
2033 }\r
2034 \r
2035 void CXkeymacsDll::ClearFunctionDefinition()\r
2036 {\r
2037         memset(m_nFunctionID, -1, sizeof(m_nFunctionID));\r
2038         memset(m_szFunctionDefinition, 0, sizeof(m_szFunctionDefinition));\r
2039 }\r
2040 \r
2041 void CXkeymacsDll::SetFunctionDefinition(int nFunctionID, CString szDefinition)\r
2042 {\r
2043         if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID) {\r
2044                 return;\r
2045         }\r
2046 \r
2047         memset(m_szFunctionDefinition[nFunctionID], 0, sizeof(m_szFunctionDefinition[nFunctionID]));\r
2048         _stprintf(m_szFunctionDefinition[nFunctionID], _T("%s"), szDefinition);\r
2049 \r
2050         return;\r
2051 \r
2052 }\r
2053 \r
2054 // call an original command which is defined in dot.xkeymacs\r
2055 void CXkeymacsDll::CallFunction(int nFunctionID)\r
2056 {\r
2057         CArray<KeyBind, KeyBind> keybinds;\r
2058 \r
2059         if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID || !_tcslen(m_szFunctionDefinition[nFunctionID])) {\r
2060                 return;\r
2061         }\r
2062 \r
2063         BOOL bIsCtrlDown = CXkeymacsDll::IsDown(VK_CONTROL);\r
2064         BOOL bIsAltDown = CXkeymacsDll::IsDown(VK_MENU);\r
2065         BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
2066 \r
2067         if (m_szFunctionDefinition[nFunctionID][0] == _T('"') && m_szFunctionDefinition[nFunctionID][_tcslen(m_szFunctionDefinition[nFunctionID]) - 1] == _T('"')) {\r
2068                 for (unsigned int i = 1; i < _tcslen(m_szFunctionDefinition[nFunctionID]) - 1; ++i) {   // skip '"'\r
2069                         keybinds.Add(ParseKey(nFunctionID, i));\r
2070                 }\r
2071         } else if (m_szFunctionDefinition[nFunctionID][0] == _T('[') && m_szFunctionDefinition[nFunctionID][_tcslen(m_szFunctionDefinition[nFunctionID]) - 1] == _T(']')) {\r
2072                 for (unsigned int i = 1; i < _tcslen(m_szFunctionDefinition[nFunctionID]) - 1; ++i) {   // skip '[' and ']'\r
2073                         if (m_szFunctionDefinition[nFunctionID][i] == _T('?')) {        // [?f ?o ?o]\r
2074                                 ++i;\r
2075                                 keybinds.Add(ParseKey(nFunctionID, i));\r
2076                         } else {                                                                                                // [ControlCharacter]\r
2077                                 for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
2078                                         if (!_tcsncmp(m_szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
2079                                                 KeyBind keybind = {NONE, ControlCharacters[nKeyID].bVk};\r
2080                                                 keybinds.Add(keybind);\r
2081                                                 i += _tcslen(ControlCharacters[nKeyID].name);\r
2082                                                 break;\r
2083                                         }\r
2084                                 }\r
2085                         }\r
2086                 }\r
2087         } else {\r
2088                 return;\r
2089         }\r
2090 \r
2091         BOOL bM_x = FALSE;\r
2092         TCHAR szPath[MAX_PATH] = {'\0'};\r
2093         unsigned int index = 0;\r
2094         BOOL bInitialized = FALSE;\r
2095 \r
2096         for (int i = 0; i < keybinds.GetSize(); ++i) {\r
2097                 const int nCommandType = keybinds.GetAt(i).nCommandType;\r
2098                 const BYTE bVk = keybinds.GetAt(i).bVk;\r
2099 \r
2100                 if (nCommandType < MAX_COMMAND_TYPE && Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand) {\r
2101                         if (Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand == CCommands::ExecuteExtendedCommand) {\r
2102                                 bM_x = TRUE;\r
2103                         } else if (!bInitialized) {\r
2104                                 if (bIsCtrlDown) {\r
2105                                         CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
2106                                         ReleaseKey(VK_CONTROL);\r
2107                                 }\r
2108 \r
2109                                 if (bIsAltDown) {\r
2110                                         ReleaseKey(VK_MENU);\r
2111                                 }\r
2112 \r
2113                                 if (bIsShiftDown) {\r
2114                                         ReleaseKey(VK_SHIFT);\r
2115                                 }\r
2116 \r
2117                                 bInitialized = TRUE;\r
2118                         }\r
2119 //                      CUtils::Log("CallFunction: Command Name: %s", Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].szCommandName);\r
2120                         while (Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand() == GOTO_RECURSIVE) {\r
2121                                 ;\r
2122                         }\r
2123                 } else if (bM_x) {\r
2124                         if (bVk == VK_RETURN) {\r
2125                                 InvokeM_x(szPath);\r
2126                         } else {\r
2127                                 for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
2128                                         if (bVk != 0 && a2v(nAscii) == bVk && ((nCommandType & SHIFT) != 0) == IsShift(nAscii)) {\r
2129 //                                              CUtils::Log("M-x: %#X (%c), %#X (%c)", bVk, bVk, nAscii, nAscii);\r
2130                                                 szPath[index++] = nAscii;\r
2131                                                 break;\r
2132                                         }\r
2133                                 }\r
2134                         }\r
2135                 } else {\r
2136                         if (!bInitialized) {\r
2137                                 if (bIsCtrlDown) {\r
2138                                         CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
2139                                         ReleaseKey(VK_CONTROL);\r
2140                                 }\r
2141 \r
2142                                 if (bIsAltDown) {\r
2143                                         ReleaseKey(VK_MENU);\r
2144                                 }\r
2145 \r
2146                                 if (bIsShiftDown) {\r
2147                                         ReleaseKey(VK_SHIFT);\r
2148                                 }\r
2149 \r
2150                                 bInitialized = TRUE;\r
2151                         }\r
2152                         if (nCommandType & WIN_WIN) {\r
2153                                 DepressKey(VK_LWIN);\r
2154                         }\r
2155                         if (nCommandType & WIN_CTRL) {\r
2156                                 DepressKey(VK_CONTROL);\r
2157                         }\r
2158                         if (nCommandType & WIN_ALT) {\r
2159                                 DepressKey(VK_MENU);\r
2160                         }\r
2161                         if (nCommandType & SHIFT) {\r
2162                                 DepressKey(VK_SHIFT);\r
2163                         }\r
2164 \r
2165                         Kdu(bVk);\r
2166 \r
2167                         if (nCommandType & SHIFT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & SHIFT))) {\r
2168                                 ReleaseKey(VK_SHIFT);\r
2169                         }\r
2170                         if (nCommandType & WIN_ALT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_ALT))) {\r
2171                                 ReleaseKey(VK_MENU);\r
2172                         }\r
2173                         if (nCommandType & WIN_CTRL && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_CTRL))) {\r
2174                                 ReleaseKey(VK_CONTROL);\r
2175                         }\r
2176                         if (nCommandType & WIN_WIN && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_WIN))) {\r
2177                                 ReleaseKey(VK_LWIN);\r
2178                         }\r
2179                 }\r
2180         }\r
2181 \r
2182         keybinds.RemoveAll();\r
2183 \r
2184         if (bInitialized) {\r
2185                 // If these lines are invoked at M-x, a window transition does not work well.\r
2186 \r
2187                 if (bIsShiftDown) {\r
2188                         DepressKey(VK_SHIFT);\r
2189                 }\r
2190 \r
2191                 if (bIsAltDown) {\r
2192                         DepressKey(VK_MENU);\r
2193                 }\r
2194 \r
2195                 if (bIsCtrlDown) {\r
2196                         DepressKey(VK_CONTROL);\r
2197                         CUtils::UpdateKeyboardState(VK_CONTROL, 1);\r
2198                 }\r
2199         }\r
2200         return;\r
2201 }\r
2202 \r
2203 KeyBind CXkeymacsDll::ParseKey(const int nFunctionID, unsigned int &i)\r
2204 {\r
2205         KeyBind keybind = {NONE};\r
2206 \r
2207         if (m_szFunctionDefinition[nFunctionID][i] == _T('\\')) {\r
2208                 ++i;\r
2209                 BOOL bFound = FALSE;\r
2210                 do {\r
2211                         bFound = FALSE;\r
2212                         for (int ModifierID = 0; ModifierID < sizeof(Modifiers) / sizeof(Modifiers[0]); ++ModifierID) {\r
2213                                 if (!_tcsncmp(m_szFunctionDefinition[nFunctionID] + i, Modifiers[ModifierID].name, _tcslen(Modifiers[ModifierID].name))\r
2214                                  && _tcslen(Modifiers[ModifierID].name) < _tcslen(m_szFunctionDefinition[nFunctionID] + i)) {\r
2215                                         keybind.nCommandType |= Modifiers[ModifierID].id;\r
2216                                         i+= _tcslen(Modifiers[ModifierID].name);\r
2217                                         bFound = TRUE;\r
2218                                 }\r
2219                         }\r
2220                 } while (bFound);\r
2221         }\r
2222         if (IsShift(m_szFunctionDefinition[nFunctionID][i]) && !(keybind.nCommandType & (WIN_CTRL | WIN_ALT | WIN_WIN))) {\r
2223                 keybind.nCommandType |= SHIFT;\r
2224         }\r
2225 \r
2226         for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
2227                 if (!_tcsncmp(m_szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
2228                         i += _tcslen(ControlCharacters[nKeyID].name);\r
2229                         break;\r
2230                 }\r
2231         }\r
2232         if (nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0])) {\r
2233                 keybind.bVk = ControlCharacters[nKeyID].bVk;\r
2234         } else {\r
2235                 keybind.bVk = a2v(m_szFunctionDefinition[nFunctionID][i]);\r
2236         }\r
2237 \r
2238         return keybind;\r
2239 }\r
2240 \r
2241 BOOL CXkeymacsDll::IsShift(TCHAR nAscii)\r
2242 {\r
2243         switch (nAscii) {\r
2244         case _T(' '):\r
2245                 return FALSE;\r
2246         case _T('!'):\r
2247         case _T('"'):\r
2248         case _T('#'):\r
2249         case _T('$'):\r
2250         case _T('%'):\r
2251         case _T('&'):\r
2252                 return TRUE;\r
2253         case _T('\''):\r
2254                 return CXkeymacsData::Is106Keyboard();\r
2255         case _T('('):\r
2256         case _T(')'):\r
2257         case _T('*'):\r
2258         case _T('+'):\r
2259                 return TRUE;\r
2260         case _T(','):\r
2261         case _T('-'):\r
2262         case _T('.'):\r
2263         case _T('/'):\r
2264         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
2265                 return FALSE;\r
2266         case _T(':'):\r
2267                 return !CXkeymacsData::Is106Keyboard();\r
2268         case _T(';'):\r
2269                 return FALSE;\r
2270         case _T('<'):\r
2271                 return TRUE;\r
2272         case _T('='):\r
2273                 return CXkeymacsData::Is106Keyboard();\r
2274         case _T('>'):\r
2275         case _T('?'):\r
2276                 return TRUE;\r
2277         case _T('@'):\r
2278                 return !CXkeymacsData::Is106Keyboard();\r
2279         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
2280         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
2281         case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
2282                 return TRUE;\r
2283         case _T('['):\r
2284         case _T('\\'):\r
2285         case _T(']'):\r
2286                 return FALSE;\r
2287         case _T('^'):\r
2288                 return !CXkeymacsData::Is106Keyboard();\r
2289         case _T('_'):\r
2290                 return TRUE;\r
2291         case _T('`'):\r
2292                 return CXkeymacsData::Is106Keyboard();\r
2293         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
2294         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
2295         case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
2296                 return FALSE;\r
2297         case _T('{'):\r
2298         case _T('|'):\r
2299         case _T('}'):\r
2300         case _T('~'):\r
2301                 return TRUE;\r
2302         default:\r
2303                 return FALSE;\r
2304         }\r
2305 }\r
2306 \r
2307 BYTE CXkeymacsDll::a2v(TCHAR nAscii)\r
2308 {\r
2309         switch (nAscii) {\r
2310         case _T(' '):\r
2311                 return VK_SPACE;\r
2312         case _T('!'):\r
2313                 return '1';\r
2314         case _T('"'):\r
2315                 return CXkeymacsData::Is106Keyboard() ? '2' : (BYTE) 0xde;      // VK_OEM_7\r
2316         case _T('#'):\r
2317                 return '3';\r
2318         case _T('$'):\r
2319                 return '4';\r
2320         case _T('%'):\r
2321                 return '5';\r
2322         case _T('&'):\r
2323                 return CXkeymacsData::Is106Keyboard() ? '6' : '7';\r
2324         case _T('\''):\r
2325                 return CXkeymacsData::Is106Keyboard() ? '7' : (BYTE) 0xde;      // VK_OEM_7\r
2326         case _T('('):\r
2327                 return CXkeymacsData::Is106Keyboard() ? '8' : '9';\r
2328         case _T(')'):\r
2329                 return CXkeymacsData::Is106Keyboard() ? '9' : '0';\r
2330         case _T('*'):\r
2331                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xba : '8';      // VK_OEM_1\r
2332         case _T('+'):\r
2333                 return 0xbb;    // VK_OEM_PLUS\r
2334         case _T(','):\r
2335                 return 0xbc;    // VK_OEM_COMMA\r
2336         case _T('-'):\r
2337                 return 0xbd;    // VK_OEM_MINUS\r
2338         case _T('.'):\r
2339                 return 0xbe;    // VK_OEM_PERIOD\r
2340         case _T('/'):\r
2341                 return 0xbf;    // VK_OEM_2\r
2342         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
2343                 return nAscii;\r
2344         case _T(':'):\r
2345                 return 0xba;    // VK_OEM_1\r
2346         case _T(';'):\r
2347                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xbb : (BYTE) 0xba;      // VK_OEM_PLUS  VK_OEM_1\r
2348         case _T('<'):\r
2349                 return 0xbc;    // VK_OEM_COMMA\r
2350         case _T('='):\r
2351                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xbd : (BYTE) 0xbb;      // VK_OEM_MINUS VK_OEM_PLUS\r
2352         case _T('>'):\r
2353                 return 0xbe;    // VK_OEM_PERIOD\r
2354         case _T('?'):\r
2355                 return 0xbf;    // VK_OEM_2\r
2356         case _T('@'):\r
2357                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xc0 : '2';\r
2358         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
2359         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
2360         case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
2361                 return nAscii;\r
2362         case _T('['):\r
2363                 return 0xdb;    // VK_OEM_4\r
2364         case _T('\\'):\r
2365                 return 0xdc;    // VK_OEM_5\r
2366         case _T(']'):\r
2367                 return 0xdd;    // VK_OEM_6\r
2368         case _T('^'):\r
2369                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xde : '6';      // VK_OEM_7\r
2370         case _T('_'):\r
2371                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xe2 : (BYTE) 0xbd;      // VK_OEM_102   VK_OEM_MINUS\r
2372         case _T('`'):\r
2373                 return 0xc0;    // VK_OEM_3\r
2374         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
2375         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
2376         case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
2377                 return (BYTE) (nAscii - (_T('a') - _T('A')));\r
2378         case _T('{'):\r
2379                 return 0xdb;    // VK_OEM_4\r
2380         case _T('|'):\r
2381                 return 0xdc;    // VK_OEM_5\r
2382         case _T('}'):\r
2383                 return 0xdd;    // VK_OEM_6\r
2384         case _T('~'):\r
2385                 return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xde : (BYTE) 0xc0;      // VK_OEM_7     VK_OEM_3\r
2386         default:\r
2387                 return 0;\r
2388         }\r
2389 }\r
2390 \r
2391 void CXkeymacsDll::DeleteAllShell_NotifyIcon()\r
2392 {\r
2393         for (int icon = 0; icon < MAX_ICON_TYPE; ++icon) {\r
2394                 DeleteShell_NotifyIcon((ICON_TYPE)icon);\r
2395         }\r
2396 }\r
2397 \r
2398 void CXkeymacsDll::AddAllShell_NotifyIcon()\r
2399 {\r
2400         for (int icon = 0; icon < MAX_ICON_TYPE; ++icon) {\r
2401                 AddShell_NotifyIcon((ICON_TYPE)icon);\r
2402         }\r
2403 }\r
2404 \r
2405 void CXkeymacsData::SetWindowText(LPCTSTR lpszWindowText)\r
2406 {\r
2407         m_nWindowTextType = CUtils::GetWindowTextType(lpszWindowText);\r
2408         if (m_nWindowTextType == IDS_WINDOW_TEXT_IGNORE) {\r
2409                 m_strWindowText = _T('*');\r
2410         } else {\r
2411                 m_strWindowText.Format(lpszWindowText);\r
2412         }\r
2413 }\r
2414 \r
2415 CString CXkeymacsData::GetWindowText()\r
2416 {\r
2417         return m_strWindowText;\r
2418 }\r
2419 \r
2420 void CXkeymacsData::SetWindowTextType(int nWindowTextType)\r
2421 {\r
2422         m_nWindowTextType = nWindowTextType;\r
2423 }\r
2424 \r
2425 int CXkeymacsData::GetWindowTextType()\r
2426 {\r
2427         return m_nWindowTextType;\r
2428 }\r
2429 \r
2430 BOOL CXkeymacsDll::IsMatchWindowText(CString szWindowText)\r
2431 {\r
2432         BOOL bIsMatchWindowText = TRUE;\r
2433 \r
2434         TCHAR szCurrentWindowText[0x100] = {'\0'};\r
2435         GetWindowText(GetForegroundWindow(), szCurrentWindowText, sizeof(szCurrentWindowText));\r
2436 \r
2437         switch (CUtils::GetWindowTextType(szWindowText)) {\r
2438         case IDS_WINDOW_TEXT_MATCH:                                                             // *foo*\r
2439                 szWindowText.Delete(0);                                                         // Delete first '*'\r
2440                 szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
2441                 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText);\r
2442                 break;\r
2443         case IDS_WINDOW_TEXT_MATCH_FORWARD:                                             // foo*\r
2444                 szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
2445                 bIsMatchWindowText = 0 == CString(szCurrentWindowText).Find(szWindowText);\r
2446                 break;\r
2447         case IDS_WINDOW_TEXT_MATCH_BACKWARD:                                    // *foo\r
2448                 szWindowText.Delete(0);                                                         // Delete first '*'\r
2449                 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText, CString(szCurrentWindowText).GetLength() - szWindowText.GetLength());\r
2450                 break;\r
2451         case IDS_WINDOW_TEXT_MATCH_FULL:                                                // foo\r
2452                 bIsMatchWindowText = szWindowText == CString(szCurrentWindowText);\r
2453                 break;\r
2454         case IDS_WINDOW_TEXT_IGNORE:                                                    // *\r
2455                 bIsMatchWindowText = TRUE;\r
2456                 break;\r
2457         default:\r
2458                 ASSERT(0);\r
2459                 break;\r
2460         }\r
2461 \r
2462 //      CUtils::Log(_T("IsMatchWindowText: %d, _%s_, _%s_"), bIsMatchWindowText, szCurrentWindowText, szWindowText);\r
2463         return bIsMatchWindowText;\r
2464 }\r
2465 \r
2466 void CXkeymacsDll::SetAccelerate(int nAccelerate)\r
2467 {\r
2468         m_nAccelerate = nAccelerate;\r
2469 }\r
2470 \r
2471 int CXkeymacsDll::GetAccelerate()\r
2472 {\r
2473         return m_nAccelerate;\r
2474 }\r
2475 \r
2476 void CXkeymacsDll::SetKeyboardSpeed(int nKeyboardSpeed)\r
2477 {\r
2478         m_nKeyboardSpeed = nKeyboardSpeed;\r
2479 }\r
2480 \r
2481 unsigned int CXkeymacsDll::GetMaxKeyInterval()\r
2482 {\r
2483         // m_nKeyboardSpeed == 0:       slowest repeat rate; approximately  2 characters per second\r
2484         // m_nKeyboardSpeed == 31:      fastest repeat rate; approximately 30 characters per second\r
2485         // 47 ms is max on my machine w/ KeyboardSpeed 31.\r
2486         // 1000 /  2 + 50 = 550\r
2487         // 1000 / 30 + 50 = 83\r
2488         return (unsigned int) (1000.0 / (2.0 + m_nKeyboardSpeed % 32 * 28.0 / 31.0) + 50.0);\r
2489 }\r
2490 \r
2491 void CXkeymacsDll::SetCursorData(HCURSOR hEnable, HCURSOR hDisableTMP, HCURSOR hDisableWOCQ, HICON hDisable, BOOL bEnable)\r
2492 {\r
2493         m_hCursor[STATUS_ENABLE] = hEnable;\r
2494         m_hCursor[STATUS_DISABLE_TMP] = hDisableTMP;\r
2495         m_hCursor[STATUS_DISABLE_WOCQ] = hDisableWOCQ;\r
2496         m_hCursor[STATUS_DISABLE] = hDisable;\r
2497         m_bCursor = bEnable;\r
2498 }\r
2499 \r
2500 void CXkeymacsDll::DoSetCursor()\r
2501 {\r
2502         if (m_bCursor && m_hCurrentCursor) {\r
2503                 ::SetCursor(m_hCurrentCursor);\r
2504         }\r
2505 }\r
2506 \r
2507 BOOL CXkeymacsData::Get326Compatible()\r
2508 {\r
2509         return m_b326Compatible;\r
2510 }\r
2511 \r
2512 void CXkeymacsData::Set326Compatible(BOOL b326Compatible)\r
2513 {\r
2514         m_b326Compatible = b326Compatible;\r
2515 }\r
2516 \r
2517 void CXkeymacsDll::Set326Compatible(int nApplicationID, BOOL b326Compatible)\r
2518 {\r
2519         m_b326Compatible[nApplicationID] = b326Compatible;\r
2520 }\r
2521 \r
2522 BOOL CXkeymacsDll::Get326Compatible()\r
2523 {\r
2524         return m_b326Compatible[m_nApplicationID];\r
2525 }\r
2526 \r
2527 void CXkeymacsDll::InvokeM_x(const TCHAR *const szPath)\r
2528 {\r
2529 //      CUtils::Log("M-x: szPath=_%s_", szPath);\r
2530         int (*fCommand)() = NULL;\r
2531 \r
2532         for (int i = 0; i < MAX_COMMAND; ++i) {\r
2533                 if (_tcsicmp(szPath, Commands[i].szCommandName) == 0) {\r
2534                         fCommand = Commands[i].fCommand;\r
2535                         break;\r
2536                 }\r
2537         }\r
2538 \r
2539         if (fCommand) {\r
2540 //              CUtils::Log("M-x: Command: _%s_", Commands[i].szCommandName);\r
2541                 fCommand();\r
2542         } else {\r
2543 //              CUtils::Log("M-x: Path: _%s_", szPath);\r
2544                 ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);\r
2545         }\r
2546 }\r
2547 \r
2548 void CXkeymacsDll::ModifyM_xTip(const TCHAR *const szPath)\r
2549 {\r
2550         if (szPath) {\r
2551                 if (_tcslen(szPath) < sizeof(m_stNtfyIcon[MX_ICON].szTip) / sizeof(m_stNtfyIcon[MX_ICON].szTip[0]) - 5) {\r
2552                         memset(m_stNtfyIcon[MX_ICON].szTip, 0, sizeof(m_stNtfyIcon[MX_ICON].szTip));\r
2553                         _stprintf(m_stNtfyIcon[MX_ICON].szTip, "M-x %s", szPath);\r
2554                 }\r
2555         } else {\r
2556                 memset(m_stNtfyIcon[MX_ICON].szTip, 0, sizeof(m_stNtfyIcon[MX_ICON].szTip));\r
2557                 _stprintf(m_stNtfyIcon[MX_ICON].szTip, "M-x LED");\r
2558         }\r
2559 \r
2560         ModifyShell_NotifyIcon(MX_ICON, CCommands::bM_x(), TRUE);\r
2561 }\r