1 // xkeymacsdll.cpp : Defines the initialization routines for the DLL.
\r
5 #include "resource.h"
\r
7 #include "Commands.h"
\r
14 #define new DEBUG_NEW
\r
16 static char THIS_FILE[] = __FILE__;
\r
24 static const Modifier Modifiers[] = {
\r
25 // { _T("A-"), ALT },
\r
26 { _T("C-"), CONTROL},
\r
27 // { _T("H-"), HYPER },
\r
29 { _T("S-"), SHIFT },
\r
30 // { _T("s-"), SUPER },
\r
31 { _T("Ctrl+"), WIN_CTRL },
\r
32 { _T("Alt+"), WIN_ALT },
\r
33 { _T("Win+"), WIN_WIN },
\r
35 static const int MAX_MODIFIER = _countof(Modifiers);
\r
37 static const KeyName KeyNames[] = {
\r
38 // { VK_LBUTTON, _T("mouse-1") }, // does not work well
\r
39 // { VK_RBUTTON, _T("mouse-3") }, // does not work well
\r
40 { VK_CANCEL, _T("break") },
\r
41 // { VK_MBUTTON, _T("mouse-2") }, // does not work well
\r
42 { VK_BACK, _T("backspace") },
\r
43 { VK_TAB, _T("tab") },
\r
44 { VK_RETURN, _T("return") },
\r
45 { VK_CAPITAL, _T("capslock") },
\r
46 { VK_KANA, _T("kana") },
\r
47 { VK_KANJI, _T("kanji") },
\r
48 { VK_ESCAPE, _T("escape") },
\r
49 { VK_CONVERT, _T("convert") },
\r
50 { VK_NONCONVERT, _T("nonconvert") },
\r
51 // { VK_SPACE, _T("SPC") }, // [? ]
\r
52 { VK_PRIOR, _T("prior") },
\r
53 { VK_NEXT, _T("next") },
\r
54 { VK_END, _T("end") },
\r
55 { VK_HOME, _T("home") },
\r
56 { VK_LEFT, _T("left") },
\r
57 { VK_UP, _T("up") },
\r
58 { VK_RIGHT, _T("right") },
\r
59 { VK_DOWN, _T("down") },
\r
60 { VK_SELECT, _T("select") },
\r
61 { VK_PRINT, _T("print") },
\r
62 { VK_EXECUTE, _T("execute") },
\r
63 { VK_SNAPSHOT, _T("printscreen") }, // work as print
\r
64 { VK_INSERT, _T("insert") },
\r
65 { VK_DELETE, _T("delete") },
\r
66 { VK_LWIN, _T("lwindow") },
\r
67 { VK_RWIN, _T("rwindow") },
\r
68 { VK_APPS, _T("apps") },
\r
69 { VK_SLEEP, _T("sleep") },
\r
70 { VK_NUMPAD0, _T("kp-0") },
\r
71 { VK_NUMPAD1, _T("kp-1") },
\r
72 { VK_NUMPAD2, _T("kp-2") },
\r
73 { VK_NUMPAD3, _T("kp-3") },
\r
74 { VK_NUMPAD4, _T("kp-4") },
\r
75 { VK_NUMPAD5, _T("kp-5") },
\r
76 { VK_NUMPAD6, _T("kp-6") },
\r
77 { VK_NUMPAD7, _T("kp-7") },
\r
78 { VK_NUMPAD8, _T("kp-8") },
\r
79 { VK_NUMPAD9, _T("kp-9") },
\r
80 { VK_MULTIPLY, _T("kp-multiply") },
\r
81 { VK_ADD, _T("kp-add") },
\r
82 { VK_SUBTRACT, _T("kp-subtract") },
\r
83 { VK_DECIMAL, _T("kp-decimal") },
\r
84 { VK_DIVIDE, _T("kp-divide") },
\r
85 // { VK_F1, _T("f1") }, // FIXME
\r
86 // { VK_F2, _T("f2") }, // Move at the end of definition of function keys to keep away confliction f1/f2 and f1?/f2? by _tcsncmp() i.e. strncmp()
\r
87 { VK_F3, _T("f3") },
\r
88 { VK_F4, _T("f4") },
\r
89 { VK_F5, _T("f5") },
\r
90 { VK_F6, _T("f6") },
\r
91 { VK_F7, _T("f7") },
\r
92 { VK_F8, _T("f8") },
\r
93 { VK_F9, _T("f9") },
\r
94 { VK_F10, _T("f10") },
\r
95 { VK_F11, _T("f11") },
\r
96 { VK_F12, _T("f12") },
\r
97 { VK_F13, _T("f13") },
\r
98 { VK_F14, _T("f14") },
\r
99 { VK_F15, _T("f15") },
\r
100 { VK_F16, _T("f16") },
\r
101 { VK_F17, _T("f17") },
\r
102 { VK_F18, _T("f18") },
\r
103 { VK_F19, _T("f19") },
\r
104 { VK_F20, _T("f20") },
\r
105 { VK_F21, _T("f21") },
\r
106 { VK_F22, _T("f22") },
\r
107 { VK_F23, _T("f23") },
\r
108 { VK_F24, _T("f24") },
\r
109 { VK_F1, _T("f1") },
\r
110 { VK_F2, _T("f2") },
\r
111 { VK_NUMLOCK, _T("kp-numlock") },
\r
112 { VK_SCROLL, _T("scroll") },
\r
113 { 0xa6, _T("browser-back") }, // VK_BROWSER_BACK
\r
114 { 0xa7, _T("browser-forward") }, // VK_BROWSER_FORWARD
\r
115 { 0xa8, _T("browser-refresh") }, // VK_BROWSER_REFRESH
\r
116 { 0xa9, _T("browser-stop") }, // VK_BROWSER_STOP
\r
117 { 0xaa, _T("browser-search") }, // VK_BROWSER_SEARCH
\r
118 { 0xab, _T("browser-favorites") }, // VK_BROWSER_FAVORITES
\r
119 { 0xac, _T("browser-home") }, // VK_BROWSER_HOME
\r
120 { 0xad, _T("volume-mute") }, // VK_VOLUME_MUTE
\r
121 { 0xae, _T("volume-down") }, // VK_VOLUME_DOWN
\r
122 { 0xaf, _T("volume-up") }, // VK_VOLUME_UP
\r
123 { 0xb0, _T("media-next-track") }, // VK_MEDIA_NEXT_TRACK
\r
124 { 0xb1, _T("media-prev-track") }, // VK_MEDIA_PREV_TRACK
\r
125 { 0xb2, _T("media-stop") }, // VK_MEDIA_STOP
\r
126 { 0xb3, _T("media-play-pause") }, // VK_MEDIA_PLAY_PAUSE
\r
127 { 0xb4, _T("launch-mail") }, // VK_LAUNCH_MAIL
\r
128 { 0xb5, _T("launch-media-select") }, // VK_LAUNCH_MEDIA_SELECT
\r
129 { 0xb6, _T("launch-1") }, // VK_LAUNCH_APP1
\r
130 { 0xb7, _T("launch-2") }, // VK_LAUNCH_APP2
\r
132 static const int MAX_KEYNAME = _countof(KeyNames);
\r
134 static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL };
\r
136 static HINSTANCE g_hDllInst = NULL;
\r
137 static DWORD g_TlsIndex = NULL;
\r
139 extern "C" int APIENTRY
\r
140 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
\r
142 g_hDllInst = hInstance;
\r
145 // Remove this if you use lpReserved
\r
146 UNREFERENCED_PARAMETER(lpReserved);
\r
148 switch (dwReason) {
\r
149 case DLL_PROCESS_ATTACH:
\r
150 TRACE0("XKEYMACSDLL.DLL Initializing!\n");
\r
152 // Extension DLL one-time initialization
\r
153 if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) {
\r
157 // Insert this DLL into the resource chain
\r
158 // NOTE: If this Extension DLL is being implicitly linked to by
\r
159 // an MFC Regular DLL (such as an ActiveX Control)
\r
160 // instead of an MFC application, then you will want to
\r
161 // remove this line from DllMain and put it in a separate
\r
162 // function exported from this Extension DLL. The Regular DLL
\r
163 // that uses this Extension DLL should then explicitly call that
\r
164 // function to initialize this Extension DLL. Otherwise,
\r
165 // the CDynLinkLibrary object will not be attached to the
\r
166 // Regular DLL's resource chain, and serious problems will
\r
170 new CDynLinkLibrary(XkeymacsdllDLL);
\r
172 catch (CMemoryException* e) {
\r
174 // CUtils::Log("DllMain: 'new' threw an exception");
\r
177 if ((g_TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
\r
180 case DLL_THREAD_ATTACH:
\r
181 if ((lpData = LocalAlloc(LPTR, sizeof(HHOOK))) != NULL)
\r
182 TlsSetValue(g_TlsIndex, lpData);
\r
184 case DLL_PROCESS_DETACH:
\r
185 TRACE0("XKEYMACSDLL.DLL Terminating!\n");
\r
186 // Terminate the library before destructors are called
\r
187 AfxTermExtensionModule(XkeymacsdllDLL);
\r
188 CXkeymacsDll::ReleaseKeyboardHook();
\r
189 if ((lpData = TlsGetValue(g_TlsIndex)) != NULL)
\r
191 TlsFree(g_TlsIndex);
\r
193 case DLL_THREAD_DETACH:
\r
194 CXkeymacsDll::ReleaseKeyboardHook();
\r
195 if ((lpData = TlsGetValue(g_TlsIndex)) != NULL)
\r
202 //////////////////////////////////////////////////////////////////////
\r
203 // CXkeymacsDll Class
\r
204 //////////////////////////////////////////////////////////////////////
\r
206 #include "xkeymacsDll.h"
\r
207 #pragma data_seg(".xkmcs")
\r
208 bool CXkeymacsDll::m_bEnableKeyboardHook = false;
\r
209 DWORD CXkeymacsDll::m_nHookAltRelease = 0;
\r
210 HHOOK CXkeymacsDll::m_hHookCallWnd = NULL;
\r
211 HHOOK CXkeymacsDll::m_hHookCallWndRet = NULL;
\r
212 HHOOK CXkeymacsDll::m_hHookGetMessage = NULL;
\r
213 HHOOK CXkeymacsDll::m_hHookShell = NULL;
\r
214 BOOL CXkeymacsDll::m_bRightControl = FALSE;
\r
215 BOOL CXkeymacsDll::m_bRightAlt = FALSE;
\r
216 BOOL CXkeymacsDll::m_bRightShift = FALSE;
\r
217 BOOL CXkeymacsDll::m_bHook = TRUE;
\r
218 CList<CClipboardSnap *, CClipboardSnap *> CXkeymacsDll::m_oKillRing;
\r
219 int CXkeymacsDll::m_nKillRing = 0;
\r
220 BYTE CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
\r
221 int CXkeymacsDll::m_nAppID = 0;
\r
222 int CXkeymacsDll::m_nAccelerate = 0;
\r
223 int CXkeymacsDll::m_nKeyboardSpeed = 31;
\r
224 HCURSOR CXkeymacsDll::m_hCursor[MAX_STATUS] = {'\0'};
\r
225 HCURSOR CXkeymacsDll::m_hCurrentCursor = NULL;
\r
226 BOOL CXkeymacsDll::m_bCursor = FALSE;
\r
227 TCHAR CXkeymacsDll::m_M_xTip[128] = "";
\r
228 CONFIG CXkeymacsDll::m_Config = {0};
\r
230 BOOL CXkeymacsDll::m_bRecordingMacro = FALSE;
\r
231 BOOL CXkeymacsDll::m_bDown[MAX_KEY] = {0};
\r
232 std::list<KbdMacro> CXkeymacsDll::m_Macro;
\r
234 BOOL CXkeymacsDll::SaveConfig()
\r
236 TCHAR szTmp[MAX_PATH];
\r
237 if (!GetTempPath(MAX_PATH, szTmp))
\r
239 if (_tmakepath_s(szTmp, NULL, szTmp, _T("xkeymacs"), _T("tmp")))
\r
241 HANDLE hFile = CreateFile(szTmp, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
\r
242 if (hFile == INVALID_HANDLE_VALUE)
\r
245 BOOL res = WriteFile(hFile, &m_Config, sizeof(m_Config), &written, NULL) || written != sizeof(m_Config);
\r
246 CloseHandle(hFile);
\r
250 BOOL CXkeymacsDll::LoadConfig()
\r
252 TCHAR szTmp[MAX_PATH];
\r
253 if (!GetTempPath(MAX_PATH, szTmp))
\r
255 if (_tmakepath_s(szTmp, NULL, szTmp, _T("xkeymacs"), _T("tmp")))
\r
257 HANDLE hFile = CreateFile(szTmp, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
\r
258 if (hFile == INVALID_HANDLE_VALUE)
\r
261 BOOL res = ReadFile(hFile, &m_Config, sizeof(m_Config), &read, NULL) && read == sizeof(m_Config);
\r
262 CloseHandle(hFile);
\r
266 void CXkeymacsDll::SetConfig(const CONFIG& config)
\r
271 void CXkeymacsDll::SetHooks()
\r
273 m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);
\r
274 m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);
\r
275 m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);
\r
276 m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);
\r
277 m_bEnableKeyboardHook = true;
\r
280 void CXkeymacsDll::SetKeyboardHook()
\r
282 HHOOK *phHook = reinterpret_cast<HHOOK *>(TlsGetValue(g_TlsIndex));
\r
286 *phHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, GetCurrentThreadId());
\r
289 inline void unhook(HHOOK &hh)
\r
292 UnhookWindowsHookEx(hh);
\r
296 void CXkeymacsDll::ResetHooks()
\r
302 void CXkeymacsDll::ReleaseHooks()
\r
304 unhook(m_hHookCallWnd);
\r
305 unhook(m_hHookCallWndRet);
\r
306 unhook(m_hHookGetMessage);
\r
307 unhook(m_hHookShell);
\r
308 m_bEnableKeyboardHook = false;
\r
311 void CXkeymacsDll::ReleaseKeyboardHook()
\r
313 HHOOK *phHook = reinterpret_cast<HHOOK *>(TlsGetValue(g_TlsIndex));
\r
318 void CXkeymacsDll::ToggleKeyboardHookState()
\r
320 m_bHook = !m_bHook;
\r
321 ShowKeyboardHookState();
\r
324 void CXkeymacsDll::ShowKeyboardHookState()
\r
326 ICONMSG msg = {MAIN_ICON,};
\r
328 if (CCommands::IsTemporarilyDisableXKeymacs()) {
\r
329 msg.nState = STATUS_DISABLE_TMP;
\r
330 m_hCurrentCursor = m_hCursor[STATUS_DISABLE_TMP];
\r
332 msg.nState = STATUS_ENABLE;
\r
333 m_hCurrentCursor = m_hCursor[STATUS_ENABLE];
\r
336 msg.nState = STATUS_DISABLE_WOCQ;
\r
338 if (m_Config.nSettingStyle[m_nAppID] == SETTING_DISABLE
\r
339 || (!_tcsicmp(m_Config.szSpecialApp[m_nAppID], _T("Default"))
\r
340 && CUtils::IsDefaultIgnoreApplication())) {
\r
341 msg.nState = STATUS_DISABLE;
\r
342 m_hCurrentCursor = m_hCursor[STATUS_DISABLE];
\r
344 SendIconMessage(&msg, 1);
\r
348 BOOL CXkeymacsDll::IsKeyboardHook()
\r
353 LRESULT CALLBACK CXkeymacsDll::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
\r
357 return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);
\r
358 const CWPSTRUCT *cwps = reinterpret_cast<CWPSTRUCT *>(lParam);
\r
359 switch (cwps->message) {
\r
360 case WM_IME_STARTCOMPOSITION:
\r
361 InitKeyboardProc(TRUE);
\r
363 case WM_IME_ENDCOMPOSITION:
\r
364 InitKeyboardProc(FALSE);
\r
367 if (cwps->hwnd == GetForegroundWindow()) {
\r
368 InitKeyboardProc(FALSE);
\r
369 ShowKeyboardHookState();
\r
372 case WM_NCACTIVATE:
\r
373 if (cwps->wParam && cwps->hwnd == GetForegroundWindow()) {
\r
374 InitKeyboardProc(FALSE);
\r
375 ShowKeyboardHookState();
\r
379 return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);
\r
382 LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
\r
385 const CWPRETSTRUCT *cwprets = reinterpret_cast<CWPRETSTRUCT *>(lParam);
\r
386 switch (cwprets->message) {
\r
388 if (cwprets->hwnd == GetForegroundWindow())
\r
389 InitKeyboardProc(FALSE);
\r
396 return CallNextHookEx(m_hHookCallWndRet, nCode, wParam, lParam);
\r
399 LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
\r
401 const MSG *msg = reinterpret_cast<MSG *>(lParam);
\r
402 switch (msg->message) {
\r
403 case WM_IME_STARTCOMPOSITION:
\r
404 InitKeyboardProc(TRUE);
\r
406 case WM_IME_ENDCOMPOSITION:
\r
407 InitKeyboardProc(FALSE);
\r
410 return CallNextHookEx(m_hHookGetMessage, nCode, wParam, lParam);
\r
413 LRESULT CALLBACK CXkeymacsDll::ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
\r
415 if (nCode == HSHELL_WINDOWACTIVATED) {
\r
416 TCHAR className[256];
\r
417 GetClassName((HWND)wParam, className, 255);
\r
418 if (!_tcsicmp(className, _T("ConsoleWindowClass"))) {
\r
419 InitKeyboardProc(FALSE);
\r
420 ShowKeyboardHookState();
\r
423 return CallNextHookEx( m_hHookShell, nCode, wParam, lParam );
\r
426 UINT CXkeymacsDll::GetModifierState(BOOL bPhysicalKey)
\r
429 if (IsDown(VK_SHIFT, bPhysicalKey))
\r
431 if (IsDown(VK_CONTROL, bPhysicalKey))
\r
433 if (IsDown(VK_MENU, bPhysicalKey))
\r
438 void CXkeymacsDll::SetModifierState(const UINT after, const UINT before)
\r
440 if (after & SHIFT && !(before & SHIFT))
\r
441 DepressKey(VK_SHIFT);
\r
442 else if (!(after & SHIFT) && before & SHIFT)
\r
443 ReleaseKey(VK_SHIFT);
\r
445 if (after & CONTROL && !(before & CONTROL)) {
\r
446 UpdateKeyboardState(VK_CONTROL, 1);
\r
447 DepressKey(VK_CONTROL);
\r
448 } else if (!(after & CONTROL) && before & CONTROL) {
\r
449 ReleaseKey(VK_CONTROL);
\r
450 UpdateKeyboardState(VK_CONTROL, 0);
\r
453 const BOOL bHookApp = CUtils::IsVisualCpp() || CUtils::IsFirefox() || CUtils::IsVisualStudio() || CUtils::IsInternetExplorer();
\r
454 if (after & META && !(before & META)) {
\r
456 m_nHookAltRelease |= HOOK_ALT_LATER;
\r
457 DepressKey(VK_MENU);
\r
458 } else if (!(after & META) && before & META) {
\r
460 ++m_nHookAltRelease;
\r
461 ReleaseKey(VK_MENU);
\r
465 BOOL CXkeymacsDll::UpdateKeyboardState(BYTE bVk, BYTE bState)
\r
467 BYTE ks[256] = {'\0'};
\r
468 if (!GetKeyboardState(ks))
\r
471 return SetKeyboardState(ks);
\r
474 BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)
\r
476 return bPhysicalKey ? GetAsyncKeyState(bVk) < 0 : GetKeyState(bVk) < 0;
\r
480 void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)
\r
482 // Set KEYEVENTF_EXTENDEDKEY if needed
\r
485 if (m_bRightControl)
\r
486 dwFlags |= KEYEVENTF_EXTENDEDKEY;
\r
491 dwFlags |= KEYEVENTF_EXTENDEDKEY;
\r
495 if (m_bRightShift) {
\r
496 if (CUtils::IsXPorLater())
\r
499 dwFlags |= KEYEVENTF_EXTENDEDKEY;
\r
503 if (IsDown(VK_CONTROL, FALSE)) // Break
\r
504 dwFlags |= KEYEVENTF_EXTENDEDKEY;
\r
518 dwFlags |= KEYEVENTF_EXTENDEDKEY;
\r
521 // CUtils::Log(_T("b: %x, %x, %x, %#hx, %#hx"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));
\r
522 keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());
\r
523 // CUtils::Log(_T("a: %x, %x, %x, %#hx, %#hx"), bVk, dwFlags, GetMessageExtraInfo(), GetKeyState(bVk), GetAsyncKeyState(bVk));
\r
526 // the key is being depressed
\r
527 void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal) // bVk is virtual-key code, MSDN said
\r
530 // CUtils::Log(_T("i: %x, %d, %d, %d, %d, %d, %d, %d, %d"), bVk,
\r
531 // IsDown(VK_CONTROL), IsDown(VK_CONTROL, FALSE), IsDepressedModifier(CCommands::C_), IsDepressedModifier(CCommands::C_, FALSE),
\r
532 // IsDown(VK_MENU), IsDown(VK_MENU, FALSE), IsDepressedModifier(CCommands::MetaAlt), IsDepressedModifier(CCommands::MetaAlt, FALSE));
\r
533 SetOriginal(GetModifierState(), bVk);
\r
535 DoKeybd_event(bVk, 0);
\r
538 // the key is being released
\r
539 void CXkeymacsDll::ReleaseKey(BYTE bVk) // bVk is virtual-key code, MSDN said
\r
541 DoKeybd_event(bVk, KEYEVENTF_KEYUP);
\r
544 // bVk down, bVk up
\r
545 void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)
\r
548 DepressKey(bVk, bOriginal);
\r
553 void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)
\r
555 CUtils::SetApplicationName(bImeComposition);
\r
556 if (_tcsnicmp(m_Config.szSpecialApp[m_nAppID], CUtils::GetApplicationName(), 0xF) || !IsMatchWindowText(m_Config.szWindowText[m_nAppID])) { // PROCESSENTRY32 has only 0xF bytes of Name
\r
558 for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {
\r
559 if (_tcsnicmp(m_Config.szSpecialApp[nAppID], CUtils::GetApplicationName(), 0xF) || !IsMatchWindowText(m_Config.szWindowText[nAppID]))
\r
564 const LPCSTR curText = m_Config.szWindowText[m_nAppID];
\r
565 const LPCSTR newText = m_Config.szWindowText[nAppID];
\r
566 const int curType = CUtils::GetWindowTextType(curText);
\r
567 const int newType = CUtils::GetWindowTextType(newText);
\r
568 if (curType < newType || curType == newType && _tcscmp(curText, newText) <= 0)
\r
573 m_nAppID = GetAppID(_T("Default"), 0);
\r
575 if (m_Config.nSettingStyle[m_nAppID] != SETTING_DISABLE &&
\r
576 (_tcsicmp(m_Config.szSpecialApp[m_nAppID], _T("Default")) || !CUtils::IsDefaultIgnoreApplication()) &&
\r
577 !bImeComposition && CUtils::IsDialog() && m_Config.bUseDialogSetting[m_nAppID])
\r
578 // Use Dialog Setting
\r
579 m_nAppID = GetAppID(_T("Dialog"), m_nAppID);
\r
582 {CX_ICON, OFF_ICON, ""},
\r
583 {MX_ICON, OFF_ICON, ""},
\r
584 {META_ICON, OFF_ICON, ""}
\r
586 SendIconMessage(msg, 3);
\r
587 CCommands::SetMark(FALSE);
\r
588 CCommands::SetTemporarilyDisableXKeymacs(FALSE);
\r
589 CCommands::Reset();
\r
592 int CXkeymacsDll::GetAppID(const LPCSTR szName, const int fallback)
\r
594 for (int i = 0; i < MAX_APP; ++i)
\r
595 if (!_tcsicmp(m_Config.szSpecialApp[i], szName))
\r
600 LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
\r
602 const BYTE nOrigKey = static_cast<BYTE>(wParam);
\r
603 const bool bRelease = (lParam & BEING_RELEASED) != 0;
\r
604 const bool bExtended = (lParam & EXTENDED_KEY) != 0;
\r
605 const HHOOK *phHook = reinterpret_cast<HHOOK *>(TlsGetValue(g_TlsIndex));
\r
607 static BOOL bLocked = FALSE;
\r
608 static const BYTE RECURSIVE_KEY = 0x07;
\r
609 static int (*fLastCommand)() = NULL;
\r
610 static BYTE nOneShotModifier[MAX_KEY] = {'\0'};
\r
611 static BOOL bCherryOneShotModifier = FALSE;
\r
613 // CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nOrigKey, lParam);
\r
615 if (!m_bEnableKeyboardHook || CUtils::IsXkeymacs() ||
\r
616 nCode < 0 || nCode == HC_NOREMOVE)
\r
617 return CallNextHookEx(*phHook, nCode, wParam, lParam);
\r
619 // CUtils::Log(_T("nKey = %#x, ext = %d, rel = %d, pre = %d, %#hx, %#hx"), nOrigKey,
\r
620 // (lParam & EXTENDED_KEY) ? 1 : 0, (lParam & BEING_RELEASED) ? 1 : 0, (lParam & REPEATED_KEY) ? 1 : 0,
\r
621 // GetKeyState(nOrigKey), GetAsyncKeyState(nOrigKey));
\r
623 if (nOrigKey == RECURSIVE_KEY) {
\r
625 goto HOOK_RECURSIVE_KEY;
\r
627 goto RECURSIVE_COMMAND;
\r
630 CancelMarkWithShift(nOrigKey, bRelease);
\r
632 BYTE nKey = nOrigKey;
\r
635 nKey = bExtended ? VK_RCONTROL : VK_LCONTROL;
\r
638 nKey = bExtended ? VK_RMENU : VK_LMENU;
\r
641 nKey = bExtended ? VK_RSHIFT : VK_LSHIFT;
\r
645 #define fCommand(type) (Commands[m_Config.nCommandID[m_nAppID][(type)][nKey]].fCommand)
\r
646 #define nFunctionID (m_Config.nFunctionID[m_nAppID][nType][nKey])
\r
649 switch (nOrigKey) {
\r
651 if (m_nHookAltRelease) {
\r
652 if (m_nHookAltRelease & ~HOOK_ALT_LATER)
\r
653 m_nHookAltRelease--;
\r
654 else if (m_nHookAltRelease & HOOK_ALT_LATER)
\r
655 m_nHookAltRelease = 0;
\r
662 for (int i = 0; i < MAX_COMMAND_TYPE; ++i) {
\r
663 int (*const fCommand)() = fCommand(i);
\r
664 if (fCommand && !(nOrigKey == VK_MENU && fCommand == CCommands::MetaAlt))
\r
668 if (nOneShotModifier[nKey]) {
\r
669 ReleaseKey(nOneShotModifier[nKey]);
\r
670 nOneShotModifier[nKey] = 0;
\r
671 if (bCherryOneShotModifier) {
\r
672 bCherryOneShotModifier = FALSE;
\r
679 if (m_Config.nSettingStyle[m_nAppID] == SETTING_DISABLE)
\r
682 // Do Nothing for Meadow, Mule for Win32, ... if those use default setting.
\r
683 if (!_tcsicmp(m_Config.szSpecialApp[m_nAppID], _T("Default")) && CUtils::IsDefaultIgnoreApplication())
\r
686 switch (IsPassThrough(nKey)) {
\r
687 case GOTO_DO_NOTHING:
\r
695 // set command type
\r
696 int nType = IsDown(VK_SHIFT) * SHIFT | IsControl() * CONTROL | IsMeta() * META | CCommands::bC_x() * CONTROLX;
\r
697 // Ignore undefined C-x ?
\r
698 if (nType & CONTROLX && fCommand(nType) == NULL && nFunctionID < 0) {
\r
699 if (m_Config.bIgnoreUndefinedC_x[m_nAppID]) {
\r
700 CCommands::Reset(GOTO_HOOK);
\r
703 nType &= ~CONTROLX;
\r
705 // Ignore undefined Meta Ctrl+?
\r
706 if (CCommands::bM_() && nType & CONTROL && fCommand(nType) == NULL && nFunctionID < 0) {
\r
707 if (m_Config.bIgnoreUndefinedMetaCtrl[m_nAppID]) {
\r
708 if (CheckOriginal(CONTROL, nKey))
\r
710 CCommands::Reset(GOTO_HOOK);
\r
716 int nVirtualType = GetModifierState(FALSE);
\r
717 if (nOrigKey == VK_CONTROL)
\r
718 nVirtualType &= ~CONTROL;
\r
719 if (nOrigKey == VK_MENU)
\r
720 nVirtualType &= ~META;
\r
721 if (CheckOriginal(nVirtualType, nOrigKey)) {
\r
725 int (*const fCommand)() = fCommand(nType);
\r
726 if (fCommand == CCommands::EnableOrDisableXKeymacs) {
\r
727 ToggleKeyboardHookState();
\r
730 if (fCommand == CCommands::EnableXKeymacs) {
\r
732 ToggleKeyboardHookState();
\r
735 if (fCommand == CCommands::DisableXKeymacs) {
\r
737 ToggleKeyboardHookState();
\r
743 if (CCommands::bM_x() && !bRelease) {
\r
744 static size_t index = 0;
\r
745 static TCHAR szPath[MAX_PATH] = {'\0'};
\r
746 if (fCommand == CCommands::BackwardChar) {
\r
750 } else if (fCommand == CCommands::BeginningOfLine) {
\r
753 } else if (fCommand == CCommands::DeleteBackwardChar) {
\r
756 memmove(szPath + index, szPath + index + 1, MAX_PATH - index);
\r
760 } else if (fCommand == CCommands::DeleteChar) {
\r
761 if (index < _tcslen(szPath)) {
\r
762 memmove(szPath + index, szPath + index + 1, MAX_PATH - index);
\r
766 } else if (fCommand == CCommands::EndOfLine) {
\r
767 index = _tcslen(szPath);
\r
769 } else if (fCommand == CCommands::ForwardChar) {
\r
770 if (index < _tcslen(szPath))
\r
773 } else if (fCommand == CCommands::KeyboardQuit) {
\r
774 CCommands::bM_x(FALSE);
\r
776 memset(szPath, 0, sizeof(szPath));
\r
778 } else if (nKey == VK_RETURN || fCommand == CCommands::Newline) {
\r
780 CCommands::bM_x(FALSE);
\r
782 memset(szPath, 0, sizeof(szPath));
\r
784 } else if (nKey && index < MAX_PATH - 1) {
\r
785 const BOOL bIsShiftDown = IsDown(VK_SHIFT, FALSE);
\r
788 if (a2v(++nAscii) == nKey && bIsShiftDown == IsShift(nAscii)) {
\r
789 // CUtils::Log("M-x: %#X (%c), %#X (%c)", nKey, nKey, nAscii, nAscii);
\r
790 if (index < _tcslen(szPath))
\r
791 memmove(szPath + index + 1, szPath + index, MAX_PATH - index - 1);
\r
792 szPath[index++] = nAscii;
\r
793 // CUtils::Log("M-x: %c(%#04x)", nAscii, nAscii);
\r
797 } while (nAscii != 127);
\r
801 if (CCommands::bC_u() && nType == NONE) {
\r
802 if ('0' <= nKey && nKey <= '9') {
\r
803 CCommands::NumericArgument(nKey - '0');
\r
806 if (nKey == VK_OEM_MINUS) {
\r
807 CCommands::NumericArgumentMinus();
\r
812 #define OneShotModifier(type, vk, mod) \
\r
813 if (fCommand(nType & ~type) == CCommands::OneShotModifier ## mod || \
\r
814 fCommand(nType) == CCommands::OneShotModifier ## mod ## Repeat) { \
\r
815 nOneShotModifier[nKey] = vk; \
\r
817 bCherryOneShotModifier = TRUE; \
\r
819 } else if (fCommand(nType & ~CONTROL) == CCommands::OneShotModifier ## mod ## Repeat) { \
\r
821 bCherryOneShotModifier = FALSE; \
\r
826 OneShotModifier(CONTROL, VK_CONTROL, Ctrl);
\r
827 OneShotModifier(META, VK_MENU, Alt);
\r
828 OneShotModifier(SHIFT, VK_SHIFT, Shift);
\r
830 for (i = 0; i < MAX_KEY; ++i)
\r
831 if (nOneShotModifier[i] == nOrigKey)
\r
834 bCherryOneShotModifier = FALSE;
\r
836 if (0 <= nFunctionID && nFunctionID < MAX_FUNCTION && m_Config.szFunctionDefinition[nFunctionID][0]) {
\r
837 CallFunction(nFunctionID);
\r
838 CCommands::Reset(GOTO_HOOK);
\r
845 if (nOrigKey == VK_CONTROL || nOrigKey == VK_MENU || nOrigKey == VK_SHIFT)
\r
847 if (!(nType & SHIFT)) {
\r
848 if (CCommands::IsSetMark()) {
\r
849 if (CCommands::MoveCaret(nKey, nType & CONTROL) != CONTINUE) {
\r
850 CCommands::ClearNumericArgument();
\r
853 CCommands::SetMark(FALSE);
\r
856 if (1 < CCommands::GetNumericArgument()) {
\r
857 Kdu(nKey, CCommands::GetNumericArgument());
\r
858 CCommands::ClearNumericArgument();
\r
864 if (CCommands::IsTemporarilyDisableXKeymacs() && fCommand != CCommands::KeyboardQuit) {
\r
865 CCommands::SetTemporarilyDisableXKeymacs(FALSE);
\r
869 m_bRightControl = IsDown(VK_RCONTROL, FALSE);
\r
870 m_bRightAlt = IsDown(VK_RMENU, FALSE);
\r
871 m_bRightShift = IsDown(VK_RSHIFT, FALSE);
\r
874 goto HOOK_RECURSIVE_KEY;
\r
876 fLastCommand = fCommand;
\r
878 switch (fLastCommand()) {
\r
879 case GOTO_DO_NOTHING:
\r
885 case GOTO_RECURSIVE:
\r
896 SetModifierIcons();
\r
897 if (m_bRecordingMacro && (!bRelease || m_bDown[wParam])) {
\r
898 KbdMacro m = { nCode, wParam, lParam, TRUE };
\r
899 m_Macro.push_back(m);
\r
900 m_bDown[wParam] |= !bRelease;
\r
902 return CallNextHookEx(*phHook, nCode, wParam, lParam);
\r
905 Kdu(RECURSIVE_KEY, 1, FALSE);
\r
908 CCommands::SetLastCommand(fLastCommand);
\r
911 SetModifierIcons();
\r
912 HOOK_RECURSIVE_KEY:
\r
916 void CXkeymacsDll::SetModifierIcons()
\r
918 #define IconState(x) ((x) ? ON_ICON : OFF_ICON)
\r
920 {MX_ICON, IconState(CCommands::bM_x()), ""},
\r
921 {CX_ICON, IconState(CCommands::bC_x()), ""},
\r
922 {META_ICON, IconState(CCommands::bM_()), ""},
\r
923 {SHIFT_ICON, IconState(IsDown(VK_SHIFT, FALSE)), ""},
\r
924 {CTRL_ICON, IconState(IsControl()), ""},
\r
925 {ALT_ICON, IconState(IsDown(VK_MENU, FALSE)), ""}
\r
927 _tcscpy_s(msg[0].szTip, m_M_xTip);
\r
928 SendIconMessage(msg, 6);
\r
931 // Clear data of nAppID
\r
932 void CXkeymacsDll::Clear(int nAppID)
\r
934 if (0 <= nAppID && nAppID < MAX_APP) {
\r
935 ZeroMemory(m_Config.szSpecialApp[nAppID], sizeof(m_Config.szSpecialApp[nAppID]));
\r
936 ZeroMemory(m_Config.nCommandID[nAppID], sizeof(m_Config.nCommandID[nAppID]));
\r
937 m_Config.nKillRingMax[nAppID] = 0;
\r
938 m_Config.bUseDialogSetting[nAppID] = FALSE;
\r
939 m_Config.nSettingStyle[nAppID] = 0;
\r
945 BOOL CXkeymacsDll::IsValidKey(BYTE bVk)
\r
947 if (bVk == 0xf0) { // 0xf0: Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.
\r
963 BOOL CXkeymacsDll::IsDepressedModifier(int (__cdecl *Modifier)(void), BOOL bPhysicalKey)
\r
967 if (IsValidKey(bVk) && IsDown(bVk, bPhysicalKey) &&
\r
968 Commands[m_Config.nCommandID[m_nAppID][NONE][bVk]].fCommand == Modifier)
\r
974 void CXkeymacsDll::CancelMarkWithShift(BYTE nKey, bool bRelease)
\r
976 static bool bShift;
\r
977 if (nKey != VK_SHIFT)
\r
981 if (bVk == VK_SHIFT || VK_LSHIFT || VK_RSHIFT)
\r
983 if (IsDown(bVk, FALSE))
\r
991 CCommands::SetMark(FALSE);
\r
997 BOOL CXkeymacsDll::IsControl()
\r
999 return CCommands::bC_() || IsDepressedModifier(CCommands::C_);
\r
1002 BOOL CXkeymacsDll::IsMeta()
\r
1004 return CCommands::bM_() || IsDepressedModifier(CCommands::MetaAlt);
\r
1007 void CXkeymacsDll::AddKillRing(BOOL bNewData)
\r
1009 if (m_Config.nKillRingMax[m_nAppID] == 0) {
\r
1013 CClipboardSnap *pSnap = new CClipboardSnap;
\r
1014 if( !pSnap ) return;
\r
1016 BOOL bCapture = pSnap->Capture();
\r
1017 bCapture = pSnap->Capture(); // for "office drawing shape format". Can CClipboardSnap care this problem?
\r
1021 m_oKillRing.AddHead(pSnap);
\r
1023 if (m_oKillRing.IsEmpty()) {
\r
1024 m_oKillRing.AddHead(pSnap);
\r
1026 CClipboardSnap *pParent;
\r
1027 for (pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {
\r
1030 pParent->SetNext(pSnap);
\r
1040 if (m_Config.nKillRingMax[m_nAppID] < m_oKillRing.GetCount()) {
\r
1041 CClipboardSnap *pSnap = m_oKillRing.GetTail();
\r
1044 m_oKillRing.RemoveTail();
\r
1048 // Return TRUE if there is another data
\r
1049 // Return FALSE if there is no more data
\r
1050 CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)
\r
1052 if (m_Config.nKillRingMax[m_nAppID] == 0) {
\r
1056 if (m_oKillRing.IsEmpty()) {
\r
1060 m_nKillRing %= m_oKillRing.GetCount();
\r
1063 CClipboardSnap oCurrentSnap;
\r
1064 oCurrentSnap.Capture();
\r
1066 CClipboardSnap *pKillRing = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));
\r
1070 for (; pKillRing->GetNext(); pKillRing = pKillRing->GetNext()) {
\r
1073 if (*pKillRing != oCurrentSnap) {
\r
1079 pSnap = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));
\r
1083 return pSnap->GetNext();
\r
1086 void CXkeymacsDll::SetOriginal(UINT nType, BYTE bVk)
\r
1088 m_nOriginal[nType & ~SHIFT][bVk]++;
\r
1091 int CXkeymacsDll::CheckOriginal(UINT nType, BYTE bVk)
\r
1094 if (m_nOriginal[nType][bVk])
\r
1095 return m_nOriginal[nType][bVk]--;
\r
1099 void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)
\r
1101 m_nKillRing += nKillRing;
\r
1104 BOOL CXkeymacsDll::GetEnableCUA()
\r
1106 return m_Config.bEnableCUA[m_nAppID];
\r
1109 void CXkeymacsDll::StartRecordMacro()
\r
1111 if (CCommands::bC_u())
\r
1113 m_bRecordingMacro = TRUE;
\r
1114 m_Macro.erase(m_Macro.begin(), m_Macro.end());
\r
1115 ZeroMemory(m_bDown, MAX_KEY);
\r
1118 void CXkeymacsDll::EndRecordMacro()
\r
1120 m_bRecordingMacro = FALSE;
\r
1121 while (!m_Macro.empty()) { // remove not released push
\r
1122 const KbdMacro& m = m_Macro.back();
\r
1123 if (m.lParam & BEING_RELEASED)
\r
1125 m_Macro.pop_back();
\r
1129 void CXkeymacsDll::CallMacro()
\r
1131 if (m_bRecordingMacro)
\r
1132 m_bRecordingMacro = FALSE;
\r
1133 UINT before = GetModifierState(FALSE);
\r
1134 SetModifierState(0, before);
\r
1135 for (std::list<KbdMacro>::const_iterator m = m_Macro.begin(); m != m_Macro.end(); ++m)
\r
1136 if (m->lParam & BEING_RELEASED)
\r
1137 ReleaseKey(static_cast<BYTE>(m->wParam));
\r
1139 DepressKey(static_cast<BYTE>(m->wParam), m->bOriginal);
\r
1140 SetModifierState(before, 0);
\r
1143 BOOL CXkeymacsDll::Is106Keyboard()
\r
1145 return m_Config.b106Keyboard;
\r
1148 int CXkeymacsDll::IsPassThrough(BYTE nKey)
\r
1153 && (Commands[m_Config.nCommandID[m_nAppID][NONE][bVk]].fCommand == CCommands::PassThrough)) {
\r
1154 if (bVk == nKey) {
\r
1158 return GOTO_DO_NOTHING;
\r
1164 // call an original command which is defined in dot.xkeymacs
\r
1165 void CXkeymacsDll::CallFunction(int nFuncID)
\r
1167 if (nFuncID < 0 || nFuncID >= MAX_FUNCTION)
\r
1169 LPCTSTR def = m_Config.szFunctionDefinition[nFuncID];
\r
1172 std::vector<KeyBind> keybinds;
\r
1173 const LPCTSTR last = def + _tcslen(def) - 1;
\r
1174 if (*def == _T('"') && *last == _T('"')) {
\r
1175 ++def; // skip '"'
\r
1176 while (def < last)
\r
1177 keybinds.push_back(ParseKey(def));
\r
1178 } else if (*def == _T('[') && *last == _T(']')) {
\r
1179 while (++def < last) { // skip '[', ']', and ' '
\r
1180 if (*def == _T('?')) { // [?f ?o ?o]
\r
1181 keybinds.push_back(ParseKey(++def));
\r
1185 for (int i = 0; i < MAX_KEYNAME; ++i) {
\r
1186 size_t keylen = _tcslen(KeyNames[i].name);
\r
1187 if (!_tcsncmp(def, KeyNames[i].name, keylen)) {
\r
1188 KeyBind keybind = {NONE, KeyNames[i].bVk};
\r
1189 keybinds.push_back(keybind);
\r
1198 BOOL bM_x = FALSE;
\r
1199 TCHAR szPath[MAX_PATH] = {'\0'};
\r
1200 unsigned int index = 0;
\r
1201 BOOL bInitialized = FALSE;
\r
1202 UINT before = GetModifierState(FALSE);
\r
1204 for (std::vector<KeyBind>::const_iterator p = keybinds.begin(); p != keybinds.end(); ++p) {
\r
1205 const int nType = p->nType;
\r
1206 const BYTE bVk = p->bVk;
\r
1207 int (*fCommand)() = nType < MAX_COMMAND_TYPE ? Commands[m_Config.nCommandID[m_nAppID][nType][bVk]].fCommand : NULL;
\r
1209 if (fCommand == CCommands::ExecuteExtendedCommand)
\r
1211 else if (!bInitialized) {
\r
1212 SetModifierState(0, before);
\r
1213 bInitialized = TRUE;
\r
1215 // CUtils::Log("CallFunction: Command Name: %s", Commands[m_Config.nCommandID[m_nAppID][nType][bVk]].szCommandName);
\r
1216 while (fCommand() == GOTO_RECURSIVE)
\r
1221 if (bVk == VK_RETURN)
\r
1222 InvokeM_x(szPath);
\r
1223 else if (bVk != 0) {
\r
1226 if (a2v(++nAscii) == bVk && ((nType & SHIFT) != 0) == IsShift(nAscii)) {
\r
1227 // CUtils::Log("M-x: %#X (%c), %#X (%c)", bVk, bVk, nAscii, nAscii);
\r
1228 szPath[index++] = nAscii;
\r
1231 } while (nAscii != 127);
\r
1235 if (!bInitialized) {
\r
1236 SetModifierState(0, before);
\r
1237 bInitialized = TRUE;
\r
1239 if (nType & WIN_WIN)
\r
1240 DepressKey(VK_LWIN);
\r
1241 if (nType & WIN_CTRL)
\r
1242 DepressKey(VK_CONTROL);
\r
1243 if (nType & WIN_ALT)
\r
1244 DepressKey(VK_MENU);
\r
1245 if (nType & SHIFT)
\r
1246 DepressKey(VK_SHIFT);
\r
1248 const int nNextType = (p + 1) != keybinds.end() ? (p + 1)->nType : 0;
\r
1249 if (nType & SHIFT && !(nNextType & SHIFT))
\r
1250 ReleaseKey(VK_SHIFT);
\r
1251 if (nType & WIN_ALT && !(nNextType & WIN_ALT))
\r
1252 ReleaseKey(VK_MENU);
\r
1253 if (nType & WIN_CTRL && !(nNextType & WIN_CTRL))
\r
1254 ReleaseKey(VK_CONTROL);
\r
1255 if (nType & WIN_WIN && !(nNextType & WIN_WIN))
\r
1256 ReleaseKey(VK_LWIN);
\r
1260 // If this lines is invoked on M-x, a window transition does not work well.
\r
1261 SetModifierState(before, 0);
\r
1265 KeyBind CXkeymacsDll::ParseKey(LPCTSTR& def)
\r
1267 KeyBind keybind = {NONE};
\r
1268 if (*def == _T('\\')) { // set modifiers
\r
1271 for (int i = 0; i < MAX_MODIFIER; ++i) {
\r
1272 size_t len = _tcslen(Modifiers[i].name);
\r
1273 if (!_tcsncmp(def, Modifiers[i].name, len)) {
\r
1274 keybind.nType |= Modifiers[i].id;
\r
1280 if (IsShift(*def) && !(keybind.nType & (WIN_CTRL | WIN_ALT | WIN_WIN)))
\r
1281 keybind.nType |= SHIFT;
\r
1283 for (; i < MAX_KEYNAME; ++i) {
\r
1284 size_t len = _tcslen(KeyNames[i].name);
\r
1285 if (!_tcsncmp(def, KeyNames[i].name, len)) {
\r
1290 keybind.bVk = i < MAX_KEYNAME ? KeyNames[i].bVk : a2v(*def++);
\r
1294 BOOL CXkeymacsDll::IsShift(TCHAR nAscii)
\r
1307 return m_Config.b106Keyboard;
\r
1317 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
1320 return !m_Config.b106Keyboard;
\r
1326 return m_Config.b106Keyboard;
\r
1331 return !m_Config.b106Keyboard;
\r
1332 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
1333 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
1334 case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'):
\r
1341 return !m_Config.b106Keyboard;
\r
1345 return m_Config.b106Keyboard;
\r
1346 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
1347 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
1348 case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'):
\r
1360 BYTE CXkeymacsDll::a2v(TCHAR nAscii)
\r
1368 return m_Config.b106Keyboard ? '2' : (BYTE) 0xde; // VK_OEM_7
\r
1376 return m_Config.b106Keyboard ? '6' : '7';
\r
1378 return m_Config.b106Keyboard ? '7' : (BYTE) 0xde; // VK_OEM_7
\r
1380 return m_Config.b106Keyboard ? '8' : '9';
\r
1382 return m_Config.b106Keyboard ? '9' : '0';
\r
1384 return m_Config.b106Keyboard ? (BYTE) 0xba : '8'; // VK_OEM_1
\r
1386 return 0xbb; // VK_OEM_PLUS
\r
1388 return 0xbc; // VK_OEM_COMMA
\r
1390 return 0xbd; // VK_OEM_MINUS
\r
1392 return 0xbe; // VK_OEM_PERIOD
\r
1394 return 0xbf; // VK_OEM_2
\r
1395 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
1398 return 0xba; // VK_OEM_1
\r
1400 return m_Config.b106Keyboard ? (BYTE) 0xbb : (BYTE) 0xba; // VK_OEM_PLUS VK_OEM_1
\r
1402 return 0xbc; // VK_OEM_COMMA
\r
1404 return m_Config.b106Keyboard ? (BYTE) 0xbd : (BYTE) 0xbb; // VK_OEM_MINUS VK_OEM_PLUS
\r
1406 return 0xbe; // VK_OEM_PERIOD
\r
1408 return 0xbf; // VK_OEM_2
\r
1410 return m_Config.b106Keyboard ? (BYTE) 0xc0 : '2';
\r
1411 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
1412 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
1413 case _T('U'): case _T('V'): case _T('W'): case _T('X'): case _T('Y'): case _T('Z'):
\r
1416 return 0xdb; // VK_OEM_4
\r
1418 return 0xdc; // VK_OEM_5
\r
1420 return 0xdd; // VK_OEM_6
\r
1422 return m_Config.b106Keyboard ? (BYTE) 0xde : '6'; // VK_OEM_7
\r
1424 return m_Config.b106Keyboard ? (BYTE) 0xe2 : (BYTE) 0xbd; // VK_OEM_102 VK_OEM_MINUS
\r
1426 return 0xc0; // VK_OEM_3
\r
1427 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
1428 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
1429 case _T('u'): case _T('v'): case _T('w'): case _T('x'): case _T('y'): case _T('z'):
\r
1430 return (BYTE) (nAscii - (_T('a') - _T('A')));
\r
1432 return 0xdb; // VK_OEM_4
\r
1434 return 0xdc; // VK_OEM_5
\r
1436 return 0xdd; // VK_OEM_6
\r
1438 return m_Config.b106Keyboard ? (BYTE) 0xde : (BYTE) 0xc0; // VK_OEM_7 VK_OEM_3
\r
1444 BOOL CXkeymacsDll::IsMatchWindowText(CString szWindowText)
\r
1446 BOOL bIsMatchWindowText = TRUE;
\r
1448 TCHAR szCurrentWindowText[WINDOW_TEXT_LENGTH] = {'\0'};
\r
1449 GetWindowText(GetForegroundWindow(), szCurrentWindowText, sizeof(szCurrentWindowText));
\r
1451 switch (CUtils::GetWindowTextType(szWindowText)) {
\r
1452 case IDS_WINDOW_TEXT_MATCH: // *foo*
\r
1453 szWindowText.Delete(0); // Delete first '*'
\r
1454 szWindowText.Delete(szWindowText.GetLength() - 1); // Delete last '*'
\r
1455 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText);
\r
1457 case IDS_WINDOW_TEXT_MATCH_FORWARD: // foo*
\r
1458 szWindowText.Delete(szWindowText.GetLength() - 1); // Delete last '*'
\r
1459 bIsMatchWindowText = 0 == CString(szCurrentWindowText).Find(szWindowText);
\r
1461 case IDS_WINDOW_TEXT_MATCH_BACKWARD: // *foo
\r
1462 szWindowText.Delete(0); // Delete first '*'
\r
1463 bIsMatchWindowText = 0 <= CString(szCurrentWindowText).Find(szWindowText, CString(szCurrentWindowText).GetLength() - szWindowText.GetLength());
\r
1465 case IDS_WINDOW_TEXT_MATCH_FULL: // foo
\r
1466 bIsMatchWindowText = szWindowText == CString(szCurrentWindowText);
\r
1468 case IDS_WINDOW_TEXT_IGNORE: // *
\r
1469 bIsMatchWindowText = TRUE;
\r
1476 // CUtils::Log(_T("IsMatchWindowText: %d, _%s_, _%s_"), bIsMatchWindowText, szCurrentWindowText, szWindowText);
\r
1477 return bIsMatchWindowText;
\r
1480 void CXkeymacsDll::SetAccelerate(int nAccelerate)
\r
1482 m_nAccelerate = nAccelerate;
\r
1485 int CXkeymacsDll::GetAccelerate()
\r
1487 return m_nAccelerate;
\r
1490 void CXkeymacsDll::SetKeyboardSpeed(int nKeyboardSpeed)
\r
1492 m_nKeyboardSpeed = nKeyboardSpeed;
\r
1495 unsigned int CXkeymacsDll::GetMaxKeyInterval()
\r
1497 // m_nKeyboardSpeed == 0: slowest repeat rate; approximately 2 characters per second
\r
1498 // m_nKeyboardSpeed == 31: fastest repeat rate; approximately 30 characters per second
\r
1499 // 47 ms is max on my machine w/ KeyboardSpeed 31.
\r
1500 // 1000 / 2 + 50 = 550
\r
1501 // 1000 / 30 + 50 = 83
\r
1502 return (unsigned int) (1000.0 / (2.0 + m_nKeyboardSpeed % 32 * 28.0 / 31.0) + 50.0);
\r
1505 void CXkeymacsDll::SetCursorData(HCURSOR hEnable, HCURSOR hDisableTMP, HCURSOR hDisableWOCQ, HICON hDisable, BOOL bEnable)
\r
1507 m_hCursor[STATUS_ENABLE] = hEnable;
\r
1508 m_hCursor[STATUS_DISABLE_TMP] = hDisableTMP;
\r
1509 m_hCursor[STATUS_DISABLE_WOCQ] = hDisableWOCQ;
\r
1510 m_hCursor[STATUS_DISABLE] = hDisable;
\r
1511 m_bCursor = bEnable;
\r
1514 void CXkeymacsDll::DoSetCursor()
\r
1516 if (m_bCursor && m_hCurrentCursor) {
\r
1517 ::SetCursor(m_hCurrentCursor);
\r
1521 BOOL CXkeymacsDll::Get326Compatible()
\r
1523 return m_Config.b326Compatible[m_nAppID];
\r
1526 void CXkeymacsDll::InvokeM_x(const TCHAR *const szPath)
\r
1528 // CUtils::Log("M-x: szPath=_%s_", szPath);
\r
1529 int (*fCommand)() = NULL;
\r
1531 for (int i = 0; i < MAX_COMMAND; ++i) {
\r
1532 if (_tcsicmp(szPath, Commands[i].szCommandName) == 0) {
\r
1533 fCommand = Commands[i].fCommand;
\r
1539 // CUtils::Log("M-x: Command: _%s_", Commands[i].szCommandName);
\r
1542 // CUtils::Log("M-x: Path: _%s_", szPath);
\r
1543 ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);
\r
1547 void CXkeymacsDll::SetM_xTip(const TCHAR *const szPath)
\r
1549 _tcscpy_s(m_M_xTip, "M-x LED");
\r
1550 if (szPath && _tcslen(szPath) < 128 - 5)
\r
1551 _stprintf_s(m_M_xTip, "M-x %s", szPath);
\r
1554 BOOL CXkeymacsDll::SendIconMessage(ICONMSG *pMsg, DWORD num)
\r
1557 return CallNamedPipe(ICON_PIPE, pMsg, sizeof(ICONMSG) * num, &ack, sizeof(DWORD), &read, NMPWAIT_NOWAIT);
\r