- rewrite the transaction system to be based on a settings overlay,

to have a nicer API, and to actually work (always a bonus)
- change the libraries page to be based on a listbox rather than a
  treeview, clean up and shrink the code
- add accelerator keys to the libraries page, focus management
- make the window title reflect what the user is currently editing
- remove bogus root warning
- remove some unused control IDs in resource.h
- start converting the x11drv dialog to kernel_style from javaStyle
- bugfixing
This commit is contained in:
Mike Hearn 2004-09-28 03:55:16 +00:00 committed by Alexandre Julliard
parent a5ce4ee7aa
commit 0af614e77b
10 changed files with 808 additions and 845 deletions

View File

@ -84,20 +84,18 @@ STYLE WS_CHILD | WS_DISABLED
FONT 8, "MS Shell Dlg"
BEGIN
GROUPBOX "DLL Overrides",IDC_STATIC,8,4,244,240
LTEXT "Libraries can be specified individually to be either builtin or native. A DLL entry specified as ""*"" pertains to all DLLs not specified explicitly."
LTEXT "Dynamic Link Libraries can be specified individually to be either builtin (provided by Wine) or native (taken from Windows or provided by the application)."
, IDC_STATIC,15,17,228,32
CONTROL "DLL Overrides", IDC_TREE_DLLS, "SysTreeView32", WS_BORDER | WS_TABSTOP | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_HASBUTTONS, 15,50,142,187
LISTBOX IDC_DLLS_LIST,15,50,142,187,WS_BORDER | WS_TABSTOP | WS_VSCROLL
LTEXT "Load order:",IDC_STATIC,163,50,37,8
CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,163,65,75,10
CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,163,80,75,10
CONTROL "Builtin, Native",IDC_RAD_BUILTIN_NATIVE,"Button", BS_AUTORADIOBUTTON,163,95,75,10
CONTROL "Native, Builtin",IDC_RAD_NATIVE_BUILTIN,"Button", BS_AUTORADIOBUTTON,163,110,75,10
CONTROL "Disable",IDC_RAD_DISABLE,"Button", BS_AUTORADIOBUTTON,163,125,75,10
PUSHBUTTON "Add application...",IDC_DLLS_ADDAPP,163,144,82,14
PUSHBUTTON "Remove application",IDC_DLLS_REMOVEAPP, 163,164,82,14
PUSHBUTTON "Add DLL override for:",IDC_DLLS_ADDDLL, 163,184,82,14
COMBOBOX IDC_DLLLIST,163,204,82,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | CBS_SORT | CBS_LOWERCASE
PUSHBUTTON "Remove DLL override",IDC_DLLS_REMOVEDLL,163,224,82,14
CONTROL "&Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,163,65,75,10
CONTROL "&Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,163,80,75,10
CONTROL "Bui&ltin then Native",IDC_RAD_BUILTIN_NATIVE,"Button", BS_AUTORADIOBUTTON,163,95,75,10
CONTROL "Nati&ve then Builtin",IDC_RAD_NATIVE_BUILTIN,"Button", BS_AUTORADIOBUTTON,163,110,75,10
CONTROL "&Disable",IDC_RAD_DISABLE,"Button", BS_AUTORADIOBUTTON,163,125,75,10
PUSHBUTTON "&Add DLL override for:",IDC_DLLS_ADDDLL, 163,184,82,14
COMBOBOX IDC_DLLCOMBO,163,204,82,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | CBS_SORT | CBS_LOWERCASE
PUSHBUTTON "&Remove DLL override",IDC_DLLS_REMOVEDLL,163,224,82,14
END
IDD_SYSTEMCFG DIALOG DISCARDABLE 0, 0, 260, 250

View File

