- Implement "Input language Properties" dialog
[reactos.git] / reactos / dll / cpl / input / add.c
1 /*
2 *
3 * PROJECT: input.dll
4 * FILE: dll/win32/input/add.c
5 * PURPOSE: input.dll
6 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
7 * Colin Finck
8 * UPDATE HISTORY:
9 * 06-09-2007 Created
10 */
11
12 #include "resource.h"
13 #include "input.h"
14
15 static HWND hLangList;
16 static HWND hLayoutList;
17
18 static VOID
19 SelectLayoutByLang(VOID)
20 {
21 TCHAR Layout[MAX_PATH], Lang[MAX_PATH], LangID[CCH_LAYOUT_ID + 1];
22 INT iIndex;
23 LCID Lcid;
24
25 iIndex = SendMessage(hLangList, CB_GETCURSEL, 0, 0);
26 Lcid = SendMessage(hLangList, CB_GETITEMDATA, iIndex, 0);
27
28 GetLocaleInfo(MAKELCID(Lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Lang, sizeof(Lang) / sizeof(TCHAR));
29
30 wsprintf(LangID, _T("0000%s"), Lang);
31
32 if (GetLayoutName(LangID, Layout))
33 {
34 SendMessage(hLayoutList, CB_SELECTSTRING,
35 (WPARAM) -1, (LPARAM)Layout);
36 }
37 }
38
39 INT
40 GetLayoutCount(LPTSTR szLang)
41 {
42 HKEY hKey;
43 TCHAR szLayoutID[3 + 1], szPreload[CCH_LAYOUT_ID + 1], szLOLang[MAX_PATH];
44 DWORD dwIndex = 0, dwType, dwSize;
45 INT Count = 0, i, j;
46
47 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"),
48 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
49 {
50 dwSize = sizeof(szLayoutID);
51
52 while (RegEnumValue(hKey, dwIndex, szLayoutID, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
53 {
54 dwSize = sizeof(szPreload);
55 RegQueryValueEx(hKey, szLayoutID, NULL, NULL, (LPBYTE)szPreload, &dwSize);
56
57 for (i = 4, j = 0; i < _tcslen(szPreload)+1; i++, j++)
58 szLOLang[j] = szPreload[i];
59
60 if (_tcscmp(szLOLang, szLang) == 0) Count += 1;
61
62 dwSize = sizeof(szLayoutID);
63 dwIndex++;
64 }
65
66 RegCloseKey(hKey);
67 }
68
69 return Count;
70 }
71
72 static VOID
73 AddNewLayout(HWND hwndDlg)
74 {
75 TCHAR NewLayout[CCH_ULONG_DEC + 1], Lang[MAX_PATH],
76 LangID[CCH_LAYOUT_ID + 1], Layout[MAX_PATH],
77 SubPath[CCH_LAYOUT_ID + 1];
78 INT iLayout, iLang;
79 HKEY hKey, hSubKey;
80 DWORD cValues;
81 PTSTR pts;
82 LCID lcid;
83
84 iLayout = SendMessage(hLayoutList, CB_GETCURSEL, 0, 0);
85 if (iLayout == CB_ERR) return;
86
87 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
88 {
89 if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &cValues, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
90 {
91 _ultot(cValues + 1, NewLayout, 10);
92
93 iLang = SendMessage(hLangList, CB_GETCURSEL, 0, 0);
94 lcid = SendMessage(hLangList, CB_GETITEMDATA, iLang, 0);
95
96 GetLocaleInfo(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Lang, sizeof(Lang) / sizeof(TCHAR));
97 wsprintf(LangID, _T("0000%s"), Lang);
98
99 if (GetLayoutName(LangID, Layout))
100 {
101 if ((SendMessage(hLayoutList, CB_SELECTSTRING, (WPARAM) -1, (LPARAM)Layout) != CB_ERR)&&
102 (GetLayoutCount(Lang) >= 1))
103 {
104 wsprintf(SubPath, _T("d%03d%s"), GetLayoutCount(Lang)-1, Lang);
105 }
106 else SubPath[0] = '\0';
107 }
108
109 pts = (PTSTR) SendMessage(hLayoutList, CB_GETITEMDATA, iLayout, 0);
110
111 if (_tcslen(SubPath) != 0)
112 {
113 if (RegCreateKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0, NULL,
114 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
115 NULL, &hSubKey, NULL) == ERROR_SUCCESS)
116 {
117 if (RegSetValueEx(hSubKey, SubPath, 0, REG_SZ, (LPBYTE)pts,
118 (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(TCHAR))) != ERROR_SUCCESS)
119 {
120 RegCloseKey(hSubKey);
121 RegCloseKey(hKey);
122 return;
123 }
124 RegCloseKey(hSubKey);
125 }
126 lstrcpy(pts, SubPath);
127 }
128
129 if (RegSetValueEx(hKey,
130 NewLayout,
131 0,
132 REG_SZ,
133 (LPBYTE)pts,
134 (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(TCHAR))) == ERROR_SUCCESS)
135 {
136 UpdateLayoutsList();
137 }
138 }
139 RegCloseKey(hKey);
140 }
141 }
142
143 VOID
144 CreateKeyboardLayoutList(HWND hItemsList)
145 {
146 HKEY hKey;
147 PTSTR pstrLayoutID;
148 TCHAR szLayoutID[CCH_LAYOUT_ID + 1], KeyName[MAX_PATH];
149 DWORD dwIndex = 0;
150 DWORD dwSize;
151
152 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\Keyboard Layouts"), 0, KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS)
153 {
154 dwSize = sizeof(szLayoutID) / sizeof(TCHAR);
155
156 while (RegEnumKeyEx(hKey, dwIndex, szLayoutID, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
157 {
158 GetLayoutName(szLayoutID, KeyName);
159
160 INT iIndex = (INT) SendMessage(hItemsList, CB_ADDSTRING, 0, (LPARAM)KeyName);
161
162 pstrLayoutID = (PTSTR)HeapAlloc(hProcessHeap, 0, sizeof(szLayoutID));
163 lstrcpy(pstrLayoutID, szLayoutID);
164 SendMessage(hItemsList, CB_SETITEMDATA, iIndex, (LPARAM)pstrLayoutID);
165
166 // FIXME!
167 if (_tcscmp(szLayoutID, _T("00000409")) == 0)
168 {
169 SendMessage(hItemsList, CB_SETCURSEL, (WPARAM)iIndex, (LPARAM)0);
170 }
171
172 dwIndex++;
173
174 dwSize = sizeof(szLayoutID) / sizeof(TCHAR);
175 }
176
177 RegCloseKey(hKey);
178 }
179 }
180
181 /* Language enumerate procedure */
182 static BOOL CALLBACK
183 LanguagesEnumProc(LPTSTR lpLanguage)
184 {
185 LCID Lcid;
186 TCHAR Lang[1024];
187 INT Index;
188
189 Lcid = _tcstoul(lpLanguage, NULL, 16);
190
191 GetLocaleInfo(Lcid, LOCALE_SLANGUAGE, Lang, sizeof(Lang));
192 Index = (INT)SendMessage(hLangList, CB_ADDSTRING,
193 0, (LPARAM)Lang);
194
195 SendMessage(hLangList, CB_SETITEMDATA,
196 Index, (LPARAM)Lcid);
197
198 // FIXME!
199 if (Lcid == 0x0409)
200 {
201 SendMessage(hLangList, CB_SELECTSTRING,
202 (WPARAM) -1, (LPARAM)Lang);
203 }
204
205 return TRUE;
206 }
207
208 INT_PTR CALLBACK
209 AddDlgProc(HWND hDlg,
210 UINT message,
211 WPARAM wParam,
212 LPARAM lParam)
213 {
214 UNREFERENCED_PARAMETER(lParam);
215
216 switch (message)
217 {
218 case WM_INITDIALOG:
219 {
220 hLangList = GetDlgItem(hDlg, IDC_INPUT_LANG_COMBO);
221 hLayoutList = GetDlgItem(hDlg, IDC_KEYBOARD_LO_COMBO);
222 EnumSystemLocales(LanguagesEnumProc, LCID_INSTALLED);
223 CreateKeyboardLayoutList(hLayoutList);
224 }
225 break;
226
227 case WM_COMMAND:
228 {
229 switch (LOWORD(wParam))
230 {
231 case IDC_INPUT_LANG_COMBO:
232 {
233 if (HIWORD(wParam) == CBN_SELCHANGE)
234 {
235 SelectLayoutByLang();
236 }
237 }
238 break;
239
240 case IDOK:
241 {
242 AddNewLayout(hDlg);
243 EndDialog(hDlg, LOWORD(wParam));
244 }
245 break;
246
247 case IDCANCEL:
248 {
249 EndDialog(hDlg, LOWORD(wParam));
250 }
251 }
252 }
253 break;
254
255 case WM_DESTROY:
256 {
257 INT iCount;
258
259 for(iCount = SendMessage(hLayoutList, CB_GETCOUNT, 0, 0); --iCount >= 0;)
260 HeapFree(hProcessHeap, 0, (LPVOID)SendMessage(hLayoutList, CB_GETITEMDATA, iCount, 0));
261 }
262 break;
263 }
264
265 return FALSE;
266 }
267
268 /* EOF */