Move a fixed size buffer to the heap.
[wine/multimedia.git] / programs / winecfg / libraries.c
blob372109ba68a03cac4c2bdfb562df577c77534284
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 /* Convert a registry string to a dllmode */
51 static enum dllmode string_to_mode(char *in)
53 int i, j, len;
54 char *out;
55 enum dllmode res;
57 len = strlen(in);
58 out = HeapAlloc(GetProcessHeap(), 0, len);
60 /* remove the spaces */
61 for (i = j = 0; i <= len; ++i) {
62 if (in[i] != ' ') {
63 out[j++] = in[i];
67 /* parse the string */
68 res = UNKNOWN;
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);
76 return res;
79 /* Convert a dllmode to a registry string. */
80 static const char* mode_to_string(enum dllmode mode)
82 switch( 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)
103 switch( 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)
117 switch( 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);
136 int i;
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"));
154 char **p;
155 int sel, count = 0;
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);
169 return;
172 enable(IDC_DLLS_EDITDLL);
173 enable(IDC_DLLS_REMOVEDLL);
175 for (p = overrides; *p != NULL; p++)
177 int index;
178 char *str, *value;
179 const char *label;
180 struct dll *dll;
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);
187 strcpy(str, *p);
188 strcat(str, " (");
189 strcat(str, label);
190 strcat(str, ")");
192 dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll));
193 dll->name = *p;
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);
201 count++;
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)
225 char buffer[1024];
227 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
229 if (strlen(buffer))
230 enable(IDC_DLLS_ADDDLL)
231 else
232 disable(IDC_DLLS_ADDDLL);
235 static void set_dllmode(HWND dialog, DWORD id)
237 enum dllmode mode;
238 struct dll *dll;
239 int sel;
240 const char *str;
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 char buffer[1024];
262 ZeroMemory(buffer, sizeof(buffer));
264 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
266 SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM) "");
267 disable(IDC_DLLS_ADDDLL);
269 WINE_TRACE("Adding %s as native, builtin", buffer);
271 SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0);
272 set_reg_key(config_key, keypath("DllOverrides"), buffer, "native,builtin");
274 load_library_settings(dialog);
276 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, (WPARAM) 0, (LPARAM) buffer);
278 set_controls_from_selection(dialog);
281 static INT_PTR CALLBACK loadorder_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
283 static WORD sel;
285 switch(uMsg)
287 case WM_INITDIALOG:
288 CheckRadioButton(hwndDlg, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, lParam);
289 sel = lParam;
290 return TRUE;
292 case WM_COMMAND:
293 if(HIWORD(wParam) != BN_CLICKED) break;
294 switch (LOWORD(wParam))
296 case IDC_RAD_BUILTIN:
297 case IDC_RAD_NATIVE:
298 case IDC_RAD_BUILTIN_NATIVE:
299 case IDC_RAD_NATIVE_BUILTIN:
300 case IDC_RAD_DISABLE:
301 sel = LOWORD(wParam);
302 return TRUE;
303 case IDOK:
304 EndDialog(hwndDlg, sel);
305 return TRUE;
306 case IDCANCEL:
307 EndDialog(hwndDlg, wParam);
308 return TRUE;
311 return FALSE;
314 static void on_edit_click(HWND hwnd)
316 INT_PTR ret;
317 int index = SendDlgItemMessage(hwnd, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
318 struct dll *dll;
319 DWORD id;
321 /* if no override is selected the edit button should be disabled... */
322 assert(index != -1);
324 dll = (struct dll *) SendDlgItemMessage(hwnd, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0);
325 id = mode_to_id(dll->mode);
327 ret = DialogBoxParam(0, MAKEINTRESOURCE(IDD_LOADORDER), hwnd, loadorder_dlgproc, id);
329 if(ret != IDCANCEL)
330 set_dllmode(hwnd, ret);
333 static void on_remove_click(HWND dialog)
335 int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
336 struct dll *dll;
338 if (sel == LB_ERR) return;
340 dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
342 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0);
344 SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0);
345 set_reg_key(config_key, keypath("DllOverrides"), dll->name, NULL);
347 HeapFree(GetProcessHeap(), 0, dll->name);
348 HeapFree(GetProcessHeap(), 0, dll);
350 if (SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0)
351 SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0);
352 else
354 disable(IDC_DLLS_EDITDLL);
355 disable(IDC_DLLS_REMOVEDLL);
358 set_controls_from_selection(dialog);
361 INT_PTR CALLBACK
362 LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
364 switch (uMsg)
366 case WM_INITDIALOG:
367 init_libsheet(hDlg);
368 break;
369 case WM_SHOWWINDOW:
370 set_window_title(hDlg);
371 break;
372 case WM_NOTIFY:
373 switch (((LPNMHDR)lParam)->code) {
374 case PSN_SETACTIVE:
375 load_library_settings(hDlg);
376 break;
378 break;
379 case WM_COMMAND:
380 switch(HIWORD(wParam)) {
382 /* FIXME: when the user hits enter in the DLL combo box we should invoke the add
383 * add button, rather than the propsheet OK button. But I don't know how to do that!
386 case CBN_EDITCHANGE:
387 if(LOWORD(wParam) == IDC_DLLCOMBO)
389 on_add_combo_change(hDlg);
390 break;
393 case BN_CLICKED:
394 switch(LOWORD(wParam)) {
395 case IDC_DLLS_ADDDLL:
396 on_add_click(hDlg);
397 break;
398 case IDC_DLLS_EDITDLL:
399 on_edit_click(hDlg);
400 break;
401 case IDC_DLLS_REMOVEDLL:
402 on_remove_click(hDlg);
403 break;
405 break;
406 case LBN_SELCHANGE:
407 set_controls_from_selection(hDlg);
408 break;
410 break;
413 return 0;