@ -40,23 +40,21 @@ static void update_comboboxes(HWND dialog)
char *winver, *dosver;
/* retrieve the registry values */
winver = getConfigValue(keypath("Version"), "Windows", NULL);
dosver = getConfigValue(keypath("Version"), "DOS", NULL);
winver = get(keypath("Version"), "Windows", "");
dosver = get(keypath("Version"), "DOS", "");
/* NULL winver/dosver means use automatic mode (ie the builtin dll linkage heuristics) */
/* empty winver/dosver means use automatic mode (ie the builtin dll linkage heuristics) */
WINE_TRACE("winver is %s\n", winver ? winver : "null (automatic mode)");
WINE_TRACE("dosver is %s\n", dosver ? dosver : "null (automatic mode)");
WINE_TRACE("winver is %s\n", *winver != '\0' ? winver : "null (automatic mode)");
WINE_TRACE("dosver is %s\n", *dosver != '\0' ? dosver : "null (automatic mode)");
/* normalize the version strings */
if (winver && strlen(winver))
if (*winver != '\0')
{
if ((pVer = getWinVersions ()))
{
WINE_TRACE("Windows version\n");
for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
{
WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
if (!strcasecmp (pVer->szVersion, winver))
{
SendDlgItemMessage (dialog, IDC_WINVER, CB_SETCURSEL, (WPARAM) (i + 1), 0);
@ -71,14 +69,12 @@ static void update_comboboxes(HWND dialog)
SendDlgItemMessage (dialog, IDC_WINVER, CB_SETCURSEL, 0, 0);
}
if (dosver && strlen(dosver))
if (*dosver != '\0')
{
if ((pVer = getDOSVersions ()))
{
WINE_TRACE("DOS version\n");
for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
{
WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
if (!strcasecmp (pVer->szVersion, dosver))
{
SendDlgItemMessage (dialog, IDC_DOSVER, CB_SETCURSEL,
@ -93,9 +89,9 @@ static void update_comboboxes(HWND dialog)
WINE_TRACE("setting dosver combobox to automatic/default\n");
SendDlgItemMessage (dialog, IDC_DOSVER, CB_SETCURSEL, 0, 0);
}
if (winver) free(winver);
if (dosver) free(dosver);
HeapFree(GetProcessHeap(), 0, winver);
HeapFree(GetProcessHeap(), 0, dosver);
}
void
@ -153,6 +149,7 @@ static void add_listview_item(HWND listview, char *text, void *association)
ListView_InsertItem(listview, &item);
}
/* Called when the application is initialized (cannot reinit!) */
static void init_appsheet(HWND dialog)
{
HWND listview;
@ -160,22 +157,21 @@ static void init_appsheet(HWND dialog)
int i;
DWORD size;
char appname[1024];
FILETIME ft;
WINE_TRACE("()\n");
listview = GetDlgItem(dialog, IDC_APP_LISTVIEW);
/* we use the lparam field of the item so we can alter the presentation later and not change code
* for instance, to use the tile view or to display the EXEs embedded 'display name' */
add_listview_item(listview, "Default Settings", NULL);
/* do the application specific stuff, then add the default item last */
if (RegOpenKey(configKey, "AppDefaults", &key) == ERROR_SUCCESS)
/* because this list is only populated once, it's safe to bypass the settings list here */
if (RegOpenKey(config_key, "AppDefaults", &key) == ERROR_SUCCESS)
{
i = 0;
size = sizeof(appname);
while (RegEnumKeyEx(key, i, appname, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
while (RegEnumKeyEx(key, i, appname, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
add_listview_item(listview, appname, strdup(appname));
@ -218,12 +214,13 @@ static int get_listview_selection(HWND listview)
return -1;
}
/* called when the user selects a different application */
static void on_selection_change(HWND dialog, HWND listview)
{
LVITEM item;
char *oldapp = currentApp;
WINE_TRACE("()\n");
item.iItem = get_listview_selection(listview);
@ -253,6 +250,8 @@ static void on_selection_change(HWND dialog, HWND listview)
init_comboboxes(dialog);
update_comboboxes(dialog);
set_window_title(dialog);
}
static void on_add_app_click(HWND dialog)
@ -295,14 +294,14 @@ static void on_remove_app_click(HWND dialog)
{
HWND listview = GetDlgItem(dialog, IDC_APP_LISTVIEW);
int selection = get_listview_selection(listview);
char *section = keypath("");
char *section = keypath(""); /* AppDefaults\\whatever.exe\\ */
WINE_TRACE("selection=%d, section=%s\n", selection, section);
assert( selection != 0 ); /* user cannot click this button when "default settings" is selected */
section[strlen(section)] = '\0'; /* remove last backslash */
addTransaction(section, NULL, ACTION_REMOVE, NULL);
set(section, NULL, NULL); /* delete the section */
ListView_DeleteItem(listview, selection);
SetFocus(listview);
@ -316,13 +315,16 @@ static void on_winver_change(HWND dialog)
if (selection == 0)
{
WINE_TRACE("automatic/default selected so removing current setting\n");
addTransaction(keypath("Version"), "Windows", ACTION_REMOVE, NULL);
set(keypath("Version"), "Windows", NULL);
}
else
{
WINE_TRACE("setting Version\\Windows key to value '%s'\n", ver[selection - 1].szVersion);
addTransaction(keypath("Version"), "Windows", ACTION_SET, ver[selection - 1].szVersion);
set(keypath("Version"), "Windows", ver[selection - 1].szVersion);
}
/* enable the apply button */
SendMessage(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
}
static void on_dosver_change(HWND dialog)
@ -333,13 +335,16 @@ static void on_dosver_change(HWND dialog)
if (selection == 0)
{
WINE_TRACE("automatic/default selected so removing current setting\n");
addTransaction(keypath("Version"), "DOS", ACTION_REMOVE, NULL);
set(keypath("Version"), "DOS", NULL);
}
else
{
WINE_TRACE("setting Version\\DOS key to value '%s'\n", ver[selection - 1].szVersion);
addTransaction(keypath("Version"), "DOS", ACTION_SET, ver[selection - 1].szVersion);
set(keypath("Version"), "DOS", ver[selection - 1].szVersion);
}
/* enable the apply button */
SendMessage(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
}
INT_PTR CALLBACK
@ -348,17 +353,25 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg)
{
case WM_INITDIALOG:
init_appsheet(hDlg);
break;
init_appsheet(hDlg);
break;
case WM_SHOWWINDOW:
set_window_title(hDlg);
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED:
on_selection_change(hDlg, GetDlgItem(hDlg, IDC_APP_LISTVIEW));
break;
on_selection_change(hDlg, GetDlgItem(hDlg, IDC_APP_LISTVIEW));
break;
case PSN_APPLY:
apply();
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
break;
}
break;
case WM_COMMAND:
@ -383,6 +396,7 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
break;
}
break;
}

View File

@ -55,7 +55,8 @@ void selectAudioDriver(HWND hDlg, char *drivername)
{
if (!strcmp (pAudioDrv->szDriver, drivername))
{
addTransaction("Winmm", "Drivers", ACTION_SET, pAudioDrv->szDriver);
set("Winmm", "Drivers", (char *) pAudioDrv->szDriver);
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM) hDlg, 0); /* enable apply button */
SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_SETCURSEL,
(WPARAM) i, 0);
}
@ -66,7 +67,7 @@ void selectAudioDriver(HWND hDlg, char *drivername)
void
initAudioDlg (HWND hDlg)
{
char *curAudioDriver = getConfigValue("Winmm", "Drivers", "winealsa.drv");
char *curAudioDriver = get("Winmm", "Drivers", "winealsa.drv");
const AUDIO_DRIVER *pAudioDrv = NULL;
int i;
@ -175,13 +176,18 @@ AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
}
break;
case WM_SHOWWINDOW:
set_window_title(hDlg);
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code) {
case PSN_KILLACTIVE:
SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
break;
case PSN_APPLY:
apply();
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
break;
case PSN_SETACTIVE:

View File

@ -212,14 +212,13 @@ int refreshDriveDlg (HWND dialog)
ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_HIDE);
/* disable or enable controls depending on whether we are editing global vs app specific config */
if (appSettings == EDITING_GLOBAL) {
if (currentApp) {
WINE_TRACE("enabling controls\n");
enable(IDC_LIST_DRIVES);
enable(IDC_BUTTON_ADD);
enable(IDC_BUTTON_REMOVE);
enable(IDC_BUTTON_EDIT);
enable(IDC_BUTTON_AUTODETECT);
} else {
WINE_TRACE("disabling controls\n");
disable(IDC_LIST_DRIVES);
@ -1016,6 +1015,11 @@ DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_INITDIALOG:
onDriveInitDialog();
break;
case WM_SHOWWINDOW:
set_window_title(hDlg);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_LIST_DRIVES:

View File

@ -2,6 +2,7 @@
* 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
@ -24,535 +25,324 @@
#include <commdlg.h>
#include <wine/debug.h>
#include <stdio.h>
#include <assert.h>
#include "winecfg.h"
#include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
typedef enum _DLGMODE
enum dllmode
{
DLL,
APP,
GLOBAL,
} DLGMODE;
typedef enum _DLLMODE {
BUILTIN_NATIVE,
NATIVE_BUILTIN,
BUILTIN,
NATIVE,
DISABLE,
UNKNOWN /*Special value indicating an erronous DLL override mode*/
} DLLMODE;
UNKNOWN /* Special value indicating an erronous DLL override mode */
};
static void removeSpaces(char* in, char* out)
struct dll
{
int i,j;
j = 0;
for (i = 0; i < strlen(in); i++)
{
if (in[i] != ' ')
char *name;
enum dllmode mode;
};
static enum dllmode parse_override(char *in)
{
int i, j;
char *out;
out = HeapAlloc(GetProcessHeap(), 0, strlen(in));
/* remove the spaces */
j = 0;
for (i = 0; i < strlen(in); i++)
{
out[j] = in[i];
j++;
if (in[i] != ' ')
{
out[j] = in[i];
j++;
}
}
}
out[j] = 0;
}
out[j] = 0;
/* parse the string */
if (strcmp(out, "builtin,native") == 0) return BUILTIN_NATIVE;
else if (strcmp(out, "native,builtin") == 0) return NATIVE_BUILTIN;
else if (strcmp(out, "native") == 0) return NATIVE;
else if (strcmp(out, "builtin") == 0) return BUILTIN;
else if (strcmp(out, "") == 0) return DISABLE;
static DLLMODE Str2DLLMode(char* c)
{
/*Parse a string into a DLLMode*/
char* d = HeapAlloc(GetProcessHeap(), 0, sizeof(c));
removeSpaces(c,d);
if (strcmp (d, "builtin,native") == 0) {
return BUILTIN_NATIVE;
} else
if (strcmp (d, "native,builtin") == 0) {
return NATIVE_BUILTIN;
} else
if (strcmp (d, "native") == 0){
return NATIVE;
} else
if (strcmp (d, "builtin") == 0) {
return BUILTIN;
} else
if (strcmp (d, "") == 0) {
return DISABLE;
} else
return UNKNOWN;
}
static char* DLLMode2Str(DLLMODE mode)
/* this is used to convert a dllmode to a human readable string. we should read from the translations here */
static char* mode_to_label(enum dllmode mode)
{
char* res;
switch (mode) {
case NATIVE:
res = "native";
break;
case BUILTIN:
res = "builtin";
break;
case NATIVE_BUILTIN:
res = "native, builtin";
break;
case BUILTIN_NATIVE:
res = "builtin, native";
break;
case DISABLE:
res = "";
break;
default:
res = "unknown";
}
return strdup(res);
char* res;
switch (mode) {
case NATIVE:
res = "native";
break;
case BUILTIN:
res = "builtin";
break;
case NATIVE_BUILTIN:
res = "native, builtin";
break;
case BUILTIN_NATIVE:
res = "builtin, native";
break;
case DISABLE:
res = "disabled";
break;
default:
res = "unknown/invalid";
break;
}
return res;
}
typedef struct _DLLOVERRIDE
static void set_controls_from_selection(HWND dialog)
{
char* lpcKey; /*The actual dll name*/
DLLMODE mode;
} DLLOVERRIDE, *LPDLLOVERRIDE;
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);
static LPDLLOVERRIDE CreateDLLOverride(char* lpcKey)
{
LPDLLOVERRIDE out = HeapAlloc(GetProcessHeap(),0,sizeof(DLLOVERRIDE));
out->lpcKey = strdup (lpcKey);
return out;
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);
switch (dll->mode)
{
case NATIVE:
id = IDC_RAD_NATIVE;
break;
case BUILTIN:
id = IDC_RAD_BUILTIN;
break;
case NATIVE_BUILTIN:
id = IDC_RAD_NATIVE_BUILTIN;
break;
case BUILTIN_NATIVE:
id = IDC_RAD_BUILTIN_NATIVE;
break;
case DISABLE:
id = IDC_RAD_DISABLE;
break;
case UNKNOWN:
default:
id = -1;
break;
}
CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, id);
}
static VOID FreeDLLOverride(LPDLLOVERRIDE ldo)
static void clear_settings(HWND dialog)
{
if (ldo->lpcKey)
free(ldo->lpcKey);
HeapFree(GetProcessHeap(),0,ldo);
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);
}
}
typedef struct _APPL
static void load_library_settings(HWND dialog)
{
BOOL isGlobal;
char* lpcApplication;
char* lpcSection; /*Registry section*/
} APPL, *LPAPPL;
char **overrides = enumerate_values(keypath("DllOverrides"));
char **p;
int sel, count = 0;
static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* section)
{
LPAPPL out;
out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
out->lpcApplication = strdup(application);
out->lpcSection = strdup(section);
out->isGlobal = isGlobal;
return out;
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(parse_override(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 = parse_override(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);
}
static VOID FreeAppl(LPAPPL lpAppl)
/* Called when the application is initialized (cannot reinit!) */
static void init_libsheet(HWND dialog)
{
if (lpAppl->lpcApplication)
free(lpAppl->lpcApplication); /* The strings were strdup-ped, so we use "free" */
if (lpAppl->lpcSection)
free(lpAppl->lpcSection);
HeapFree(GetProcessHeap(),0,lpAppl);
/* clear the add dll controls */
SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM) "");
disable(IDC_DLLS_ADDDLL);
}
typedef struct _ITEMTAG
{
LPAPPL lpAppl;
LPDLLOVERRIDE lpDo;
} ITEMTAG, *LPITEMTAG;
static LPITEMTAG CreateItemTag()
static void on_add_combo_change(HWND dialog)
{
LPITEMTAG out;
out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
out->lpAppl = 0;
out->lpDo = 0;
return out;
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 FreeItemTag(LPITEMTAG lpit)
static void set_dllmode(HWND dialog, DWORD id)
{
if (lpit->lpAppl)
FreeAppl(lpit->lpAppl);
if (lpit->lpDo)
FreeDLLOverride(lpit->lpDo);
HeapFree(GetProcessHeap(),0,lpit);
enum dllmode mode;
struct dll *dll;
int sel;
char *str;
#define CONVERT(s) case IDC_RAD_##s: mode = s; break;
switch (id)
{
CONVERT( BUILTIN );
CONVERT( NATIVE );
CONVERT( BUILTIN_NATIVE );
CONVERT( NATIVE_BUILTIN );
CONVERT( DISABLE );
default: assert( FALSE ); /* should not be reached */
}
#undef CONVERT
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);
switch (mode)
{
case BUILTIN: str = "builtin"; break;
case NATIVE: str = "native"; break;
case BUILTIN_NATIVE: str = "builtin, native"; break;
case NATIVE_BUILTIN: str = "native, builtin"; break;
case DISABLE: str = ""; break;
default: assert( FALSE ); /* unreachable */
}
WINE_TRACE("Setting %s to %s\n", dll->name, str);
set(keypath("DllOverrides"), dll->name, str);
load_library_settings(dialog); /* ... and refresh */
}
static VOID UpdateDLLList(HWND hDlg, char* dll)
static void on_add_click(HWND dialog)
{
/*Add if it isn't already in*/
if (SendDlgItemMessage(hDlg, IDC_DLLLIST, CB_FINDSTRING, 1, (LPARAM) dll) == CB_ERR)
SendDlgItemMessage(hDlg,IDC_DLLLIST,CB_ADDSTRING,0,(LPARAM) dll);
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);
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 LoadLibrarySettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
static void on_remove_click(HWND dialog)
{
HKEY key;
int i;
DWORD size;
DWORD readSize;
char name [255];
char read [255];
LPITEMTAG lpIt;
TVINSERTSTRUCT tis;
HTREEITEM hParent;
LPDLLOVERRIDE lpdo;
WINE_TRACE("opening %s\n", appl->lpcSection);
if (RegOpenKey (configKey, appl->lpcSection, &key) == ERROR_SUCCESS)
{
i = 0;
size = 255;
readSize = 255;
lpIt = CreateItemTag();
lpIt->lpAppl = appl;
int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
struct dll *dll;
tis.hParent = NULL;
tis.hInsertAfter = TVI_LAST;
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
tis.u.item.pszText = appl->lpcApplication;
tis.u.item.lParam = (LPARAM)lpIt;
hParent = TreeView_InsertItem(hwndTV,&tis);
tis.hParent = hParent;
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);
while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
{
WINE_TRACE("Reading value %s, namely %s\n", name, read);
lpIt = CreateItemTag();
lpdo = CreateDLLOverride(name);
lpIt->lpDo = lpdo;
tis.u.item.lParam = (LPARAM)lpIt;
tis.u.item.pszText = name;
lpdo->mode = Str2DLLMode(read);
TreeView_InsertItem(hwndTV,&tis);
UpdateDLLList(hDlg, name);
i ++; size = 255; readSize = 255;
}
RegCloseKey(key);
}
}
set(keypath("DllOverrides"), dll->name, NULL);
static VOID SetEnabledDLLControls(HWND dialog, DLGMODE dlgmode)
{
if (dlgmode == DLL) {
enable(IDC_RAD_BUILTIN);
enable(IDC_RAD_NATIVE);
enable(IDC_RAD_BUILTIN_NATIVE);
enable(IDC_RAD_NATIVE_BUILTIN);
enable(IDC_RAD_DISABLE);
enable(IDC_DLLS_REMOVEDLL);
} else {
disable(IDC_RAD_BUILTIN);
disable(IDC_RAD_NATIVE);
disable(IDC_RAD_BUILTIN_NATIVE);
disable(IDC_RAD_NATIVE_BUILTIN);
disable(IDC_RAD_DISABLE);
disable(IDC_DLLS_REMOVEDLL);
}
HeapFree(GetProcessHeap(), 0, dll->name);
HeapFree(GetProcessHeap(), 0, dll);
if (dlgmode == APP) {
enable(IDC_DLLS_REMOVEAPP);
}
else {
disable(IDC_DLLS_REMOVEAPP);
}
}
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);
static VOID OnInitLibrariesDlg(HWND hDlg)
{
HWND hwndTV;
LPAPPL lpAppl;
HKEY applKey;
int i;
DWORD size;
char appl [255];
char lpcKey [255];
FILETIME ft;
hwndTV = GetDlgItem(hDlg,IDC_TREE_DLLS);
lpAppl = CreateAppl(TRUE,"Global DLL Overrides", "DllOverrides");
LoadLibrarySettings(lpAppl, hDlg, hwndTV);
/*And now the application specific stuff:*/
if (RegOpenKey(configKey, "AppDefaults", &applKey) == ERROR_SUCCESS) {
i = 0;
size = 255;
while (RegEnumKeyEx(applKey, i, appl, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
{
sprintf(lpcKey, "AppDefaults\\%s\\DllOverrides", appl);
lpAppl = CreateAppl(FALSE,appl, lpcKey);
LoadLibrarySettings(lpAppl, hDlg, hwndTV);
i++; size = 255;
}
RegCloseKey(applKey);
}
SetEnabledDLLControls(hDlg, GLOBAL);
}
static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
{
TVITEM ti;
LPITEMTAG lpit;
int buttonId;
ti.mask = TVIF_PARAM;
ti.hItem = TreeView_GetSelection(hTV);
if (TreeView_GetItem (hTV, &ti))
{
lpit = (LPITEMTAG) ti.lParam;
if (lpit->lpDo)
{
WINE_TRACE("%s\n", lpit->lpDo->lpcKey);
buttonId = IDC_RAD_BUILTIN;
switch (lpit->lpDo->mode)
{
case NATIVE:
buttonId = IDC_RAD_NATIVE;
break;
case BUILTIN:
buttonId = IDC_RAD_BUILTIN;
break;
case NATIVE_BUILTIN:
buttonId = IDC_RAD_NATIVE_BUILTIN;
break;
case BUILTIN_NATIVE:
buttonId = IDC_RAD_BUILTIN_NATIVE;
break;
case DISABLE:
buttonId = IDC_RAD_DISABLE;
break;
case UNKNOWN:
buttonId = -1;
break;
}
CheckRadioButton(hDlg, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, buttonId);
SetEnabledDLLControls(hDlg, DLL);
} else {
if (lpit->lpAppl)
{
if (lpit->lpAppl->isGlobal == TRUE)
SetEnabledDLLControls(hDlg, GLOBAL);
else
SetEnabledDLLControls(hDlg, APP);
}
}
}
}
static VOID SetDLLMode(HWND hDlg, DLLMODE mode)
{
HWND hTV;
TVITEM ti;
LPITEMTAG lpit;
char* cMode;
TVITEM tiPar;
LPITEMTAG lpitPar;
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
ti.mask = TVIF_PARAM;
ti.hItem = TreeView_GetSelection(hTV);
if (TreeView_GetItem (hTV, &ti))
{
lpit = (LPITEMTAG) ti.lParam;
if (lpit->lpDo)
{
lpit->lpDo->mode = mode;
cMode = DLLMode2Str (mode);
/*Find parent, so we can read registry section*/
tiPar.mask = TVIF_PARAM;
tiPar.hItem = TreeView_GetParent(hTV, ti.hItem);
if (TreeView_GetItem(hTV,&tiPar))
{
lpitPar = (LPITEMTAG) tiPar.lParam;
if (lpitPar->lpAppl)
{
addTransaction(lpitPar->lpAppl->lpcSection, lpit->lpDo->lpcKey, ACTION_SET, cMode);
}
}
free(cMode);
}
}
}
static VOID OnBuiltinClick(HWND hDlg)
{
SetDLLMode(hDlg, BUILTIN);
}
static VOID OnNativeClick(HWND hDlg)
{
SetDLLMode(hDlg, NATIVE);
}
static VOID OnBuiltinNativeClick(HWND hDlg)
{
SetDLLMode(hDlg, BUILTIN_NATIVE);
}
static VOID OnNativeBuiltinClick(HWND hDlg)
{
SetDLLMode(hDlg, NATIVE_BUILTIN);
}
static VOID OnDisableClick(HWND hDlg)
{
SetDLLMode(hDlg, DISABLE);
}
static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
{
FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
}
static VOID OnAddDLLClick(HWND hDlg)
{
HWND hTV;
TVITEM ti;
LPITEMTAG lpit;
LPITEMTAG lpitNew;
TVITEM childti;
char dll [255];
BOOL doAdd;
TVINSERTSTRUCT tis;
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
ti.mask = TVIF_PARAM;
ti.hItem = TreeView_GetSelection(hTV);
if (TreeView_GetItem (hTV, &ti))
{
lpit = (LPITEMTAG) ti.lParam;
if (lpit->lpDo) { /*Is this a DLL override (that is: a subitem), then find the parent*/
ti.hItem = TreeView_GetParent(hTV, ti.hItem);
if (TreeView_GetItem(hTV,&ti)) {
lpit = (LPITEMTAG) ti.lParam;
} else return;
}
} else return;
/*Now we should have an parent item*/
if (lpit->lpAppl)
{
lpitNew = CreateItemTag();
SendDlgItemMessage(hDlg,IDC_DLLLIST,WM_GETTEXT,(WPARAM)255, (LPARAM) dll);
if (strlen(dll) > 0) {
/*Is the dll already in the list? If so, don't do it*/
doAdd = TRUE;
childti.mask = TVIF_PARAM;
if ((childti.hItem = TreeView_GetNextItem(hTV, ti.hItem, TVGN_CHILD))) {
/*Retrieved first child*/
while (TreeView_GetItem (hTV, &childti))
{
if (strcmp(((LPITEMTAG)childti.lParam)->lpDo->lpcKey,dll) == 0) {
doAdd = FALSE;
break;
}
childti.hItem = TreeView_GetNextItem(hTV, childti.hItem, TVGN_NEXT);
}
}
if (doAdd)
{
lpitNew->lpDo = CreateDLLOverride(dll);
lpitNew->lpDo->mode = NATIVE;
tis.hInsertAfter = TVI_LAST;
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
tis.u.item.pszText = dll;
tis.u.item.lParam = (LPARAM)lpitNew;
tis.hParent = ti.hItem;
TreeView_InsertItem(hTV,&tis);
UpdateDLLList(hDlg, dll);
addTransaction(lpit->lpAppl->lpcSection, dll, ACTION_SET, "native");
} else MessageBox(hDlg, "A DLL with that name is already in this list...", "", MB_OK | MB_ICONINFORMATION);
}
} else return;
}
static VOID OnRemoveDLLClick(HWND hDlg)
{
HWND hTV;
TVITEM ti;
LPITEMTAG lpit;
TVITEM tiPar;
LPITEMTAG lpitPar;
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
ti.mask = TVIF_PARAM;
ti.hItem = TreeView_GetSelection(hTV);
if (TreeView_GetItem (hTV, &ti)) {
lpit = (LPITEMTAG) ti.lParam;
if (lpit->lpDo)
{
/*Find parent for section*/
tiPar.mask = TVIF_PARAM;
tiPar.hItem = TreeView_GetParent(hTV, ti.hItem);
if (TreeView_GetItem(hTV,&tiPar))
{
lpitPar = (LPITEMTAG) tiPar.lParam;
if (lpitPar->lpAppl)
{
addTransaction(lpitPar->lpAppl->lpcSection, lpit->lpDo->lpcKey, ACTION_REMOVE, NULL);
TreeView_DeleteItem(hTV,ti.hItem);
}
}
}
}
}
static VOID OnAddApplicationClick(HWND hDlg)
{
char szFileTitle [255];
char szFile [255];
char lpcKey [255];
TVINSERTSTRUCT tis;
LPITEMTAG lpit;
OPENFILENAME ofn = { sizeof(OPENFILENAME),
0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL, 0, 0, NULL,
0, NULL, 0, NULL, NULL,
OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
ofn.lpstrFileTitle = szFileTitle;
ofn.lpstrFileTitle[0] = '\0';
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
if (GetOpenFileName(&ofn))
{
tis.hParent = NULL;
tis.hInsertAfter = TVI_LAST;
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
tis.u.item.pszText = szFileTitle;
lpit = CreateItemTag();
sprintf(lpcKey, "AppDefaults\\%s\\DllOverrides", szFileTitle);
lpit->lpAppl = CreateAppl(FALSE,szFileTitle,lpcKey);
tis.u.item.lParam = (LPARAM)lpit;
TreeView_InsertItem(GetDlgItem(hDlg,IDC_TREE_DLLS), &tis);
setConfigValue(lpcKey,NULL,NULL);
}
}
static VOID OnRemoveApplicationClick(HWND hDlg)
{
HWND hTV;
TVITEM ti;
LPITEMTAG lpit;
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
ti.mask = TVIF_PARAM;
ti.hItem = TreeView_GetSelection(hTV);
if (TreeView_GetItem (hTV, &ti)) {
lpit = (LPITEMTAG) ti.lParam;
if (lpit->lpAppl)
{
addTransaction(lpit->lpAppl->lpcSection, NULL, ACTION_REMOVE, NULL);
TreeView_DeleteItem(hTV,ti.hItem);
}
}
set_controls_from_selection(dialog);
}
INT_PTR CALLBACK
@ -561,56 +351,53 @@ LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg)
{
case WM_INITDIALOG:
OnInitLibrariesDlg(hDlg);
break;
init_libsheet(hDlg);
break;
case WM_SHOWWINDOW:
set_window_title(hDlg);
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) {
case TVN_SELCHANGED: {
switch(LOWORD(wParam)) {
case IDC_TREE_DLLS:
OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_TREE_DLLS));
break;
}
}
break;
case TVN_DELETEITEM:
OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
break;
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:
OnBuiltinClick(hDlg);
break;
case IDC_RAD_NATIVE:
OnNativeClick(hDlg);
break;
case IDC_RAD_BUILTIN_NATIVE:
OnBuiltinNativeClick(hDlg);
break;
case IDC_RAD_NATIVE_BUILTIN:
OnNativeBuiltinClick(hDlg);
break;
case IDC_RAD_DISABLE:
OnDisableClick(hDlg);
break;
case IDC_DLLS_ADDAPP:
OnAddApplicationClick(hDlg);
break;
case IDC_DLLS_REMOVEAPP:
OnRemoveApplicationClick(hDlg);
break;
set_dllmode(hDlg, LOWORD(wParam));
break;
case IDC_DLLS_ADDDLL:
OnAddDLLClick(hDlg);
break;
on_add_click(hDlg);
break;
case IDC_DLLS_REMOVEDLL:
OnRemoveDLLClick(hDlg);
break;
on_remove_click(hDlg);
break;
}
break;
case LBN_SELCHANGE:
set_controls_from_selection(hDlg);
break;
}
break;
}

