blob: 4ae58790da5bc7b73c37c83e3a64e44337ed8af8 [file] [log] [blame]
/*
* 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;
}