ntdll: Check file size when mapping image sections to avoid SIGBUS errors.
[wine/multimedia.git] / programs / winecfg / theme.c
blob37541ccbfda6276208e00456eeb960ec491f003d
1 /*
2 * Theme configuration code
4 * Copyright (c) 2005 by Frank Richter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
26 #include <windef.h>
27 #include <winbase.h>
28 #include <wingdi.h>
29 #include <winuser.h>
30 #include <uxtheme.h>
31 #include <tmschema.h>
32 #include <shlobj.h>
33 #include <shlwapi.h>
34 #include <wine/debug.h>
36 #include "resource.h"
37 #include "winecfg.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
41 /* UXTHEME functions not in the headers */
43 typedef struct tagTHEMENAMES
45 WCHAR szName[MAX_PATH+1];
46 WCHAR szDisplayName[MAX_PATH+1];
47 WCHAR szTooltip[MAX_PATH+1];
48 } THEMENAMES, *PTHEMENAMES;
50 typedef void* HTHEMEFILE;
51 typedef BOOL (CALLBACK *EnumThemeProc)(LPVOID lpReserved,
52 LPCWSTR pszThemeFileName,
53 LPCWSTR pszThemeName,
54 LPCWSTR pszToolTip, LPVOID lpReserved2,
55 LPVOID lpData);
57 HRESULT WINAPI EnumThemeColors (LPWSTR pszThemeFileName, LPWSTR pszSizeName,
58 DWORD dwColorNum, PTHEMENAMES pszColorNames);
59 HRESULT WINAPI EnumThemeSizes (LPWSTR pszThemeFileName, LPWSTR pszColorName,
60 DWORD dwSizeNum, PTHEMENAMES pszSizeNames);
61 HRESULT WINAPI ApplyTheme (HTHEMEFILE hThemeFile, char* unknown, HWND hWnd);
62 HRESULT WINAPI OpenThemeFile (LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
63 LPCWSTR pszSizeName, HTHEMEFILE* hThemeFile,
64 DWORD unknown);
65 HRESULT WINAPI CloseThemeFile (HTHEMEFILE hThemeFile);
66 HRESULT WINAPI EnumThemes (LPCWSTR pszThemePath, EnumThemeProc callback,
67 LPVOID lpData);
69 /* A struct to keep both the internal and "fancy" name of a color or size */
70 typedef struct
72 WCHAR* name;
73 WCHAR* fancyName;
74 } ThemeColorOrSize;
76 /* wrapper around DSA that also keeps an item count */
77 typedef struct
79 HDSA dsa;
80 int count;
81 } WrappedDsa;
83 /* Some helper functions to deal with ThemeColorOrSize structs in WrappedDSAs */
85 static void color_or_size_dsa_add (WrappedDsa* wdsa, const WCHAR* name,
86 const WCHAR* fancyName)
88 ThemeColorOrSize item;
90 item.name = HeapAlloc (GetProcessHeap(), 0,
91 (lstrlenW (name) + 1) * sizeof(WCHAR));
92 lstrcpyW (item.name, name);
94 item.fancyName = HeapAlloc (GetProcessHeap(), 0,
95 (lstrlenW (fancyName) + 1) * sizeof(WCHAR));
96 lstrcpyW (item.fancyName, fancyName);
98 DSA_InsertItem (wdsa->dsa, wdsa->count, &item);
99 wdsa->count++;
102 static int CALLBACK dsa_destroy_callback (LPVOID p, LPVOID pData)
104 ThemeColorOrSize* item = (ThemeColorOrSize*)p;
105 HeapFree (GetProcessHeap(), 0, item->name);
106 HeapFree (GetProcessHeap(), 0, item->fancyName);
107 return 1;
110 static void free_color_or_size_dsa (WrappedDsa* wdsa)
112 DSA_DestroyCallback (wdsa->dsa, dsa_destroy_callback, NULL);
115 static void create_color_or_size_dsa (WrappedDsa* wdsa)
117 wdsa->dsa = DSA_Create (sizeof (ThemeColorOrSize), 1);
118 wdsa->count = 0;
121 static ThemeColorOrSize* color_or_size_dsa_get (WrappedDsa* wdsa, int index)
123 return (ThemeColorOrSize*)DSA_GetItemPtr (wdsa->dsa, index);
126 static int color_or_size_dsa_find (WrappedDsa* wdsa, const WCHAR* name)
128 int i = 0;
129 for (; i < wdsa->count; i++)
131 ThemeColorOrSize* item = color_or_size_dsa_get (wdsa, i);
132 if (lstrcmpiW (item->name, name) == 0) break;
134 return i;
137 /* A theme file, contains file name, display name, color and size scheme names */
138 typedef struct
140 WCHAR* themeFileName;
141 WCHAR* fancyName;
142 WrappedDsa colors;
143 WrappedDsa sizes;
144 } ThemeFile;
146 static HDSA themeFiles = NULL;
147 static int themeFilesCount = 0;
149 static int CALLBACK theme_dsa_destroy_callback (LPVOID p, LPVOID pData)
151 ThemeFile* item = (ThemeFile*)p;
152 HeapFree (GetProcessHeap(), 0, item->themeFileName);
153 HeapFree (GetProcessHeap(), 0, item->fancyName);
154 free_color_or_size_dsa (&item->colors);
155 free_color_or_size_dsa (&item->sizes);
156 return 1;
159 /* Free memory occupied by the theme list */
160 static void free_theme_files(void)
162 if (themeFiles == NULL) return;
164 DSA_DestroyCallback (themeFiles , theme_dsa_destroy_callback, NULL);
165 themeFiles = NULL;
166 themeFilesCount = 0;
169 typedef HRESULT (WINAPI * EnumTheme) (LPWSTR, LPWSTR, DWORD, PTHEMENAMES);
171 /* fill a string list with either colors or sizes of a theme */
172 static void fill_theme_string_array (const WCHAR* filename,
173 WrappedDsa* wdsa,
174 EnumTheme enumTheme)
176 DWORD index = 0;
177 THEMENAMES names;
179 WINE_TRACE ("%s %p %p\n", wine_dbgstr_w (filename), wdsa, enumTheme);
181 while (SUCCEEDED (enumTheme ((WCHAR*)filename, NULL, index++, &names)))
183 WINE_TRACE ("%s: %s\n", wine_dbgstr_w (names.szName),
184 wine_dbgstr_w (names.szDisplayName));
185 color_or_size_dsa_add (wdsa, names.szName, names.szDisplayName);
189 /* Theme enumeration callback, adds theme to theme list */
190 static BOOL CALLBACK myEnumThemeProc (LPVOID lpReserved,
191 LPCWSTR pszThemeFileName,
192 LPCWSTR pszThemeName,
193 LPCWSTR pszToolTip,
194 LPVOID lpReserved2, LPVOID lpData)
196 ThemeFile newEntry;
198 /* fill size/color lists */
199 create_color_or_size_dsa (&newEntry.colors);
200 fill_theme_string_array (pszThemeFileName, &newEntry.colors, EnumThemeColors);
201 create_color_or_size_dsa (&newEntry.sizes);
202 fill_theme_string_array (pszThemeFileName, &newEntry.sizes, EnumThemeSizes);
204 newEntry.themeFileName = HeapAlloc (GetProcessHeap(), 0,
205 (lstrlenW (pszThemeFileName) + 1) * sizeof(WCHAR));
206 lstrcpyW (newEntry.themeFileName, pszThemeFileName);
208 newEntry.fancyName = HeapAlloc (GetProcessHeap(), 0,
209 (lstrlenW (pszThemeName) + 1) * sizeof(WCHAR));
210 lstrcpyW (newEntry.fancyName, pszThemeName);
212 /*list_add_tail (&themeFiles, &newEntry->entry);*/
213 DSA_InsertItem (themeFiles, themeFilesCount, &newEntry);
214 themeFilesCount++;
216 return TRUE;
219 /* Scan for themes */
220 static void scan_theme_files(void)
222 static const WCHAR themesSubdir[] = { '\\','T','h','e','m','e','s',0 };
223 WCHAR themesPath[MAX_PATH];
225 free_theme_files();
227 if (FAILED (SHGetFolderPathW (NULL, CSIDL_RESOURCES, NULL,
228 SHGFP_TYPE_CURRENT, themesPath))) return;
230 themeFiles = DSA_Create (sizeof (ThemeFile), 1);
231 lstrcatW (themesPath, themesSubdir);
233 EnumThemes (themesPath, myEnumThemeProc, 0);
236 /* fill the color & size combo boxes for a given theme */
237 static void fill_color_size_combos (ThemeFile* theme, HWND comboColor,
238 HWND comboSize)
240 int i;
242 SendMessageW (comboColor, CB_RESETCONTENT, 0, 0);
243 for (i = 0; i < theme->colors.count; i++)
245 ThemeColorOrSize* item = color_or_size_dsa_get (&theme->colors, i);
246 SendMessageW (comboColor, CB_ADDSTRING, 0, (LPARAM)item->fancyName);
249 SendMessageW (comboSize, CB_RESETCONTENT, 0, 0);
250 for (i = 0; i < theme->sizes.count; i++)
252 ThemeColorOrSize* item = color_or_size_dsa_get (&theme->sizes, i);
253 SendMessageW (comboSize, CB_ADDSTRING, 0, (LPARAM)item->fancyName);
257 /* Select the item of a combo box that matches a theme's color and size
258 * scheme. */
259 static void select_color_and_size (ThemeFile* theme,
260 const WCHAR* colorName, HWND comboColor,
261 const WCHAR* sizeName, HWND comboSize)
263 SendMessageW (comboColor, CB_SETCURSEL,
264 color_or_size_dsa_find (&theme->colors, colorName), 0);
265 SendMessageW (comboSize, CB_SETCURSEL,
266 color_or_size_dsa_find (&theme->sizes, sizeName), 0);
269 /* Fill theme, color and sizes combo boxes with the know themes and select
270 * the entries matching the currently active theme. */
271 static BOOL fill_theme_list (HWND comboTheme, HWND comboColor, HWND comboSize)
273 WCHAR textNoTheme[256];
274 int themeIndex = 0;
275 BOOL ret = TRUE;
276 int i;
277 WCHAR currentTheme[MAX_PATH];
278 WCHAR currentColor[MAX_PATH];
279 WCHAR currentSize[MAX_PATH];
280 ThemeFile* theme = NULL;
282 LoadStringW (GetModuleHandle (NULL), IDS_NOTHEME, textNoTheme,
283 sizeof(textNoTheme) / sizeof(WCHAR));
285 SendMessageW (comboTheme, CB_RESETCONTENT, 0, 0);
286 SendMessageW (comboTheme, CB_ADDSTRING, 0, (LPARAM)textNoTheme);
288 for (i = 0; i < themeFilesCount; i++)
290 ThemeFile* item = (ThemeFile*)DSA_GetItemPtr (themeFiles, i);
291 SendMessageW (comboTheme, CB_ADDSTRING, 0,
292 (LPARAM)item->fancyName);
295 if (IsThemeActive () && SUCCEEDED (GetCurrentThemeName (currentTheme,
296 sizeof(currentTheme) / sizeof(WCHAR),
297 currentColor, sizeof(currentColor) / sizeof(WCHAR),
298 currentSize, sizeof(currentSize) / sizeof(WCHAR))))
300 /* Determine the index of the currently active theme. */
301 BOOL found = FALSE;
302 for (i = 0; i < themeFilesCount; i++)
304 theme = (ThemeFile*)DSA_GetItemPtr (themeFiles, i);
305 if (lstrcmpiW (theme->themeFileName, currentTheme) == 0)
307 found = TRUE;
308 themeIndex = i+1;
309 break;
312 if (!found)
314 /* Current theme not found?... add to the list, then... */
315 WINE_TRACE("Theme %s not in list of enumerated themes",
316 wine_dbgstr_w (currentTheme));
317 myEnumThemeProc (NULL, currentTheme, currentTheme,
318 currentTheme, NULL, NULL);
319 themeIndex = themeFilesCount;
320 theme = (ThemeFile*)DSA_GetItemPtr (themeFiles,
321 themeFilesCount-1);
323 fill_color_size_combos (theme, comboColor, comboSize);
324 select_color_and_size (theme, currentColor, comboColor,
325 currentSize, comboSize);
327 else
329 /* No theme selected */
330 ret = FALSE;
333 SendMessageW (comboTheme, CB_SETCURSEL, themeIndex, 0);
334 return ret;
337 /* Update the color & size combo boxes when the selection of the theme
338 * combo changed. Selects the current color and size scheme if the theme
339 * is currently active, otherwise the first color and size. */
340 static BOOL update_color_and_size (int themeIndex, HWND comboColor,
341 HWND comboSize)
343 if (themeIndex == 0)
345 return FALSE;
347 else
349 WCHAR currentTheme[MAX_PATH];
350 WCHAR currentColor[MAX_PATH];
351 WCHAR currentSize[MAX_PATH];
352 ThemeFile* theme =
353 (ThemeFile*)DSA_GetItemPtr (themeFiles, themeIndex - 1);
355 fill_color_size_combos (theme, comboColor, comboSize);
357 if ((SUCCEEDED (GetCurrentThemeName (currentTheme,
358 sizeof(currentTheme) / sizeof(WCHAR),
359 currentColor, sizeof(currentColor) / sizeof(WCHAR),
360 currentSize, sizeof(currentSize) / sizeof(WCHAR))))
361 && (lstrcmpiW (currentTheme, theme->themeFileName) == 0))
363 select_color_and_size (theme, currentColor, comboColor,
364 currentSize, comboSize);
366 else
368 SendMessageW (comboColor, CB_SETCURSEL, 0, 0);
369 SendMessageW (comboSize, CB_SETCURSEL, 0, 0);
372 return TRUE;
375 /* Apply a theme from a given theme, color and size combo box item index. */
376 static void do_apply_theme (int themeIndex, int colorIndex, int sizeIndex)
378 static char b[] = "\0";
380 if (themeIndex == 0)
382 /* no theme */
383 ApplyTheme (NULL, b, NULL);
385 else
387 ThemeFile* theme =
388 (ThemeFile*)DSA_GetItemPtr (themeFiles, themeIndex-1);
389 const WCHAR* themeFileName = theme->themeFileName;
390 const WCHAR* colorName = NULL;
391 const WCHAR* sizeName = NULL;
392 HTHEMEFILE hTheme;
393 ThemeColorOrSize* item;
395 item = color_or_size_dsa_get (&theme->colors, colorIndex);
396 colorName = item->name;
398 item = color_or_size_dsa_get (&theme->sizes, sizeIndex);
399 sizeName = item->name;
401 if (SUCCEEDED (OpenThemeFile (themeFileName, colorName, sizeName,
402 &hTheme, 0)))
404 ApplyTheme (hTheme, b, NULL);
405 CloseThemeFile (hTheme);
407 else
409 ApplyTheme (NULL, b, NULL);
414 int updating_ui;
415 BOOL theme_dirty;
417 static void enable_size_and_color_controls (HWND dialog, BOOL enable)
419 EnableWindow (GetDlgItem (dialog, IDC_THEME_COLORCOMBO), enable);
420 EnableWindow (GetDlgItem (dialog, IDC_THEME_COLORTEXT), enable);
421 EnableWindow (GetDlgItem (dialog, IDC_THEME_SIZECOMBO), enable);
422 EnableWindow (GetDlgItem (dialog, IDC_THEME_SIZETEXT), enable);
425 static void init_dialog (HWND dialog)
427 updating_ui = TRUE;
429 scan_theme_files();
430 if (!fill_theme_list (GetDlgItem (dialog, IDC_THEME_THEMECOMBO),
431 GetDlgItem (dialog, IDC_THEME_COLORCOMBO),
432 GetDlgItem (dialog, IDC_THEME_SIZECOMBO)))
434 SendMessageW (GetDlgItem (dialog, IDC_THEME_COLORCOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
435 SendMessageW (GetDlgItem (dialog, IDC_THEME_SIZECOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
436 enable_size_and_color_controls (dialog, FALSE);
438 else
440 enable_size_and_color_controls (dialog, TRUE);
442 theme_dirty = FALSE;
444 updating_ui = FALSE;
447 static void on_theme_changed(HWND dialog) {
448 int index = SendMessageW (GetDlgItem (dialog, IDC_THEME_THEMECOMBO),
449 CB_GETCURSEL, 0, 0);
450 if (!update_color_and_size (index, GetDlgItem (dialog, IDC_THEME_COLORCOMBO),
451 GetDlgItem (dialog, IDC_THEME_SIZECOMBO)))
453 SendMessageW (GetDlgItem (dialog, IDC_THEME_COLORCOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
454 SendMessageW (GetDlgItem (dialog, IDC_THEME_SIZECOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
455 enable_size_and_color_controls (dialog, FALSE);
457 else
459 enable_size_and_color_controls (dialog, TRUE);
461 theme_dirty = TRUE;
464 static void apply_theme(HWND dialog)
466 int themeIndex, colorIndex, sizeIndex;
468 if (!theme_dirty) return;
470 themeIndex = SendMessageW (GetDlgItem (dialog, IDC_THEME_THEMECOMBO),
471 CB_GETCURSEL, 0, 0);
472 colorIndex = SendMessageW (GetDlgItem (dialog, IDC_THEME_COLORCOMBO),
473 CB_GETCURSEL, 0, 0);
474 sizeIndex = SendMessageW (GetDlgItem (dialog, IDC_THEME_SIZECOMBO),
475 CB_GETCURSEL, 0, 0);
477 do_apply_theme (themeIndex, colorIndex, sizeIndex);
478 theme_dirty = FALSE;
481 static void on_theme_install(HWND dialog)
483 static const WCHAR filterMask[] = {0,'*','.','m','s','s','t','y','l','e','s',0,0};
484 const int filterMaskLen = sizeof(filterMask)/sizeof(filterMask[0]);
485 OPENFILENAMEW ofn;
486 WCHAR filetitle[MAX_PATH];
487 WCHAR file[MAX_PATH];
488 WCHAR filter[100];
489 WCHAR title[100];
491 LoadStringW (GetModuleHandle (NULL), IDS_THEMEFILE,
492 filter, sizeof (filter) / sizeof (filter[0]) - filterMaskLen);
493 memcpy (filter + lstrlenW (filter), filterMask,
494 filterMaskLen * sizeof (WCHAR));
495 LoadStringW (GetModuleHandle (NULL), IDS_THEMEFILE_SELECT,
496 title, sizeof (title) / sizeof (title[0]));
498 ofn.lStructSize = sizeof(OPENFILENAMEW);
499 ofn.hwndOwner = 0;
500 ofn.hInstance = 0;
501 ofn.lpstrFilter = filter;
502 ofn.lpstrCustomFilter = NULL;
503 ofn.nMaxCustFilter = 0;
504 ofn.nFilterIndex = 0;
505 ofn.lpstrFile = file;
506 ofn.lpstrFile[0] = '\0';
507 ofn.nMaxFile = sizeof(file)/sizeof(filetitle[0]);
508 ofn.lpstrFileTitle = filetitle;
509 ofn.lpstrFileTitle[0] = '\0';
510 ofn.nMaxFileTitle = sizeof(filetitle)/sizeof(filetitle[0]);
511 ofn.lpstrInitialDir = NULL;
512 ofn.lpstrTitle = title;
513 ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
514 ofn.nFileOffset = 0;
515 ofn.nFileExtension = 0;
516 ofn.lpstrDefExt = NULL;
517 ofn.lCustData = 0;
518 ofn.lpfnHook = NULL;
519 ofn.lpTemplateName = NULL;
521 if (GetOpenFileNameW(&ofn))
523 static const WCHAR themesSubdir[] = { '\\','T','h','e','m','e','s',0 };
524 static const WCHAR backslash[] = { '\\',0 };
525 WCHAR themeFilePath[MAX_PATH];
526 SHFILEOPSTRUCTW shfop;
528 if (FAILED (SHGetFolderPathW (NULL, CSIDL_RESOURCES, NULL,
529 SHGFP_TYPE_CURRENT, themeFilePath))) return;
531 PathRemoveExtensionW (filetitle);
533 /* Construct path into which the theme file goes */
534 lstrcatW (themeFilePath, themesSubdir);
535 lstrcatW (themeFilePath, backslash);
536 lstrcatW (themeFilePath, filetitle);
538 /* Create the directory */
539 SHCreateDirectoryExW (dialog, themeFilePath, NULL);
541 /* Append theme file name itself */
542 lstrcatW (themeFilePath, backslash);
543 lstrcatW (themeFilePath, PathFindFileNameW (file));
544 /* SHFileOperation() takes lists as input, so double-nullterminate */
545 themeFilePath[lstrlenW (themeFilePath)+1] = 0;
546 file[lstrlenW (file)+1] = 0;
548 /* Do the copying */
549 WINE_TRACE("copying: %s -> %s\n", wine_dbgstr_w (file),
550 wine_dbgstr_w (themeFilePath));
551 shfop.hwnd = dialog;
552 shfop.wFunc = FO_COPY;
553 shfop.pFrom = file;
554 shfop.pTo = themeFilePath;
555 shfop.fFlags = FOF_NOCONFIRMMKDIR;
556 if (SHFileOperationW (&shfop) == 0)
558 scan_theme_files();
559 if (!fill_theme_list (GetDlgItem (dialog, IDC_THEME_THEMECOMBO),
560 GetDlgItem (dialog, IDC_THEME_COLORCOMBO),
561 GetDlgItem (dialog, IDC_THEME_SIZECOMBO)))
563 SendMessageW (GetDlgItem (dialog, IDC_THEME_COLORCOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
564 SendMessageW (GetDlgItem (dialog, IDC_THEME_SIZECOMBO), CB_SETCURSEL, (WPARAM)-1, 0);
565 enable_size_and_color_controls (dialog, FALSE);
567 else
569 enable_size_and_color_controls (dialog, TRUE);
572 else
573 WINE_TRACE("copy operation failed\n");
575 else WINE_TRACE("user cancelled\n");
578 INT_PTR CALLBACK
579 ThemeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
581 switch (uMsg) {
582 case WM_INITDIALOG:
583 break;
585 case WM_DESTROY:
586 free_theme_files();
587 break;
589 case WM_SHOWWINDOW:
590 set_window_title(hDlg);
591 break;
593 case WM_COMMAND:
594 switch(HIWORD(wParam)) {
595 case CBN_SELCHANGE: {
596 if (updating_ui) break;
597 SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
598 switch (LOWORD(wParam))
600 case IDC_THEME_THEMECOMBO: on_theme_changed(hDlg); break;
601 case IDC_THEME_COLORCOMBO: /* fall through */
602 case IDC_THEME_SIZECOMBO: theme_dirty = TRUE; break;
604 break;
607 default:
608 break;
610 switch (LOWORD(wParam))
612 case IDC_THEME_INSTALL:
613 if (HIWORD(wParam) != BN_CLICKED) break;
614 on_theme_install (hDlg);
615 break;
617 default:
618 break;
620 break;
623 case WM_NOTIFY:
624 switch (((LPNMHDR)lParam)->code) {
625 case PSN_KILLACTIVE: {
626 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
627 break;
629 case PSN_APPLY: {
630 apply();
631 apply_theme(hDlg);
632 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
633 break;
635 case PSN_SETACTIVE: {
636 init_dialog (hDlg);
637 break;
640 break;
642 default:
643 break;
645 return FALSE;