View File

@ -217,10 +217,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nShow)
WINE_ERR("initialization failed, aborting\n");
ExitProcess(1);
}
/* is the user running as root? */
if(getuid() == 0)
MessageBox(NULL, "It is not advisable to run wine as root. Doing so may compromise the security of your computer. Please run wine as a normal user.", "", MB_OK);
/*
* The next 3 lines should be all that is needed

View File

@ -53,26 +53,17 @@
#define IDC_DESKTOP_BY 1026
#define IDC_XDGA 1027
#define IDC_XSHM 1028
/* dll editing */
#define IDC_RAD_BUILTIN 1029
#define IDC_RAD_NATIVE 1030
#define IDC_RAD_BUILTIN_NATIVE 1031
#define IDC_RAD_NATIVE_BUILTIN 1032
#define IDC_RAD_DISABLE 1033
#define IDC_TREE_DLLS 1034
#define IDC_DLLS_ADDAPP 8000
#define IDC_DLLS_LIST 1034
#define IDC_DLLS_ADDDLL 8001
#define IDC_DLLS_REMOVEAPP 8002
#define IDC_DLLS_REMOVEDLL 8003
#define IDC_DLLLIST 8004
#define IDC_RADIO_DEFAULT_BUILTIN 1033
#define IDC_RADIO_DEFAULT_NATIVE 1034
#define IDC_RADIO_VIRTUAL 1035
#define IDC_EDIT_VIRTUAL 1036
#define IDC_BUTTON_VIRTUAL 1037
#define IDC_RADIO_REAL 1038
#define IDC_EDIT_REAL 1039
#define IDC_BUTTON_REAL 1040
#define IDC_BUTTON_FOLDERS 1041
#define IDC_DLLCOMBO 8004
/* drive editing */
#define IDC_LIST_DRIVES 1042

