wine/programs/winecfg/libraries.c
Crestez Leonard 3e55df3925 Fix add application (memory error).
Fix apply button lighting up in audio tab.
Fix video tab(crash when checking desktop, apply button not lighting
up.
Deal with invalid Desktop registry value in video tab.
Fix apply button in libraries tab.
Cleaned up and documented all the conversions in the libraries tab.
2005-01-14 19:48:41 +00:00

377 lines
10 KiB
C

/*
* 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)
{
if (mode == NATIVE) return "native";
if (mode == BUILTIN) return "builtin";
if (mode == NATIVE_BUILTIN) return "native,builtin";
if (mode == BUILTIN_NATIVE) return "builtin,native";
if (mode == DISABLE) return "";
assert(FALSE);
}
/* 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)
{
if (id == IDC_RAD_BUILTIN) return BUILTIN;
if (id == IDC_RAD_NATIVE) return NATIVE;
if (id == IDC_RAD_NATIVE_BUILTIN) return NATIVE_BUILTIN;
if (id == IDC_RAD_BUILTIN_NATIVE) return BUILTIN_NATIVE;
if (id == IDC_RAD_DISABLE) return DISABLE;
assert( FALSE ); /* should not be reached */
}
/* Convert a dllmode to a control id (IDC_ constant) */
static DWORD mode_to_id(enum dllmode mode)
{
if (mode == BUILTIN) return IDC_RAD_BUILTIN;
if (mode == NATIVE) return IDC_RAD_NATIVE;
if (mode == NATIVE_BUILTIN) return IDC_RAD_NATIVE_BUILTIN;
if (mode == BUILTIN_NATIVE) return IDC_RAD_BUILTIN_NATIVE;
if (mode == DISABLE) return IDC_RAD_DISABLE;
assert( FALSE ); /* 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;
}