OSDN Git Service

Support recent versions of Microsoft Visual Studio.
[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_bHookAltRelease = FALSE;\r
200         BOOL    CXkeymacsDll::m_bEnableKeyboardHook = FALSE;\r
201         HHOOK   CXkeymacsDll::m_hHookCallWnd = NULL;\r
202         HHOOK   CXkeymacsDll::m_hHookCallWndRet = NULL;\r
203         HHOOK   CXkeymacsDll::m_hHookGetMessage = NULL;\r
204         HHOOK   CXkeymacsDll::m_hHookShell = NULL;\r
205         BOOL    CXkeymacsDll::m_bRightControl   = FALSE;\r
206         BOOL    CXkeymacsDll::m_bRightAlt               = FALSE;\r
207         BOOL    CXkeymacsDll::m_bRightShift             = FALSE;\r
208         BOOL    CXkeymacsDll::m_bHook                   = TRUE;\r
209         BOOL    CXkeymacsDll::m_bDefiningMacro  = FALSE;\r
210         CList<CClipboardSnap *, CClipboardSnap *> CXkeymacsDll::m_oKillRing;\r
211         CObList CXkeymacsDll::m_Macro;\r
212         int             CXkeymacsDll::m_nKillRing = 0;\r
213         int             CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
214         int             CXkeymacsDll::m_nApplicationID = 0;\r
215         int             CXkeymacsDll::m_nAccelerate = 0;\r
216         int             CXkeymacsDll::m_nKeyboardSpeed = 31;\r
217         HCURSOR CXkeymacsDll::m_hCursor[MAX_STATUS] = {'\0'};\r
218         HCURSOR CXkeymacsDll::m_hCurrentCursor = NULL;\r
219         BOOL    CXkeymacsDll::m_bCursor = FALSE;\r
220         TCHAR   CXkeymacsDll::m_M_xTip[128] = "";\r
221         CONFIG  CXkeymacsDll::m_Config = {0};\r
222 #pragma data_seg()\r
223 \r
224 //////////////////////////////////////////////////////////////////////\r
225 // Construction/Destruction\r
226 //////////////////////////////////////////////////////////////////////\r
227 \r
228 CXkeymacsDll::CXkeymacsDll()\r
229 {\r
230 \r
231 }\r
232 \r
233 CXkeymacsDll::~CXkeymacsDll()\r
234 {\r
235 \r
236 }\r
237 \r
238 BOOL CXkeymacsDll::SaveConfig()\r
239 {\r
240         TCHAR szTmp[MAX_PATH];\r
241         if (!GetTempPath(MAX_PATH, szTmp))\r
242                 return FALSE;\r
243         if (_tmakepath_s(szTmp, NULL, szTmp, _T("xkeymacs"), _T("tmp")))\r
244                 return FALSE;\r
245         HANDLE hFile = CreateFile(szTmp, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);\r
246         if (hFile == INVALID_HANDLE_VALUE)\r
247                 return FALSE;\r
248         DWORD written;\r
249         BOOL res = WriteFile(hFile, &m_Config, sizeof(m_Config), &written, NULL) || written != sizeof(m_Config);\r
250         CloseHandle(hFile);\r
251         return res;\r
252 }\r
253 \r
254 BOOL CXkeymacsDll::LoadConfig()\r
255 {\r
256         TCHAR szTmp[MAX_PATH];\r
257         if (!GetTempPath(MAX_PATH, szTmp))\r
258                 return FALSE;\r
259         if (_tmakepath_s(szTmp, NULL, szTmp, _T("xkeymacs"), _T("tmp")))\r
260                 return FALSE;\r
261         HANDLE hFile = CreateFile(szTmp, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);\r
262         if (hFile == INVALID_HANDLE_VALUE)\r
263                 return FALSE;\r
264         DWORD read;\r
265         BOOL res = ReadFile(hFile, &m_Config, sizeof(m_Config), &read, NULL) && read == sizeof(m_Config);\r
266         CloseHandle(hFile);\r
267         return res;\r
268 }\r
269 \r
270 void CXkeymacsDll::SetHookAltRelease()\r
271 {\r
272         m_bHookAltRelease = TRUE;\r
273 }\r
274 \r
275 // set hooks\r
276 void CXkeymacsDll::SetHooks()\r
277 {\r
278         m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);\r
279         m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);\r
280         m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);\r
281         m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);\r
282 }\r
283 \r
284 void CXkeymacsDll::EnableKeyboardHook()\r
285 {\r
286         m_bEnableKeyboardHook = TRUE;\r
287 }\r
288 \r
289 void CXkeymacsDll::SetKeyboardHook()\r
290 {\r
291         if (!g_hHookKeyboard)\r
292                 SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, GetCurrentThreadId());\r
293 }\r
294 \r
295 // release hooks\r
296 void CXkeymacsDll::ReleaseHooks()\r
297 {\r
298         m_bEnableKeyboardHook = FALSE;\r
299         if (m_hHookCallWnd)\r
300                 UnhookWindowsHookEx(m_hHookCallWnd);\r
301         m_hHookCallWnd = NULL;\r
302         if (m_hHookCallWndRet)\r
303                 UnhookWindowsHookEx(m_hHookCallWndRet);\r
304         m_hHookCallWndRet = NULL;\r
305         if (m_hHookGetMessage)\r
306                 UnhookWindowsHookEx(m_hHookGetMessage);\r
307         m_hHookGetMessage = NULL;\r
308         if (m_hHookShell)\r
309                 UnhookWindowsHookEx(m_hHookShell);\r
310         m_hHookShell = NULL;\r
311 }\r
312 \r
313 void CXkeymacsDll::ReleaseKeyboardHook()\r
314 {\r
315         if (g_hHookKeyboard)\r
316                 UnhookWindowsHookEx(g_hHookKeyboard);\r
317         g_hHookKeyboard = NULL;\r
318 }\r
319 \r
320 void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)\r
321 {\r
322         m_bHook = bFlag;\r
323         ICONMSG msg = {MAIN_ICON,};\r
324         if (m_bHook) {\r
325                 if (CCommands::IsTemporarilyDisableXKeymacs()) {\r
326                         msg.nState = STATUS_DISABLE_TMP;\r
327                         m_hCurrentCursor = m_hCursor[STATUS_DISABLE_TMP];\r
328                 } else {\r
329                         msg.nState = STATUS_ENABLE;\r
330                         m_hCurrentCursor = m_hCursor[STATUS_ENABLE];\r
331                 }\r
332         } else {\r
333                 msg.nState = STATUS_DISABLE_WOCQ;\r
334         }\r
335         if (m_Config.nSettingStyle[m_nApplicationID] == SETTING_DISABLE\r
336          || (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default"))\r
337           && CUtils::IsDefaultIgnoreApplication())) {\r
338                 msg.nState = STATUS_DISABLE;\r
339                 m_hCurrentCursor = m_hCursor[STATUS_DISABLE];\r
340         }\r
341         SendIconMessage(&msg, 1);\r
342         DoSetCursor();\r
343 }\r
344 \r
345 // if be keyboard hook, return TRUE\r
346 BOOL CXkeymacsDll::IsKeyboardHook()\r
347 {\r
348         if (m_bHook) {\r
349                 return TRUE;\r
350         }\r
351 \r
352         return FALSE;\r
353 }\r
354 \r
355 void CXkeymacsDll::LogCallWndProcMessage(WPARAM wParam, LPARAM lParam)\r
356 {\r
357         CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
358 \r
359         switch (cwps.message) {\r
360         case WM_PAINT:                                  // 0x000F\r
361         case WM_MDIGETACTIVE:                   // 0x0229\r
362         case 0x0403:\r
363         case 0x0407:\r
364         case 0x0418:\r
365         case 0x043F:\r
366         case 0x0440:\r
367                 break;\r
368         case WM_CREATE:                                 // 0x0001\r
369 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_CREATE"));\r
370                 break;\r
371         case WM_DESTROY:                                // 0x0002\r
372 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_DESTROY"));\r
373                 break;\r
374         case WM_MOVE:                                   // 0x0003\r
375 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_MOVE");)\r
376                 break;\r
377         case WM_SIZE:                                   // 0x0005\r
378 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_SIZE"));\r
379                 break;\r
380         case WM_GETTEXT:                                // 0x000D\r
381 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_GETTEXT"));\r
382                 break;\r
383         case WM_ERASEBKGND:                             // 0x0014\r
384 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_ERASEBKGND"));\r
385                 break;\r
386         case WM_WINDOWPOSCHANGING:              // 0x0046\r
387 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGING"));\r
388                 break;\r
389         case WM_WINDOWPOSCHANGED:               // 0x0047\r
390 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_WINDOWPOSCHANGED"));\r
391                 break;\r
392         case WM_COPYDATA:                               // 0x004A\r
393 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_COPYDATA"));\r
394                 break;\r
395         case WM_NCCREATE:                               // 0x0081\r
396 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCREATE"));\r
397                 break;\r
398         case WM_NCDESTROY:                              // 0x0082\r
399 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCDESTROY"));\r
400                 break;\r
401         case WM_NCCALCSIZE:                             // 0x0083\r
402 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCCALCSIZE"));\r
403                 break;\r
404         case WM_NCPAINT:                                // 0x0085\r
405 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_NCPAINT"));\r
406                 break;\r
407         case WM_IME_STARTCOMPOSITION:   // 0x010D\r
408 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_STARTCOMPOSITION"));\r
409                 break;\r
410         case WM_IME_ENDCOMPOSITION:             // 0x010E\r
411 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_ENDCOMPOSITION"));\r
412                 break;\r
413         case WM_IME_KEYLAST:                    // 0x010F\r
414 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_KEYLAST"));\r
415                 break;\r
416         case WM_COMMAND:                                // 0x0111\r
417 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_COMMAND"));\r
418                 break;\r
419         case WM_CTLCOLOREDIT:                   // 0x0133\r
420 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_CTLCOLOREDIT"));\r
421                 break;\r
422         case WM_POWERBROADCAST:                 // 0x0218\r
423 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_POWERBROADCAST"));\r
424                 switch (wParam) {\r
425                 case PBT_APMQUERYSUSPEND:               // 0x0000\r
426 //                      CUtils::Log(_T("PBT_APMQUERYSUSPEND"));\r
427                         break;\r
428                 case PBT_APMQUERYSTANDBY:               // 0x0001\r
429 //                      CUtils::Log(_T("PBT_APMQUERYSTANDBY"));\r
430                         break;\r
431                 case PBT_APMQUERYSUSPENDFAILED: // 0x0002\r
432 //                      CUtils::Log(_T("PBT_APMQUERYSUSPENDFAILED"));\r
433                         break;\r
434                 case PBT_APMQUERYSTANDBYFAILED: // 0x0003\r
435 //                      CUtils::Log(_T("PBT_APMQUERYSTANDBYFAILED"));\r
436                         break;\r
437                 case PBT_APMSUSPEND:                    // 0x0004\r
438 //                      CUtils::Log(_T("PBT_APMSUSPEND"));\r
439                         break;\r
440                 case PBT_APMSTANDBY:                    // 0x0005\r
441 //                      CUtils::Log(_T("PBT_APMSTANDBY"));\r
442                         break;\r
443                 case PBT_APMRESUMECRITICAL:             // 0x0006\r
444 //                      CUtils::Log(_T("PBT_APMRESUMECRITICAL"));\r
445                         break;\r
446                 case PBT_APMRESUMESUSPEND:              // 0x0007\r
447 //                      CUtils::Log(_T("PBT_APMRESUMESUSPEND"));\r
448                         break;\r
449                 case PBT_APMRESUMESTANDBY:              // 0x0008\r
450 //                      CUtils::Log(_T("PBT_APMRESUMESTANDBY"));\r
451                         break;\r
452                 case PBT_APMBATTERYLOW:                 // 0x0009\r
453 //                      CUtils::Log(_T("PBT_APMBATTERYLOW"));\r
454                         break;\r
455                 case PBT_APMPOWERSTATUSCHANGE:  // 0x000A\r
456 //                      CUtils::Log(_T("PBT_APMPOWERSTATUSCHANGE"));\r
457                         break;\r
458                 case PBT_APMOEMEVENT:                   // 0x000B\r
459 //                      CUtils::Log(_T("PBT_APMOEMEVENT"));\r
460                         break;\r
461                 case PBT_APMRESUMEAUTOMATIC:    // 0x0012\r
462 //                      CUtils::Log(_T("PBT_APMRESUMEAUTOMATIC"));\r
463                         break;\r
464                 default:\r
465 //                      CUtils::Log(_T("PBT_OTHERS: %d"), wParam);\r
466                         break;\r
467                 }\r
468                 break;\r
469         case WM_IME_NOTIFY:                             // 0x0282\r
470 //              CUtils::Log(_T("CallWndProc: cwps.message = WM_IME_NOTIFY"));\r
471                 break;\r
472         default:\r
473 //              CUtils::Log(_T("CallWndProc: cwps.message = 0x%04X"), cwps.message);\r
474                 break;\r
475         }\r
476 }\r
477 \r
478 LRESULT CALLBACK CXkeymacsDll::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)\r
479 {\r
480 //      LogCallWndProcMessage(wParam, lParam);\r
481 \r
482         if (0 <= nCode) {\r
483                 CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;\r
484                 switch (cwps.message) {\r
485                 case WM_IME_STARTCOMPOSITION:\r
486                         InitKeyboardProc(TRUE);\r
487                         break;\r
488                 case WM_IME_ENDCOMPOSITION:\r
489                         InitKeyboardProc(FALSE);\r
490                         break;\r
491                 case WM_SETFOCUS:\r
492                         if (cwps.hwnd == GetForegroundWindow()) {\r
493                                 InitKeyboardProc(FALSE);\r
494                                 SetKeyboardHookFlag(m_bHook);\r
495                         }\r
496                         break;\r
497                 case WM_NCACTIVATE:\r
498                         if (cwps.wParam) {\r
499                                 if (cwps.hwnd == GetForegroundWindow()) {\r
500                                         InitKeyboardProc(FALSE);\r
501                                         SetKeyboardHookFlag(m_bHook);\r
502                                 }\r
503                         }\r
504                         break;\r
505                 case WM_POWERBROADCAST:\r
506                         switch (wParam) {\r
507                         case PBT_APMRESUMECRITICAL: // 0x0006\r
508                         case PBT_APMRESUMESUSPEND:  // 0x0007\r
509                         case PBT_APMRESUMESTANDBY:  // 0x0008\r
510                                 ReleaseHooks();\r
511                                 SetHooks();\r
512                                 break;\r
513                         default:\r
514                                 break;\r
515                         }\r
516                         break;\r
517                 default:\r
518                         break;\r
519                 }\r
520         }\r
521         return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);\r
522 }\r
523 \r
524 LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)\r
525 {\r
526         if (0 <= nCode) {\r
527                 CWPRETSTRUCT &cwprets = *(CWPRETSTRUCT *)lParam;\r
528                 switch (cwprets.message) {\r
529                 case WM_SETTEXT:\r
530                         if (cwprets.hwnd == GetForegroundWindow()) {\r
531                                 InitKeyboardProc(FALSE);\r
532                         }\r
533                         break;\r
534                 case WM_SETCURSOR:\r
535                         DoSetCursor();\r
536                         break;\r
537                 default:\r
538                         break;\r
539                 }\r
540         }\r
541         return CallNextHookEx(m_hHookCallWndRet, nCode, wParam, lParam);\r
542 }\r
543 \r
544 LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)\r
545 {\r
546         MSG &msg = (*(MSG *)lParam);\r
547 \r
548         switch (msg.message) {\r
549         case WM_IME_STARTCOMPOSITION:\r
550                 InitKeyboardProc(TRUE);\r
551                 break;\r
552         case WM_IME_ENDCOMPOSITION:\r
553                 InitKeyboardProc(FALSE);\r
554                 break;\r
555         }\r
556         return CallNextHookEx(m_hHookGetMessage, nCode, wParam, lParam);\r
557 }\r
558 \r
559 LRESULT CALLBACK CXkeymacsDll::ShellProc(int nCode, WPARAM wParam, LPARAM lParam)\r
560 {\r
561         switch (nCode) {\r
562         case HSHELL_WINDOWACTIVATED:\r
563         {\r
564                 TCHAR className[256];\r
565                 ::GetClassName((HWND)wParam, className, 255);\r
566                 if (!_tcsicmp(className, _T("ConsoleWindowClass"))) {\r
567                         InitKeyboardProc(FALSE);\r
568                         SetKeyboardHookFlag(m_bHook);\r
569                 }\r
570                 break;\r
571         }\r
572         default:\r
573                 break;\r
574         }\r
575         return CallNextHookEx( m_hHookShell, nCode, wParam, lParam );\r
576 }\r
577 \r
578 // return true if the key is down\r
579 BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)\r
580 {\r
581         if (bPhysicalKey) {\r
582                 return GetKeyState(bVk) < 0;\r
583         } else {\r
584                 return GetAsyncKeyState(bVk) < 0;\r
585         }\r
586 }\r
587 \r
588 // Do keybd_event\r
589 void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)\r
590 {\r
591         // Set KEYEVENTF_EXTENDEDKEY if needed\r
592         switch (bVk) {\r
593         case VK_CONTROL:\r
594                 if (m_bRightControl) {          // Right Ctrl\r
595                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
596                 }\r
597                 break;\r
598 \r
599         case VK_MENU:\r
600                 if (m_bRightAlt) {                      // Right Alt\r
601                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
602 //                      CUtils::Log("Right Alt %d", dwFlags);\r
603 //              } else {\r
604 //                      CUtils::Log("Left Alt %d", dwFlags);\r
605                 }\r
606                 break;\r
607 \r
608         case VK_SHIFT:\r
609                 if (m_bRightShift) {            // Right Shift\r
610                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
611                 }\r
612                 break;\r
613 \r
614         case VK_PAUSE:\r
615                 if (IsDown(VK_CONTROL)) {       // Break\r
616                         dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
617                 }\r
618                 break;\r
619 \r
620         case VK_INSERT:\r
621         case VK_DELETE:\r
622         case VK_HOME:\r
623         case VK_END:\r
624         case VK_NEXT:\r
625         case VK_PRIOR:\r
626         case VK_UP:\r
627         case VK_DOWN:\r
628         case VK_RIGHT:\r
629         case VK_LEFT:\r
630         case VK_NUMLOCK:\r
631         case VK_PRINT:\r
632                 dwFlags |= KEYEVENTF_EXTENDEDKEY;\r
633                 break;\r
634 \r
635         default:\r
636                 break;\r
637         }\r
638 \r
639 //      CUtils::Log(_T("b: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
640         keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());\r
641 //      CUtils::Log(_T("a: %x, %x, %x, %#x, %#x"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));\r
642 }\r
643 \r
644 // the key is being depressed\r
645 void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal) // bVk is virtual-key code, MSDN said\r
646 {\r
647         if (bOriginal) {\r
648 //              CUtils::Log(_T("i: %x, %d, %d, %d, %d, %d, %d, %d, %d"), bVk,\r
649 //                      IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
650 //                      IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
651 \r
652                 int nCommandType = NONE;\r
653                 if (IsDown(VK_CONTROL, FALSE)) {\r
654                         nCommandType |= CONTROL;\r
655                 }\r
656                 if (IsDown(VK_MENU, FALSE)) {\r
657                         nCommandType |= META;\r
658                 }\r
659                 Original(nCommandType, bVk, 1);\r
660         }\r
661 \r
662         DoKeybd_event(bVk, 0);\r
663 }\r
664 \r
665 // the key is being released\r
666 void CXkeymacsDll::ReleaseKey(BYTE bVk) // bVk is virtual-key code, MSDN said\r
667 {\r
668         DoKeybd_event(bVk, KEYEVENTF_KEYUP);\r
669 }\r
670 \r
671 // bVk down, bVk up\r
672 void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)\r
673 {\r
674         while (n--) {\r
675                 DepressKey(bVk, bOriginal);\r
676                 ReleaseKey(bVk);\r
677         }\r
678 }\r
679 \r
680 void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)\r
681 {\r
682         if (CUtils::IsFindDialog()) {\r
683                 static BOOL bImeCompositionOld = FALSE;\r
684                 if (!bImeComposition\r
685                  && bImeCompositionOld) {\r
686                         DepressKey(VK_END);\r
687                         ReleaseKey(VK_END);\r
688                 }\r
689                 bImeCompositionOld = bImeComposition;\r
690         }\r
691 \r
692         CUtils::SetApplicationName(bImeComposition);\r
693 \r
694         if (_tcsnicmp(m_Config.szSpecialApp[m_nApplicationID], CUtils::GetApplicationName(), 0xF) || !IsMatchWindowText(m_Config.szWindowText[m_nApplicationID])) {     // PROCESSENTRY32 has only 0xF bytes of Name\r
695                 m_nApplicationID = -1;\r
696 \r
697                 for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
698                         if (!_tcsnicmp(m_Config.szSpecialApp[nApplicationID], CUtils::GetApplicationName(), 0xF) && IsMatchWindowText(m_Config.szWindowText[nApplicationID])) {\r
699 \r
700                                 if (m_nApplicationID < 0\r
701                                  || CUtils::GetWindowTextType(m_Config.szWindowText[m_nApplicationID]) < CUtils::GetWindowTextType(m_Config.szWindowText[nApplicationID])\r
702                                  || CUtils::GetWindowTextType(m_Config.szWindowText[m_nApplicationID]) == CUtils::GetWindowTextType(m_Config.szWindowText[nApplicationID])\r
703                                  && _tcscmp(m_Config.szWindowText[m_nApplicationID], m_Config.szWindowText[nApplicationID]) <= 0) {\r
704                                         m_nApplicationID = nApplicationID;\r
705                                 }\r
706                         }\r
707                 }\r
708 \r
709                 if (m_nApplicationID < 0) {\r
710                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
711                                 if (!_tcsicmp(m_Config.szSpecialApp[nApplicationID], _T("Default"))) {\r
712                                         m_nApplicationID = nApplicationID;\r
713                                         break;\r
714                                 }\r
715                         }\r
716 \r
717                         if (m_nApplicationID < 0) {\r
718                                 m_nApplicationID = 0;\r
719                         }\r
720                 }\r
721         }\r
722 \r
723         if (m_Config.nSettingStyle[m_nApplicationID] != SETTING_DISABLE\r
724          && (_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default")) || !CUtils::IsDefaultIgnoreApplication())\r
725          && !bImeComposition\r
726          && CUtils::IsDialog()) {\r
727                 // Use Dialog Setting\r
728                 if (m_Config.bUseDialogSetting[m_nApplicationID]) {\r
729                         int nOriginalApplicationID = m_nApplicationID;\r
730                         for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {\r
731                                 if (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Dialog"))) {\r
732                                         break;\r
733                                 }\r
734                         }\r
735                         if (m_nApplicationID == MAX_APP) {\r
736                                 m_nApplicationID = nOriginalApplicationID;\r
737                         }\r
738                 }\r
739         }\r
740 \r
741         ICONMSG msg[3] = {\r
742                 {CX_ICON, OFF_ICON, ""},\r
743                 {MX_ICON, OFF_ICON, ""},\r
744                 {META_ICON, OFF_ICON, ""}\r
745         };\r
746         SendIconMessage(msg, 3);\r
747         CCommands::SetMark(FALSE);\r
748         CCommands::SetTemporarilyDisableXKeymacs(FALSE);\r
749         CCommands::Reset();\r
750 }\r
751 \r
752 // emulate emacs        // cf virtual-key code\r
753 LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)\r
754 {\r
755         ASSERT(0 <= wParam && wParam <= UCHAR_MAX);\r
756 \r
757         int nCommandType = NONE;\r
758         BYTE nKey = (BYTE)wParam;\r
759 \r
760         static BOOL bLocked = FALSE;\r
761         static const BYTE RECURSIVE_KEY = 0x07;\r
762         static int (*fCommand)() = NULL;\r
763         static BYTE nOneShotModifier[MAX_KEY] = {'\0'};\r
764         static BOOL bCherryOneShotModifier = FALSE;\r
765 \r
766 //      CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nKey, lParam);\r
767 \r
768         if (!m_bEnableKeyboardHook)\r
769                 return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
770 \r
771         if (nCode < 0 || nCode == HC_NOREMOVE) {\r
772                 goto DO_NOTHING;\r
773         }\r
774 \r
775         if (nKey == RECURSIVE_KEY) {\r
776                 if (lParam & BEING_RELEASED) {\r
777                         goto HOOK_RECURSIVE_KEY;\r
778                 } else {\r
779                         goto RECURSIVE_COMMAND;\r
780                 }\r
781         }\r
782 \r
783         {\r
784                 static BOOL bShift = FALSE;\r
785                 if (IsDepressedShiftKeyOnly(nKey)) {\r
786                         if (lParam & BEING_RELEASED) {\r
787                                 if (bShift) {\r
788                                         CCommands::SetMark(FALSE);\r
789                                 }\r
790                         } else {\r
791                                 bShift = TRUE;\r
792                         }\r
793                 } else {\r
794                         bShift = FALSE;\r
795                 }\r
796         }\r
797 \r
798         switch (nKey) {\r
799         case VK_CONTROL:\r
800                 if (lParam & EXTENDED_KEY) {\r
801                         nKey = VK_RCONTROL;\r
802                 } else {\r
803                         nKey = VK_LCONTROL;\r
804                 }\r
805                 break;\r
806         case VK_MENU:\r
807                 if (lParam & EXTENDED_KEY) {\r
808                         nKey = VK_RMENU;\r
809                 } else {\r
810                         nKey = VK_LMENU;\r
811                 }\r
812                 break;\r
813         case VK_SHIFT:\r
814                 if (lParam & EXTENDED_KEY) {\r
815                         nKey = VK_RSHIFT;\r
816                 } else {\r
817                         nKey = VK_LSHIFT;\r
818                 }\r
819                 break;\r
820         default:\r
821                 break;\r
822         }\r
823 \r
824         if (lParam & BEING_RELEASED) {\r
825                 BOOL bAlt = FALSE;\r
826                 switch (nKey) {\r
827                 case VK_MENU:\r
828                 case VK_LMENU:\r
829                 case VK_RMENU:\r
830                         bAlt = TRUE;\r
831                         if (m_bHookAltRelease) {\r
832                                 m_bHookAltRelease = FALSE;\r
833                                 goto HOOK;\r
834                         }\r
835                         // pass through\r
836                 case VK_LWIN:\r
837                 case VK_RWIN:\r
838                 case VK_APPS:\r
839                         for (int i = 0; i < MAX_COMMAND_TYPE; i++) {\r
840                                 int (*func)() = Commands[m_Config.nCommandID[m_nApplicationID][i][nKey]].fCommand;\r
841                                 if (func && !(bAlt && func == CCommands::MetaAlt))\r
842                                         goto HOOK;\r
843                         }\r
844                 }\r
845                 if (nOneShotModifier[nKey]) {\r
846                         ReleaseKey(nOneShotModifier[nKey]);\r
847                         nOneShotModifier[nKey] = 0;\r
848 \r
849                         if (bCherryOneShotModifier) {\r
850                                 bCherryOneShotModifier = FALSE;\r
851                                 Kdu(nKey);\r
852                         }\r
853                 }\r
854                 goto DO_NOTHING;\r
855         }\r
856 \r
857         if (m_Config.nSettingStyle[m_nApplicationID] == SETTING_DISABLE) {\r
858                 goto DO_NOTHING;\r
859         }\r
860 \r
861         // Do Nothing for Meadow, Mule for Win32, ... if those use default setting.\r
862         if (!_tcsicmp(m_Config.szSpecialApp[m_nApplicationID], _T("Default"))\r
863          && CUtils::IsDefaultIgnoreApplication()) {\r
864                 goto DO_NOTHING;\r
865         }\r
866 \r
867         switch (IsPassThrough(nKey)) {\r
868         case GOTO_DO_NOTHING:\r
869                 goto DO_NOTHING;\r
870         case GOTO_HOOK:\r
871                 goto HOOK;\r
872         case CONTINUE:\r
873                 break;\r
874         default:\r
875                 ASSERT(0);\r
876                 break;\r
877         }\r
878 \r
879         // set command type\r
880         {\r
881                 nCommandType = NONE;\r
882                 if (IsDown(VK_SHIFT, FALSE)) {\r
883                         nCommandType |= SHIFT;\r
884                 }\r
885                 if (IsControl()) {\r
886                         nCommandType |= CONTROL;\r
887                 }\r
888                 if (IsMeta()) {\r
889                         nCommandType |= META;\r
890                 }\r
891                 if (CCommands::bC_x()) {\r
892                         nCommandType |= CONTROLX;\r
893                 }\r
894 \r
895                 // Ignore undefined C-x ?\r
896                 if (nCommandType & CONTROLX) {\r
897                         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
898                          && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
899                                 if (m_Config.bIgnoreUndefinedC_x[m_nApplicationID]) {\r
900                                         CCommands::Reset(GOTO_HOOK);\r
901                                         goto HOOK;\r
902                                 }\r
903                                 nCommandType &= ~CONTROLX;\r
904                         }\r
905                 }\r
906 \r
907                 // Ignore undefined Meta Ctrl+?\r
908                 if (CCommands::bM_() && (nCommandType & CONTROL)) {\r
909                         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL\r
910                          && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {\r
911                                 if (m_Config.bIgnoreUndefinedMetaCtrl[m_nApplicationID]) {\r
912                                         if (Original(CONTROL, nKey)) {\r
913                                                 Original(CONTROL, nKey, -1);\r
914                                                 goto DO_NOTHING;\r
915                                         }\r
916                                         CCommands::Reset(GOTO_HOOK);\r
917                                         goto HOOK;\r
918                                 }\r
919                                 nCommandType &= ~META;\r
920                         }\r
921                 }\r
922         }\r
923 \r
924         {\r
925 //              CUtils::Log(_T("o: %x, %d, %d, %d, %d, %d, %d, %d, %d"), (BYTE)wParam,\r
926 //                      IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),\r
927 //                      IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));\r
928 \r
929                 BYTE nKey = (BYTE)wParam; // VK_CONTROL is needed instead of VK_RCONTROL and VK_LCONTROL in this block just for Original()\r
930                 int nVirtualCommandType = NONE;\r
931                 if (IsDown(VK_CONTROL) && nKey != VK_CONTROL) {\r
932                         nVirtualCommandType |= CONTROL;\r
933                 }\r
934                 if (IsDown(VK_MENU) && nKey != VK_MENU) {\r
935                         nVirtualCommandType |= META;\r
936                 }\r
937                 if (Original(nVirtualCommandType, nKey)) {\r
938                         Original(nVirtualCommandType, nKey, -1);\r
939                         goto DO_NOTHING;\r
940                 }\r
941         }\r
942 \r
943         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableOrDisableXKeymacs) {\r
944                 SetKeyboardHookFlag(!m_bHook);\r
945                 goto HOOK;\r
946         }\r
947         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableXKeymacs) {\r
948                 if (!m_bHook) {\r
949                         SetKeyboardHookFlag(!m_bHook);\r
950                 }\r
951                 goto HOOK;\r
952         }\r
953         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DisableXKeymacs) {\r
954                 if (m_bHook) {\r
955                         SetKeyboardHookFlag(!m_bHook);\r
956                 }\r
957                 goto HOOK;\r
958         }\r
959         if (!m_bHook) {\r
960                 goto DO_NOTHING;\r
961         }\r
962 \r
963         if (CCommands::bM_x()) {\r
964                 static unsigned int index = 0;\r
965                 static TCHAR szPath[MAX_PATH] = {'\0'};\r
966 \r
967                 if (lParam & BEING_RELEASED) {\r
968                         // ignore\r
969                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BackwardChar) {\r
970                         if (index) {\r
971                                 --index;\r
972                         }\r
973                         goto HOOKX;\r
974                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::BeginningOfLine) {\r
975                         index = 0;\r
976                         goto HOOKX;\r
977                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteBackwardChar) {\r
978                         if (index) {\r
979                                 --index;\r
980                                 memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
981                                 SetM_xTip(szPath);\r
982                         }\r
983                         goto HOOKX;\r
984                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DeleteChar) {\r
985                         if (index < _tcslen(szPath)) {\r
986                                 memmove(&szPath[index], &szPath[index + 1], _tcslen(szPath) - index);\r
987                                 SetM_xTip(szPath);\r
988                         }\r
989                         goto HOOKX;\r
990                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EndOfLine) {\r
991                         index = _tcslen(szPath);\r
992                         goto HOOKX;\r
993                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::ForwardChar) {\r
994                         if (index < _tcslen(szPath)) {\r
995                                 ++index;\r
996                         }\r
997                         goto HOOKX;\r
998                 } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::KeyboardQuit) {\r
999                         CCommands::bM_x(FALSE);\r
1000                         index = 0;\r
1001                         memset(szPath, 0, sizeof(szPath));\r
1002                         goto HOOK;\r
1003                 } else if (nKey == VK_RETURN\r
1004                                 || Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::Newline) {\r
1005                         InvokeM_x(szPath);\r
1006 \r
1007                         CCommands::bM_x(FALSE);\r
1008                         index = 0;\r
1009                         memset(szPath, 0, sizeof(szPath));\r
1010                         goto HOOK;\r
1011                 } else if (index < MAX_PATH - 1) {\r
1012                         const BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
1013                         for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
1014                                 if (nKey != 0 && a2v(nAscii) == nKey && bIsShiftDown == IsShift(nAscii)) {\r
1015 //                                      CUtils::Log("M-x: %#X (%c), %#X (%c)", nKey, nKey, nAscii, nAscii);\r
1016                                         if (index < _tcslen(szPath)) {\r
1017                                                 memmove(&szPath[index + 1], &szPath[index], __min(_tcslen(szPath) - index, MAX_PATH - (index + 1) - 1));\r
1018                                         }\r
1019                                         szPath[index++] = nAscii;\r
1020 //                                      CUtils::Log("M-x: %c(%#04x)", nAscii, nAscii);\r
1021                                         SetM_xTip(szPath);\r
1022                                         goto HOOKX;\r
1023                                 }\r
1024                         }\r
1025                 }\r
1026         }\r
1027 \r
1028         if (CCommands::bC_u()) {\r
1029                 if ((nCommandType == NONE) && ('0' <= nKey) && (nKey <= '9')) {\r
1030                         CCommands::NumericArgument(nKey - '0');\r
1031                         goto HOOK0_9;\r
1032                 }\r
1033                 if ((nCommandType == NONE) && (nKey == 0xBD)) {\r
1034                         CCommands::NumericArgumentMinus();\r
1035                         goto HOOK0_9;\r
1036                 }\r
1037         }\r
1038 \r
1039         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrl) {\r
1040                 nOneShotModifier[nKey] = VK_LCONTROL;\r
1041                 DepressKey(nOneShotModifier[nKey]);\r
1042                 bCherryOneShotModifier = TRUE;\r
1043                 goto HOOK;\r
1044         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
1045                 nOneShotModifier[nKey] = VK_LCONTROL;\r
1046                 DepressKey(nOneShotModifier[nKey]);\r
1047                 bCherryOneShotModifier = TRUE;\r
1048                 goto HOOK;\r
1049         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {\r
1050                 ReleaseKey(nOneShotModifier[nKey]);\r
1051                 bCherryOneShotModifier = FALSE;\r
1052                 Kdu(nKey);\r
1053                 goto HOOK;\r
1054         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAlt) {\r
1055                 nOneShotModifier[nKey] = VK_LMENU;\r
1056                 DepressKey(nOneShotModifier[nKey]);\r
1057                 bCherryOneShotModifier = TRUE;\r
1058                 goto HOOK;\r
1059         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
1060                 nOneShotModifier[nKey] = VK_LMENU;\r
1061                 DepressKey(nOneShotModifier[nKey]);\r
1062                 bCherryOneShotModifier = TRUE;\r
1063                 goto HOOK;\r
1064         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {\r
1065                 ReleaseKey(nOneShotModifier[nKey]);\r
1066                 bCherryOneShotModifier = FALSE;\r
1067                 Kdu(nKey);\r
1068                 goto HOOK;\r
1069         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShift) {\r
1070                 nOneShotModifier[nKey] = VK_SHIFT;\r
1071                 DepressKey(nOneShotModifier[nKey]);\r
1072                 bCherryOneShotModifier = TRUE;\r
1073                 goto HOOK;\r
1074         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
1075                 nOneShotModifier[nKey] = VK_SHIFT;\r
1076                 DepressKey(nOneShotModifier[nKey]);\r
1077                 bCherryOneShotModifier = TRUE;\r
1078                 goto HOOK;\r
1079         } else if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {\r
1080                 ReleaseKey(nOneShotModifier[nKey]);\r
1081                 bCherryOneShotModifier = FALSE;\r
1082                 Kdu(nKey);\r
1083                 goto HOOK;\r
1084         } else {\r
1085                 for (int i = 0; i < MAX_KEY; ++i) {\r
1086                         if (nOneShotModifier[i] == nKey) {\r
1087                                 break;\r
1088                         }\r
1089                 }\r
1090                 if (i == MAX_KEY) {\r
1091                         bCherryOneShotModifier = FALSE;\r
1092                 }\r
1093         }\r
1094 \r
1095         if (0 <= m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]\r
1096          && m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey] < MAX_FUNCTION\r
1097          && _tcslen(m_Config.szFunctionDefinition[m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]])) {\r
1098                 CallFunction(m_Config.nFunctionID[m_nApplicationID][nCommandType][nKey]);\r
1099                 CCommands::Reset(GOTO_HOOK);\r
1100                 goto HOOK;\r
1101         }\r
1102 \r
1103         if (!Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand) {\r
1104                 if (nKey == VK_CONTROL\r
1105                  || nKey == VK_LCONTROL\r
1106                  || nKey == VK_RCONTROL\r
1107                  || nKey == VK_MENU\r
1108                  || nKey == VK_LMENU\r
1109                  || nKey == VK_RMENU\r
1110                  || nKey == VK_SHIFT\r
1111                  || nKey == VK_LSHIFT\r
1112                  || nKey == VK_RSHIFT) {\r
1113                         goto DO_NOTHING;\r
1114                 }\r
1115 \r
1116                 if (!(nCommandType & SHIFT)) {\r
1117                         if (CCommands::IsSetMark()) {\r
1118                                 if (CCommands::MoveCaret(nKey, nCommandType & CONTROL) != CONTINUE) {\r
1119                                         CCommands::ClearNumericArgument();\r
1120                                         goto HOOK;\r
1121                                 }\r
1122                                 CCommands::SetMark(FALSE);\r
1123                         }\r
1124                 }\r
1125 \r
1126                 if (1 < CCommands::GetNumericArgument()) {\r
1127                         Kdu(nKey, CCommands::GetNumericArgument());\r
1128                         CCommands::ClearNumericArgument();\r
1129                         goto HOOK;\r
1130                 }\r
1131 \r
1132                 goto DO_NOTHING;\r
1133         }\r
1134 \r
1135         if (CCommands::IsTemporarilyDisableXKeymacs()\r
1136          && Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand != CCommands::KeyboardQuit) {\r
1137                 CCommands::SetTemporarilyDisableXKeymacs(FALSE);\r
1138                 goto DO_NOTHING;\r
1139         }\r
1140 \r
1141         if (m_Config.bAtIbeamCursorOnly[m_nApplicationID][nCommandType][nKey]) {\r
1142                 CURSORINFO cursorinfo = { sizeof(cursorinfo) };\r
1143                 if (GetCursorInfo(&cursorinfo) && cursorinfo.flags && cursorinfo.hCursor != LoadCursor(NULL, IDC_IBEAM)) {\r
1144                         goto DO_NOTHING;\r
1145                 }\r
1146         }\r
1147 \r
1148         m_bRightControl = IsDown(VK_RCONTROL);\r
1149         m_bRightAlt             = IsDown(VK_RMENU);\r
1150         m_bRightShift   = IsDown(VK_RSHIFT);\r
1151 \r
1152         if (!bLocked) {\r
1153                 bLocked = TRUE;\r
1154                 fCommand = Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand;\r
1155 RECURSIVE_COMMAND:\r
1156                 switch (fCommand()) {\r
1157                 case GOTO_DO_NOTHING:\r
1158                         bLocked = FALSE;\r
1159                         goto DO_NOTHING;\r
1160                 case GOTO_HOOK:\r
1161                         bLocked = FALSE;\r
1162                         goto HOOK;\r
1163                 case GOTO_RECURSIVE:\r
1164                         goto RECURSIVE;\r
1165                 case GOTO_HOOKX:\r
1166                         bLocked = FALSE;\r
1167                         goto HOOKX;\r
1168                 case GOTO_HOOK0_9:\r
1169                         bLocked = FALSE;\r
1170                         goto HOOK0_9;\r
1171                 default:\r
1172                         ASSERT(0);\r
1173                         bLocked = FALSE;\r
1174                         goto DO_NOTHING;\r
1175                 }\r
1176         } else {\r
1177                 goto HOOK_RECURSIVE_KEY;\r
1178         }\r
1179 \r
1180 DO_NOTHING:\r
1181         SetModifierIcons();\r
1182         {\r
1183                 static BOOL bDefiningMacro = FALSE;\r
1184                 if (m_bDefiningMacro) {\r
1185                         static BOOL bDown[MAX_KEY] = {'\0'};\r
1186 \r
1187                         if (!bDefiningMacro) {\r
1188                                 while (m_Macro.GetHeadPosition()) {\r
1189                                         void *p = m_Macro.GetAt(m_Macro.GetHeadPosition());\r
1190                                         m_Macro.RemoveHead();\r
1191                                         delete p;\r
1192                                         p = NULL;\r
1193                                 }\r
1194                                 memset(bDown, 0, sizeof(bDown));\r
1195                         }\r
1196 \r
1197                         if ((!(lParam & BEING_RELEASED)) || bDown[wParam]) {\r
1198                                 try {\r
1199                                         KbdMacro *pKbdMacro = new KbdMacro;\r
1200                                         if (pKbdMacro) {\r
1201                                                 pKbdMacro->nCode = nCode;\r
1202                                                 pKbdMacro->wParam = wParam;\r
1203                                                 pKbdMacro->lParam = lParam;\r
1204                                                 pKbdMacro->bOriginal = TRUE;\r
1205                                                 m_Macro.AddTail((CObject *)pKbdMacro);\r
1206                                         }\r
1207                                 }\r
1208                                 catch (CMemoryException* e) {\r
1209                                         e->Delete();\r
1210 //                                      CUtils::Log("KeyboardProc: 'new' threw an exception");\r
1211                                 }\r
1212                                 if (!(lParam & BEING_RELEASED)) {\r
1213                                         bDown[wParam] = TRUE;\r
1214                                 }\r
1215                         }\r
1216                 }\r
1217                 bDefiningMacro = m_bDefiningMacro;\r
1218         }\r
1219 \r
1220         return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
1221 \r
1222 RECURSIVE:\r
1223         Kdu(RECURSIVE_KEY, 1, FALSE);\r
1224         goto HOOKX;\r
1225 HOOK:\r
1226         CCommands::SetLastCommand(fCommand);\r
1227 HOOK0_9:\r
1228 HOOKX:\r
1229         SetModifierIcons();\r
1230 HOOK_RECURSIVE_KEY:\r
1231         return TRUE;\r
1232 }\r
1233 \r
1234 void CXkeymacsDll::SetModifierIcons()\r
1235 {\r
1236 #define IconState(x) ((x) ? ON_ICON : OFF_ICON)\r
1237         ICONMSG msg[6] = {\r
1238                 {MX_ICON, IconState(CCommands::bM_x()), ""},\r
1239                 {CX_ICON, IconState(CCommands::bC_x()), ""},\r
1240                 {META_ICON, IconState(CCommands::bM_()), ""},\r
1241                 {SHIFT_ICON, IconState(IsDown(VK_SHIFT)), ""},\r
1242                 {CTRL_ICON, IconState(IsControl()), ""},\r
1243                 {ALT_ICON, IconState(IsDown(VK_MENU)), ""}\r
1244         };\r
1245         _tcscpy_s(msg[0].szTip, m_M_xTip);\r
1246         SendIconMessage(msg, 6);\r
1247 }\r
1248 \r
1249 void CXkeymacsDll::SetApplicationName(int nApplicationID, CString szApplicationName)\r
1250 {\r
1251         ZeroMemory(m_Config.szSpecialApp[nApplicationID], CLASS_NAME_LENGTH);\r
1252         _tcsncpy_s(m_Config.szSpecialApp[nApplicationID], szApplicationName, _TRUNCATE);\r
1253 }\r
1254 \r
1255 void CXkeymacsDll::SetWindowText(int nApplicationID, CString szWindowText)\r
1256 {\r
1257         ZeroMemory(m_Config.szWindowText[nApplicationID], WINDOW_TEXT_LENGTH);\r
1258         _tcsncpy_s(m_Config.szWindowText[nApplicationID], szWindowText, _TRUNCATE);\r
1259 }\r
1260 \r
1261 void CXkeymacsDll::SetCommandID(int nApplicationID, int nCommandType, int nKey, int nCommandID)\r
1262 {\r
1263         m_Config.nCommandID[nApplicationID][nCommandType][nKey] = nCommandID;\r
1264 }\r
1265 \r
1266 void CXkeymacsDll::SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly)\r
1267 {\r
1268         m_Config.bAtIbeamCursorOnly[nApplicationID][nCommandType][nKey] = bAtIbeamCursorOnly;\r
1269 }\r
1270 \r
1271 void CXkeymacsDll::SetKillRingMax(int nApplicationID, int nKillRingMax)\r
1272 {\r
1273         m_Config.nKillRingMax[nApplicationID] = nKillRingMax;\r
1274 }\r
1275 \r
1276 void CXkeymacsDll::SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting)\r
1277 {\r
1278         m_Config.bUseDialogSetting[nApplicationID] = bUseDialogSetting;\r
1279 }\r
1280 \r
1281 // Clear data of nApplicationID\r
1282 void CXkeymacsDll::Clear(int nApplicationID)\r
1283 {\r
1284         if (0 <= nApplicationID && nApplicationID < MAX_APP) {\r
1285                 ZeroMemory(m_Config.szSpecialApp[nApplicationID], sizeof(m_Config.szSpecialApp[nApplicationID]));\r
1286                 ZeroMemory(m_Config.nCommandID[nApplicationID], sizeof(m_Config.nCommandID[nApplicationID]));\r
1287                 ZeroMemory(m_Config.bAtIbeamCursorOnly[nApplicationID], sizeof(m_Config.bAtIbeamCursorOnly[nApplicationID]));\r
1288                 m_Config.nKillRingMax[nApplicationID] = 0;\r
1289                 m_Config.bUseDialogSetting[nApplicationID] = FALSE;\r
1290                 m_Config.nSettingStyle[nApplicationID] = 0;\r
1291         } else {\r
1292                 ASSERT(0);\r
1293         }\r
1294 }\r
1295 \r
1296 BOOL CXkeymacsDll::IsValidKey(BYTE bVk)\r
1297 {\r
1298         if (bVk == 0xf0) {      // 0xf0: Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.\r
1299                 return FALSE;\r
1300         }\r
1301 \r
1302         switch (bVk) {\r
1303         case VK_CONTROL:\r
1304         case VK_MENU:\r
1305         case VK_SHIFT:\r
1306                 return FALSE;\r
1307         default:\r
1308                 break;\r
1309         }\r
1310 \r
1311         return TRUE;\r
1312 }\r
1313 \r
1314 BOOL CXkeymacsDll::IsDepressedModifier(int (__cdecl *Modifier)(void), BOOL bPhysicalKey)\r
1315 {\r
1316         BYTE bVk = 0;\r
1317         do {\r
1318                 if (IsValidKey(bVk)\r
1319                  && IsDown(bVk, bPhysicalKey)\r
1320                  && Commands[m_Config.nCommandID[m_nApplicationID][NONE][bVk]].fCommand == Modifier) {\r
1321                         return TRUE;\r
1322                 }\r
1323         } while (++bVk);\r
1324         return FALSE;\r
1325 }\r
1326 \r
1327 BOOL CXkeymacsDll::IsDepressedShiftKeyOnly(BYTE nKey)\r
1328 {\r
1329         if (nKey != VK_SHIFT\r
1330          && nKey != VK_LSHIFT\r
1331          && nKey != VK_RSHIFT) {\r
1332                 return FALSE;\r
1333         }\r
1334 \r
1335         BYTE bVk = 0;\r
1336         do {\r
1337                 if (bVk == VK_SHIFT\r
1338                  || bVk == VK_LSHIFT\r
1339                  || bVk == VK_RSHIFT) {\r
1340                         continue;\r
1341                 }\r
1342 \r
1343                 if (IsDown(bVk)) {\r
1344                         return FALSE;\r
1345                 }\r
1346         } while (++bVk);\r
1347         return TRUE;\r
1348 }\r
1349 \r
1350 BOOL CXkeymacsDll::IsControl()\r
1351 {\r
1352         return CCommands::bC_() || IsDepressedModifier(CCommands::C_, FALSE);\r
1353 }\r
1354 \r
1355 BOOL CXkeymacsDll::IsMeta()\r
1356 {\r
1357         return CCommands::bM_() || IsDepressedModifier(CCommands::MetaAlt, FALSE);\r
1358 }\r
1359 \r
1360 void CXkeymacsDll::AddKillRing(BOOL bNewData)\r
1361 {\r
1362         if (m_Config.nKillRingMax[m_nApplicationID] == 0) {\r
1363                 return;\r
1364         }\r
1365 \r
1366         CClipboardSnap *pSnap = new CClipboardSnap;\r
1367         if( !pSnap ) return;\r
1368 \r
1369         BOOL bCapture = pSnap->Capture();\r
1370         bCapture = pSnap->Capture();    // for "office drawing shape format". Can CClipboardSnap care this problem?\r
1371 \r
1372         if( bCapture ) {\r
1373                 if (bNewData) {\r
1374                         m_oKillRing.AddHead(pSnap);\r
1375                 } else {\r
1376                         if (m_oKillRing.IsEmpty()) {\r
1377                                 m_oKillRing.AddHead(pSnap);\r
1378                         } else {\r
1379                                 for (CClipboardSnap *pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {\r
1380                                         ;\r
1381                                 }\r
1382                                 pParent->SetNext(pSnap);\r
1383                         }\r
1384                 }\r
1385         } else {\r
1386                 delete pSnap;\r
1387                 pSnap = NULL;\r
1388         }\r
1389 \r
1390         m_nKillRing = 0;\r
1391 \r
1392         if (m_Config.nKillRingMax[m_nApplicationID] < m_oKillRing.GetCount()) {\r
1393                 CClipboardSnap *pSnap = m_oKillRing.GetTail();\r
1394                 delete pSnap;\r
1395                 pSnap = NULL;\r
1396                 m_oKillRing.RemoveTail();\r
1397         }\r
1398 }\r
1399 \r
1400 // Return TRUE if there is another data\r
1401 // Return FALSE if there is no more data\r
1402 CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)\r
1403 {\r
1404         if (m_Config.nKillRingMax[m_nApplicationID] == 0) {\r
1405                 return NULL;\r
1406         }\r
1407 \r
1408         if (m_oKillRing.IsEmpty()) {\r
1409                 return NULL;\r
1410         }\r
1411 \r
1412         m_nKillRing %= m_oKillRing.GetCount();\r
1413 \r
1414         if (!bForce) {\r
1415                 CClipboardSnap oCurrentSnap;\r
1416                 oCurrentSnap.Capture();\r
1417 \r
1418                 CClipboardSnap *pKillRing = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));\r
1419                 if (!pKillRing) {\r
1420                         return NULL;\r
1421                 }\r
1422                 for (; pKillRing->GetNext(); pKillRing = pKillRing->GetNext()) {\r
1423                         ;\r
1424                 }\r
1425                 if (*pKillRing != oCurrentSnap) {\r
1426                         return NULL;\r
1427                 }\r
1428         }\r
1429 \r
1430         if (!pSnap) {\r
1431                 pSnap = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));\r
1432         }\r
1433         pSnap->Restore();\r
1434 \r
1435         return pSnap->GetNext();\r
1436 }\r
1437 \r
1438 void CXkeymacsDll::Original(int nCommandType, BYTE bVk, int nOriginal)\r
1439 {\r
1440         nCommandType &= ~SHIFT;\r
1441 \r
1442         switch (bVk) {\r
1443         case VK_CONTROL:\r
1444                 bVk = VK_LCONTROL;\r
1445                 break;\r
1446         case VK_MENU:\r
1447                 bVk = VK_LMENU;\r
1448                 break;\r
1449         case VK_SHIFT:\r
1450                 bVk = VK_LSHIFT;\r
1451                 break;\r
1452         default:\r
1453                 break;\r
1454         }\r
1455 \r
1456         m_nOriginal[nCommandType][bVk] += nOriginal;\r
1457 }\r
1458 \r
1459 int CXkeymacsDll::Original(int nCommandType, BYTE bVk)\r
1460 {\r
1461         nCommandType &= ~SHIFT;\r
1462 \r
1463         switch (bVk) {\r
1464         case VK_CONTROL:\r
1465                 bVk = VK_LCONTROL;\r
1466                 break;\r
1467         case VK_MENU:\r
1468                 bVk = VK_LMENU;\r
1469                 break;\r
1470         case VK_SHIFT:\r
1471                 bVk = VK_LSHIFT;\r
1472                 break;\r
1473         default:\r
1474                 break;\r
1475         }\r
1476 \r
1477         return m_nOriginal[nCommandType][bVk];\r
1478 }\r
1479 \r
1480 void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)\r
1481 {\r
1482         m_nKillRing += nKillRing;\r
1483 }\r
1484 \r
1485 // nobody use\r
1486 int CXkeymacsDll::GetMickey(int nDifferential, int nThreshold1, int nThreshold2, int nAcceleration, int nSpeed)\r
1487 {\r
1488         nDifferential = nDifferential * 10 / nSpeed;\r
1489 \r
1490         switch (nAcceleration) {\r
1491         case 2:\r
1492                 if (nThreshold2 < fabs((double)(nDifferential / 4))) {\r
1493                         nDifferential /= 4;\r
1494                         break;\r
1495                 }\r
1496                 // Do NOT write break; here.\r
1497         case 1:\r
1498                 if (nThreshold1 < fabs((double)(nDifferential / 2))) {\r
1499                         nDifferential /= 2;\r
1500                 }\r
1501                 break;\r
1502         case 0:\r
1503                 break;\r
1504         default:\r
1505                 ASSERT(0);\r
1506                 break;\r
1507         }\r
1508 \r
1509         return nDifferential;\r
1510 }\r
1511 \r
1512 void CXkeymacsDll::SetSettingStyle(int nApplicationID, int nSettingStyle)\r
1513 {\r
1514         m_Config.nSettingStyle[nApplicationID] = nSettingStyle;\r
1515 }\r
1516 \r
1517 void CXkeymacsDll::SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl)\r
1518 {\r
1519         m_Config.bIgnoreUndefinedMetaCtrl[nApplicationID] = bIgnoreUndefinedMetaCtrl;\r
1520 }\r
1521 \r
1522 void CXkeymacsDll::SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x)\r
1523 {\r
1524         m_Config.bIgnoreUndefinedC_x[nApplicationID] = bIgnoreUndefinedC_x;\r
1525 }\r
1526 \r
1527 void CXkeymacsDll::SetEnableCUA(int nApplicationID, BOOL bEnableCUA)\r
1528 {\r
1529         m_Config.bEnableCUA[nApplicationID] = bEnableCUA;\r
1530 }\r
1531 \r
1532 BOOL CXkeymacsDll::GetEnableCUA()\r
1533 {\r
1534         return m_Config.bEnableCUA[m_nApplicationID];\r
1535 }\r
1536 \r
1537 void CXkeymacsDll::DefiningMacro(BOOL bDefiningMacro)\r
1538 {\r
1539         m_bDefiningMacro = bDefiningMacro;\r
1540 \r
1541         if (bDefiningMacro) {   // start-kbd-macro\r
1542                 if (CCommands::bC_u()) {\r
1543                         ReleaseKey(VK_SHIFT);\r
1544                         CallMacro();\r
1545                 }\r
1546         } else {                                // end-kbd-macro\r
1547                 while (!m_Macro.IsEmpty()) {\r
1548                         KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetTail();\r
1549                         if (pKbdMacro->lParam & BEING_RELEASED) {\r
1550                                 break;\r
1551                         } else {\r
1552                                 m_Macro.RemoveTail();\r
1553                                 delete pKbdMacro;\r
1554                                 pKbdMacro = NULL;\r
1555                         }\r
1556                 }\r
1557 \r
1558 //              CUtils::Log(_T("Macro MemMap: start"));\r
1559                 if (!m_Macro.IsEmpty()) {\r
1560                         static HANDLE hMacro = NULL;\r
1561                         if (!hMacro) {\r
1562                                 hMacro = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x3000, _T("macro"));\r
1563                         }\r
1564                         if (hMacro) {\r
1565 //                              CUtils::Log(_T("Macro MemMap: 1"));\r
1566                                 PVOID pView = MapViewOfFile(hMacro, FILE_MAP_ALL_ACCESS, 0, 0, 0);\r
1567 //                              CUtils::Log(_T("Macro MemMap: 2"));\r
1568                                 if (pView) {\r
1569 //                                      CUtils::Log(_T("Macro MemMap: 2.5"));\r
1570                                         for (int i = 0; i < m_Macro.GetCount(); ++i) {\r
1571 //                                              CUtils::Log(_T("Macro MemMap: 3-1 %d"), i);\r
1572                                                 KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetAt(m_Macro.FindIndex(i));\r
1573 //                                              CUtils::Log(_T("Macro MemMap: 3-2 %d"), i);\r
1574                                                 memcpy((LPTSTR) pView + i * sizeof(KbdMacro), pKbdMacro, sizeof(KbdMacro));\r
1575 //                                              CUtils::Log(_T("Macro MemMap: 3-3 %d"), i);\r
1576                                         }\r
1577 //                                      CUtils::Log(_T("Macro MemMap: 4"));\r
1578                                         UnmapViewOfFile(pView);\r
1579 //                                      CUtils::Log(_T("Macro MemMap: 5"));\r
1580                                 } else {\r
1581 //                                      CUtils::Log(_T("Macro MemMpa: error: %d"), GetLastError());\r
1582                                 }\r
1583                         } else {\r
1584 //                              CUtils::Log(_T("Macro MemMap: 6"));\r
1585                                 ASSERT(0);\r
1586                         }\r
1587                 }\r
1588         }\r
1589 }\r
1590 \r
1591 BOOL CXkeymacsDll::DefiningMacro()\r
1592 {\r
1593         return m_bDefiningMacro;\r
1594 }\r
1595 \r
1596 /**/ \r
1597 void CXkeymacsDll::CallMacro()\r
1598 {\r
1599         BOOL bIsCtrlDown = IsDown(VK_CONTROL);\r
1600         if (bIsCtrlDown) {\r
1601                 ReleaseKey(VK_CONTROL);\r
1602         }\r
1603         BOOL bIsAltDown = IsDown(VK_MENU);\r
1604         if (bIsAltDown) {\r
1605                 ReleaseKey(VK_MENU);\r
1606         }\r
1607         BOOL bIsShiftDown = IsDown(VK_SHIFT);\r
1608         if (bIsShiftDown) {\r
1609                 ReleaseKey(VK_SHIFT);\r
1610         }\r
1611 \r
1612         for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
1613                 KbdMacro *pKbdMacro = (KbdMacro *)m_Macro.GetNext(pos);\r
1614                 if (pKbdMacro->lParam & BEING_RELEASED) {\r
1615                         ReleaseKey((BYTE)pKbdMacro->wParam);\r
1616                 } else {\r
1617                         DepressKey((BYTE)pKbdMacro->wParam, pKbdMacro->bOriginal);\r
1618                 }\r
1619         }\r
1620 \r
1621         if (bIsCtrlDown) {\r
1622                 DepressKey(VK_CONTROL);\r
1623         }\r
1624         if (bIsAltDown) {\r
1625                 DepressKey(VK_MENU);\r
1626         }\r
1627         if (bIsShiftDown) {\r
1628                 DepressKey(VK_SHIFT);\r
1629         }\r
1630 }\r
1631 \r
1632 /*\r
1633 void CXkeymacsDll::CallMacro()  // for debug\r
1634 {\r
1635         CString sz;\r
1636         for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {\r
1637                 KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetNext(pos);\r
1638                 if (pKbdMacro->lParam & BEING_RELEASED) {\r
1639                         CString t;\r
1640                         t.Format(_T("0x%xu "), pKbdMacro->wParam);\r
1641                         sz += t;\r
1642                 } else {\r
1643                         CString t;\r
1644                         t.Format(_T("0x%xd "), pKbdMacro->wParam);\r
1645                         sz += t;\r
1646                 }\r
1647         }\r
1648 //      CUtils::Log(sz);\r
1649 }\r
1650 */\r
1651 \r
1652 void CXkeymacsDll::Set106Keyboard(BOOL b106Keyboard)\r
1653 {\r
1654         m_Config.b106Keyboard = b106Keyboard;\r
1655 }\r
1656 \r
1657 BOOL CXkeymacsDll::Is106Keyboard()\r
1658 {\r
1659         return m_Config.b106Keyboard;\r
1660 }\r
1661 \r
1662 int CXkeymacsDll::IsPassThrough(BYTE nKey)\r
1663 {\r
1664         BYTE bVk = 0;\r
1665         do {\r
1666                 if (IsDown(bVk)\r
1667                  && (Commands[m_Config.nCommandID[m_nApplicationID][NONE][bVk]].fCommand == CCommands::PassThrough)) {\r
1668                         if (bVk == nKey) {\r
1669                                 return GOTO_HOOK;\r
1670                         }\r
1671 \r
1672                         return GOTO_DO_NOTHING;\r
1673                 }\r
1674         } while (++bVk);\r
1675         return CONTINUE;\r
1676 }\r
1677 \r
1678 void CXkeymacsDll::SetKeyboardHookFlag()\r
1679 {\r
1680         SetKeyboardHookFlag(m_bHook);\r
1681 }\r
1682 \r
1683 void CXkeymacsDll::SetFunctionKey(int nFunctionID, int nApplicationID, int nCommandType, int nKey)\r
1684 {\r
1685         if (nApplicationID      < 0 || MAX_APP                  <= nApplicationID\r
1686          || nCommandType        < 0 || MAX_COMMAND_TYPE <= nCommandType\r
1687          || nKey                        < 0 || MAX_KEY                  <= nKey) {\r
1688                 return;\r
1689         }\r
1690 \r
1691         m_Config.nFunctionID[nApplicationID][nCommandType][nKey] = nFunctionID;\r
1692 }\r
1693 \r
1694 void CXkeymacsDll::ClearFunctionDefinition()\r
1695 {\r
1696         memset(m_Config.nFunctionID, -1, sizeof(m_Config.nFunctionID));\r
1697         memset(m_Config.szFunctionDefinition, 0, sizeof(m_Config.szFunctionDefinition));\r
1698 }\r
1699 \r
1700 void CXkeymacsDll::SetFunctionDefinition(int nFunctionID, CString szDefinition)\r
1701 {\r
1702         if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID) {\r
1703                 return;\r
1704         }\r
1705 \r
1706         memset(m_Config.szFunctionDefinition[nFunctionID], 0, sizeof(m_Config.szFunctionDefinition[nFunctionID]));\r
1707         _stprintf_s(m_Config.szFunctionDefinition[nFunctionID], _T("%s"), szDefinition);\r
1708 \r
1709         return;\r
1710 \r
1711 }\r
1712 \r
1713 // call an original command which is defined in dot.xkeymacs\r
1714 void CXkeymacsDll::CallFunction(int nFunctionID)\r
1715 {\r
1716         CArray<KeyBind, KeyBind> keybinds;\r
1717 \r
1718         if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID || !_tcslen(m_Config.szFunctionDefinition[nFunctionID])) {\r
1719                 return;\r
1720         }\r
1721 \r
1722         BOOL bIsCtrlDown = CXkeymacsDll::IsDown(VK_CONTROL);\r
1723         BOOL bIsAltDown = CXkeymacsDll::IsDown(VK_MENU);\r
1724         BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);\r
1725 \r
1726         if (m_Config.szFunctionDefinition[nFunctionID][0] == _T('"') && m_Config.szFunctionDefinition[nFunctionID][_tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1] == _T('"')) {\r
1727                 for (unsigned int i = 1; i < _tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1; ++i) {    // skip '"'\r
1728                         keybinds.Add(ParseKey(nFunctionID, i));\r
1729                 }\r
1730         } else if (m_Config.szFunctionDefinition[nFunctionID][0] == _T('[') && m_Config.szFunctionDefinition[nFunctionID][_tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1] == _T(']')) {\r
1731                 for (unsigned int i = 1; i < _tcslen(m_Config.szFunctionDefinition[nFunctionID]) - 1; ++i) {    // skip '[' and ']'\r
1732                         if (m_Config.szFunctionDefinition[nFunctionID][i] == _T('?')) { // [?f ?o ?o]\r
1733                                 ++i;\r
1734                                 keybinds.Add(ParseKey(nFunctionID, i));\r
1735                         } else {                                                                                                // [ControlCharacter]\r
1736                                 for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
1737                                         if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
1738                                                 KeyBind keybind = {NONE, ControlCharacters[nKeyID].bVk};\r
1739                                                 keybinds.Add(keybind);\r
1740                                                 i += _tcslen(ControlCharacters[nKeyID].name);\r
1741                                                 break;\r
1742                                         }\r
1743                                 }\r
1744                         }\r
1745                 }\r
1746         } else {\r
1747                 return;\r
1748         }\r
1749 \r
1750         BOOL bM_x = FALSE;\r
1751         TCHAR szPath[MAX_PATH] = {'\0'};\r
1752         unsigned int index = 0;\r
1753         BOOL bInitialized = FALSE;\r
1754 \r
1755         for (int i = 0; i < keybinds.GetSize(); ++i) {\r
1756                 const int nCommandType = keybinds.GetAt(i).nCommandType;\r
1757                 const BYTE bVk = keybinds.GetAt(i).bVk;\r
1758 \r
1759                 if (nCommandType < MAX_COMMAND_TYPE && Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand) {\r
1760                         if (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand == CCommands::ExecuteExtendedCommand) {\r
1761                                 bM_x = TRUE;\r
1762                         } else if (!bInitialized) {\r
1763                                 if (bIsCtrlDown) {\r
1764                                         CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
1765                                         ReleaseKey(VK_CONTROL);\r
1766                                 }\r
1767 \r
1768                                 if (bIsAltDown) {\r
1769                                         ReleaseKey(VK_MENU);\r
1770                                 }\r
1771 \r
1772                                 if (bIsShiftDown) {\r
1773                                         ReleaseKey(VK_SHIFT);\r
1774                                 }\r
1775 \r
1776                                 bInitialized = TRUE;\r
1777                         }\r
1778 //                      CUtils::Log("CallFunction: Command Name: %s", Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].szCommandName);\r
1779                         while (Commands[m_Config.nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand() == GOTO_RECURSIVE) {\r
1780                                 ;\r
1781                         }\r
1782                 } else if (bM_x) {\r
1783                         if (bVk == VK_RETURN) {\r
1784                                 InvokeM_x(szPath);\r
1785                         } else {\r
1786                                 for (TCHAR nAscii = 1; nAscii != 0; ++nAscii) { // repeat until overflow\r
1787                                         if (bVk != 0 && a2v(nAscii) == bVk && ((nCommandType & SHIFT) != 0) == IsShift(nAscii)) {\r
1788 //                                              CUtils::Log("M-x: %#X (%c), %#X (%c)", bVk, bVk, nAscii, nAscii);\r
1789                                                 szPath[index++] = nAscii;\r
1790                                                 break;\r
1791                                         }\r
1792                                 }\r
1793                         }\r
1794                 } else {\r
1795                         if (!bInitialized) {\r
1796                                 if (bIsCtrlDown) {\r
1797                                         CUtils::UpdateKeyboardState(VK_CONTROL, 0);\r
1798                                         ReleaseKey(VK_CONTROL);\r
1799                                 }\r
1800 \r
1801                                 if (bIsAltDown) {\r
1802                                         ReleaseKey(VK_MENU);\r
1803                                 }\r
1804 \r
1805                                 if (bIsShiftDown) {\r
1806                                         ReleaseKey(VK_SHIFT);\r
1807                                 }\r
1808 \r
1809                                 bInitialized = TRUE;\r
1810                         }\r
1811                         if (nCommandType & WIN_WIN) {\r
1812                                 DepressKey(VK_LWIN);\r
1813                         }\r
1814                         if (nCommandType & WIN_CTRL) {\r
1815                                 DepressKey(VK_CONTROL);\r
1816                         }\r
1817                         if (nCommandType & WIN_ALT) {\r
1818                                 DepressKey(VK_MENU);\r
1819                         }\r
1820                         if (nCommandType & SHIFT) {\r
1821                                 DepressKey(VK_SHIFT);\r
1822                         }\r
1823 \r
1824                         Kdu(bVk);\r
1825 \r
1826                         if (nCommandType & SHIFT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & SHIFT))) {\r
1827                                 ReleaseKey(VK_SHIFT);\r
1828                         }\r
1829                         if (nCommandType & WIN_ALT && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_ALT))) {\r
1830                                 ReleaseKey(VK_MENU);\r
1831                         }\r
1832                         if (nCommandType & WIN_CTRL && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_CTRL))) {\r
1833                                 ReleaseKey(VK_CONTROL);\r
1834                         }\r
1835                         if (nCommandType & WIN_WIN && (keybinds.GetSize() <= i + 1 || !(keybinds.GetAt(i + 1).nCommandType & WIN_WIN))) {\r
1836                                 ReleaseKey(VK_LWIN);\r
1837                         }\r
1838                 }\r
1839         }\r
1840 \r
1841         keybinds.RemoveAll();\r
1842 \r
1843         if (bInitialized) {\r
1844                 // If these lines are invoked at M-x, a window transition does not work well.\r
1845 \r
1846                 if (bIsShiftDown) {\r
1847                         DepressKey(VK_SHIFT);\r
1848                 }\r
1849 \r
1850                 if (bIsAltDown) {\r
1851                         DepressKey(VK_MENU);\r
1852                 }\r
1853 \r
1854                 if (bIsCtrlDown) {\r
1855                         DepressKey(VK_CONTROL);\r
1856                         CUtils::UpdateKeyboardState(VK_CONTROL, 1);\r
1857                 }\r
1858         }\r
1859         return;\r
1860 }\r
1861 \r
1862 KeyBind CXkeymacsDll::ParseKey(const int nFunctionID, unsigned int &i)\r
1863 {\r
1864         KeyBind keybind = {NONE};\r
1865 \r
1866         if (m_Config.szFunctionDefinition[nFunctionID][i] == _T('\\')) {\r
1867                 ++i;\r
1868                 BOOL bFound = FALSE;\r
1869                 do {\r
1870                         bFound = FALSE;\r
1871                         for (int ModifierID = 0; ModifierID < sizeof(Modifiers) / sizeof(Modifiers[0]); ++ModifierID) {\r
1872                                 if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, Modifiers[ModifierID].name, _tcslen(Modifiers[ModifierID].name))\r
1873                                  && _tcslen(Modifiers[ModifierID].name) < _tcslen(m_Config.szFunctionDefinition[nFunctionID] + i)) {\r
1874                                         keybind.nCommandType |= Modifiers[ModifierID].id;\r
1875                                         i+= _tcslen(Modifiers[ModifierID].name);\r
1876                                         bFound = TRUE;\r
1877                                 }\r
1878                         }\r
1879                 } while (bFound);\r
1880         }\r
1881         if (IsShift(m_Config.szFunctionDefinition[nFunctionID][i]) && !(keybind.nCommandType & (WIN_CTRL | WIN_ALT | WIN_WIN))) {\r
1882                 keybind.nCommandType |= SHIFT;\r
1883         }\r
1884 \r
1885         for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {\r
1886                 if (!_tcsncmp(m_Config.szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, _tcslen(ControlCharacters[nKeyID].name))) {\r
1887                         i += _tcslen(ControlCharacters[nKeyID].name);\r
1888                         break;\r
1889                 }\r
1890         }\r
1891         if (nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0])) {\r
1892                 keybind.bVk = ControlCharacters[nKeyID].bVk;\r
1893         } else {\r
1894                 keybind.bVk = a2v(m_Config.szFunctionDefinition[nFunctionID][i]);\r
1895         }\r
1896 \r
1897         return keybind;\r
1898 }\r
1899 \r
1900 BOOL CXkeymacsDll::IsShift(TCHAR nAscii)\r
1901 {\r
1902         switch (nAscii) {\r
1903         case _T(' '):\r
1904                 return FALSE;\r
1905         case _T('!'):\r
1906         case _T('"'):\r
1907         case _T('#'):\r
1908         case _T('$'):\r
1909         case _T('%'):\r
1910         case _T('&'):\r
1911                 return TRUE;\r
1912         case _T('\''):\r
1913                 return m_Config.b106Keyboard;\r
1914         case _T('('):\r
1915         case _T(')'):\r
1916         case _T('*'):\r
1917         case _T('+'):\r
1918                 return TRUE;\r
1919         case _T(','):\r
1920         case _T('-'):\r
1921         case _T('.'):\r
1922         case _T('/'):\r
1923         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
1924                 return FALSE;\r
1925         case _T(':'):\r
1926                 return !m_Config.b106Keyboard;\r
1927         case _T(';'):\r
1928                 return FALSE;\r
1929         case _T('<'):\r
1930                 return TRUE;\r
1931         case _T('='):\r
1932                 return m_Config.b106Keyboard;\r
1933         case _T('>'):\r
1934         case _T('?'):\r
1935                 return TRUE;\r
1936         case _T('@'):\r
1937                 return !m_Config.b106Keyboard;\r
1938         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
1939         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
1940         case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
1941                 return TRUE;\r
1942         case _T('['):\r
1943         case _T('\\'):\r
1944         case _T(']'):\r
1945                 return FALSE;\r
1946         case _T('^'):\r
1947                 return !m_Config.b106Keyboard;\r
1948         case _T('_'):\r
1949                 return TRUE;\r
1950         case _T('`'):\r
1951                 return m_Config.b106Keyboard;\r
1952         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
1953         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
1954         case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
1955                 return FALSE;\r
1956         case _T('{'):\r
1957         case _T('|'):\r
1958         case _T('}'):\r
1959         case _T('~'):\r
1960                 return TRUE;\r
1961         default:\r
1962                 return FALSE;\r
1963         }\r
1964 }\r
1965 \r
1966 BYTE CXkeymacsDll::a2v(TCHAR nAscii)\r
1967 {\r
1968         switch (nAscii) {\r
1969         case _T(' '):\r
1970                 return VK_SPACE;\r
1971         case _T('!'):\r
1972                 return '1';\r
1973         case _T('"'):\r
1974                 return m_Config.b106Keyboard ? '2' : (BYTE) 0xde;       // VK_OEM_7\r
1975         case _T('#'):\r
1976                 return '3';\r
1977         case _T('$'):\r
1978                 return '4';\r
1979         case _T('%'):\r
1980                 return '5';\r
1981         case _T('&'):\r
1982                 return m_Config.b106Keyboard ? '6' : '7';\r
1983         case _T('\''):\r
1984                 return m_Config.b106Keyboard ? '7' : (BYTE) 0xde;       // VK_OEM_7\r
1985         case _T('('):\r
1986                 return m_Config.b106Keyboard ? '8' : '9';\r
1987         case _T(')'):\r
1988                 return m_Config.b106Keyboard ? '9' : '0';\r
1989         case _T('*'):\r
1990                 return m_Config.b106Keyboard ? (BYTE) 0xba : '8';       // VK_OEM_1\r
1991         case _T('+'):\r
1992                 return 0xbb;    // VK_OEM_PLUS\r
1993         case _T(','):\r
1994                 return 0xbc;    // VK_OEM_COMMA\r
1995         case _T('-'):\r
1996                 return 0xbd;    // VK_OEM_MINUS\r
1997         case _T('.'):\r
1998                 return 0xbe;    // VK_OEM_PERIOD\r
1999         case _T('/'):\r
2000                 return 0xbf;    // VK_OEM_2\r
2001         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
2002                 return nAscii;\r
2003         case _T(':'):\r
2004                 return 0xba;    // VK_OEM_1\r
2005         case _T(';'):\r
2006                 return m_Config.b106Keyboard ? (BYTE) 0xbb : (BYTE) 0xba;       // VK_OEM_PLUS  VK_OEM_1\r
2007         case _T('<'):\r
2008                 return 0xbc;    // VK_OEM_COMMA\r
2009         case _T('='):\r
2010                 return m_Config.b106Keyboard ? (BYTE) 0xbd : (BYTE) 0xbb;       // VK_OEM_MINUS VK_OEM_PLUS\r
2011         case _T('>'):\r
2012                 return 0xbe;    // VK_OEM_PERIOD\r
2013         case _T('?'):\r
2014                 return 0xbf;    // VK_OEM_2\r
2015         case _T('@'):\r
2016                 return m_Config.b106Keyboard ? (BYTE) 0xc0 : '2';\r
2017         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
2018         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
2019         case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'): \r
2020                 return nAscii;\r
2021         case _T('['):\r
2022                 return 0xdb;    // VK_OEM_4\r
2023         case _T('\\'):\r
2024                 return 0xdc;    // VK_OEM_5\r
2025         case _T(']'):\r
2026                 return 0xdd;    // VK_OEM_6\r
2027         case _T('^'):\r
2028                 return m_Config.b106Keyboard ? (BYTE) 0xde : '6';       // VK_OEM_7\r
2029         case _T('_'):\r
2030                 return m_Config.b106Keyboard ? (BYTE) 0xe2 : (BYTE) 0xbd;       // VK_OEM_102   VK_OEM_MINUS\r
2031         case _T('`'):\r
2032                 return 0xc0;    // VK_OEM_3\r
2033         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
2034         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
2035         case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'): \r
2036                 return (BYTE) (nAscii - (_T('a') - _T('A')));\r
2037         case _T('{'):\r
2038                 return 0xdb;    // VK_OEM_4\r
2039         case _T('|'):\r
2040                 return 0xdc;    // VK_OEM_5\r
2041         case _T('}'):\r
2042                 return 0xdd;    // VK_OEM_6\r
2043         case _T('~'):\r
2044                 return m_Config.b106Keyboard ? (BYTE) 0xde : (BYTE) 0xc0;       // VK_OEM_7     VK_OEM_3\r
2045         default:\r
2046                 return 0;\r
2047         }\r
2048 }\r
2049 \r
2050 BOOL CXkeymacsDll::IsMatchWindowText(CString szWindowText)\r
2051 {\r
2052         BOOL bIsMatchWindowText = TRUE;\r
2053 \r
2054         TCHAR szCurrentWindowText[WINDOW_TEXT_LENGTH] = {'\0'};\r
2055         GetWindowText(GetForegroundWindow(), szCurrentWindowText, sizeof(szCurrentWindowText));\r
2056 \r
2057         switch (CUtils::GetWindowTextType(szWindowText)) {\r
2058         case IDS_WINDOW_TEXT_MATCH:                                                             // *foo*\r
2059                 szWindowText.Delete(0);                                                         // Delete first '*'\r
2060                 szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
2061                 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText);\r
2062                 break;\r
2063         case IDS_WINDOW_TEXT_MATCH_FORWARD:                                             // foo*\r
2064                 szWindowText.Delete(szWindowText.GetLength() - 1);      // Delete last '*'\r
2065                 bIsMatchWindowText = 0 == CString(szCurrentWindowText).Find(szWindowText);\r
2066                 break;\r
2067         case IDS_WINDOW_TEXT_MATCH_BACKWARD:                                    // *foo\r
2068                 szWindowText.Delete(0);                                                         // Delete first '*'\r
2069                 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText, CString(szCurrentWindowText).GetLength() - szWindowText.GetLength());\r
2070                 break;\r
2071         case IDS_WINDOW_TEXT_MATCH_FULL:                                                // foo\r
2072                 bIsMatchWindowText = szWindowText == CString(szCurrentWindowText);\r
2073                 break;\r
2074         case IDS_WINDOW_TEXT_IGNORE:                                                    // *\r
2075                 bIsMatchWindowText = TRUE;\r
2076                 break;\r
2077         default:\r
2078                 ASSERT(0);\r
2079                 break;\r
2080         }\r
2081 \r
2082 //      CUtils::Log(_T("IsMatchWindowText: %d, _%s_, _%s_"), bIsMatchWindowText, szCurrentWindowText, szWindowText);\r
2083         return bIsMatchWindowText;\r
2084 }\r
2085 \r
2086 void CXkeymacsDll::SetAccelerate(int nAccelerate)\r
2087 {\r
2088         m_nAccelerate = nAccelerate;\r
2089 }\r
2090 \r
2091 int CXkeymacsDll::GetAccelerate()\r
2092 {\r
2093         return m_nAccelerate;\r
2094 }\r
2095 \r
2096 void CXkeymacsDll::SetKeyboardSpeed(int nKeyboardSpeed)\r
2097 {\r
2098         m_nKeyboardSpeed = nKeyboardSpeed;\r
2099 }\r
2100 \r
2101 unsigned int CXkeymacsDll::GetMaxKeyInterval()\r
2102 {\r
2103         // m_nKeyboardSpeed == 0:       slowest repeat rate; approximately  2 characters per second\r
2104         // m_nKeyboardSpeed == 31:      fastest repeat rate; approximately 30 characters per second\r
2105         // 47 ms is max on my machine w/ KeyboardSpeed 31.\r
2106         // 1000 /  2 + 50 = 550\r
2107         // 1000 / 30 + 50 = 83\r
2108         return (unsigned int) (1000.0 / (2.0 + m_nKeyboardSpeed % 32 * 28.0 / 31.0) + 50.0);\r
2109 }\r
2110 \r
2111 void CXkeymacsDll::SetCursorData(HCURSOR hEnable, HCURSOR hDisableTMP, HCURSOR hDisableWOCQ, HICON hDisable, BOOL bEnable)\r
2112 {\r
2113         m_hCursor[STATUS_ENABLE] = hEnable;\r
2114         m_hCursor[STATUS_DISABLE_TMP] = hDisableTMP;\r
2115         m_hCursor[STATUS_DISABLE_WOCQ] = hDisableWOCQ;\r
2116         m_hCursor[STATUS_DISABLE] = hDisable;\r
2117         m_bCursor = bEnable;\r
2118 }\r
2119 \r
2120 void CXkeymacsDll::DoSetCursor()\r
2121 {\r
2122         if (m_bCursor && m_hCurrentCursor) {\r
2123                 ::SetCursor(m_hCurrentCursor);\r
2124         }\r
2125 }\r
2126 \r
2127 void CXkeymacsDll::Set326Compatible(int nApplicationID, BOOL b326Compatible)\r
2128 {\r
2129         m_Config.b326Compatible[nApplicationID] = b326Compatible;\r
2130 }\r
2131 \r
2132 BOOL CXkeymacsDll::Get326Compatible()\r
2133 {\r
2134         return m_Config.b326Compatible[m_nApplicationID];\r
2135 }\r
2136 \r
2137 void CXkeymacsDll::InvokeM_x(const TCHAR *const szPath)\r
2138 {\r
2139 //      CUtils::Log("M-x: szPath=_%s_", szPath);\r
2140         int (*fCommand)() = NULL;\r
2141 \r
2142         for (int i = 0; i < MAX_COMMAND; ++i) {\r
2143                 if (_tcsicmp(szPath, Commands[i].szCommandName) == 0) {\r
2144                         fCommand = Commands[i].fCommand;\r
2145                         break;\r
2146                 }\r
2147         }\r
2148 \r
2149         if (fCommand) {\r
2150 //              CUtils::Log("M-x: Command: _%s_", Commands[i].szCommandName);\r
2151                 fCommand();\r
2152         } else {\r
2153 //              CUtils::Log("M-x: Path: _%s_", szPath);\r
2154                 ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);\r
2155         }\r
2156 }\r
2157 \r
2158 void CXkeymacsDll::SetM_xTip(const TCHAR *const szPath)\r
2159 {\r
2160         _tcscpy_s(m_M_xTip, "M-x LED");\r
2161         if (szPath && _tcslen(szPath) < 128 - 5)\r
2162                 _stprintf_s(m_M_xTip, "M-x %s", szPath);\r
2163 }\r
2164 \r
2165 BOOL CXkeymacsDll::SendIconMessage(ICONMSG *pMsg, DWORD num)\r
2166 {\r
2167         DWORD ack, read;\r
2168         return CallNamedPipe(ICON_PIPE, pMsg, sizeof(ICONMSG) * num, &ack, sizeof(DWORD), &read, NMPWAIT_NOWAIT);\r
2169 }\r