// PropertiesAdvanced.cpp : implementation file
//
#include "stdafx.h"
#include "xkeymacs.h"
#include "DotXkeymacs.h"
#include "Profile.h"
#include "Properties.h"
#include "PropertiesAdvanced.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma data_seg(".xkmcs")
int CPropertiesAdvanced::m_nApplicationID = 0;
#pragma data_seg()
/////////////////////////////////////////////////////////////////////////////
// CPropertiesAdvanced property page
int CPropertiesAdvanced::m_nCommandID = 0;
CEdit * CPropertiesAdvanced::m_pNewKey = NULL;
CButton * CPropertiesAdvanced::m_pAssign = NULL;
CStatic * CPropertiesAdvanced::m_pCurrentlyAssigned = NULL;
CListBox * CPropertiesAdvanced::m_pCurrentKeys = NULL;
HHOOK CPropertiesAdvanced::m_hKeyboardHook = NULL;
BOOL CPropertiesAdvanced::m_bC_x = FALSE;
BOOL CPropertiesAdvanced::m_bC = TRUE;
BOOL CPropertiesAdvanced::m_bM = TRUE;
BOOL CPropertiesAdvanced::m_bShift = TRUE;
int CPropertiesAdvanced::m_nAssignCommandType = 0;
int CPropertiesAdvanced::m_nAssignKey = 0;
int CPropertiesAdvanced::m_nCommandIDs[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
IMPLEMENT_DYNCREATE(CPropertiesAdvanced, CPropertyPage)
CPropertiesAdvanced::CPropertiesAdvanced() : CPropertyPage(CPropertiesAdvanced::IDD)
{
//{{AFX_DATA_INIT(CPropertiesAdvanced)
m_bEnableCUA = FALSE;
//}}AFX_DATA_INIT
}
CPropertiesAdvanced::~CPropertiesAdvanced()
{
}
void CPropertiesAdvanced::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPropertiesAdvanced)
DDX_Control(pDX, IDC_CURRENTLY_ASSIGNED, m_cCurrentlyAssigned);
DDX_Control(pDX, IDC_RESET_ALL, m_cResetAll);
DDX_Control(pDX, IDC_REMOVE, m_cRemove);
DDX_Control(pDX, IDC_NEW_KEY, m_cNewKey);
DDX_Control(pDX, IDC_DESCRIPTION, m_cDescription);
DDX_Control(pDX, IDC_CURRENT_KEYS, m_cCurrentKeys);
DDX_Control(pDX, IDC_COMMANDS, m_cCommands);
DDX_Control(pDX, IDC_CATEGORY, m_cCategory);
DDX_Control(pDX, IDC_ASSIGN, m_cAssign);
DDX_Check(pDX, IDC_ENABLE_CUA, m_bEnableCUA);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPropertiesAdvanced, CPropertyPage)
//{{AFX_MSG_MAP(CPropertiesAdvanced)
ON_WM_CREATE()
ON_CBN_SELCHANGE(IDC_CATEGORY, OnSelchangeCategory)
ON_LBN_SELCHANGE(IDC_COMMANDS, OnSelchangeCommands)
ON_LBN_SELCHANGE(IDC_CURRENT_KEYS, OnSelchangeCurrentKeys)
ON_EN_SETFOCUS(IDC_NEW_KEY, OnSetfocusNewKey)
ON_BN_CLICKED(IDC_ASSIGN, OnAssign)
ON_BN_CLICKED(IDC_REMOVE, OnRemove)
ON_BN_CLICKED(IDC_RESET_ALL, OnResetAll)
ON_BN_CLICKED(IDC_C_X, OnCX)
ON_EN_KILLFOCUS(IDC_NEW_KEY, OnKillfocusNewKey)
ON_BN_CLICKED(IDC_ENABLE_CUA, OnEnableCua)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPropertiesAdvanced message handlers
BOOL CPropertiesAdvanced::OnSetActive()
{
// TODO: Add your specialized code here and/or call the base class
m_pProperties->EnableControl(ADVANCED_TAB);
SetDialogData(m_pProperties->GetCurrentApplication());
return CPropertyPage::OnSetActive();
}
void CPropertiesAdvanced::SetDialogData(CString szApplicationName)
{
UpdateDialogData(szApplicationName, FALSE);
}
void CPropertiesAdvanced::UpdateDialogData(CString szApplicationName, BOOL bSaveAndValidate)
{
m_nApplicationID = m_pProperties->GetApplicationID();
if (bSaveAndValidate) { // GetDialogData
UpdateData();
}
if (m_nApplicationID == MAX_APP) { // FIXME
return;
}
InitCommandIDs();
m_bEnableCUA = CProfile::GetEnableCUA(m_nApplicationID);
if (!bSaveAndValidate) { // SetDialogData
SetCurrentKeys();
}
if (!bSaveAndValidate) { // SetDialogData
UpdateData(FALSE);
}
}
void CPropertiesAdvanced::GetDialogData()
{
UpdateDialogData(m_pProperties->GetCurrentApplication(), TRUE);
}
int CPropertiesAdvanced::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CPropertyPage::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_pProperties = (CProperties *)GetParent()->GetParent();
return 0;
}
BOOL CPropertiesAdvanced::OnKillActive()
{
// TODO: Add your specialized code here and/or call the base class
GetDialogData();
return CPropertyPage::OnKillActive();
}
void CPropertiesAdvanced::EnableControl()
{
BOOL bEnable = m_pProperties->IsEnableControl();
m_cCategory.EnableWindow(bEnable);
m_cCommands.EnableWindow(bEnable);
m_cCurrentKeys.EnableWindow(bEnable);
m_cNewKey.EnableWindow(bEnable);
m_cAssign.EnableWindow(FALSE);
m_cRemove.EnableWindow(FALSE);
m_cResetAll.EnableWindow(bEnable);
}
BOOL CPropertiesAdvanced::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// TODO: Add extra initialization here
m_nApplicationID = m_pProperties->GetApplicationID();
InitCategoryList();
SetCommands();
SetDialogData(m_pProperties->GetCurrentApplication());
m_cAssign.EnableWindow(FALSE);
m_cRemove.EnableWindow(FALSE);
m_cCurrentlyAssigned.SetWindowText("");
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CPropertiesAdvanced::InitCategoryList()
{
int nCategoryIDs[128] = {'\0'};
// get all category type
m_cCategory.ResetContent();
for (int nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {
CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);
if (szCommandName.IsEmpty()) {
break;
}
int nCategoryID = CXkeymacsData::GetCategoryID(nCommandID);
if (!nCategoryID) {
continue;
}
BOOL bExist = FALSE;
for (int i = 0; nCategoryIDs[i]; ++i) {
if (nCategoryIDs[i] == nCategoryID) {
bExist = TRUE;
}
}
if (!bExist) {
nCategoryIDs[i] = nCategoryID;
}
}
// sort category type in combo box
int nMinimumID = 0;
for (int i = 0; nCategoryIDs[i]; ++i) {
int nID = 0;
for (int j = 0; nCategoryIDs[j]; ++j) {
if (nMinimumID < nCategoryIDs[j]
&& (nID == 0 || nCategoryIDs[j] < nID)) {
nID = nCategoryIDs[j];
}
}
m_cCategory.InsertString(-1, CString(MAKEINTRESOURCE(nID)));
nMinimumID = nID;
}
if (CDotXkeymacs::GetFunctionNumber()) {
m_cCategory.InsertString(-1, CString(MAKEINTRESOURCE(IDS_ORIGINAL)));
}
m_cCategory.SetCurSel(0);
}
void CPropertiesAdvanced::SetCommands()
{
m_cCommands.ResetContent();
CString szCategory;
m_cCategory.GetLBText(m_cCategory.GetCurSel(), szCategory);
if (szCategory.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {
for (int nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {
CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);
if (szCommandName.IsEmpty()) {
break;
}
if (szCategory == CString(MAKEINTRESOURCE(CXkeymacsData::GetCategoryID(nCommandID)))) {
m_cCommands.AddString(CXkeymacsData::GetCommandName(nCommandID));
}
}
} else {
for (int i = 0; i < CDotXkeymacs::GetFunctionNumber(); ++i) {
m_cCommands.AddString(CDotXkeymacs::GetFunctionSymbol(i));
}
}
m_cCommands.SetCurSel(0);
SetCurrentKeys();
}
void CPropertiesAdvanced::SetCurrentKeys()
{
m_cCurrentKeys.ResetContent();
m_cRemove.EnableWindow(FALSE);
CString szCategory;
m_cCategory.GetLBText(m_cCategory.GetCurSel(), szCategory);
CString szCurrentCommandName;
m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);
if (szCategory.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {
for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {
for (int nKey = 0; nKey < MAX_KEY; ++nKey) {
if (CXkeymacsData::GetCommandName(CProfile::GetCommandID(m_nApplicationID, nCommandType, nKey)) == szCurrentCommandName) {
CString sz;
sz.Format("%s%s", CProfile::CommandType2String(nCommandType), CProfile::Key2String(nKey));
m_cCurrentKeys.AddString(sz);
}
}
}
for (int nCommandID = 0; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {
CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);
if (szCommandName.IsEmpty()) {
break;
}
if (szCommandName == szCurrentCommandName) {
m_nCommandID = nCommandID;
break;
}
}
m_cDescription.SetWindowText(CString(MAKEINTRESOURCE(CXkeymacsData::GetDescriptionID(m_nCommandID))));
} else {
const int nIndex = CDotXkeymacs::GetIndex(szCurrentCommandName);
for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nIndex, m_nApplicationID); ++nKeyID) {
int nCommandType = 0;
int nKey = 0;
CDotXkeymacs::GetKey(nIndex, m_nApplicationID, nKeyID, &nCommandType, &nKey);
CString sz;
sz.Format("%s%s", CProfile::CommandType2String(nCommandType), CProfile::Key2String(nKey));
m_cCurrentKeys.AddString(sz);
}
m_cDescription.SetWindowText(CDotXkeymacs::GetFunctionDefinition(szCurrentCommandName));
}
}
void CPropertiesAdvanced::OnSelchangeCategory()
{
// TODO: Add your control notification handler code here
SetCommands();
ClearNewKey();
}
void CPropertiesAdvanced::OnSelchangeCommands()
{
// TODO: Add your control notification handler code here
BOOL bEnableWindow = FALSE;
CString szCurrentCommandName;
m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);
if (szCurrentCommandName.CompareNoCase("C-")
&& szCurrentCommandName.CompareNoCase("Meta for Alt")
&& szCurrentCommandName.CompareNoCase("Pass Through")) {
bEnableWindow = TRUE;
}
GetDlgItem(IDC_C_X)->EnableWindow(bEnableWindow);
m_bC = bEnableWindow;
m_bM = bEnableWindow;
m_bShift = bEnableWindow;
SetCurrentKeys();
ClearNewKey();
}
void CPropertiesAdvanced::OnSelchangeCurrentKeys()
{
// TODO: Add your control notification handler code here
char szKeyBind[128] = {'\0'};
m_cCurrentKeys.GetText(m_cCurrentKeys.GetCurSel(), szKeyBind);
CProfile::ReadKeyBind(&m_nRemoveCommandType, &m_nRemoveKey, szKeyBind);
m_cRemove.EnableWindow();
}
void CPropertiesAdvanced::OnSetfocusNewKey()
{
// TODO: Add your control notification handler code here
m_pNewKey = &m_cNewKey;
m_pAssign = &m_cAssign;
m_pCurrentlyAssigned = &m_cCurrentlyAssigned;
m_pCurrentKeys = &m_cCurrentKeys;
m_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)CPropertiesAdvanced::KeyboardProc, NULL, AfxGetApp()->m_nThreadID);
m_bC_x = IsDlgButtonChecked(IDC_C_X) && GetDlgItem(IDC_C_X)->IsWindowEnabled();
}
void CPropertiesAdvanced::OnAssign()
{
// TODO: Add your control notification handler code here
// Remove Current Setting
CProfile::SetCommandID(m_nApplicationID, m_nAssignCommandType, m_nAssignKey, 0);
SetCommandID(m_nAssignCommandType, m_nAssignKey, 0);
CDotXkeymacs::RemoveKey(m_nApplicationID, m_nAssignCommandType, m_nAssignKey);
// Assign New Setting
CString szItem;
szItem.Format("%s%s", CProfile::CommandType2String(m_nAssignCommandType), CProfile::Key2String(m_nAssignKey));
if (m_cCurrentKeys.FindString(-1, szItem) == LB_ERR) { // This key bind has not assignd to the same command yet.
CString szCategory;
m_cCategory.GetLBText(m_cCategory.GetCurSel(), szCategory);
if (szCategory.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {
CProfile::SetCommandID(m_nApplicationID, m_nAssignCommandType, m_nAssignKey, m_nCommandID);
SetCommandID(m_nAssignCommandType, m_nAssignKey, m_nCommandID);
} else {
CString szCurrentCommandName;
m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);
CDotXkeymacs::SetKey(CDotXkeymacs::GetIndex(szCurrentCommandName), m_nApplicationID, m_nAssignCommandType, m_nAssignKey);
}
m_cCurrentKeys.AddString(szItem);
}
ClearNewKey();
}
void CPropertiesAdvanced::OnRemove()
{
// TODO: Add your control notification handler code here
CString szCategory;
m_cCategory.GetLBText(m_cCategory.GetCurSel(), szCategory);
if (szCategory.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {
CProfile::SetCommandID(m_nApplicationID, m_nRemoveCommandType, m_nRemoveKey, 0);
SetCommandID(m_nRemoveCommandType, m_nRemoveKey, 0);
} else {
CString szCurrentCommandName;
m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);
CDotXkeymacs::RemoveKey(CDotXkeymacs::GetIndex(szCurrentCommandName), m_nApplicationID, m_nRemoveCommandType, m_nRemoveKey);
}
m_cCurrentKeys.DeleteString(m_cCurrentKeys.GetCurSel());
m_cRemove.EnableWindow(FALSE);
m_nRemoveCommandType = 0;
m_nRemoveKey = 0;
}
void CPropertiesAdvanced::OnResetAll()
{
// TODO: Add your control notification handler code here
CProfile::LoadRegistryData();
InitCommandIDs();
SetCurrentKeys();
}
void CPropertiesAdvanced::ClearNewKey()
{
m_cNewKey.SetWindowText("");
m_cAssign.EnableWindow(FALSE);
m_nAssignCommandType = 0;
m_nAssignKey = 0;
m_cCurrentlyAssigned.SetWindowText("");
}
LRESULT CALLBACK CPropertiesAdvanced::KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code < 0 || code == HC_NOREMOVE) {
return ::CallNextHookEx(m_hKeyboardHook, code, wParam, lParam);
}
if (lParam & BEING_RELEASED) { // Key Up
} else { // Key Down
if (CProfile::IsNT()) {
switch (wParam) {
case VK_CONTROL:
if (lParam & EXTENDED_KEY) {
wParam = VK_RCONTROL;
} else {
wParam = VK_LCONTROL;
}
break;
case VK_MENU:
if (lParam & EXTENDED_KEY) {
wParam = VK_RMENU;
} else {
wParam = VK_LMENU;
}
break;
case VK_SHIFT:
if (lParam & EXTENDED_KEY) {
wParam = VK_RSHIFT;
} else {
wParam = VK_LSHIFT;
}
break;
default:
break;
}
}
m_nAssignKey = wParam;
SetNewKey();
}
return TRUE;
}
void CPropertiesAdvanced::SetNewKey()
{
CString szNewKey;
int nCommandType = NONE;
if (m_bC_x) {
szNewKey += "Ctrl+X ";
nCommandType += CONTROLX;
}
if (IsCtrlDown()) {
szNewKey += "Ctrl+";
nCommandType += CONTROL;
}
if (IsMetaDown()) {
szNewKey += "Meta+";
nCommandType += META;
}
if (IsShiftDown()) {
szNewKey += "Shift+";
nCommandType += SHIFT;
}
m_nAssignCommandType = nCommandType;
szNewKey += CProfile::Key2String(m_nAssignKey);
if (m_pNewKey) {
m_pNewKey->SetWindowText(szNewKey);
}
if (m_pAssign) {
BOOL bEnable = TRUE;
if (m_pCurrentKeys
&& m_pCurrentKeys->FindString(-1, szNewKey) != LB_ERR) { // This key bind is already assigned.
bEnable = FALSE;
}
m_pAssign->EnableWindow(bEnable);
}
if (m_pCurrentlyAssigned) {
CString szCurrentlyAssigned("Currently assigned to:\n");
if (m_nCommandIDs[m_nAssignCommandType][m_nAssignKey] || CDotXkeymacs::GetIndex(m_nApplicationID, m_nAssignCommandType, m_nAssignKey) == -1) {
szCurrentlyAssigned += CXkeymacsData::GetCommandName(m_nCommandIDs[m_nAssignCommandType][m_nAssignKey]);
} else {
szCurrentlyAssigned += CDotXkeymacs::GetFunctionSymbol(CDotXkeymacs::GetIndex(m_nApplicationID, m_nAssignCommandType, m_nAssignKey));
}
m_pCurrentlyAssigned->SetWindowText(szCurrentlyAssigned);
}
}
void CPropertiesAdvanced::SetCommandID(int nCommandType, int nKey, int nCommandID)
{
m_nCommandIDs[nCommandType][nKey] = nCommandID;
// Set C-x if it is needed.
if ((nCommandType & CONTROLX)) {
// Get CommandID of C-x.
for (int nCommandIDofC_x = 0; nCommandIDofC_x < sizeof(Commands) / sizeof(Commands[0]); ++nCommandIDofC_x) {
if (!stricmp(CXkeymacsData::GetCommandName(nCommandIDofC_x), "C-x")) {
break;
}
}
if (nCommandID) {
m_nCommandIDs[CONTROL]['X'] = nCommandIDofC_x;
} else {
for (int i = 0; i < MAX_COMMAND_TYPE; ++i) { // i is command-type.
if (!(i & CONTROLX)) {
continue;
}
for (int j = 0; j < MAX_KEY; ++j) { // j is key.
if (m_nCommandIDs[i][j]) {
m_nCommandIDs[CONTROL]['X'] = nCommandIDofC_x; // needless
return;
}
}
}
m_nCommandIDs[CONTROL]['X'] = 0;
}
}
}
void CPropertiesAdvanced::InitCommandIDs()
{
for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {
for (int nKey = 0; nKey < MAX_KEY; ++nKey) {
SetCommandID(nCommandType, nKey, CProfile::GetCommandID(m_nApplicationID, nCommandType, nKey));
}
}
}
void CPropertiesAdvanced::OnCX()
{
// TODO: Add your control notification handler code here
if (m_nAssignKey) {
OnSetfocusNewKey();
SetNewKey();
}
}
void CPropertiesAdvanced::OnKillfocusNewKey()
{
// TODO: Add your control notification handler code here
if (m_hKeyboardHook) {
::UnhookWindowsHookEx(m_hKeyboardHook);
}
m_hKeyboardHook = NULL;
}
void CPropertiesAdvanced::OnEnableCua()
{
// TODO: Add your control notification handler code here
UpdateData();
CProfile::SetEnableCUA(m_nApplicationID, m_bEnableCUA);
}
BOOL CPropertiesAdvanced::IsCtrlDown()
{
return m_bC && IsFooDown(CString("C-"));
}
BOOL CPropertiesAdvanced::IsMetaDown()
{
return m_bM && IsFooDown(CString("Meta for Alt"));
}
BOOL CPropertiesAdvanced::IsShiftDown()
{
// temporary code
return m_bShift
&& (GetKeyState(VK_SHIFT ) < 0
|| GetKeyState(VK_LSHIFT) < 0
|| GetKeyState(VK_RSHIFT) < 0);
// return m_bShift && IsFooDown(CString("Foo"));
}
BOOL CPropertiesAdvanced::IsFooDown(CString szCommandName)
{
for (int nKey = 0; nKey < MAX_KEY; ++nKey) {
if (CXkeymacsData::GetCommandName(CProfile::GetCommandID(0, NONE, nKey)) == szCommandName) { // FIXME
if (GetKeyState(nKey) < 0) {
return TRUE;
}
}
}
return FALSE;
}