mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 08:49:15 +00:00
517 lines
13 KiB
C
517 lines
13 KiB
C
/*
|
|
* WineCfg app settings tabsheet
|
|
*
|
|
* Copyright 2004 Robert van Herk
|
|
* Chris Morgan
|
|
*
|
|
* 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 "winecfg.h"
|
|
#include "resource.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
|
|
|
|
typedef struct _APPL
|
|
{
|
|
BOOL isGlobal;
|
|
char* lpcApplication;
|
|
char* lpcVersionSection;
|
|
} APPL, *LPAPPL;
|
|
|
|
static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* version_section)
|
|
{
|
|
LPAPPL out;
|
|
WINE_TRACE("application: '%s', version_section: '%s'\n", application, version_section);
|
|
out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
|
|
out->lpcApplication = strdup(application);
|
|
out->lpcVersionSection = strdup(version_section);
|
|
out->isGlobal = isGlobal;
|
|
return out;
|
|
}
|
|
|
|
static VOID FreeAppl(LPAPPL lpAppl)
|
|
{
|
|
/* The strings were strdup-ped, so we use "free" */
|
|
if (lpAppl->lpcApplication) free(lpAppl->lpcApplication);
|
|
if (lpAppl->lpcVersionSection) free(lpAppl->lpcVersionSection);
|
|
HeapFree(GetProcessHeap(),0,lpAppl);
|
|
}
|
|
|
|
/* section can be "Version" */
|
|
/* key can be "Windows"/"Dos" */
|
|
/* value can be appropriate values for the above keys */
|
|
typedef struct _APPSETTING
|
|
{
|
|
char* section;
|
|
char* lpcKey;
|
|
char* value;
|
|
} APPSETTING, *LPAPPSETTING;
|
|
|
|
static LPAPPSETTING CreateAppSetting(char* lpcKey, char* value)
|
|
{
|
|
LPAPPSETTING out = HeapAlloc(GetProcessHeap(),0,sizeof(APPSETTING));
|
|
out->lpcKey = strdup (lpcKey);
|
|
out->value = strdup(value);
|
|
return out;
|
|
}
|
|
|
|
static VOID FreeAppSetting(LPAPPSETTING las)
|
|
{
|
|
if (las->lpcKey) free(las->lpcKey);
|
|
if (las->value) free(las->value);
|
|
HeapFree(GetProcessHeap(),0,las);
|
|
}
|
|
|
|
typedef struct _ITEMTAG
|
|
{
|
|
LPAPPL lpAppl;
|
|
LPAPPSETTING lpSetting;
|
|
} ITEMTAG, *LPITEMTAG;
|
|
|
|
static LPITEMTAG CreateItemTag()
|
|
{
|
|
LPITEMTAG out;
|
|
out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
|
|
out->lpAppl = 0;
|
|
out->lpSetting = 0;
|
|
return out;
|
|
}
|
|
|
|
static VOID FreeItemTag(LPITEMTAG lpit)
|
|
{
|
|
/* if child, only free the lpSetting, the lpAppl will be freed when we free the parents item tag */
|
|
if (lpit->lpSetting)
|
|
{
|
|
FreeAppSetting(lpit->lpSetting);
|
|
} else
|
|
{
|
|
if (lpit->lpAppl)
|
|
FreeAppl(lpit->lpAppl);
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, lpit);
|
|
}
|
|
|
|
static VOID LoadAppSettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
|
|
{
|
|
HKEY key;
|
|
int i;
|
|
DWORD size;
|
|
DWORD readSize;
|
|
char name [255];
|
|
char read [255];
|
|
char *description;
|
|
LPITEMTAG lpIt;
|
|
TVINSERTSTRUCT tis;
|
|
HTREEITEM hParent;
|
|
LPAPPSETTING lpas;
|
|
|
|
WINE_TRACE("opening '%s'\n", appl->lpcVersionSection);
|
|
if (RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
|
|
{
|
|
i = 0;
|
|
size = 255;
|
|
readSize = 255;
|
|
|
|
lpIt = CreateItemTag();
|
|
lpIt->lpAppl = appl;
|
|
|
|
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;
|
|
|
|
/* insert version entries */
|
|
if(RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
|
|
{
|
|
while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
|
|
{
|
|
char itemtext[128];
|
|
|
|
WINE_TRACE("Reading value %s, namely %s\n", name, read);
|
|
|
|
lpIt = CreateItemTag();
|
|
lpas = CreateAppSetting(name, read);
|
|
lpIt->lpSetting = lpas;
|
|
lpIt->lpAppl = appl;
|
|
tis.u.item.lParam = (LPARAM)lpIt;
|
|
|
|
/* convert the value for 'dosver or winver' to human readable form */
|
|
description = getDescriptionFromVersion(getWinVersions(), read);
|
|
if(!description)
|
|
{
|
|
description = getDescriptionFromVersion(getDOSVersions(), read);
|
|
if(!description)
|
|
description = "Not found";
|
|
}
|
|
|
|
sprintf(itemtext, "%s - %s", name, description);
|
|
tis.u.item.pszText = itemtext;
|
|
|
|
TreeView_InsertItem(hwndTV,&tis);
|
|
i++; size = 255; readSize = 255;
|
|
}
|
|
RegCloseKey(key);
|
|
} else
|
|
{
|
|
WINE_TRACE("no version section found\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID SetEnabledAppControls(HWND dialog)
|
|
{
|
|
}
|
|
|
|
static VOID UpdateComboboxes(HWND hDlg, LPAPPL lpAppl)
|
|
{
|
|
int i;
|
|
const VERSION_DESC *pVer = NULL;
|
|
|
|
/* retrieve the registry values for this application */
|
|
char *curWinVer = getConfigValue(lpAppl->lpcVersionSection, "Windows", "");
|
|
char *curDOSVer = getConfigValue(lpAppl->lpcVersionSection, "DOS", "");
|
|
|
|
if(curWinVer) WINE_TRACE("curWinVer is '%s'\n", curWinVer);
|
|
else WINE_TRACE("curWinVer is null\n");
|
|
if(curDOSVer) WINE_TRACE("curDOSVer is '%s'\n", curDOSVer);
|
|
else WINE_TRACE("curDOSVer is null\n");
|
|
|
|
/* normalize the version strings */
|
|
if(strlen(curWinVer) != 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, curWinVer))
|
|
{
|
|
SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
|
|
(WPARAM) i, 0);
|
|
WINE_TRACE("match with %s\n", pVer->szVersion);
|
|
}
|
|
}
|
|
}
|
|
} else /* clear selection */
|
|
{
|
|
WINE_TRACE("setting winver to nothing\n");
|
|
SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
|
|
-1, 0);
|
|
}
|
|
|
|
if(strlen(curDOSVer) != 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, curDOSVer))
|
|
{
|
|
SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
|
|
(WPARAM) i, 0);
|
|
WINE_TRACE("match with %s\n", pVer->szVersion);
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
{
|
|
WINE_TRACE("setting dosver to nothing\n");
|
|
SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
|
|
-1, 0);
|
|
}
|
|
|
|
if(curWinVer) free(curWinVer);
|
|
if(curDOSVer) free(curDOSVer);
|
|
}
|
|
|
|
void
|
|
initAppDlgComboboxes (HWND hDlg)
|
|
{
|
|
int i;
|
|
const VERSION_DESC *pVer = NULL;
|
|
|
|
if ((pVer = getWinVersions ()))
|
|
{
|
|
for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
|
|
{
|
|
SendDlgItemMessage (hDlg, IDC_WINVER, CB_ADDSTRING,
|
|
0, (LPARAM) pVer->szDescription);
|
|
}
|
|
}
|
|
if ((pVer = getDOSVersions ()))
|
|
{
|
|
for (i = 0; *pVer->szVersion || *pVer->szDescription ; i++, pVer++)
|
|
{
|
|
SendDlgItemMessage (hDlg, IDC_DOSVER, CB_ADDSTRING,
|
|
0, (LPARAM) pVer->szDescription);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static VOID OnInitAppDlg(HWND hDlg)
|
|
{
|
|
HWND hwndTV;
|
|
LPAPPL lpAppl;
|
|
HKEY applKey;
|
|
int i;
|
|
DWORD size;
|
|
char appl [255];
|
|
char lpcVersionKey [255];
|
|
FILETIME ft;
|
|
|
|
hwndTV = GetDlgItem(hDlg,IDC_APP_TREEVIEW);
|
|
lpAppl = CreateAppl(TRUE, "Global Settings", "Version");
|
|
LoadAppSettings(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(lpcVersionKey, "AppDefaults\\%s\\Version", appl);
|
|
lpAppl = CreateAppl(FALSE, appl, lpcVersionKey);
|
|
LoadAppSettings(lpAppl, hDlg, hwndTV);
|
|
i++; size = 255;
|
|
}
|
|
RegCloseKey(applKey);
|
|
}
|
|
SetEnabledAppControls(hDlg);
|
|
}
|
|
|
|
static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
|
|
{
|
|
TVITEM ti;
|
|
LPITEMTAG lpit;
|
|
|
|
ti.mask = TVIF_PARAM;
|
|
ti.hItem = TreeView_GetSelection(hTV);
|
|
if (TreeView_GetItem (hTV, &ti))
|
|
{
|
|
lpit = (LPITEMTAG) ti.lParam;
|
|
if (lpit->lpAppl)
|
|
{
|
|
WINE_TRACE("lpit->lpAppl is non-null\n");
|
|
/* update comboboxes to reflect settings for this app */
|
|
UpdateComboboxes(hDlg, lpit->lpAppl);
|
|
} else
|
|
{
|
|
WINE_TRACE("lpit->lpAppl is null\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
|
|
{
|
|
FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
|
|
}
|
|
|
|
static VOID OnAddApplicationClick(HWND hDlg)
|
|
{
|
|
char szFileTitle [255];
|
|
char szFile [255];
|
|
char lpcVersionKey [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(lpcVersionKey, "AppDefaults\\%s\\Version", szFileTitle);
|
|
lpit->lpAppl = CreateAppl(FALSE, szFileTitle, lpcVersionKey);
|
|
tis.u.item.lParam = (LPARAM)lpit;
|
|
TreeView_InsertItem(GetDlgItem(hDlg, IDC_APP_TREEVIEW), &tis);
|
|
|
|
/* add the empty entries for the Version section for this app */
|
|
setConfigValue(lpcVersionKey,NULL,NULL);
|
|
}
|
|
}
|
|
|
|
static VOID OnRemoveApplicationClick(HWND hDlg)
|
|
{
|
|
HWND hTV;
|
|
TVITEM ti;
|
|
LPITEMTAG lpit;
|
|
|
|
hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
|
|
ti.mask = TVIF_PARAM;
|
|
ti.hItem = TreeView_GetSelection(hTV);
|
|
if (TreeView_GetItem (hTV, &ti))
|
|
{
|
|
lpit = (LPITEMTAG) ti.lParam;
|
|
if (lpit->lpAppl)
|
|
{
|
|
/* add transactions to remove all entries for this application */
|
|
addTransaction(lpit->lpAppl->lpcVersionSection, NULL, ACTION_REMOVE, NULL);
|
|
TreeView_DeleteItem(hTV,ti.hItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void UpdateWinverSelection(HWND hDlg, int selection)
|
|
{
|
|
TVITEM ti;
|
|
LPITEMTAG lpit;
|
|
VERSION_DESC *pVer = NULL;
|
|
HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
|
|
|
|
ti.mask = TVIF_PARAM;
|
|
ti.hItem = TreeView_GetSelection(hTV);
|
|
if (TreeView_GetItem (hTV, &ti))
|
|
{
|
|
lpit = (LPITEMTAG) ti.lParam;
|
|
|
|
if(lpit->lpAppl)
|
|
{
|
|
pVer = getWinVersions();
|
|
|
|
/* if no item is selected OR if our version string is null */
|
|
/* remove this applications setting */
|
|
if((selection == CB_ERR) || !(*pVer[selection].szVersion))
|
|
{
|
|
WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
|
|
addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_REMOVE, NULL); /* change registry entry */
|
|
} else
|
|
{
|
|
WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "Windows", pVer[selection].szVersion);
|
|
addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
|
|
}
|
|
|
|
TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
|
|
OnInitAppDlg(hDlg);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void UpdateDosverSelection(HWND hDlg, int selection)
|
|
{
|
|
TVITEM ti;
|
|
LPITEMTAG lpit;
|
|
VERSION_DESC *pVer = NULL;
|
|
HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
|
|
|
|
ti.mask = TVIF_PARAM;
|
|
ti.hItem = TreeView_GetSelection(hTV);
|
|
if (TreeView_GetItem (hTV, &ti))
|
|
{
|
|
lpit = (LPITEMTAG) ti.lParam;
|
|
|
|
if(lpit->lpAppl)
|
|
{
|
|
pVer = getDOSVersions();
|
|
|
|
/* if no item is selected OR if our version string is null */
|
|
/* remove this applications setting */
|
|
if((selection == CB_ERR) || !(*pVer[selection].szVersion))
|
|
{
|
|
WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
|
|
addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_REMOVE, NULL); /* change registry entry */
|
|
} else
|
|
{
|
|
WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "DOS", pVer[selection].szVersion);
|
|
addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
|
|
}
|
|
|
|
TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
|
|
OnInitAppDlg(hDlg);
|
|
}
|
|
}
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int selection;
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
OnInitAppDlg(hDlg);
|
|
initAppDlgComboboxes(hDlg);
|
|
break;
|
|
case WM_NOTIFY:
|
|
switch (((LPNMHDR)lParam)->code) {
|
|
case TVN_SELCHANGED: {
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_APP_TREEVIEW:
|
|
OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_APP_TREEVIEW));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case TVN_DELETEITEM:
|
|
OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
|
|
break;
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
switch(HIWORD(wParam)) {
|
|
case CBN_SELCHANGE:
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_WINVER:
|
|
selection = SendDlgItemMessage( hDlg, IDC_WINVER, CB_GETCURSEL, 0, 0);
|
|
UpdateWinverSelection(hDlg, selection);
|
|
break;
|
|
case IDC_DOSVER:
|
|
selection = SendDlgItemMessage( hDlg, IDC_DOSVER, CB_GETCURSEL, 0, 0);
|
|
UpdateDosverSelection(hDlg, selection);
|
|
break;
|
|
}
|
|
case BN_CLICKED:
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_APP_ADDAPP:
|
|
OnAddApplicationClick(hDlg);
|
|
break;
|
|
case IDC_APP_REMOVEAPP:
|
|
OnRemoveApplicationClick(hDlg);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|