Copy wininet to branch
[reactos.git] / reactos / lib / cpl / intl / locale.c
1 /*
2 * ReactOS
3 * Copyright (C) 2004, 2005 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS International Control Panel
22 * FILE: lib/cpl/intl/locale.c
23 * PURPOSE: Locale property page
24 * PROGRAMMER: Eric Kohl
25 * Klemens Friedl
26 */
27
28 #include <windows.h>
29 #include <commctrl.h>
30 #include <cpl.h>
31
32 #include "intl.h"
33 #include "resource.h"
34
35
36 // FIXME:
37 // * change registry function (-> "HKCR\MIME\Database\Rfc1766")
38
39
40
41 typedef struct _TZ_INFO
42 {
43 LONG Bias;
44 LONG StandardBias;
45 LONG DaylightBias;
46 SYSTEMTIME StandardDate;
47 SYSTEMTIME DaylightDate;
48 } TZ_INFO, *PTZ_INFO;
49
50 typedef struct _TIMEZONE_ENTRY
51 {
52 struct _TIMEZONE_ENTRY *Prev;
53 struct _TIMEZONE_ENTRY *Next;
54 WCHAR Description[64]; /* 'Display' */
55 WCHAR StandardName[32]; /* 'Std' */
56 WCHAR DaylightName[32]; /* 'Dlt' */
57 TZ_INFO TimezoneInfo; /* 'TZI' */
58 ULONG Index; /* 'Index' */
59 } TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
60
61
62
63 PTIMEZONE_ENTRY TimeZoneListHead = NULL;
64 PTIMEZONE_ENTRY TimeZoneListTail = NULL;
65
66
67
68
69 static PTIMEZONE_ENTRY
70 GetLargerTimeZoneEntry(DWORD Index)
71 {
72 PTIMEZONE_ENTRY Entry;
73
74 Entry = TimeZoneListHead;
75 while (Entry != NULL)
76 {
77 if (Entry->Index >= Index)
78 return Entry;
79
80 Entry = Entry->Next;
81 }
82
83 return NULL;
84 }
85
86
87 static VOID
88 CreateTimeZoneList(VOID)
89 {
90
91 WCHAR szKeyName[256];
92 DWORD dwIndex;
93 DWORD dwNameSize;
94 DWORD dwValueSize;
95 LONG lError;
96 HKEY hZonesKey;
97 HKEY hZoneKey;
98
99 PTIMEZONE_ENTRY Entry;
100 PTIMEZONE_ENTRY Current;
101
102
103
104 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
105 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
106 0,
107 KEY_ALL_ACCESS,
108 &hZonesKey))
109 return;
110
111 dwIndex = 0;
112 while (TRUE)
113 {
114 dwNameSize = 256;
115 lError = RegEnumKeyExW(hZonesKey,
116 dwIndex,
117 szKeyName,
118 &dwNameSize,
119 NULL,
120 NULL,
121 NULL,
122 NULL);
123 if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
124 break;
125
126
127 if (RegOpenKeyExW(hZonesKey,
128 szKeyName,
129 0,
130 KEY_ALL_ACCESS,
131 &hZoneKey))
132 break;
133
134
135 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
136 if (Entry == NULL)
137 {
138 RegCloseKey(hZonesKey);
139 break;
140 }
141
142 dwValueSize = 64 * sizeof(WCHAR);
143 if (RegQueryValueExW(hZonesKey,
144 L"Display",
145 NULL,
146 NULL,
147 (LPBYTE)&Entry->Description,
148 &dwValueSize))
149 {
150 RegCloseKey(hZonesKey);
151 break;
152 }
153
154 dwValueSize = 32 * sizeof(WCHAR);
155 if (RegQueryValueExW(hZonesKey,
156 L"Std",
157 NULL,
158 NULL,
159 (LPBYTE)&Entry->StandardName,
160 &dwValueSize))
161 {
162 RegCloseKey(hZonesKey);
163 break;
164 }
165
166 dwValueSize = 32 * sizeof(WCHAR);
167 if (RegQueryValueExW(hZonesKey,
168 L"Dlt",
169 NULL,
170 NULL,
171 (LPBYTE)&Entry->DaylightName,
172 &dwValueSize))
173 {
174 RegCloseKey(hZonesKey);
175 break;
176 }
177
178 dwValueSize = sizeof(DWORD);
179 if (RegQueryValueExW(hZonesKey,
180 L"Index",
181 NULL,
182 NULL,
183 (LPBYTE)&Entry->Index,
184 &dwValueSize))
185 {
186 RegCloseKey(hZonesKey);
187 break;
188 }
189
190 dwValueSize = sizeof(TZ_INFO);
191 if (RegQueryValueExW(hZonesKey,
192 L"TZI",
193 NULL,
194 NULL,
195 (LPBYTE)&Entry->TimezoneInfo,
196 &dwValueSize))
197 {
198 RegCloseKey(hZonesKey);
199 break;
200 }
201
202 RegCloseKey(hZoneKey);
203
204 if (TimeZoneListHead == NULL &&
205 TimeZoneListTail == NULL)
206 {
207 Entry->Prev = NULL;
208 Entry->Next = NULL;
209 TimeZoneListHead = Entry;
210 TimeZoneListTail = Entry;
211 }
212 else
213 {
214 Current = GetLargerTimeZoneEntry(Entry->Index);
215 if (Current != NULL)
216 {
217 if (Current == TimeZoneListHead)
218 {
219 /* Prepend to head */
220 Entry->Prev = NULL;
221 Entry->Next = TimeZoneListHead;
222 TimeZoneListHead->Prev = Entry;
223 TimeZoneListHead = Entry;
224 }
225 else
226 {
227 /* Insert before current */
228 Entry->Prev = Current->Prev;
229 Entry->Next = Current;
230 Current->Prev->Next = Entry;
231 Current->Prev = Entry;
232 }
233 }
234 else
235 {
236 /* Append to tail */
237 Entry->Prev = TimeZoneListTail;
238 Entry->Next = NULL;
239 TimeZoneListTail->Next = Entry;
240 TimeZoneListTail = Entry;
241 }
242 }
243
244 dwIndex++;
245 }
246
247 RegCloseKey(hZonesKey);
248
249 }
250
251
252 static VOID
253 ShowTimeZoneList(HWND hwnd)
254 {
255 TIME_ZONE_INFORMATION TimeZoneInfo;
256 PTIMEZONE_ENTRY Entry;
257 DWORD dwIndex;
258 DWORD i;
259
260 GetTimeZoneInformation(&TimeZoneInfo);
261
262 dwIndex = 0;
263 i = 0;
264 Entry = TimeZoneListHead;
265 while (Entry != NULL)
266 {
267 SendMessageW(hwnd,
268 CB_ADDSTRING,
269 0,
270 (LPARAM)Entry->Description);
271
272 if (!wcscmp(Entry->StandardName, TimeZoneInfo.StandardName))
273 dwIndex = i;
274
275 i++;
276 Entry = Entry->Next;
277 }
278
279 SendMessageW(hwnd,
280 CB_SETCURSEL,
281 (WPARAM)dwIndex,
282 0);
283 }
284
285
286
287
288 /* Property page dialog callback */
289 INT_PTR CALLBACK
290 LocalePageProc(HWND hwndDlg,
291 UINT uMsg,
292 WPARAM wParam,
293 LPARAM lParam)
294 {
295 switch(uMsg)
296 {
297 case WM_INITDIALOG:
298
299 CreateTimeZoneList();
300 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_LANGUAGELIST));
301
302 break;
303 }
304 return FALSE;
305 }
306
307
308 /* EOF */