2 * WineCfg libraries tabsheet
4 * Copyright 2004 Robert van Herk
5 * Copyright 2004 Mike Hearn
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define NONAMELESSUNION
26 #include <wine/debug.h>
32 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
41 UNKNOWN /* Special value indicating an erronous DLL override mode */
50 /* Convert a registry string to a dllmode */
51 static enum dllmode string_to_mode(char *in)
58 out = HeapAlloc(GetProcessHeap(), 0, len);
60 /* remove the spaces */
61 for (i = j = 0; i <= len; ++i) {
67 /* parse the string */
69 if (strcmp(out, "builtin,native") == 0) res = BUILTIN_NATIVE;
70 if (strcmp(out, "native,builtin") == 0) res = NATIVE_BUILTIN;
71 if (strcmp(out, "builtin") == 0) res = BUILTIN;
72 if (strcmp(out, "native") == 0) res = NATIVE;
73 if (strcmp(out, "") == 0) res = DISABLE;
75 HeapFree(GetProcessHeap(), 0, out);
79 /* Convert a dllmode to a registry string. */
80 static const char* mode_to_string(enum dllmode mode)
84 case NATIVE: return "native";
85 case BUILTIN: return "builtin";
86 case NATIVE_BUILTIN: return "native,builtin";
87 case BUILTIN_NATIVE: return "builtin,native";
88 case DISABLE: return "";
89 default: assert(FALSE); return "";
93 /* Convert a dllmode to a pretty string for display. TODO: use translations. */
94 static const char* mode_to_label(enum dllmode mode)
96 WINE_FIXME("translate me\n");
97 return mode_to_string(mode);
100 /* Convert a control id (IDC_ constant) to a dllmode */
101 static enum dllmode id_to_mode(DWORD id)
105 case IDC_RAD_BUILTIN: return BUILTIN;
106 case IDC_RAD_NATIVE: return NATIVE;
107 case IDC_RAD_NATIVE_BUILTIN: return NATIVE_BUILTIN;
108 case IDC_RAD_BUILTIN_NATIVE: return BUILTIN_NATIVE;
109 case IDC_RAD_DISABLE: return DISABLE;
110 default: assert( FALSE ); return 0; /* should not be reached */
114 /* Convert a dllmode to a control id (IDC_ constant) */
115 static DWORD mode_to_id(enum dllmode mode)
119 case BUILTIN: return IDC_RAD_BUILTIN;
120 case NATIVE: return IDC_RAD_NATIVE;
121 case NATIVE_BUILTIN: return IDC_RAD_NATIVE_BUILTIN;
122 case BUILTIN_NATIVE: return IDC_RAD_BUILTIN_NATIVE;
123 case DISABLE: return IDC_RAD_DISABLE;
124 default: assert( FALSE ); return 0; /* should not be reached */
128 static void set_controls_from_selection(HWND dialog)
130 /* FIXME: display/update some information about the selected dll (purpose, recommended loadorder) maybe? */
133 static void clear_settings(HWND dialog)
135 int count = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0);
138 WINE_TRACE("count=%d\n", count);
140 for (i = 0; i < count; i++)
142 struct dll *dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, 0, 0);
144 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, 0, 0);
146 HeapFree(GetProcessHeap(), 0, dll->name);
147 HeapFree(GetProcessHeap(), 0, dll);
151 static void load_library_settings(HWND dialog)
153 char **overrides = enumerate_values(config_key, keypath("DllOverrides"));
157 sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
159 WINE_TRACE("sel=%d\n", sel);
161 clear_settings(dialog);
163 if (!overrides || *overrides == NULL)
165 set_controls_from_selection(dialog);
166 disable(IDC_DLLS_EDITDLL);
167 disable(IDC_DLLS_REMOVEDLL);
168 HeapFree(GetProcessHeap(), 0, overrides);
172 enable(IDC_DLLS_EDITDLL);
173 enable(IDC_DLLS_REMOVEDLL);
175 for (p = overrides; *p != NULL; p++)
182 value = get_reg_key(config_key, keypath("DllOverrides"), *p, NULL);
184 label = mode_to_label(string_to_mode(value));
186 str = HeapAlloc(GetProcessHeap(), 0, strlen(*p) + 2 + strlen(label) + 2);
192 dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll));
194 dll->mode = string_to_mode(value);
196 index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_ADDSTRING, (WPARAM) -1, (LPARAM) str);
197 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETITEMDATA, index, (LPARAM) dll);
199 HeapFree(GetProcessHeap(), 0, str);
204 HeapFree(GetProcessHeap(), 0, overrides);
206 /* restore the previous selection, if possible */
207 if (sel >= count - 1) sel = count - 1;
208 else if (sel == -1) sel = 0;
210 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, sel, 0);
212 set_controls_from_selection(dialog);
215 /* Called when the application is initialized (cannot reinit!) */
216 static void init_libsheet(HWND dialog)
218 /* clear the add dll controls */
219 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM) "");
220 disable(IDC_DLLS_ADDDLL);
223 static void on_add_combo_change(HWND dialog)
227 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
230 enable(IDC_DLLS_ADDDLL)
232 disable(IDC_DLLS_ADDDLL);
235 static void set_dllmode(HWND dialog, DWORD id)
242 mode = id_to_mode(id);
244 sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
245 if (sel == -1) return;
247 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
249 str = mode_to_string(mode);
250 WINE_TRACE("Setting %s to %s\n", dll->name, str);
252 SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0);
253 set_reg_key(config_key, keypath("DllOverrides"), dll->name, str);
255 load_library_settings(dialog); /* ... and refresh */
258 static void on_add_click(HWND dialog)
260 static const char dotDll[] = ".dll";
261 char buffer[1024], *ptr;
263 ZeroMemory(buffer, sizeof(buffer));
265 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
266 if (lstrlenA(buffer) >= sizeof(dotDll))
268 ptr = buffer + lstrlenA(buffer) - sizeof(dotDll) + 1;
269 if (!lstrcmpiA(ptr, dotDll))
271 WINE_TRACE("Stripping dll extension\n");
275 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM) "");
276 disable(IDC_DLLS_ADDDLL);
278 WINE_TRACE("Adding %s as native, builtin", buffer);
280 SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0);
281 set_reg_key(config_key, keypath("DllOverrides"), buffer, "native,builtin");
283 load_library_settings(dialog);
285 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, (WPARAM) 0, (LPARAM) buffer);
287 set_controls_from_selection(dialog);
290 static INT_PTR CALLBACK loadorder_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
297 CheckRadioButton(hwndDlg, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, lParam);
302 if(HIWORD(wParam) != BN_CLICKED) break;
303 switch (LOWORD(wParam))
305 case IDC_RAD_BUILTIN:
307 case IDC_RAD_BUILTIN_NATIVE:
308 case IDC_RAD_NATIVE_BUILTIN:
309 case IDC_RAD_DISABLE:
310 sel = LOWORD(wParam);
313 EndDialog(hwndDlg, sel);
316 EndDialog(hwndDlg, wParam);
323 static void on_edit_click(HWND hwnd)
326 int index = SendDlgItemMessage(hwnd, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
330 /* if no override is selected the edit button should be disabled... */
333 dll = (struct dll *) SendDlgItemMessage(hwnd, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0);
334 id = mode_to_id(dll->mode);
336 ret = DialogBoxParam(0, MAKEINTRESOURCE(IDD_LOADORDER), hwnd, loadorder_dlgproc, id);
339 set_dllmode(hwnd, ret);
342 static void on_remove_click(HWND dialog)
344 int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
347 if (sel == LB_ERR) return;
349 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
351 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0);
353 SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0);
354 set_reg_key(config_key, keypath("DllOverrides"), dll->name, NULL);
356 HeapFree(GetProcessHeap(), 0, dll->name);
357 HeapFree(GetProcessHeap(), 0, dll);
359 if (SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0)
360 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0);
363 disable(IDC_DLLS_EDITDLL);
364 disable(IDC_DLLS_REMOVEDLL);
367 set_controls_from_selection(dialog);
371 LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
379 set_window_title(hDlg);
382 switch (((LPNMHDR)lParam)->code) {
384 load_library_settings(hDlg);
389 switch(HIWORD(wParam)) {
391 /* FIXME: when the user hits enter in the DLL combo box we should invoke the add
392 * add button, rather than the propsheet OK button. But I don't know how to do that!
396 if(LOWORD(wParam) == IDC_DLLCOMBO)
398 on_add_combo_change(hDlg);
403 switch(LOWORD(wParam)) {
404 case IDC_DLLS_ADDDLL:
407 case IDC_DLLS_EDITDLL:
410 case IDC_DLLS_REMOVEDLL:
411 on_remove_click(hDlg);
416 set_controls_from_selection(hDlg);