// Customize.cpp : implementation file
//
#include "stdafx.h"
#include "xkeymacs.h"
#include "Customize.h"
#include "Profile.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCustomize dialog
HHOOK CCustomize::m_hKeyboardHook = NULL;
CEdit *CCustomize::m_pNewKey = NULL;
CButton *CCustomize::m_pAssign = NULL;
CStatic *CCustomize::m_pCurrentlyAssigned = NULL;
int CCustomize::m_nApplicationID = 0;
int CCustomize::m_nAssignCommandType = 0;
int CCustomize::m_nAssignKey = 0;
int CCustomize::m_nCommandID = 0;
int CCustomize::m_nCommandIDs[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};
CCustomize::CCustomize(CWnd* pParent /*=NULL*/)
: CDialog(CCustomize::IDD, pParent)
{
//{{AFX_DATA_INIT(CCustomize)
m_nSettingStyle = -1;
//}}AFX_DATA_INIT
}
void CCustomize::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCustomize)
DDX_Control(pDX, IDC_DESCRIPTION, m_cDescription);
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_ASSIGN, m_cAssign);
DDX_Control(pDX, IDC_NEW_KEY, m_cNewKey);
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_APPLICATION, m_cApplication);
DDX_Radio(pDX, IDC_SETTING_DEFAULT, m_nSettingStyle);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCustomize, CDialog)
//{{AFX_MSG_MAP(CCustomize)
ON_BN_CLICKED(IDC_SETTING_DEFAULT, OnSettingDefault)
ON_BN_CLICKED(IDC_SETTING_DISABLE, OnSettingDisable)
ON_BN_CLICKED(IDC_SETTING_SPECIFIC, OnSettingSpecific)
ON_BN_CLICKED(IDC_APPLY, OnApply)
ON_CBN_SELCHANGE(IDC_APPLICATION, OnSelchangeApplication)
ON_CBN_DROPDOWN(IDC_APPLICATION, OnDropdownApplication)
ON_CBN_SELCHANGE(IDC_CATEGORY, OnSelchangeCategory)
ON_LBN_SELCHANGE(IDC_COMMANDS, OnSelchangeCommands)
ON_EN_SETFOCUS(IDC_NEW_KEY, OnSetfocusNewKey)
ON_EN_KILLFOCUS(IDC_NEW_KEY, OnKillfocusNewKey)
ON_BN_CLICKED(IDC_ASSIGN, OnAssign)
ON_BN_CLICKED(IDC_REMOVE, OnRemove)
ON_BN_CLICKED(IDC_RESET_ALL, OnResetAll)
ON_LBN_SELCHANGE(IDC_CURRENT_KEYS, OnSelchangeCurrentKeys)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCustomize message handlers
void CCustomize::OnSettingDefault()
{
// TODO: Add your control notification handler code here
UpdateData();
EnableControl();
}
void CCustomize::OnSettingDisable()
{
// TODO: Add your control notification handler code here
UpdateData();
EnableControl();
}
void CCustomize::OnSettingSpecific()
{
// TODO: Add your control notification handler code here
UpdateData();
EnableControl();
if (CProfile::GetApplicationIndex(m_szCurrentApplication) == MAX_APP) {
CString szDefault;
szDefault.LoadString(IDS_DEFAULT);
CProfile::CopyData(m_szCurrentApplication, szDefault);
SetDialogData(m_szCurrentApplication);
}
}
void CCustomize::EnableControl()
{
BOOL bEnableWindow = (m_nSettingStyle == SETTING_SPECIFIC);
m_cCategory.EnableWindow(bEnableWindow);
m_cCommands.EnableWindow(bEnableWindow);
m_cCurrentKeys.EnableWindow(bEnableWindow);
m_cNewKey.EnableWindow(bEnableWindow);
m_cAssign.EnableWindow(FALSE);
m_cRemove.EnableWindow(FALSE);
m_cResetAll.EnableWindow(bEnableWindow);
}
void CCustomize::UpdateDialogData(CString szApplicationName, BOOL bSaveAndValidate)
{
m_nApplicationID = CProfile::GetApplicationIndex(szApplicationName, bSaveAndValidate, &m_nSettingStyle);
if (m_nApplicationID == MAX_APP) {
if (!bSaveAndValidate) {
// SetAllDialogData(1);
}
return;
}
InitCommandIDs();
if (!bSaveAndValidate) { // SetDialogData
EnableControl();
}
if (CProfile::IsDefault(szApplicationName)) {
EnableUseDefaultButton(FALSE);
} else {
EnableUseDefaultButton(TRUE);
}
// application title
CProfile::UpdateApplicationTitle(&m_cApplication, m_szCurrentApplication, m_nApplicationID, bSaveAndValidate);
if (!bSaveAndValidate) { // SetDialogData
SetCurrentKeys();
}
}
void CCustomize::SetDialogData(CString szApplicationName)
{
UpdateDialogData(szApplicationName, FALSE);
UpdateData(FALSE);
}
void CCustomize::GetDialogData()
{
UpdateData();
if (m_nSettingStyle == SETTING_DEFAULT) {
CProfile::ClearData(m_szCurrentApplication);
} else {
UpdateDialogData(m_szCurrentApplication, TRUE);
}
}
void CCustomize::OnApply()
{
// TODO: Add your control notification handler code here
GetDialogData();
CProfile::SaveRegistryData();
}
void CCustomize::OnOK()
{
// TODO: Add extra validation here
OnApply();
CDialog::OnOK();
}
void CCustomize::OnSelchangeApplication()
{
// TODO: Add your control notification handler code here
GetDialogData();
CProfile::GetApplicationTitle(&m_cApplication, m_szCurrentApplication, m_cApplication.GetCurSel());
int nStart;
if ((nStart = m_szCurrentApplication.ReverseFind('(')) != -1) {
nStart++;
m_szCurrentApplication =
m_szCurrentApplication.Mid(nStart, m_szCurrentApplication.GetLength() - nStart - 1);
}
SetDialogData(m_szCurrentApplication);
}
void CCustomize::OnDropdownApplication()
{
// TODO: Add your control notification handler code here
InitApplicationList();
int nID = GetCurrentApplicationID();
if (nID != CB_ERR) {
m_cApplication.SetCurSel(nID);
} else {
GetDialogData();
m_szCurrentApplication.LoadString(IDS_DEFAULT_TITLE);
m_cApplication.SelectString(-1, m_szCurrentApplication);
SetDialogData(m_szCurrentApplication);
}
}
void CCustomize::InitApplicationList()
{
CProfile::InitApplicationList(&m_cApplication);
}
void CCustomize::InitCategoryList()
{
int nCategoryIDs[128] = {'\0'};
// get all category type
m_cCategory.ResetContent();
for (int nCommandID = 1; ; 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];
}
}
CString szCategory;
szCategory.LoadString(nID);
m_cCategory.InsertString(-1, szCategory);
nMinimumID = nID;
}
m_cCategory.SetCurSel(0);
}
BOOL CCustomize::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
SetForegroundWindow();
InitApplicationList();
InitCategoryList();
SetCommands();
CProfile::LoadRegistryData();
m_szCurrentApplication.LoadString(IDS_DEFAULT);
SetDialogData(m_szCurrentApplication);
EnableUseDefaultButton(FALSE);
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
}
int CCustomize::GetCurrentApplicationID()
{
return CProfile::GetCurrentApplicationID(&m_cApplication, m_szCurrentApplication);
}
void CCustomize::EnableUseDefaultButton(BOOL bEnable)
{
if (GetDlgItem(IDC_SETTING_DEFAULT)) {
GetDlgItem(IDC_SETTING_DEFAULT)->EnableWindow(bEnable);
}
}
void CCustomize::OnSelchangeCategory()
{
// TODO: Add your control notification handler code here
SetCommands();
ClearNewKey();
}
void CCustomize::SetCommands()
{
m_cCommands.ResetContent();
CString szCategory;
m_cCategory.GetLBText(m_cCategory.GetCurSel(), szCategory);
for (int nCommandID = 1; ; nCommandID++) {
CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);
if (szCommandName.IsEmpty()) {
break;
}
CString sz;
sz.LoadString(CXkeymacsData::GetCategoryID(nCommandID));
if (sz == szCategory) {
m_cCommands.AddString(CXkeymacsData::GetCommandName(nCommandID));
}
}
m_cCommands.SetCurSel(0);
SetCurrentKeys();
}
void CCustomize::OnSelchangeCommands()
{
// TODO: Add your control notification handler code here
SetCurrentKeys();
ClearNewKey();
}
void CCustomize::SetCurrentKeys()
{
m_cCurrentKeys.ResetContent();
m_cRemove.EnableWindow(FALSE);
CString szCurrentCommandName;
m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);
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++) {
CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);
if (szCommandName.IsEmpty()) {
break;
}
if (szCommandName == szCurrentCommandName) {
m_nCommandID = nCommandID;
break;
}
}
CString szDescription;
szDescription.LoadString(CXkeymacsData::GetDescriptionID(m_nCommandID));
m_cDescription.SetWindowText(szDescription);
}
void CCustomize::OnSetfocusNewKey()
{
// TODO: Add your control notification handler code here
m_pNewKey = &m_cNewKey;
m_pAssign = &m_cAssign;
m_pCurrentlyAssigned = &m_cCurrentlyAssigned;
m_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)CCustomize::KeyboardProc, NULL, AfxGetApp()->m_nThreadID);
}
void CCustomize::OnKillfocusNewKey()
{
// TODO: Add your control notification handler code here
if (m_hKeyboardHook) {
::UnhookWindowsHookEx(m_hKeyboardHook);
}
m_hKeyboardHook = NULL;
}
LRESULT CALLBACK CCustomize::KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code < 0 || code == HC_NOREMOVE) {
return ::CallNextHookEx(m_hKeyboardHook, code, wParam, lParam);
}
if (2 < (lParam & 0xff)) {
return ::CallNextHookEx(m_hKeyboardHook, code, wParam, lParam);
}
CString szNewKey;
static BOOL bC_x = FALSE;
int nCommandType = NONE;
if (Commands[m_nCommandID].fCommand != CCommands::C_) {
if (bC_x) {
szNewKey += "Ctrl+X ";
nCommandType += CONTROLX;
}
if (GetKeyState(VK_CONTROL) < 0) {
szNewKey += "Ctrl+";
nCommandType += CONTROL;
}
if (GetKeyState(VK_MENU) < 0) {
szNewKey += "Meta+";
nCommandType += META;
}
if (GetKeyState(VK_SHIFT) < 0) {
szNewKey += "Shift+";
nCommandType += SHIFT;
}
}
static BOOL bNewKey = FALSE;
if (Commands[m_nCommandID].fCommand != CCommands::C_ &&
(wParam == VK_CONTROL ||
wParam == VK_MENU ||
wParam == VK_SHIFT)) {
if (lParam & 0x80000000) { // Key Up
if (!bNewKey) {
m_pNewKey->SetWindowText(szNewKey);
}
} else { // Key Down
m_pNewKey->SetWindowText(szNewKey);
bNewKey = FALSE;
m_pAssign->EnableWindow(bNewKey);
m_pCurrentlyAssigned->SetWindowText("");
m_nAssignCommandType = 0;
m_nAssignKey = 0;
}
} else {
if (lParam & 0x80000000) { // Key Up
} else { // Key Down
szNewKey += CProfile::Key2String(wParam);
m_pNewKey->SetWindowText(szNewKey);
m_nAssignCommandType = nCommandType;
m_nAssignKey = wParam;
bNewKey = TRUE;
m_pAssign->EnableWindow(bNewKey);
CString szCurrentlyAssigned;
szCurrentlyAssigned.Format("Currently assigned to:\n%s",
CXkeymacsData::GetCommandName(m_nCommandIDs[nCommandType][wParam]));
m_pCurrentlyAssigned->SetWindowText(szCurrentlyAssigned);
// if (CXkeymacsData::GetCommandName(CProfile::GetCommandID(m_nApplicationID, nCommandType, wParam)) == "C-x") {
if ((nCommandType & CONTROL) &&
!(nCommandType & META) &&
wParam == 'X') {
bC_x = TRUE;
m_pNewKey->SetWindowText("Ctrl+X");
} else {
bC_x = FALSE;
}
}
}
return TRUE;
}
void CCustomize::OnAssign()
{
// TODO: Add your control notification handler code here
CProfile::SetCommandID(m_nApplicationID, m_nAssignCommandType, m_nAssignKey, m_nCommandID);
m_nCommandIDs[m_nAssignCommandType][m_nAssignKey] = m_nCommandID;
CString sz;
sz.Format("%s%s", CProfile::CommandType2String(m_nAssignCommandType), CProfile::Key2String(m_nAssignKey));
m_cCurrentKeys.AddString(sz);
ClearNewKey();
}
void CCustomize::OnRemove()
{
// TODO: Add your control notification handler code here
CProfile::SetCommandID(m_nApplicationID, m_nRemoveCommandType, m_nRemoveKey, 0);
m_nCommandIDs[m_nRemoveCommandType][m_nRemoveKey] = 0;
m_cCurrentKeys.DeleteString(m_cCurrentKeys.GetCurSel());
m_cRemove.EnableWindow(FALSE);
m_nRemoveCommandType = 0;
m_nRemoveKey = 0;
}
void CCustomize::OnResetAll()
{
// TODO: Add your control notification handler code here
CProfile::LoadRegistryData();
InitCommandIDs();
SetCurrentKeys();
}
void CCustomize::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 CCustomize::InitCommandIDs()
{
// initialize local static CommandID for static function i.e. KeyboardProc
for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; nCommandType++) {
for (int nKey = 0; nKey < MAX_KEY; nKey++) {
m_nCommandIDs[nCommandType][nKey] = CProfile::GetCommandID(m_nApplicationID, nCommandType, nKey);
}
}
}
void CCustomize::ClearNewKey()
{
m_cNewKey.SetWindowText("");
m_cAssign.EnableWindow(FALSE);
m_nAssignCommandType = 0;
m_nAssignKey = 0;
m_cCurrentlyAssigned.SetWindowText("");
}