OSDN Git Service

79b2504d614b125e41d7683979647b8aa82d4ee5
[xkeymacs/xkeymacs.git] / xkeymacs / keyboardlayout.cpp
1 #include "stdafx.h"\r
2 #include "keyboardlayout.h"\r
3 \r
4 const int MAX_KEYBOARD_LAYOUT = 112;\r
5 KeyboardLayout CKeyboardLayout::m_KeyboardLayouts[] = {\r
6         {{0x01, 0x00}, IDC_ESC,                         IDC_ESC_,                       IDS_ESC},\r
7         {{0x02, 0x00}, IDC_1,                           IDC_1_,                         IDS_1},\r
8         {{0x03, 0x00}, IDC_2,                           IDC_2_,                         IDS_2},\r
9         {{0x04, 0x00}, IDC_3,                           IDC_3_,                         IDS_3},\r
10         {{0x05, 0x00}, IDC_4,                           IDC_4_,                         IDS_4},\r
11         {{0x06, 0x00}, IDC_5,                           IDC_5_,                         IDS_5},\r
12         {{0x07, 0x00}, IDC_6,                           IDC_6_,                         IDS_6},\r
13         {{0x08, 0x00}, IDC_7,                           IDC_7_,                         IDS_7},\r
14         {{0x09, 0x00}, IDC_8,                           IDC_8_,                         IDS_8},\r
15         {{0x0a, 0x00}, IDC_9,                           IDC_9_,                         IDS_9},\r
16         {{0x0b, 0x00}, IDC_0,                           IDC_0_,                         IDS_0_},\r
17         {{0x0c, 0x00}, IDC_MINUS,                       IDC_MINUS_,                     IDS_MINUS},\r
18         {{0x0d, 0x00}, IDC_EQUAL,                       IDC_EQUAL_,                     IDS_EQUAL},             // =            /// ^\r
19         {{0x0e, 0x00}, IDC_BACKSPACE,           IDC_BACKSPACE_,         IDS_BACKSPACE},\r
20         {{0x0f, 0x00}, IDC_TAB,                         IDC_TAB_,                       IDS_TAB},\r
21         {{0x10, 0x00}, IDC_Q,                           IDC_Q_,                         IDS_Q},\r
22         {{0x11, 0x00}, IDC_W,                           IDC_W_,                         IDS_W},\r
23         {{0x12, 0x00}, IDC_E,                           IDC_E_,                         IDS_E},\r
24         {{0x13, 0x00}, IDC_R,                           IDC_R_,                         IDS_R},\r
25         {{0x14, 0x00}, IDC_T,                           IDC_T_,                         IDS_T},\r
26         {{0x15, 0x00}, IDC_Y,                           IDC_Y_,                         IDS_Y},\r
27         {{0x16, 0x00}, IDC_U,                           IDC_U_,                         IDS_U},\r
28         {{0x17, 0x00}, IDC_I,                           IDC_I_,                         IDS_I},\r
29         {{0x18, 0x00}, IDC_O,                           IDC_O_,                         IDS_O},\r
30         {{0x19, 0x00}, IDC_P,                           IDC_P_,                         IDS_P},\r
31         {{0x1a, 0x00}, IDC_SQUARE_BRA,          IDC_SQUARE_BRA_,        IDS_SQUARE_BRA},        // 101/104: [, 106/109: @\r
32         {{0x1b, 0x00}, IDC_SQUARE_CKET,         IDC_SQUARE_CKET_,       IDS_SQUARE_CKET},       // 101/104: ], 106/109: [\r
33         {{0x1c, 0x00}, IDC_ENTER,                       IDC_ENTER_,                     IDS_ENTER},\r
34         {{0x1c, 0xe0}, IDC_NUMPADENTER,         IDC_NUMPADENTER_,       IDS_NUMPADENTER},\r
35         {{0x1d, 0x00}, IDC_LEFT_CTRL,           IDC_LEFT_CTRL_,         IDS_LEFT_CTRL},\r
36         {{0x1d, 0xe0}, IDC_RIGHT_CTRL,          IDC_RIGHT_CTRL_,        IDS_RIGHT_CTRL},\r
37         {{0x1d, 0xe1}, IDC_PAUSE,                       IDC_PAUSE_,                     IDS_PAUSE},\r
38         {{0x1e, 0x00}, IDC_A,                           IDC_A_,                         IDS_A},\r
39         {{0x1f, 0x00}, IDC_S,                           IDC_S_,                         IDS_S},\r
40         {{0x20, 0x00}, IDC_D,                           IDC_D_,                         IDS_D},\r
41         {{0x21, 0x00}, IDC_F,                           IDC_F_,                         IDS_F},\r
42         {{0x22, 0x00}, IDC_G,                           IDC_G_,                         IDS_G},\r
43         {{0x23, 0x00}, IDC_H,                           IDC_H_,                         IDS_H},\r
44         {{0x24, 0x00}, IDC_J,                           IDC_J_,                         IDS_J},\r
45         {{0x25, 0x00}, IDC_K,                           IDC_K_,                         IDS_K},\r
46         {{0x26, 0x00}, IDC_L,                           IDC_L_,                         IDS_L},\r
47         {{0x27, 0x00}, IDC_SEMICOLON,           IDC_SEMICOLON_,         IDS_SEMICOLON},\r
48         {{0x28, 0x00}, IDC_QUOTE,                       IDC_QUOTE_,                     IDS_QUOTE},             // 101/104: ', 106/109: :\r
49         {{0x29, 0x00}, IDC_BACK_QUOTE,          IDC_BACK_QUOTE_,        IDS_BACK_QUOTE},        // 101/104: `, 106/109: hankaku/zenkaku\r
50         {{0x2a, 0x00}, IDC_LEFT_SHIFT,          IDC_LEFT_SHIFT_,        IDS_LEFT_SHIFT},\r
51         {{0x2b, 0x00}, IDC_BACKSLASH,           IDC_BACKSLASH_,         IDS_BACKSLASH}, // 101/104: \, 106/109: ]\r
52         {{0x2c, 0x00}, IDC_Z,                           IDC_Z_,                         IDS_Z},\r
53         {{0x2d, 0x00}, IDC_X,                           IDC_X_,                         IDS_X},\r
54         {{0x2e, 0x00}, IDC_C,                           IDC_C_,                         IDS_C},\r
55         {{0x2f, 0x00}, IDC_V,                           IDC_V_,                         IDS_V},\r
56         {{0x30, 0x00}, IDC_B,                           IDC_B_,                         IDS_B},\r
57         {{0x31, 0x00}, IDC_N,                           IDC_N_,                         IDS_N},\r
58         {{0x32, 0x00}, IDC_M,                           IDC_M_,                         IDS_M},\r
59         {{0x33, 0x00}, IDC_COMMA,                       IDC_COMMA_,                     IDS_COMMA},\r
60         {{0x34, 0x00}, IDC_PERIOD,                      IDC_PERIOD_,            IDS_PERIOD},\r
61         {{0x35, 0x00}, IDC_SLASH,                       IDC_SLASH_,                     IDS_SLASH},\r
62         {{0x35, 0xe0}, IDC_DIVIDE,                      IDC_DIVIDE_,            IDS_DIVIDE},\r
63         {{0x36, 0x00}, IDC_RIGHT_SHIFT,         IDC_RIGHT_SHIFT_,       IDS_RIGHT_SHIFT},\r
64         {{0x37, 0x00}, IDC_MULTIPLY,            IDC_MULTIPLY_,          IDS_MULTIPLY},\r
65         {{0x37, 0xe0}, IDC_PRINT_SCREEN,        IDC_PRINT_SCREEN_,      IDS_PRINT_SCREEN},\r
66         {{0x38, 0x00}, IDC_LEFT_ALT,            IDC_LEFT_ALT_,          IDS_LEFT_ALT},\r
67         {{0x38, 0xe0}, IDC_RIGHT_ALT,           IDC_RIGHT_ALT_,         IDS_RIGHT_ALT},\r
68         {{0x39, 0x00}, IDC_SPACE,                       IDC_SPACE_,                     IDS_SPACE},\r
69         {{0x3a, 0x00}, IDC_CAPS_LOCK,           IDC_CAPS_LOCK_,         IDS_CAPS_LOCK},\r
70         {{0x3b, 0x00}, IDC_F1,                          IDC_F1_,                        IDS_F1},\r
71         {{0x3c, 0x00}, IDC_F2,                          IDC_F2_,                        IDS_F2},\r
72         {{0x3d, 0x00}, IDC_F3,                          IDC_F3_,                        IDS_F3},\r
73         {{0x3e, 0x00}, IDC_F4,                          IDC_F4_,                        IDS_F4},\r
74         {{0x3f, 0x00}, IDC_F5,                          IDC_F5_,                        IDS_F5},\r
75         {{0x40, 0x00}, IDC_F6,                          IDC_F6_,                        IDS_F6},\r
76         {{0x41, 0x00}, IDC_F7,                          IDC_F7_,                        IDS_F7},\r
77         {{0x42, 0x00}, IDC_F8,                          IDC_F8_,                        IDS_F8},\r
78         {{0x43, 0x00}, IDC_F9,                          IDC_F9_,                        IDS_F9},\r
79         {{0x44, 0x00}, IDC_F10,                         IDC_F10_,                       IDS_F10},\r
80         {{0x45, 0xe0}, IDC_NUM_LOCK,            IDC_NUM_LOCK_,          IDS_NUM_LOCK},\r
81         {{0x46, 0x00}, IDC_SCROLL_LOCK,         IDC_SCROLL_LOCK_,       IDS_SCROLL_LOCK},\r
82         {{0x47, 0x00}, IDC_NUMPAD7,                     IDC_NUMPAD7_,           IDS_NUMPAD7},\r
83         {{0x47, 0xe0}, IDC_HOME,                        IDC_HOME_,                      IDS_HOME},\r
84         {{0x48, 0x00}, IDC_NUMPAD8,                     IDC_NUMPAD8_,           IDS_NUMPAD8},\r
85         {{0x48, 0xe0}, IDC_UP,                          IDC_UP_,                        IDS_UP},\r
86         {{0x49, 0x00}, IDC_NUMPAD9,                     IDC_NUMPAD9_,           IDS_NUMPAD9},\r
87         {{0x49, 0xe0}, IDC_PAGE_UP,                     IDC_PAGE_UP_,           IDS_PAGE_UP},\r
88         {{0x4a, 0x00}, IDC_SUBTRACT,            IDC_SUBTRACT_,          IDS_SUBTRACT},\r
89         {{0x4b, 0x00}, IDC_NUMPAD4,                     IDC_NUMPAD4_,           IDS_NUMPAD4},\r
90         {{0x4b, 0xe0}, IDC_LEFT,                        IDC_LEFT_,                      IDS_LEFT},\r
91         {{0x4c, 0x00}, IDC_NUMPAD5,                     IDC_NUMPAD5_,           IDS_NUMPAD5},\r
92         {{0x4d, 0x00}, IDC_NUMPAD6,                     IDC_NUMPAD6_,           IDS_NUMPAD6},\r
93         {{0x4d, 0xe0}, IDC_RIGHT,                       IDC_RIGHT_,                     IDS_RIGHT},\r
94         {{0x4e, 0x00}, IDC_ADD,                         IDC_ADD_,                       IDS_ADD},\r
95         {{0x4f, 0x00}, IDC_NUMPAD1,                     IDC_NUMPAD1_,           IDS_NUMPAD1},\r
96         {{0x4f, 0xe0}, IDC_END,                         IDC_END_,                       IDS_END},\r
97         {{0x50, 0x00}, IDC_NUMPAD2,                     IDC_NUMPAD2_,           IDS_NUMPAD2},\r
98         {{0x50, 0xe0}, IDC_DOWN,                        IDC_DOWN_,                      IDS_DOWN},\r
99         {{0x51, 0x00}, IDC_NUMPAD3,                     IDC_NUMPAD3_,           IDS_NUMPAD3},\r
100         {{0x51, 0xe0}, IDC_PAGE_DOWN,           IDC_PAGE_DOWN_,         IDS_PAGE_DOWN},\r
101         {{0x52, 0x00}, IDC_NUMPAD0,                     IDC_NUMPAD0_,           IDS_NUMPAD0},\r
102         {{0x52, 0xe0}, IDC_INSERT,                      IDC_INSERT_,            IDS_INSERT},\r
103         {{0x53, 0x00}, IDC_NUMPADDELETE,        IDC_NUMPADDELETE_,      IDS_NUMPADDELETE},\r
104         {{0x53, 0xe0}, IDC_DELETE,                      IDC_DELETE_,            IDS_DELETE},\r
105         {{0x57, 0x00}, IDC_F11,                         IDC_F11_,                       IDS_F11},\r
106         {{0x58, 0x00}, IDC_F12,                         IDC_F12_,                       IDS_F12},\r
107         {{0x5b, 0xe0}, IDC_LEFT_WINDOWS,        IDC_LEFT_WINDOWS_,      IDS_LEFT_WINDOWS},\r
108         {{0x5c, 0xe0}, IDC_RIGHT_WINDOWS,       IDC_RIGHT_WINDOWS_,     IDS_RIGHT_WINDOWS},\r
109         {{0x5d, 0xe0}, IDC_APPLICATION,         IDC_APPLICATION_,       IDS_APPLICATION},\r
110         {{0x5e, 0xe0}, IDC_ACPI_POWER,          IDC_ACPI_POWER_,        IDS_ACPI_POWER},\r
111         {{0x5f, 0xe0}, IDC_ACPI_SLEEP,          IDC_ACPI_SLEEP_,        IDS_ACPI_SLEEP},\r
112         {{0x63, 0xe0}, IDC_ACPI_WAKE,           IDC_ACPI_WAKE_,         IDS_ACPI_WAKE},\r
113         {{0x70, 0x00}, IDC_KANA,                        IDC_KANA_,                      IDS_KANA},\r
114         {{0x73, 0x00}, IDC_BACKSLASH2,          IDC_BACKSLASH2_,        IDS_BACKSLASH2},        // \  ,./\ \r
115         {{0x79, 0x00}, IDC_CONVERT,                     IDC_CONVERT_,           IDS_CONVERT},\r
116         {{0x7b, 0x00}, IDC_NONCONVERT,          IDC_NONCONVERT_,        IDS_NONCONVERT},\r
117         {{0x7d, 0x00}, IDC_BACKSLASH1,          IDC_BACKSLASH1_,        IDS_BACKSLASH1},        // \  -^\ \r
118 };\r
119 \r
120 ScanCode CKeyboardLayout::m_CurrentScanCodeMap[MAX_HKEY_TYPE][4][256];\r
121 ScanCode CKeyboardLayout::m_ScanCodeMap[MAX_HKEY_TYPE][4][256];\r
122 \r
123 CKeyboardLayout::CKeyboardLayout(const HKEY_TYPE hkey_type, UINT nIDTemplate, CWnd* pParentWnd)\r
124         : CDialog(nIDTemplate, pParentWnd)\r
125 {\r
126         m_HkeyType = hkey_type;\r
127 }\r
128 \r
129 CKeyboardLayout::~CKeyboardLayout()\r
130 {\r
131 }\r
132 \r
133 void CKeyboardLayout::InitKeyboardLayout()\r
134 {\r
135         m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_NOPREFIX);\r
136         m_ToolTip.SetMaxTipWidth(0x100);        // Enable multiline\r
137 \r
138         LoadScanCodeMap(m_HkeyType);\r
139                 for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i) {\r
140                 if (!GetDlgItem(m_KeyboardLayouts[i].nBaseControlID)\r
141                  || !GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID)) {\r
142                         continue;\r
143                 }\r
144 \r
145                 m_KeyboardLayouts[i].pBaseKey = new CKey(m_KeyboardLayouts[i].nBaseControlID, NORMAL_KEY, m_HkeyType);\r
146                 m_KeyboardLayouts[i].pBaseKey->SubclassDlgItem(m_KeyboardLayouts[i].nBaseControlID, this);\r
147                 m_ToolTip.AddTool(GetDlgItem(m_KeyboardLayouts[i].nBaseControlID), GetToolTipID(m_KeyboardLayouts[i].nToolTipID));\r
148 \r
149                 m_KeyboardLayouts[i].pCurrentKey = new CKey(m_KeyboardLayouts[i].nCurrentControlID, ORIGINAL_KEY, m_HkeyType);\r
150                 m_KeyboardLayouts[i].pCurrentKey->SubclassDlgItem(m_KeyboardLayouts[i].nCurrentControlID, this);\r
151                 m_ToolTip.AddTool(GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID), GetToolTipID(m_KeyboardLayouts[i].nToolTipID));\r
152 \r
153                 ScanCode current = {'\0'};\r
154                 if (GetScanCodeMap(m_HkeyType, m_KeyboardLayouts[i].scancode, &current)) {\r
155                         m_KeyboardLayouts[i].pCurrentKey->SetKeyType(REMAPPED_KEY);\r
156 \r
157                         CString szWindowText;\r
158                         GetDlgItem(GetBaseControlID(current))->GetWindowText(szWindowText);\r
159                         GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID)->SetWindowText(szWindowText);\r
160 \r
161                         KeyboardLayout *pKeyboardLayout = GetKeyboardLayout(GetBaseControlID(current));\r
162                         if (pKeyboardLayout) {\r
163                                 m_ToolTip.UpdateTipText(GetToolTipID(pKeyboardLayout->nToolTipID), GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID));\r
164                         }\r
165                 }\r
166         }\r
167 }\r
168 \r
169 KeyboardLayout *CKeyboardLayout::GetKeyboardLayout(const int nKey, BOOL bBaseOnly)\r
170 {\r
171         for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i) {\r
172                 if (m_KeyboardLayouts[i].nBaseControlID == nKey\r
173                  || !bBaseOnly && m_KeyboardLayouts[i].nCurrentControlID == nKey) {\r
174                         return &m_KeyboardLayouts[i];\r
175                 }\r
176         }\r
177         return NULL;\r
178 }\r
179 \r
180 void CKeyboardLayout::DestroyKeyboardLayout()\r
181 {\r
182         for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i) {\r
183                 if (!GetDlgItem(m_KeyboardLayouts[i].nBaseControlID)\r
184                  || !GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID)) {\r
185                         continue;\r
186                 }\r
187                 if (m_KeyboardLayouts[i].pBaseKey) {\r
188                         delete m_KeyboardLayouts[i].pBaseKey;\r
189                         m_KeyboardLayouts[i].pBaseKey = NULL;\r
190                 }\r
191                 if (m_KeyboardLayouts[i].pCurrentKey) {\r
192                         delete m_KeyboardLayouts[i].pCurrentKey;\r
193                         m_KeyboardLayouts[i].pCurrentKey = NULL;\r
194                 }\r
195         }\r
196 }\r
197 \r
198 CToolTipCtrl *CKeyboardLayout::ToolTip()\r
199 {\r
200         return &m_ToolTip;\r
201 }\r
202 \r
203 void CKeyboardLayout::LoadScanCodeMap(const HKEY_TYPE hkeyType)\r
204 {\r
205         memset(m_ScanCodeMap[hkeyType], 0, sizeof(m_ScanCodeMap[hkeyType]));\r
206         memset(m_CurrentScanCodeMap[hkeyType], 0, sizeof(m_CurrentScanCodeMap[hkeyType]));\r
207 \r
208         CString szSubKey;\r
209         CString szValueName;\r
210         HKEY hKey = HKEY_LOCAL_MACHINE;\r
211         switch (hkeyType) {\r
212         case CURRENT_USER:\r
213                 hKey = HKEY_CURRENT_USER;\r
214                 szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
215                 break;\r
216         case LOCAL_MACHINE:\r
217                 szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
218                 break;\r
219         default:\r
220                 return;\r
221         }\r
222         szValueName.LoadString(IDS_SCANCODE_MAP);\r
223 \r
224         HKEY hkResult = NULL;\r
225         if (RegOpenKeyEx(hKey, szSubKey, 0, KEY_QUERY_VALUE, &hkResult) == ERROR_SUCCESS) {\r
226                 // get data size\r
227                 DWORD dwType = REG_BINARY;\r
228                 DWORD dwData = 0;\r
229                 RegQueryValueEx(hkResult, szValueName, NULL, &dwType, NULL, &dwData);\r
230 \r
231                 // get data\r
232                 LPBYTE lpData = new BYTE[dwData];\r
233                 if (lpData) {\r
234                         RegQueryValueEx(hkResult, szValueName, NULL, &dwType, lpData, &dwData);\r
235                 }\r
236                 RegCloseKey(hkResult);\r
237 \r
238                 if (lpData && dwData) {\r
239                         DWORD offset = 0;\r
240                         offset += 8;    // skip Version Information and Flags\r
241                         DWORD *pdwMappings = (DWORD *)(lpData + offset);\r
242                         offset += 4;    // skip Number of Mappings\r
243                         DWORD *pdwNullTerminator = (DWORD *)(lpData + dwData - 4);\r
244 \r
245                         if (4 * *pdwMappings + 12 != dwData) {\r
246                                 // illegal data\r
247                         } else if (*pdwNullTerminator != 0) {\r
248                                 // illegal data\r
249                         } else {\r
250                                 while (offset < dwData - 4) {\r
251                                         ScanCodeMapping *pMapping = (ScanCodeMapping *)(lpData + offset);\r
252                                         offset += 4;    // go to next data\r
253                                         m_CurrentScanCodeMap[hkeyType][Prefix2ID(pMapping->original.nPrefix)][pMapping->original.nScanCode].nPrefix = pMapping->current.nPrefix;\r
254                                         m_CurrentScanCodeMap[hkeyType][Prefix2ID(pMapping->original.nPrefix)][pMapping->original.nScanCode].nScanCode = pMapping->current.nScanCode;\r
255                                         m_ScanCodeMap[hkeyType][Prefix2ID(pMapping->original.nPrefix)][pMapping->original.nScanCode].nPrefix = pMapping->current.nPrefix;\r
256                                         m_ScanCodeMap[hkeyType][Prefix2ID(pMapping->original.nPrefix)][pMapping->original.nScanCode].nScanCode = pMapping->current.nScanCode;\r
257                                 }\r
258                         }\r
259                 }\r
260                 delete[] lpData;\r
261                 lpData = NULL;\r
262         }\r
263 }\r
264 \r
265 int CKeyboardLayout::LostKeyWarning(const HKEY_TYPE hkeyType)\r
266 {\r
267         if (!ChangedKeyboardLayout(hkeyType)) {\r
268                 return IDOK;\r
269         }\r
270 \r
271         CString szLostKeysList;\r
272 \r
273         for (int nPrefixID = 0; nPrefixID < 3; ++nPrefixID) {\r
274                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
275                         if (m_ScanCodeMap[hkeyType][nPrefixID][nScanCode].nScanCode) {\r
276                                 BOOL lostKey = TRUE;\r
277 \r
278                                 for (int i = 0; i < 3 && lostKey; ++i) {\r
279                                         for (int j = 0; j < 256 && lostKey; ++j) {\r
280                                                 if (m_ScanCodeMap[hkeyType][i][j].nPrefix == nPrefixID\r
281                                                  && m_ScanCodeMap[hkeyType][i][j].nScanCode == nScanCode) {\r
282                                                         lostKey = FALSE;\r
283                                                 }\r
284                                         }\r
285                                 }\r
286 \r
287                                 if (lostKey) {\r
288                                         for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i) {\r
289                                                 if (m_KeyboardLayouts[i].scancode.nScanCode == nScanCode\r
290                                                         && m_KeyboardLayouts[i].scancode.nPrefix == nPrefixID) {\r
291                                                         CString szLostKey;\r
292                                                         szLostKey.Format(IDS_ERR_LOST_KEY, CString(MAKEINTRESOURCE(GetToolTipID(m_KeyboardLayouts[i].nToolTipID))));\r
293                                                         szLostKeysList += szLostKey;\r
294                                                         break;\r
295                                                 }\r
296                                         }\r
297                                 }\r
298                         }\r
299                 }\r
300         }\r
301 \r
302         if (szLostKeysList.IsEmpty()) {\r
303                 return IDOK;\r
304         }\r
305 \r
306         return AfxMessageBox(szLostKeysList, MB_OKCANCEL | MB_ICONEXCLAMATION);\r
307 }\r
308 \r
309 void CKeyboardLayout::SaveScanCodeMap(const HKEY_TYPE hkeyType)\r
310 {\r
311         CString szSubKey;\r
312         CString szValueName;\r
313         HKEY hKey = HKEY_LOCAL_MACHINE;\r
314         switch (hkeyType) {\r
315         case CURRENT_USER:\r
316                 hKey = HKEY_CURRENT_USER;\r
317                 szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT);\r
318                 break;\r
319         case LOCAL_MACHINE:\r
320                 szSubKey.LoadString(IDS_REGSUBKEY_KEYBOARD_LAYOUT_ANY_USER);\r
321                 break;\r
322         default:\r
323                 return;\r
324         }\r
325         szValueName.LoadString(IDS_SCANCODE_MAP);\r
326 \r
327         HKEY hkResult = NULL;\r
328         if (RegCreateKeyEx(hKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkResult, NULL) == ERROR_SUCCESS) {\r
329                 DWORD cbData = GetScanCodeLength(hkeyType);\r
330                 if (cbData <= 16) {\r
331                         RegDeleteValue(hkResult, szValueName);\r
332                 } else {\r
333                         LPBYTE lpData = new BYTE[cbData];\r
334                         memset(lpData, 0, sizeof(BYTE) * cbData);\r
335 \r
336                         {\r
337                                 DWORD dwMappings = (cbData - 12) / 4;\r
338                                 memmove(lpData + 8, &dwMappings, 4);\r
339                         }\r
340 \r
341                         int offset = 12;\r
342                         for (int nPrefixID = 0; nPrefixID < 3; ++nPrefixID) {\r
343                                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode) {\r
344                                         if (m_ScanCodeMap[hkeyType][nPrefixID][nScanCode].nScanCode) {\r
345                                                 ScanCodeMapping sScanCodeMapping = {'\0'};\r
346                                                 sScanCodeMapping.original.nPrefix = PrefixID2Code(nPrefixID);\r
347                                                 sScanCodeMapping.original.nScanCode = (BYTE)nScanCode;\r
348                                                 sScanCodeMapping.current.nPrefix = m_ScanCodeMap[hkeyType][nPrefixID][nScanCode].nPrefix;\r
349                                                 sScanCodeMapping.current.nScanCode = m_ScanCodeMap[hkeyType][nPrefixID][nScanCode].nScanCode;\r
350                                                 memcpy(lpData + offset, &sScanCodeMapping, sizeof(sScanCodeMapping));\r
351                                                 offset += sizeof(sScanCodeMapping);\r
352                                         }\r
353                                 }\r
354                         }\r
355                         RegSetValueEx(hkResult, szValueName, 0, REG_BINARY, lpData, cbData);\r
356 \r
357                         delete[] lpData;\r
358                         lpData = NULL;\r
359                 }\r
360                 RegCloseKey(hkResult);\r
361         }\r
362 \r
363         // Do you want to restart computer?\r
364         if (ChangedKeyboardLayout(hkeyType)) {\r
365                 if (AfxMessageBox(CString(MAKEINTRESOURCE(IDS_RESTART_OR_NOT)), MB_YESNO | MB_ICONQUESTION) == IDYES) {\r
366                         CProfile::RestartComputer();\r
367                 }\r
368         }\r
369 }\r
370 \r
371 int CKeyboardLayout::GetControlID(const ScanCode scancode, const BOOL bBase)\r
372 {\r
373         for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i)\r
374                 if (m_KeyboardLayouts[i].scancode.nPrefix == scancode.nPrefix &&\r
375                                 m_KeyboardLayouts[i].scancode.nScanCode == scancode.nScanCode) {\r
376                         if (bBase)\r
377                                 return m_KeyboardLayouts[i].nBaseControlID;\r
378                         else\r
379                                 return m_KeyboardLayouts[i].nCurrentControlID;\r
380                 }\r
381         return 0;\r
382 }\r
383 \r
384 int CKeyboardLayout::GetBaseControlID(const ScanCode scancode)\r
385 {\r
386         return GetControlID(scancode, TRUE);\r
387 }\r
388 \r
389 int CKeyboardLayout::GetCurrentControlID(const ScanCode scancode)\r
390 {\r
391         return GetControlID(scancode, FALSE);\r
392 }\r
393 \r
394 BOOL CKeyboardLayout::GetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCode original, ScanCode *const current)\r
395 {\r
396         if (!current) {\r
397                 return FALSE;\r
398         }\r
399         *current = m_ScanCodeMap[hkeyType][Prefix2ID(original.nPrefix)][original.nScanCode];\r
400         return 0 < current->nScanCode;\r
401 }\r
402 \r
403 void CKeyboardLayout::SetScanCodeMap(const HKEY_TYPE hkeyType, const ScanCodeMapping ScanCodeMappeing)\r
404 {\r
405         m_ScanCodeMap[hkeyType][Prefix2ID(ScanCodeMappeing.original.nPrefix)][ScanCodeMappeing.original.nScanCode] = ScanCodeMappeing.current;\r
406 }\r
407 \r
408 int CKeyboardLayout::Prefix2ID(const BYTE nPrefix)\r
409 {\r
410         int nID = 0;\r
411         switch (nPrefix) {\r
412         case 0x00:\r
413                 nID = 0;\r
414                 break;\r
415         case 0xe0:\r
416                 nID = 1;\r
417                 break;\r
418         case 0xe1:\r
419                 nID = 2;\r
420                 break;\r
421         default:\r
422                 // invalid scan code\r
423                 nID = 3;\r
424                 break;\r
425         }\r
426         return nID;\r
427 }\r
428 \r
429 BYTE CKeyboardLayout::PrefixID2Code(const int nID)\r
430 {\r
431         BYTE nCode = 0;\r
432         switch (nID) {\r
433         case 0:\r
434                 nCode = 0x00;\r
435                 break;\r
436         case 1:\r
437                 nCode = 0xe0;\r
438                 break;\r
439         case 2:\r
440                 nCode = 0xe1;\r
441                 break;\r
442         default:\r
443                 ASSERT(0);\r
444                 break;\r
445         }\r
446         return nCode;\r
447 }\r
448 \r
449 DWORD CKeyboardLayout::GetScanCodeLength(const HKEY_TYPE hkeyType)\r
450 {\r
451         DWORD dwScanCodeLength = 0;\r
452         dwScanCodeLength += 4;  // Header: Version Information\r
453         dwScanCodeLength += 4;  // Header: Flags\r
454         dwScanCodeLength += 4;  // Header: Number of Mappings\r
455         for (int nID = 0; nID < 3; ++nID)\r
456                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode)\r
457                         if (m_ScanCodeMap[hkeyType][nID][nScanCode].nScanCode)\r
458                                 dwScanCodeLength += 4;  // Individual Mappings\r
459         dwScanCodeLength += 4;  // Null Terminator (0x00000000)\r
460         return dwScanCodeLength;\r
461 }\r
462 \r
463 BOOL CKeyboardLayout::ChangedKeyboardLayout(const HKEY_TYPE hkeyType)\r
464 {\r
465         for (int nID = 0; nID < 3; ++nID)\r
466                 for (int nScanCode = 0; nScanCode < 256; ++nScanCode)\r
467                         if (m_ScanCodeMap[hkeyType][nID][nScanCode].nPrefix !=\r
468                                         m_CurrentScanCodeMap[hkeyType][nID][nScanCode].nPrefix ||\r
469                                         m_ScanCodeMap[hkeyType][nID][nScanCode].nScanCode !=\r
470                                         m_CurrentScanCodeMap[hkeyType][nID][nScanCode].nScanCode)\r
471                                 return TRUE;\r
472         return FALSE;\r
473 }\r
474 \r
475 int CKeyboardLayout::GetPointedKey(const CPoint point)\r
476 {\r
477         for (int i = 0; i < MAX_KEYBOARD_LAYOUT; ++i) {\r
478                 if (!GetDlgItem(m_KeyboardLayouts[i].nBaseControlID) ||\r
479                                 !GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID))\r
480                         continue;\r
481                 CRect rButton;\r
482                 GetDlgItem(m_KeyboardLayouts[i].nBaseControlID)->GetWindowRect(&rButton);\r
483                 if (rButton.PtInRect(point))\r
484                         return m_KeyboardLayouts[i].nBaseControlID;\r
485                 GetDlgItem(m_KeyboardLayouts[i].nCurrentControlID)->GetWindowRect(&rButton);\r
486                 if (rButton.PtInRect(point))\r
487                         return m_KeyboardLayouts[i].nCurrentControlID;\r
488         }\r
489         return 0;\r
490 }\r
491 \r
492 int CKeyboardLayout::GetToolTipID(int nToolTipID)\r
493 {\r
494         return nToolTipID;\r
495 }\r