OSDN Git Service

Use MAX_COMMAND and MAX_KEY_BIND.
[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 struct CommandTypeName\r
21 {\r
22         int nCommandType;\r
23         LPCTSTR szCommandTypeName;\r
24 };\r
25 \r
26 static const CommandTypeName CommandTypes[] = {\r
27         {NONE,                                                  _T("")},\r
28         {SHIFT,                                                 _T("Shift+")},\r
29         {CONTROL,                                               _T("Ctrl+")},\r
30         {CONTROL+SHIFT,                                 _T("Ctrl+Shift+")},\r
31         {META,                                                  _T("Meta+")},\r
32         {META+SHIFT,                                    _T("Meta+Shift+")},\r
33         {CONTROL+META,                                  _T("Ctrl+Meta+")},\r
34         {CONTROL+META+SHIFT,                    _T("Ctrl+Meta+Shift+")},\r
35         {CONTROLX+NONE,                                 _T("Ctrl+X ")},\r
36         {CONTROLX+SHIFT,                                _T("Ctrl+X Shift+")},\r
37         {CONTROLX+CONTROL,                              _T("Ctrl+X Ctrl+")},\r
38         {CONTROLX+CONTROL+SHIFT,                _T("Ctrl+X Ctrl+Shift+")},\r
39         {CONTROLX+META,                                 _T("Ctrl+X Meta+")},\r
40         {CONTROLX+META+SHIFT,                   _T("Ctrl+X Meta+Shift+")},\r
41         {CONTROLX+CONTROL+META,                 _T("Ctrl+X Ctrl+Meta+")},\r
42         {CONTROLX+CONTROL+META+SHIFT,   _T("Ctrl+X Ctrl+Meta+Shift+")},\r
43 };\r
44 \r
45 static const KeyName KeyNames[] = {\r
46         {0,                             _T("")},\r
47         {VK_LBUTTON,    _T("Left mouse button")},\r
48         {VK_RBUTTON,    _T("Right mouse button")},\r
49         {VK_CANCEL,             _T("Break")},\r
50         {VK_MBUTTON,    _T("Middle mouse button")},\r
51         {0x05,                  _T("X1 mouse button")}, // VK_XBUTTON1\r
52         {0x06,                  _T("X2 mouse button")}, // VK_XBUTTON2\r
53         {0x07,                  _T("Undefined")},\r
54         {VK_BACK,               _T("Backspace")},\r
55         {VK_TAB,                _T("Tab")},\r
56         {0x0a,                  _T("Reserved")},\r
57         {0x0b,                  _T("Reserved")},\r
58         {VK_CLEAR,              _T("Clear")},\r
59         {VK_RETURN,             _T("Enter")},\r
60         {0x0e,                  _T("Undefined")},\r
61         {0x0f,                  _T("Undefined")},\r
62         {VK_SHIFT,              _T("Shift")},\r
63         {VK_CONTROL,    _T("Ctrl")},\r
64         {VK_MENU,               _T("Alt")},\r
65         {VK_PAUSE,              _T("Pause")},\r
66         {VK_CAPITAL,    _T("Caps Lock")},\r
67         {VK_KANA,               _T("Kana")},    //      {VK_HANGUEL,    "Hanguel"},     {VK_HANGUL,             "Hangul"},\r
68         {0x16,                  _T("Undefined")},\r
69         {VK_JUNJA,              _T("Junja")},\r
70         {VK_FINAL,              _T("Final")},\r
71         {VK_KANJI,              _T("Kanji")},   //      {VK_HANJA,              "Hanja"},\r
72         {0x1a,                  _T("Undefined")},\r
73         {VK_ESCAPE,             _T("Esc")},\r
74         {VK_CONVERT,    _T("Convert")},         // \95Ï\8a·\r
75         {VK_NONCONVERT, _T("Nonconvert")},      // \96³\95Ï\8a·\r
76         {VK_ACCEPT,             _T("Accept")},\r
77         {VK_MODECHANGE, _T("Mode change")},\r
78         {VK_SPACE,              _T("Space")},\r
79         {VK_PRIOR,              _T("Page Up")},\r
80         {VK_NEXT,               _T("Page Down")},\r
81         {VK_END,                _T("End")},\r
82         {VK_HOME,               _T("Home")},\r
83         {VK_LEFT,               _T("Left")},\r
84         {VK_UP,                 _T("Up")},\r
85         {VK_RIGHT,              _T("Right")},\r
86         {VK_DOWN,               _T("Down")},\r
87         {VK_SELECT,             _T("Select")},\r
88         {VK_PRINT,              _T("Print")},\r
89         {VK_EXECUTE,    _T("Execute")},\r
90         {VK_SNAPSHOT,   _T("Print Screen")},\r
91         {VK_INSERT,             _T("Ins")},\r
92         {VK_DELETE,             _T("Del")},\r
93         {VK_HELP,               _T("Help")},\r
94         {'0',                   _T("0")},\r
95         {'1',                   _T("1")},\r
96         {'2',                   _T("2")},\r
97         {'3',                   _T("3")},\r
98         {'4',                   _T("4")},\r
99         {'5',                   _T("5")},\r
100         {'6',                   _T("6")},\r
101         {'7',                   _T("7")},\r
102         {'8',                   _T("8")},\r
103         {'9',                   _T("9")},\r
104         {0x3a,                  _T("Undefined")},\r
105         {0x3b,                  _T("Undefined")},\r
106         {0x3c,                  _T("Undefined")},\r
107         {0x3d,                  _T("Undefined")},\r
108         {0x3e,                  _T("Undefined")},\r
109         {0x3f,                  _T("Undefined")},\r
110         {0x40,                  _T("Undefined")},\r
111         {'A',                   _T("A")},\r
112         {'B',                   _T("B")},\r
113         {'C',                   _T("C")},\r
114         {'D',                   _T("D")},\r
115         {'E',                   _T("E")},\r
116         {'F',                   _T("F")},\r
117         {'G',                   _T("G")},\r
118         {'H',                   _T("H")},\r
119         {'I',                   _T("I")},\r
120         {'J',                   _T("J")},\r
121         {'K',                   _T("K")},\r
122         {'L',                   _T("L")},\r
123         {'M',                   _T("M")},\r
124         {'N',                   _T("N")},\r
125         {'O',                   _T("O")},\r
126         {'P',                   _T("P")},\r
127         {'Q',                   _T("Q")},\r
128         {'R',                   _T("R")},\r
129         {'S',                   _T("S")},\r
130         {'T',                   _T("T")},\r
131         {'U',                   _T("U")},\r
132         {'V',                   _T("V")},\r
133         {'W',                   _T("W")},\r
134         {'X',                   _T("X")},\r
135         {'Y',                   _T("Y")},\r
136         {'Z',                   _T("Z")},\r
137         {VK_LWIN,               _T("Left Windows")},\r
138         {VK_RWIN,               _T("Right Windows")},\r
139         {VK_APPS,               _T("Application")},\r
140         {0x5e,                  _T("Reserved")},\r
141         {0x5f,                  _T("Sleep")},   // VK_SLEEP\r
142         {VK_NUMPAD0,    _T("Num 0")},\r
143         {VK_NUMPAD1,    _T("Num 1")},\r
144         {VK_NUMPAD2,    _T("Num 2")},\r
145         {VK_NUMPAD3,    _T("Num 3")},\r
146         {VK_NUMPAD4,    _T("Num 4")},\r
147         {VK_NUMPAD5,    _T("Num 5")},\r
148         {VK_NUMPAD6,    _T("Num 6")},\r
149         {VK_NUMPAD7,    _T("Num 7")},\r
150         {VK_NUMPAD8,    _T("Num 8")},\r
151         {VK_NUMPAD9,    _T("Num 9")},\r
152         {VK_MULTIPLY,   _T("Num *")},\r
153         {VK_ADD,                _T("Num +")},\r
154         {VK_SEPARATOR,  _T("Separator")},\r
155         {VK_SUBTRACT,   _T("Num -")},\r
156         {VK_DECIMAL,    _T("Num .")},\r
157         {VK_DIVIDE,             _T("Num /")},\r
158         {VK_F1,                 _T("F1")},\r
159         {VK_F2,                 _T("F2")},\r
160         {VK_F3,                 _T("F3")},\r
161         {VK_F4,                 _T("F4")},\r
162         {VK_F5,                 _T("F5")},\r
163         {VK_F6,                 _T("F6")},\r
164         {VK_F7,                 _T("F7")},\r
165         {VK_F8,                 _T("F8")},\r
166         {VK_F9,                 _T("F9")},\r
167         {VK_F10,                _T("F10")},\r
168         {VK_F11,                _T("F11")},\r
169         {VK_F12,                _T("F12")},\r
170         {VK_F13,                _T("F13")},\r
171         {VK_F14,                _T("F14")},\r
172         {VK_F15,                _T("F15")},\r
173         {VK_F16,                _T("F16")},\r
174         {VK_F17,                _T("F17")},\r
175         {VK_F18,                _T("F18")},\r
176         {VK_F19,                _T("F19")},\r
177         {VK_F20,                _T("F20")},\r
178         {VK_F21,                _T("F21")},\r
179         {VK_F22,                _T("F22")},\r
180         {VK_F23,                _T("F23")},\r
181         {VK_F24,                _T("F24")},\r
182         {0x88,                  _T("Unassigned")},\r
183         {0x89,                  _T("Unassigned")},\r
184         {0x8a,                  _T("Unassigned")},\r
185         {0x8b,                  _T("Unassigned")},\r
186         {0x8c,                  _T("Unassigned")},\r
187         {0x8d,                  _T("Unassigned")},\r
188         {0x8e,                  _T("Unassigned")},\r
189         {0x8f,                  _T("Unassigned")},\r
190         {VK_NUMLOCK,    _T("Num Lock")},\r
191         {VK_SCROLL,             _T("Scroll Lock")},\r
192         {0x92,                  _T("OEM specific")},\r
193         {0x93,                  _T("OEM specific")},\r
194         {0x94,                  _T("OEM specific")},\r
195         {0x95,                  _T("OEM specific")},\r
196         {0x96,                  _T("OEM specific")},\r
197         {0x97,                  _T("Unassigned")},\r
198         {0x98,                  _T("Unassigned")},\r
199         {0x99,                  _T("Unassigned")},\r
200         {0x9a,                  _T("Unassigned")},\r
201         {0x9b,                  _T("Unassigned")},\r
202         {0x9c,                  _T("Unassigned")},\r
203         {0x9d,                  _T("Unassigned")},\r
204         {0x9e,                  _T("Unassigned")},\r
205         {0x9f,                  _T("Unassigned")},\r
206         {VK_LSHIFT,             _T("Left Shift")},\r
207         {VK_RSHIFT,             _T("Right Shift")},\r
208         {VK_LCONTROL,   _T("Left Ctrl")},\r
209         {VK_RCONTROL,   _T("Right Ctrl")},\r
210         {VK_LMENU,              _T("Left Alt")},\r
211         {VK_RMENU,              _T("Right Alt")},\r
212         {0xa6,                  _T("Browser Back")},            // VK_BROWSER_BACK\r
213         {0xa7,                  _T("Browser Forward")},         // VK_BROWSER_FORWARD\r
214         {0xa8,                  _T("Browser Refresh")},         // VK_BROWSER_REFRESH\r
215         {0xa9,                  _T("Browser Stop")},            // VK_BROWSER_STOP\r
216         {0xaa,                  _T("Browser Search")},          // VK_BROWSER_SEARCH\r
217         {0xab,                  _T("Browser Favorites")},       // VK_BROWSER_FAVORITES\r
218         {0xac,                  _T("Browser Start")},           // VK_BROWSER_HOME\r
219         {0xad,                  _T("Volume Mute")},                     // VK_VOLUME_MUTE\r
220         {0xae,                  _T("Volume Down")},                     // VK_VOLUME_DOWN\r
221         {0xaf,                  _T("Volume Up")},                       // VK_VOLUME_UP\r
222         {0xb0,                  _T("Next Track")},                      // VK_MEDIA_NEXT_TRACK\r
223         {0xb1,                  _T("Previous Track")},          // VK_MEDIA_PREV_TRACK\r
224         {0xb2,                  _T("Stop Media")},                      // VK_MEDIA_STOP\r
225         {0xb3,                  _T("Play/Pause Media")},        // VK_MEDIA_PLAY_PAUSE\r
226         {0xb4,                  _T("Start Mail")},                      // VK_LAUNCH_MAIL\r
227         {0xb5,                  _T("Select Media")},            // VK_LAUNCH_MEDIA_SELECT\r
228         {0xb6,                  _T("Start Application 1")},     // VK_LAUNCH_APP1\r
229         {0xb7,                  _T("Start Application 2")},     // VK_LAUNCH_APP2\r
230         {0xb8,                  _T("Reserved")},\r
231         {0xb9,                  _T("Reserved")},\r
232         {0xba,                  _T(";")},                                       // VK_OEM_1\r
233 //      {0xba,                  _T(":")},                                       // VK_OEM_1             // for Japanese keyboard\r
234         {0xbb,                  _T("+")},                                       // VK_OEM_PLUS\r
235 //      {0xbb,                  _T(";")},                                       // VK_OEM_PLUS  // for Japanese keyboard\r
236         {0xbc,                  _T(",")},                                       // VK_OEM_COMMA\r
237         {0xbd,                  _T("-")},                                       // VK_OEM_MINUS\r
238         {0xbe,                  _T(".")},                                       // VK_OEM_PERIOD\r
239         {0xbf,                  _T("/")},                                       // VK_OEM_2\r
240         {0xc0,                  _T("`")},                                       // VK_OEM_3\r
241 //      {0xc0,                  _T("@")},                                       // VK_OEM_3             // for Japanese keyboard\r
242         {0xc1,                  _T("Reserved")},\r
243         {0xc2,                  _T("Reserved")},\r
244         {0xc3,                  _T("Reserved")},\r
245         {0xc4,                  _T("Reserved")},\r
246         {0xc5,                  _T("Reserved")},\r
247         {0xc6,                  _T("Reserved")},\r
248         {0xc7,                  _T("Reserved")},\r
249         {0xc8,                  _T("Reserved")},\r
250         {0xc9,                  _T("Reserved")},\r
251         {0xca,                  _T("Reserved")},\r
252         {0xcb,                  _T("Reserved")},\r
253         {0xcc,                  _T("Reserved")},\r
254         {0xcd,                  _T("Reserved")},\r
255         {0xce,                  _T("Reserved")},\r
256         {0xcf,                  _T("Reserved")},\r
257         {0xd0,                  _T("Reserved")},\r
258         {0xd1,                  _T("Reserved")},\r
259         {0xd2,                  _T("Reserved")},\r
260         {0xd3,                  _T("Reserved")},\r
261         {0xd4,                  _T("Reserved")},\r
262         {0xd5,                  _T("Reserved")},\r
263         {0xd6,                  _T("Reserved")},\r
264         {0xd7,                  _T("Reserved")},\r
265         {0xd8,                  _T("Unassigned")},\r
266         {0xd9,                  _T("Unassigned")},\r
267         {0xda,                  _T("Unassigned")},\r
268         {0xdb,                  _T("[")},                                       // VK_OEM_4\r
269         {0xdc,                  _T("Backslash")},                       // VK_OEM_5\r
270         {0xdd,                  _T("]")},                                       // VK_OEM_6\r
271         {0xde,                  _T("'")},                                       // VK_OEM_7\r
272         {0xdf,                  _T("OEM specific")},            // VK_OEM_8\r
273         {0xe0,                  _T("Reserved")},\r
274         {0xe1,                  _T("OEM specific")},\r
275         {0xe2,                  _T("Backslash for 106 keyboard")},      // VK_OEM_102\r
276         {0xe3,                  _T("OEM specific")},\r
277         {0xe4,                  _T("OEM specific")},\r
278         {0xe5,                  _T("Process")},                         // VK_PROCESSKEY\r
279         {0xe6,                  _T("OEM specific")},\r
280         {0xe7,                  _T("Packet")},  // VK_PACKET\r
281         {0xe8,                  _T("Unassigned")},\r
282         {0xe9,                  _T("OEM specific")},\r
283         {0xea,                  _T("OEM specific")},\r
284         {0xeb,                  _T("OEM specific")},\r
285         {0xec,                  _T("OEM specific")},\r
286         {0xed,                  _T("OEM specific")},\r
287         {0xee,                  _T("OEM specific")},\r
288         {0xef,                  _T("OEM specific")},\r
289         {0xf0,                  _T("Eisu")},                                    // \89p\90\94\r
290         {0xf1,                  _T("OEM specific")},\r
291         {0xf2,                  _T("Hiragana")},                                // \82Ð\82ç\82ª\82È\r
292         {0xf3,                  _T("Hankaku/Zenkaku 0xf3")},    // "\94¼\8ap/\91S\8ap"\r
293         {0xf4,                  _T("Hankaku/Zenkaku 0xf4")},    // "\94¼\8ap/\91S\8ap"\r
294         {0xf5,                  _T("OEM specific")},\r
295         {VK_ATTN,               _T("Attn")},\r
296         {VK_CRSEL,              _T("CrSel")},\r
297         {VK_EXSEL,              _T("ExSel")},\r
298         {VK_EREOF,              _T("Erace EOF")},\r
299         {VK_PLAY,               _T("Play")},\r
300         {VK_ZOOM,               _T("Zoom")},\r
301         {VK_NONAME,             _T("Noname")},\r
302         {VK_PA1,                _T("PA1")},\r
303         {VK_OEM_CLEAR,  _T("OEM Clear")},\r
304         {0xff,                  _T("")},\r
305 };\r
306 \r
307 CXkeymacsData CProfile::m_XkeymacsData[MAX_APP];\r
308 TASK_LIST CProfile::m_TaskList[MAX_TASKS];\r
309 DWORD CProfile::m_dwTasks;\r
310 ScanCode CProfile::m_CurrentScanCodeMap[MAX_HKEY_TYPE][4][256];\r
311 ScanCode CProfile::m_ScanCodeMap[MAX_HKEY_TYPE][4][256];\r
312 \r
313 enum { INITIAL_SIZE     = 51200 };\r
314 enum { EXTEND_SIZE      = 25600 };\r
315 \r
316 void CProfile::Item2AppName(CString *const sz)\r
317 {\r
318         if (IsTheString(*sz, IDS_DEFAULT_TITLE)) {\r
319                 sz->LoadString(IDS_DEFAULT);\r
320         }\r
321 \r
322         if (IsTheString(*sz, IDS_DIALOG_TITLE)) {\r
323                 sz->LoadString(IDS_DIALOG);\r
324         }\r
325 \r
326         int nStart, nEnd, nCount;\r
327 \r
328         nStart  = sz->ReverseFind(_T('(')) + 1;\r
329         nEnd    = sz->Find(_T(')'), nStart) - 1;\r
330         nCount  = (nEnd + 1) - nStart;\r
331         *sz             = sz->Mid(nStart, nCount);\r
332 }\r
333 \r
334 int CProfile::IsNotSameString(CComboBox *const pApplication, const CString szListItem)\r
335 {\r
336         CString szItem, szList;\r
337         szList = szListItem;\r
338         Item2AppName(&szList);\r
339 \r
340         for (int i = 0; i < pApplication->GetCount(); ++i) {\r
341                 pApplication->GetLBText(i, szItem);\r
342                 Item2AppName(&szItem);\r
343                 if (!_tcsicmp(szItem, szList)) {\r
344                         return 0;\r
345                 }\r
346         }\r
347 \r
348         return 1;\r
349 }\r
350 \r
351 int CProfile::CountSeparator(const CString szMainString, const CString szSeparator)\r
352 {\r
353         int index       = 0;\r
354         int counter     = 0;\r
355 \r
356         while ((index = szMainString.Find(szSeparator, index)) != -1) {\r
357                 ++index;\r
358                 ++counter;\r
359         }\r
360 \r
361         return counter;\r
362 }\r
363 \r
364 void CProfile::GetNthString(CString *const szAppName, const CString szWindowName, const CString szSeparator, int n)\r
365 {\r
366         int index = -1;\r
367 \r
368         while (--n) {\r
369                 index = szWindowName.Find(szSeparator, index + 1);\r
370         }\r
371 \r
372         int nStart;\r
373         if (index != -1) {\r
374                 nStart = index + szSeparator.GetLength();\r
375         } else {\r
376                 nStart = 0;\r
377         }\r
378 \r
379         int nEnd = szWindowName.Find(szSeparator, nStart);\r
380         if (nEnd == -1) {\r
381                 nEnd = szWindowName.GetLength();\r
382         }\r
383 \r
384         *szAppName = szWindowName.Mid(nStart, nEnd - nStart);\r
385 }\r
386 \r
387 void CProfile::GetAppName(CString *const szAppName, LPCTSTR pWindowName)\r
388 {\r
389         CString szWindowName(pWindowName);\r
390         CString szSeparator(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE));\r
391         int nWord = CountSeparator(szWindowName, szSeparator) + 1;\r
392 \r
393         while (nWord) {\r
394                 GetNthString(szAppName, szWindowName, szSeparator, nWord);\r
395                 if (szAppName->GetAt(0) == _T('[')\r
396                  || szAppName->Find(_T('.'), 0) != -1           // for Microsoft Project\r
397                  || szAppName->Find(_T(']'), 0) != -1) {        // for the file name like [foo - bar]\r
398                         --nWord;\r
399                 } else {\r
400                         return;\r
401                 }\r
402         }\r
403 \r
404         *szAppName = szWindowName;\r
405 }\r
406 \r
407 BOOL CALLBACK CProfile::EnumWindowsProc(const HWND hWnd, const LPARAM lParam)\r
408 {\r
409         CComboBox               *pApplication   = (CComboBox*)lParam;\r
410         PTASK_LIST              pTask                   = CProfile::m_TaskList;\r
411         \r
412         TCHAR szWindowName[WINDOW_NAME_LENGTH];\r
413         TCHAR szClassName[CLASS_NAME_LENGTH];\r
414         WINDOWPLACEMENT wpl;\r
415         \r
416         wpl.length = sizeof(WINDOWPLACEMENT);\r
417         ::GetWindowText(hWnd, szWindowName, sizeof(szWindowName));\r
418         GetClassName(hWnd, szClassName, sizeof(szClassName));\r
419 \r
420         CString szAppName;\r
421         // Get Process Name\r
422         DWORD dwProcessId = 0;\r
423         GetWindowThreadProcessId(hWnd, &dwProcessId);\r
424         for (DWORD i = 0; i < CProfile::m_dwTasks; ++i) {\r
425                 if (pTask[i].dwProcessId == dwProcessId) {\r
426 \r
427                         // Get Application Name\r
428                         if (szWindowName[0] == '\0') {\r
429                                 continue;\r
430                         }\r
431                         if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_B2)), sizeof(pTask[i].ProcessName))) {\r
432                                 szAppName.LoadString(IDS_BECKY);\r
433                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXPLORER)), sizeof(pTask[i].ProcessName))) {\r
434                                 szAppName.LoadString(IDS_PROGRAM_MANAGER);\r
435                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSIMN)), sizeof(pTask[i].ProcessName))) {\r
436                                 szAppName.LoadString(IDS_OUTLOOK_EXPRESS);\r
437                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_PROJECT)), sizeof(pTask[i].ProcessName))\r
438                                         || !_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_EXCEL)), sizeof(pTask[i].ProcessName))\r
439                                         || !_tcsnicmp(pTask[i].ProcessName, _T("psp.exe"), sizeof(pTask[i].ProcessName))) {\r
440                                 GetNthString(&szAppName, szWindowName, CString(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE)), 1);\r
441                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sakura.exe"), sizeof(pTask[i].ProcessName))) {\r
442                                 GetNthString(&szAppName, szWindowName, CString(MAKEINTRESOURCE(IDS_SEPARATE_WINDOWTITLE)), 2);  // '.' is included, so...\r
443                         } else if (!_tcsnicmp(pTask[i].ProcessName, CString(MAKEINTRESOURCE(IDS_MSDN)), sizeof(pTask[i].ProcessName))) {\r
444                                 szAppName = szWindowName;\r
445                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("devenv.exe"), sizeof(pTask[i].ProcessName))) {\r
446                                 szAppName.Format(_T("Microsoft Visual Studio .NET"));\r
447                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vb6.exe"), sizeof(pTask[i].ProcessName))) {\r
448                                 szAppName.Format(_T("Microsoft Visual Basic"));\r
449                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("ssexp.exe"), sizeof(pTask[i].ProcessName))) {\r
450                                 szAppName.LoadString(IDS_VISUAL_SOURCESAFE_EXPLORER);\r
451                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("sh.exe"), sizeof(pTask[i].ProcessName))) {\r
452                                 szAppName.Format(_T("MKS Korn Shell"));\r
453                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("csh.exe"), sizeof(pTask[i].ProcessName))) {\r
454                                 szAppName.Format(_T("C Shell"));\r
455                         } else if (!_tcsnicmp(pTask[i].ProcessName, _T("vim.exe"), sizeof(pTask[i].ProcessName))) {\r
456                                 szAppName.Format(_T("VIM"));\r
457                         } else {\r
458                                 CUtils::SetCorrectApplicationName(pTask[i].ProcessName, sizeof(pTask[i].ProcessName), szWindowName, sizeof(szWindowName));\r
459                                 GetAppName(&szAppName, szWindowName);\r
460                         }\r
461                         break;\r
462                 }\r
463         }\r
464         \r
465         \r
466         if ((IsWindowVisible(hWnd))                                                                     // Is visible?\r
467          && (GetWindow(hWnd, GW_OWNER) == NULL)                                         // Is top level window?\r
468          && (lstrlen(szWindowName) > 0)                                                         // Have caption?\r
469          && (pApplication->FindString(-1, szClassName) == CB_ERR)) {// Is not same string?\r
470                 CString szListItem;\r
471                 szListItem.Format(IDS_APPLICATION_LIST_ITEM, szAppName, pTask[i].ProcessName);\r
472                 if (IsNotSameString(pApplication, szListItem)) {\r
473                         pApplication->AddString(szListItem);\r
474                 }\r
475         }\r
476         return TRUE;\r
477 }\r
478         \r
479 //////////////////////////////////////////////////////////////////////\r
480 // Construction/Destruction\r
481 //////////////////////////////////////////////////////////////////////\r
482 \r
483 CProfile::CProfile()\r
484 {\r
485 \r
486 }\r
487 \r
488 CProfile::~CProfile()\r
489 {\r
490 \r
491 }\r
492 \r
493 // This method initializes data in the registry, or retrieves and validates registry data.\r
494 // bSaveAndValidate specifies a flag that indicates \r
495 // whether registry data is being initialized (FALSE) or data is being retrieved (TRUE). \r
496 void CProfile::UpdateRegistryData(const BOOL bSaveAndValidate)\r
497 {\r
498         CString szEntry;\r
499         CString szApplicationName;\r
500         CString szApplicationTitle;\r
501         CString szWindowText;\r
502         CString szWindowTextType;\r
503 \r
504         BOOL bUseDialogSetting = FALSE;\r
505 \r
506         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
507                 // application name\r
508                 CString szSection(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION));\r
509                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
510                 if (bSaveAndValidate) { // retrieve\r
511                         m_XkeymacsData[nApplicationID].ClearAll();\r
512                         szApplicationName = AfxGetApp()->GetProfileString(szSection, szEntry);\r
513                         if (szApplicationName.IsEmpty()) {\r
514                                 if (nApplicationID) {\r
515                                         if (!bUseDialogSetting) {\r
516                                                 szApplicationName.LoadString(IDS_DIALOG);\r
517                                                 bUseDialogSetting = TRUE;\r
518                                         } else {\r
519                                                 continue;\r
520                                         }\r
521                                 } else {\r
522                                         szApplicationName.LoadString(IDS_DEFAULT);\r
523                                 }\r
524                         } else {\r
525                                 if (szApplicationName == CString(MAKEINTRESOURCE(IDS_DIALOG))) {\r
526                                         bUseDialogSetting = TRUE;\r
527                                 }\r
528                         }\r
529                         m_XkeymacsData[nApplicationID].SetApplicationName(szApplicationName);\r
530                 } else {                                // initialize\r
531                         szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
532                         if (szApplicationName.IsEmpty()) {\r
533                                 continue;\r
534                         }\r
535                         AfxGetApp()->WriteProfileString(szSection, szEntry, szApplicationName);\r
536                 }\r
537 \r
538                 // application title\r
539                 szEntry.LoadString(IDS_REG_ENTRY_APPLICATOIN_TITLE);\r
540                 if (bSaveAndValidate) { // retrieve\r
541                         szApplicationTitle = AfxGetApp()->GetProfileString(szApplicationName, szEntry);\r
542                         m_XkeymacsData[nApplicationID].SetApplicationTitle(szApplicationTitle);\r
543                 } else {                                // initialize\r
544                         szApplicationTitle = m_XkeymacsData[nApplicationID].GetApplicationTitle();\r
545                         while (!szApplicationTitle.IsEmpty() && szApplicationTitle.GetAt(0) == _T(' ')) {\r
546                                 szApplicationTitle.Delete(0);\r
547                         }\r
548                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szApplicationTitle);\r
549                 }\r
550 \r
551                 // window text\r
552                 szEntry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT);\r
553                 if (bSaveAndValidate) { // retrieve\r
554                         szWindowText = AfxGetApp()->GetProfileString(szApplicationName, szEntry, _T("*"));\r
555                         if (szWindowText.IsEmpty()) {\r
556                                 szWindowText = _T('*');\r
557                         }\r
558                         m_XkeymacsData[nApplicationID].SetWindowText(szWindowText);\r
559                 } else {                                // initialize\r
560                         szWindowText = m_XkeymacsData[nApplicationID].GetWindowText();\r
561                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szWindowText);\r
562                 }\r
563 \r
564                 // window text type\r
565                 szEntry.LoadString(IDS_REG_ENTRY_WINDOW_TEXT_TYPE);\r
566                 if (bSaveAndValidate) { // retrieve\r
567                         szWindowTextType = AfxGetApp()->GetProfileString(szApplicationName, szEntry);\r
568 \r
569                         int nWindowTextType = IDS_WINDOW_TEXT_IGNORE;\r
570                         if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH))) {\r
571                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH;\r
572                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_FORWARD))) {\r
573                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_FORWARD;\r
574                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_BACKWARD))) {\r
575                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_BACKWARD;\r
576                         } else if (szWindowTextType == CString(MAKEINTRESOURCE(IDS_WINDOW_TEXT_MATCH_FULL))) {\r
577                                 nWindowTextType = IDS_WINDOW_TEXT_MATCH_FULL;\r
578                         }\r
579 \r
580                         m_XkeymacsData[nApplicationID].SetWindowTextType(nWindowTextType);\r
581                 } else {                                // initialize\r
582                         szWindowTextType.LoadString(m_XkeymacsData[nApplicationID].GetWindowTextType());\r
583                         AfxGetApp()->WriteProfileString(szApplicationName, szEntry, szWindowTextType);\r
584                 }\r
585 \r
586                 // on/off\r
587                 if (bSaveAndValidate) { // retrieve\r
588                         for (int nCommandID = 1; nCommandID < MAX_COMMAND; ++nCommandID) {\r
589                                 szEntry = CXkeymacsData::GetCommandName(nCommandID);\r
590                                 if (szEntry.IsEmpty()) {\r
591                                         break;\r
592                                 }\r
593 \r
594                                 HKEY hKey = NULL;\r
595                                 CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
596                                 szSubKey += _T("\\") + szApplicationName + _T("\\") + szEntry;\r
597                                 if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
598                                         // Use registry data\r
599                                         TCHAR szKeyBind[128] = {'\0'};\r
600                                         DWORD dwKeyBind = sizeof(szKeyBind);\r
601                                         FILETIME ft = {'\0'};   // not use\r
602                                         for (DWORD dwIndex = 0;\r
603                                                  RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS;\r
604                                                  ++dwIndex) {\r
605                                                 int nCommandType = 0;\r
606                                                 int nKey = 0;\r
607                                                 ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
608                                                 m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
609 \r
610 //                                              if (nCommandType == CONTROL && nKey == 'D') {\r
611 //                                                      CUtils::Log("GetProfileInt(at ibeam cursor only): %s, %s", szSubKey, szKeyBind);\r
612 //                                              }\r
613                                                 const CString szSection = szSubKey.Right(szSubKey.GetLength() - CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)).GetLength() - _tcslen(_T("\\"))) + _T("\\") + szKeyBind;\r
614                                                 const BOOL bAtIbeamCursorOnly = AfxGetApp()->GetProfileInt(szSection, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_AT_IBEAM_CURSOR_ONLY)), FALSE);\r
615                                                 m_XkeymacsData[nApplicationID].SetAtIbeamCursorOnly(nCommandType, nKey, bAtIbeamCursorOnly);\r
616 \r
617                                                 memset(szKeyBind, 0, sizeof(szKeyBind));\r
618                                                 dwKeyBind = sizeof(szKeyBind);\r
619                                         }\r
620                                         RegCloseKey(hKey);\r
621                                 } else {\r
622                                         // Use default setting\r
623                                         for (int i = 0; ; ++i) {\r
624                                                 if (CXkeymacsData::GetDefaultControlID(nCommandID, i) == IDC_CO2) {\r
625                                                         continue;\r
626                                                 }\r
627 \r
628                                                 int nCommandType = CXkeymacsData::GetDefaultCommandType(nCommandID, i);\r
629                                                 int nKey = CXkeymacsData::GetDefaultCommandKey(nCommandID, i);\r
630                                                 if (nKey == 0) {\r
631                                                         break;\r
632                                                 }\r
633                                                 m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
634                                                 m_XkeymacsData[nApplicationID].SetAtIbeamCursorOnly(nCommandType, nKey, FALSE);\r
635                                         }\r
636                                 }\r
637                         }\r
638                         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
639                                 HKEY hKey = NULL;\r
640                                 CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
641                                 szSubKey += _T("\\") + szApplicationName + _T("\\") + CDotXkeymacs::GetFunctionSymbol(nFunctionID);\r
642                                 if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
643                                         // Use registry data\r
644                                         CDotXkeymacs::ClearKey(nFunctionID, nApplicationID);\r
645                                         TCHAR szKeyBind[128] = {'\0'};\r
646                                         DWORD dwKeyBind = sizeof(szKeyBind);\r
647                                         FILETIME ft = {'\0'};   // not use\r
648                                         for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS; ++dwIndex) {\r
649                                                 int nCommandType = 0;\r
650                                                 int nKey = 0;\r
651                                                 ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
652                                                 CDotXkeymacs::SetKey(nFunctionID, nApplicationID, nCommandType, nKey);\r
653 \r
654                                                 memset(szKeyBind, 0, sizeof(szKeyBind));\r
655                                                 dwKeyBind = sizeof(szKeyBind);\r
656                                         }\r
657                                         RegCloseKey(hKey);\r
658                                 }\r
659                         }\r
660                 } else {                                // initialize\r
661                         // create all commands\r
662                         for (int nCommandID = 1; nCommandID < MAX_COMMAND; ++nCommandID) {\r
663                                 szEntry = CXkeymacsData::GetCommandName(nCommandID);\r
664                                 if (szEntry.IsEmpty()) {\r
665                                         break;\r
666                                 }\r
667 \r
668                                 SaveCommand(szApplicationName, nCommandID);\r
669                         }\r
670                         for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {\r
671                                 for (int nKey = 0; nKey < MAX_KEY; ++nKey) {\r
672                                         int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
673                                         SaveKeyBind(szApplicationName, nCommandID, nCommandType, nKey);\r
674                                 }\r
675                         }\r
676                         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
677                                 for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFunctionID, nApplicationID); ++nKeyID) {\r
678                                         int nCommandType = 0;\r
679                                         int nKey = 0;\r
680                                         CDotXkeymacs::GetKey(nFunctionID, nApplicationID, nKeyID, &nCommandType, &nKey);\r
681                                         SaveKeyBind(szApplicationName, CDotXkeymacs::GetFunctionSymbol(nFunctionID), nCommandType, nKey);\r
682                                 }\r
683                         }\r
684                 }\r
685 \r
686                 // kill-ring-max\r
687                 szEntry.LoadString(IDS_REG_ENTRY_KILL_RING_MAX);\r
688                 if (bSaveAndValidate) { // retrieve\r
689                         int nKillRingMax = AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 1);\r
690                         m_XkeymacsData[nApplicationID].SetKillRingMax(nKillRingMax);\r
691                 } else {                                // initialize\r
692                         int nKillRingMax = m_XkeymacsData[nApplicationID].GetKillRingMax();\r
693                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, nKillRingMax);\r
694                 }\r
695 \r
696                 // Use Dialog Setting\r
697                 szEntry.LoadString(IDS_REG_ENTRY_USE_DIALOG_SETTING);\r
698                 if (bSaveAndValidate) { // retrieve\r
699                         BOOL bUseDialogSetting = AfxGetApp()->GetProfileInt(szApplicationName,szEntry, 1);\r
700                         m_XkeymacsData[nApplicationID].SetUseDialogSetting(bUseDialogSetting);\r
701                 } else {                                // initialize\r
702                         BOOL bUseDialogSetting = m_XkeymacsData[nApplicationID].GetUseDialogSetting();\r
703                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, bUseDialogSetting);\r
704                 }\r
705 \r
706                 // Setting Style\r
707                 szEntry.LoadString(IDS_REG_ENTRY_DISABLE_XKEYMACS);\r
708                 if (bSaveAndValidate) { // retrieve\r
709                         int nSettingStyle = SETTING_SPECIFIC;\r
710                         if (AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0) != 0) {\r
711                                 nSettingStyle = SETTING_DISABLE;\r
712                         }\r
713                         m_XkeymacsData[nApplicationID].SetSettingStyle(nSettingStyle);\r
714                 } else {                                // initialize\r
715                         BOOL bDisableXkeymacs = FALSE;\r
716                         if (m_XkeymacsData[nApplicationID].GetSettingStyle() == SETTING_DISABLE) {\r
717                                 bDisableXkeymacs = TRUE;\r
718                         }\r
719                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, bDisableXkeymacs);\r
720                 }\r
721 \r
722                 // Ignore Meta Ctrl+? when it is undefined.\r
723                 szEntry.LoadString(IDC_REG_ENTRY_IGNORE_META_CTRL);\r
724                 if (bSaveAndValidate) { // retrieve\r
725                         m_XkeymacsData[nApplicationID].SetIgnoreUndefinedMetaCtrl(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
726                 } else {                                // initialize\r
727                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedMetaCtrl());\r
728                 }\r
729 \r
730                 // Ignore C-x ? when it is undefined.\r
731                 szEntry.LoadString(IDC_REG_ENTRY_IGNORE_C_X);\r
732                 if (bSaveAndValidate) { // retrieve\r
733                         m_XkeymacsData[nApplicationID].SetIgnoreUndefinedC_x(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
734                 } else {                                // initialize\r
735                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedC_x());\r
736                 }\r
737 \r
738                 // Enable CUA-mode\r
739                 szEntry.LoadString(IDC_REG_ENTRY_ENABLE_CUA);\r
740                 if (bSaveAndValidate) { // retrieve\r
741                         m_XkeymacsData[nApplicationID].SetEnableCUA(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
742                 } else {                                // initialize\r
743                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].GetEnableCUA());\r
744                 }\r
745 \r
746                 // Version 3.26 compatible mode\r
747                 szEntry.LoadString(IDS_REG_ENTRY_326_COMPATIBLE);\r
748                 if (bSaveAndValidate) { // retrieve\r
749                         m_XkeymacsData[nApplicationID].Set326Compatible(AfxGetApp()->GetProfileInt(szApplicationName, szEntry, 0));\r
750                 } else {                                // initialize\r
751                         AfxGetApp()->WriteProfileInt(szApplicationName, szEntry, m_XkeymacsData[nApplicationID].Get326Compatible());\r
752                 }\r
753         }\r
754 }\r
755 \r
756 void CProfile::LoadRegistryData()\r
757 {\r
758         CDotXkeymacs::Load();\r
759         LevelUp();\r
760         UpdateRegistryData(TRUE);\r
761 }\r
762 \r
763 void CProfile::SaveRegistryData()\r
764 {\r
765         DeleteAllRegistryData();\r
766         UpdateRegistryData(FALSE);\r
767         SetDllData();\r
768 }\r
769 \r
770 void CProfile::SetDllData()\r
771 {\r
772         CMainFrame *pMainFrame = (CMainFrame*)AfxGetMainWnd();\r
773 \r
774         pMainFrame->m_pXkeymacsDll->ClearFunctionDefinition();\r
775         for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
776                 pMainFrame->m_pXkeymacsDll->SetFunctionDefinition(nFunctionID, CDotXkeymacs::GetFunctionDefinition(nFunctionID));\r
777         }\r
778 \r
779         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
780 \r
781                 CString szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
782 \r
783                 if (szApplicationName.IsEmpty()) {\r
784                         pMainFrame->m_pXkeymacsDll->Clear(nApplicationID);\r
785                         continue;\r
786                 }\r
787 \r
788                 pMainFrame->m_pXkeymacsDll->SetApplicationName(nApplicationID, szApplicationName);\r
789                 pMainFrame->m_pXkeymacsDll->SetWindowText(nApplicationID, m_XkeymacsData[nApplicationID].GetWindowText());\r
790                 pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 0);\r
791                 pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', FALSE);\r
792 \r
793                 for (int nCommandType = 0; nCommandType < MAX_COMMAND_TYPE; ++nCommandType) {\r
794                         for (int nKey = 0; nKey < MAX_KEY; ++nKey) {\r
795                                 const int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
796                                 pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, nCommandType, nKey, nCommandID);\r
797                                 const BOOL bAtIbeamCursorOnly = m_XkeymacsData[nApplicationID].GetAtIbeamCursorOnly(nCommandType, nKey);\r
798                                 pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, nCommandType, nKey, bAtIbeamCursorOnly);\r
799                                 if ((nCommandType & CONTROLX) && nCommandID) {\r
800                                         pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 1);                      // Commands[1] is C-x\r
801                                         pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', bAtIbeamCursorOnly);\r
802                                 }\r
803                         }\r
804                 }\r
805 \r
806                 for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
807                         for (int nKeyID = 0; nKeyID < CDotXkeymacs::GetKeyNumber(nFunctionID, nApplicationID); ++nKeyID) {\r
808                                 int nCommandType = 0;\r
809                                 int nKey = 0;\r
810                                 CDotXkeymacs::GetKey(nFunctionID, nApplicationID, nKeyID, &nCommandType, &nKey);\r
811                                 pMainFrame->m_pXkeymacsDll->SetFunctionKey(nFunctionID, nApplicationID, nCommandType, nKey);\r
812                                 if (nCommandType & CONTROLX) {\r
813                                         pMainFrame->m_pXkeymacsDll->SetCommandID(nApplicationID, CONTROL, 'X', 1);                      // Commands[1] is C-x\r
814                                         const BOOL bAtIbeamCursorOnly = m_XkeymacsData[nApplicationID].GetAtIbeamCursorOnly(nCommandType, nKey);\r
815                                         pMainFrame->m_pXkeymacsDll->SetAtIbeamCursorOnly(nApplicationID, CONTROL, 'X', bAtIbeamCursorOnly);\r
816                                 }\r
817                         }\r
818                 }\r
819 \r
820                 pMainFrame->m_pXkeymacsDll->SetKillRingMax(nApplicationID, m_XkeymacsData[nApplicationID].GetKillRingMax());\r
821                 pMainFrame->m_pXkeymacsDll->SetUseDialogSetting(nApplicationID, m_XkeymacsData[nApplicationID].GetUseDialogSetting());\r
822                 pMainFrame->m_pXkeymacsDll->SetSettingStyle(nApplicationID, m_XkeymacsData[nApplicationID].GetSettingStyle());\r
823                 pMainFrame->m_pXkeymacsDll->SetIgnoreUndefinedMetaCtrl(nApplicationID, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedMetaCtrl());\r
824                 pMainFrame->m_pXkeymacsDll->SetIgnoreUndefinedC_x(nApplicationID, m_XkeymacsData[nApplicationID].GetIgnoreUndefinedC_x());\r
825                 pMainFrame->m_pXkeymacsDll->SetEnableCUA(nApplicationID, m_XkeymacsData[nApplicationID].GetEnableCUA());\r
826                 pMainFrame->m_pXkeymacsDll->Set326Compatible(nApplicationID, m_XkeymacsData[nApplicationID].Get326Compatible());\r
827         }\r
828 }\r
829 \r
830 void CProfile::ReadKeyBind(int *const pnCommandType, int *const pnKey, LPCTSTR szKeyBind)\r
831 {\r
832         *pnCommandType = KeyBind2CommandType(szKeyBind);\r
833         *pnKey = KeyBind2Key(szKeyBind + _tcslen(CommandType2String(*pnCommandType)));\r
834 }\r
835 \r
836 CString CProfile::WriteKeyBind(const int nCommandType, const int nKey)\r
837 {\r
838         CString szKeyBind;\r
839         szKeyBind.Format(_T("%s%s"), CommandType2String(nCommandType), Key2String(nKey));\r
840         return szKeyBind;\r
841 }\r
842 \r
843 int CProfile::KeyBind2CommandType(LPCTSTR szKeyBind)\r
844 {\r
845         for (int nCommandType = MAX_COMMAND_TYPE - 1; nCommandType; --nCommandType) {\r
846                 if (IsCommandType(nCommandType, szKeyBind)) {\r
847                         return nCommandType;\r
848                 }\r
849         }\r
850         return NONE;\r
851 }\r
852 \r
853 int CProfile::KeyBind2Key(LPCTSTR szKey)\r
854 {\r
855         for (int nKey = 1; nKey < 0xff; ++nKey) {\r
856                 if (!_tcscmp(szKey, Key2String(nKey))) {\r
857                         return nKey;\r
858                 }\r
859         }\r
860         return 0;\r
861 }\r
862 \r
863 LPCTSTR CProfile::CommandType2String(int nCommandType)\r
864 {\r
865         if (nCommandType < 0 || sizeof(CommandTypes) / sizeof(CommandTypes[0]) <= nCommandType) {\r
866                 ASSERT(0);\r
867                 nCommandType = NONE;\r
868         }\r
869         return CommandTypes[nCommandType].szCommandTypeName;\r
870 }\r
871 \r
872 LPCTSTR CProfile::Key2String(int nKey)\r
873 {\r
874         if (CProfile::Is106Keyboard()) {\r
875                 switch (nKey) {\r
876                 case 0xBA:\r
877                         return _T(":");\r
878                 case 0xBB:\r
879                         return _T(";");\r
880                 case 0xC0:\r
881                         return _T("@");\r
882                 case 0xDE:\r
883                         return _T("^");\r
884                 default:\r
885                         break;\r
886                 }\r
887         }\r
888 \r
889         if (nKey < 0 || sizeof(KeyNames) / sizeof(KeyNames[0]) <= nKey) {\r
890                 ASSERT(0);\r
891                 nKey = 0;\r
892         }\r
893         return KeyNames[nKey].name;\r
894 }\r
895 \r
896 BOOL CProfile::IsCommandType(const int nCommandType, LPCTSTR szKeyBind)\r
897 {\r
898         LPCTSTR szCommandType = CommandType2String(nCommandType);\r
899 \r
900         if (!_tcsnicmp(szKeyBind, szCommandType, _tcslen(szCommandType))) {\r
901                 return TRUE;\r
902         }\r
903 \r
904         return FALSE;\r
905 }\r
906 \r
907 void CProfile::SaveKeyBind(const CString szApplicationName, const int nCommandID, const int nCommandType, const int nKey)\r
908 {\r
909         if (!nCommandID) {\r
910                 return;\r
911         }\r
912 \r
913         CString szCommandName = CXkeymacsData::GetCommandName(nCommandID);\r
914         if (szCommandName.IsEmpty()) {\r
915                 return;\r
916         }\r
917 \r
918         SaveKeyBind(szApplicationName, szCommandName, nCommandType, nKey);\r
919 }\r
920 \r
921 void CProfile::SaveKeyBind(const CString szApplicationName, const CString szCommandName, const int nCommandType, const int nKey)\r
922 {\r
923         CString szKeyBind = WriteKeyBind(nCommandType, nKey);\r
924         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
925         szSubKey += _T("\\") + szApplicationName + _T("\\") + szCommandName;\r
926         if (!szKeyBind.IsEmpty()) {\r
927                 szSubKey += _T("\\") + szKeyBind;\r
928         }\r
929 \r
930         HKEY hKey = NULL;\r
931         if (RegCreateKeyEx(HKEY_CURRENT_USER, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) {\r
932                 RegCloseKey(hKey);\r
933         }\r
934 }\r
935 \r
936 void CProfile::SaveCommand(const CString szApplicationName, const int nCommandID)\r
937 {\r
938         SaveKeyBind(szApplicationName, nCommandID, 0, 0);\r
939 }\r
940 \r
941 void CProfile::AddKeyBind2C_(const CString szApplicationName, const BYTE bVk)\r
942 {\r
943         for (int nCommandID = 0; nCommandID < MAX_COMMAND; ++nCommandID) {\r
944                 if (Commands[nCommandID].fCommand == CCommands::C_) {\r
945                         break;\r
946                 }\r
947         }\r
948 \r
949         SaveKeyBind(szApplicationName, nCommandID, NONE, bVk);\r
950 }\r
951 \r
952 void CProfile::LevelUp()\r
953 {\r
954         const int nDefalutLevel = 0;\r
955         const int nLatestLevel = 4;\r
956 \r
957         CString szSection;\r
958         CString szEntry;\r
959         szEntry.Format(_T("Level"));\r
960 \r
961         switch (AfxGetApp()->GetProfileInt(szSection, szEntry, nDefalutLevel)) {\r
962         case nDefalutLevel:\r
963                 {\r
964                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
965                                 CString szEntry;\r
966                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
967 \r
968                                 CString szApplicationName;\r
969                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
970                                 if (szApplicationName.IsEmpty()) {\r
971                                         continue;\r
972                                 }\r
973 \r
974                                 AddKeyBind2C_(szApplicationName, VK_LCONTROL);\r
975                                 AddKeyBind2C_(szApplicationName, VK_RCONTROL);\r
976                         }\r
977                 }\r
978                 // Do NOT write break; here.\r
979         case 1:\r
980                 {\r
981                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
982                                 CString szEntry;\r
983                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
984 \r
985                                 CString szApplicationName;\r
986                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
987                                 if (szApplicationName.IsEmpty()) {\r
988                                         continue;\r
989                                 }\r
990 \r
991                                 // Set kill-ring-max 1 if it is 0.\r
992                                 if (!AfxGetApp()->GetProfileInt(szApplicationName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 0)) {\r
993                                         AfxGetApp()->WriteProfileInt(szApplicationName, CString(MAKEINTRESOURCE(IDS_REG_ENTRY_KILL_RING_MAX)), 1);\r
994                                 }\r
995                         }\r
996                 }\r
997                 // Do NOT write break; here.\r
998         case 2:\r
999                 {\r
1000                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1001                                 CString szEntry;\r
1002                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
1003 \r
1004                                 CString szApplicationName;\r
1005                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
1006                                 if (szApplicationName.IsEmpty()) {\r
1007                                         continue;\r
1008                                 }\r
1009 \r
1010                                 // Chaged a label from Enter to newline.\r
1011                                 CString szSrcSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
1012                                 szSrcSubKey += _T("\\") + szApplicationName + _T("\\") + _T("Enter");\r
1013                                 CString szDestSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
1014                                 szDestSubKey += _T("\\") + szApplicationName + _T("\\") + _T("newline");\r
1015                                 HKEY hKeyDest = NULL;\r
1016                                 if (RegCreateKeyEx(HKEY_CURRENT_USER, szDestSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyDest, NULL) == ERROR_SUCCESS) {\r
1017                                         SHCopyKey(HKEY_CURRENT_USER, szSrcSubKey, hKeyDest, NULL);\r
1018                                         SHDeleteKey(HKEY_CURRENT_USER, szSrcSubKey);\r
1019                                         RegCloseKey(hKeyDest);\r
1020                                 }\r
1021                         }\r
1022                 }\r
1023                 // Do NOT write break; here.\r
1024         case 3:\r
1025                 {\r
1026                         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1027                                 CString szEntry;\r
1028                                 szEntry.Format(IDS_REG_ENTRY_APPLICATION, nApplicationID);\r
1029 \r
1030                                 CString szApplicationName;\r
1031                                 szApplicationName = AfxGetApp()->GetProfileString(CString(MAKEINTRESOURCE(IDS_REG_SECTION_APPLICATION)), szEntry);\r
1032                                 if (szApplicationName.IsEmpty()) {\r
1033                                         continue;\r
1034                                 }\r
1035 \r
1036                                 // rename original function to remove IDS_REG_ORIGINAL_PREFIX\r
1037                                 for (int nFunctionID = 0; nFunctionID < CDotXkeymacs::GetFunctionNumber(); ++nFunctionID) {\r
1038                                         HKEY hKey = NULL;\r
1039                                         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA));\r
1040                                         szSubKey += _T("\\") + szApplicationName + _T("\\") + CString(MAKEINTRESOURCE(IDS_REG_ORIGINAL_PREFIX)) + CDotXkeymacs::GetFunctionSymbol(nFunctionID);\r
1041                                         if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {\r
1042                                                 // Use registry data\r
1043                                                 TCHAR szKeyBind[128] = {'\0'};\r
1044                                                 DWORD dwKeyBind = sizeof(szKeyBind);\r
1045                                                 FILETIME ft = {'\0'};   // not use\r
1046                                                 for (DWORD dwIndex = 0; RegEnumKeyEx(hKey, dwIndex, szKeyBind, &dwKeyBind, NULL, NULL, NULL, &ft) == ERROR_SUCCESS; ++dwIndex) {\r
1047                                                         int nCommandType = 0;\r
1048                                                         int nKey = 0;\r
1049                                                         ReadKeyBind(&nCommandType, &nKey, szKeyBind);\r
1050                                                         SaveKeyBind(szApplicationName, CDotXkeymacs::GetFunctionSymbol(nFunctionID), nCommandType, nKey);\r
1051 \r
1052                                                         memset(szKeyBind, 0, sizeof(szKeyBind));\r
1053                                                         dwKeyBind = sizeof(szKeyBind);\r
1054                                                 }\r
1055                                                 RegCloseKey(hKey);\r
1056                                         }\r
1057                                 }\r
1058                         }\r
1059                 }\r
1060 //      case 4:\r
1061 //              foo();\r
1062 //      ...\r
1063 //      case nLatestLevel-1:\r
1064 //              bar();\r
1065                 AfxGetApp()->WriteProfileInt(szSection, szEntry, nLatestLevel);\r
1066                 break;\r
1067         default:\r
1068                 break;\r
1069         }\r
1070 }\r
1071 \r
1072 void CProfile::InitDllData()\r
1073 {\r
1074         LoadRegistryData();\r
1075         SetDllData();\r
1076 }\r
1077 \r
1078 void CProfile::ClearData(const CString szCurrentApplication)\r
1079 {\r
1080         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1081                 if (m_XkeymacsData[nApplicationID].GetApplicationName() == szCurrentApplication) {\r
1082                         break;\r
1083                 }\r
1084         }\r
1085         if (nApplicationID < MAX_APP) {\r
1086                 m_XkeymacsData[nApplicationID].ClearAll();\r
1087         }\r
1088 }\r
1089 \r
1090 // return count of saved settings\r
1091 int CProfile::GetSavedSettingCount()\r
1092 {\r
1093         int nSavedSetting = 0;\r
1094 \r
1095         for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1096                 CString szApplicationName;\r
1097                 szApplicationName = m_XkeymacsData[nApplicationID].GetApplicationName();\r
1098                 if (!szApplicationName.IsEmpty()) {\r
1099                         ++nSavedSetting;\r
1100                 }\r
1101         }\r
1102 \r
1103         return nSavedSetting;\r
1104 }\r
1105 \r
1106 void CProfile::InitApplicationList(CComboBox *const cApplicationList)\r
1107 {\r
1108         cApplicationList->ResetContent();\r
1109 \r
1110         m_dwTasks = GetTaskList(m_TaskList, MAX_TASKS);\r
1111 \r
1112         EnumWindows(EnumWindowsProc, (LPARAM)cApplicationList);\r
1113 \r
1114         for (int i = 0; i < MAX_APP; ++i) {\r
1115                 CString szApplicationName       = m_XkeymacsData[i].GetApplicationName();\r
1116                 CString szApplicationTitle      = m_XkeymacsData[i].GetApplicationTitle();\r
1117 \r
1118                 CString szListItem;\r
1119                 szListItem.Format(IDS_APPLICATION_LIST_ITEM, szApplicationTitle, szApplicationName);\r
1120                 if (IsNotSameString(cApplicationList, szListItem)\r
1121                  && !IsDefault(szApplicationName)\r
1122                  && !IsDialog(szApplicationName)\r
1123                  && !szApplicationName.IsEmpty()) {\r
1124                         cApplicationList->AddString(szListItem);\r
1125                 }\r
1126         }\r
1127 \r
1128         // Add IME\r
1129         HKL hKL = GetKeyboardLayout(0);\r
1130         if (ImmIsIME(hKL)) {\r
1131                 LPTSTR szIMEDescription = NULL;\r
1132                 UINT nIMEDescription = ImmGetDescription(hKL, NULL, 0);\r
1133                 if (nIMEDescription) {\r
1134                         nIMEDescription += sizeof(TCHAR);       // for NULL\r
1135                         if ((szIMEDescription = new TCHAR[nIMEDescription]) != NULL) {\r
1136                                 ImmGetDescription(hKL, szIMEDescription, nIMEDescription);\r
1137                         }\r
1138 //                      CUtils::Log(_T("nIMEDescription = %d, szIMEDescription = _%s_"), nIMEDescription, szIMEDescription);\r
1139                 }\r
1140 \r
1141                 LPTSTR szIMEFileName = NULL;\r
1142                 UINT nIMEFileName = ImmGetIMEFileName(hKL, NULL, 0);\r
1143                 if (nIMEFileName) {\r
1144                         nIMEFileName += sizeof(TCHAR);\r
1145                         if ((szIMEFileName = new TCHAR[nIMEFileName]) != NULL) {\r
1146                                 ImmGetIMEFileName(hKL, szIMEFileName, nIMEFileName);\r
1147                         }\r
1148 //                      CUtils::Log(_T("nIMEFileName = %d, szIMEFileName = _%s_"), nIMEFileName, szIMEFileName);\r
1149                 }\r
1150 \r
1151                 CString szIMETitle;\r
1152                 CString szIME(MAKEINTRESOURCE(IDS_IME_FILE_NAME));\r
1153                 szIMETitle.Format(IDS_APPLICATION_LIST_ITEM, szIMEDescription ? szIMEDescription : szIME, szIMEFileName ? szIMEFileName : szIME);\r
1154 //              CUtils::Log(_T("szIMETitle = _%s_, szIMEDescription = _%s_, szIMEFileName = _%s_"), szIMETitle, szIMEDescription, szIMEFileName);\r
1155                 if (IsNotSameString(cApplicationList, szIMETitle)) {\r
1156                         cApplicationList->AddString(szIMETitle);\r
1157                 }\r
1158 \r
1159                 delete[] szIMEDescription;\r
1160                 szIMEDescription = NULL;\r
1161                 delete[] szIMEFileName;\r
1162                 szIMEFileName = NULL;\r
1163         }\r
1164 \r
1165         // Add Dialog\r
1166         cApplicationList->InsertString(0, CString(MAKEINTRESOURCE(IDS_DIALOG_TITLE)));\r
1167 \r
1168         // Add Default\r
1169         cApplicationList->InsertString( 0, CString(MAKEINTRESOURCE(IDS_DEFAULT_TITLE)));\r
1170         cApplicationList->SelectString(-1, CString(MAKEINTRESOURCE(IDS_DEFAULT_TITLE)));\r
1171 }\r
1172 \r
1173 DWORD CProfile::GetTaskList(PTASK_LIST pTask, const DWORD dwNumTasks)\r
1174 {\r
1175         for (int i = 0; i < MAX_TASKS; ++i) {\r
1176                 ZeroMemory(&pTask[i], sizeof(PTASK_LIST));\r
1177         }\r
1178 \r
1179         OSVERSIONINFO verInfo = {0};\r
1180         verInfo.dwOSVersionInfoSize = sizeof (verInfo);\r
1181         GetVersionEx(&verInfo);\r
1182         if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT\r
1183          && verInfo.dwMajorVersion < 5) {\r
1184                 return GetTaskListNT(pTask, dwNumTasks);\r
1185         }\r
1186 \r
1187         HMODULE hKernel = GetModuleHandle(_T("KERNEL32.DLL"));\r
1188         if (!hKernel) {\r
1189                 return 0;\r
1190         }\r
1191 \r
1192         CREATESNAPSHOT pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");\r
1193         if (!pCreateToolhelp32Snapshot) {\r
1194                 return 0;\r
1195         }\r
1196 \r
1197         PROCESSWALK pProcess32First = (PROCESSWALK)GetProcAddress(hKernel, "Process32First");\r
1198         if (!pProcess32First) {\r
1199                 return 0;\r
1200         }\r
1201 \r
1202         PROCESSWALK pProcess32Next = (PROCESSWALK)GetProcAddress(hKernel, "Process32Next");\r
1203         if (!pProcess32Next) {\r
1204                 return 0;\r
1205         }\r
1206 \r
1207         HANDLE hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
1208         if (hProcessSnap == (HANDLE)-1) {\r
1209                 return 0;\r
1210         }\r
1211 \r
1212         DWORD dwTaskCount = 0;\r
1213         PROCESSENTRY32 processEntry32 = {sizeof(PROCESSENTRY32)};\r
1214         if (pProcess32First(hProcessSnap, &processEntry32)) {\r
1215                 do {\r
1216                         LPTSTR pCurChar = NULL;\r
1217                         for (pCurChar = processEntry32.szExeFile + lstrlen(processEntry32.szExeFile); *pCurChar != _T('\\') && pCurChar != processEntry32.szExeFile; --pCurChar) {\r
1218                                 ;\r
1219                         }\r
1220                         if (*pCurChar == _T('\\')) {\r
1221                                 ++pCurChar;\r
1222                         }\r
1223 \r
1224                         lstrcpy(pTask->ProcessName, pCurChar);\r
1225                         pTask->dwProcessId = processEntry32.th32ProcessID;\r
1226 \r
1227                         ++dwTaskCount;\r
1228                         ++pTask;\r
1229                 } while (dwTaskCount < dwNumTasks && pProcess32Next(hProcessSnap, &processEntry32));\r
1230         }\r
1231 \r
1232         CloseHandle(hProcessSnap);\r
1233         return dwTaskCount;\r
1234 }\r
1235 \r
1236 LPBYTE CProfile::GetCounters()\r
1237 {\r
1238         LANGID lid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);\r
1239         CString szSubKey;\r
1240         szSubKey.Format(CString(MAKEINTRESOURCE(IDS_REGSUBKEY_PERF)), lid);\r
1241         HKEY hKey = NULL;\r
1242         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {\r
1243                 return NULL;\r
1244         }\r
1245 \r
1246         DWORD dwSize = 0;\r
1247         if (RegQueryValueEx(hKey, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_COUNTERS)), NULL, NULL, NULL, &dwSize) != ERROR_SUCCESS) {\r
1248                 RegCloseKey(hKey);\r
1249                 return NULL;\r
1250         }\r
1251         LPBYTE pCounters = (LPBYTE) calloc(dwSize, sizeof(BYTE));\r
1252         if (pCounters == NULL) {\r
1253                 RegCloseKey(hKey);\r
1254                 return NULL;\r
1255         }\r
1256         if (RegQueryValueEx(hKey, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_COUNTERS)), NULL, NULL, pCounters, &dwSize) != ERROR_SUCCESS) {\r
1257                 RegCloseKey(hKey);\r
1258                 free(pCounters);\r
1259                 return NULL;\r
1260         }\r
1261         RegCloseKey(hKey);\r
1262         return pCounters;\r
1263 }\r
1264 \r
1265 BOOL CProfile::GetProcessInfo(CString *const szProcessName, DWORD *const dwProcessId)\r
1266 {\r
1267         LPBYTE pCounters = GetCounters();\r
1268         if (!pCounters) {\r
1269                 return FALSE;\r
1270         }\r
1271         LPTSTR pTopOfString = (LPTSTR)pCounters;\r
1272         while (*pTopOfString) {\r
1273                 if (_tcsicmp(pTopOfString, CString(MAKEINTRESOURCE(IDS_PROCESS))) == 0) {\r
1274                         for (LPTSTR p2 = pTopOfString - 2; _istdigit(*p2); --p2) {\r
1275                                 ;\r
1276                         }\r
1277                         szProcessName->Format(_T("%s"), p2 + 1);        // 230\r
1278                 } else if (_tcsicmp(pTopOfString, CString(MAKEINTRESOURCE(IDS_PROCESSID))) == 0) {\r
1279                         for (LPTSTR p2 = pTopOfString - 2; _istdigit(*p2); --p2) {\r
1280                                 ;\r
1281                         }\r
1282                         *dwProcessId = _ttol(p2 + 1);                   // 784\r
1283                 }\r
1284                 pTopOfString += (_tcslen(pTopOfString) + 1);\r
1285         }\r
1286         free(pCounters);\r
1287         return TRUE;\r
1288 }\r
1289 \r
1290 PPERF_DATA_BLOCK CProfile::GetPerformanceData(const CString szProcessName)\r
1291 {\r
1292         DWORD dwSize = INITIAL_SIZE;\r
1293         PPERF_DATA_BLOCK pPerformanceData = (PPERF_DATA_BLOCK) calloc(dwSize, sizeof(BYTE));\r
1294         if (pPerformanceData == NULL) {\r
1295                 return NULL;\r
1296         }\r
1297 \r
1298         for (;;) {\r
1299                 switch (RegQueryValueEx(HKEY_PERFORMANCE_DATA, szProcessName, NULL, NULL, (LPBYTE)pPerformanceData, &dwSize)) {\r
1300                 case ERROR_SUCCESS:\r
1301                         if (0 < dwSize\r
1302                          && pPerformanceData->Signature[0] == (WCHAR)'P'\r
1303                          && pPerformanceData->Signature[1] == (WCHAR)'E'\r
1304                          && pPerformanceData->Signature[2] == (WCHAR)'R'\r
1305                          && pPerformanceData->Signature[3] == (WCHAR)'F') {\r
1306                                 return pPerformanceData;\r
1307                         }\r
1308                 case ERROR_MORE_DATA:\r
1309                         dwSize += EXTEND_SIZE;\r
1310                         pPerformanceData = (PPERF_DATA_BLOCK) realloc(pPerformanceData, dwSize);\r
1311                         if (!pPerformanceData) {\r
1312                                 return NULL;\r
1313                         }\r
1314                         memset(pPerformanceData, 0, dwSize);\r
1315                         break;\r
1316                 default:\r
1317                         free(pPerformanceData);\r
1318                         return NULL;\r
1319                 }\r
1320         }\r
1321 }\r
1322 \r
1323 // Add running application's names to the list\r
1324 // only for _Windows NT_\r
1325 DWORD CProfile::GetTaskListNT(PTASK_LIST pTask, DWORD dwNumTasks)\r
1326 {\r
1327         CString szProcessName;\r
1328         DWORD dwProcessIdTitle = 0;\r
1329         if (!GetProcessInfo(&szProcessName, &dwProcessIdTitle)) {\r
1330                 return dwNumTasks;\r
1331         }\r
1332 \r
1333         PPERF_DATA_BLOCK pPerformanceData = GetPerformanceData(szProcessName);\r
1334         if (!pPerformanceData) {\r
1335                 return dwNumTasks;\r
1336         }\r
1337 \r
1338         PPERF_OBJECT_TYPE pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerformanceData + pPerformanceData->HeaderLength);\r
1339         PPERF_COUNTER_DEFINITION pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);\r
1340         DWORD dwProcessIdCounter = 0;\r
1341         for (DWORD i = 0; i < pObj->NumCounters; ++i) {\r
1342                 if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {\r
1343                         dwProcessIdCounter = pCounterDef->CounterOffset;\r
1344                         break;\r
1345                 }\r
1346                 ++pCounterDef;\r
1347         }\r
1348 \r
1349         dwNumTasks = min(dwNumTasks - 1, (DWORD)pObj->NumInstances);\r
1350         PPERF_INSTANCE_DEFINITION pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);\r
1351         for (i = 0; i < dwNumTasks; ++i) {\r
1352                 LPCWSTR pProcessName = (LPCWSTR) ((DWORD)pInst + pInst->NameOffset);\r
1353 \r
1354                 CHAR szProcessName[MAX_PATH] = {'\0'};\r
1355                 if (!WideCharToMultiByte(CP_ACP, 0, pProcessName, -1, szProcessName, sizeof(szProcessName), NULL, NULL)) {\r
1356                         _tcscpy(pTask->ProcessName, CString(MAKEINTRESOURCE(IDS_UNKNOWN_TASK)));\r
1357                 }\r
1358 \r
1359                 if (_tcslen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {\r
1360                         _tcscpy(pTask->ProcessName, szProcessName);\r
1361                         _tcscat(pTask->ProcessName, CString(MAKEINTRESOURCE(IDS_EXTENSION_EXECUTABLE)));\r
1362                 }\r
1363 \r
1364                 PPERF_COUNTER_BLOCK pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);\r
1365                 pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));\r
1366                 if (pTask->dwProcessId == 0) {\r
1367                         pTask->dwProcessId = (DWORD) -2;\r
1368                 }\r
1369 \r
1370                 ++pTask;\r
1371                 pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);\r
1372         }\r
1373 \r
1374         free(pPerformanceData);\r
1375         return dwNumTasks;\r
1376 }\r
1377 \r
1378 // return application index\r
1379 // and update setting style\r
1380 // if there is NOT the application in the data, this function takes care of it.\r
1381 int CProfile::GetApplicationIndex(const CString szApplicationName, const BOOL bSaveAndValidate, int *const nSettingStyle)\r
1382 {\r
1383         if (!bSaveAndValidate) {        // SetDialogData\r
1384                 *nSettingStyle = SETTING_UNDEFINED;\r
1385         }\r
1386 \r
1387         int nApplicationID = GetApplicationIndex(szApplicationName);\r
1388 \r
1389         if (nApplicationID == MAX_APP) {\r
1390                 if (bSaveAndValidate) { // GetDialogData\r
1391                         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1392                                 CString sz = m_XkeymacsData[nApplicationID].GetApplicationName();\r
1393                                 if (sz.IsEmpty()) {\r
1394                                         m_XkeymacsData[nApplicationID].SetApplicationName(szApplicationName);\r
1395                                         break;\r
1396                                 }\r
1397                         }\r
1398                         if (nApplicationID == MAX_APP) {\r
1399                                 return nApplicationID;\r
1400                         }\r
1401                 } else {                                // SetDialogData\r
1402                         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1403                                 if (IsDefault(m_XkeymacsData[nApplicationID].GetApplicationName())) {\r
1404                                         *nSettingStyle = SETTING_DEFAULT;\r
1405                                         break;\r
1406                                 }\r
1407                         }\r
1408                         if (nApplicationID == MAX_APP) {\r
1409                                 return nApplicationID;\r
1410                         }\r
1411                 }\r
1412         }\r
1413 \r
1414         if (bSaveAndValidate) { // GetDialogData\r
1415                 m_XkeymacsData[nApplicationID].SetSettingStyle(*nSettingStyle);\r
1416         } else {                                // SetDialogData\r
1417                 if (*nSettingStyle == SETTING_UNDEFINED) {      // It means that *nSettingStyle != SETTING_DEFAULT.\r
1418                         *nSettingStyle = m_XkeymacsData[nApplicationID].GetSettingStyle();\r
1419                 }\r
1420         }\r
1421 \r
1422         return nApplicationID;\r
1423 }\r
1424 \r
1425 BOOL CProfile::IsTheString(const CString sz, const UINT nID)\r
1426 {\r
1427         return sz == CString(MAKEINTRESOURCE(nID));\r
1428 }\r
1429 \r
1430 // if sz is "Default", return TRUE\r
1431 BOOL CProfile::IsDefault(const CString sz)\r
1432 {\r
1433         return IsTheString(sz, IDS_DEFAULT);\r
1434 }\r
1435 \r
1436 // if sz is "Dialog", return TRUE\r
1437 BOOL CProfile::IsDialog(const CString sz)\r
1438 {\r
1439         return IsTheString(sz, IDS_DIALOG);\r
1440 }\r
1441 \r
1442 void CProfile::GetApplicationTitle(CComboBox *const cApplicationList, CString &rList, const int nIndex)\r
1443 {\r
1444         if (0 <= nIndex) {\r
1445                 cApplicationList->GetLBText(nIndex, rList);\r
1446         } else {\r
1447                 cApplicationList->GetWindowText(rList);\r
1448         }\r
1449 \r
1450         if (IsTheString(rList, IDS_DEFAULT_TITLE)) {\r
1451                 rList.LoadString(IDS_DEFAULT);\r
1452         }\r
1453 \r
1454         if (IsTheString(rList, IDS_DIALOG_TITLE)) {\r
1455                 rList.LoadString(IDS_DIALOG);\r
1456         }\r
1457 \r
1458         return;\r
1459 }\r
1460 \r
1461 void CProfile::UpdateApplicationTitle(CComboBox *const cApplicationList, const CString szCurrentApplication, const int nApplicationID, const BOOL bSaveAndValidate)\r
1462 {\r
1463         static CString szApplicationTitle;\r
1464         if (bSaveAndValidate) { // GetDialogData\r
1465                 if (!CProfile::IsDefault(szCurrentApplication)) {\r
1466                         m_XkeymacsData[nApplicationID].SetApplicationTitle(szApplicationTitle);\r
1467                 }\r
1468                 szApplicationTitle.Empty();\r
1469         } else {                                // SetDialogData\r
1470                 CString szListItem;\r
1471                 CProfile::GetApplicationTitle(cApplicationList, szListItem);\r
1472                 int nEndTitle = szListItem.ReverseFind(_T('('));\r
1473                 if (nEndTitle > 0) {\r
1474                         szApplicationTitle = szListItem.Left(nEndTitle);\r
1475                 }\r
1476         }\r
1477 }\r
1478 \r
1479 void CProfile::SetCommandID(const int nApplicationID, const int nCommandType, const int nKey, int nCommandID)\r
1480 {\r
1481         if (nKey == 0xf0 && Commands[nCommandID].fCommand == CCommands::C_) {\r
1482                 // Change CommandID C_Eisu\r
1483                 for (nCommandID = 1; nCommandID < MAX_COMMAND; ++nCommandID) {\r
1484                         if (Commands[nCommandID].fCommand == CCommands::C_Eisu) {\r
1485                                 break;\r
1486                         }\r
1487                 }\r
1488         }\r
1489         m_XkeymacsData[nApplicationID].SetCommandID(nCommandType, nKey, nCommandID);\r
1490 }\r
1491 \r
1492 int CProfile::GetCommandID(const int nApplicationID, const int nCommandType, const int nKey)\r
1493 {\r
1494         int nCommandID = m_XkeymacsData[nApplicationID].GetCommandID(nCommandType, nKey);\r
1495         if (nKey == 0xf0 && Commands[nCommandID].fCommand == CCommands::C_Eisu) {\r
1496                 // Change CommandID C_\r
1497                 for (nCommandID = 1; nCommandID < MAX_COMMAND; ++nCommandID) {\r
1498                         if (Commands[nCommandID].fCommand == CCommands::C_) {\r
1499                                 break;\r
1500                         }\r
1501                 }\r
1502         }\r
1503         return nCommandID;\r
1504 }\r
1505 \r
1506 void CProfile::SetKillRingMax(const int nApplicationID, const int nKillRingMax)\r
1507 {\r
1508         m_XkeymacsData[nApplicationID].SetKillRingMax(nKillRingMax);\r
1509 }\r
1510 \r
1511 int CProfile::GetKillRingMax(const int nApplicationID)\r
1512 {\r
1513         return m_XkeymacsData[nApplicationID].GetKillRingMax();\r
1514 }\r
1515 \r
1516 void CProfile::SetUseDialogSetting(const int nApplicationID, const BOOL bUseDialogSetting)\r
1517 {\r
1518         m_XkeymacsData[nApplicationID].SetUseDialogSetting(bUseDialogSetting);\r
1519 }\r
1520 \r
1521 BOOL CProfile::GetUseDialogSetting(const int nApplicationID)\r
1522 {\r
1523         return m_XkeymacsData[nApplicationID].GetUseDialogSetting();\r
1524 }\r
1525 \r
1526 void CProfile::SetWindowText(const int nApplicationID, const CString szWindowText)\r
1527 {\r
1528         m_XkeymacsData[nApplicationID].SetWindowText(szWindowText);\r
1529 }\r
1530 \r
1531 CString CProfile::GetWindowText(const int nApplicationID)\r
1532 {\r
1533         return m_XkeymacsData[nApplicationID].GetWindowText();\r
1534 }\r
1535 \r
1536 void CProfile::DeleteAllRegistryData()\r
1537 {\r
1538         HKEY hkey = NULL;\r
1539         if (RegOpenKeyEx(HKEY_CURRENT_USER, CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)), 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) {\r
1540                 // I am sure that I have to do only one time, but...\r
1541                 for (int nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1542                         DWORD dwIndex = 0;\r
1543                         TCHAR szName[SUB_KEY_NAME_LENGTH] = {'\0'};\r
1544                         DWORD dwName = sizeof(szName);\r
1545                         FILETIME filetime;\r
1546 \r
1547                         while (RegEnumKeyEx(hkey, dwIndex++, szName, &dwName, NULL, NULL, NULL, &filetime) == ERROR_SUCCESS) {\r
1548 //                              RegDeleteKey(hkey, szName);\r
1549                                 SHDeleteKey(hkey, szName);\r
1550                                 ZeroMemory(szName, sizeof(szName));\r
1551                                 dwName = sizeof(szName);\r
1552                         }\r
1553                 }\r
1554                 RegCloseKey(hkey);\r
1555         }\r
1556 }\r
1557 \r
1558 int CProfile::GetCurrentApplicationID(CComboBox *const cApplicationList, const CString szCurrentApplication)\r
1559 {\r
1560         int nCounter = cApplicationList->GetCount();\r
1561         CString szListItem;\r
1562         int nCurSel = cApplicationList->GetCurSel();\r
1563 \r
1564         for (int i = 0; i < nCounter; ++i) {\r
1565                 cApplicationList->SetCurSel(i);\r
1566                 CProfile::GetApplicationTitle(cApplicationList, szListItem);\r
1567                 if (szListItem.Find(szCurrentApplication) != -1) {\r
1568                         cApplicationList->SetCurSel(nCurSel);\r
1569                         return i;\r
1570                 }\r
1571         }\r
1572         return -1;\r
1573 }\r
1574 \r
1575 void CProfile::CopyData(const CString szDestinationApplication, const CString szSourceApplication)\r
1576 {\r
1577         int nSettingStyle = SETTING_SPECIFIC;\r
1578         int nDestinationApplication = GetApplicationIndex(szDestinationApplication, TRUE, &nSettingStyle);\r
1579         int nSourceApplication = GetApplicationIndex(szSourceApplication);\r
1580 \r
1581         CString szApplicationName = m_XkeymacsData[nDestinationApplication].GetApplicationName();\r
1582         CString szApplicationTitle = m_XkeymacsData[nDestinationApplication].GetApplicationTitle();\r
1583         CString szWindowText = m_XkeymacsData[nDestinationApplication].GetWindowText();\r
1584         int nWindowTextType = m_XkeymacsData[nDestinationApplication].GetWindowTextType();\r
1585 \r
1586         m_XkeymacsData[nDestinationApplication] = m_XkeymacsData[nSourceApplication];\r
1587 \r
1588         m_XkeymacsData[nDestinationApplication].SetApplicationName(szApplicationName);\r
1589         m_XkeymacsData[nDestinationApplication].SetApplicationTitle(szApplicationTitle);\r
1590         m_XkeymacsData[nDestinationApplication].SetWindowText(szWindowText);\r
1591         m_XkeymacsData[nDestinationApplication].SetWindowTextType(nWindowTextType);\r
1592 }\r
1593 \r
1594 // return application index\r
1595 // if there is NOT the application in the data, return MAX_APP\r
1596 int CProfile::GetApplicationIndex(const CString szApplicationName)\r
1597 {\r
1598         int nApplicationID = 0;\r
1599         for (nApplicationID = 0; nApplicationID < MAX_APP; ++nApplicationID) {\r
1600                 if (m_XkeymacsData[nApplicationID].GetApplicationName() == szApplicationName) {\r
1601                         break;\r
1602                 }\r
1603         }\r
1604         return nApplicationID;\r
1605 }\r
1606 \r
1607 BOOL CProfile::Is106Keyboard()\r
1608 {\r
1609         static KEYBOARD_TYPE keyboard = UNKNOWN_KEYBOARD;\r
1610 \r
1611         if (keyboard == UNKNOWN_KEYBOARD) {\r
1612                 OSVERSIONINFO verInfo = {0};\r
1613                 verInfo.dwOSVersionInfoSize = sizeof (verInfo);\r
1614                 GetVersionEx(&verInfo);\r
1615 \r
1616                 DWORD subtype = 0;\r
1617                 DWORD cbData = sizeof(subtype);\r
1618 \r
1619                 if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
1620                         HKEY hKey = NULL;\r
1621                         CString szSubKey(_T("SYSTEM\\CurrentControlSet\\Services\\i8042prt\\Parameters"));\r
1622                         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
1623                                 static const CString szValueName(_T("OverrideKeyboardSubtype"));\r
1624                                 if (RegQueryValueEx(hKey, szValueName, NULL, NULL, (LPBYTE)&subtype, &cbData) != ERROR_SUCCESS) {\r
1625                                         subtype = 0;\r
1626                                 }\r
1627                                 RegCloseKey(hKey);\r
1628                         }\r
1629                 } else if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {\r
1630                         subtype = GetPrivateProfileInt(_T("keyboard"), _T("subtype"), 0, _T("system.ini"));\r
1631                 }\r
1632 \r
1633                 keyboard = (subtype & 0x02) ? JAPANESE_KEYBOARD : ENGLISH_KEYBOARD;\r
1634         }\r
1635 \r
1636         return keyboard == JAPANESE_KEYBOARD;\r
1637 }\r
1638 \r
1639 void CProfile::LoadScanCodeMap(const HKEY_TYPE hkeyType)\r
1640 {\r
1641         memset(m_ScanCodeMap[hkeyType], 0, sizeof(m_ScanCodeMap[hkeyType]));\r
1642         memset(m_CurrentScanCodeMap[hkeyType], 0, sizeof(m_CurrentScanCodeMap[hkeyType]));\r
1643 \r
1644         CString szSubKey;\r
1645         CString szValueName;\r
1646         HKEY hKey = HKEY_LOCAL_MACHINE;\r
1647         if (IsNT()) {\r
1648                 switch (hkeyType) {\r
1649                 case CURRENT_USER:\r
1650                         hKey = HKEY_CURRENT_USER;\r
1651                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
1652                         break;\r
1653                 case LOCAL_MACHINE:\r
1654                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
1655                         break;\r
1656                 default:\r
1657                         return;\r
1658                 }\r
1659                 szValueName.LoadString(IDS_SCANCODE_MAP);\r
1660         } else if (Is9x()) {\r
1661                 szSubKey.LoadString(IDS_REGSUBKEY_KEY_REMAP);\r
1662                 szValueName.LoadString(IDS_0);\r
1663         } else {\r
1664                 return;\r
1665         }\r
1666 \r
1667         HKEY hkResult = NULL;\r
1668         if (RegOpenKeyEx(hKey, szSubKey, 0, KEY_QUERY_VALUE, &hkResult) == ERROR_SUCCESS) {\r
1669                 // get data size\r
1670                 DWORD dwType = REG_BINARY;\r
1671                 DWORD dwData = 0;\r
1672                 RegQueryValueEx(hkResult, szValueName, NULL, &dwType, NULL, &dwData);\r
1673 \r
1674                 // get data\r
1675                 LPBYTE lpData = new BYTE[dwData];\r
1676                 if (lpData) {\r
1677                         RegQueryValueEx(hkResult, szValueName, NULL, &dwType, lpData, &dwData);\r
1678                 }\r
1679                 RegCloseKey(hkResult);\r
1680 \r
1681                 if (IsNT()) {\r
1682                         if (lpData && dwData) {\r
1683                                 DWORD offset = 0;\r
1684                                 offset += 8;    // skip Version Information and Flags\r
1685                                 DWORD *pdwMappings = (DWORD *)(lpData + offset);\r
1686                                 offset += 4;    // skip Number of Mappings\r
1687                                 DWORD *pdwNullTerminator = (DWORD *)(lpData + dwData - 4);\r
1688 \r
1689                                 if (4 * *pdwMappings + 12 != dwData) {\r
1690                                         // illegal data\r
1691                                 } else if (*pdwNullTerminator != 0) {\r
1692                                         // illegal data\r
1693                                 } else {\r
1694                                         while (offset < dwData - 4) {\r
1695                                                 ScanCodeMapping *pMapping = (ScanCodeMapping *)(lpData + offset);\r
1696                                                 offset += 4;    // go to next data\r
1697                                                 m_CurrentScanCodeMap[hkeyType][PrefixedScanCode2ID(pMapping->original.nPrefixedScanCode)][pMapping->original.nScanCode].nPrefixedScanCode = pMapping->current.nPrefixedScanCode;\r
1698                                                 m_CurrentScanCodeMap[hkeyType][PrefixedScanCode2ID(pMapping->original.nPrefixedScanCode)][pMapping->original.nScanCode].nScanCode = pMapping->current.nScanCode;\r
1699                                                 m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(pMapping->original.nPrefixedScanCode)][pMapping->original.nScanCode].nPrefixedScanCode = pMapping->current.nPrefixedScanCode;\r
1700                                                 m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(pMapping->original.nPrefixedScanCode)][pMapping->original.nScanCode].nScanCode = pMapping->current.nScanCode;\r
1701                                         }\r
1702                                 }\r
1703                         }\r
1704                 }\r
1705                 delete[] lpData;\r
1706                 lpData = NULL;\r
1707         }\r
1708 }\r
1709 \r
1710 int CProfile::LostKeyWarning(const HKEY_TYPE hkeyType)\r
1711 {\r
1712         if (!ChangedKeyboardLayout(hkeyType)) {\r
1713                 return IDOK;\r
1714         }\r
1715 \r
1716         CString szLostKeysList;\r
1717 \r
1718         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1719                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1720                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1721                                 BOOL lostKey = TRUE;\r
1722 \r
1723                                 for (int i = 0; i < 3 && lostKey; ++i) {\r
1724                                         for (int j = 0; j < 256 && lostKey; ++j) {\r
1725                                                 if (m_ScanCodeMap[hkeyType][i][j].nPrefixedScanCode == nPrefixedScanCodeID\r
1726                                                  && m_ScanCodeMap[hkeyType][i][j].nScanCode == nScanCode) {\r
1727                                                         lostKey = FALSE;\r
1728                                                 }\r
1729                                         }\r
1730                                 }\r
1731 \r
1732                                 if (lostKey) {\r
1733                                         for (int i = 0; i < sizeof(KeyboardLayouts)/sizeof(KeyboardLayouts[0]); ++i) {\r
1734                                                 if (KeyboardLayouts[i].scancode.nScanCode == nScanCode\r
1735                                                         && KeyboardLayouts[i].scancode.nPrefixedScanCode == nPrefixedScanCodeID) {\r
1736                                                         CString szLostKey;\r
1737                                                         szLostKey.Format(IDS_ERR_LOST_KEY, CString(MAKEINTRESOURCE(GetToolTipID(KeyboardLayouts[i].nToolTipID))));\r
1738                                                         szLostKeysList += szLostKey;\r
1739                                                         break;\r
1740                                                 }\r
1741                                         }\r
1742                                 }\r
1743                         }\r
1744                 }\r
1745         }\r
1746 \r
1747         if (szLostKeysList.IsEmpty()) {\r
1748                 return IDOK;\r
1749         }\r
1750 \r
1751         return AfxMessageBox(szLostKeysList, MB_OKCANCEL | MB_ICONEXCLAMATION);\r
1752 }\r
1753 \r
1754 void CProfile::SaveScanCodeMap(const HKEY_TYPE hkeyType)\r
1755 {\r
1756         CString szSubKey;\r
1757         CString szValueName;\r
1758         HKEY hKey = HKEY_LOCAL_MACHINE;\r
1759         if (IsNT()) {\r
1760                 switch (hkeyType) {\r
1761                 case CURRENT_USER:\r
1762                         hKey = HKEY_CURRENT_USER;\r
1763                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
1764                         break;\r
1765                 case LOCAL_MACHINE:\r
1766                         szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
1767                         break;\r
1768                 default:\r
1769                         return;\r
1770                 }\r
1771                 szValueName.LoadString(IDS_SCANCODE_MAP);\r
1772         } else if (Is9x()) {\r
1773                 szSubKey.LoadString(IDS_REGSUBKEY_KEY_REMAP);\r
1774                 szValueName.LoadString(IDS_0);\r
1775         } else {\r
1776                 return;\r
1777         }\r
1778 \r
1779         HKEY hkResult = NULL;\r
1780         if (RegCreateKeyEx(hKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkResult, NULL) == ERROR_SUCCESS) {\r
1781                 if (IsNT()) {\r
1782                         DWORD cbData = GetScanCodeLength(hkeyType);\r
1783                         if (cbData <= 16) {\r
1784                                 RegDeleteValue(hkResult, szValueName);\r
1785                         } else {\r
1786                                 LPBYTE lpData = new BYTE[cbData];\r
1787                                 memset(lpData, 0, sizeof(BYTE) * cbData);\r
1788 \r
1789                                 {\r
1790                                         DWORD dwMappings = (cbData - 12) / 4;\r
1791                                         memmove(lpData + 8, &dwMappings, 4);\r
1792                                 }\r
1793 \r
1794                                 int offset = 12;\r
1795                                 for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1796                                         for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1797                                                 if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1798                                                         ScanCodeMapping sScanCodeMapping = {'\0'};\r
1799                                                         sScanCodeMapping.original.nPrefixedScanCode = PrefixedScanCodeID2Code(nPrefixedScanCodeID);\r
1800                                                         sScanCodeMapping.original.nScanCode = (BYTE)nScanCode;\r
1801                                                         sScanCodeMapping.current.nPrefixedScanCode = m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode;\r
1802                                                         sScanCodeMapping.current.nScanCode = m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode;\r
1803                                                         memcpy(lpData + offset, &sScanCodeMapping, sizeof(sScanCodeMapping));\r
1804                                                         offset += sizeof(sScanCodeMapping);\r
1805                                                 }\r
1806                                         }\r
1807                                 }\r
1808                                 RegSetValueEx(hkResult, szValueName, 0, REG_BINARY, lpData, cbData);\r
1809 \r
1810                                 delete[] lpData;\r
1811                                 lpData = NULL;\r
1812                         }\r
1813                 }\r
1814                 RegCloseKey(hkResult);\r
1815         }\r
1816 \r
1817         // Do you want to restart computer?\r
1818         if (ChangedKeyboardLayout(hkeyType)) {\r
1819                 if (AfxMessageBox(CString(MAKEINTRESOURCE(IDS_RESTART_OR_NOT)), MB_YESNO | MB_ICONQUESTION) == IDYES) {\r
1820                         RestartComputer();\r
1821                 }\r
1822         }\r
1823 }\r
1824 \r
1825 // Return True if Windows 95, Windows 98, or Windows Me. \r
1826 BOOL CProfile::Is9x()\r
1827 {\r
1828         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1829         GetVersionEx(&info);\r
1830 \r
1831         if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {\r
1832                 return TRUE;\r
1833         }\r
1834         return FALSE;\r
1835 }\r
1836 \r
1837 // Return True if Windows NT 4.0, Windows 2000, Windows XP, Windows 2003 or Windows Vista.\r
1838 BOOL CProfile::IsNT()\r
1839 {\r
1840         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1841         GetVersionEx(&info);\r
1842 \r
1843         if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
1844                 return TRUE;\r
1845         }\r
1846         return FALSE;\r
1847 }\r
1848 \r
1849 // Return True if Windows Vista or later.\r
1850 BOOL CProfile::IsVistaOrLater()\r
1851 {\r
1852         OSVERSIONINFO info = {sizeof(OSVERSIONINFO)};\r
1853         GetVersionEx(&info);\r
1854 \r
1855         if (6 <= info.dwMajorVersion) {\r
1856                 return TRUE;\r
1857         }\r
1858         return FALSE;\r
1859 }\r
1860 \r
1861 void CProfile::RestartComputer()\r
1862 {\r
1863         if (!AdjustTokenPrivileges(SE_SHUTDOWN_NAME)) {\r
1864                 return;\r
1865         }\r
1866 \r
1867         ExitWindowsEx(EWX_REBOOT, 0);\r
1868 }\r
1869 \r
1870 int CProfile::GetControlID(const ScanCode scancode, const BOOL bBase)\r
1871 {\r
1872         for (int i = 0; ; ++i) {\r
1873                 if (KeyboardLayouts[i].scancode.nPrefixedScanCode == scancode.nPrefixedScanCode\r
1874                  && KeyboardLayouts[i].scancode.nScanCode == scancode.nScanCode) {\r
1875                         if (bBase) {\r
1876                                 return KeyboardLayouts[i].nBaseControlID;\r
1877                         } else {\r
1878                                 return KeyboardLayouts[i].nCurrentControlID;\r
1879                         }\r
1880                 }\r
1881         }\r
1882         return 0;\r
1883 }\r
1884 \r
1885 int CProfile::GetBaseControlID(const ScanCode scancode)\r
1886 {\r
1887         return GetControlID(scancode, TRUE);\r
1888 }\r
1889 \r
1890 int CProfile::GetCurrentControlID(const ScanCode scancode)\r
1891 {\r
1892         return GetControlID(scancode, FALSE);\r
1893 }\r
1894 \r
1895 BOOL CProfile::GetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCode original, ScanCode *const current)\r
1896 {\r
1897         if (!current) {\r
1898                 return FALSE;\r
1899         }\r
1900         *current = m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(original.nPrefixedScanCode)][original.nScanCode];\r
1901         return 0 < current->nScanCode;\r
1902 }\r
1903 \r
1904 void CProfile::SetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCodeMapping ScanCodeMappeing)\r
1905 {\r
1906         m_ScanCodeMap[hkeyType][PrefixedScanCode2ID(ScanCodeMappeing.original.nPrefixedScanCode)][ScanCodeMappeing.original.nScanCode] = ScanCodeMappeing.current;\r
1907 }\r
1908 \r
1909 int CProfile::PrefixedScanCode2ID(const BYTE nPrefixedScanCode)\r
1910 {\r
1911         int nID = 0;\r
1912 \r
1913         switch (nPrefixedScanCode) {\r
1914         case 0x00:\r
1915                 nID = 0;\r
1916                 break;\r
1917         case 0xe0:\r
1918                 nID = 1;\r
1919                 break;\r
1920         case 0xe1:\r
1921                 nID = 2;\r
1922                 break;\r
1923         default:\r
1924                 // invalid scan code\r
1925                 nID = 3;\r
1926                 break;\r
1927         }\r
1928 \r
1929         return nID;\r
1930 }\r
1931 \r
1932 BYTE CProfile::PrefixedScanCodeID2Code(const int nPrefixedScanCodeID)\r
1933 {\r
1934         BYTE nCode = 0;\r
1935 \r
1936         switch (nPrefixedScanCodeID) {\r
1937         case 0:\r
1938                 nCode = 0x00;\r
1939                 break;\r
1940         case 1:\r
1941                 nCode = 0xe0;\r
1942                 break;\r
1943         case 2:\r
1944                 nCode = 0xe1;\r
1945                 break;\r
1946         default:\r
1947                 ASSERT(0);\r
1948                 break;\r
1949         }\r
1950 \r
1951         return nCode;\r
1952 }\r
1953 \r
1954 DWORD CProfile::GetScanCodeLength(const HKEY_TYPE hkeyType)\r
1955 {\r
1956         DWORD dwScanCodeLength = 0;\r
1957         dwScanCodeLength += 4;  // Header: Version Information\r
1958         dwScanCodeLength += 4;  // Header: Flags\r
1959         dwScanCodeLength += 4;  // Header: Number of Mappings\r
1960         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1961                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1962                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1963                                 dwScanCodeLength += 4;  // Individual Mappings\r
1964                         }\r
1965                 }\r
1966         }\r
1967         dwScanCodeLength += 4;  // Null Terminator (0x00000000)\r
1968         return dwScanCodeLength;\r
1969 }\r
1970 \r
1971 BOOL CProfile::ChangedKeyboardLayout(const HKEY_TYPE hkeyType)\r
1972 {\r
1973         for (int nPrefixedScanCodeID = 0; nPrefixedScanCodeID < 3; ++nPrefixedScanCodeID) {\r
1974                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
1975                         if (m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode   != m_CurrentScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nPrefixedScanCode\r
1976                          || m_ScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode                   != m_CurrentScanCodeMap[hkeyType][nPrefixedScanCodeID][nScanCode].nScanCode) {\r
1977                                 return TRUE;\r
1978                         }\r
1979                 }\r
1980         }\r
1981 \r
1982         return FALSE;\r
1983 }\r
1984 \r
1985 void CProfile::SetDraggingCursor()\r
1986 {\r
1987         HCURSOR hCursor = (HCURSOR)LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDC_DRAG_CURSOR),\r
1988                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
1989         SetCursor(hCursor);\r
1990 }\r
1991 \r
1992 void CProfile::SetNormalCursor()\r
1993 {\r
1994         HCURSOR hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW),\r
1995                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
1996         SetCursor(hCursor);\r
1997 }\r
1998 \r
1999 void CProfile::SetNoCursor()\r
2000 {\r
2001         HCURSOR hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_NO),\r
2002                                                                                  IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
2003         SetCursor(hCursor);\r
2004 }\r
2005 \r
2006 int CProfile::GetToolTipID(int nToolTipID)\r
2007 {\r
2008         if (Is106Keyboard()) {\r
2009                 switch (nToolTipID) {\r
2010                 case IDS_EQUAL:                 // ^\r
2011                         nToolTipID = IDS_CARET;\r
2012                         break;\r
2013                 case IDS_SQUARE_BRA:    // @\r
2014                         nToolTipID = IDS_AT_MARK;\r
2015                         break;\r
2016                 case IDS_SQUARE_CKET:   // [\r
2017                         nToolTipID = IDS_SQUARE_BRA;\r
2018                         break;\r
2019                 case IDS_QUOTE:                 // :\r
2020                         nToolTipID = IDS_COLON;\r
2021                         break;\r
2022                 case IDS_BACK_QUOTE:    // Hankaku/Zenkaku\r
2023                         nToolTipID = IDS_HANKAKU;\r
2024                         break;\r
2025                 case IDS_BACKSLASH:             // ]\r
2026                         nToolTipID = IDS_SQUARE_CKET;\r
2027                         break;\r
2028                 }\r
2029         }\r
2030 \r
2031         return nToolTipID;\r
2032 }\r
2033 \r
2034 KeyboardLayout* CProfile::GetKeyboardLayouts(const int nKey)\r
2035 {\r
2036         for (int i = 0; i < sizeof(KeyboardLayouts) / sizeof(KeyboardLayouts[0]); ++i) {\r
2037                 if (KeyboardLayouts[i].nBaseControlID == nKey\r
2038                  || KeyboardLayouts[i].nCurrentControlID == nKey) {\r
2039                         return &KeyboardLayouts[i];\r
2040                 }\r
2041         }\r
2042         return NULL;\r
2043 }\r
2044 \r
2045 BOOL CProfile::AdjustTokenPrivileges(LPCTSTR lpName)\r
2046 {\r
2047         BOOL rc = TRUE;\r
2048 \r
2049         if (IsNT()) {\r
2050                 HANDLE hToken;\r
2051                 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
2052                         LUID luid;\r
2053                         if (LookupPrivilegeValue(NULL, lpName, &luid)) {\r
2054                                 TOKEN_PRIVILEGES tp;\r
2055                                 tp.PrivilegeCount = 1;\r
2056                                 tp.Privileges[0].Luid = luid;\r
2057                                 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
2058 \r
2059                                 if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {\r
2060                                         rc = FALSE;\r
2061                                 }\r
2062                         } else {\r
2063                                 rc = FALSE;\r
2064                         }\r
2065                         CloseHandle(hToken);\r
2066                 } else {\r
2067                         rc = FALSE;\r
2068                 }\r
2069         }\r
2070 \r
2071         return rc;\r
2072 }\r
2073 \r
2074 BOOL CProfile::DiableTokenPrivileges()\r
2075 {\r
2076         BOOL rc = TRUE;\r
2077 \r
2078         if (IsNT()) {\r
2079                 HANDLE hToken;\r
2080                 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
2081                         if (!::AdjustTokenPrivileges(hToken, TRUE, NULL, NULL, NULL, NULL)) {\r
2082                                 rc = FALSE;\r
2083                         }\r
2084                         CloseHandle(hToken);\r
2085                 } else {\r
2086                         rc = FALSE;\r
2087                 }\r
2088         }\r
2089 \r
2090         return rc;\r
2091 }\r
2092 \r
2093 void CProfile::ExportProperties()\r
2094 {\r
2095         if (!AdjustTokenPrivileges(SE_BACKUP_NAME)) {\r
2096                 return;\r
2097         }\r
2098 \r
2099         CFileDialog oFileOpenDialog(FALSE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
2100         if (oFileOpenDialog.DoModal() == IDOK) {\r
2101                 CString szCommandLine;\r
2102                 szCommandLine.Format(_T("regedit /e \"%s\" HKEY_CURRENT_USER\\%s"), oFileOpenDialog.GetPathName(), CString(MAKEINTRESOURCE(IDS_REGSUBKEY_DATA)));\r
2103                 CUtils::Run(szCommandLine, TRUE);       // regedit /e "x:\xkeymacs.reg" HKEY_CURRENT_USER\Software\Oishi\XKeymacs2\r
2104         }\r
2105 \r
2106         DiableTokenPrivileges();\r
2107         return;\r
2108 }\r
2109 \r
2110 void CProfile::ImportProperties()\r
2111 {\r
2112         if (!AdjustTokenPrivileges(SE_RESTORE_NAME)) {\r
2113                 return;\r
2114         }\r
2115 \r
2116         CFileDialog oFileOpenDialog(TRUE, _T("reg"), _T("xkeymacs"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, CString(MAKEINTRESOURCE(IDS_REGISTRATION_FILTER)));\r
2117         if (oFileOpenDialog.DoModal() == IDOK) {\r
2118                 CString szCommandLine;\r
2119                 szCommandLine.Format(_T("regedit \"%s\""), oFileOpenDialog.GetPathName());\r
2120                 CUtils::Run(szCommandLine, TRUE);       // regedit "x:\xkeymacs.reg"\r
2121         }\r
2122 \r
2123         DiableTokenPrivileges();\r
2124         return;\r
2125 }\r
2126 \r
2127 BOOL CProfile::GetEnableCUA(const int nApplicationID)\r
2128 {\r
2129         return m_XkeymacsData[nApplicationID].GetEnableCUA();\r
2130 }\r
2131 \r
2132 void CProfile::SetEnableCUA(const int nApplicationID, const BOOL bEnableCUA)\r
2133 {\r
2134         m_XkeymacsData[nApplicationID].SetEnableCUA(bEnableCUA);\r
2135 }\r
2136 \r
2137 int CProfile::GetKeyboardSpeed()\r
2138 {\r
2139         int nKeyboardSpeed = 31; // default value of Windows\r
2140         CString szSubKey(MAKEINTRESOURCE(IDS_REGSUBKEY_KEYBOARD));\r
2141         CString szValueName(MAKEINTRESOURCE(IDS_KEYBOARD_SPEED));\r
2142 \r
2143         HKEY hKey = NULL;\r
2144         if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\r
2145                 // get data size\r
2146                 DWORD dwType = REG_SZ;\r
2147                 BYTE data[4] = {0};\r
2148                 DWORD dwcbData = sizeof(data)/sizeof(data[0]);\r
2149                 RegQueryValueEx(hKey, szValueName, NULL, &dwType, (LPBYTE)&data, &dwcbData);\r
2150                 RegCloseKey(hKey);\r
2151 \r
2152                 for (DWORD i = 0; i < dwcbData; ++i) {\r
2153                         if (data[i]) {\r
2154                                 if (i) {\r
2155                                         nKeyboardSpeed = nKeyboardSpeed * 10 + data[i] - _T('0');\r
2156                                 } else {\r
2157                                         nKeyboardSpeed = data[i] - _T('0');\r
2158                                 }\r
2159                         } else {\r
2160                                 break;\r
2161                         }\r
2162                 }\r
2163         }\r
2164 \r
2165         return nKeyboardSpeed;\r
2166 }\r