| /* |
| * 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; |
| } |