OSDN Git Service

Import from xkeymacssrc347.
[xkeymacs/xkeymacs.git] / xkeymacs / profile.cpp
1 // Profile.cpp: implementation of the CProfile class\r
2 //\r
3 //////////////////////////////////////////////////////////////////////\r
4 \r
5 #include "stdafx.h"\r
6 #include "xkeymacs.h"\r
7 #include "Profile.h"\r
8 #include "MainFrm.h"\r
9 #include "DotXkeymacs.h"\r
10 #include <Imm.h>\r
11 #include <Shlwapi.h>    // Windows NT/2000: Requires Windows 2000 (or Windows NT 4.0 with Internet Explorer 4.0 or later). \r
12                                                 // Windows 95/98/Me: Requires Windows 98 (or Windows 95 with Internet Explorer 4.0 or later). \r
13 \r
14 #ifdef _DEBUG\r
15 #undef THIS_FILE\r
16 static char THIS_FILE[]=__FILE__;\r
17 #define new DEBUG_NEW\r
18 #endif\r
19 \r
20 #pragma data_seg(".xkmcs")\r
21         CXkeymacsData CProfile::m_XkeymacsData[MAX_APP];\r
22         TASK_LIST CProfile::m_TaskList[MAX_TASKS];\r
23         DWORD CProfile::m_dwTasks;\r
24         ScanCode_t CProfile::m_CurrentScanCodeMap[MAX_HKEY_TYPE][4][256];\r
25         ScanCode_t CProfile::m_ScanCodeMap[MAX_HKEY_TYPE][4][256];\r
26 #pragma data_seg()\r
27 \r
28 enum { INITIAL_SIZE     = 51200 };\r
29 enum { EXTEND_SIZE      = 25600 };\r
30 \r
31 void CProfile::Item2AppName(CString *const sz)\r
32 {\r
33         if (IsTheString(*sz, IDS_DEFAULT_TITLE)) {\r
34                 sz->LoadString(IDS_DEFAULT);\r
35         }\r
36 \r
37         if (IsTheString(*sz, IDS_DIALOG_TITLE)) {\r
38                 sz->LoadString(IDS_DIALOG);\r
39         }\r
40 \r
41         int nStart, nEnd, nCount;\r
42 \r
43         nStart  = sz->ReverseFind(_T('(')) + 1;\r
44         nEnd    = sz->Find(_T(')'), nStart) - 1;\r
45         nCount  = (nEnd + 1) - nStart;\r
46         *sz             = sz->Mid(nStart, nCount);\r
47 }\r
48 \r
49 int CProfile::IsNotSameString(CComboBox *const pApplication, const CString szListItem)\r
50 {\r
51         CString szItem, szList;\r
52         szList = szListItem;\r
53         Item2AppName(&szList);\r
54 \r
55         for (int i = 0; i < pApplication->GetCount(); ++i) {\r
56                 pApplication->GetLBText(i, szItem);\r
57                 Item2AppName(&szItem);\r
58                 if (!_tcsicmp(szItem, szList)) {\r
59                         return 0;\r
60                 }\r
61         }\r
62 \r
63         return 1;\r
64 }\r
65 \r
66 int CProfile::CountSeparator(const CString szMainString, const CString szSeparator)\r
67 {\r
68         int index       = 0;\r
69         int counter     = 0;\r
70 \r
71         while ((index = szMainString.Find(szSeparator, index)) != -1) {\r
72                 ++index;\r
73                 ++counter;\r
74         }\r
75 \r
76         return counter;\r
77 }\r
78 \r
79 void CProfile::GetNthString(CString *const szAppName, const CString szWindowName, const CString szSeparator, int n)\r
80 {\r
81         int index = -1;\r
82 \r
83         while (--n) {\r
84                 index = szWindowName.Find(szSeparator, index + 1);\r
85         }\r
86 \r
87         int nStart;\r
88         if (index != -1) {\r
89                 nStart = index + szSeparator.GetLength();\r
90         } else {\r
91                 nStart = 0;\r
92         }\r
93 \r
94         int nEnd = szWindowName.Find(szSeparator, nStart);\r
95         if (nEnd == -1) {\r
96                 nEnd = szWindowName.GetLength();\r
97         }\r
98 \r
99         *szAppName = szWindowName.Mid(nStart, nEnd - nStart);\r
100 }\r
101 \r
102 void CProfile::GetAppName(CString *const szAppName, LPCTSTR pWindowName)\r
103 {\r
104         CString szWindowName(pWindowName);\r
105         CString szSeparator(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE));\r
106         int nWord = CountSeparator(szWindowName, szSeparator) + 1;\r
107 \r
108         while (nWord) {\r
109                 GetNthString(szAppName, szWindowName, szSeparator, nWord);\r
110                 if (szAppName->GetAt(0) == _T('[')\r
111                  || szAppName->Find(_T('.'), 0) != -1           // for Microsoft Project\r
112                  || szAppName->Find(_T(']'), 0) != -1) {        // for the file name like [foo - bar]\r
113                         --nWord;\r
114                 } else {\r
115                         return;\r
116                 }\r
117         }\r
118 \r
119         *szAppName = szWindowName;\r
120 }\r
121 \r
122 BOOL CALLBACK CProfile::EnumWindowsProc(const HWND hWnd, const LPARAM lParam)\r
123 {\r
124         CComboBox               *pApplication   = (CComboBox*)lParam;\r
125         PTASK_LIST              pTask                   = CProfile::m_TaskList;\r
126         \r
127         TCHAR szWindowName[WINDOW_NAME_LENGTH];\r
128         TCHAR szClassName[CLASS_NAME_LENGTH];\r
129         WINDOWPLACEMENT wpl;\r
130         \r
131         wpl.length = sizeof(WINDOWPLACEMENT);\r
132         ::GetWindowText(hWnd, szWindowName, sizeof(szWindowName));\r
133         GetClassName(hWnd, szClassName, sizeof(szClassName));\r
134 \r
135         CString szAppName;\r
136         // Get Process Name\r
137         DWORD dwProcessId = 0;\r
138         GetWindowThreadProcessId(hWnd, &dwProcessId);\r
139         for (DWORD i = 0; i < CProfile::m_dwTasks; ++i) {\r
140                 if (pTask[i].dwProcessId == dwProcessId) {\r
141 \r
142                         // Get Application Name\r
143                         if (szWindowName[0] == '\0') {\r
144                                 continue;\r
145                         }\r
146                         if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_B2)), sizeof(pTask[i].ProcessName))) {\r
147                                 szAppName.LoadString(IDS_BECKY);\r
148                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXPLORER)), sizeof(pTask[i].ProcessName))) {\r
149                                 szAppName.LoadString(IDS_PROGRAM_MANAGER);\r
150                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSIMN)), sizeof(pTask[i].ProcessName))) {\r
151                                 szAppName.LoadString(IDS_OUTLOOK_EXPRESS);\r
152                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_PROJECT)), sizeof(pTask[i].ProcessName))\r
153                                         || !_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXCEL)), sizeof(pTask[i].ProcessName))\r
154                                         || !_tcsnicmp(pTask[i].ProcessName, _T("psp.exe"), sizeof(pTask[i].ProcessName))) {\r
155                                 GetNthString(&szAppName, szWindowName, CString(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE)), 1);\r
156                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sakura.exe"), sizeof(pTask[i].ProcessName))) {\r
157                                 GetNthString(&szAppName, szWindowName, CString(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE)), 2);  // '.' is included, so...\r
158                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSDN)), sizeof(pTask[i].ProcessName))) {\r
159                                 szAppName = szWindowName;\r
160                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("devenv.exe"), sizeof(pTask[i].ProcessName))) {\r
161                                 szAppName.Format(_T("Microsoft Visual Studio .NET"));\r
162                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vb6.exe"), sizeof(pTask[i].ProcessName))) {\r
163                                 szAppName.Format(_T("Microsoft Visual Basic"));\r
164                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("ssexp.exe"), sizeof(pTask[i].ProcessName))) {\r
165                                 szAppName.LoadString(IDS_VISUAL_SOURCESAFE_EXPLORER);\r
166                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sh.exe"), sizeof(pTask[i].ProcessName))) {\r
167                                 szAppName.Format(_T("MKS Korn Shell"));\r
168                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("csh.exe"), sizeof(pTask[i].ProcessName))) {\r
169                                 szAppName.Format(_T("C Shell"));\r
170                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vim.exe"), sizeof(pTask[i].ProcessName))) {\r
171                                 szAppName.Format(_T("VIM"));\r
172                         } else {\r
173                                 CUtils::SetCorrectApplicationName(pTask[i].ProcessName, sizeof(pTask[i].ProcessName), szWindowName, sizeof(szWindowName));\r
174                                 GetAppName(&szAppName, szWindowName);\r
175                         }\r
176                         break;\r
177                 }\r
178         }\r
179         \r
180         \r
181         if ((IsWindowVisible(hWnd))                                                                     // Is visible?\r
182          && (GetWindow(hWnd, GW_OWNER) == NULL)                                         // Is top level window?\r
183          && (lstrlen(szWindowName) > 0)                                                         // Have caption?\r
184          && (pApplication->FindString(-1, szClassName) == CB_ERR)) {// Is not same string?\r
185                 CString szListItem;\r
186                 szListItem.Format(IDS_APPLICATION_LIST_ITEM, szAppName, pTask[i].ProcessName);\r
187                 if (IsNotSameString(pApplication, szListItem)) {\r
188                         pApplication->AddString(szListItem);\r
189                 }\r
190         }\r
191         return TRUE;\r
192 }\r
193 \r
194         \r
195 //////////////////////////////////////////////////////////////////////\r
196 // Construction/Destruction\r
197 //////////////////////////////////////////////////////////////////////\r
198 \r
199 CProfile::CProfile()\r
200 {\r
201 \r
202 }\r
203 \r
204 CProfile::~CProfile()\r
205 {\r
206 \r
207 }\r
208 \r
209 // This method initializes data in the registry, or retrieves and validates registry data.\r
210 // bSaveAndValidate specifies a flag that indicates \r
211 // whether registry data is being initialized (FALSE) or data is being retrieved (TRUE). \r
212 void CProfile::UpdateRegistryData(const BOOL bSaveAndValidate)\r
213 {\r
214         CString szEntry;\r
215         CString szApplicationName;\r
216         CString szApplicationTitle;\r
217         CString szWindowText;\r
218         CString szWindowTextType;\r
219 \r
220         BOOL bUseDialogSetting = FALSE;\r
221 \r
222         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
223                 // application name\r
224                 CString szSection(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION));\r
225                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
226                 if (bSaveAndValidate) { // retrieve\r
227                         m_XkeymacsData[nApplicationID].ClearAll();\r
228                         szApplicationName = AfxGetApp()->GetProfileString(szSection, szEntry);\r
229                         if (szApplicationName.IsEmpty()) {\r
230                                 if (nApplicationID) {\r
231                                         if (!bUseDialogSetting) {\r
232                                                 szApplicationName.LoadString(IDS_DIALOG);\r
233                                                 bUseDialogSetting = TRUE;\r
234                                         } else {\r
235                                                 continue;\r
236                                         }\r
237                                 } else {\r
238                                         szApplicationName.LoadString(IDS_DEFAULT);\r
239                                 }\r
240                         } else {\r
241                                 if (szApplicationName == CString(MAKEINTRESOURCE(IDS_DIALOG))) {\r
242                                         bUseDialogSetting = TRUE;\r
243                                 }\r
244                         }\r
245                         m_XkeymacsData[nApplicationID].SetApplicationName(szApplicationName);\r
246                 } else {                                // initialize\r
247                         szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
248                         if (szApplicationName.IsEmpty()) {\r
249                                 continue;\r
250                         }\r
251                         AfxGetApp()->WriteProfileString(szSection, szEntry, szApplicationName);\r
252                 }\r
253 \r
254                 // application title\r
255                 szEntry.LoadString(IDS_REG_ENTRY_APPLICATOIN_TITLE);\r
256                 if (bSaveAndValidate) { // retrieve\r
257                         szApplicationTitle = AfxGetApp()->GetProfileString(szApplicationName, szEntry);\r
258                         m_XkeymacsData[nApplicationID].SetApplicationTitle(szApplicationTitle);\r
259                 } else {                                // initialize\r
260                         szApplicationTitle = m_XkeymacsData[nApplicationID].GetApplicationTitle();\r
261                         while (!szApplicationTitle.IsEmpty() && szApplicationTitle.GetAt(0) == _T(' ')) {\r
262                                 szApplicationTitle.Delete(0);\r
263                         }\r
264                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szApplicationTitle);\r
265                 }\r
266 \r
267                 // window text\r
268                 szEntry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT);\r
269                 if (bSaveAndValidate) { // retrieve\r
270                         szWindowText = AfxGetApp()->GetProfileString(szApplicationName, szEntry, _T("*"));\r
271                         if (szWindowText.IsEmpty()) {\r
272                                 szWindowText = _T('*');\r
273                         }\r
274                         m_XkeymacsData[nApplicationID].SetWindowText(szWindowText);\r
275                 } else {                                // initialize\r
276                         szWindowText = m_XkeymacsData[nApplicationID].GetWindowText();\r
277                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szWindowText);\r
278                 }\r
279 \r
280                 // window text type\r
281                 szEntry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT_TYPE);\r
282                 if (bSaveAndValidate) { // retrieve\r
283                         szWindowTextType = AfxGetApp()->GetProfileString(szApplicationName, szEntry);\r
284 \r
285                         int nWindowTextType = IDS_WINDOW_TEXT_IGNORE;\r
286                         if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH))) {\r
287                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH;\r
288                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_FORWARD))) {\r
289                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_FORWARD;\r
290                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_BACKWARD))) {\r
291                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_BACKWARD;\r
292                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_FULL))) {\r
293                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_FULL;\r
294                         }\r
295 \r
296                         m_XkeymacsData[nApplicationID].SetWindowTextType(nWindowTextType);\r
297                 } else {                                // initialize\r
298                         szWindowTextType.LoadString(m_XkeymacsData[nApplicationID].GetWindowTextType());\r
299                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szWindowTextType);\r
300                 }\r
301 \r
302                 // on/off\r
303                 if (bSaveAndValidate) { // retrieve\r
304                         for (int nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {\r
305                                 szEntry = CXkeymacsData::GetCommandName(nCommandID);\r
306                                 if (szEntry.IsEmpty()) {\r
307                                         break;\r
308                                 }\r
309 \r
310                                 HKEY hKey = NULL;\r
311                                 CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
312                                 szSubKey += _T("\\") + szApplicationName + _T("\\") + szEntry;\r
313                                 if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
314                                         // Use registry data\r
315                                         TCHAR szKeyBind[128] = {'\0'};\r
316                                         DWORD dwKeyBind = sizeof(szKeyBind);\r
317                                         FILETIME ft = {'\0'};   // not use\r
318                                         for (DWORD dwIndex = 0;\r
319                                                  RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS;\r
320                                                  ++dwIndex) {\r
321                                                 int nCommandType = 0;\r
322                                                 int nKey = 0;\r
323                                                 ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
324                                                 m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
325 \r
326 //                                              if (nCommandType == CONTROL && nKey == 'D') {\r
327 //                                                      CUtils::Log("GetProfileInt(at ibeam cursor only): %s, %s", szSubKey, szKeyBind);\r
328 //                                              }\r
329                                                 const CString szSection = szSubKey.Right(szSubKey.GetLength() - CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)).GetLength() - _tcslen(_T("\\"))) + _T("\\") + szKeyBind;\r
330                                                 const BOOL bAtIbeamCursorOnly = AfxGetApp()->GetProfileInt(szSection, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_AT_IBEAM_CURSOR_ONLY)), FALSE);\r
331                                                 m_XkeymacsData[nApplicationID].SetAtIbeamCursorOnly(nCommandType, nKey, bAtIbeamCursorOnly);\r
332 \r
333                                                 memset(szKeyBind, 0, sizeof(szKeyBind));\r
334                                                 dwKeyBind = sizeof(szKeyBind);\r
335                                         }\r
336                                         RegCloseKey(hKey);\r
337                                 } else {\r
338                                         // Use default setting\r
339                                         for (int i = 0; ; ++i) {\r
340                                                 if (CXkeymacsData::GetDefaultControlID(nCommandID, i) == IDC_CO2) {\r
341                                                         continue;\r
342                                                 }\r
343 \r
344                                                 int nCommandType = CXkeymacsData::GetDefaultCommandType(nCommandID, i);\r
345                                                 int nKey = CXkeymacsData::GetDefaultCommandKey(nCommandID, i);\r
346                                                 if (nKey == 0) {\r
347                                                         break;\r
348                                                 }\r
349                                                 m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
350                                                 m_XkeymacsData[nApplicationID].SetAtIbeamCursorOnly(nCommandType, nKey, FALSE);\r
351                                         }\r
352                                 }\r
353                         }\r
354                         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
355                                 HKEY hKey = NULL;\r
356                                 CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
357                                 szSubKey += _T("\\") + szApplicationName + _T("\\") + CDotXkeymacs::GetFunctionSymbol(nFunctionID);\r
358                                 if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
359                                         // Use registry data\r
360                                         CDotXkeymacs::ClearKey(nFunctionID, nApplicationID);\r
361                                         TCHAR szKeyBind[128] = {'\0'};\r
362                                         DWORD dwKeyBind = sizeof(szKeyBind);\r
363                                         FILETIME ft = {'\0'};   // not use\r
364                                         for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS; ++dwIndex) {\r
365                                                 int nCommandType = 0;\r
366                                                 int nKey = 0;\r
367                                                 ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
368                                                 CDotXkeymacs::SetKey(nFunctionID, nApplicationID, nCommandType, nKey);\r
369 \r
370                                                 memset(szKeyBind, 0, sizeof(szKeyBind));\r
371                                                 dwKeyBind = sizeof(szKeyBind);\r
372                                         }\r
373                                         RegCloseKey(hKey);\r
374                                 }\r
375                         }\r
376                 } else {                                // initialize\r
377                         // create all commands\r
378                         for (int nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {\r
379                                 szEntry = CXkeymacsData::GetCommandName(nCommandID);\r
380                                 if (szEntry.IsEmpty()) {\r
381                                         break;\r
382                                 }\r
383 \r
384                                 SaveCommand(szApplicationName, nCommandID);\r
385                         }\r
386                         for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {\r
387                                 for (int nKey = 0; nKey < MAX_KEY; ++nKey) {\r
388                                         int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
389                                         SaveKeyBind(szApplicationName, nCommandID, nCommandType, nKey);\r
390                                 }\r
391                         }\r
392                         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
393                                 for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFunctionID, nApplicationID); ++nKeyID) {\r
394                                         int nCommandType = 0;\r
395                                         int nKey = 0;\r
396                                         CDotXkeymacs::GetKey(nFunctionID, nApplicationID, nKeyID, &nCommandType, &nKey);\r
397                                         SaveKeyBind(szApplicationName, CDotXkeymacs::GetFunctionSymbol(nFunctionID), nCommandType, nKey);\r
398                                 }\r
399                         }\r
400                 }\r
401 \r
402                 // kill-ring-max\r
403                 szEntry.LoadString(IDS_REG_ENTRY_KILL_RING_MAX);\r
404                 if (bSaveAndValidate) { // retrieve\r
405                         int nKillRingMax = AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 1);\r
406                         m_XkeymacsData[nApplicationID].SetKillRingMax(nKillRingMax);\r
407                 } else {                                // initialize\r
408                         int nKillRingMax = m_XkeymacsData[nApplicationID].GetKillRingMax();\r
409                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, nKillRingMax);\r
410                 }\r
411 \r
412                 // Use Dialog Setting\r
413                 szEntry.LoadString(IDS_REG_ENTRY_USE_DIALOG_SETTING);\r
414                 if (bSaveAndValidate) { // retrieve\r
415                         BOOL bUseDialogSetting = AfxGetApp()->GetProfileInt(szApplicationName,szEntry, 1);\r
416                         m_XkeymacsData[nApplicationID].SetUseDialogSetting(bUseDialogSetting);\r
417                 } else {                                // initialize\r
418                         BOOL bUseDialogSetting = m_XkeymacsData[nApplicationID].GetUseDialogSetting();\r
419                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, bUseDialogSetting);\r
420                 }\r
421 \r
422                 // Setting Style\r
423                 szEntry.LoadString(IDS_REG_ENTRY_DISABLE_XKEYMACS);\r
424                 if (bSaveAndValidate) { // retrieve\r
425                         int nSettingStyle = SETTING_SPECIFIC;\r
426                         if (AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0) != 0) {\r
427                                 nSettingStyle = SETTING_DISABLE;\r
428                         }\r
429                         m_XkeymacsData[nApplicationID].SetSettingStyle(nSettingStyle);\r
430                 } else {                                // initialize\r
431                         BOOL bDisableXkeymacs = FALSE;\r
432                         if (m_XkeymacsData[nApplicationID].GetSettingStyle() == SETTING_DISABLE) {\r
433                                 bDisableXkeymacs = TRUE;\r
434                         }\r
435                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, bDisableXkeymacs);\r
436                 }\r
437 \r
438                 // Ignore Meta Ctrl+? when it is undefined.\r
439                 szEntry.LoadString(IDC_REG_ENTRY_IGNORE_META_CTRL);\r
440                 if (bSaveAndValidate) { // retrieve\r
441                         m_XkeymacsData[nApplicationID].SetIgnoreUndefinedMetaCtrl(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
442                 } else {                                // initialize\r
443                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedMetaCtrl());\r
444                 }\r
445 \r
446                 // Ignore C-x ? when it is undefined.\r
447                 szEntry.LoadString(IDC_REG_ENTRY_IGNORE_C_X);\r
448                 if (bSaveAndValidate) { // retrieve\r
449                         m_XkeymacsData[nApplicationID].SetIgnoreUndefinedC_x(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
450                 } else {                                // initialize\r
451                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedC_x());\r
452                 }\r
453 \r
454                 // Enable CUA-mode\r
455                 szEntry.LoadString(IDC_REG_ENTRY_ENABLE_CUA);\r
456                 if (bSaveAndValidate) { // retrieve\r
457                         m_XkeymacsData[nApplicationID].SetEnableCUA(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
458                 } else {                                // initialize\r
459                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetEnableCUA());\r
460                 }\r
461 \r
462                 // Version 3.26 compatible mode\r
463                 szEntry.LoadString(IDS_REG_ENTRY_326_COMPATIBLE);\r
464                 if (bSaveAndValidate) { // retrieve\r
465                         m_XkeymacsData[nApplicationID].Set326Compatible(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
466                 } else {                                // initialize\r
467                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].Get326Compatible());\r
468                 }\r
469         }\r
470 }\r
471 \r
472 void CProfile::LoadRegistryData()\r
473 {\r
474         CDotXkeymacs::Load();\r
475         LevelUp();\r
476         UpdateRegistryData(TRUE);\r
477 }\r
478 \r
479 void CProfile::SaveRegistryData()\r
480 {\r
481         DeleteAllRegistryData();\r
482         UpdateRegistryData(FALSE);\r
483         SetDllData();\r
484 }\r
485 \r
486 void CProfile::SetDllData()\r
487 {\r
488         CMainFrame *pMainFrame = (CMainFrame*)AfxGetMainWnd();\r
489 \r
490         pMainFrame->m_pXkeymacsDll->ClearFunctionDefinition();\r
491         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
492                 pMainFrame->m_pXkeymacsDll->SetFunctionDefinition(nFunctionID, CDotXkeymacs::GetFunctionDefinition(nFunctionID));\r
493         }\r
494 \r
495         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
496 \r
497                 CString szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
498 \r
499                 if (szApplicationName.IsEmpty()) {\r
500                         pMainFrame->m_pXkeymacsDll->Clear(nApplicationID);\r
501                         continue;\r
502                 }\r
503 \r
504                 pMainFrame->m_pXkeymacsDll->SetApplicationName(nApplicationID, szApplicationName);\r
505                 pMainFrame->m_pXkeymacsDll->SetWindowText(nApplicationID, m_XkeymacsData[nApplicationID].GetWindowText());\r
506                 pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 0);\r
507                 pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', FALSE);\r
508 \r
509                 for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {\r
510                         for (int nKey = 0; nKey < MAX_KEY; ++nKey) {\r
511                                 const int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
512                                 pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, nCommandType, nKey, nCommandID);\r
513                                 const BOOL bAtIbeamCursorOnly = m_XkeymacsData[nApplicationID].GetAtIbeamCursorOnly(nCommandType, nKey);\r
514                                 pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, nCommandType, nKey, bAtIbeamCursorOnly);\r
515                                 if ((nCommandType & CONTROLX) && nCommandID) {\r
516                                         pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 1);                      // Commands[1] is C-x\r
517                                         pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', bAtIbeamCursorOnly);\r
518                                 }\r
519                         }\r
520                 }\r
521 \r
522                 for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
523                         for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFunctionID, nApplicationID); ++nKeyID) {\r
524                                 int nCommandType = 0;\r
525                                 int nKey = 0;\r
526                                 CDotXkeymacs::GetKey(nFunctionID, nApplicationID, nKeyID, &nCommandType, &nKey);\r
527                                 pMainFrame->m_pXkeymacsDll->SetFunctionKey(nFunctionID, nApplicationID, nCommandType, nKey);\r
528                                 if (nCommandType & CONTROLX) {\r
529                                         pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 1);                      // Commands[1] is C-x\r
530                                         const BOOL bAtIbeamCursorOnly = m_XkeymacsData[nApplicationID].GetAtIbeamCursorOnly(nCommandType, nKey);\r
531                                         pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', bAtIbeamCursorOnly);\r
532                                 }\r
533                         }\r
534                 }\r
535 \r
536                 pMainFrame->m_pXkeymacsDll->SetKillRingMax(nApplicationID, m_XkeymacsData[nApplicationID].GetKillRingMax());\r
537                 pMainFrame->m_pXkeymacsDll->SetUseDialogSetting(nApplicationID, m_XkeymacsData[nApplicationID].GetUseDialogSetting());\r
538                 pMainFrame->m_pXkeymacsDll->SetSettingStyle(nApplicationID, m_XkeymacsData[nApplicationID].GetSettingStyle());\r
539                 pMainFrame->m_pXkeymacsDll->SetIgnoreUndefinedMetaCtrl(nApplicationID, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedMetaCtrl());\r
540                 pMainFrame->m_pXkeymacsDll->SetIgnoreUndefinedC_x(nApplicationID, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedC_x());\r
541                 pMainFrame->m_pXkeymacsDll->SetEnableCUA(nApplicationID, m_XkeymacsData[nApplicationID].GetEnableCUA());\r
542                 pMainFrame->m_pXkeymacsDll->Set326Compatible(nApplicationID, m_XkeymacsData[nApplicationID].Get326Compatible());\r
543         }\r
544 }\r
545 \r
546 void CProfile::ReadKeyBind(int *const pnCommandType, int *const pnKey, LPCTSTR szKeyBind)\r
547 {\r
548         *pnCommandType = KeyBind2CommandType(szKeyBind);\r
549         *pnKey = KeyBind2Key(szKeyBind + _tcslen(CommandType2String(*pnCommandType)));\r
550 }\r
551 \r
552 CString CProfile::WriteKeyBind(const int nCommandType, const int nKey)\r
553 {\r
554         CString szKeyBind;\r
555         szKeyBind.Format(_T("%s%s"), CommandType2String(nCommandType), Key2String(nKey));\r
556         return szKeyBind;\r
557 }\r
558 \r
559 int CProfile::KeyBind2CommandType(LPCTSTR szKeyBind)\r
560 {\r
561         for (int nCommandType = MAX_COMMAND_TYPE - 1; nCommandType; --nCommandType) {\r
562                 if (IsCommandType(nCommandType, szKeyBind)) {\r
563                         return nCommandType;\r
564                 }\r
565         }\r
566         return NONE;\r
567 }\r
568 \r
569 int CProfile::KeyBind2Key(LPCTSTR szKey)\r
570 {\r
571         for (int nKey = 1; nKey < 0xff; ++nKey) {\r
572                 if (!_tcscmp(szKey, Key2String(nKey))) {\r
573                         return nKey;\r
574                 }\r
575         }\r
576         return 0;\r
577 }\r
578 \r
579 LPCTSTR CProfile::CommandType2String(int nCommandType)\r
580 {\r
581         if (nCommandType < 0 || sizeof(CommandTypes) / sizeof(CommandTypes[0]) <= nCommandType) {\r
582                 ASSERT(0);\r
583                 nCommandType = NONE;\r
584         }\r
585         return CommandTypes[nCommandType].szCommandTypeName;\r
586 }\r
587 \r
588 LPCTSTR CProfile::Key2String(int nKey)\r
589 {\r
590         if (CProfile::Is106Keyboard()) {\r
591                 switch (nKey) {\r
592                 case 0xBA:\r
593                         return _T(":");\r
594                 case 0xBB:\r
595                         return _T(";");\r
596                 case 0xC0:\r
597                         return _T("@");\r
598                 case 0xDE:\r
599                         return _T("^");\r
600                 default:\r
601                         break;\r
602                 }\r
603         }\r
604 \r
605         if (nKey < 0 || sizeof(KeyNames) / sizeof(KeyNames[0]) <= nKey) {\r
606                 ASSERT(0);\r
607                 nKey = 0;\r
608         }\r
609         return KeyNames[nKey].name;\r
610 }\r
611 \r
612 BOOL CProfile::IsCommandType(const int nCommandType, LPCTSTR szKeyBind)\r
613 {\r
614         LPCTSTR szCommandType = CommandType2String(nCommandType);\r
615 \r
616         if (!_tcsnicmp(szKeyBind, szCommandType, _tcslen(szCommandType))) {\r
617                 return TRUE;\r
618         }\r
619 \r
620         return FALSE;\r
621 }\r
622 \r
623 void CProfile::SaveKeyBind(const CString szApplicationName, const int nCommandID, const int nCommandType, const int nKey)\r
624 {\r
625         if (!nCommandID) {\r
626                 return;\r
627         }\r
628 \r
629         CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);\r
630         if (szCommandName.IsEmpty()) {\r
631                 return;\r
632         }\r
633 \r
634         SaveKeyBind(szApplicationName, szCommandName, nCommandType, nKey);\r
635 }\r
636 \r
637 void CProfile::SaveKeyBind(const CString szApplicationName, const CString szCommandName, const int nCommandType, const int nKey)\r
638 {\r
639         CString szKeyBind = WriteKeyBind(nCommandType, nKey);\r
640         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
641         szSubKey += _T("\\") + szApplicationName + _T("\\") + szCommandName;\r
642         if (!szKeyBind.IsEmpty()) {\r
643                 szSubKey += _T("\\") + szKeyBind;\r
644         }\r
645 \r
646         HKEY hKey = NULL;\r
647         if (RegCreateKeyEx(HKEY_CURRENT_USER, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) {\r
648                 RegCloseKey(hKey);\r
649         }\r
650 }\r
651 \r
652 void CProfile::SaveCommand(const CString szApplicationName, const int nCommandID)\r
653 {\r
654         SaveKeyBind(szApplicationName, nCommandID, 0, 0);\r
655 }\r
656 \r
657 void CProfile::AddKeyBind2C_(const CString szApplicationName, const BYTE bVk)\r
658 {\r
659         for (int nCommandID = 0; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {\r
660                 if (Commands[nCommandID].fCommand == CCommands::C_) {\r
661                         break;\r
662                 }\r
663         }\r
664 \r
665         SaveKeyBind(szApplicationName, nCommandID, NONE, bVk);\r
666 }\r
667 \r
668 void CProfile::LevelUp()\r
669 {\r
670         const int nDefalutLevel = 0;\r
671         const int nLatestLevel = 4;\r
672 \r
673         CString szSection;\r
674         CString szEntry;\r
675         szEntry.Format(_T("Level"));\r
676 \r
677 //      const int nCurrentLevel = AfxGetApp()->GetProfileInt(szSection, szEntry, nDefalutLevel);\r
678         switch (AfxGetApp()->GetProfileInt(szSection, szEntry, nDefalutLevel)) {\r
679         case nDefalutLevel:\r
680                 {\r
681                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
682                                 CString szEntry;\r
683                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
684 \r
685                                 CString szApplicationName;\r
686                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
687                                 if (szApplicationName.IsEmpty()) {\r
688                                         continue;\r
689                                 }\r
690 \r
691                                 AddKeyBind2C_(szApplicationName, VK_LCONTROL);\r
692                                 AddKeyBind2C_(szApplicationName, VK_RCONTROL);\r
693                         }\r
694                 }\r
695                 // Do NOT write break; here.\r
696         case 1:\r
697                 {\r
698                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
699                                 CString szEntry;\r
700                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
701 \r
702                                 CString szApplicationName;\r
703                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
704                                 if (szApplicationName.IsEmpty()) {\r
705                                         continue;\r
706                                 }\r
707 \r
708                                 // Set kill-ring-max 1 if it is 0.\r
709                                 if (!AfxGetApp()->GetProfileInt(szApplicationName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 0)) {\r
710                                         AfxGetApp()->WriteProfileInt(szApplicationName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 1);\r
711                                 }\r
712                         }\r
713                 }\r
714                 // Do NOT write break; here.\r
715         case 2:\r
716                 {\r
717                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
718                                 CString szEntry;\r
719                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
720 \r
721                                 CString szApplicationName;\r
722                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
723                                 if (szApplicationName.IsEmpty()) {\r
724                                         continue;\r
725                                 }\r
726 \r
727                                 // Chaged a label from Enter to newline.\r
728                                 CString szSrcSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
729                                 szSrcSubKey += _T("\\") + szApplicationName + _T("\\") + _T("Enter");\r
730                                 CString szDestSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
731                                 szDestSubKey += _T("\\") + szApplicationName + _T("\\") + _T("newline");\r
732                                 HKEY hKeyDest = NULL;\r
733                                 if (RegCreateKeyEx(HKEY_CURRENT_USER, szDestSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyDest, NULL) == ERROR_SUCCESS) {\r
734                                         SHCopyKey(HKEY_CURRENT_USER, szSrcSubKey, hKeyDest, NULL);\r
735                                         SHDeleteKey(HKEY_CURRENT_USER, szSrcSubKey);\r
736                                         RegCloseKey(hKeyDest);\r
737                                 }\r
738                         }\r
739                 }\r
740                 // Do NOT write break; here.\r
741         case 3:\r
742                 {\r
743                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
744                                 CString szEntry;\r
745                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
746 \r
747                                 CString szApplicationName;\r
748                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
749                                 if (szApplicationName.IsEmpty()) {\r
750                                         continue;\r
751                                 }\r
752 \r
753                                 // rename original function to remove IDS_REG_ORIGINAL_PREFIX\r
754                                 for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
755                                         HKEY hKey = NULL;\r
756                                         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
757                                         szSubKey += _T("\\") + szApplicationName + _T("\\") + CString(MAKEINTRESOURCE(IDS_REG_ORIGINAL_PREFIX)) + CDotXkeymacs::GetFunctionSymbol(nFunctionID);\r
758                                         if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
759                                                 // Use registry data\r
760                                                 TCHAR szKeyBind[128] = {'\0'};\r
761                                                 DWORD dwKeyBind = sizeof(szKeyBind);\r
762                                                 FILETIME ft = {'\0'};   // not use\r
763                                                 for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS; ++dwIndex) {\r
764                                                         int nCommandType = 0;\r
765                                                         int nKey = 0;\r
766                                                         ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
767                                                         SaveKeyBind(szApplicationName, CDotXkeymacs::GetFunctionSymbol(nFunctionID), nCommandType, nKey);\r
768 \r
769                                                         memset(szKeyBind, 0, sizeof(szKeyBind));\r
770                                                         dwKeyBind = sizeof(szKeyBind);\r
771                                                 }\r
772                                                 RegCloseKey(hKey);\r
773                                         }\r
774                                 }\r
775                         }\r
776                 }\r
777 //      case 4:\r
778 //              foo();\r
779 //      ...\r
780 //      case nLatestLevel-1:\r
781 //              bar();\r
782                 AfxGetApp()->WriteProfileInt(szSection, szEntry, nLatestLevel);\r
783                 break;\r
784         default:\r
785                 break;\r
786         }\r
787 }\r
788 \r
789 void CProfile::InitDllData()\r
790 {\r
791         LoadRegistryData();\r
792         SetDllData();\r
793 }\r
794 \r
795 void CProfile::ClearData(const CString szCurrentApplication)\r
796 {\r
797         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
798                 if (m_XkeymacsData[nApplicationID].GetApplicationName() == szCurrentApplication) {\r
799                         break;\r
800                 }\r
801         }\r
802         if (nApplicationID < MAX_APP) {\r
803                 m_XkeymacsData[nApplicationID].ClearAll();\r
804         }\r
805 }\r
806 \r
807 // return count of saved settings\r
808 int CProfile::GetSavedSettingCount()\r
809 {\r
810         int nSavedSetting = 0;\r
811 \r
812         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
813                 CString szApplicationName;\r
814                 szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
815                 if (!szApplicationName.IsEmpty()) {\r
816                         ++nSavedSetting;\r
817                 }\r
818         }\r
819 \r
820         return nSavedSetting;\r
821 }\r
822 \r
823 void CProfile::InitApplicationList(CComboBox *const cApplicationList)\r
824 {\r
825         cApplicationList->ResetContent();\r
826 \r
827         m_dwTasks = GetTaskList(m_TaskList, MAX_TASKS);\r
828 \r
829         EnumWindows(EnumWindowsProc, (LPARAM)cApplicationList);\r
830 \r
831         for (int i = 0; i < MAX_APP; ++i) {\r
832                 CString szApplicationName       = m_XkeymacsData[i].GetApplicationName();\r
833                 CString szApplicationTitle      = m_XkeymacsData[i].GetApplicationTitle();\r
834 \r
835                 CString szListItem;\r
836                 szListItem.Format(IDS_APPLICATION_LIST_ITEM, szApplicationTitle, szApplicationName);\r
837                 if (IsNotSameString(cApplicationList, szListItem)\r
838                  && !IsDefault(szApplicationName)\r
839                  && !IsDialog(szApplicationName)\r
840                  && !szApplicationName.IsEmpty()) {\r
841                         cApplicationList->AddString(szListItem);\r
842                 }\r
843         }\r
844 \r
845         // Add IME\r
846         HKL hKL = GetKeyboardLayout(0);\r
847         if (ImmIsIME(hKL)) {\r
848                 LPTSTR szIMEDescription = NULL;\r
849                 UINT nIMEDescription = ImmGetDescription(hKL, NULL, 0);\r
850                 if (nIMEDescription) {\r
851                         nIMEDescription += sizeof(TCHAR);       // for NULL\r
852                         if ((szIMEDescription = new TCHAR[nIMEDescription]) != NULL) {\r
853                                 ImmGetDescription(hKL, szIMEDescription, nIMEDescription);\r
854                         }\r
855 //                      CUtils::Log(_T("nIMEDescription = %d, szIMEDescription = _%s_"), nIMEDescription, szIMEDescription);\r
856                 }\r
857 \r
858                 LPTSTR szIMEFileName = NULL;\r
859                 UINT nIMEFileName = ImmGetIMEFileName(hKL, NULL, 0);\r
860                 if (nIMEFileName) {\r
861                         nIMEFileName += sizeof(TCHAR);\r
862                         if ((szIMEFileName = new TCHAR[nIMEFileName]) != NULL) {\r
863                                 ImmGetIMEFileName(hKL, szIMEFileName, nIMEFileName);\r
864                         }\r
865 //                      CUtils::Log(_T("nIMEFileName = %d, szIMEFileName = _%s_"), nIMEFileName, szIMEFileName);\r
866                 }\r
867 \r
868                 CString szIMETitle;\r
869                 CString szIME(MAKEINTRESOURCE(IDS_IME_FILE_NAME));\r
870                 szIMETitle.Format(IDS_APPLICATION_LIST_ITEM, szIMEDescription ? szIMEDescription : szIME, szIMEFileName ? szIMEFileName : szIME);\r
871 //              CUtils::Log(_T("szIMETitle = _%s_, szIMEDescription = _%s_, szIMEFileName = _%s_"), szIMETitle, szIMEDescription, szIMEFileName);\r
872                 if (IsNotSameString(cApplicationList, szIMETitle)) {\r
873                         cApplicationList->AddString(szIMETitle);\r
874                 }\r
875 \r
876                 delete[] szIMEDescription;\r
877                 szIMEDescription = NULL;\r
878                 delete[] szIMEFileName;\r
879                 szIMEFileName = NULL;\r
880         }\r
881 \r
882         // Add Dialog\r
883         cApplicationList->InsertString(0, CString(MAKEINTRESOURCE(IDS_DIALOG_TITLE)));\r
884 \r
885         // Add Default\r
886         cApplicationList->InsertString( 0, CString(MAKEINTRESOURCE(IDS_DEFAULT_TITLE)));\r
887         cApplicationList->SelectString(-1, CString(MAKEINTRESOURCE(IDS_DEFAULT_TITLE)));\r
888 }\r
889 \r
890 DWORD CProfile::GetTaskList(PTASK_LIST pTask, const DWORD dwNumTasks)\r
891 {\r
892         for (int i = 0; i < MAX_TASKS; ++i) {\r
893                 ZeroMemory(&pTask[i], sizeof(PTASK_LIST));\r
894         }\r
895 \r
896         OSVERSIONINFO verInfo = {0};\r
897         verInfo.dwOSVersionInfoSize = sizeof (verInfo);\r
898         GetVersionEx(&verInfo);\r
899         if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT\r
900          && verInfo.dwMajorVersion < 5) {\r
901                 return GetTaskListNT(pTask, dwNumTasks);\r
902         }\r
903 \r
904         HMODULE hKernel = GetModuleHandle(_T("KERNEL32.DLL"));\r
905         if (!hKernel) {\r
906                 return 0;\r
907         }\r
908 \r
909         CREATESNAPSHOT pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");\r
910         if (!pCreateToolhelp32Snapshot) {\r
911                 return 0;\r
912         }\r
913 \r
914         PROCESSWALK pProcess32First = (PROCESSWALK)GetProcAddress(hKernel, "Process32First");\r
915         if (!pProcess32First) {\r
916                 return 0;\r
917         }\r
918 \r
919         PROCESSWALK pProcess32Next = (PROCESSWALK)GetProcAddress(hKernel, "Process32Next");\r
920         if (!pProcess32Next) {\r
921                 return 0;\r
922         }\r
923 \r
924         HANDLE hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
925         if (hProcessSnap == (HANDLE)-1) {\r
926                 return 0;\r
927         }\r
928 \r
929         DWORD dwTaskCount = 0;\r
930         PROCESSENTRY32 processEntry32 = {sizeof(PROCESSENTRY32)};\r
931         if (pProcess32First(hProcessSnap, &processEntry32)) {\r
932                 do {\r
933                         LPTSTR pCurChar = NULL;\r
934                         for (pCurChar = processEntry32.szExeFile + lstrlen(processEntry32.szExeFile); *pCurChar != _T('\\') && pCurChar != processEntry32.szExeFile; --pCurChar) {\r
935                                 ;\r
936                         }\r
937                         if (*pCurChar == _T('\\')) {\r
938                                 ++pCurChar;\r
939                         }\r
940 \r
941                         lstrcpy(pTask->ProcessName, pCurChar);\r
942                         pTask->dwProcessId = processEntry32.th32ProcessID;\r
943 \r
944                         ++dwTaskCount;\r
945                         ++pTask;\r
946                 } while (dwTaskCount < dwNumTasks && pProcess32Next(hProcessSnap, &processEntry32));\r
947         }\r
948 \r
949         CloseHandle(hProcessSnap);\r
950         return dwTaskCount;\r
951 }\r
952 \r
953 LPBYTE CProfile::GetCounters()\r
954 {\r
955         LANGID lid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);\r
956         CString szSubKey;\r
957         szSubKey.Format(CString(MAKEINTRESOURCE(IDS_REGSUBKEY_PERF)), lid);\r
958         HKEY hKey = NULL;\r
959         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {\r
960                 return NULL;\r
961         }\r
962 \r
963         DWORD dwSize = 0;\r
964         if (RegQueryValueEx(hKey, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_COUNTERS)), NULL, NULL, NULL, &dwSize) != ERROR_SUCCESS) {\r
965                 RegCloseKey(hKey);\r
966                 return NULL;\r
967         }\r
968         LPBYTE pCounters = (LPBYTE) calloc(dwSize, sizeof(BYTE));\r
969         if (pCounters == NULL) {\r
970                 RegCloseKey(hKey);\r
971                 return NULL;\r
972         }\r
973         if (RegQueryValueEx(hKey, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_COUNTERS)), NULL, NULL, pCounters, &dwSize) != ERROR_SUCCESS) {\r
974                 RegCloseKey(hKey);\r
975                 free(pCounters);\r
976                 return NULL;\r
977         }\r
978         RegCloseKey(hKey);\r
979         return pCounters;\r
980 }\r
981 \r
982 BOOL CProfile::GetProcessInfo(CString *const szProcessName, DWORD *const dwProcessId)\r
983 {\r
984         LPBYTE pCounters = GetCounters();\r
985         if (!pCounters) {\r
986                 return FALSE;\r
987         }\r
988         LPTSTR pTopOfString = (LPTSTR)pCounters;\r
989         while (*pTopOfString) {\r
990                 if (_tcsicmp(pTopOfString, CString(MAKEINTRESOURCE(IDS_PROCESS))) == 0) {\r
991                         for (LPTSTR p2 = pTopOfString - 2; _istdigit(*p2); --p2) {\r
992                                 ;\r
993                         }\r
994                         szProcessName->Format(_T("%s"), p2 + 1);        // 230\r
995                 } else if (_tcsicmp(pTopOfString, CString(MAKEINTRESOURCE(IDS_PROCESSID))) == 0) {\r
996                         for (LPTSTR p2 = pTopOfString - 2; _istdigit(*p2); --p2) {\r
997                                 ;\r
998                         }\r
999                         *dwProcessId = _ttol(p2 + 1);                   // 784\r
1000                 }\r
1001                 pTopOfString += (_tcslen(pTopOfString) + 1);\r
1002         }\r
1003         free(pCounters);\r
1004         return TRUE;\r
1005 }\r
1006 \r
1007 PPERF_DATA_BLOCK CProfile::GetPerformanceData(const CString szProcessName)\r
1008 {\r
1009         DWORD dwSize = INITIAL_SIZE;\r
1010         PPERF_DATA_BLOCK pPerformanceData = (PPERF_DATA_BLOCK) calloc(dwSize, sizeof(BYTE));\r
1011         if (pPerformanceData == NULL) {\r
1012                 return NULL;\r
1013         }\r
1014 \r
1015         for (;;) {\r
1016                 switch (RegQueryValueEx(HKEY_PERFORMANCE_DATA, szProcessName, NULL, NULL, (LPBYTE)pPerformanceData, &dwSize)) {\r
1017                 case ERROR_SUCCESS:\r
1018                         if (0 < dwSize\r
1019                          && pPerformanceData->Signature[0] == (WCHAR)'P'\r
1020                          && pPerformanceData->Signature[1] == (WCHAR)'E'\r
1021                          && pPerformanceData->Signature[2] == (WCHAR)'R'\r
1022                          && pPerformanceData->Signature[3] == (WCHAR)'F') {\r
1023                                 return pPerformanceData;\r
1024                         }\r
1025                 case ERROR_MORE_DATA:\r
1026                         dwSize += EXTEND_SIZE;\r
1027                         pPerformanceData = (PPERF_DATA_BLOCK) realloc(pPerformanceData, dwSize);\r
1028                         if (!pPerformanceData) {\r
1029                                 return NULL;\r
1030                         }\r
1031                         memset(pPerformanceData, 0, dwSize);\r
1032                         break;\r
1033                 default:\r
1034                         free(pPerformanceData);\r
1035                         return NULL;\r
1036                 }\r
1037         }\r
1038 }\r
1039 \r
1040 // Add running application's names to the list\r
1041 // only for _Windows NT_\r
1042 DWORD CProfile::GetTaskListNT(PTASK_LIST pTask, DWORD dwNumTasks)\r
1043 {\r
1044         CString szProcessName;\r
1045         DWORD dwProcessIdTitle = 0;\r
1046         if (!GetProcessInfo(&szProcessName, &dwProcessIdTitle)) {\r
1047                 return dwNumTasks;\r
1048         }\r
1049 \r
1050         PPERF_DATA_BLOCK pPerformanceData = GetPerformanceData(szProcessName);\r
1051         if (!pPerformanceData) {\r
1052                 return dwNumTasks;\r
1053         }\r
1054 \r
1055         PPERF_OBJECT_TYPE pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerformanceData + pPerformanceData->HeaderLength);\r
1056         PPERF_COUNTER_DEFINITION pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);\r
1057         DWORD dwProcessIdCounter = 0;\r
1058         for (DWORD i = 0; i < pObj->NumCounters; ++i) {\r
1059                 if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {\r
1060                         dwProcessIdCounter = pCounterDef->CounterOffset;\r
1061                         break;\r
1062                 }\r
1063                 ++pCounterDef;\r
1064         }\r
1065 \r
1066         dwNumTasks = min(dwNumTasks - 1, (DWORD)pObj->NumInstances);\r
1067         PPERF_INSTANCE_DEFINITION pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);\r
1068         for (i = 0; i < dwNumTasks; ++i) {\r
1069                 LPCWSTR pProcessName = (LPCWSTR) ((DWORD)pInst + pInst->NameOffset);\r
1070 \r
1071                 CHAR szProcessName[MAX_PATH] = {'\0'};\r
1072                 if (!WideCharToMultiByte(CP_ACP, 0, pProcessName, -1, szProcessName, sizeof(szProcessName), NULL, NULL)) {\r
1073                         _tcscpy(pTask->ProcessName, CString(MAKEINTRESOURCE(IDS_UNKNOWN_TASK)));\r
1074                 }\r
1075 \r
1076                 if (_tcslen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {\r
1077                         _tcscpy(pTask->ProcessName, szProcessName);\r
1078                         _tcscat(pTask->ProcessName, CString(MAKEINTRESOURCE(IDS_EXTENSION_EXECUTABLE)));\r
1079                 }\r
1080 \r
1081                 PPERF_COUNTER_BLOCK pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);\r
1082                 pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));\r
1083                 if (pTask->dwProcessId == 0) {\r
1084                         pTask->dwProcessId = (DWORD) -2;\r
1085                 }\r
1086 \r
1087                 ++pTask;\r
1088                 pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);\r
1089         }\r
1090 \r
1091         free(pPerformanceData);\r
1092         return dwNumTasks;\r
1093 }\r
1094 \r
1095 // return application index\r
1096 // and update setting style\r
1097 // if there is NOT the application in the data, this function takes care of it.\r
1098 int CProfile::GetApplicationIndex(const CString szApplicationName, const BOOL bSaveAndValidate, int *const nSettingStyle)\r
1099 {\r
1100         if (!bSaveAndValidate) {        // SetDialogData\r
1101                 *nSettingStyle = SETTING_UNDEFINED;\r
1102         }\r
1103 \r
1104         int nApplicationID = GetApplicationIndex(szApplicationName);\r
1105 \r
1106         if (nApplicationID == MAX_APP) {\r
1107                 if (bSaveAndValidate) { // GetDialogData\r
1108                         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1109                                 CString sz = m_XkeymacsData[nApplicationID].GetApplicationName();\r
1110                                 if (sz.IsEmpty()) {\r
1111                                         m_XkeymacsData[nApplicationID].SetApplicationName(szApplicationName);\r
1112                                         break;\r
1113                                 }\r
1114                         }\r
1115                         if (nApplicationID == MAX_APP) {\r
1116                                 return nApplicationID;\r
1117                         }\r
1118                 } else {                                // SetDialogData\r
1119                         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1120                                 if (IsDefault(m_XkeymacsData[nApplicationID].GetApplicationName())) {\r
1121                                         *nSettingStyle = SETTING_DEFAULT;\r
1122                                         break;\r
1123                                 }\r
1124                         }\r
1125                         if (nApplicationID == MAX_APP) {\r
1126                                 return nApplicationID;\r
1127                         }\r
1128                 }\r
1129         }\r
1130 \r
1131         if (bSaveAndValidate) { // GetDialogData\r
1132                 m_XkeymacsData[nApplicationID].SetSettingStyle(*nSettingStyle);\r
1133         } else {                                // SetDialogData\r
1134                 if (*nSettingStyle == SETTING_UNDEFINED) {      // It means that *nSettingStyle != SETTING_DEFAULT.\r
1135                         *nSettingStyle = m_XkeymacsData[nApplicationID].GetSettingStyle();\r
1136                 }\r
1137         }\r
1138 \r
1139         return nApplicationID;\r
1140 }\r
1141 \r
1142 BOOL CProfile::IsTheString(const CString sz, const UINT nID)\r
1143 {\r
1144         return sz == CString(MAKEINTRESOURCE(nID));\r
1145 }\r
1146 \r
1147 // if sz is "Default", return TRUE\r
1148 BOOL CProfile::IsDefault(const CString sz)\r
1149 {\r
1150         return IsTheString(sz, IDS_DEFAULT);\r
1151 }\r
1152 \r
1153 // if sz is "Dialog", return TRUE\r
1154 BOOL CProfile::IsDialog(const CString sz)\r
1155 {\r
1156         return IsTheString(sz, IDS_DIALOG);\r
1157 }\r
1158 \r
1159 void CProfile::GetApplicationTitle(CComboBox *const cApplicationList, CString &rList, const int nIndex)\r
1160 {\r
1161         if (0 <= nIndex) {\r
1162                 cApplicationList->GetLBText(nIndex, rList);\r
1163         } else {\r
1164                 cApplicationList->GetWindowText(rList);\r
1165         }\r
1166 \r
1167         if (IsTheString(rList, IDS_DEFAULT_TITLE)) {\r
1168                 rList.LoadString(IDS_DEFAULT);\r
1169         }\r
1170 \r
1171         if (IsTheString(rList, IDS_DIALOG_TITLE)) {\r
1172                 rList.LoadString(IDS_DIALOG);\r
1173         }\r
1174 \r
1175         return;\r
1176 }\r
1177 \r
1178 void CProfile::UpdateApplicationTitle(CComboBox *const cApplicationList, const CString szCurrentApplication, const int nApplicationID, const BOOL bSaveAndValidate)\r
1179 {\r
1180         static CString szApplicationTitle;\r
1181         if (bSaveAndValidate) { // GetDialogData\r
1182                 if (!CProfile::IsDefault(szCurrentApplication)) {\r
1183                         m_XkeymacsData[nApplicationID].SetApplicationTitle(szApplicationTitle);\r
1184                 }\r
1185                 szApplicationTitle.Empty();\r
1186         } else {                                // SetDialogData\r
1187                 CString szListItem;\r
1188                 CProfile::GetApplicationTitle(cApplicationList, szListItem);\r
1189                 int nEndTitle = szListItem.ReverseFind(_T('('));\r
1190                 if (nEndTitle > 0) {\r
1191                         szApplicationTitle = szListItem.Left(nEndTitle);\r
1192                 }\r
1193         }\r
1194 }\r
1195 \r
1196 void CProfile::SetCommandID(const int nApplicationID, const int nCommandType, const int nKey, int nCommandID)\r
1197 {\r
1198         if (nKey == 0xf0 && Commands[nCommandID].fCommand == CCommands::C_) {\r
1199                 // Change CommandID C_Eisu\r
1200                 for (nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {\r
1201                         if (Commands[nCommandID].fCommand == CCommands::C_Eisu) {\r
1202                                 break;\r
1203                         }\r
1204                 }\r
1205         }\r
1206         m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
1207 }\r
1208 \r
1209 int CProfile::GetCommandID(const int nApplicationID, const int nCommandType, const int nKey)\r
1210 {\r
1211         int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
1212         if (nKey == 0xf0 && Commands[nCommandID].fCommand == CCommands::C_Eisu) {\r
1213                 // Change CommandID C_\r
1214                 for (nCommandID = 1; nCommandID < sizeof(Commands) / sizeof(Commands[0]); ++nCommandID) {\r
1215                         if (Commands[nCommandID].fCommand == CCommands::C_) {\r
1216                                 break;\r
1217                         }\r
1218                 }\r
1219         }\r
1220         return nCommandID;\r
1221 }\r
1222 \r
1223 void CProfile::SetKillRingMax(const int nApplicationID, const int nKillRingMax)\r
1224 {\r
1225         m_XkeymacsData[nApplicationID].SetKillRingMax(nKillRingMax);\r
1226 }\r
1227 \r
1228 int CProfile::GetKillRingMax(const int nApplicationID)\r
1229 {\r
1230         return m_XkeymacsData[nApplicationID].GetKillRingMax();\r
1231 }\r
1232 \r
1233 void CProfile::SetUseDialogSetting(const int nApplicationID, const BOOL bUseDialogSetting)\r
1234 {\r
1235         m_XkeymacsData[nApplicationID].SetUseDialogSetting(bUseDialogSetting);\r
1236 }\r
1237 \r
1238 BOOL CProfile::GetUseDialogSetting(const int nApplicationID)\r
1239 {\r
1240         return m_XkeymacsData[nApplicationID].GetUseDialogSetting();\r
1241 }\r
1242 \r
1243 void CProfile::SetWindowText(const int nApplicationID, const CString szWindowText)\r
1244 {\r
1245         m_XkeymacsData[nApplicationID].SetWindowText(szWindowText);\r
1246 }\r
1247 \r
1248 CString CProfile::GetWindowText(const int nApplicationID)\r
1249 {\r
1250         return m_XkeymacsData[nApplicationID].GetWindowText();\r
1251 }\r
1252 \r
1253 void CProfile::DeleteAllRegistryData()\r
1254 {\r
1255         HKEY hkey = NULL;\r
1256         if (RegOpenKeyEx(HKEY_CURRENT_USER, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)), 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) {\r
1257                 // I am sure that I have to do only one time, but...\r
1258                 for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1259                         DWORD dwIndex = 0;\r
1260                         TCHAR szName[SUB_KEY_NAME_LENGTH] = {'\0'};\r
1261                         DWORD dwName = sizeof(szName);\r
1262                         FILETIME filetime;\r
1263 \r
1264                         while (RegEnumKeyEx(hkey, dwIndex, szName, &dwName, NULL, NULL, NULL, &filetime) == ERROR_SUCCESS) {\r
1265 //                              RegDeleteKey(hkey, szName);\r
1266                                 SHDeleteKey(hkey, szName);\r
1267                                 ZeroMemory(szName, sizeof(szName));\r
1268                                 dwName = sizeof(szName);\r
1269                         }\r
1270                 }\r
1271                 RegCloseKey(hkey);\r
1272         }\r
1273 }\r
1274 \r
1275 int CProfile::GetCurrentApplicationID(CComboBox *const cApplicationList, const CString szCurrentApplication)\r
1276 {\r
1277         int nCounter = cApplicationList->GetCount();\r
1278         CString szListItem;\r
1279         int nCurSel = cApplicationList->GetCurSel();\r
1280 \r
1281         for (int i = 0; i < nCounter; ++i) {\r
1282                 cApplicationList->SetCurSel(i);\r
1283                 CProfile::GetApplicationTitle(cApplicationList, szListItem);\r
1284                 if (szListItem.Find(szCurrentApplication) != -1) {\r
1285                         cApplicationList->SetCurSel(nCurSel);\r
1286                         return i;\r
1287                 }\r
1288         }\r
1289         return -1;\r
1290 }\r
1291 \r
1292 void CProfile::CopyData(const CString szDestinationApplication, const CString szSourceApplication)\r
1293 {\r
1294         int nSettingStyle = SETTING_SPECIFIC;\r
1295         int nDestinationApplication = GetApplicationIndex(szDestinationApplication, TRUE, &nSettingStyle);\r
1296         int nSourceApplication = GetApplicationIndex(szSourceApplication);\r
1297 \r
1298         CString szApplicationName = m_XkeymacsData[nDestinationApplication].GetApplicationName();\r
1299         CString szApplicationTitle = m_XkeymacsData[nDestinationApplication].GetApplicationTitle();\r
1300         CString szWindowText = m_XkeymacsData[nDestinationApplication].GetWindowText();\r
1301         int nWindowTextType = m_XkeymacsData[nDestinationApplication].GetWindowTextType();\r
1302 \r
1303         m_XkeymacsData[nDestinationApplication] = m_XkeymacsData[nSourceApplication];\r
1304 \r
1305         m_XkeymacsData[nDestinationApplication].SetApplicationName(szApplicationName);\r
1306         m_XkeymacsData[nDestinationApplication].SetApplicationTitle(szApplicationTitle);\r
1307         m_XkeymacsData[nDestinationApplication].SetWindowText(szWindowText);\r
1308         m_XkeymacsData[nDestinationApplication].SetWindowTextType(nWindowTextType);\r
1309 }\r
1310 \r
1311 // return application index\r
1312 // if there is NOT the application in the data, return MAX_APP\r
1313 int CProfile::GetApplicationIndex(const CString szApplicationName)\r
1314 {\r
1315         int nApplicationID = 0;\r
1316         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1317                 if (m_XkeymacsData[nApplicationID].GetApplicationName() == szApplicationName) {\r
1318                         break;\r
1319                 }\r
1320         }\r
1321         return nApplicationID;\r
1322 }\r
1323 \r
1324 BOOL CProfile::Is106Keyboard()\r
1325 {\r
1326         static KEYBOARD_TYPE keyboard = UNKNOWN_KEYBOARD;\r
1327 \r
1328         if (keyboard == UNKNOWN_KEYBOARD) {\r
1329                 OSVERSIONINFO verInfo = {0};\r
1330                 verInfo.dwOSVersionInfoSize = sizeof (verInfo);\r
1331                 GetVersionEx(&verInfo);\r
1332 \r
1333                 DWORD subtype = 0;\r
1334                 DWORD cbData = sizeof(subtype);\r
1335 \r
1336                 if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
1337                         HKEY hKey = NULL;\r
1338                         CString szSubKey(_T("SYSTEM\\CurrentControlSet\\Services\\i8042prt\\Parameters"));\r
1339                         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
1340                                 static const CString szValueName(_T("OverrideKeyboardSubtype"));\r
1341                                 if (RegQueryValueEx(hKey, szValueName, NULL, NULL, (LPBYTE)&subtype, &cbData) != ERROR_SUCCESS) {\r
1342                                         subtype = 0;\r
1343                                 }\r
1344                                 RegCloseKey(hKey);\r
1345                         }\r
1346                 } else if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {\r
1347                         subtype = GetPrivateProfileInt(_T("keyboard"), _T("subtype"), 0, _T("system.ini"));\r
1348                 }\r
1349 \r
1350                 keyboard = (subtype & 0x02) ? JAPANESE_KEYBOARD : ENGLISH_KEYBOARD;\r
1351         }\r
1352 \r
1353         return keyboard == JAPANESE_KEYBOARD;\r
1354 }\r
1355 \r
1356 void CProfile::LoadScanCodeMap(const HKEY_TYPE hkeyType)\r
1357 {\r
1358         memset(m_ScanCodeMap[hkeyType], 0, sizeof(m_ScanCodeMap[hkeyType]));\r
1359         memset(m_CurrentScanCodeMap[hkeyType], 0, sizeof(m_CurrentScanCodeMap[hkeyType]));\r
1360 \r
1361         CString szSubKey;\r
1362         CString szValueName;\r
1363         HKEY hKey = HKEY_LOCAL_MACHINE;\r
1364         if (IsNT()) {\r
1365                 switch (hkeyType) {\r
1366                 case CURRENT_USER:\r
1367                         hKey = HKEY_CURRENT_USER;\r
1368                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
1369                         break;\r
1370                 case LOCAL_MACHINE:\r
1371                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
1372                         break;\r
1373                 default:\r
1374                         return;\r
1375                 }\r
1376                 szValueName.LoadString(IDS_SCANCODE_MAP);\r
1377         } else if (Is9x()) {\r
1378                 szSubKey.LoadString(IDS_REGSUBKEY_KEY_REMAP);\r
1379                 szValueName.LoadString(IDS_0);\r
1380         } else {\r
1381                 return;\r
1382         }\r
1383 \r
1384         HKEY hkResult = NULL;\r
1385         if (RegOpenKeyEx(hKey, szSubKey, 0, KEY_QUERY_VALUE, &hkResult) == ERROR_SUCCESS) {\r
1386                 // get data size\r
1387                 DWORD dwType = REG_BINARY;\r
1388                 DWORD dwData = 0;\r
1389                 RegQueryValueEx(hkResult, szValueName, NULL, &dwType, NULL, &dwData);\r
1390 \r
1391                 // get data\r
1392                 LPBYTE lpData = new BYTE[dwData];\r
1393                 if (lpData) {\r
1394                         RegQueryValueEx(hkResult, szValueName, NULL, &dwType, lpData, &dwData);\r
1395                 }\r
1396                 RegCloseKey(hkResult);\r
1397 \r
1398                 if (IsNT()) {\r
1399                         if (lpData && dwData) {\r
1400                                 DWORD offset = 0;\r
1401                                 offset += 8;    // skip Version Information and Flags\r
1402                                 DWORD *pdwMappings = (DWORD *)(lpData + offset);\r
1403                                 offset += 4;    // skip Number of Mappings\r
1404                                 DWORD *pdwNullTerminator = (DWORD *)(lpData + dwData - 4);\r
1405 \r
1406                                 if (4 * *pdwMappings + 12 != dwData) {\r
1407                                         // illegal data\r
1408                                 } else if (*pdwNullTerminator != 0) {\r
1409                                         // illegal data\r
1410                                 } else {\r
1411                                         while (offset < dwData - 4) {\r
1412                                                 ScanCodeMapping_t *pScanCodeMapping = (ScanCodeMapping_t *)(lpData + offset);\r
1413                                                 offset += 4;    // go to next data\r
1414 \r
1415                                                 m_CurrentScanCodeMap[hkeyType][PrefixedScanCode2ID(pScanCodeMapping->original.nPrefixedScanCode)][pScanCodeMapping->original.nScanCode].nPrefixedScanCode = pScanCodeMapping->current.nPrefixedScanCode;\r
1416                                                 m_CurrentScanCodeMap[hkeyType][PrefixedScanCode2ID(pScanCodeMapping->original.nPrefixedScanCode)][pScanCodeMapping->original.nScanCode].nScanCode = pScanCodeMapping->current.nScanCode;\r
1417                                                 m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(pScanCodeMapping->original.nPrefixedScanCode)][pScanCodeMapping->original.nScanCode].nPrefixedScanCode = pScanCodeMapping->current.nPrefixedScanCode;\r
1418                                                 m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(pScanCodeMapping->original.nPrefixedScanCode)][pScanCodeMapping->original.nScanCode].nScanCode = pScanCodeMapping->current.nScanCode;\r
1419                                         }\r
1420                                 }\r
1421                         }\r
1422                 }\r
1423                 delete[] lpData;\r
1424                 lpData = NULL;\r
1425         }\r
1426 }\r
1427 \r
1428 int CProfile::LostKeyWarning(const HKEY_TYPE hkeyType)\r
1429 {\r
1430         if (!ChangedKeyboardLayout(hkeyType)) {\r
1431                 return IDOK;\r
1432         }\r
1433 \r
1434         CString szLostKeysList;\r
1435 \r
1436         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1437                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1438                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1439                                 BOOL lostKey = TRUE;\r
1440 \r
1441                                 for (int i = 0; i < 3 && lostKey; ++i) {\r
1442                                         for (int j = 0; j < 256 && lostKey; ++j) {\r
1443                                                 if (m_ScanCodeMap[hkeyType][i][j].nPrefixedScanCode == nPrefixedScanCodeID\r
1444                                                  && m_ScanCodeMap[hkeyType][i][j].nScanCode == nScanCode) {\r
1445                                                         lostKey = FALSE;\r
1446                                                 }\r
1447                                         }\r
1448                                 }\r
1449 \r
1450                                 if (lostKey) {\r
1451                                         for (int i = 0; i < sizeof(KeyboardLayouts)/sizeof(KeyboardLayouts[0]); ++i) {\r
1452                                                 if (KeyboardLayouts[i].scancode.nScanCode == nScanCode\r
1453                                                         && KeyboardLayouts[i].scancode.nPrefixedScanCode == nPrefixedScanCodeID) {\r
1454                                                         CString szLostKey;\r
1455                                                         szLostKey.Format(IDS_ERR_LOST_KEY, CString(MAKEINTRESOURCE(GetToolTipID(KeyboardLayouts[i].nToolTipID))));\r
1456                                                         szLostKeysList += szLostKey;\r
1457                                                         break;\r
1458                                                 }\r
1459                                         }\r
1460                                 }\r
1461                         }\r
1462                 }\r
1463         }\r
1464 \r
1465         if (szLostKeysList.IsEmpty()) {\r
1466                 return IDOK;\r
1467         }\r
1468 \r
1469         return AfxMessageBox(szLostKeysList, MB_OKCANCEL | MB_ICONEXCLAMATION);\r
1470 }\r
1471 \r
1472 void CProfile::SaveScanCodeMap(const HKEY_TYPE hkeyType)\r
1473 {\r
1474         CString szSubKey;\r
1475         CString szValueName;\r
1476         HKEY hKey = HKEY_LOCAL_MACHINE;\r
1477         if (IsNT()) {\r
1478                 switch (hkeyType) {\r
1479                 case CURRENT_USER:\r
1480                         hKey = HKEY_CURRENT_USER;\r
1481                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
1482                         break;\r
1483                 case LOCAL_MACHINE:\r
1484                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
1485                         break;\r
1486                 default:\r
1487                         return;\r
1488                 }\r
1489                 szValueName.LoadString(IDS_SCANCODE_MAP);\r
1490         } else if (Is9x()) {\r
1491                 szSubKey.LoadString(IDS_REGSUBKEY_KEY_REMAP);\r
1492                 szValueName.LoadString(IDS_0);\r
1493         } else {\r
1494                 return;\r
1495         }\r
1496 \r
1497         HKEY hkResult = NULL;\r
1498         if (RegCreateKeyEx(hKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkResult, NULL) == ERROR_SUCCESS) {\r
1499                 if (IsNT()) {\r
1500                         DWORD cbData = GetScanCodeLength(hkeyType);\r
1501                         if (cbData <= 16) {\r
1502                                 RegDeleteValue(hkResult, szValueName);\r
1503                         } else {\r
1504                                 LPBYTE lpData = new BYTE[cbData];\r
1505                                 memset(lpData, 0, sizeof(BYTE) * cbData);\r
1506 \r
1507                                 {\r
1508                                         DWORD dwMappings = (cbData - 12) / 4;\r
1509                                         memmove(lpData + 8, &dwMappings, 4);\r
1510                                 }\r
1511 \r
1512                                 int offset = 12;\r
1513                                 for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1514                                         for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1515                                                 if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1516                                                         ScanCodeMapping_t sScanCodeMapping = {'\0'};\r
1517                                                         sScanCodeMapping.original.nPrefixedScanCode = PrefixedScanCodeID2Code(nPrefixedScanCodeID);\r
1518                                                         sScanCodeMapping.original.nScanCode = (BYTE)nScanCode;\r
1519                                                         sScanCodeMapping.current.nPrefixedScanCode = m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode;\r
1520                                                         sScanCodeMapping.current.nScanCode = m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode;\r
1521                                                         memcpy(lpData + offset, &sScanCodeMapping, sizeof(sScanCodeMapping));\r
1522                                                         offset += sizeof(sScanCodeMapping);\r
1523                                                 }\r
1524                                         }\r
1525                                 }\r
1526                                 RegSetValueEx(hkResult, szValueName, 0, REG_BINARY, lpData, cbData);\r
1527 \r
1528                                 delete[] lpData;\r
1529                                 lpData = NULL;\r
1530                         }\r
1531                 }\r
1532                 RegCloseKey(hkResult);\r
1533         }\r
1534 \r
1535         // Do you want to restart computer?\r
1536         if (ChangedKeyboardLayout(hkeyType)) {\r
1537                 if (AfxMessageBox(CString(MAKEINTRESOURCE(IDS_RESTART_OR_NOT)), MB_YESNO | MB_ICONQUESTION) == IDYES) {\r
1538                         RestartComputer();\r
1539                 }\r
1540         }\r
1541 }\r
1542 \r
1543 // Return True if Windows 95, Windows 98, or Windows Me. \r
1544 BOOL CProfile::Is9x()\r
1545 {\r
1546         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1547         GetVersionEx(&info);\r
1548 \r
1549         if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {\r
1550                 return TRUE;\r
1551         }\r
1552         return FALSE;\r
1553 }\r
1554 \r
1555 // Return True if Windows NT 4.0, Windows 2000, Windows XP, Windows 2003 or Windows Vista.\r
1556 BOOL CProfile::IsNT()\r
1557 {\r
1558         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1559         GetVersionEx(&info);\r
1560 \r
1561         if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
1562                 return TRUE;\r
1563         }\r
1564         return FALSE;\r
1565 }\r
1566 \r
1567 // Return True if Windows Vista or later.\r
1568 BOOL CProfile::IsVistaOrLater()\r
1569 {\r
1570         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1571         GetVersionEx(&info);\r
1572 \r
1573         if (6 <= info.dwMajorVersion) {\r
1574                 return TRUE;\r
1575         }\r
1576         return FALSE;\r
1577 }\r
1578 \r
1579 void CProfile::RestartComputer()\r
1580 {\r
1581         if (!AdjustTokenPrivileges(SE_SHUTDOWN_NAME)) {\r
1582                 return;\r
1583         }\r
1584 \r
1585         ExitWindowsEx(EWX_REBOOT, 0);\r
1586 }\r
1587 \r
1588 int CProfile::GetControlID(const ScanCode_t scancode, const BOOL bBase)\r
1589 {\r
1590         for (int i = 0; ; ++i) {\r
1591                 if (KeyboardLayouts[i].scancode.nPrefixedScanCode == scancode.nPrefixedScanCode\r
1592                  && KeyboardLayouts[i].scancode.nScanCode == scancode.nScanCode) {\r
1593                         if (bBase) {\r
1594                                 return KeyboardLayouts[i].nBaseControlID;\r
1595                         } else {\r
1596                                 return KeyboardLayouts[i].nCurrentControlID;\r
1597                         }\r
1598                 }\r
1599         }\r
1600         return 0;\r
1601 }\r
1602 \r
1603 int CProfile::GetBaseControlID(const ScanCode_t scancode)\r
1604 {\r
1605         return GetControlID(scancode, TRUE);\r
1606 }\r
1607 \r
1608 int CProfile::GetCurrentControlID(const ScanCode_t scancode)\r
1609 {\r
1610         return GetControlID(scancode, FALSE);\r
1611 }\r
1612 \r
1613 BOOL CProfile::GetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCode_t original, ScanCode_t *const current)\r
1614 {\r
1615         if (!current) {\r
1616                 return FALSE;\r
1617         }\r
1618         *current = m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(original.nPrefixedScanCode)][original.nScanCode];\r
1619         return 0 < current->nScanCode;\r
1620 }\r
1621 \r
1622 void CProfile::SetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCodeMapping_t ScanCodeMappeing)\r
1623 {\r
1624         m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(ScanCodeMappeing.original.nPrefixedScanCode)][ScanCodeMappeing.original.nScanCode] = ScanCodeMappeing.current;\r
1625 }\r
1626 \r
1627 int CProfile::PrefixedScanCode2ID(const BYTE nPrefixedScanCode)\r
1628 {\r
1629         int nID = 0;\r
1630 \r
1631         switch (nPrefixedScanCode) {\r
1632         case 0x00:\r
1633                 nID = 0;\r
1634                 break;\r
1635         case 0xe0:\r
1636                 nID = 1;\r
1637                 break;\r
1638         case 0xe1:\r
1639                 nID = 2;\r
1640                 break;\r
1641         default:\r
1642                 // invalid scan code\r
1643                 nID = 3;\r
1644                 break;\r
1645         }\r
1646 \r
1647         return nID;\r
1648 }\r
1649 \r
1650 BYTE CProfile::PrefixedScanCodeID2Code(const int nPrefixedScanCodeID)\r
1651 {\r
1652         BYTE nCode = 0;\r
1653 \r
1654         switch (nPrefixedScanCodeID) {\r
1655         case 0:\r
1656                 nCode = 0x00;\r
1657                 break;\r
1658         case 1:\r
1659                 nCode = 0xe0;\r
1660                 break;\r
1661         case 2:\r
1662                 nCode = 0xe1;\r
1663                 break;\r
1664         default:\r
1665                 ASSERT(0);\r
1666                 break;\r
1667         }\r
1668 \r
1669         return nCode;\r
1670 }\r
1671 \r
1672 DWORD CProfile::GetScanCodeLength(const HKEY_TYPE hkeyType)\r
1673 {\r
1674         DWORD dwScanCodeLength = 0;\r
1675         dwScanCodeLength += 4;  // Header: Version Information\r
1676         dwScanCodeLength += 4;  // Header: Flags\r
1677         dwScanCodeLength += 4;  // Header: Number of Mappings\r
1678         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1679                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1680                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1681                                 dwScanCodeLength += 4;  // Individual Mappings\r
1682                         }\r
1683                 }\r
1684         }\r
1685         dwScanCodeLength += 4;  // Null Terminator (0x00000000)\r
1686         return dwScanCodeLength;\r
1687 }\r
1688 \r
1689 BOOL CProfile::ChangedKeyboardLayout(const HKEY_TYPE hkeyType)\r
1690 {\r
1691         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1692                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1693                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode   != m_CurrentScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode\r
1694                          || m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode                   != m_CurrentScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1695                                 return TRUE;\r
1696                         }\r
1697                 }\r
1698         }\r
1699 \r
1700         return FALSE;\r
1701 }\r
1702 \r
1703 void CProfile::SetDraggingCursor()\r
1704 {\r
1705         HCURSOR hCursor = (HCURSOR)LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDC_DRAG_CURSOR),\r
1706                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
1707         SetCursor(hCursor);\r
1708 }\r
1709 \r
1710 void CProfile::SetNormalCursor()\r
1711 {\r
1712         HCURSOR hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW),\r
1713                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
1714         SetCursor(hCursor);\r
1715 }\r
1716 \r
1717 void CProfile::SetNoCursor()\r
1718 {\r
1719         HCURSOR hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_NO),\r
1720                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
1721         SetCursor(hCursor);\r
1722 }\r
1723 \r
1724 int CProfile::GetToolTipID(int nToolTipID)\r
1725 {\r
1726         if (Is106Keyboard()) {\r
1727                 switch (nToolTipID) {\r
1728                 case IDS_EQUAL:                 // ^\r
1729                         nToolTipID = IDS_CARET;\r
1730                         break;\r
1731                 case IDS_SQUARE_BRA:    // @\r
1732                         nToolTipID = IDS_AT_MARK;\r
1733                         break;\r
1734                 case IDS_SQUARE_CKET:   // [\r
1735                         nToolTipID = IDS_SQUARE_BRA;\r
1736                         break;\r
1737                 case IDS_QUOTE:                 // :\r
1738                         nToolTipID = IDS_COLON;\r
1739                         break;\r
1740                 case IDS_BACK_QUOTE:    // Hankaku/Zenkaku\r
1741                         nToolTipID = IDS_HANKAKU;\r
1742                         break;\r
1743                 case IDS_BACKSLASH:             // ]\r
1744                         nToolTipID = IDS_SQUARE_CKET;\r
1745                         break;\r
1746                 }\r
1747         }\r
1748 \r
1749         return nToolTipID;\r
1750 }\r
1751 \r
1752 KeyboardLayout_t* CProfile::GetKeyboardLayouts(const int nKey)\r
1753 {\r
1754         for (int i = 0; i < sizeof(KeyboardLayouts) / sizeof(KeyboardLayouts[0]); ++i) {\r
1755                 if (KeyboardLayouts[i].nBaseControlID == nKey\r
1756                  || KeyboardLayouts[i].nCurrentControlID == nKey) {\r
1757                         return &KeyboardLayouts[i];\r
1758                 }\r
1759         }\r
1760         return NULL;\r
1761 }\r
1762 \r
1763 BOOL CProfile::AdjustTokenPrivileges(LPCTSTR lpName)\r
1764 {\r
1765         BOOL rc = TRUE;\r
1766 \r
1767         if (IsNT()) {\r
1768                 HANDLE hToken;\r
1769                 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
1770                         LUID luid;\r
1771                         if (LookupPrivilegeValue(NULL, lpName, &luid)) {\r
1772                                 TOKEN_PRIVILEGES tp;\r
1773                                 tp.PrivilegeCount = 1;\r
1774                                 tp.Privileges[0].Luid = luid;\r
1775                                 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
1776 \r
1777                                 if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {\r
1778                                         rc = FALSE;\r
1779                                 }\r
1780                         } else {\r
1781                                 rc = FALSE;\r
1782                         }\r
1783                         CloseHandle(hToken);\r
1784                 } else {\r
1785                         rc = FALSE;\r
1786                 }\r
1787         }\r
1788 \r
1789         return rc;\r
1790 }\r
1791 \r
1792 BOOL CProfile::DiableTokenPrivileges()\r
1793 {\r
1794         BOOL rc = TRUE;\r
1795 \r
1796         if (IsNT()) {\r
1797                 HANDLE hToken;\r
1798                 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
1799                         if (!::AdjustTokenPrivileges(hToken, TRUE, NULL, NULL, NULL, NULL)) {\r
1800                                 rc = FALSE;\r
1801                         }\r
1802                         CloseHandle(hToken);\r
1803                 } else {\r
1804                         rc = FALSE;\r
1805                 }\r
1806         }\r
1807 \r
1808         return rc;\r
1809 }\r
1810 \r
1811 void CProfile::ExportProperties()\r
1812 {\r
1813         if (!AdjustTokenPrivileges(SE_BACKUP_NAME)) {\r
1814                 return;\r
1815         }\r
1816 \r
1817         CFileDialog oFileOpenDialog(FALSE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
1818         if (oFileOpenDialog.DoModal() == IDOK) {\r
1819                 CString szCommandLine;\r
1820                 szCommandLine.Format(_T("regedit /e \"%s\" HKEY_CURRENT_USER\\%s"), oFileOpenDialog.GetPathName(), CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)));\r
1821                 CUtils::Run(szCommandLine, TRUE);       // regedit /e "x:\xkeymacs.reg" HKEY_CURRENT_USER\Software\Oishi\XKeymacs2\r
1822         }\r
1823 \r
1824         DiableTokenPrivileges();\r
1825         return;\r
1826 }\r
1827 \r
1828 void CProfile::ImportProperties()\r
1829 {\r
1830         if (!AdjustTokenPrivileges(SE_RESTORE_NAME)) {\r
1831                 return;\r
1832         }\r
1833 \r
1834         CFileDialog oFileOpenDialog(TRUE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
1835         if (oFileOpenDialog.DoModal() == IDOK) {\r
1836                 CString szCommandLine;\r
1837                 szCommandLine.Format(_T("regedit \"%s\""), oFileOpenDialog.GetPathName());\r
1838                 CUtils::Run(szCommandLine, TRUE);       // regedit "x:\xkeymacs.reg"\r
1839         }\r
1840 \r
1841         DiableTokenPrivileges();\r
1842         return;\r
1843 }\r
1844 \r
1845 BOOL CProfile::GetEnableCUA(const int nApplicationID)\r
1846 {\r
1847         return m_XkeymacsData[nApplicationID].GetEnableCUA();\r
1848 }\r
1849 \r
1850 void CProfile::SetEnableCUA(const int nApplicationID, const BOOL bEnableCUA)\r
1851 {\r
1852         m_XkeymacsData[nApplicationID].SetEnableCUA(bEnableCUA);\r
1853 }\r
1854 \r
1855 int CProfile::GetKeyboardSpeed()\r
1856 {\r
1857         int nKeyboardSpeed = 31; // default value of Windows\r
1858         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_KEYBOARD));\r
1859         CString szValueName(MAKEINTRESOURCE(IDS_KEYBOARD_SPEED));\r
1860 \r
1861         HKEY hKey = NULL;\r
1862         if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
1863                 // get data size\r
1864                 DWORD dwType = REG_SZ;\r
1865                 BYTE data[4] = {0};\r
1866                 DWORD dwcbData = sizeof(data)/sizeof(data[0]);\r
1867                 RegQueryValueEx(hKey, szValueName, NULL, &dwType, (LPBYTE)&data, &dwcbData);\r
1868                 RegCloseKey(hKey);\r
1869 \r
1870                 for (DWORD i = 0; i < dwcbData; ++i) {\r
1871                         if (data[i]) {\r
1872                                 if (i) {\r
1873                                         nKeyboardSpeed = nKeyboardSpeed * 10 + data[i] - _T('0');\r
1874                                 } else {\r
1875                                         nKeyboardSpeed = data[i] - _T('0');\r
1876                                 }\r
1877                         } else {\r
1878                                 break;\r
1879                         }\r
1880                 }\r
1881         }\r
1882 \r
1883         return nKeyboardSpeed;\r
1884 }\r