When we send out a notification to a registered window with
[wine.git] / programs / winecfg / appdefaults.c
blob4ae58790da5bc7b73c37c83e3a64e44337ed8af8
1 /*
2 * WineCfg app settings tabsheet
4 * Copyright 2004 Robert van Herk
5 * Chris Morgan
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define NONAMELESSUNION
24 #include <windows.h>
25 #include <commdlg.h>
26 #include <wine/debug.h>
27 #include <stdio.h>
28 #include "winecfg.h"
29 #include "resource.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
33 typedef struct _APPL
35 BOOL isGlobal;
36 char* lpcApplication;
37 char* lpcVersionSection;
38 } APPL, *LPAPPL;
40 static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* version_section)
42 LPAPPL out;
43 WINE_TRACE("application: '%s', version_section: '%s'\n", application, version_section);
44 out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
45 out->lpcApplication = strdup(application);
46 out->lpcVersionSection = strdup(version_section);
47 out->isGlobal = isGlobal;
48 return out;
51 static VOID FreeAppl(LPAPPL lpAppl)
53 /* The strings were strdup-ped, so we use "free" */
54 if (lpAppl->lpcApplication) free(lpAppl->lpcApplication);
55 if (lpAppl->lpcVersionSection) free(lpAppl->lpcVersionSection);
56 HeapFree(GetProcessHeap(),0,lpAppl);
59 /* section can be "Version" */
60 /* key can be "Windows"/"Dos" */
61 /* value can be appropriate values for the above keys */
62 typedef struct _APPSETTING
64 char* section;
65 char* lpcKey;
66 char* value;
67 } APPSETTING, *LPAPPSETTING;
69 static LPAPPSETTING CreateAppSetting(char* lpcKey, char* value)
71 LPAPPSETTING out = HeapAlloc(GetProcessHeap(),0,sizeof(APPSETTING));
72 out->lpcKey = strdup (lpcKey);
73 out->value = strdup(value);
74 return out;
77 static VOID FreeAppSetting(LPAPPSETTING las)
79 if (las->lpcKey) free(las->lpcKey);
80 if (las->value) free(las->value);
81 HeapFree(GetProcessHeap(),0,las);
84 typedef struct _ITEMTAG
86 LPAPPL lpAppl;
87 LPAPPSETTING lpSetting;
88 } ITEMTAG, *LPITEMTAG;
90 static LPITEMTAG CreateItemTag()
92 LPITEMTAG out;
93 out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
94 out->lpAppl = 0;
95 out->lpSetting = 0;
96 return out;
99 static VOID FreeItemTag(LPITEMTAG lpit)
101 /* if child, only free the lpSetting, the lpAppl will be freed when we free the parents item tag */
102 if (lpit->lpSetting)
104 FreeAppSetting(lpit->lpSetting);
105 } else
107 if (lpit->lpAppl)
108 FreeAppl(lpit->lpAppl);
110 HeapFree(GetProcessHeap(), 0, lpit);
113 static VOID LoadAppSettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
115 HKEY key;
116 int i;
117 DWORD size;
118 DWORD readSize;
119 char name [255];
120 char read [255];
121 char *description;
122 LPITEMTAG lpIt;
123 TVINSERTSTRUCT tis;
124 HTREEITEM hParent;
125 LPAPPSETTING lpas;
127 WINE_TRACE("opening '%s'\n", appl->lpcVersionSection);
128 if (RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
130 i = 0;
131 size = 255;
132 readSize = 255;
134 lpIt = CreateItemTag();
135 lpIt->lpAppl = appl;
137 tis.hParent = NULL;
138 tis.hInsertAfter = TVI_LAST;
139 tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
140 tis.u.item.pszText = appl->lpcApplication;
141 tis.u.item.lParam = (LPARAM)lpIt;
142 hParent = TreeView_InsertItem(hwndTV,&tis);
143 tis.hParent = hParent;
145 /* insert version entries */
146 if(RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
148 while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
150 char itemtext[128];
152 WINE_TRACE("Reading value %s, namely %s\n", name, read);
154 lpIt = CreateItemTag();
155 lpas = CreateAppSetting(name, read);
156 lpIt->lpSetting = lpas;
157 lpIt->lpAppl = appl;
158 tis.u.item.lParam = (LPARAM)lpIt;
160 /* convert the value for 'dosver or winver' to human readable form */
161 description = getDescriptionFromVersion(getWinVersions(), read);
162 if(!description)
164 description = getDescriptionFromVersion(getDOSVersions(), read);
165 if(!description)
166 description = "Not found";
169 sprintf(itemtext, "%s - %s", name, description);
170 tis.u.item.pszText = itemtext;
172 TreeView_InsertItem(hwndTV,&tis);
173 i++; size = 255; readSize = 255;
175 RegCloseKey(key);
176 } else
178 WINE_TRACE("no version section found\n");
183 static VOID SetEnabledAppControls(HWND dialog)
187 static VOID UpdateComboboxes(HWND hDlg, LPAPPL lpAppl)
189 int i;
190 const VERSION_DESC *pVer = NULL;
192 /* retrieve the registry values for this application */
193 char *curWinVer = getConfigValue(lpAppl->lpcVersionSection, "Windows", "");
194 char *curDOSVer = getConfigValue(lpAppl->lpcVersionSection, "DOS", "");
196 if(curWinVer) WINE_TRACE("curWinVer is '%s'\n", curWinVer);
197 else WINE_TRACE("curWinVer is null\n");
198 if(curDOSVer) WINE_TRACE("curDOSVer is '%s'\n", curDOSVer);
199 else WINE_TRACE("curDOSVer is null\n");
201 /* normalize the version strings */
202 if(strlen(curWinVer) != 0)
204 if ((pVer = getWinVersions ()))
206 WINE_TRACE("Windows version\n");
207 for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
209 WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
210 if (!strcasecmp (pVer->szVersion, curWinVer))
212 SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
213 (WPARAM) i, 0);
214 WINE_TRACE("match with %s\n", pVer->szVersion);
218 } else /* clear selection */
220 WINE_TRACE("setting winver to nothing\n");
221 SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
222 -1, 0);
225 if(strlen(curDOSVer) != 0)
227 if ((pVer = getDOSVersions ()))
229 WINE_TRACE("DOS version\n");
230 for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
232 WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
233 if (!strcasecmp (pVer->szVersion, curDOSVer))
235 SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
236 (WPARAM) i, 0);
237 WINE_TRACE("match with %s\n", pVer->szVersion);
241 } else
243 WINE_TRACE("setting dosver to nothing\n");
244 SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
245 -1, 0);
248 if(curWinVer) free(curWinVer);
249 if(curDOSVer) free(curDOSVer);
252 void
253 initAppDlgComboboxes (HWND hDlg)
255 int i;
256 const VERSION_DESC *pVer = NULL;
258 if ((pVer = getWinVersions ()))
260 for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
262 SendDlgItemMessage (hDlg, IDC_WINVER, CB_ADDSTRING,
263 0, (LPARAM) pVer->szDescription);
266 if ((pVer = getDOSVersions ()))
268 for (i = 0; *pVer->szVersion || *pVer->szDescription ; i++, pVer++)
270 SendDlgItemMessage (hDlg, IDC_DOSVER, CB_ADDSTRING,
271 0, (LPARAM) pVer->szDescription);
277 static VOID OnInitAppDlg(HWND hDlg)
279 HWND hwndTV;
280 LPAPPL lpAppl;
281 HKEY applKey;
282 int i;
283 DWORD size;
284 char appl [255];
285 char lpcVersionKey [255];
286 FILETIME ft;
288 hwndTV = GetDlgItem(hDlg,IDC_APP_TREEVIEW);
289 lpAppl = CreateAppl(TRUE, "Global Settings", "Version");
290 LoadAppSettings(lpAppl, hDlg, hwndTV);
292 /*And now the application specific stuff:*/
293 if (RegOpenKey(configKey, "AppDefaults", &applKey) == ERROR_SUCCESS)
295 i = 0;
296 size = 255;
297 while (RegEnumKeyEx(applKey, i, appl, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
299 sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", appl);
300 lpAppl = CreateAppl(FALSE, appl, lpcVersionKey);
301 LoadAppSettings(lpAppl, hDlg, hwndTV);
302 i++; size = 255;
304 RegCloseKey(applKey);
306 SetEnabledAppControls(hDlg);
309 static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
311 TVITEM ti;
312 LPITEMTAG lpit;
314 ti.mask = TVIF_PARAM;
315 ti.hItem = TreeView_GetSelection(hTV);
316 if (TreeView_GetItem (hTV, &ti))
318 lpit = (LPITEMTAG) ti.lParam;
319 if (lpit->lpAppl)
321 WINE_TRACE("lpit->lpAppl is non-null\n");
322 /* update comboboxes to reflect settings for this app */
323 UpdateComboboxes(hDlg, lpit->lpAppl);
324 } else
326 WINE_TRACE("lpit->lpAppl is null\n");
331 static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
333 FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
336 static VOID OnAddApplicationClick(HWND hDlg)
338 char szFileTitle [255];
339 char szFile [255];
340 char lpcVersionKey [255];
342 TVINSERTSTRUCT tis;
343 LPITEMTAG lpit;
344 OPENFILENAME ofn = { sizeof(OPENFILENAME),
345 0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL, 0, 0, NULL,
346 0, NULL, 0, NULL, NULL,
347 OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
349 ofn.lpstrFileTitle = szFileTitle;
350 ofn.lpstrFileTitle[0] = '\0';
351 ofn.nMaxFileTitle = sizeof(szFileTitle);
352 ofn.lpstrFile = szFile;
353 ofn.lpstrFile[0] = '\0';
354 ofn.nMaxFile = sizeof(szFile);
356 if (GetOpenFileName(&ofn))
358 tis.hParent = NULL;
359 tis.hInsertAfter = TVI_LAST;
360 tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
361 tis.u.item.pszText = szFileTitle;
362 lpit = CreateItemTag();
363 sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", szFileTitle);
364 lpit->lpAppl = CreateAppl(FALSE, szFileTitle, lpcVersionKey);
365 tis.u.item.lParam = (LPARAM)lpit;
366 TreeView_InsertItem(GetDlgItem(hDlg, IDC_APP_TREEVIEW), &tis);
368 /* add the empty entries for the Version section for this app */
369 setConfigValue(lpcVersionKey,NULL,NULL);
373 static VOID OnRemoveApplicationClick(HWND hDlg)
375 HWND hTV;
376 TVITEM ti;
377 LPITEMTAG lpit;
379 hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
380 ti.mask = TVIF_PARAM;
381 ti.hItem = TreeView_GetSelection(hTV);
382 if (TreeView_GetItem (hTV, &ti))
384 lpit = (LPITEMTAG) ti.lParam;
385 if (lpit->lpAppl)
387 /* add transactions to remove all entries for this application */
388 addTransaction(lpit->lpAppl->lpcVersionSection, NULL, ACTION_REMOVE, NULL);
389 TreeView_DeleteItem(hTV,ti.hItem);
394 static void UpdateWinverSelection(HWND hDlg, int selection)
396 TVITEM ti;
397 LPITEMTAG lpit;
398 VERSION_DESC *pVer = NULL;
399 HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
401 ti.mask = TVIF_PARAM;
402 ti.hItem = TreeView_GetSelection(hTV);
403 if (TreeView_GetItem (hTV, &ti))
405 lpit = (LPITEMTAG) ti.lParam;
407 if(lpit->lpAppl)
409 pVer = getWinVersions();
411 /* if no item is selected OR if our version string is null */
412 /* remove this applications setting */
413 if((selection == CB_ERR) || !(*pVer[selection].szVersion))
415 WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
416 addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_REMOVE, NULL); /* change registry entry */
417 } else
419 WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "Windows", pVer[selection].szVersion);
420 addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
423 TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
424 OnInitAppDlg(hDlg);
429 static void UpdateDosverSelection(HWND hDlg, int selection)
431 TVITEM ti;
432 LPITEMTAG lpit;
433 VERSION_DESC *pVer = NULL;
434 HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
436 ti.mask = TVIF_PARAM;
437 ti.hItem = TreeView_GetSelection(hTV);
438 if (TreeView_GetItem (hTV, &ti))
440 lpit = (LPITEMTAG) ti.lParam;
442 if(lpit->lpAppl)
444 pVer = getDOSVersions();
446 /* if no item is selected OR if our version string is null */
447 /* remove this applications setting */
448 if((selection == CB_ERR) || !(*pVer[selection].szVersion))
450 WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
451 addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_REMOVE, NULL); /* change registry entry */
452 } else
454 WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "DOS", pVer[selection].szVersion);
455 addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
458 TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
459 OnInitAppDlg(hDlg);
464 INT_PTR CALLBACK
465 AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
467 int selection;
468 switch (uMsg)
470 case WM_INITDIALOG:
471 OnInitAppDlg(hDlg);
472 initAppDlgComboboxes(hDlg);
473 break;
474 case WM_NOTIFY:
475 switch (((LPNMHDR)lParam)->code) {
476 case TVN_SELCHANGED: {
477 switch(LOWORD(wParam)) {
478 case IDC_APP_TREEVIEW:
479 OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_APP_TREEVIEW));
480 break;
483 break;
484 case TVN_DELETEITEM:
485 OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
486 break;
488 break;
489 case WM_COMMAND:
490 switch(HIWORD(wParam)) {
491 case CBN_SELCHANGE:
492 switch(LOWORD(wParam)) {
493 case IDC_WINVER:
494 selection = SendDlgItemMessage( hDlg, IDC_WINVER, CB_GETCURSEL, 0, 0);
495 UpdateWinverSelection(hDlg, selection);
496 break;
497 case IDC_DOSVER:
498 selection = SendDlgItemMessage( hDlg, IDC_DOSVER, CB_GETCURSEL, 0, 0);
499 UpdateDosverSelection(hDlg, selection);
500 break;
502 case BN_CLICKED:
503 switch(LOWORD(wParam)) {
504 case IDC_APP_ADDAPP:
505 OnAddApplicationClick(hDlg);
506 break;
507 case IDC_APP_REMOVEAPP:
508 OnRemoveApplicationClick(hDlg);
509 break;
511 break;
513 break;
516 return 0;