// xkeymacsdll.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "resource.h"
#include "Utils.h"
#include "Commands.h"
#include
#include
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL };
static HINSTANCE g_hDllInst = NULL;
HINSTANCE GetThisHInst()
{
return g_hDllInst;
}
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
g_hDllInst = hInstance;
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH) {
TRACE0("XKEYMACSDLL.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) {
return 0;
}
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(XkeymacsdllDLL);
} else if (dwReason == DLL_PROCESS_DETACH) {
TRACE0("XKEYMACSDLL.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(XkeymacsdllDLL);
}
return 1; // ok
}
//////////////////////////////////////////////////////////////////////
// CXkeymacsDll Class
//////////////////////////////////////////////////////////////////////
#include "xkeymacsDll.h"
#pragma data_seg(".xkmcs")
HHOOK CXkeymacsDll::m_hHookKeyboard = NULL;
HHOOK CXkeymacsDll::m_hHookCallWnd = NULL;
HHOOK CXkeymacsDll::m_hHookGetMessage = NULL;
HHOOK CXkeymacsDll::m_hHookShell = NULL;
int CXkeymacsDll::m_nCommandID[MAX_APP][MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
int CXkeymacsDll::m_nFunctionID[MAX_APP][MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
char CXkeymacsDll::m_szSpecialApp[MAX_APP][CLASS_NAME_LENGTH] = {'\0'};
BOOL CXkeymacsDll::m_bRightControl = FALSE;
BOOL CXkeymacsDll::m_bRightAlt = FALSE;
BOOL CXkeymacsDll::m_bRightShift = FALSE;
BOOL CXkeymacsDll::m_bHook = TRUE;
BOOL CXkeymacsDll::m_bDefiningMacro = FALSE;
DWORD CXkeymacsDll::m_dwOldMessage[MAX_ICON_TYPE] = {'\0'};
NOTIFYICONDATA CXkeymacsDll::m_stNtfyIcon[MAX_ICON_TYPE] = {'\0'};
NOTIFYICONDATA CXkeymacsDll::m_stOldNtfyIcon[MAX_ICON_TYPE] = {'\0'};
HICON CXkeymacsDll::m_hIcon[MAX_ICON_TYPE][MAX_STATUS] = {'\0'};
BOOL CXkeymacsDll::m_bIcon[MAX_ICON_TYPE] = {'\0'};
int CXkeymacsDll::m_nKillRingMax[MAX_APP] = {'\0'};
BOOL CXkeymacsDll::m_bUseDialogSetting[MAX_APP] = {'\0'};
CList CXkeymacsDll::m_oKillRing;
CObList CXkeymacsDll::m_Macro;
int CXkeymacsDll::m_nKillRing = 0;
int CXkeymacsDll::m_nOriginal[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
int CXkeymacsDll::m_nApplicationID = 0;
int CXkeymacsDll::m_nSettingStyle[MAX_APP] = {'\0'};
BOOL CXkeymacsDll::m_bIgnoreUndefinedMetaCtrl[MAX_APP] = {'\0'};
BOOL CXkeymacsDll::m_bIgnoreUndefinedC_x[MAX_APP] = {'\0'};
// int CXkeymacsDll::m_nPassThrough = 0;
char CXkeymacsDll::m_szApplicationName[MAX_PATH] = {'\0'};
char CXkeymacsDll::m_szOldApplicationName[MAX_PATH] = {'\0'};
BOOL CXkeymacsDll::m_bEnableCUA[MAX_APP] = {'\0'};
char CXkeymacsDll::m_szFunctionDefinition[MAX_FUNCTION][MAX_DEFINITION] = {'\0'};
BOOL CXkeymacsData::m_b106Keyboard = FALSE;
#pragma data_seg()
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXkeymacsDll::CXkeymacsDll()
{
CUtils::InitCUtils();
}
CXkeymacsDll::~CXkeymacsDll()
{
}
int CXkeymacsDll::ModifyShell_NotifyIcon(ICON_TYPE icon, BOOL bNewStatus)
{
if (m_stNtfyIcon[icon].hIcon == (bNewStatus ? m_hIcon[icon][ON_ICON] : m_hIcon[icon][OFF_ICON])) {
return TRUE;
} else {
m_stNtfyIcon[icon].hIcon = (bNewStatus ? m_hIcon[icon][ON_ICON] : m_hIcon[icon][OFF_ICON]);
}
return DoShell_NotifyIcon(icon, NIM_MODIFY);
}
void CXkeymacsDll::SetNotifyIconData(ICON_TYPE icon, NOTIFYICONDATA stNtfyIcon, HICON hEnable, HICON hDisableTMP, HICON hDisableWOCQ, HICON hDisable, BOOL bEnable)
{
m_hIcon[icon][STATUS_ENABLE] = hEnable;
m_hIcon[icon][STATUS_DISABLE_TMP] = hDisableTMP;
m_hIcon[icon][STATUS_DISABLE_WOCQ] = hDisableWOCQ;
m_hIcon[icon][STATUS_DISABLE] = hDisable;
m_bIcon[icon] = bEnable;
m_stNtfyIcon[icon] = stNtfyIcon;
AddShell_NotifyIcon(icon);
}
void CXkeymacsDll::SetNotifyIconData(ICON_TYPE icon, NOTIFYICONDATA stNtfyIcon, HICON hOn, HICON hOff, BOOL bEnable)
{
m_hIcon[icon][ON_ICON] = hOn;
m_hIcon[icon][OFF_ICON] = hOff;
m_bIcon[icon] = bEnable;
m_stNtfyIcon[icon] = stNtfyIcon;
AddShell_NotifyIcon(icon);
}
void CXkeymacsDll::EnableShell_NotifyIcon(ICON_TYPE icon, BOOL bEnable)
{
DeleteShell_NotifyIcon(icon);
m_bIcon[icon] = bEnable;
AddShell_NotifyIcon(icon);
}
BOOL CXkeymacsDll::DoShell_NotifyIcon(ICON_TYPE icon, DWORD dwMessage)
{
if (m_bIcon[icon]
&& (m_dwOldMessage[icon] != dwMessage
|| memcmp(&m_stOldNtfyIcon[icon], &m_stNtfyIcon[icon], sizeof(m_stNtfyIcon[icon])))) {
m_dwOldMessage[icon] = dwMessage;
m_stOldNtfyIcon[icon] = m_stNtfyIcon[icon];
return ::Shell_NotifyIcon(dwMessage, &m_stNtfyIcon[icon]);
} else {
return TRUE;
}
}
void CXkeymacsDll::AddShell_NotifyIcon(ICON_TYPE icon)
{
DoShell_NotifyIcon(icon, NIM_ADD);
}
void CXkeymacsDll::DeleteShell_NotifyIcon(ICON_TYPE icon)
{
DoShell_NotifyIcon(icon, NIM_DELETE);
}
// set keyboard hook
BOOL CXkeymacsDll::SetKeyboardHook()
{
m_hHookKeyboard = ::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, GetThisHInst(), 0);
if (!m_hHookKeyboard) {
return FALSE;
}
m_hHookCallWnd = ::SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, GetThisHInst(), 0);
m_hHookGetMessage = ::SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, GetThisHInst(), 0);
m_hHookShell = ::SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, GetThisHInst(), 0);
AddShell_NotifyIcon(MAIN_ICON);
return TRUE;
}
// release keyboard hook
BOOL CXkeymacsDll::ReleaseKeyboardHook()
{
BOOL bKeyboard = TRUE;
BOOL bCallWnd = TRUE;
BOOL bGetMessage = TRUE;
BOOL bShell = TRUE;
if (m_hHookKeyboard) {
bKeyboard = ::UnhookWindowsHookEx(m_hHookKeyboard);
}
m_hHookKeyboard = NULL;
if (m_hHookCallWnd) {
bCallWnd = ::UnhookWindowsHookEx(m_hHookCallWnd);
}
m_hHookCallWnd = NULL;
if (m_hHookGetMessage) {
bGetMessage = ::UnhookWindowsHookEx(m_hHookGetMessage);
}
m_hHookGetMessage = NULL;
if (m_hHookShell) {
bShell = ::UnhookWindowsHookEx(m_hHookShell);
}
m_hHookShell = NULL;
return bKeyboard && bCallWnd && bGetMessage && bShell;
}
void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)
{
m_bHook = bFlag;
if (m_bHook) {
if (CCommands::IsTemporarilyDisableXKeymacs()) {
m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE_TMP];
} else {
m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_ENABLE];
}
} else {
m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE_WOCQ];
}
if (m_nSettingStyle[m_nApplicationID] == SETTING_DISABLE
|| (!stricmp(m_szSpecialApp[m_nApplicationID], "Default")
&& CUtils::IsDefaultIgnoreApplication())) {
m_stNtfyIcon[MAIN_ICON].hIcon = m_hIcon[MAIN_ICON][STATUS_DISABLE];
}
DoShell_NotifyIcon(MAIN_ICON, NIM_MODIFY);
}
// if be keyboard hook, return TRUE
BOOL CXkeymacsDll::IsKeyboardHook()
{
if (m_bHook) {
return TRUE;
}
return FALSE;
}
LRESULT CALLBACK CXkeymacsDll::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (0 <= nCode) {
CWPSTRUCT &cwps = *(CWPSTRUCT *)lParam;
switch (cwps.message) {
case WM_IME_STARTCOMPOSITION:
InitKeyboardProc(TRUE);
break;
case WM_IME_ENDCOMPOSITION:
InitKeyboardProc(FALSE);
break;
case WM_SETFOCUS:
if (cwps.hwnd == GetForegroundWindow()) {
InitKeyboardProc(FALSE);
SetKeyboardHookFlag(m_bHook);
}
break;
case WM_NCACTIVATE:
if (cwps.wParam) {
if (cwps.hwnd == GetForegroundWindow()) {
InitKeyboardProc(FALSE);
SetKeyboardHookFlag(m_bHook);
}
}
break;
default:
break;
}
}
return CallNextHookEx(m_hHookCallWnd, nCode, wParam, lParam);
}
LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG &msg = (*(MSG *)lParam);
switch (msg.message) {
case WM_IME_STARTCOMPOSITION:
InitKeyboardProc(TRUE);
break;
case WM_IME_ENDCOMPOSITION:
InitKeyboardProc(FALSE);
break;
}
return CallNextHookEx(m_hHookGetMessage, nCode, wParam, lParam);
}
LRESULT CALLBACK CXkeymacsDll::ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch (nCode) {
case HSHELL_WINDOWACTIVATED:
{
TCHAR className[256];
::GetClassName((HWND)wParam, className, 255);
if (!stricmp(className, "ConsoleWindowClass")) {
InitKeyboardProc(FALSE);
SetKeyboardHookFlag(m_bHook);
}
break;
}
default:
break;
}
return CallNextHookEx( m_hHookShell, nCode, wParam, lParam );
}
// return true if the key is down
BOOL CXkeymacsDll::IsDown(BYTE bVk, BOOL bPhysicalKey)
{
if (bPhysicalKey) {
return GetAsyncKeyState(bVk) < 0;
} else {
return GetKeyState(bVk) < 0;
}
}
// Do keybd_event
void CXkeymacsDll::DoKeybd_event(BYTE bVk, DWORD dwFlags)
{
// Set KEYEVENTF_EXTENDEDKEY if needed
switch (bVk) {
case VK_CONTROL:
if (m_bRightControl) { // Right Ctrl
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
break;
case VK_MENU:
if (m_bRightAlt) { // Right Alt
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
break;
case VK_SHIFT:
if (m_bRightShift) { // Right Shift
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
break;
case VK_PAUSE:
if (IsDown(VK_CONTROL, FALSE)) { // Break
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
break;
case VK_INSERT:
case VK_DELETE:
case VK_HOME:
case VK_END:
case VK_NEXT:
case VK_PRIOR:
case VK_UP:
case VK_DOWN:
case VK_RIGHT:
case VK_LEFT:
case VK_NUMLOCK:
case VK_PRINT:
dwFlags |= KEYEVENTF_EXTENDEDKEY;
break;
default:
break;
}
keybd_event(bVk, 0, dwFlags, GetMessageExtraInfo());
}
// the key is being depressed
void CXkeymacsDll::DepressKey(BYTE bVk, BOOL bOriginal) // bVk is virtual-key code, MSDN said
{
if (bOriginal) {
int nCommandType = NONE;
if (IsDown(VK_CONTROL)) {
nCommandType |= CONTROL;
}
if (IsDown(VK_MENU)) {
nCommandType |= META;
}
Original(nCommandType, bVk, 1);
}
DoKeybd_event(bVk, 0);
}
// the key is being released
void CXkeymacsDll::ReleaseKey(BYTE bVk) // bVk is virtual-key code, MSDN said
{
DoKeybd_event(bVk, KEYEVENTF_KEYUP);
}
// bVk down, bVk up
void CXkeymacsDll::Kdu(BYTE bVk, DWORD n, BOOL bOriginal)
{
while (n--) {
DepressKey(bVk, bOriginal);
ReleaseKey(bVk);
}
}
void CXkeymacsDll::InitKeyboardProc(BOOL bImeComposition)
{
if (CUtils::IsFindDialog()) {
static BOOL bImeCompositionOld = FALSE;
if (!bImeComposition
&& bImeCompositionOld) {
DepressKey(VK_END);
ReleaseKey(VK_END);
}
bImeCompositionOld = bImeComposition;
}
CUtils::SetApplicationName(bImeComposition);
if (strnicmp(m_szSpecialApp[m_nApplicationID], CUtils::GetApplicationName(), 0xF)) { // PROCESSENTRY32 has only 0xF bytes of Name
for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {
if (!strnicmp(m_szSpecialApp[m_nApplicationID], CUtils::GetApplicationName(), 0xF)) { // PROCESSENTRY32 has only 0xF bytes of Name
break;
}
}
if (m_nApplicationID == MAX_APP) {
for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {
if (!stricmp(m_szSpecialApp[m_nApplicationID], "Default")) {
break;
}
}
if (m_nApplicationID == MAX_APP) {
m_nApplicationID = 0;
}
}
}
if (m_nSettingStyle[m_nApplicationID] != SETTING_DISABLE
&& (stricmp(m_szSpecialApp[m_nApplicationID], "Default") || !CUtils::IsDefaultIgnoreApplication())
&& !bImeComposition
&& CUtils::IsDialog()) {
// Use Dialog Setting
if (m_bUseDialogSetting[m_nApplicationID]) {
int nOriginalApplicationID = m_nApplicationID;
for (m_nApplicationID = 0; m_nApplicationID < MAX_APP; ++m_nApplicationID) {
if (!stricmp(m_szSpecialApp[m_nApplicationID], "Dialog")) {
break;
}
}
if (m_nApplicationID == MAX_APP) {
m_nApplicationID = nOriginalApplicationID;
}
}
}
ModifyShell_NotifyIcon(CX_ICON, FALSE);
ModifyShell_NotifyIcon(META_ICON, FALSE);
CCommands::SetMark(FALSE);
CCommands::SetTemporarilyDisableXKeymacs(FALSE);
CCommands::Reset();
}
// emulate emacs // cf virtual-key code
LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
ASSERT(0 <= wParam && wParam <= UCHAR_MAX);
int nCommandType = NONE;
BYTE nKey = (BYTE)wParam;
static BOOL bLocked = FALSE;
static const BYTE RECURSIVE_KEY = 0x07;
static int (*fCommand)() = NULL;
static BYTE nOneShotModifier[MAX_KEY] = {'\0'};
static BOOL bCherryOneShotModifier = FALSE;
// CUtils::Log("nCode = %#x, nKey = %#x, lParam = %#x", nCode, nKey, lParam);
if (nCode < 0 || nCode == HC_NOREMOVE) {
goto DO_NOTHING;
}
if (nKey == RECURSIVE_KEY) {
if (lParam & BEING_RELEASED) {
goto HOOK_RECURSIVE_KEY;
} else {
goto RECURSIVE_COMMAND;
}
}
{
static BOOL bShift = FALSE;
if (IsDepressedShiftKeyOnly(nKey)) {
if (lParam & BEING_RELEASED) {
if (bShift) {
CCommands::SetMark(FALSE);
}
} else {
bShift = TRUE;
}
} else {
bShift = FALSE;
}
}
if (CUtils::IsNT()) {
switch (nKey) {
case VK_CONTROL:
if (lParam & EXTENDED_KEY) {
nKey = VK_RCONTROL;
} else {
nKey = VK_LCONTROL;
}
break;
case VK_MENU:
if (lParam & EXTENDED_KEY) {
nKey = VK_RMENU;
} else {
nKey = VK_LMENU;
}
break;
case VK_SHIFT:
if (lParam & EXTENDED_KEY) {
nKey = VK_RSHIFT;
} else {
nKey = VK_LSHIFT;
}
break;
default:
break;
}
}
if (lParam & BEING_RELEASED) {
if (nKey == VK_LWIN
|| nKey == VK_RWIN
|| nKey == VK_APPS) {
for (int i = 0; i < MAX_COMMAND_TYPE; ++i) {
if (Commands[m_nCommandID[m_nApplicationID][i][nKey]].fCommand) {
goto HOOK;
}
}
}
if (nOneShotModifier[nKey]) {
ReleaseKey(nOneShotModifier[nKey]);
nOneShotModifier[nKey] = 0;
if (bCherryOneShotModifier) {
bCherryOneShotModifier = FALSE;
Kdu(nKey);
}
}
goto DO_NOTHING;
}
if (m_nSettingStyle[m_nApplicationID] == SETTING_DISABLE) {
goto DO_NOTHING;
}
// Do Nothing for Meadow, Mule for Win32, ... if those use default setting.
if (!stricmp(m_szSpecialApp[m_nApplicationID], "Default")
&& CUtils::IsDefaultIgnoreApplication()) {
goto DO_NOTHING;
}
switch (IsPassThrough(nKey)) {
case GOTO_DO_NOTHING:
goto DO_NOTHING;
case GOTO_HOOK:
goto HOOK;
case CONTINUE:
break;
default:
ASSERT(0);
break;
}
// set command type
{
nCommandType = NONE;
if (IsDown(VK_SHIFT)) {
nCommandType |= SHIFT;
}
if (IsControl()) {
nCommandType |= CONTROL;
}
if (IsMeta()) {
nCommandType |= META;
}
if (CCommands::bC_x()) {
nCommandType |= CONTROLX;
}
// Ignore undefined C-x ?
if (nCommandType & CONTROLX) {
if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL
&& m_nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {
if (m_bIgnoreUndefinedC_x[m_nApplicationID]) {
CCommands::Reset(GOTO_HOOK);
goto HOOK;
}
nCommandType &= ~CONTROLX;
}
}
// Ignore undefined Meta Ctrl+?
if (CCommands::bM_() && (nCommandType & CONTROL)) {
if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == NULL
&& m_nFunctionID[m_nApplicationID][nCommandType][nKey] < 0) {
if (m_bIgnoreUndefinedMetaCtrl[m_nApplicationID]) {
if (Original(CONTROL, nKey)) {
Original(CONTROL, nKey, -1);
goto DO_NOTHING;
}
CCommands::Reset(GOTO_HOOK);
goto HOOK;
}
nCommandType &= ~META;
}
}
}
{
int nVirtualCommandType = NONE;
if (IsDown(VK_CONTROL, FALSE)) {
nVirtualCommandType |= CONTROL;
}
if (IsDown(VK_MENU, FALSE)) {
nVirtualCommandType |= META;
}
if (Original(nVirtualCommandType, nKey)) {
Original(nVirtualCommandType, nKey, -1);
goto DO_NOTHING;
}
}
if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableOrDisableXKeymacs) {
SetKeyboardHookFlag(!m_bHook);
goto HOOK;
}
if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::EnableXKeymacs) {
if (!m_bHook) {
SetKeyboardHookFlag(!m_bHook);
}
goto HOOK;
}
if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::DisableXKeymacs) {
if (m_bHook) {
SetKeyboardHookFlag(!m_bHook);
}
goto HOOK;
}
if (!m_bHook) {
goto DO_NOTHING;
}
if (CCommands::bC_u()) {
if ((nCommandType == NONE) && ('0' <= nKey) && (nKey <= '9')) {
CCommands::NumericArgument(nKey - '0');
goto HOOK0_9;
}
if ((nCommandType == NONE) && (nKey == 0xBD)) {
CCommands::NumericArgumentMinus();
goto HOOK0_9;
}
}
if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrl) {
nOneShotModifier[nKey] = VK_LCONTROL;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {
nOneShotModifier[nKey] = VK_LCONTROL;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~CONTROL][nKey]].fCommand == CCommands::OneShotModifierCtrlRepeat) {
ReleaseKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = FALSE;
Kdu(nKey);
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAlt) {
nOneShotModifier[nKey] = VK_LMENU;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {
nOneShotModifier[nKey] = VK_LMENU;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~META][nKey]].fCommand == CCommands::OneShotModifierAltRepeat) {
ReleaseKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = FALSE;
Kdu(nKey);
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShift) {
nOneShotModifier[nKey] = VK_SHIFT;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {
nOneShotModifier[nKey] = VK_SHIFT;
DepressKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = TRUE;
goto HOOK;
} else if (Commands[m_nCommandID[m_nApplicationID][nCommandType & ~SHIFT][nKey]].fCommand == CCommands::OneShotModifierShiftRepeat) {
ReleaseKey(nOneShotModifier[nKey]);
bCherryOneShotModifier = FALSE;
Kdu(nKey);
goto HOOK;
} else {
for (int i = 0; i < MAX_KEY; ++i) {
if (nOneShotModifier[i] == nKey) {
break;
}
}
if (i == MAX_KEY) {
bCherryOneShotModifier = FALSE;
}
}
if (!Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand) {
if (0 <= m_nFunctionID[m_nApplicationID][nCommandType][nKey]
&& m_nFunctionID[m_nApplicationID][nCommandType][nKey] < MAX_FUNCTION
&& strlen(m_szFunctionDefinition[m_nFunctionID[m_nApplicationID][nCommandType][nKey]])) {
CallFunction(m_nFunctionID[m_nApplicationID][nCommandType][nKey]);
goto HOOK;
}
if (nKey == VK_CONTROL
|| nKey == VK_LCONTROL
|| nKey == VK_RCONTROL
|| nKey == VK_MENU
|| nKey == VK_LMENU
|| nKey == VK_RMENU
|| nKey == VK_SHIFT
|| nKey == VK_LSHIFT
|| nKey == VK_RSHIFT) {
goto DO_NOTHING;
}
if (!(nCommandType & SHIFT)) {
if (CCommands::IsSetMark()) {
if (CCommands::MoveCaret(nKey, nCommandType & CONTROL) != CONTINUE) {
CCommands::ClearNumericArgument();
goto HOOK;
}
CCommands::SetMark(FALSE);
}
}
if (1 < CCommands::GetNumericArgument()) {
Kdu(nKey, CCommands::GetNumericArgument());
CCommands::ClearNumericArgument();
goto HOOK;
}
goto DO_NOTHING;
}
if (CCommands::IsTemporarilyDisableXKeymacs()
&& Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand != CCommands::KeyboardQuit) {
CCommands::SetTemporarilyDisableXKeymacs(FALSE);
goto DO_NOTHING;
}
m_bRightControl = IsDown(VK_RCONTROL);
m_bRightAlt = IsDown(VK_RMENU);
m_bRightShift = IsDown(VK_RSHIFT);
if (!bLocked) {
bLocked = TRUE;
fCommand = Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand;
RECURSIVE_COMMAND:
switch (fCommand()) {
case GOTO_DO_NOTHING:
bLocked = FALSE;
goto DO_NOTHING;
case GOTO_HOOK:
bLocked = FALSE;
goto HOOK;
case GOTO_RECURSIVE:
goto RECURSIVE;
case GOTO_HOOKX:
bLocked = FALSE;
goto HOOKX;
case GOTO_HOOK0_9:
bLocked = FALSE;
goto HOOK0_9;
default:
ASSERT(0);
bLocked = FALSE;
goto DO_NOTHING;
}
} else {
goto HOOK_RECURSIVE_KEY;
}
DO_NOTHING:
ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT, FALSE));
ModifyShell_NotifyIcon(CTRL_ICON, IsControl());
ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU, FALSE));
{
static BOOL bDefiningMacro = FALSE;
if (m_bDefiningMacro) {
static BOOL bDown[MAX_KEY] = {'\0'};
if (!bDefiningMacro) {
while (m_Macro.GetHeadPosition()) {
void *p = m_Macro.GetAt(m_Macro.GetHeadPosition());
m_Macro.RemoveHead();
delete p;
p = NULL;
}
memset(bDown, 0, sizeof(bDown));
}
if ((!(lParam & BEING_RELEASED)) || bDown[wParam]) {
KbdMacro_t *pKbdMacro = new KbdMacro;
pKbdMacro->nCode = nCode;
pKbdMacro->wParam = wParam;
pKbdMacro->lParam = lParam;
pKbdMacro->bOriginal = TRUE;
m_Macro.AddTail((CObject *)pKbdMacro);
if (!(lParam & BEING_RELEASED)) {
bDown[wParam] = TRUE;
}
}
}
bDefiningMacro = m_bDefiningMacro;
}
return ::CallNextHookEx(m_hHookKeyboard, nCode, wParam, lParam);
RECURSIVE:
Kdu(RECURSIVE_KEY, 1, FALSE);
ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT, FALSE));
ModifyShell_NotifyIcon(CTRL_ICON, IsControl());
ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU, FALSE));
return TRUE;
HOOK:
CCommands::SetLastCommand(fCommand);
HOOK0_9:
HOOKX:
ModifyShell_NotifyIcon(SHIFT_ICON, IsDown(VK_SHIFT, FALSE));
ModifyShell_NotifyIcon(CTRL_ICON, IsControl());
ModifyShell_NotifyIcon(ALT_ICON, IsDown(VK_MENU, FALSE));
HOOK_RECURSIVE_KEY:
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CXkeymacsData Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXkeymacsData::CXkeymacsData()
{
ClearAll();
}
CXkeymacsData::~CXkeymacsData()
{
}
// set application name
void CXkeymacsData::SetApplicationName(LPCTSTR lpszApplicationName)
{
m_strApplicationName.Format(lpszApplicationName);
}
// return application name
CString CXkeymacsData::GetApplicationName()
{
return m_strApplicationName;
}
// set hook or not
void CXkeymacsData::SetCommandID(int nCommandType, int nKey, int nCommandID)
{
ASSERT(0 <= nCommandType || nCommandType < MAX_COMMAND_TYPE);
ASSERT(0 <= nKey || nKey < MAX_KEY);
m_nCommandID[nCommandType][nKey] = nCommandID;
}
// return hook or not
int CXkeymacsData::GetCommandID(int nCommandType, int nKey)
{
ASSERT(0 <= nCommandType || nCommandType < MAX_COMMAND_TYPE);
ASSERT(0 <= nKey || nKey < MAX_KEY);
return m_nCommandID[nCommandType][nKey];
}
// clear all data
void CXkeymacsData::ClearAll()
{
ZeroMemory(m_nCommandID, sizeof(m_nCommandID));
m_strApplicationName.Empty();
}
// set application name
void CXkeymacsDll::SetApplicationName(int nApplicationID, CString szApplicationName)
{
ZeroMemory(m_szSpecialApp[nApplicationID], sizeof(m_szSpecialApp[nApplicationID]));
strncpy(m_szSpecialApp[nApplicationID], szApplicationName, sizeof(m_szSpecialApp[nApplicationID]));
}
// set m_nCommandID[nApplicationID][nCommandType][nKey] nCommandID
void CXkeymacsDll::SetCommandID(int nApplicationID, int nCommandType, int nKey, int nCommandID)
{
m_nCommandID[nApplicationID][nCommandType][nKey] = nCommandID;
}
void CXkeymacsDll::SetKillRingMax(int nApplicationID, int nKillRingMax)
{
m_nKillRingMax[nApplicationID] = nKillRingMax;
}
void CXkeymacsDll::SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting)
{
m_bUseDialogSetting[nApplicationID] = bUseDialogSetting;
}
// Clear data of nApplicationID
void CXkeymacsDll::Clear(int nApplicationID)
{
if (0 <= nApplicationID && nApplicationID < MAX_APP) {
ZeroMemory(m_szSpecialApp[nApplicationID], sizeof(m_szSpecialApp[nApplicationID]));
ZeroMemory(m_nCommandID[nApplicationID], sizeof(m_nCommandID[nApplicationID]));
m_nKillRingMax[nApplicationID] = 0;
m_bUseDialogSetting[nApplicationID] = FALSE;
m_nSettingStyle[nApplicationID] = 0;
} else {
ASSERT(0);
}
}
void CXkeymacsData::SetApplicationTitle(LPCTSTR lpszApplicationTitle)
{
m_strApplicationTitle.Format(lpszApplicationTitle);
// delete white space at the end of the application title.
while (!m_strApplicationTitle.IsEmpty()
&& isspace(m_strApplicationTitle.GetAt(m_strApplicationTitle.GetLength() - 1))) {
m_strApplicationTitle.Delete(m_strApplicationTitle.GetLength() - 1);
}
}
CString CXkeymacsData::GetApplicationTitle()
{
return m_strApplicationTitle;
}
void CXkeymacsData::SetKillRingMax(int nKillRingMax)
{
m_nKillRingMax = nKillRingMax;
}
int CXkeymacsData::GetKillRingMax()
{
return m_nKillRingMax;
}
BOOL CXkeymacsDll::IsValidKey(BYTE bVk)
{
if (bVk == 0xf0) { // 0xf0: Eisu key. GetAsyncKeyState returns the wrong state of Eisu key.
return FALSE;
}
if (CUtils::IsNT()) {
switch (bVk) {
case VK_CONTROL:
case VK_MENU:
case VK_SHIFT:
return FALSE;
default:
break;
}
}
return TRUE;
}
BOOL CXkeymacsDll::IsFoo(BOOL (__cdecl *bF_)(void), int (__cdecl *Foo)(void))
{
if (bF_()) {
return TRUE;
}
BYTE bVk = 0;
do {
if (!IsValidKey(bVk)) {
continue;
}
if (!IsDown(bVk)) {
continue;
}
if (Commands[m_nCommandID[m_nApplicationID][NONE][bVk]].fCommand == Foo) {
return TRUE;
}
} while (++bVk);
return FALSE;
}
BOOL CXkeymacsDll::IsDepressedShiftKeyOnly(BYTE nKey)
{
if (nKey != VK_SHIFT
&& nKey != VK_LSHIFT
&& nKey != VK_RSHIFT) {
return FALSE;
}
BYTE bVk = 0;
do {
if (bVk == VK_SHIFT
|| bVk == VK_LSHIFT
|| bVk == VK_RSHIFT) {
continue;
}
if (IsDown(bVk)) {
return FALSE;
}
} while (++bVk);
return TRUE;
}
BOOL CXkeymacsDll::IsControl()
{
return IsFoo(CCommands::bC_, CCommands::C_);
}
BOOL CXkeymacsDll::IsMeta()
{
return IsFoo(CCommands::bM_, CCommands::MetaAlt);
}
void CXkeymacsDll::AddKillRing(BOOL bNewData)
{
if (m_nKillRingMax[m_nApplicationID] == 0) {
return;
}
CClipboardSnap *pSnap = new CClipboardSnap;
if( !pSnap ) return;
BOOL bCapture = pSnap->Capture();
bCapture = pSnap->Capture(); // for "office drawing shape format". Can CClipboardSnap care this problem?
if( bCapture ) {
if (bNewData) {
m_oKillRing.AddHead(pSnap);
} else {
if (m_oKillRing.IsEmpty()) {
m_oKillRing.AddHead(pSnap);
} else {
for (CClipboardSnap *pParent = m_oKillRing.GetHead(); pParent->GetNext(); pParent = pParent->GetNext()) {
;
}
pParent->SetNext(pSnap);
}
}
} else {
delete pSnap;
pSnap = NULL;
}
m_nKillRing = 0;
if (m_nKillRingMax[m_nApplicationID] < m_oKillRing.GetCount()) {
CClipboardSnap *pSnap = m_oKillRing.GetTail();
delete pSnap;
pSnap = NULL;
m_oKillRing.RemoveTail();
}
}
// Return TRUE if there is another data
// Return FALSE if there is no more data
CClipboardSnap* CXkeymacsDll::GetKillRing(CClipboardSnap* pSnap, BOOL bForce)
{
if (m_nKillRingMax[m_nApplicationID] == 0) {
return NULL;
}
if (m_oKillRing.IsEmpty()) {
return NULL;
}
m_nKillRing %= m_oKillRing.GetCount();
if (!bForce) {
CClipboardSnap oCurrentSnap;
oCurrentSnap.Capture();
CClipboardSnap *pKillRing = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));
if (!pKillRing) {
return NULL;
}
for (; pKillRing->GetNext(); pKillRing = pKillRing->GetNext()) {
;
}
if (*pKillRing != oCurrentSnap) {
return NULL;
}
}
if (!pSnap) {
pSnap = m_oKillRing.GetAt(m_oKillRing.FindIndex(m_nKillRing));
}
pSnap->Restore();
return pSnap->GetNext();
}
void CXkeymacsDll::Original(int nCommandType, BYTE bVk, int nOriginal)
{
nCommandType &= ~SHIFT;
if (CUtils::IsNT()) {
switch (bVk) {
case VK_CONTROL:
bVk = VK_LCONTROL;
break;
case VK_MENU:
bVk = VK_LMENU;
break;
case VK_SHIFT:
bVk = VK_LSHIFT;
break;
default:
break;
}
}
m_nOriginal[nCommandType][bVk] += nOriginal;
}
int CXkeymacsDll::Original(int nCommandType, BYTE bVk)
{
nCommandType &= ~SHIFT;
if (CUtils::IsNT()) {
switch (bVk) {
case VK_CONTROL:
bVk = VK_LCONTROL;
break;
case VK_MENU:
bVk = VK_LMENU;
break;
case VK_SHIFT:
bVk = VK_LSHIFT;
break;
default:
break;
}
}
return m_nOriginal[nCommandType][bVk];
}
void CXkeymacsDll::IncreaseKillRingIndex(int nKillRing)
{
m_nKillRing += nKillRing;
}
// move CCommands
CString CXkeymacsData::GetCommandName(int nCommandID)
{
CString szCommandName(Commands[nCommandID].szCommandName);
return szCommandName;
}
// move CCommands
int CXkeymacsData::GetDefaultCommandType(int nCommandID, int nIndex)
{
if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID
|| nIndex < 0 || sizeof(Commands[nCommandID].keybind) / sizeof(Commands[nCommandID].keybind[0]) <= nIndex) {
ASSERT(0);
return NONE;
}
int nCommandType = Commands[nCommandID].keybind[nIndex].nCommandType;
int bVk = Commands[nCommandID].keybind[nIndex].bVk;
if (m_b106Keyboard) {
if (nCommandType & SHIFT) { // Shift
switch (bVk) {
case '2':
case '6':
case 0xBA: // VK_OEM_1 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the ';:' key
nCommandType &= ~SHIFT;
break;
default:
break;
}
} else { // Normal
switch (bVk) {
case 0xBB: // VK_OEM_PLUS Windows 2000/XP: For any country/region, the '+' key
case 0xC0: // VK_OEM_3 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the '`~' key
case 0xDE: // VK_OEM_7 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
nCommandType |= SHIFT;
break;
default:
break;
}
}
}
return nCommandType;
}
// move CCommands
int CXkeymacsData::GetDefaultCommandKey(int nCommandID, int nIndex)
{
if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID
|| nIndex < 0 || sizeof(Commands[nCommandID].keybind) / sizeof(Commands[nCommandID].keybind[0]) <= nIndex) {
ASSERT(0);
return 0;
}
int nCommandType = Commands[nCommandID].keybind[nIndex].nCommandType;
int bVk = Commands[nCommandID].keybind[nIndex].bVk;
if (m_b106Keyboard) {
if (nCommandType & SHIFT) { // Shift
switch (bVk) {
case '0':
bVk = '9';
break;
case '2':
bVk = 0xC0; // VK_OEM_3 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the '`~' key
break;
case '6':
bVk = 0xDE; // VK_OEM_7 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
break;
case '7':
bVk = '6';
break;
case '8':
bVk = 0xBA; // VK_OEM_1 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the ';:' key
break;
case '9':
bVk = '8';
break;
case 0xBD: // VK_OEM_MINUS Windows 2000/XP: For any country/region, the '-' key
bVk = 0xE2; // VK_OEM_102 Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
break;
case 0xC0:
bVk = 0xDE; // VK_OEM_7 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
break;
case 0xDE: // VK_OEM_7 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
bVk = '2';
break;
default:
break;
}
} else { // Normal
switch (bVk) {
case 0xBA: // VK_OEM_1 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the ';:' key
bVk = 0xBB; // VK_OEM_PLUS Windows 2000/XP: For any country/region, the '+' key
break;
case 0xBB: // VK_OEM_PLUS Windows 2000/XP: For any country/region, the '+' key
bVk = 0xBD; // VK_OEM_MINUS Windows 2000/XP: For any country/region, the '-' key
break;
case 0xDE: // VK_OEM_7 Used for miscellaneous characters; it can vary by keyboard.
// Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
bVk = '7';
break;
default:
break;
}
}
}
return bVk;
}
// move CCommands
int CXkeymacsData::GetDefaultControlID(int nCommandID, int nIndex)
{
if (nCommandID < 0 || sizeof(Commands) / sizeof(Commands[0]) <= nCommandID
|| nIndex < 0 || sizeof(Commands[nCommandID].keybind) / sizeof(Commands[nCommandID].keybind[0]) <= nIndex) {
ASSERT(0);
return 0;
}
return Commands[nCommandID].keybind[nIndex].nControlID;
}
// nobody use
int CXkeymacsDll::GetMickey(int nDifferential, int nThreshold1, int nThreshold2, int nAcceleration, int nSpeed)
{
nDifferential = nDifferential * 10 / nSpeed;
switch (nAcceleration) {
case 2:
if (nThreshold2 < fabs((double)(nDifferential / 4))) {
nDifferential /= 4;
break;
}
// Do NOT write break; here.
case 1:
if (nThreshold1 < fabs((double)(nDifferential / 2))) {
nDifferential /= 2;
}
break;
case 0:
break;
default:
ASSERT(0);
break;
}
return nDifferential;
}
int CXkeymacsData::GetSettingStyle()
{
return m_nSettingStyle;
}
void CXkeymacsData::SetSettingStyle(int nSettingStyle)
{
m_nSettingStyle = nSettingStyle;
}
void CXkeymacsDll::SetSettingStyle(int nApplicationID, int nSettingStyle)
{
m_nSettingStyle[nApplicationID] = nSettingStyle;
}
int CXkeymacsData::GetCategoryID(int nCommandID)
{
return Commands[nCommandID].nCategoryID;
}
void CXkeymacsData::SetIgnoreUndefinedMetaCtrl(BOOL bIgnoreUndefinedMetaCtrl)
{
m_bIgnoreUndefinedMetaCtrl = bIgnoreUndefinedMetaCtrl;
}
BOOL CXkeymacsData::GetIgnoreUndefinedMetaCtrl()
{
return m_bIgnoreUndefinedMetaCtrl;
}
void CXkeymacsDll::SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl)
{
m_bIgnoreUndefinedMetaCtrl[nApplicationID] = bIgnoreUndefinedMetaCtrl;
}
void CXkeymacsData::SetIgnoreUndefinedC_x(BOOL bIgnoreUndefinedC_x)
{
m_bIgnoreUndefinedC_x = bIgnoreUndefinedC_x;
}
BOOL CXkeymacsData::GetIgnoreUndefinedC_x()
{
return m_bIgnoreUndefinedC_x;
}
void CXkeymacsDll::SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x)
{
m_bIgnoreUndefinedC_x[nApplicationID] = bIgnoreUndefinedC_x;
}
void CXkeymacsData::SetEnableCUA(BOOL bEnableCUA)
{
m_bEnableCUA = bEnableCUA;
}
BOOL CXkeymacsData::GetEnableCUA()
{
return m_bEnableCUA;
}
void CXkeymacsDll::SetEnableCUA(int nApplicationID, BOOL bEnableCUA)
{
m_bEnableCUA[nApplicationID] = bEnableCUA;
}
BOOL CXkeymacsDll::GetEnableCUA()
{
return m_bEnableCUA[m_nApplicationID];
}
void CXkeymacsData::SetUseDialogSetting(BOOL bUseDialogSetting)
{
m_bUseDialogSetting = bUseDialogSetting;
}
BOOL CXkeymacsData::GetUseDialogSetting()
{
return m_bUseDialogSetting;
}
int CXkeymacsData::GetDescriptionID(int nCommandID)
{
return Commands[nCommandID].nDescriptionID;
}
int CXkeymacsData::GetToolTipID(int nCommandID)
{
return Commands[nCommandID].nToolTipID;
}
void CXkeymacsDll::DefiningMacro(BOOL bDefiningMacro)
{
m_bDefiningMacro = bDefiningMacro;
if (bDefiningMacro) { // start-kbd-macro
if (CCommands::bC_u()) {
ReleaseKey(VK_SHIFT);
CallMacro();
}
} else { // end-kbd-macro
while (!m_Macro.IsEmpty()) {
KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetTail();
if (pKbdMacro->lParam & BEING_RELEASED) {
break;
} else {
m_Macro.RemoveTail();
delete pKbdMacro;
pKbdMacro = NULL;
}
}
// CUtils::Log("Macro MemMap: start");
if (!m_Macro.IsEmpty()) {
static HANDLE hMacro = NULL;
if (!hMacro) {
hMacro = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x3000, "macro");
}
if (hMacro) {
// CUtils::Log("Macro MemMap: 1");
PVOID pView = MapViewOfFile(hMacro, FILE_MAP_ALL_ACCESS, 0, 0, 0);
// CUtils::Log("Macro MemMap: 2");
if (pView) {
// CUtils::Log("Macro MemMap: 2.5");
for (int i = 0; i < m_Macro.GetCount(); ++i) {
// CUtils::Log("Macro MemMap: 3-1 %d", i);
KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetAt(m_Macro.FindIndex(i));
// CUtils::Log("Macro MemMap: 3-2 %d", i);
memcpy((char *) pView + i * sizeof(KbdMacro_t), pKbdMacro, sizeof(KbdMacro_t));
// CUtils::Log("Macro MemMap: 3-3 %d", i);
}
// CUtils::Log("Macro MemMap: 4");
UnmapViewOfFile(pView);
// CUtils::Log("Macro MemMap: 5");
} else {
// CUtils::Log("Macro MemMpa: error: %d", GetLastError());
}
} else {
// CUtils::Log("Macro MemMap: 6");
ASSERT(0);
}
}
}
}
BOOL CXkeymacsDll::DefiningMacro()
{
return m_bDefiningMacro;
}
/**/
void CXkeymacsDll::CallMacro()
{
BOOL bIsCtrlDown = IsDown(VK_CONTROL);
if (bIsCtrlDown) {
ReleaseKey(VK_CONTROL);
}
BOOL bIsAltDown = IsDown(VK_MENU);
if (bIsAltDown) {
ReleaseKey(VK_MENU);
}
BOOL bIsShiftDown = IsDown(VK_SHIFT);
if (bIsShiftDown) {
ReleaseKey(VK_SHIFT);
}
for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {
KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetNext(pos);
if (pKbdMacro->lParam & BEING_RELEASED) {
ReleaseKey((BYTE)pKbdMacro->wParam);
} else {
DepressKey((BYTE)pKbdMacro->wParam, pKbdMacro->bOriginal);
}
}
if (bIsCtrlDown) {
DepressKey(VK_CONTROL);
}
if (bIsAltDown) {
DepressKey(VK_MENU);
}
if (bIsShiftDown) {
DepressKey(VK_SHIFT);
}
}
/*/
void CXkeymacsDll::CallMacro() // for debug
{
CString sz;
for (POSITION pos = m_Macro.GetHeadPosition(); pos; ) {
KbdMacro_t *pKbdMacro = (KbdMacro_t *)m_Macro.GetNext(pos);
if (pKbdMacro->lParam & BEING_RELEASED) {
CString t;
t.Format("0x%xu ", pKbdMacro->wParam);
sz += t;
} else {
CString t;
t.Format("0x%xd ", pKbdMacro->wParam);
sz += t;
}
}
// CUtils::Log(sz);
}
/**/
void CXkeymacsData::Set106Keyboard(BOOL b106Keyboard)
{
m_b106Keyboard = b106Keyboard;
}
BOOL CXkeymacsData::Is106Keyboard()
{
return m_b106Keyboard;
}
int CXkeymacsDll::IsPassThrough(BYTE nKey)
{
BYTE bVk = 0;
do {
if (IsDown(bVk)
&& (Commands[m_nCommandID[m_nApplicationID][NONE][bVk]].fCommand == CCommands::PassThrough)) {
if (bVk == nKey) {
return GOTO_HOOK;
}
return GOTO_DO_NOTHING;
}
} while (++bVk);
return CONTINUE;
}
void CXkeymacsDll::SetKeyboardHookFlag()
{
SetKeyboardHookFlag(m_bHook);
}
void CXkeymacsDll::SetFunctionKey(int nFunctionID, int nApplicationID, int nCommandType, int nKey)
{
if (nApplicationID < 0 || MAX_APP <= nApplicationID
|| nCommandType < 0 || MAX_COMMAND_TYPE <= nCommandType
|| nKey < 0 || MAX_KEY <= nKey) {
return;
}
m_nFunctionID[nApplicationID][nCommandType][nKey] = nFunctionID;
}
void CXkeymacsDll::ClearFunctionDefinition()
{
memset(m_nFunctionID, -1, sizeof(m_nFunctionID));
memset(m_szFunctionDefinition, 0, sizeof(m_szFunctionDefinition));
}
void CXkeymacsDll::SetFunctionDefinition(int nFunctionID, CString szDefinition)
{
if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID) {
return;
}
memset(m_szFunctionDefinition[nFunctionID], 0, sizeof(m_szFunctionDefinition[nFunctionID]));
sprintf(m_szFunctionDefinition[nFunctionID], "%s", szDefinition);
return;
}
void CXkeymacsDll::CallFunction(int nFunctionID)
{
if (nFunctionID < 0 || MAX_FUNCTION <= nFunctionID || !strlen(m_szFunctionDefinition[nFunctionID])) {
return;
}
BOOL bIsCtrlDown = CXkeymacsDll::IsDown(VK_CONTROL);
BOOL bIsAltDown = CXkeymacsDll::IsDown(VK_MENU);
BOOL bIsShiftDown = CXkeymacsDll::IsDown(VK_SHIFT);
if (bIsCtrlDown) {
CUtils::UpdateKeyboardState(VK_CONTROL, 0);
ReleaseKey(VK_CONTROL);
}
if (bIsAltDown) {
ReleaseKey(VK_MENU);
}
if (bIsShiftDown) {
ReleaseKey(VK_SHIFT);
}
if (m_szFunctionDefinition[nFunctionID][0] == '"' && m_szFunctionDefinition[nFunctionID][strlen(m_szFunctionDefinition[nFunctionID]) - 1] == '"') {
for (unsigned int i = 1; i < strlen(m_szFunctionDefinition[nFunctionID]) - 1; ++i) { // skip '"'
ParseKey(nFunctionID, i);
}
} else if (m_szFunctionDefinition[nFunctionID][0] == '[' && m_szFunctionDefinition[nFunctionID][strlen(m_szFunctionDefinition[nFunctionID]) - 1] == ']') {
for (unsigned int i = 1; i < strlen(m_szFunctionDefinition[nFunctionID]) - 1; ++i) { // skip '[' and ']'
if (m_szFunctionDefinition[nFunctionID][i] == '?') { // [?f ?o ?o]
++i;
ParseKey(nFunctionID, i);
} else { // [ControlCharacter]
for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {
if (!strncmp(m_szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, strlen(ControlCharacters[nKeyID].name))) {
Kdu(ControlCharacters[nKeyID].bVk);
i += strlen(ControlCharacters[nKeyID].name);
break;
}
}
}
}
} else {
return;
}
if (bIsShiftDown) {
DepressKey(VK_SHIFT);
}
if (bIsAltDown) {
DepressKey(VK_MENU);
}
if (bIsCtrlDown) {
DepressKey(VK_CONTROL);
CUtils::UpdateKeyboardState(VK_CONTROL, 1);
}
return;
}
void CXkeymacsDll::ParseKey(const int nFunctionID, unsigned int &i) // FIXME: Do NOT call Kdu but return command type and key.
{
int nCommandType = NONE;
if (m_szFunctionDefinition[nFunctionID][i] == '\\') {
++i;
BOOL bFound = FALSE;
do {
bFound = FALSE;
for (int ModifierID = 0; ModifierID < sizeof(Modifiers) / sizeof(Modifiers[0]); ++ModifierID) {
if (!strncmp(m_szFunctionDefinition[nFunctionID] + i, Modifiers[ModifierID].name, strlen(Modifiers[ModifierID].name))
&& strlen(Modifiers[ModifierID].name) < strlen(m_szFunctionDefinition[nFunctionID] + i)) {
nCommandType |= Modifiers[ModifierID].id;
i+= strlen(Modifiers[ModifierID].name);
bFound = TRUE;
}
}
} while (bFound);
}
if (IsShift(m_szFunctionDefinition[nFunctionID][i]) && !(nCommandType & (WIN_CTRL | WIN_ALT))) {
nCommandType |= SHIFT;
}
for (int nKeyID = 0; nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0]); ++nKeyID) {
if (!strncmp(m_szFunctionDefinition[nFunctionID] + i, ControlCharacters[nKeyID].name, strlen(ControlCharacters[nKeyID].name))) {
i += strlen(ControlCharacters[nKeyID].name);
break;
}
}
BYTE nKey = NULL;
if (nKeyID < sizeof(ControlCharacters) / sizeof(ControlCharacters[0])) {
nKey = ControlCharacters[nKeyID].bVk;
} else {
nKey = a2v(m_szFunctionDefinition[nFunctionID][i]);
}
if (nCommandType < MAX_COMMAND_TYPE && Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand) {
while (Commands[m_nCommandID[m_nApplicationID][nCommandType][nKey]].fCommand() == GOTO_RECURSIVE) {
;
}
} else {
Kdu(nCommandType, nKey);
}
}
void CXkeymacsDll::Kdu(int nCommandType, BYTE bVk)
{
if (nCommandType < MAX_COMMAND_TYPE && Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand) {
Commands[m_nCommandID[m_nApplicationID][nCommandType][bVk]].fCommand();
} else { // FIXME
if (nCommandType & WIN_CTRL) {
DepressKey(VK_CONTROL);
}
if (nCommandType & WIN_ALT) {
DepressKey(VK_MENU);
}
if (nCommandType & SHIFT) {
DepressKey(VK_SHIFT);
}
Kdu(bVk);
if (nCommandType & SHIFT) {
ReleaseKey(VK_SHIFT);
}
if (nCommandType & WIN_ALT) {
ReleaseKey(VK_MENU);
}
if (nCommandType & WIN_CTRL) {
ReleaseKey(VK_CONTROL);
}
}
return;
}
BOOL CXkeymacsDll::IsShift(char nAscii)
{
switch (nAscii) {
case ' ':
return FALSE;
case '!':
case '"':
case '#':
case '$':
case '%':
case '&':
return TRUE;
case '\'':
return CXkeymacsData::Is106Keyboard();
case '(':
case ')':
case '*':
case '+':
return TRUE;
case ',':
case '-':
case '.':
case '/':
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
return FALSE;
case ':':
return !CXkeymacsData::Is106Keyboard();
case ';':
return FALSE;
case '<':
return TRUE;
case '=':
return CXkeymacsData::Is106Keyboard();
case '>':
case '?':
return TRUE;
case '@':
return !CXkeymacsData::Is106Keyboard();
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
return TRUE;
case '[':
case '\\':
case ']':
return FALSE;
case '^':
return !CXkeymacsData::Is106Keyboard();
case '_':
return TRUE;
case '`':
return CXkeymacsData::Is106Keyboard();
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
return FALSE;
case '{':
case '|':
case '}':
case '~':
return TRUE;
default:
return FALSE;
}
}
BYTE CXkeymacsDll::a2v(char nAscii)
{
switch (nAscii) {
case ' ':
return VK_SPACE;
case '!':
return '1';
case '"':
return CXkeymacsData::Is106Keyboard() ? '2' : (BYTE) 0xde; // VK_OEM_7
case '#':
return '3';
case '$':
return '4';
case '%':
return '5';
case '&':
return CXkeymacsData::Is106Keyboard() ? '6' : '7';
case '\'':
return CXkeymacsData::Is106Keyboard() ? '7' : (BYTE) 0xde; // VK_OEM_7
case '(':
return CXkeymacsData::Is106Keyboard() ? '8' : '9';
case ')':
return CXkeymacsData::Is106Keyboard() ? '9' : '0';
case '*':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xba : '8'; // VK_OEM_1
case '+':
return 0xbb; // VK_OEM_PLUS
case ',':
return 0xbc; // VK_OEM_COMMA
case '-':
return 0xbd; // VK_OEM_MINUS
case '.':
return 0xbe; // VK_OEM_PERIOD
case '/':
return 0xbf; // VK_OEM_2
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
return nAscii;
case ':':
return 0xba; // VK_OEM_1
case ';':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xbb : (BYTE) 0xba; // VK_OEM_PLUS VK_OEM_1
case '<':
return 0xbc; // VK_OEM_COMMA
case '=':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xbd : (BYTE) 0xbb; // VK_OEM_MINUS VK_OEM_PLUS
case '>':
return 0xbe; // VK_OEM_PERIOD
case '?':
return 0xbf; // VK_OEM_2
case '@':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xc0 : '2';
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
return nAscii;
case '[':
return 0xdb; // VK_OEM_4
case '\\':
return 0xdc; // VK_OEM_5
case ']':
return 0xdd; // VK_OEM_6
case '^':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xde : '6'; // VK_OEM_7
case '_':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xe2 : (BYTE) 0xbd; // VK_OEM_102 VK_OEM_MINUS
case '`':
return 0xc0; // VK_OEM_3
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
return (BYTE) (nAscii - ('a' - 'A'));
case '{':
return 0xdb; // VK_OEM_4
case '|':
return 0xdc; // VK_OEM_5
case '}':
return 0xdd; // VK_OEM_6
case '~':
return CXkeymacsData::Is106Keyboard() ? (BYTE) 0xde : (BYTE) 0xc0; // VK_OEM_7 VK_OEM_3
default:
return 0;
}
}
void CXkeymacsDll::DeleteAllShell_NotifyIcon()
{
for (int icon = 0; icon < MAX_ICON_TYPE; ++icon) {
DeleteShell_NotifyIcon((ICON_TYPE)icon);
}
}
void CXkeymacsDll::AddAllShell_NotifyIcon()
{
for (int icon = 0; icon < MAX_ICON_TYPE; ++icon) {
AddShell_NotifyIcon((ICON_TYPE)icon);
}
}
void CXkeymacsData::SetWindowText(LPCTSTR lpszWindowText)
{
m_strWindowText.Format(lpszWindowText);
}
CString CXkeymacsData::GetWindowText()
{
return m_strWindowText;
}
void CXkeymacsData::SetWindowTextType(int nWindowTextType)
{
m_nWindowTextType = nWindowTextType;
}
int CXkeymacsData::GetWindowTextType()
{
return m_nWindowTextType;
}