OSDN Git Service

Add KeyString class for conversion from a modifier and key code to a
[xkeymacs/xkeymacs.git] / xkeymacs / profile.cpp
1 // Profile.cpp: implementation of the CProfile class\r
2 //\r
3 //////////////////////////////////////////////////////////////////////\r
4 \r
5 #include "profile.h"\r
6 #include "imelist.h"\r
7 #include "xkeymacs.h"\r
8 #include "dotxkeymacs.h"\r
9 #include "mainfrm.h"\r
10 #include "../xkeymacsdll/xkeymacsdll.h"\r
11 #include "../xkeymacsdll/AppName.h"\r
12 #include "../xkeymacsdll/Utils.h"\r
13 #include <TlHelp32.h>\r
14 \r
15 #ifdef _DEBUG\r
16 #undef THIS_FILE\r
17 static char THIS_FILE[]=__FILE__;\r
18 #define new DEBUG_NEW\r
19 #endif\r
20 \r
21 Config CProfile::m_Config;\r
22 TCHAR CProfile::m_szAppTitle[MAX_APP][WINDOW_TEXT_LENGTH];\r
23 TASK_LIST CProfile::m_TaskList[MAX_TASKS];\r
24 DWORD CProfile::m_dwTasks;\r
25 KeyString CProfile::m_KeyString(CProfile::Is106Keyboard() != FALSE);\r
26 \r
27 // This function returns the nth string in a window name separated by " - ".\r
28 // If there aren't a sufficient number of strings, it returns the last string\r
29 // appropriate for the title.\r
30 bool CProfile::GetAppTitle(CString& appTitle, const CString& windowName, int nth)\r
31 {\r
32         const CString sep(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE));\r
33         const int nSep = windowName.Find(sep);\r
34         if (nSep < 0) {\r
35                 appTitle = windowName;\r
36                 return false;\r
37         }\r
38         if (GetAppTitle(appTitle, windowName.Right(windowName.GetLength() - nSep - sep.GetLength()), --nth) ||\r
39                         !nth || nth > 0 && appTitle.GetAt(0) != _T('[') && appTitle.FindOneOf(_T(".]")) == -1)\r
40                 return true;\r
41         appTitle = windowName.Left(nSep);\r
42         return false;\r
43 }\r
44 \r
45 BOOL CALLBACK CProfile::EnumWindowsProc(const HWND hWnd, const LPARAM lParam)\r
46 {\r
47         CProperties *pProperties = reinterpret_cast<CProperties*>(lParam);\r
48         PTASK_LIST pTask = CProfile::m_TaskList;\r
49         \r
50         TCHAR szWindowName[WINDOW_TEXT_LENGTH];\r
51         TCHAR szClassName[CLASS_NAME_LENGTH];\r
52         WINDOWPLACEMENT wpl;\r
53         \r
54         wpl.length = sizeof(WINDOWPLACEMENT);\r
55         ::GetWindowText(hWnd, szWindowName, sizeof(szWindowName));\r
56         GetClassName(hWnd, szClassName, sizeof(szClassName));\r
57 \r
58         CString appTitle;\r
59         // Get Process Name\r
60         DWORD dwProcessId = 0;\r
61         GetWindowThreadProcessId(hWnd, &dwProcessId);\r
62         DWORD i;\r
63         for (i = 0; i < CProfile::m_dwTasks; ++i) {\r
64                 if (pTask[i].dwProcessId == dwProcessId) {\r
65 \r
66                         // Get Application Name\r
67                         if (szWindowName[0] == '\0') {\r
68                                 continue;\r
69                         }\r
70                         if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_B2)), sizeof(pTask[i].ProcessName))) {\r
71                                 appTitle.LoadString(IDS_BECKY);\r
72                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXPLORER)), sizeof(pTask[i].ProcessName))) {\r
73                                 appTitle.LoadString(IDS_PROGRAM_MANAGER);\r
74                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSIMN)), sizeof(pTask[i].ProcessName))) {\r
75                                 appTitle.LoadString(IDS_OUTLOOK_EXPRESS);\r
76                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_PROJECT)), sizeof(pTask[i].ProcessName))\r
77                                         || !_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXCEL)), sizeof(pTask[i].ProcessName))\r
78                                         || !_tcsnicmp(pTask[i].ProcessName, _T("psp.exe"), sizeof(pTask[i].ProcessName))) {\r
79                                 GetAppTitle(appTitle, szWindowName, 1);\r
80                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sakura.exe"), sizeof(pTask[i].ProcessName))) {\r
81                                 GetAppTitle(appTitle, szWindowName, 2); // '.' is included, so...\r
82                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSDN)), sizeof(pTask[i].ProcessName))) {\r
83                                 appTitle = szWindowName;\r
84                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("devenv.exe"), sizeof(pTask[i].ProcessName))) {\r
85                                 appTitle.Format(_T("Microsoft Visual Studio .NET"));\r
86                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vb6.exe"), sizeof(pTask[i].ProcessName))) {\r
87                                 appTitle.Format(_T("Microsoft Visual Basic"));\r
88                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("ssexp.exe"), sizeof(pTask[i].ProcessName))) {\r
89                                 appTitle.LoadString(IDS_VISUAL_SOURCESAFE_EXPLORER);\r
90                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sh.exe"), sizeof(pTask[i].ProcessName))) {\r
91                                 appTitle.Format(_T("MKS Korn Shell"));\r
92                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("csh.exe"), sizeof(pTask[i].ProcessName))) {\r
93                                 appTitle.Format(_T("C Shell"));\r
94                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vim.exe"), sizeof(pTask[i].ProcessName))) {\r
95                                 appTitle.Format(_T("VIM"));\r
96                         } else {\r
97                                 AppName::CorrectAppName(szWindowName, pTask[i].ProcessName);\r
98                                 GetAppTitle(appTitle, szWindowName);\r
99                         }\r
100                         break;\r
101                 }\r
102         }\r
103         \r
104         if (IsWindowVisible(hWnd) && // Is visible?\r
105                         GetWindow(hWnd, GW_OWNER) == NULL && // Is top level window?\r
106                         lstrlen(szWindowName) > 0) { // Have caption?\r
107                 pProperties->AddItem(appTitle, pTask[i].ProcessName);\r
108         }\r
109         return TRUE;\r
110 }\r
111 \r
112 void CProfile::LoadRegistry()\r
113 {\r
114         bool bDialog = false;\r
115         const CString section(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION));    \r
116         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
117                 CString entry;\r
118                 entry.Format(IDS_REG_ENTRY_APPLICATION, nAppID);\r
119                 CString appName = AfxGetApp()->GetProfileString(section, entry);\r
120                 if (appName.IsEmpty())  {\r
121                         if (nAppID) {\r
122                                 if (bDialog)\r
123                                         continue;\r
124                                 appName.LoadString(IDS_DIALOG);\r
125                                 bDialog = true;\r
126                         } else\r
127                                 appName.LoadString(IDS_DEFAULT);\r
128                 } else if (appName == CString(MAKEINTRESOURCE(IDS_DIALOG)))\r
129                         bDialog = true;\r
130                 _tcsncpy_s(m_Config.szSpecialApp[nAppID], appName, _TRUNCATE);\r
131                 entry.LoadString(IDS_REG_ENTRY_APPLICATOIN_TITLE);\r
132                 _tcsncpy_s(m_szAppTitle[nAppID], AfxGetApp()->GetProfileString(appName, entry), _TRUNCATE);\r
133                 entry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT);\r
134                 _tcsncpy_s(m_Config.szWindowText[nAppID], AfxGetApp()->GetProfileString(appName, entry, _T("*")), _TRUNCATE);\r
135 \r
136                 const CString regApp = CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)) + _T("\\") + appName;\r
137                 for (BYTE nComID = 1; nComID < MAX_COMMAND; ++nComID) {\r
138                         entry = CCommands::GetCommandName(nComID);\r
139                         HKEY hKey;\r
140                         const CString regKey = regApp + _T("\\") + entry;\r
141                         if (RegOpenKeyEx(HKEY_CURRENT_USER, regKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
142                                 TCHAR szKeyBind[128];\r
143                                 DWORD dwKeyBind = _countof(szKeyBind);\r
144                                 for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++dwIndex) {\r
145                                         int nType, nKey;\r
146                                         StringToKey(szKeyBind, nType, nKey);\r
147                                         m_Config.nCommandID[nAppID][nType][nKey] = nComID;\r
148                                         dwKeyBind = _countof(szKeyBind);\r
149                                 }\r
150                                 RegCloseKey(hKey);\r
151                         } else {\r
152                                 // Set the default assignment\r
153                                 for (int i = 0; const int nKey = CCommands::GetDefaultCommandKey(nComID, i); ++i) {\r
154                                         if (CCommands::GetDefaultControlID(nComID, i) == IDC_CO2)\r
155                                                 continue;\r
156                                         const int nType = CCommands::GetDefaultCommandType(nComID, i);\r
157                                         m_Config.nCommandID[nAppID][nType][nKey] = nComID;\r
158                                 }\r
159                         }\r
160                 }\r
161                 for (int nFuncID = 0; nFuncID < CDotXkeymacs::GetFunctionNumber(); ++nFuncID) {\r
162                         HKEY hKey;\r
163                         const CString regKey = regApp + _T("\\") + CDotXkeymacs::GetFunctionSymbol(nFuncID);\r
164                         if (RegOpenKeyEx(HKEY_CURRENT_USER, regKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
165                                 CDotXkeymacs::ClearKey(nFuncID, nAppID);\r
166                                 TCHAR szKeyBind[128];\r
167                                 DWORD dwKeyBind = _countof(szKeyBind);\r
168                                 for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++dwIndex) {\r
169                                         int nType, nKey;\r
170                                         StringToKey(szKeyBind, nType, nKey);\r
171                                         CDotXkeymacs::SetKey(nFuncID, nAppID, nType, nKey);\r
172                                         dwKeyBind = _countof(szKeyBind);\r
173                                 }\r
174                                 RegCloseKey(hKey);\r
175                         }\r
176                 }\r
177 \r
178                 entry.LoadString(IDS_REG_ENTRY_KILL_RING_MAX);\r
179                 int n = AfxGetApp()->GetProfileInt(appName, entry, 1);\r
180                 m_Config.nKillRingMax[nAppID] = static_cast<BYTE>(n > 255 ? 255 : n);\r
181                 entry.LoadString(IDS_REG_ENTRY_USE_DIALOG_SETTING);\r
182                 m_Config.bUseDialogSetting[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 1));\r
183                 entry.LoadString(IDS_REG_ENTRY_DISABLE_XKEYMACS);\r
184                 m_Config.nSettingStyle[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 0) ? SETTING_DISABLE : SETTING_SPECIFIC);\r
185                 entry.LoadString(IDC_REG_ENTRY_IGNORE_META_CTRL);\r
186                 m_Config.bIgnoreUndefinedMetaCtrl[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 0));\r
187                 entry.LoadString(IDC_REG_ENTRY_IGNORE_C_X);\r
188                 m_Config.bIgnoreUndefinedC_x[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 0));\r
189                 entry.LoadString(IDC_REG_ENTRY_ENABLE_CUA);\r
190                 m_Config.bEnableCUA[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 0));\r
191                 entry.LoadString(IDS_REG_ENTRY_326_COMPATIBLE);\r
192                 m_Config.b326Compatible[nAppID] = static_cast<BYTE>(AfxGetApp()->GetProfileInt(appName, entry, 0));\r
193         }\r
194 }\r
195 \r
196 void CProfile::SaveRegistry()\r
197 {\r
198         const CString section(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION));    \r
199         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
200                 const LPCTSTR szAppName = m_Config.szSpecialApp[nAppID];\r
201                 CString entry;\r
202                 entry.Format(IDS_REG_ENTRY_APPLICATION, nAppID);\r
203                 if (!szAppName[0]) {\r
204                         if (!AfxGetApp()->GetProfileString(section, entry).IsEmpty())\r
205                                 AfxGetApp()->WriteProfileString(section, entry, _T(""));\r
206                         continue;\r
207                 }\r
208                 AfxGetApp()->WriteProfileString(section, entry, szAppName);\r
209 \r
210                 entry.LoadString(IDS_REG_ENTRY_APPLICATOIN_TITLE);\r
211                 CString appTitle = m_szAppTitle[nAppID];\r
212                 appTitle.TrimLeft(_T(' '));\r
213                 AfxGetApp()->WriteProfileString(szAppName, entry, appTitle);\r
214                 entry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT);\r
215                 AfxGetApp()->WriteProfileString(szAppName, entry, m_Config.szWindowText[nAppID]);\r
216 \r
217                 // Create all commands\r
218                 for (int nComID = 1; nComID < MAX_COMMAND; ++nComID)\r
219                         SaveKeyBind(szAppName, nComID, 0, 0);\r
220                 for (int nType = 0; nType < MAX_COMMAND_TYPE; ++nType)\r
221                         for (int nKey = 0; nKey < MAX_KEY; ++nKey)\r
222                                 SaveKeyBind(szAppName, m_Config.nCommandID[nAppID][nType][nKey], nType, nKey);\r
223                 for (int nFuncID = 0; nFuncID < CDotXkeymacs::GetFunctionNumber(); ++nFuncID)\r
224                         for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFuncID, nAppID); ++nKeyID) {\r
225                                 int nType, nKey;\r
226                                 CDotXkeymacs::GetKey(nFuncID, nAppID, nKeyID, &nType, &nKey);\r
227                                 SaveKeyBind(szAppName, CDotXkeymacs::GetFunctionSymbol(nFuncID), nType, nKey);\r
228                         }\r
229 \r
230                 entry.LoadString(IDS_REG_ENTRY_KILL_RING_MAX);\r
231                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.nKillRingMax[nAppID]);\r
232                 entry.LoadString(IDS_REG_ENTRY_USE_DIALOG_SETTING);\r
233                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.bUseDialogSetting[nAppID]);\r
234                 entry.LoadString(IDS_REG_ENTRY_DISABLE_XKEYMACS);\r
235                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.nSettingStyle[nAppID] == SETTING_DISABLE);\r
236                 entry.LoadString(IDC_REG_ENTRY_IGNORE_META_CTRL);\r
237                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.bIgnoreUndefinedMetaCtrl[nAppID]);\r
238                 entry.LoadString(IDC_REG_ENTRY_IGNORE_C_X);\r
239                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.bIgnoreUndefinedC_x[nAppID]);\r
240                 entry.LoadString(IDC_REG_ENTRY_ENABLE_CUA);\r
241                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.bEnableCUA[nAppID]);\r
242                 entry.LoadString(IDS_REG_ENTRY_326_COMPATIBLE);\r
243                 AfxGetApp()->WriteProfileInt(szAppName, entry, m_Config.b326Compatible[nAppID]);\r
244         }\r
245 }\r
246 \r
247 void CProfile::LoadData()\r
248 {\r
249         CDotXkeymacs::Load();\r
250         LevelUp();\r
251         LoadRegistry();\r
252 }\r
253 \r
254 void CProfile::SaveData()\r
255 {\r
256         DeleteAllRegistryData();\r
257         SaveRegistry();\r
258         SetDllData();\r
259 }\r
260 \r
261 void CProfile::SetDllData()\r
262 {\r
263         memset(m_Config.nFunctionID, -1, sizeof(m_Config.nFunctionID));\r
264         for (int nFuncID = 0; nFuncID < CDotXkeymacs::GetFunctionNumber(); ++nFuncID)\r
265                 _tcscpy_s(m_Config.szFunctionDefinition[nFuncID], CDotXkeymacs::GetFunctionDefinition(nFuncID));\r
266 \r
267         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
268                 m_Config.nCommandID[nAppID][CONTROL]['X'] = 0; // C-x is unassigned.\r
269                 for (int nType = 0; nType < MAX_COMMAND_TYPE; ++nType)\r
270                         for (int nKey = 0; nKey < MAX_KEY; ++nKey)\r
271                                 if ((nType & CONTROLX) && m_Config.nCommandID[nAppID][nType][nKey])\r
272                                         m_Config.nCommandID[nAppID][CONTROL]['X'] = 1; // C-x is available.\r
273                 for (BYTE nFuncID = 0; nFuncID < CDotXkeymacs::GetFunctionNumber(); ++nFuncID)\r
274                         for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFuncID, nAppID); ++nKeyID) {\r
275                                 int nType, nKey;\r
276                                 CDotXkeymacs::GetKey(nFuncID, nAppID, nKeyID, &nType, &nKey);\r
277                                 m_Config.nFunctionID[nAppID][nType][nKey] = nFuncID;\r
278                                 if (nType & CONTROLX)\r
279                                         m_Config.nCommandID[nAppID][CONTROL]['X'] = 1; // C-x is available.\r
280                         }\r
281         }\r
282         m_Config.b106Keyboard = static_cast<BYTE>(Is106Keyboard());\r
283         CXkeymacsDll::SetConfig(m_Config);\r
284         CXkeymacsApp *pApp = static_cast<CXkeymacsApp *>(AfxGetApp());\r
285         if (!pApp->IsWow64())\r
286                 return;\r
287         if (!CXkeymacsDll::SaveConfig())\r
288                 return;\r
289         pApp->SendIPCMessage(XKEYMACS_RELOAD);\r
290 }\r
291 \r
292 void CProfile::SaveKeyBind(const LPCTSTR appName, int comID, int type, int key)\r
293 {\r
294         if (!comID)\r
295                 return;\r
296         LPCTSTR comName = CCommands::GetCommandName(comID);\r
297         if (!comName[0])\r
298                 return;\r
299         SaveKeyBind(appName, comName, type, key);\r
300 }\r
301 \r
302 void CProfile::SaveKeyBind(const LPCTSTR appName, const LPCTSTR comName, int type, int key)\r
303 {\r
304         CString subKey = CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)) + _T("\\") + appName + _T("\\") + comName;\r
305         CString s = KeyToString(type, key);\r
306         if (!s.IsEmpty())\r
307                 subKey = subKey + _T("\\") + s;\r
308         HKEY hKey = NULL;\r
309         if (RegCreateKeyEx(HKEY_CURRENT_USER, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)\r
310                 RegCloseKey(hKey);\r
311 }\r
312 \r
313 void CProfile::StringToKey(const LPCTSTR str, int& type, int& key)\r
314 {\r
315         m_KeyString.ToKey(str, type, key);\r
316 }\r
317 \r
318 CString CProfile::KeyToString(int type, int key)\r
319 {\r
320         return m_KeyString.ToString(type, key);\r
321 }\r
322 \r
323 void CProfile::AddKeyBind2C_(const LPCSTR szAppName, const BYTE bVk)\r
324 {\r
325         int nComID;\r
326         for (nComID = 0; nComID < MAX_COMMAND; ++nComID)\r
327                 if (Commands[nComID].fCommand == CCommands::C_)\r
328                         break;\r
329         SaveKeyBind(szAppName, nComID, NONE, bVk);\r
330 }\r
331 \r
332 void CProfile::LevelUp()\r
333 {\r
334         const int nCurrentLevel = AfxGetApp()->GetProfileInt(_T(""), _T("Level"), 0);\r
335         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
336                 CString entry;\r
337                 entry.Format(IDS_REG_ENTRY_APPLICATION, nAppID);\r
338                 const CString appName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), entry);\r
339                 if (appName.IsEmpty())\r
340                         continue;\r
341                 switch (nCurrentLevel) {\r
342                 case 0:\r
343                         AddKeyBind2C_(appName, VK_LCONTROL);\r
344                         AddKeyBind2C_(appName, VK_RCONTROL);\r
345                 // fall through\r
346                 case 1:\r
347                         // Set kill-ring-max 1 if it is 0.\r
348                         if (!AfxGetApp()->GetProfileInt(appName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 0))\r
349                                 AfxGetApp()->WriteProfileInt(appName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 1);\r
350                 // fall through\r
351                 case 2:\r
352                         {\r
353                                 // Chaged a label from Enter to newline.\r
354                                 const CString subKey = CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)) + _T("\\") + appName;\r
355                                 const CString srcKey = subKey + _T("\\") + _T("Enter");\r
356                                 const CString dstKey = subKey + _T("\\") + _T("newline");\r
357                                 HKEY hDstKey = NULL;\r
358                                 if (RegCreateKeyEx(HKEY_CURRENT_USER, dstKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hDstKey, NULL) == ERROR_SUCCESS) {\r
359                                         SHCopyKey(HKEY_CURRENT_USER, srcKey, hDstKey, NULL);\r
360                                         SHDeleteKey(HKEY_CURRENT_USER, srcKey);\r
361                                         RegCloseKey(hDstKey);\r
362                                 }\r
363                         }\r
364                 // fall through\r
365                 case 3:\r
366                         // rename original function to remove IDS_REG_ORIGINAL_PREFIX\r
367                         for (int nFuncID = 0; nFuncID < CDotXkeymacs::GetFunctionNumber(); ++nFuncID) {\r
368                                 HKEY hKey = NULL;\r
369                                 const CString subKey = CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)) + _T("\\") + appName + _T("\\") + CString(MAKEINTRESOURCE(IDS_REG_ORIGINAL_PREFIX)) + CDotXkeymacs::GetFunctionSymbol(nFuncID);\r
370                                 if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
371                                         // Use registry data\r
372                                         TCHAR szKeyBind[128];\r
373                                         DWORD dwKeyBind = sizeof(szKeyBind);\r
374                                         for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++dwIndex) {\r
375                                                 int nType, nKey;\r
376                                                 StringToKey(szKeyBind, nType, nKey);\r
377                                                 SaveKeyBind(appName, CDotXkeymacs::GetFunctionSymbol(nFuncID), nType, nKey);\r
378                                                 dwKeyBind = sizeof(szKeyBind);\r
379                                         }\r
380                                         RegCloseKey(hKey);\r
381                                 }\r
382                         }\r
383                 }\r
384         }\r
385         AfxGetApp()->WriteProfileInt(_T(""), _T("Level"), 4);\r
386 }\r
387 \r
388 void CProfile::InitDllData()\r
389 {\r
390         LoadData();\r
391         SetDllData();\r
392 }\r
393 \r
394 void CProfile::ClearData(const CString szCurrentApplication)\r
395 {\r
396         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID)\r
397                 if (szCurrentApplication == m_Config.szSpecialApp[nAppID]) {\r
398                         ZeroMemory(m_Config.nCommandID[nAppID], sizeof(m_Config.nCommandID[nAppID]));\r
399                         ZeroMemory(m_Config.szSpecialApp[nAppID], CLASS_NAME_LENGTH);\r
400                         return;\r
401                 }\r
402 }\r
403 \r
404 // return count of saved settings\r
405 int CProfile::GetSavedSettingCount()\r
406 {\r
407         int nSavedSetting = 0;\r
408         for (int nAppID = 0; nAppID < MAX_APP; ++nAppID)\r
409                 if (m_Config.szSpecialApp[nAppID][0])\r
410                         ++nSavedSetting;\r
411         return nSavedSetting;\r
412 }\r
413 \r
414 void CProfile::InitAppList(CProperties& cProperties)\r
415 {\r
416         GetTaskList();\r
417 \r
418         EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&cProperties));\r
419 \r
420         for (int i = 0; i < MAX_APP; ++i) {\r
421                 const LPCTSTR szAppName = m_Config.szSpecialApp[i];\r
422                 const LPCTSTR szAppTitle = m_szAppTitle[i];\r
423                 if (!szAppName[0] || !_tcscmp(szAppName, _T("IME")))\r
424                         continue;\r
425                 if (CString(MAKEINTRESOURCE(IDS_DEFAULT)) == szAppName ||\r
426                                 CString(MAKEINTRESOURCE(IDS_DIALOG)) == szAppName)\r
427                         continue;\r
428                 cProperties.AddItem(szAppTitle, szAppName);\r
429         }\r
430         AddIMEInfo(cProperties);\r
431 }\r
432 \r
433 void CProfile::AddIMEInfo(CProperties& cProperties)\r
434 {\r
435         IMEList imeList;\r
436         for (IMEListIterator p = imeList.begin(); p != imeList.end(); ++p)\r
437                 cProperties.AddItem(p->szDescription, p->szFileName);\r
438 }\r
439 \r
440 void CProfile::GetTaskList()\r
441 {\r
442         ZeroMemory(m_TaskList, sizeof(m_TaskList));\r
443 \r
444         HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
445         if (hProcessSnap == (HANDLE)-1)\r
446                 return;\r
447 \r
448         m_dwTasks = 0;\r
449         PROCESSENTRY32 processEntry32 = {sizeof(PROCESSENTRY32)};\r
450         if (Process32First(hProcessSnap, &processEntry32)) {\r
451                 do {\r
452                         lstrcpy(m_TaskList[m_dwTasks].ProcessName, processEntry32.szExeFile);\r
453                         m_TaskList[m_dwTasks++].dwProcessId = processEntry32.th32ProcessID;\r
454                 } while (m_dwTasks < MAX_TASKS && Process32Next(hProcessSnap, &processEntry32));\r
455         }\r
456 \r
457         CloseHandle(hProcessSnap);\r
458 }\r
459 \r
460 int CProfile::DefaultAppID()\r
461 {\r
462         const CString name(MAKEINTRESOURCE(IDS_DEFAULT));\r
463         for(int nAppID = 0; nAppID < MAX_APP; ++nAppID)\r
464                 if (name == m_Config.szSpecialApp[nAppID])\r
465                         return nAppID;\r
466         return MAX_APP;\r
467 }\r
468 \r
469 int CProfile::AssignAppID(const LPCSTR szAppName)\r
470 {\r
471         int nAppID = GetAppID(szAppName);\r
472         if (nAppID != MAX_APP)\r
473                 return nAppID;\r
474         for (nAppID = 0; nAppID < MAX_APP; ++nAppID)\r
475                 if (!m_Config.szSpecialApp[nAppID][0]) {\r
476                         _tcsncpy_s(m_Config.szSpecialApp[nAppID], szAppName, _TRUNCATE);\r
477                         return nAppID;\r
478                 }\r
479         return nAppID;\r
480 }\r
481 \r
482 int CProfile::GetSettingStyle(const int nAppID)\r
483 {\r
484         if (nAppID == MAX_APP)\r
485                 return SETTING_DEFAULT;\r
486         return m_Config.nSettingStyle[nAppID];\r
487 }\r
488 \r
489 void CProfile::SetSettingStyle(int nAppID, int nSettingStyle)\r
490 {\r
491         if (nAppID == MAX_APP)\r
492                 return;\r
493         m_Config.nSettingStyle[nAppID] = static_cast<BYTE>(nSettingStyle);\r
494 }\r
495 \r
496 BOOL CProfile::Is106Keyboard()\r
497 {\r
498         static KEYBOARD_TYPE keyboard = UNKNOWN_KEYBOARD;\r
499 \r
500         if (keyboard == UNKNOWN_KEYBOARD) {\r
501                 OSVERSIONINFO verInfo = {0};\r
502                 verInfo.dwOSVersionInfoSize = sizeof (verInfo);\r
503                 GetVersionEx(&verInfo);\r
504 \r
505                 DWORD subtype = 0;\r
506                 DWORD cbData = sizeof(subtype);\r
507 \r
508                 if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
509                         HKEY hKey = NULL;\r
510                         CString szSubKey(_T("SYSTEM\\CurrentControlSet\\Services\\i8042prt\\Parameters"));\r
511                         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
512                                 static const CString szValueName(_T("OverrideKeyboardSubtype"));\r
513                                 if (RegQueryValueEx(hKey, szValueName, NULL, NULL, (LPBYTE)&subtype, &cbData) != ERROR_SUCCESS) {\r
514                                         subtype = 0;\r
515                                 }\r
516                                 RegCloseKey(hKey);\r
517                         }\r
518                 } else if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {\r
519                         subtype = GetPrivateProfileInt(_T("keyboard"), _T("subtype"), 0, _T("system.ini"));\r
520                 }\r
521 \r
522                 keyboard = (subtype & 0x02) ? JAPANESE_KEYBOARD : ENGLISH_KEYBOARD;\r
523         }\r
524 \r
525         return keyboard == JAPANESE_KEYBOARD;\r
526 }\r
527 \r
528 void CProfile::SetAppTitle(const int nAppID, const CString& appTitle)\r
529 {\r
530         _tcsncpy_s(m_szAppTitle[nAppID], appTitle, _TRUNCATE);\r
531 }\r
532 \r
533 void CProfile::SetCommandID(const int nAppID, const int nType, const int nKey, int nComID)\r
534 {\r
535         if (nKey == 0xf0 && Commands[nComID].fCommand == CCommands::C_)\r
536                 // Change CommandID C_Eisu\r
537                 for (nComID = 1; nComID < MAX_COMMAND; ++nComID)\r
538                         if (Commands[nComID].fCommand == CCommands::C_Eisu)\r
539                                 break;\r
540         m_Config.nCommandID[nAppID][nType][nKey] = static_cast<BYTE>(nComID);\r
541 }\r
542 \r
543 int CProfile::GetCommandID(const int nAppID, const int nType, const int nKey)\r
544 {\r
545         int nComID = m_Config.nCommandID[nAppID][nType][nKey];\r
546         if (nKey == 0xf0 && Commands[nComID].fCommand == CCommands::C_Eisu)\r
547                 // Change CommandID C_\r
548                 for (nComID = 1; nComID < MAX_COMMAND; nComID++)\r
549                         if (Commands[nComID].fCommand == CCommands::C_)\r
550                                 break;\r
551         return nComID;\r
552 }\r
553 \r
554 void CProfile::SetKillRingMax(const int nAppID, const int nKillRingMax)\r
555 {\r
556         m_Config.nKillRingMax[nAppID] = static_cast<BYTE>(nKillRingMax > 255 ? 255 : nKillRingMax);\r
557 }\r
558 \r
559 int CProfile::GetKillRingMax(const int nAppID)\r
560 {\r
561         return m_Config.nKillRingMax[nAppID];\r
562 }\r
563 \r
564 void CProfile::SetUseDialogSetting(const int nAppID, const BOOL bUseDialogSetting)\r
565 {\r
566         m_Config.bUseDialogSetting[nAppID] = static_cast<BYTE>(bUseDialogSetting);\r
567 }\r
568 \r
569 BOOL CProfile::GetUseDialogSetting(const int nAppID)\r
570 {\r
571         return m_Config.bUseDialogSetting[nAppID];\r
572 }\r
573 \r
574 void CProfile::SetWindowText(const int nAppID, const CString szWindowText)\r
575 {\r
576         if (CUtils::GetWindowTextType(szWindowText) == IDS_WINDOW_TEXT_IGNORE)\r
577                 _tcscpy_s(m_Config.szWindowText[nAppID], _T("*"));\r
578         else\r
579                 _tcsncpy_s(m_Config.szWindowText[nAppID], szWindowText, _TRUNCATE);\r
580 }\r
581 \r
582 CString CProfile::GetWindowText(const int nAppID)\r
583 {\r
584         return m_Config.szWindowText[nAppID];\r
585 }\r
586 \r
587 void CProfile::DeleteAllRegistryData()\r
588 {\r
589         HKEY hkey = NULL;\r
590         if (RegOpenKeyEx(HKEY_CURRENT_USER, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)), 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) {\r
591                 // I am sure that I have to do only one time, but...\r
592                 for (int nAppID = 0; nAppID < MAX_APP; ++nAppID) {\r
593                         DWORD dwIndex = 0;\r
594                         TCHAR szName[SUB_KEY_NAME_LENGTH] = {'\0'};\r
595                         DWORD dwName = sizeof(szName);\r
596                         FILETIME filetime;\r
597 \r
598                         while (RegEnumKeyEx(hkey, dwIndex++, szName, &dwName, NULL, NULL, NULL, &filetime) == ERROR_SUCCESS) {\r
599 //                              RegDeleteKey(hkey, szName);\r
600                                 SHDeleteKey(hkey, szName);\r
601                                 ZeroMemory(szName, sizeof(szName));\r
602                                 dwName = sizeof(szName);\r
603                         }\r
604                 }\r
605                 RegCloseKey(hkey);\r
606         }\r
607 }\r
608 \r
609 void CProfile::CopyData(const CString szDstApp, const CString szSrcApp)\r
610 {\r
611         const int nDstApp = AssignAppID(szDstApp);\r
612         const int nSrcApp = GetAppID(szSrcApp);\r
613         if (nDstApp == MAX_APP || nSrcApp == MAX_APP)\r
614                 return;\r
615         SetSettingStyle(nDstApp, SETTING_SPECIFIC);\r
616 \r
617 #define CopyMember(member) CopyMemory(&m_Config. ## member ## [nDstApp], &m_Config. ## member ## [nSrcApp], sizeof(m_Config. ## member ## [nSrcApp]))\r
618         CopyMember(b326Compatible);\r
619         CopyMember(nFunctionID);\r
620         CopyMember(bEnableCUA);\r
621         CopyMember(bUseDialogSetting);\r
622         CopyMember(bIgnoreUndefinedC_x);\r
623         CopyMember(bIgnoreUndefinedMetaCtrl);\r
624         CopyMember(nKillRingMax);\r
625         CopyMember(nCommandID);\r
626 #undef CopyMember\r
627 }\r
628 \r
629 // return application index\r
630 // if there is NOT the application in the data, return MAX_APP\r
631 int CProfile::GetAppID(const LPCSTR szAppName)\r
632 {\r
633         int nAppID = 0;\r
634         for (nAppID = 0; nAppID < MAX_APP; ++nAppID)\r
635                 if (!_tcscmp(szAppName, m_Config.szSpecialApp[nAppID]))\r
636                         break;\r
637         return nAppID;\r
638 }\r
639 \r
640 // Return True if Windows Vista or later.\r
641 BOOL CProfile::IsVistaOrLater()\r
642 {\r
643         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
644         GetVersionEx(&info);\r
645 \r
646         if (6 <= info.dwMajorVersion) {\r
647                 return TRUE;\r
648         }\r
649         return FALSE;\r
650 }\r
651 \r
652 void CProfile::RestartComputer()\r
653 {\r
654         if (!AdjustTokenPrivileges(SE_SHUTDOWN_NAME)) {\r
655                 return;\r
656         }\r
657 \r
658         ExitWindowsEx(EWX_REBOOT, 0);\r
659 }\r
660 \r
661 BOOL CProfile::AdjustTokenPrivileges(LPCTSTR lpName)\r
662 {\r
663         BOOL rc = TRUE;\r
664 \r
665         HANDLE hToken;\r
666         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
667                 LUID luid;\r
668                 if (LookupPrivilegeValue(NULL, lpName, &luid)) {\r
669                         TOKEN_PRIVILEGES tp;\r
670                         tp.PrivilegeCount = 1;\r
671                         tp.Privileges[0].Luid = luid;\r
672                         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
673 \r
674                         if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {\r
675                                 rc = FALSE;\r
676                         }\r
677                 } else {\r
678                         rc = FALSE;\r
679                 }\r
680                 CloseHandle(hToken);\r
681         } else {\r
682                 rc = FALSE;\r
683         }\r
684 \r
685         return rc;\r
686 }\r
687 \r
688 BOOL CProfile::DiableTokenPrivileges()\r
689 {\r
690         BOOL rc = TRUE;\r
691 \r
692         HANDLE hToken;\r
693         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
694                 if (!::AdjustTokenPrivileges(hToken, TRUE, NULL, NULL, NULL, NULL)) {\r
695                         rc = FALSE;\r
696                 }\r
697                 CloseHandle(hToken);\r
698         } else {\r
699                 rc = FALSE;\r
700         }\r
701 \r
702         return rc;\r
703 }\r
704 \r
705 void CProfile::ExportProperties()\r
706 {\r
707         if (!AdjustTokenPrivileges(SE_BACKUP_NAME)) {\r
708                 return;\r
709         }\r
710 \r
711         CFileDialog oFileOpenDialog(FALSE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
712         if (oFileOpenDialog.DoModal() == IDOK) {\r
713                 CString szCommandLine;\r
714                 szCommandLine.Format(_T("regedit /e \"%s\" HKEY_CURRENT_USER\\%s"), oFileOpenDialog.GetPathName(), CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)));\r
715                 CUtils::Run(szCommandLine, TRUE);       // regedit /e "x:\xkeymacs.reg" HKEY_CURRENT_USER\Software\Oishi\XKeymacs2\r
716         }\r
717 \r
718         DiableTokenPrivileges();\r
719         return;\r
720 }\r
721 \r
722 void CProfile::ImportProperties()\r
723 {\r
724         if (!AdjustTokenPrivileges(SE_RESTORE_NAME)) {\r
725                 return;\r
726         }\r
727 \r
728         CFileDialog oFileOpenDialog(TRUE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
729         if (oFileOpenDialog.DoModal() == IDOK) {\r
730                 CString szCommandLine;\r
731                 szCommandLine.Format(_T("regedit \"%s\""), oFileOpenDialog.GetPathName());\r
732                 CUtils::Run(szCommandLine, TRUE);       // regedit "x:\xkeymacs.reg"\r
733         }\r
734 \r
735         DiableTokenPrivileges();\r
736         return;\r
737 }\r
738 \r
739 BOOL CProfile::GetEnableCUA(const int nAppID)\r
740 {\r
741         return m_Config.bEnableCUA[nAppID];\r
742 }\r
743 \r
744 void CProfile::SetEnableCUA(const int nAppID, const BOOL bEnableCUA)\r
745 {\r
746         m_Config.bEnableCUA[nAppID] = static_cast<BYTE>(bEnableCUA);\r
747 }\r
748 \r
749 int CProfile::GetKeyboardSpeed()\r
750 {\r
751         int nKeyboardSpeed = 31; // default value of Windows\r
752         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_KEYBOARD));\r
753         CString szValueName(MAKEINTRESOURCE(IDS_KEYBOARD_SPEED));\r
754 \r
755         HKEY hKey = NULL;\r
756         if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
757                 // get data size\r
758                 DWORD dwType = REG_SZ;\r
759                 BYTE data[4] = {0};\r
760                 DWORD dwcbData = sizeof(data)/sizeof(data[0]);\r
761                 RegQueryValueEx(hKey, szValueName, NULL, &dwType, (LPBYTE)&data, &dwcbData);\r
762                 RegCloseKey(hKey);\r
763 \r
764                 for (DWORD i = 0; i < dwcbData; ++i) {\r
765                         if (data[i]) {\r
766                                 if (i) {\r
767                                         nKeyboardSpeed = nKeyboardSpeed * 10 + data[i] - _T('0');\r
768                                 } else {\r
769                                         nKeyboardSpeed = data[i] - _T('0');\r
770                                 }\r
771                         } else {\r
772                                 break;\r
773                         }\r
774                 }\r
775         }\r
776 \r
777         return nKeyboardSpeed;\r
778 }\r