OSDN Git Service

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