| /* | |
| * WineCfg libraries tabsheet | |
| * | |
| * Copyright 2004 Robert van Herk | |
| * Copyright 2004 Mike Hearn | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| * | |
| */ | |
| #define NONAMELESSUNION | |
| #include <windows.h> | |
| #include <commdlg.h> | |
| #include <wine/debug.h> | |
| #include <stdio.h> | |
| #include <assert.h> | |
| #include "winecfg.h" | |
| #include "resource.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(winecfg); | |
| enum dllmode | |
| { | |
| BUILTIN_NATIVE, | |
| NATIVE_BUILTIN, | |
| BUILTIN, | |
| NATIVE, | |
| DISABLE, | |
| UNKNOWN /* Special value indicating an erronous DLL override mode */ | |
| }; | |
| struct dll | |
| { | |
| char *name; | |
| enum dllmode mode; | |
| }; | |
| /* Convert a registry string to a dllmode */ | |
| static enum dllmode string_to_mode(char *in) | |
| { | |
| int i, j, len; | |
| char *out; | |
| enum dllmode res; | |
| len = strlen(in); | |
| out = HeapAlloc(GetProcessHeap(), 0, len); | |
| /* remove the spaces */ | |
| for (i = j = 0; i <= len; ++i) { | |
| if (in[i] != ' ') { | |
| out[j++] = in[i]; | |
| } | |
| } | |
| /* parse the string */ | |
| res = UNKNOWN; | |
| if (strcmp(out, "builtin,native") == 0) res = BUILTIN_NATIVE; | |
| if (strcmp(out, "native,builtin") == 0) res = NATIVE_BUILTIN; | |
| if (strcmp(out, "builtin") == 0) res = BUILTIN; | |
| if (strcmp(out, "native") == 0) res = NATIVE; | |
| if (strcmp(out, "") == 0) res = DISABLE; | |
| HeapFree(GetProcessHeap(), 0, out); | |
| return res; | |
| } | |
| /* Convert a dllmode to a registry string. */ | |
| static char* mode_to_string(enum dllmode mode) | |
| { | |
| switch( mode ) | |
| { | |
| case NATIVE: return "native"; | |
| case BUILTIN: return "builtin"; | |
| case NATIVE_BUILTIN: return "native,builtin"; | |
| case BUILTIN_NATIVE: return "builtin,native"; | |
| case DISABLE: return ""; | |
| default: assert(FALSE); return ""; | |
| } | |
| } | |
| /* Convert a dllmode to a pretty string for display. TODO: use translations. */ | |
| static char* mode_to_label(enum dllmode mode) | |
| { | |
| WINE_FIXME("translate me"); | |
| return mode_to_string(mode); | |
| } | |
| /* Convert a control id (IDC_ constant) to a dllmode */ | |
| static enum dllmode id_to_mode(DWORD id) | |
| { | |
| switch( id ) | |
| { | |
| case IDC_RAD_BUILTIN: return BUILTIN; | |
| case IDC_RAD_NATIVE: return NATIVE; | |
| case IDC_RAD_NATIVE_BUILTIN: return NATIVE_BUILTIN; | |
| case IDC_RAD_BUILTIN_NATIVE: return BUILTIN_NATIVE; | |
| case IDC_RAD_DISABLE: return DISABLE; | |
| default: assert( FALSE ); return 0; /* should not be reached */ | |
| } | |
| } | |
| /* Convert a dllmode to a control id (IDC_ constant) */ | |
| static DWORD mode_to_id(enum dllmode mode) | |
| { | |
| switch( mode ) | |
| { | |
| case BUILTIN: return IDC_RAD_BUILTIN; | |
| case NATIVE: return IDC_RAD_NATIVE; | |
| case NATIVE_BUILTIN: return IDC_RAD_NATIVE_BUILTIN; | |
| case BUILTIN_NATIVE: return IDC_RAD_BUILTIN_NATIVE; | |
| case DISABLE: return IDC_RAD_DISABLE; | |
| default: assert( FALSE ); return 0; /* should not be reached */ | |
| } | |
| } | |
| static void set_controls_from_selection(HWND dialog) | |
| { | |
| int index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0); | |
| struct dll *dll; | |
| DWORD id; | |
| int i; | |
| if (index == -1) /* no selection */ | |
| { | |
| for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++) | |
| disable(i); | |
| CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, -1); | |
| return; | |
| } | |
| /* enable the controls */ | |
| for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++) | |
| enable(i); | |
| dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0); | |
| id = mode_to_id(dll->mode); | |
| CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, id); | |
| } | |
| static void clear_settings(HWND dialog) | |
| { | |
| int count = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0); | |
| int i; | |
| WINE_TRACE("count=%d\n", count); | |
| for (i = 0; i < count; i++) | |
| { | |
| struct dll *dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, 0, 0); | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, 0, 0); | |
| HeapFree(GetProcessHeap(), 0, dll->name); | |
| HeapFree(GetProcessHeap(), 0, dll); | |
| } | |
| } | |
| static void load_library_settings(HWND dialog) | |
| { | |
| char **overrides = enumerate_values(keypath("DllOverrides")); | |
| char **p; | |
| int sel, count = 0; | |
| sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0); | |
| WINE_TRACE("sel=%d\n", sel); | |
| clear_settings(dialog); | |
| if (!overrides || *overrides == NULL) | |
| { | |
| set_controls_from_selection(dialog); | |
| disable(IDC_DLLS_REMOVEDLL); | |
| HeapFree(GetProcessHeap(), 0, overrides); | |
| return; | |
| } | |
| enable(IDC_DLLS_REMOVEDLL); | |
| for (p = overrides; *p != NULL; p++) | |
| { | |
| int index; | |
| char *str, *value, *label; | |
| struct dll *dll; | |
| value = get(keypath("DllOverrides"), *p, NULL); | |
| label = mode_to_label(string_to_mode(value)); | |
| str = HeapAlloc(GetProcessHeap(), 0, strlen(*p) + 2 + strlen(label) + 2); | |
| strcpy(str, *p); | |
| strcat(str, " ("); | |
| strcat(str, label); | |
| strcat(str, ")"); | |
| dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll)); | |
| dll->name = *p; | |
| dll->mode = string_to_mode(value); | |
| index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_ADDSTRING, (WPARAM) -1, (LPARAM) str); | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETITEMDATA, index, (LPARAM) dll); | |
| HeapFree(GetProcessHeap(), 0, str); | |
| count++; | |
| } | |
| HeapFree(GetProcessHeap(), 0, overrides); | |
| /* restore the previous selection, if possible */ | |
| if (sel >= count - 1) sel = count - 1; | |
| else if (sel == -1) sel = 0; | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, sel, 0); | |
| set_controls_from_selection(dialog); | |
| } | |
| /* Called when the application is initialized (cannot reinit!) */ | |
| static void init_libsheet(HWND dialog) | |
| { | |
| /* clear the add dll controls */ | |
| SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM) ""); | |
| disable(IDC_DLLS_ADDDLL); | |
| } | |
| static void on_add_combo_change(HWND dialog) | |
| { | |
| char buffer[1024]; | |
| SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer); | |
| if (strlen(buffer)) | |
| enable(IDC_DLLS_ADDDLL) | |
| else | |
| disable(IDC_DLLS_ADDDLL); | |
| } | |
| static void set_dllmode(HWND dialog, DWORD id) | |
| { | |
| enum dllmode mode; | |
| struct dll *dll; | |
| int sel; | |
| char *str; | |
| mode = id_to_mode(id); | |
| sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0); | |
| if (sel == -1) return; | |
| dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0); | |
| str = mode_to_string(mode); | |
| WINE_TRACE("Setting %s to %s\n", dll->name, str); | |
| SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0); | |
| set(keypath("DllOverrides"), dll->name, str); | |
| load_library_settings(dialog); /* ... and refresh */ | |
| } | |
| static void on_add_click(HWND dialog) | |
| { | |
| char buffer[1024]; | |
| ZeroMemory(buffer, sizeof(buffer)); | |
| SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer); | |
| SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM) ""); | |
| disable(IDC_DLLS_ADDDLL); | |
| WINE_TRACE("Adding %s as native, builtin", buffer); | |
| SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0); | |
| set(keypath("DllOverrides"), buffer, "native,builtin"); | |
| load_library_settings(dialog); | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, (WPARAM) 0, (LPARAM) buffer); | |
| set_controls_from_selection(dialog); | |
| } | |
| static void on_remove_click(HWND dialog) | |
| { | |
| int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0); | |
| struct dll *dll; | |
| if (sel == LB_ERR) return; | |
| dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0); | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0); | |
| SendMessage(GetParent(dialog), PSM_CHANGED, 0, 0); | |
| set(keypath("DllOverrides"), dll->name, NULL); | |
| HeapFree(GetProcessHeap(), 0, dll->name); | |
| HeapFree(GetProcessHeap(), 0, dll); | |
| if (SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0) | |
| SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0); | |
| else | |
| disable(IDC_DLLS_REMOVEDLL); | |
| set_controls_from_selection(dialog); | |
| } | |
| INT_PTR CALLBACK | |
| LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| switch (uMsg) | |
| { | |
| case WM_INITDIALOG: | |
| init_libsheet(hDlg); | |
| break; | |
| case WM_SHOWWINDOW: | |
| set_window_title(hDlg); | |
| break; | |
| case WM_NOTIFY: | |
| switch (((LPNMHDR)lParam)->code) { | |
| case PSN_SETACTIVE: | |
| load_library_settings(hDlg); | |
| break; | |
| } | |
| break; | |
| case WM_COMMAND: | |
| switch(HIWORD(wParam)) { | |
| /* FIXME: when the user hits enter in the DLL combo box we should invoke the add | |
| * add button, rather than the propsheet OK button. But I don't know how to do that! | |
| */ | |
| case CBN_EDITCHANGE: | |
| if(LOWORD(wParam) == IDC_DLLCOMBO) | |
| { | |
| on_add_combo_change(hDlg); | |
| break; | |
| } | |
| case BN_CLICKED: | |
| switch(LOWORD(wParam)) { | |
| case IDC_RAD_BUILTIN: | |
| case IDC_RAD_NATIVE: | |
| case IDC_RAD_BUILTIN_NATIVE: | |
| case IDC_RAD_NATIVE_BUILTIN: | |
| case IDC_RAD_DISABLE: | |
| set_dllmode(hDlg, LOWORD(wParam)); | |
| break; | |
| case IDC_DLLS_ADDDLL: | |
| on_add_click(hDlg); | |
| break; | |
| case IDC_DLLS_REMOVEDLL: | |
| on_remove_click(hDlg); | |
| break; | |
| } | |
| break; | |
| case LBN_SELCHANGE: | |
| set_controls_from_selection(hDlg); | |
| break; | |
| } | |
| break; | |
| } | |
| return 0; | |
| } |