View File

@ -19,23 +19,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* TODO: (in rough order of priority)
* - A mind bogglingly vast amount of stuff
*
* - Implement autodetect for drive configuration
* - Figure out whether we need the virtual vs real drive selection stuff at the top of the property page
* - Implement explicit mode vs instant-apply mode
* - DLL editing
* - Multimedia page
* - Settings migration code (from old configs)
* - Clean up resource.h, it's a bog
*
* Minor things that should be done someday:
* - Make the desktop size UI a combo box, with a Custom option, so it's more obvious what you might want to choose here
*
* BUGS:
* - x11drv page triggers key writes on entry
*
*/
#include <assert.h>
@ -44,49 +27,70 @@
#include <windows.h>
#include <winreg.h>
#include <wine/debug.h>
#include <wine/list.h>
WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
#include "winecfg.h"
HKEY configKey = NULL;
HKEY config_key = NULL;
int initialize(void) {
DWORD res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &configKey);
if (res != ERROR_SUCCESS) {
WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
return 1;
/* this is called from the WM_SHOWWINDOW handlers of each tab page.
*
* it's a nasty hack, necessary because the property sheet insists on resetting the window title
* to the title of the tab, which is utterly useless. dropping the property sheet is on the todo list.
*/
void set_window_title(HWND dialog)
{
char *newtitle;
/* update the window title */
if (currentApp)
{
char *template = "Wine Configuration for %s";
newtitle = HeapAlloc(GetProcessHeap(), 0, strlen(template) + strlen(currentApp) + 1);
sprintf(newtitle, template, currentApp);
}
return 0;
else
{
newtitle = strdupA("Wine Configuration");
}
WINE_TRACE("setting title to %s\n", newtitle);
SendMessage(GetParent(dialog), PSM_SETTITLE, 0, (LPARAM) newtitle);
HeapFree(GetProcessHeap(), 0, newtitle);
}
/*****************************************************************************
* getConfigValue: Retrieves a configuration value from the registry
/**
* getkey: Retrieves a configuration value from the registry
*
* const char *subKey : the name of the config section
* const char *valueName : the name of the config value
* const char *defaultResult : if the key isn't found, return this value instead
* char *subkey : the name of the config section
* char *name : the name of the config value
* char *default : if the key isn't found, return this value instead
*
* Returns a buffer holding the value if successful, NULL if not. Caller is responsible for freeing the result.
* Returns a buffer holding the value if successful, NULL if
* not. Caller is responsible for releasing the result.
*
*/
char *getConfigValue (const char *subkey, const char *valueName, const char *defaultResult)
static char *getkey (char *subkey, char *name, char *def)
{
char *buffer = NULL;
DWORD dataLength;
LPBYTE buffer = NULL;
DWORD len;
HKEY hSubKey = NULL;
DWORD res;
WINE_TRACE("subkey=%s, valueName=%s, defaultResult=%s\n", subkey, valueName, defaultResult);
WINE_TRACE("subkey=%s, name=%s, def=%s\n", subkey, name, def);
res = RegOpenKeyEx( configKey, subkey, 0, KEY_ALL_ACCESS, &hSubKey );
if(res != ERROR_SUCCESS) {
if( res==ERROR_FILE_NOT_FOUND )
res = RegOpenKeyEx(config_key, subkey, 0, KEY_READ, &hSubKey);
if (res != ERROR_SUCCESS)
{
if (res == ERROR_FILE_NOT_FOUND)
{
WINE_TRACE("Section key not present - using default\n");
return defaultResult ? strdup(defaultResult) : NULL;
return def ? strdupA(def) : NULL;
}
else
{
@ -95,192 +99,367 @@ char *getConfigValue (const char *subkey, const char *valueName, const char *def
goto end;
}
res = RegQueryValueExA( hSubKey, valueName, NULL, NULL, NULL, &dataLength);
if( res == ERROR_FILE_NOT_FOUND ) {
res = RegQueryValueExA(hSubKey, name, NULL, NULL, NULL, &len);
if (res == ERROR_FILE_NOT_FOUND)
{
WINE_TRACE("Value not present - using default\n");
buffer = defaultResult ? strdup(defaultResult) : NULL;
buffer = def ? strdupA(def) : NULL;
goto end;
} else if( res!=ERROR_SUCCESS ) {
WINE_ERR("Couldn't query value's length (res=%ld)\n", res );
} else if (res != ERROR_SUCCESS)
{
WINE_ERR("Couldn't query value's length (res=%ld)\n", res);
goto end;
}
buffer = malloc(dataLength);
if( buffer==NULL )
{
WINE_ERR("Couldn't allocate %lu bytes for the value\n", dataLength );
goto end;
}
RegQueryValueEx(hSubKey, valueName, NULL, NULL, (LPBYTE)buffer, &dataLength);
buffer = HeapAlloc(GetProcessHeap(), 0, len + 1);
RegQueryValueEx(hSubKey, name, NULL, NULL, buffer, &len);
WINE_TRACE("buffer=%s\n", buffer);
end:
if( hSubKey!=NULL )
RegCloseKey( hSubKey );
if (hSubKey) RegCloseKey(hSubKey);
return buffer;
}
/*****************************************************************************
* setConfigValue : Sets a configuration key in the registry. Section
* will be created if it doesn't already exist
/**
* setkey: convenience wrapper to set a key/value pair
*
* HKEY hCurrent : the registry key that the configuration is rooted at
* const char *subKey : the name of the config section
* const char *valueName : the name of the config value
* const char *value : the value to set the configuration key to
*
* Returns 0 on success, non-zero otherwise
*
* If *valueName or *value is NULL, an empty section will be created
*
* If valueName or value is NULL, an empty section will be created
*/
int setConfigValue (const char *subkey, const char *valueName, const char *value) {
int setkey(const char *subkey, const char *name, const char *value) {
DWORD res = 1;
HKEY key = NULL;
WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey, valueName, value);
WINE_TRACE("subkey=%s: name=%s, value=%s\n", subkey, name, value);
assert( subkey != NULL );
res = RegCreateKey(configKey, subkey, &key);
if (res != ERROR_SUCCESS) goto end;
if (value == NULL || valueName == NULL) goto end;
res = RegSetValueEx(key, valueName, 0, REG_SZ, value, strlen(value) + 1);
res = RegCreateKey(config_key, subkey, &key);
if (res != ERROR_SUCCESS) goto end;
if (name == NULL || value == NULL) goto end;
res = RegSetValueEx(key, name, 0, REG_SZ, value, strlen(value) + 1);
if (res != ERROR_SUCCESS) goto end;
res = 0;
end:
if (key) RegCloseKey(key);
if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", valueName, subkey, value, res);
if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", name, subkey, value, res);
return res;
}
/* returns 0 on success, an HRESULT from the registry funtions otherwise */
HRESULT doesConfigValueExist(const char *subkey, const char *valueName) {
/* removes the requested value from the registry, however, does not
* remove the section if empty. Returns S_OK (0) on success.
*/
static HRESULT remove_value(const char *subkey, const char *name)
{
HRESULT hr;
HKEY key;
WINE_TRACE("subkey=%s, valueName=%s - ", subkey, valueName);
hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
if (hr != S_OK) {
WINE_TRACE("no: subkey does not exist\n");
return hr;
}
WINE_TRACE("subkey=%s, name=%s\n", subkey, name);
hr = RegQueryValueEx(key, valueName, NULL, NULL, NULL, NULL);
if (hr != S_OK) {
WINE_TRACE("no: key does not exist\n");
return hr;
}
RegCloseKey(key);
WINE_TRACE("yes\n");
return S_OK;
}
/* removes the requested value from the registry, however, does not remove the section if empty. Returns S_OK (0) on success. */
HRESULT removeConfigValue(const char *subkey, const char *valueName) {
HRESULT hr;
HKEY key;
WINE_TRACE("subkey=%s, valueName=%s\n", subkey, valueName);
hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
hr = RegOpenKeyEx(config_key, subkey, 0, KEY_READ, &key);
if (hr != S_OK) return hr;
hr = RegDeleteValue(key, valueName);
hr = RegDeleteValue(key, name);
if (hr != ERROR_SUCCESS) return hr;
return S_OK;
}
/* removes the requested configuration section (subkey) from the registry, assuming it exists */
/* this function might be slightly pointless, but in future we may wish to treat recursion specially etc, so we'll keep it for now */
HRESULT removeConfigSection(char *section) {
HRESULT hr;
/* removes the requested subkey from the registry, assuming it exists */
static HRESULT remove_path(char *section) {
WINE_TRACE("section=%s\n", section);
return hr = RegDeleteKey(configKey, section);
return RegDeleteKey(config_key, section);
}
/* ========================================================================= */
/* Transaction management code */
struct transaction *tqhead, *tqtail;
int instantApply = 1;
/* This code exists for the following reasons:
*
* - It makes working with the registry easier
* - By storing a mini cache of the registry, we can more easily implement
* cancel/revert and apply. The 'settings list' is an overlay on top of
* the actual registry data that we can write out at will.
*
* Rather than model a tree in memory, we simply store each absolute (rooted
* at the config key) path.
*
*/
void destroyTransaction(struct transaction *trans) {
assert( trans != NULL );
WINE_TRACE("destroying %p\n", trans);
free(trans->section);
if (trans->key) free(trans->key);
if (trans->newValue) free(trans->newValue);
if (trans->next) trans->next->prev = trans->prev;
if (trans->prev) trans->prev->next = trans->next;
if (trans == tqhead) tqhead = NULL;
if (trans == tqtail) tqtail = NULL;
free(trans);
}
void addTransaction(const char *section, const char *key, enum transaction_action action, const char *newValue) {
struct transaction *trans = calloc(sizeof(struct transaction),1);
assert( section != NULL );
if (action == ACTION_SET) assert( newValue != NULL );
if (action == ACTION_SET) assert( key != NULL );
trans->section = strdup(section);
if (key) trans->key = strdup(key);
if (newValue) trans->newValue = strdup(newValue);
trans->action = action;
if (tqtail == NULL) {
tqtail = trans;
tqhead = tqtail;
} else {
tqhead->next = trans;
trans->prev = tqhead;
tqhead = trans;
}
if (instantApply) {
processTransaction(trans);
destroyTransaction(trans);
}
}
void processTransaction(struct transaction *trans) {
if (trans->action == ACTION_SET) {
WINE_TRACE("Setting %s\\%s to '%s'\n", trans->section, trans->key, trans->newValue);
setConfigValue(trans->section, trans->key, trans->newValue);
} else if (trans->action == ACTION_REMOVE) {
if (trans->key) {
WINE_TRACE("Removing %s\\%s\n", trans->section, trans->key);
removeConfigValue(trans->section, trans->key);
} else {
/* NULL key means remove that section entirely */
WINE_TRACE("Removing section %s\n", trans->section);
removeConfigSection(trans->section);
}
}
/* TODO: implement notifications here */
}
void processTransQueue(void)
struct setting
{
WINE_TRACE("\n");
while (tqtail != NULL) {
struct transaction *next = tqtail->next;
processTransaction(tqtail);
destroyTransaction(tqtail);
tqtail = next;
struct list entry;
char *path; /* path in the registry rooted at the config key */
char *name; /* name of the registry value */
char *value; /* contents of the registry value. if null, this means a deletion */
};
struct list *settings;
static void free_setting(struct setting *setting)
{
assert( setting != NULL );
WINE_TRACE("destroying %p\n", setting);
assert( setting->path && setting->name );
HeapFree(GetProcessHeap(), 0, setting->path);
HeapFree(GetProcessHeap(), 0, setting->name);
if (setting->value) HeapFree(GetProcessHeap(), 0, setting->value);
list_remove(&setting->entry);
HeapFree(GetProcessHeap(), 0, setting);
}
/**
* Returns the contents of the value at path. If not in the settings
* list, it will be fetched from the registry - failing that, the
* default will be used.
*
* If already in the list, the contents as given there will be
* returned. You are expected to HeapFree the result.
*/
char *get(char *path, char *name, char *def)
{
struct list *cursor;
struct setting *s;
char *val;
WINE_TRACE("path=%s, name=%s, def=%s\n", path, name, def);
/* check if it's in the list */
LIST_FOR_EACH( cursor, settings )
{
s = LIST_ENTRY(cursor, struct setting, entry);
if (strcasecmp(path, s->path) != 0) continue;
if (strcasecmp(name, s->name) != 0) continue;
WINE_TRACE("found %s:%s in settings list, returning %s\n", path, name, s->value);
return strdupA(s->value);
}
/* no, so get from the registry */
val = getkey(path, name, def);
WINE_TRACE("returning %s\n", val);
return val;
}
/**
* Used to set a registry key.
*
* path is rooted at the config key, ie use "Version" or
* "AppDefaults\\fooapp.exe\\Version". You can use keypath()
* to get such a string.
*
* name is the value name, it must not be null (you cannot create
* empty groups, sorry ...)
*
* value is what to set the value to, or NULL to delete it.
*
* These values will be copied when necessary.
*/
void set(char *path, char *name, char *value)
{
struct list *cursor;
struct setting *s;
assert( path != NULL );
assert( name != NULL );
WINE_TRACE("path=%s, name=%s, value=%s\n", path, name, value);
/* firstly, see if we already set this setting */
LIST_FOR_EACH( cursor, settings )
{
struct setting *s = LIST_ENTRY(cursor, struct setting, entry);
if (strcasecmp(s->path, path) != 0) continue;
if (strcasecmp(s->name, name) != 0) continue;
/* yes, we have already set it, so just replace the content and return */
if (s->value) HeapFree(GetProcessHeap(), 0, s->value);
s->value = value ? strdupA(value) : NULL;
return;
}
/* otherwise add a new setting for it */
s = HeapAlloc(GetProcessHeap(), 0, sizeof(struct setting));
s->path = strdupA(path);
s->name = strdupA(name);
s->value = value ? strdupA(value) : NULL;
list_add_tail(settings, &s->entry);
}
/**
* enumerates the value names at the given path, taking into account
* the changes in the settings list.
*
* you are expected to HeapFree each element of the array, which is null
* terminated, as well as the array itself.
*/
char **enumerate_values(char *path)
{
HKEY key;
DWORD res, i = 0;
char **values = NULL;
int valueslen = 0;
struct list *cursor;
res = RegOpenKeyEx(config_key, path, 0, KEY_READ, &key);
if (res == ERROR_SUCCESS)
{
while (TRUE)
{
char name[1024];
DWORD namesize = sizeof(name);
BOOL removed = FALSE;
/* find out the needed size, allocate a buffer, read the value */
if ((res = RegEnumValue(key, i, name, &namesize, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS)
break;
WINE_TRACE("name=%s\n", name);
/* check if this value name has been removed in the settings list */
LIST_FOR_EACH( cursor, settings )
{
struct setting *s = LIST_ENTRY(cursor, struct setting, entry);
if (strcasecmp(s->path, path) != 0) continue;
if (strcasecmp(s->name, name) != 0) continue;
if (!s->value)
{
WINE_TRACE("this key has been removed, so skipping\n");
removed = TRUE;
break;
}
}
if (removed) /* this value was deleted by the user, so don't include it */
{
HeapFree(GetProcessHeap(), 0, name);
i++;
continue;
}
/* grow the array if necessary, add buffer to it, iterate */
if (values) values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
else values = HeapAlloc(GetProcessHeap(), 0, sizeof(char*));
values[valueslen++] = strdupA(name);
WINE_TRACE("valueslen is now %d\n", valueslen);
i++;
}
}
else
{
WINE_WARN("failed opening registry key %s, res=0x%lx\n", path, res);
}
WINE_TRACE("adding settings in list but not registry\n");
/* now we have to add the values that aren't in the registry but are in the settings list */
LIST_FOR_EACH( cursor, settings )
{
struct setting *setting = LIST_ENTRY(cursor, struct setting, entry);
BOOL found = FALSE;
if (strcasecmp(setting->path, path) != 0) continue;
if (!setting->value) continue;
for (i = 0; i < valueslen; i++)
{
if (strcasecmp(setting->name, values[i]) == 0)
{
found = TRUE;
break;
}
}
if (found) continue;
WINE_TRACE("%s in list but not registry\n", setting->name);
/* otherwise it's been set by the user but isn't in the registry */
if (values) values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
else values = HeapAlloc(GetProcessHeap(), 0, sizeof(char*));
values[valueslen++] = strdupA(setting->name);
}
WINE_TRACE("adding null terminator\n");
if (values)
{
values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
values[valueslen] = NULL;
}
RegCloseKey(key);
return values;
}
/**
* returns true if the given key/value pair exists in the registry or
* has been written to.
*/
BOOL exists(char *path, char *name)
{
char *val = get(path, name, NULL);
if (val)
{
HeapFree(GetProcessHeap(), 0, val);
return TRUE;
}
return FALSE;
}
static void process_setting(struct setting *s)
{
if (s->value)
{
WINE_TRACE("Setting %s:%s to '%s'\n", s->path, s->name, s->value);
setkey(s->path, s->name, s->value);
}
else
{
/* NULL name means remove that path/section entirely */
if (s->path && s->name) remove_value(s->path, s->name);
else if (s->path && !s->name) remove_path(s->path);
}
}
void apply(void)
{
if (list_empty(settings)) return; /* we will be called for each page when the user clicks OK */
WINE_TRACE("()\n");
while (!list_empty(settings))
{
struct setting *s = (struct setting *) list_head(settings);
process_setting(s);
free_setting(s);
}
}
@ -292,19 +471,19 @@ char *currentApp = NULL; /* the app we are currently editing, or NULL if editing
char *keypath(char *section)
{
static char *result = NULL;
if (result) release(result);
if (result) HeapFree(GetProcessHeap(), 0, result);
if (currentApp)
{
result = alloc(strlen("AppDefaults\\") + strlen(currentApp) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
result = HeapAlloc(GetProcessHeap(), 0, strlen("AppDefaults\\") + strlen(currentApp) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
sprintf(result, "AppDefaults\\%s\\%s", currentApp, section);
}
else
{
result = strdupA(section);
}
return result;
}
@ -326,3 +505,18 @@ void PRINTERROR(void)
(LPSTR)&msg, 0, NULL);
WINE_TRACE("error: '%s'\n", msg);
}
int initialize(void) {
DWORD res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &config_key);
if (res != ERROR_SUCCESS) {
WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
return 1;
}
/* we could probably just have the list as static data */
settings = HeapAlloc(GetProcessHeap(), 0, sizeof(struct list));
list_init(settings);
return 0;
}

View File

@ -45,31 +45,22 @@
}
#define WRITEME(owner) MessageBox(owner, "Write me!", "", MB_OK | MB_ICONEXCLAMATION);
/* Transaction management */
enum transaction_action {
ACTION_SET,
ACTION_REMOVE
};
struct transaction {
char *section;
char *key;
char *newValue;
enum transaction_action action;
struct transaction *next, *prev;
};
extern struct transaction *tqhead, *tqtail;
extern int instantApply; /* non-zero means apply all changes instantly */
#define EDITING_GLOBAL 0
#define EDITING_APP 1
extern int appSettings; /* non-zero means we are editing appdefault settings */
extern char *currentApp; /* NULL means editing global settings */
/* Use get and set to alter registry settings. The changes made through set
won't be committed to the registry until process_all_settings is called,
however get will still return accurate information.
You are expected to release the result of get. The parameters to set will
be copied, so release them too when necessary.
*/
void set(char *path, char *name, char *value);
char *get(char *path, char *name, char *def);
BOOL exists(char *path, char *name);
void apply(void);
char **enumerate_values(char *path);
/* returns a string of the form "AppDefaults\\appname.exe\\section", or just "section" if
* the user is editing the global settings.
*
@ -77,31 +68,11 @@ extern char *currentApp; /* NULL means editing global settings */
*/
char *keypath(char *section);
/* Commits a transaction to the registry */
void processTransaction(struct transaction *trans);
/* Processes every pending transaction in the queue, removing them as it works from head to tail */
void processTransQueue();
/* Adds a transaction to the head of the queue. If we're using instant apply, this calls processTransaction
* action can be either:
* ACTION_SET -> this transaction will change a registry key, newValue is the replacement value
* ACTION_REMOVE -> this transaction will remove a registry key. In this case, newValue is ignored.
*/
void addTransaction(const char *section, const char *key, enum transaction_action action, const char *newValue);
/* frees the transaction structure, all fields, and removes it from the queue if in it */
void destroyTransaction(struct transaction *trans);
/* Initializes the transaction system */
int initialize(void);
extern HKEY configKey;
extern HKEY config_key;
/* don't use these directly! */
int setConfigValue (const char *subkey, const char *valueName, const char *value);
char *getConfigValue (const char *subkey, const char *valueName, const char *defaultResult);
HRESULT doesConfigValueExist (const char *subkey, const char *valueName);
HRESULT removeConfigValue (const char *subkey, const char *valueName);
void set_window_title(HWND dialog);
/* Graphics */
@ -125,14 +96,12 @@ INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
char *getDialogItemText(HWND hDlg, WORD controlID);
#define disable(id) EnableWindow(GetDlgItem(dialog, id), 0);
#define enable(id) EnableWindow(GetDlgItem(dialog, id), 1);
#define alloc(size) HeapAlloc(GetProcessHeap(), 0, size);
#define release(ptr) HeapFree(GetProcessHeap(), 0, ptr);
void PRINTERROR(void); /* WINE_TRACE() the plaintext error message from GetLastError() */
/* returns a string in the win32 heap */
static inline char *strdupA(char *s)
{
char *r = alloc(strlen(s));
char *r = HeapAlloc(GetProcessHeap(), 0, strlen(s));
return strcpy(r, s);
}

View File

@ -36,19 +36,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
#define RES_MAXLEN 5 /* the maximum number of characters in a screen dimension. 5 digits should be plenty, what kind of crazy person runs their screen >10,000 pixels across? */
int updatingUI;
int updating_ui;
int appSettings = EDITING_GLOBAL; /* start by editing global */
void updateGUIForDesktopMode(HWND dialog) {
void update_gui_for_desktop_mode(HWND dialog) {
WINE_TRACE("\n");
updatingUI = TRUE;
updating_ui = TRUE;
/* do we have desktop mode enabled? */
if (doesConfigValueExist(keypath("x11drv"), "Desktop") == S_OK) {
if (exists(keypath("x11drv"), "Desktop"))
{
CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_CHECKED);
/* enable the controls */
enable(IDC_DESKTOP_WIDTH);
enable(IDC_DESKTOP_HEIGHT);
enable(IDC_DESKTOP_SIZE);
@ -57,9 +56,10 @@ void updateGUIForDesktopMode(HWND dialog) {
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "640");
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "480");
}
else {
else
{
CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_UNCHECKED);
/* disable the controls */
disable(IDC_DESKTOP_WIDTH);
disable(IDC_DESKTOP_HEIGHT);
disable(IDC_DESKTOP_SIZE);
@ -69,22 +69,22 @@ void updateGUIForDesktopMode(HWND dialog) {
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "");
}
updatingUI = FALSE;
updating_ui = FALSE;
}
/* pokes the win32 api to setup the dialog from the config struct */
void initGraphDlg (HWND hDlg)
{
static const char default_desktop[] = "640x480";
static char *default_desktop = "640x480";
char *buf;
char *bufindex;
updateGUIForDesktopMode(hDlg);
update_gui_for_desktop_mode(hDlg);
updatingUI = TRUE;
updating_ui = TRUE;
/* desktop size */
buf = getConfigValue(keypath("x11drv"), "Desktop", default_desktop);
buf = get(keypath("x11drv"), "Desktop", default_desktop);
bufindex = strchr(buf, 'x');
if(!bufindex) /* handle invalid "Desktop" values */
{
@ -96,7 +96,7 @@ void initGraphDlg (HWND hDlg)
bufindex++;
SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_WIDTH), buf);
SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_HEIGHT), bufindex);
free(buf);
HeapFree(GetProcessHeap(), 0, buf);
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "8 bit");
@ -104,7 +104,7 @@ void initGraphDlg (HWND hDlg)
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "24 bit");
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "32 bit"); /* is this valid? */
buf = getConfigValue(keypath("x11drv"), "ScreenDepth", "24");
buf = get(keypath("x11drv"), "ScreenDepth", "24");
if (strcmp(buf, "8") == 0)
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 0, 0);
else if (strcmp(buf, "16") == 0)
@ -115,36 +115,34 @@ void initGraphDlg (HWND hDlg)
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 3, 0);
else
WINE_ERR("Invalid screen depth read from registry (%s)\n", buf);
free(buf);
HeapFree(GetProcessHeap(), 0, buf);
SendDlgItemMessage(hDlg, IDC_DESKTOP_WIDTH, EM_LIMITTEXT, RES_MAXLEN, 0);
SendDlgItemMessage(hDlg, IDC_DESKTOP_HEIGHT, EM_LIMITTEXT, RES_MAXLEN, 0);
buf = getConfigValue(keypath("x11drv"), "DXGrab", "Y");
buf = get(keypath("x11drv"), "DXGrab", "Y");
if (IS_OPTION_TRUE(*buf))
CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_CHECKED);
else
CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_UNCHECKED);
free(buf);
HeapFree(GetProcessHeap(), 0, buf);
buf = getConfigValue(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
buf = get(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
if (IS_OPTION_TRUE(*buf))
CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_CHECKED);
else
CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_UNCHECKED);
free(buf);
HeapFree(GetProcessHeap(), 0, buf);
updatingUI = FALSE;
updating_ui = FALSE;
}
void setFromDesktopSizeEdits(HWND hDlg) {
char *width = malloc(RES_MAXLEN+1);
char *height = malloc(RES_MAXLEN+1);
char *newStr = malloc((RES_MAXLEN*2) + 2);
char *width = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
char *height = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
char *new = HeapAlloc(GetProcessHeap(), 0, (RES_MAXLEN*2) + 2);
if (updatingUI) return;
if (updating_ui) goto end;
WINE_TRACE("\n");
@ -154,12 +152,13 @@ void setFromDesktopSizeEdits(HWND hDlg) {
if (strcmp(width, "") == 0) strcpy(width, "640");
if (strcmp(height, "") == 0) strcpy(height, "480");
sprintf(newStr, "%sx%s", width, height);
addTransaction(keypath("x11drv"), "Desktop", ACTION_SET, newStr);
free(width);
free(height);
free(newStr);
sprintf(new, "%sx%s", width, height);
set(keypath("x11drv"), "Desktop", new);
end:
HeapFree(GetProcessHeap(), 0, width);
HeapFree(GetProcessHeap(), 0, height);
HeapFree(GetProcessHeap(), 0, new);
}
void onEnableDesktopClicked(HWND hDlg) {
@ -169,9 +168,9 @@ void onEnableDesktopClicked(HWND hDlg) {
setFromDesktopSizeEdits(hDlg);
} else {
/* it was just checked, so remove the config values */
addTransaction(keypath("x11drv"), "Desktop", ACTION_REMOVE, NULL);
set(keypath("x11drv"), "Desktop", NULL);
}
updateGUIForDesktopMode(hDlg);
update_gui_for_desktop_mode(hDlg);
}
void onScreenDepthChanged(HWND hDlg) {
@ -179,26 +178,26 @@ void onScreenDepthChanged(HWND hDlg) {
char *spaceIndex = strchr(newvalue, ' ');
WINE_TRACE("newvalue=%s\n", newvalue);
if (updatingUI) return;
if (updating_ui) return;
*spaceIndex = '\0';
addTransaction(keypath("x11drv"), "ScreenDepth", ACTION_SET, newvalue);
set(keypath("x11drv"), "ScreenDepth", newvalue);
free(newvalue);
}
void onDXMouseGrabClicked(HWND hDlg) {
if (IsDlgButtonChecked(hDlg, IDC_DX_MOUSE_GRAB) == BST_CHECKED)
addTransaction(keypath("x11drv"), "DXGrab", ACTION_SET, "Y");
set(keypath("x11drv"), "DXGrab", "Y");
else
addTransaction(keypath("x11drv"), "DXGrab", ACTION_SET, "N");
set(keypath("x11drv"), "DXGrab", "N");
}
void onDoubleBufferClicked(HWND hDlg) {
if (IsDlgButtonChecked(hDlg, IDC_DOUBLE_BUFFER) == BST_CHECKED)
addTransaction(keypath("x11drv"), "DesktopDoubleBuffered", ACTION_SET, "Y");
set(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
else
addTransaction(keypath("x11drv"), "DesktopDoubleBuffered", ACTION_SET, "N");
set(keypath("x11drv"), "DesktopDoubleBuffered", "N");
}
INT_PTR CALLBACK
@ -207,17 +206,21 @@ GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg) {
case WM_INITDIALOG:
break;
case WM_SHOWWINDOW:
set_window_title(hDlg);
break;
case WM_COMMAND:
switch(HIWORD(wParam)) {
case EN_CHANGE: {
SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updatingUI )
if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updating_ui )
setFromDesktopSizeEdits(hDlg);
break;
}
case BN_CLICKED: {
if (updatingUI) break;
if (updating_ui) break;
switch(LOWORD(wParam)) {
case IDC_ENABLE_DESKTOP: onEnableDesktopClicked(hDlg); break;
case IDC_DX_MOUSE_GRAB: onDXMouseGrabClicked(hDlg); break;
@ -243,6 +246,7 @@ GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
}
case PSN_APPLY: {
apply();
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
break;
}