[SOLITAIRE]
[reactos.git] / reactos / dll / cpl / intl / kblayouts.c
1 /*
2 * PROJECT: ReactOS International Control Panel
3 * FILE: dll/cpl/intl/kblayouts.c
4 * PURPOSE: Functions for manipulation with keyboard layouts
5 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
6 */
7
8 #include "intl.h"
9
10 /* Character Count of a layout ID like "00000409" */
11 #define CCH_LAYOUT_ID 8
12
13 /* Maximum Character Count of a ULONG in decimal */
14 #define CCH_ULONG_DEC 10
15
16
17 /* szLayoutID like 00000409, szLangID like 00000409 */
18 static BOOL
19 IsLayoutExists(LPTSTR szLayoutID, LPTSTR szLangID)
20 {
21 HKEY hKey, hSubKey;
22 TCHAR szPreload[CCH_LAYOUT_ID + 1], szLayoutNum[3 + 1],
23 szTmp[CCH_LAYOUT_ID + 1], szOldLangID[CCH_LAYOUT_ID + 1];
24 DWORD dwIndex = 0, dwType, dwSize;
25 BOOL IsLangExists = FALSE;
26 LANGID langid;
27
28 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"),
29 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
30 {
31 dwSize = sizeof(szLayoutNum);
32
33 while (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
34 {
35 dwSize = sizeof(szPreload);
36 if (RegQueryValueEx(hKey, szLayoutNum, NULL, NULL, (LPBYTE)szPreload, &dwSize) != ERROR_SUCCESS)
37 {
38 RegCloseKey(hKey);
39 return FALSE;
40 }
41
42 langid = (LANGID)_tcstoul(szPreload, NULL, 16);
43 GetLocaleInfo(langid, LOCALE_ILANGUAGE, szTmp, sizeof(szTmp) / sizeof(TCHAR));
44 wsprintf(szOldLangID, _T("0000%s"), szTmp);
45
46 if (_tcscmp(szOldLangID, szLangID) == 0)
47 IsLangExists = TRUE;
48 else
49 IsLangExists = FALSE;
50
51 if (szPreload[0] == 'd')
52 {
53 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"),
54 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
55 {
56 dwSize = sizeof(szTmp);
57 RegQueryValueEx(hSubKey, szPreload, NULL, NULL, (LPBYTE)szTmp, &dwSize);
58
59 if ((_tcscmp(szTmp, szLayoutID) == 0)&&(IsLangExists))
60 {
61 RegCloseKey(hSubKey);
62 RegCloseKey(hKey);
63 return TRUE;
64 }
65 }
66 }
67 else
68 {
69 if ((_tcscmp(szPreload, szLayoutID) == 0) && (IsLangExists))
70 {
71 RegCloseKey(hKey);
72 return TRUE;
73 }
74 }
75
76 IsLangExists = FALSE;
77 dwSize = sizeof(szLayoutNum);
78 dwIndex++;
79 }
80
81 RegCloseKey(hKey);
82 }
83
84 return FALSE;
85 }
86
87 static INT
88 GetLayoutCount(LPTSTR szLang)
89 {
90 HKEY hKey;
91 TCHAR szLayoutID[3 + 1], szPreload[CCH_LAYOUT_ID + 1], szLOLang[MAX_PATH];
92 DWORD dwIndex = 0, dwType, dwSize;
93 UINT Count = 0, i, j;
94
95 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"),
96 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
97 {
98 dwSize = sizeof(szLayoutID);
99
100 while (RegEnumValue(hKey, dwIndex, szLayoutID, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
101 {
102 dwSize = sizeof(szPreload);
103 RegQueryValueEx(hKey, szLayoutID, NULL, NULL, (LPBYTE)szPreload, &dwSize);
104
105 for (i = 4, j = 0; i < _tcslen(szPreload)+1; i++, j++)
106 szLOLang[j] = szPreload[i];
107
108 if (_tcscmp(szLOLang, szLang) == 0) Count += 1;
109
110 dwSize = sizeof(szLayoutID);
111 dwIndex++;
112 }
113
114 RegCloseKey(hKey);
115 }
116
117 return Count;
118 }
119
120 /* szLayoutID like 00000409, szLangID like 00000409 */
121 static BOOL
122 AddNewLayout(LPTSTR szLayoutID, LPTSTR szLangID)
123 {
124 TCHAR NewLayout[CCH_ULONG_DEC + 1], Lang[MAX_PATH],
125 LangID[CCH_LAYOUT_ID + 1], SubPath[CCH_LAYOUT_ID + 1];
126 HKEY hKey, hSubKey;
127 DWORD cValues;
128 LCID lcid;
129
130 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
131 {
132 if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &cValues, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
133 {
134 _ultot(cValues + 1, NewLayout, 10);
135
136 lcid = _tcstoul(szLangID, NULL, 16);
137
138 GetLocaleInfo(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Lang, sizeof(Lang) / sizeof(TCHAR));
139 wsprintf(LangID, _T("0000%s"), Lang);
140
141 if (IsLayoutExists(szLayoutID, LangID))
142 {
143 RegCloseKey(hKey);
144 return FALSE;
145 }
146
147 if (GetLayoutCount(Lang) >= 1)
148 {
149 wsprintf(SubPath, _T("d%03d%s"), GetLayoutCount(Lang), Lang);
150 }
151 else if ((_tcscmp(LangID, szLayoutID) != 0) && (GetLayoutCount(Lang) == 0))
152 {
153 wsprintf(SubPath, _T("d%03d%s"), 0, Lang);
154 }
155 else SubPath[0] = '\0';
156
157 if (_tcslen(SubPath) != 0)
158 {
159 if (RegCreateKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0, NULL,
160 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
161 NULL, &hSubKey, NULL) == ERROR_SUCCESS)
162 {
163 if (RegSetValueEx(hSubKey, SubPath, 0, REG_SZ, (LPBYTE)szLayoutID,
164 (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(TCHAR))) != ERROR_SUCCESS)
165 {
166 RegCloseKey(hSubKey);
167 RegCloseKey(hKey);
168 return FALSE;
169 }
170 RegCloseKey(hSubKey);
171 }
172 lstrcpy(szLayoutID, SubPath);
173 }
174
175 RegSetValueEx(hKey,
176 NewLayout,
177 0,
178 REG_SZ,
179 (LPBYTE)szLayoutID,
180 (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(TCHAR)));
181 }
182 RegCloseKey(hKey);
183 }
184
185 return TRUE;
186 }
187
188 VOID
189 AddNewKbLayoutsByLcid(LCID Lcid)
190 {
191 HINF hIntlInf;
192 TCHAR szLang[CCH_LAYOUT_ID + 1], szLangID[CCH_LAYOUT_ID + 1];
193 TCHAR szLangStr[MAX_STR_SIZE], szLayoutStr[MAX_STR_SIZE], szStr[MAX_STR_SIZE];
194 INFCONTEXT InfContext;
195 LONG Count;
196 DWORD FieldCount, Index;
197
198 GetLocaleInfo(MAKELCID(Lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, szLang, sizeof(szLang) / sizeof(TCHAR));
199 wsprintf(szLangID, _T("0000%s"), szLang);
200
201 hIntlInf = SetupOpenInfFile(_T("intl.inf"), NULL, INF_STYLE_WIN4, NULL);
202
203 if (hIntlInf == INVALID_HANDLE_VALUE)
204 return;
205
206 if (!SetupOpenAppendInfFile(NULL, hIntlInf, NULL))
207 {
208 SetupCloseInfFile(hIntlInf);
209 hIntlInf = NULL;
210 return;
211 }
212
213 Count = SetupGetLineCount(hIntlInf, _T("Locales"));
214 if (Count <= 0) return;
215
216 if (SetupFindFirstLine(hIntlInf, _T("Locales"), szLangID, &InfContext))
217 {
218 FieldCount = SetupGetFieldCount(&InfContext);
219
220 if (FieldCount != 0)
221 {
222 for (Index = 5; Index <= FieldCount; Index++)
223 {
224 if (SetupGetStringField(&InfContext, Index, szStr, MAX_STR_SIZE, NULL))
225 {
226 INT i, j;
227
228 if (_tcslen(szStr) != 13) continue;
229
230 wsprintf(szLangStr, _T("0000%s"), szStr);
231 szLangStr[8] = '\0';
232
233 for (i = 5, j = 0; i <= _tcslen(szStr); i++, j++)
234 szLayoutStr[j] = szStr[i];
235
236 AddNewLayout(szLayoutStr, szLangStr);
237 }
238 }
239 }
240 }
241 SetupCloseInfFile(hIntlInf);
242 }