- rewrite the transaction system to be based on a settings overlay,
[wine/gsoc_dplay.git] / programs / winecfg / libraries.c
blobd3caaa19d6a147f1306379d4202fac3523d40966
1 /*
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
24 #include <windows.h>
25 #include <commdlg.h>
26 #include <wine/debug.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include "winecfg.h"
30 #include "resource.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
34 enum dllmode
36 BUILTIN_NATIVE,
37 NATIVE_BUILTIN,
38 BUILTIN,
39 NATIVE,
40 DISABLE,
41 UNKNOWN /* Special value indicating an erronous DLL override mode */
44 struct dll
46 char *name;
47 enum dllmode mode;
50 static enum dllmode parse_override(char *in)
52 int i, j;
53 char *out;
55 out = HeapAlloc(GetProcessHeap(), 0, strlen(in));
57 /* remove the spaces */
58 j = 0;
59 for (i = 0; i < strlen(in); i++)
61 if (in[i] != ' ')
63 out[j] = in[i];
64 j++;
67 out[j] = 0;
69 /* parse the string */
70 if (strcmp(out, "builtin,native") == 0) return BUILTIN_NATIVE;
71 else if (strcmp(out, "native,builtin") == 0) return NATIVE_BUILTIN;
72 else if (strcmp(out, "native") == 0) return NATIVE;
73 else if (strcmp(out, "builtin") == 0) return BUILTIN;
74 else if (strcmp(out, "") == 0) return DISABLE;
76 return UNKNOWN;
79 /* this is used to convert a dllmode to a human readable string. we should read from the translations here */
80 static char* mode_to_label(enum dllmode mode)
82 char* res;
84 switch (mode) {
85 case NATIVE:
86 res = "native";
87 break;
88 case BUILTIN:
89 res = "builtin";
90 break;
91 case NATIVE_BUILTIN:
92 res = "native, builtin";
93 break;
94 case BUILTIN_NATIVE:
95 res = "builtin, native";
96 break;
97 case DISABLE:
98 res = "disabled";
99 break;
100 default:
101 res = "unknown/invalid";
102 break;
105 return res;
108 static void set_controls_from_selection(HWND dialog)
110 int index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
111 struct dll *dll;
112 DWORD id;
113 int i;
115 if (index == -1) /* no selection */
117 for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++)
118 disable(i);
120 CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, -1);
122 return;
125 /* enable the controls */
126 for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++)
127 enable(i);
129 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0);
131 switch (dll->mode)
133 case NATIVE:
134 id = IDC_RAD_NATIVE;
135 break;
136 case BUILTIN:
137 id = IDC_RAD_BUILTIN;
138 break;
139 case NATIVE_BUILTIN:
140 id = IDC_RAD_NATIVE_BUILTIN;
141 break;
142 case BUILTIN_NATIVE:
143 id = IDC_RAD_BUILTIN_NATIVE;
144 break;
145 case DISABLE:
146 id = IDC_RAD_DISABLE;
147 break;
149 case UNKNOWN:
150 default:
151 id = -1;
152 break;
155 CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, id);
159 static void clear_settings(HWND dialog)
161 int count = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0);
162 int i;
164 WINE_TRACE("count=%d\n", count);
166 for (i = 0; i < count; i++)
168 struct dll *dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, 0, 0);
170 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, 0, 0);
172 HeapFree(GetProcessHeap(), 0, dll->name);
173 HeapFree(GetProcessHeap(), 0, dll);
177 static void load_library_settings(HWND dialog)
179 char **overrides = enumerate_values(keypath("DllOverrides"));
180 char **p;
181 int sel, count = 0;
183 sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
185 WINE_TRACE("sel=%d\n", sel);
187 clear_settings(dialog);
189 if (!overrides || *overrides == NULL)
191 set_controls_from_selection(dialog);
192 disable(IDC_DLLS_REMOVEDLL);
193 HeapFree(GetProcessHeap(), 0, overrides);
194 return;
197 enable(IDC_DLLS_REMOVEDLL);
199 for (p = overrides; *p != NULL; p++)
201 int index;
202 char *str, *value, *label;
203 struct dll *dll;
205 value = get(keypath("DllOverrides"), *p, NULL);
207 label = mode_to_label(parse_override(value));
209 str = HeapAlloc(GetProcessHeap(), 0, strlen(*p) + 2 + strlen(label) + 2);
210 strcpy(str, *p);
211 strcat(str, " (");
212 strcat(str, label);
213 strcat(str, ")");
215 dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll));
216 dll->name = *p;
217 dll->mode = parse_override(value);
219 index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_ADDSTRING, (WPARAM) -1, (LPARAM) str);
220 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETITEMDATA, index, (LPARAM) dll);
222 HeapFree(GetProcessHeap(), 0, str);
224 count++;
227 HeapFree(GetProcessHeap(), 0, overrides);
229 /* restore the previous selection, if possible */
230 if (sel >= count - 1) sel = count - 1;
231 else if (sel == -1) sel = 0;
233 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, sel, 0);
235 set_controls_from_selection(dialog);
238 /* Called when the application is initialized (cannot reinit!) */
239 static void init_libsheet(HWND dialog)
241 /* clear the add dll controls */
242 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM) "");
243 disable(IDC_DLLS_ADDDLL);
247 static void on_add_combo_change(HWND dialog)
249 char buffer[1024];
251 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
253 if (strlen(buffer))
254 enable(IDC_DLLS_ADDDLL)
255 else
256 disable(IDC_DLLS_ADDDLL);
259 static void set_dllmode(HWND dialog, DWORD id)
261 enum dllmode mode;
262 struct dll *dll;
263 int sel;
264 char *str;
266 #define CONVERT(s) case IDC_RAD_##s: mode = s; break;
268 switch (id)
270 CONVERT( BUILTIN );
271 CONVERT( NATIVE );
272 CONVERT( BUILTIN_NATIVE );
273 CONVERT( NATIVE_BUILTIN );
274 CONVERT( DISABLE );
276 default: assert( FALSE ); /* should not be reached */
279 #undef CONVERT
281 sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
282 if (sel == -1) return;
284 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
286 switch (mode)
288 case BUILTIN: str = "builtin"; break;
289 case NATIVE: str = "native"; break;
290 case BUILTIN_NATIVE: str = "builtin, native"; break;
291 case NATIVE_BUILTIN: str = "native, builtin"; break;
292 case DISABLE: str = ""; break;
293 default: assert( FALSE ); /* unreachable */
295 WINE_TRACE("Setting %s to %s\n", dll->name, str);
297 set(keypath("DllOverrides"), dll->name, str);
299 load_library_settings(dialog); /* ... and refresh */
302 static void on_add_click(HWND dialog)
304 char buffer[1024];
306 ZeroMemory(buffer, sizeof(buffer));
308 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
310 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM) "");
311 disable(IDC_DLLS_ADDDLL);
313 WINE_TRACE("Adding %s as native, builtin", buffer);
315 set(keypath("DllOverrides"), buffer, "native,builtin");
317 load_library_settings(dialog);
319 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, (WPARAM) 0, (LPARAM) buffer);
321 set_controls_from_selection(dialog);
324 static void on_remove_click(HWND dialog)
326 int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
327 struct dll *dll;
329 if (sel == LB_ERR) return;
331 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
333 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0);
335 set(keypath("DllOverrides"), dll->name, NULL);
337 HeapFree(GetProcessHeap(), 0, dll->name);
338 HeapFree(GetProcessHeap(), 0, dll);
340 if (SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0)
341 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0);
342 else
343 disable(IDC_DLLS_REMOVEDLL);
345 set_controls_from_selection(dialog);
348 INT_PTR CALLBACK
349 LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
351 switch (uMsg)
353 case WM_INITDIALOG:
354 init_libsheet(hDlg);
355 break;
356 case WM_SHOWWINDOW:
357 set_window_title(hDlg);
358 break;
359 case WM_NOTIFY:
360 switch (((LPNMHDR)lParam)->code) {
361 case PSN_SETACTIVE:
362 load_library_settings(hDlg);
363 break;
365 break;
366 case WM_COMMAND:
367 switch(HIWORD(wParam)) {
369 /* FIXME: when the user hits enter in the DLL combo box we should invoke the add
370 * add button, rather than the propsheet OK button. But I don't know how to do that!
373 case CBN_EDITCHANGE:
374 if(LOWORD(wParam) == IDC_DLLCOMBO)
376 on_add_combo_change(hDlg);
377 break;
380 case BN_CLICKED:
381 switch(LOWORD(wParam)) {
382 case IDC_RAD_BUILTIN:
383 case IDC_RAD_NATIVE:
384 case IDC_RAD_BUILTIN_NATIVE:
385 case IDC_RAD_NATIVE_BUILTIN:
386 case IDC_RAD_DISABLE:
387 set_dllmode(hDlg, LOWORD(wParam));
388 break;
390 case IDC_DLLS_ADDDLL:
391 on_add_click(hDlg);
392 break;
393 case IDC_DLLS_REMOVEDLL:
394 on_remove_click(hDlg);
395 break;
397 break;
398 case LBN_SELCHANGE:
399 set_controls_from_selection(hDlg);
400 break;
402 break;
405 return 0;