OSDN Git Service

Add FuncDefs class to handle functions defined in dot.xkeymacs.
[xkeymacs/xkeymacs.git] / xkeymacs / propertiesadvanced.cpp
1 // PropertiesAdvanced.cpp : implementation file\r
2 //\r
3 \r
4 #include "propertiesadvanced.h"\r
5 #include "resource.h"\r
6 #include "profile.h"\r
7 #include "FuncDefs.h"\r
8 \r
9 #ifdef _DEBUG\r
10 #define new DEBUG_NEW\r
11 #undef THIS_FILE\r
12 static char THIS_FILE[] = __FILE__;\r
13 #endif\r
14 \r
15 /////////////////////////////////////////////////////////////////////////////\r
16 // CPropertiesAdvanced property page\r
17 int     CPropertiesAdvanced::m_nAppID = 0;\r
18 int CPropertiesAdvanced::m_nCommandID = 0;\r
19 CEdit * CPropertiesAdvanced::m_pNewKey = NULL;\r
20 CButton * CPropertiesAdvanced::m_pAssign = NULL;\r
21 CStatic * CPropertiesAdvanced::m_pCurrentlyAssigned = NULL;\r
22 CListBox * CPropertiesAdvanced::m_pCurrentKeys = NULL;\r
23 HHOOK CPropertiesAdvanced::m_hKeyboardHook = NULL;\r
24 BOOL CPropertiesAdvanced::m_bC_x = FALSE;\r
25 BOOL CPropertiesAdvanced::m_bC = TRUE;\r
26 BOOL CPropertiesAdvanced::m_bM = TRUE;\r
27 BOOL CPropertiesAdvanced::m_bShift = TRUE;\r
28 int CPropertiesAdvanced::m_nAssignCommandType = 0;\r
29 int CPropertiesAdvanced::m_nAssignKey = 0;\r
30 int CPropertiesAdvanced::m_nCommandIDs[MAX_COMMAND_TYPE][MAX_KEY] = {'\0'};\r
31 \r
32 IMPLEMENT_DYNCREATE(CPropertiesAdvanced, CPropertyPage)\r
33 \r
34 CPropertiesAdvanced::CPropertiesAdvanced() : CPropertyPage(CPropertiesAdvanced::IDD)\r
35 {\r
36         //{{AFX_DATA_INIT(CPropertiesAdvanced)\r
37         m_bEnableCUA = FALSE;\r
38         //}}AFX_DATA_INIT\r
39 }\r
40 \r
41 CPropertiesAdvanced::~CPropertiesAdvanced()\r
42 {\r
43 }\r
44 \r
45 void CPropertiesAdvanced::DoDataExchange(CDataExchange* pDX)\r
46 {\r
47         CPropertyPage::DoDataExchange(pDX);\r
48         //{{AFX_DATA_MAP(CPropertiesAdvanced)\r
49         DDX_Control(pDX, IDC_CURRENTLY_ASSIGNED, m_cCurrentlyAssigned);\r
50         DDX_Control(pDX, IDC_RESET_ALL, m_cResetAll);\r
51         DDX_Control(pDX, IDC_REMOVE, m_cRemove);\r
52         DDX_Control(pDX, IDC_NEW_KEY, m_cNewKey);\r
53         DDX_Control(pDX, IDC_DESCRIPTION, m_cDescription);\r
54         DDX_Control(pDX, IDC_CURRENT_KEYS, m_cCurrentKeys);\r
55         DDX_Control(pDX, IDC_COMMANDS, m_cCommands);\r
56         DDX_Control(pDX, IDC_CATEGORY, m_cCategory);\r
57         DDX_Control(pDX, IDC_ASSIGN, m_cAssign);\r
58         DDX_Check(pDX, IDC_ENABLE_CUA, m_bEnableCUA);\r
59         //}}AFX_DATA_MAP\r
60 }\r
61 \r
62 \r
63 BEGIN_MESSAGE_MAP(CPropertiesAdvanced, CPropertyPage)\r
64         //{{AFX_MSG_MAP(CPropertiesAdvanced)\r
65         ON_WM_CREATE()\r
66         ON_CBN_SELCHANGE(IDC_CATEGORY, OnSelchangeCategory)\r
67         ON_LBN_SELCHANGE(IDC_COMMANDS, OnSelchangeCommands)\r
68         ON_LBN_SELCHANGE(IDC_CURRENT_KEYS, OnSelchangeCurrentKeys)\r
69         ON_EN_SETFOCUS(IDC_NEW_KEY, OnSetfocusNewKey)\r
70         ON_BN_CLICKED(IDC_ASSIGN, OnAssign)\r
71         ON_BN_CLICKED(IDC_REMOVE, OnRemove)\r
72         ON_BN_CLICKED(IDC_RESET_ALL, OnResetAll)\r
73         ON_BN_CLICKED(IDC_C_X, OnCX)\r
74         ON_EN_KILLFOCUS(IDC_NEW_KEY, OnKillfocusNewKey)\r
75         ON_BN_CLICKED(IDC_ENABLE_CUA, OnEnableCua)\r
76         //}}AFX_MSG_MAP\r
77 END_MESSAGE_MAP()\r
78 \r
79 /////////////////////////////////////////////////////////////////////////////\r
80 // CPropertiesAdvanced message handlers\r
81 \r
82 BOOL CPropertiesAdvanced::OnSetActive() \r
83 {\r
84         m_pProperties->EnableControl(ADVANCED_TAB);\r
85         SetDialogData();\r
86 \r
87         return CPropertyPage::OnSetActive();\r
88 }\r
89 \r
90 void CPropertiesAdvanced::SetDialogData()\r
91 {\r
92         m_nAppID = m_pProperties->GetApplicationID();\r
93         if (m_nAppID == MAX_APP)\r
94                 return;\r
95         InitCommandIDs();\r
96         m_bEnableCUA = CProfile::GetEnableCUA(m_nAppID);\r
97         SetCurrentKeys();\r
98         UpdateData(FALSE);\r
99 }\r
100 \r
101 void CPropertiesAdvanced::GetDialogData()\r
102 {\r
103         UpdateData();\r
104 }\r
105 \r
106 int CPropertiesAdvanced::OnCreate(LPCREATESTRUCT lpCreateStruct) \r
107 {\r
108         if (CPropertyPage::OnCreate(lpCreateStruct) == -1)\r
109                 return -1;\r
110 \r
111         m_pProperties = (CProperties *)GetParent()->GetParent();\r
112 \r
113         return 0;\r
114 }\r
115 \r
116 BOOL CPropertiesAdvanced::OnKillActive() \r
117 {\r
118         GetDialogData();\r
119 \r
120         return CPropertyPage::OnKillActive();\r
121 }\r
122 \r
123 void CPropertiesAdvanced::EnableControl()\r
124 {\r
125         BOOL bEnable = m_pProperties->IsEnableControl();\r
126 \r
127         m_cCategory.EnableWindow(bEnable);\r
128         m_cCommands.EnableWindow(bEnable);\r
129         m_cCurrentKeys.EnableWindow(bEnable);\r
130         m_cNewKey.EnableWindow(bEnable);\r
131 \r
132         m_cAssign.EnableWindow(FALSE);\r
133         m_cRemove.EnableWindow(FALSE);\r
134         m_cResetAll.EnableWindow(bEnable);\r
135 }\r
136 \r
137 BOOL CPropertiesAdvanced::OnInitDialog() \r
138 {\r
139         CPropertyPage::OnInitDialog();\r
140 \r
141         m_nAppID = m_pProperties->GetApplicationID();\r
142         InitCategoryList();\r
143         SetCommands();\r
144 \r
145         SetDialogData();\r
146 \r
147         m_cAssign.EnableWindow(FALSE);\r
148         m_cRemove.EnableWindow(FALSE);\r
149 \r
150         m_cCurrentlyAssigned.SetWindowText(_T(""));\r
151 \r
152         return TRUE;  // return TRUE unless you set the focus to a control\r
153                       // EXCEPTION: OCX Property Pages should return FALSE\r
154 }\r
155 \r
156 void CPropertiesAdvanced::InitCategoryList()\r
157 {\r
158         for (const int *c = CmdTable::Categories(); *c; ++c)\r
159                 m_cCategory.InsertString(-1, CString(MAKEINTRESOURCE(*c)));\r
160         if (FuncDefs::GetNumOfDefs())\r
161                 m_cCategory.InsertString(-1, CString(MAKEINTRESOURCE(IDS_ORIGINAL)));\r
162         m_cCategory.SetCurSel(0);\r
163 }\r
164 \r
165 void CPropertiesAdvanced::SetCommands()\r
166 {\r
167         m_cCommands.ResetContent();\r
168 \r
169         CString category;\r
170         m_cCategory.GetLBText(m_cCategory.GetCurSel(), category);\r
171         if (category.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {\r
172                 for (int cmd = 1; cmd < MAX_COMMAND; ++cmd)\r
173                         if (category == CString(MAKEINTRESOURCE(CmdTable::CategoryID(cmd))))\r
174                                 m_cCommands.AddString(CmdTable::Name(cmd));\r
175         } else {\r
176                 for (int nFuncID = 0; nFuncID < FuncDefs::GetNumOfDefs(); ++nFuncID)\r
177                         m_cCommands.AddString(FuncDefs::GetName(nFuncID));\r
178         }\r
179 \r
180         m_cCommands.SetCurSel(0);\r
181         SetCurrentKeys();\r
182 }\r
183 \r
184 void CPropertiesAdvanced::SetCurrentKeys()\r
185 {\r
186         m_cCurrentKeys.ResetContent();\r
187         m_cRemove.EnableWindow(FALSE);\r
188 \r
189         CString category;\r
190         m_cCategory.GetLBText(m_cCategory.GetCurSel(), category);\r
191         CString name;\r
192         m_cCommands.GetText(m_cCommands.GetCurSel(), name);\r
193 \r
194         if (category.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {\r
195                 for (int type = 0; type < MAX_COMMAND_TYPE; ++type) {\r
196                         for (int key = 0; key < MAX_KEY; ++key)\r
197                                 if (!_tcscmp(CmdTable::Name(CProfile::GetCmdID(m_nAppID, type, key)), name))\r
198                                         m_cCurrentKeys.AddString(CProfile::KeyToString(type, key));\r
199                 }\r
200                 for (int cmd = 0; cmd < MAX_COMMAND; ++cmd) {\r
201                         if (!_tcscmp(CmdTable::Name(cmd), name)) {\r
202                                 m_nCommandID = cmd;\r
203                                 break;\r
204                         }\r
205                 }\r
206                 m_cDescription.SetWindowText(CString(MAKEINTRESOURCE(CmdTable::DescriptionID(m_nCommandID))));\r
207         } else {\r
208                 int id = FuncDefs::GetID(name);\r
209                 if (id < 0)\r
210                         return;\r
211                 for (int type = 0; type < MAX_COMMAND_TYPE; ++type) {\r
212                         for (int key = 0; key < MAX_KEY; ++key)\r
213                                 if (CProfile::GetFuncID(m_nAppID, type, key) == id)\r
214                                         m_cCurrentKeys.AddString(CProfile::KeyToString(type, key));\r
215                 }\r
216                 m_cDescription.SetWindowText(FuncDefs::GetStrDef(id));\r
217         }\r
218 }\r
219 \r
220 void CPropertiesAdvanced::OnSelchangeCategory() \r
221 {\r
222         SetCommands();\r
223         ClearNewKey();\r
224 }\r
225 \r
226 void CPropertiesAdvanced::OnSelchangeCommands() \r
227 {\r
228         BOOL bEnableWindow = FALSE;\r
229         CString szCurrentCommandName;\r
230         m_cCommands.GetText(m_cCommands.GetCurSel(), szCurrentCommandName);\r
231         if (szCurrentCommandName.CompareNoCase(_T("C-"))\r
232          && szCurrentCommandName.CompareNoCase(_T("Meta for Alt"))\r
233          && szCurrentCommandName.CompareNoCase(_T("Pass Through"))) {\r
234                 bEnableWindow = TRUE;\r
235         }\r
236         GetDlgItem(IDC_C_X)->EnableWindow(bEnableWindow);\r
237         m_bC = bEnableWindow;\r
238         m_bM = bEnableWindow;\r
239         m_bShift = bEnableWindow;\r
240 \r
241         SetCurrentKeys();\r
242         ClearNewKey();\r
243 }\r
244 \r
245 void CPropertiesAdvanced::OnSelchangeCurrentKeys() \r
246 {\r
247         TCHAR szKeyBind[128] = {'\0'};\r
248         m_cCurrentKeys.GetText(m_cCurrentKeys.GetCurSel(), szKeyBind);\r
249         CProfile::StringToKey(szKeyBind, m_nRemoveCommandType, m_nRemoveKey);\r
250         m_cRemove.EnableWindow();\r
251 }\r
252 \r
253 void CPropertiesAdvanced::OnSetfocusNewKey() \r
254 {\r
255         m_pNewKey = &m_cNewKey;\r
256         m_pAssign = &m_cAssign;\r
257         m_pCurrentlyAssigned = &m_cCurrentlyAssigned;\r
258         m_pCurrentKeys = &m_cCurrentKeys;\r
259         m_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)CPropertiesAdvanced::KeyboardProc, NULL, AfxGetApp()->m_nThreadID);\r
260 \r
261         m_bC_x = IsDlgButtonChecked(IDC_C_X) && GetDlgItem(IDC_C_X)->IsWindowEnabled();\r
262 }\r
263 \r
264 void CPropertiesAdvanced::OnAssign() \r
265 {\r
266         // Remove Current Setting\r
267         CProfile::SetCmdID(m_nAppID, m_nAssignCommandType, m_nAssignKey, 0);\r
268         SetCmdID(m_nAssignCommandType, m_nAssignKey, 0);\r
269         CProfile::SetFuncID(m_nAppID, m_nAssignCommandType, m_nAssignKey, -1);\r
270 \r
271         // Assign New Setting\r
272         CString item = CProfile::KeyToString(m_nAssignCommandType, m_nAssignKey);\r
273         if (m_cCurrentKeys.FindString(-1, item) == LB_ERR) {    // This key bind has not assignd to the same command yet.\r
274                 CString category;\r
275                 m_cCategory.GetLBText(m_cCategory.GetCurSel(), category);\r
276                 if (category.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {\r
277                         CProfile::SetCmdID(m_nAppID, m_nAssignCommandType, m_nAssignKey, m_nCommandID);\r
278                         SetCmdID(m_nAssignCommandType, m_nAssignKey, m_nCommandID);\r
279                 } else {\r
280                         CString name;\r
281                         m_cCommands.GetText(m_cCommands.GetCurSel(), name);\r
282                         int id = FuncDefs::GetID(name);\r
283                         if (id >= 0)\r
284                                 CProfile::SetFuncID(m_nAppID, m_nAssignCommandType, m_nAssignKey, id);\r
285                 }\r
286                 m_cCurrentKeys.AddString(item);\r
287         }\r
288 \r
289         ClearNewKey();\r
290 }\r
291 \r
292 void CPropertiesAdvanced::OnRemove() \r
293 {\r
294         CString category;\r
295         m_cCategory.GetLBText(m_cCategory.GetCurSel(), category);\r
296 \r
297         if (category.Compare(CString(MAKEINTRESOURCE(IDS_ORIGINAL)))) {\r
298                 CProfile::SetCmdID(m_nAppID, m_nRemoveCommandType, m_nRemoveKey, 0);\r
299                 SetCmdID(m_nRemoveCommandType, m_nRemoveKey, 0);\r
300         } else\r
301                 CProfile::SetFuncID(m_nAppID, m_nRemoveCommandType, m_nRemoveKey, -1);\r
302 \r
303         m_cCurrentKeys.DeleteString(m_cCurrentKeys.GetCurSel());\r
304         m_cRemove.EnableWindow(FALSE);\r
305         m_nRemoveCommandType = 0;\r
306         m_nRemoveKey = 0;\r
307 }\r
308 \r
309 void CPropertiesAdvanced::OnResetAll() \r
310 {\r
311         CProfile::LoadData();\r
312         InitCommandIDs();\r
313         SetCurrentKeys();\r
314 }\r
315 \r
316 void CPropertiesAdvanced::ClearNewKey()\r
317 {\r
318         m_cNewKey.SetWindowText(_T(""));\r
319         m_cAssign.EnableWindow(FALSE);\r
320         m_nAssignCommandType = 0;\r
321         m_nAssignKey = 0;\r
322         m_cCurrentlyAssigned.SetWindowText(_T(""));\r
323 }\r
324 \r
325 LRESULT CALLBACK CPropertiesAdvanced::KeyboardProc(int code, WPARAM wParam, LPARAM lParam)\r
326 {\r
327         if (code < 0 || code == HC_NOREMOVE)\r
328                 return ::CallNextHookEx(m_hKeyboardHook, code, wParam, lParam);\r
329         if (HIWORD(lParam) & KF_UP)\r
330                 return TRUE;\r
331         const bool bExt = (HIWORD(lParam) & KF_EXTENDED) != 0;\r
332         switch (wParam) {\r
333         case VK_SHIFT:\r
334                 wParam = (bExt) ? VK_RSHIFT : VK_LSHIFT;\r
335                 break;\r
336         case VK_CONTROL:\r
337                 wParam = (bExt) ? VK_RCONTROL : VK_LCONTROL;\r
338                 break;\r
339         case VK_MENU:\r
340                 wParam = (bExt) ? VK_RMENU : VK_LMENU;\r
341                 break;\r
342         }\r
343         m_nAssignKey = wParam;\r
344         SetNewKey();\r
345         return TRUE;\r
346 }\r
347 \r
348 void CPropertiesAdvanced::SetNewKey()\r
349 {\r
350         UINT type = NONE;\r
351         if (m_bC_x)\r
352                 type |= CONTROLX;\r
353         if (IsCtrlDown())\r
354                 type |= CONTROL;\r
355         if (IsMetaDown())\r
356                 type |= META;\r
357         if (IsShiftDown())\r
358                 type |= SHIFT;\r
359         m_nAssignCommandType = type;\r
360 \r
361         const CString newKey = CProfile::KeyToString(type, m_nAssignKey);\r
362         if (m_pNewKey)\r
363                 m_pNewKey->SetWindowText(newKey);\r
364         if (m_pAssign)\r
365                 m_pAssign->EnableWindow(!m_pCurrentKeys || m_pCurrentKeys->FindString(-1, newKey) == LB_ERR); // this key isn't bound;\r
366         if (m_pCurrentlyAssigned) {\r
367                 CString assigned(_T("Currently assigned to:\n"));\r
368                 if (m_nCommandIDs[m_nAssignCommandType][m_nAssignKey] || CProfile::GetFuncID(m_nAppID, m_nAssignCommandType, m_nAssignKey) == -1)\r
369                         assigned += CmdTable::Name(m_nCommandIDs[m_nAssignCommandType][m_nAssignKey]);\r
370                 else\r
371                         assigned += FuncDefs::GetName(CProfile::GetFuncID(m_nAppID, m_nAssignCommandType, m_nAssignKey));\r
372                 m_pCurrentlyAssigned->SetWindowText(assigned);\r
373         }\r
374 }\r
375 \r
376 void CPropertiesAdvanced::SetCmdID(int type, int key, int cmd)\r
377 {\r
378         m_nCommandIDs[type][key] = cmd;\r
379         if (!(type & CONTROLX))\r
380                 return;\r
381         // Make C-x enable or disable.\r
382         if (cmd)\r
383                 m_nCommandIDs[CONTROL]['X'] = 1;\r
384         else {\r
385                 m_nCommandIDs[CONTROL]['X'] = 0;\r
386                 for (int i = 0; i < MAX_COMMAND_TYPE; ++i)\r
387                         for (int j = 0; j < MAX_KEY; ++j)\r
388                                 if ((i & CONTROLX) && m_nCommandIDs[i][j])\r
389                                         m_nCommandIDs[CONTROL]['X'] = 1;\r
390         }\r
391 }\r
392 \r
393 void CPropertiesAdvanced::InitCommandIDs()\r
394 {\r
395         for (int type = 0; type < MAX_COMMAND_TYPE; ++type)\r
396                 for (int key = 0; key < MAX_KEY; ++key)\r
397                         SetCmdID(type, key, CProfile::GetCmdID(m_nAppID, type, key));\r
398 }\r
399 \r
400 void CPropertiesAdvanced::OnCX() \r
401 {\r
402         if (m_nAssignKey) {\r
403                 OnSetfocusNewKey();\r
404                 SetNewKey();\r
405         }\r
406 }\r
407 \r
408 void CPropertiesAdvanced::OnKillfocusNewKey() \r
409 {\r
410         if (m_hKeyboardHook)\r
411                 ::UnhookWindowsHookEx(m_hKeyboardHook);\r
412         m_hKeyboardHook = NULL;\r
413 }\r
414 \r
415 void CPropertiesAdvanced::OnEnableCua() \r
416 {\r
417         UpdateData();\r
418         CProfile::SetEnableCUA(m_nAppID, m_bEnableCUA != FALSE);\r
419 }\r
420 \r
421 BOOL CPropertiesAdvanced::IsCtrlDown()\r
422 {\r
423         return m_bC && IsFooDown(CString(_T("C-")));\r
424 }\r
425 \r
426 BOOL CPropertiesAdvanced::IsMetaDown()\r
427 {\r
428         return m_bM && IsFooDown(CString(_T("Meta for Alt")));\r
429 }\r
430 \r
431 BOOL CPropertiesAdvanced::IsShiftDown()\r
432 {\r
433         // temporary code\r
434         return m_bShift\r
435                 && (GetKeyState(VK_SHIFT ) < 0\r
436                  || GetKeyState(VK_LSHIFT) < 0\r
437                  || GetKeyState(VK_RSHIFT) < 0);\r
438 \r
439 //      return m_bShift && IsFooDown(CString("Foo"));\r
440 }\r
441 \r
442 BOOL CPropertiesAdvanced::IsFooDown(CString szCommandName)\r
443 {\r
444         for (int key = 0; key < MAX_KEY; ++key) {\r
445                 if (CmdTable::Name(CProfile::GetCmdID(0, NONE, key)) == szCommandName) {        // FIXME\r
446                         if (GetKeyState(key) < 0) {\r
447                                 return TRUE;\r
448                         }\r
449                 }\r
450         }\r
451         return FALSE;\r
452 }\r