[CSCRIPT][WSCRIPT] Sync with Wine Staging 3.17. CORE-15127
[reactos.git] / base / shell / progman / dialog.c
1 /*
2 * Program Manager
3 *
4 * Copyright 1996 Ulrich Schmid
5 * Copyright 2002 Sylvain Petreolle
6 * Copyright 2002 Andriy Palamarchuk
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 /*
24 * PROJECT: ReactOS Program Manager
25 * COPYRIGHT: GPL - See COPYING in the top level directory
26 * FILE: base/shell/progman/dialog.c
27 * PURPOSE: ProgMan dialog boxes
28 * PROGRAMMERS: Ulrich Schmid
29 * Sylvain Petreolle
30 * Andriy Palamarchuk
31 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
32 */
33
34 #include "progman.h"
35
36 #include <commdlg.h>
37
38 /***********************************************************************
39 *
40 * DIALOG_AddFilterItem and DIALOG_BrowseXXX
41 */
42
43 static
44 VOID
45 DIALOG_AddFilterItem(LPWSTR* p, UINT ids, LPCWSTR filter)
46 {
47 LoadStringW(Globals.hInstance, ids, *p, MAX_STRING_LEN);
48 *p += wcslen(*p) + 1;
49 lstrcpyW(*p, filter);
50 *p += wcslen(*p) + 1;
51 **p = '\0';
52 }
53
54 static
55 BOOL
56 DIALOG_Browse(HWND hWnd, LPCWSTR lpszzFilter, LPWSTR lpstrFile, INT nMaxFile)
57 {
58 OPENFILENAMEW openfilename;
59 WCHAR szDir[MAX_PATH];
60
61 ZeroMemory(&openfilename, sizeof(openfilename));
62
63 GetCurrentDirectoryW(ARRAYSIZE(szDir), szDir);
64
65 openfilename.lStructSize = sizeof(openfilename);
66 openfilename.hwndOwner = hWnd;
67 openfilename.hInstance = Globals.hInstance;
68 openfilename.lpstrFilter = lpszzFilter;
69 openfilename.lpstrFile = lpstrFile;
70 openfilename.nMaxFile = nMaxFile;
71 openfilename.lpstrInitialDir = szDir;
72 openfilename.Flags = 0;
73 openfilename.lpstrDefExt = L"exe";
74 openfilename.lpstrCustomFilter = NULL;
75 openfilename.nMaxCustFilter = 0;
76 openfilename.nFilterIndex = 0;
77 openfilename.lpstrFileTitle = NULL;
78 openfilename.nMaxFileTitle = 0;
79 openfilename.lpstrTitle = NULL;
80 openfilename.nFileOffset = 0;
81 openfilename.nFileExtension = 0;
82 openfilename.lCustData = 0;
83 openfilename.lpfnHook = NULL;
84 openfilename.lpTemplateName = NULL;
85
86 return GetOpenFileNameW(&openfilename);
87 }
88
89 static
90 BOOL
91 DIALOG_BrowsePrograms(HWND hWnd, LPWSTR lpszFile, INT nMaxFile)
92 {
93 WCHAR szzFilter[2 * MAX_STRING_LEN + 100];
94 LPWSTR p = szzFilter;
95
96 DIALOG_AddFilterItem(&p, IDS_PROGRAMS , L"*.exe;*.pif;*.com;*.bat;*.cmd");
97 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*");
98
99 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile);
100 }
101
102 static
103 BOOL
104 DIALOG_BrowseSymbols(HWND hWnd, LPWSTR lpszFile, INT nMaxFile)
105 {
106 WCHAR szzFilter[5 * MAX_STRING_LEN + 100];
107 LPWSTR p = szzFilter;
108
109 DIALOG_AddFilterItem(&p, IDS_SYMBOL_FILES, L"*.ico;*.exe;*.dll");
110 DIALOG_AddFilterItem(&p, IDS_PROGRAMS, L"*.exe");
111 DIALOG_AddFilterItem(&p, IDS_LIBRARIES_DLL, L"*.dll");
112 DIALOG_AddFilterItem(&p, IDS_SYMBOLS_ICO, L"*.ico");
113 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*");
114
115 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile);
116 }
117
118
119
120 /***********************************************************************
121 *
122 * DIALOG_New
123 */
124
125 LPCWSTR GroupFormatToFormatName(GROUPFORMAT Format)
126 {
127 static const LPCWSTR FormatNames[] =
128 {
129 L"Windows 3.1",
130 L"NT Ansi",
131 L"NT Unicode"
132 };
133
134 if (Format > NT_Unicode)
135 return NULL;
136 else
137 return FormatNames[Format];
138 }
139
140 typedef struct _NEW_ITEM_CONTEXT
141 {
142 INT nDefault;
143 INT nResult;
144 } NEW_ITEM_CONTEXT, *PNEW_ITEM_CONTEXT;
145
146 static
147 INT_PTR
148 CALLBACK
149 DIALOG_NEW_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
150 {
151 PNEW_ITEM_CONTEXT pNewItem;
152 GROUPFORMAT format;
153 INT iItem;
154
155 pNewItem = (PNEW_ITEM_CONTEXT)GetWindowLongPtrW(hDlg, 8);
156
157 switch (uMsg)
158 {
159 case WM_INITDIALOG:
160 {
161 pNewItem = (PNEW_ITEM_CONTEXT)lParam;
162 SetWindowLongPtrW(hDlg, 8, lParam);
163
164 for (format = Win_311; format <= NT_Unicode; ++format)
165 {
166 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_INSERTSTRING, 0, (LPARAM)GroupFormatToFormatName(format));
167 if (iItem != CB_ERR && iItem != CB_ERRSPACE)
168 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETITEMDATA, iItem, format);
169 }
170
171 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETCURSEL, 0, 0);
172 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, pNewItem->nDefault);
173 CheckRadioButton(hDlg, PM_PERSONAL_GROUP, PM_COMMON_GROUP, PM_PERSONAL_GROUP);
174
175 EnableDlgItem(hDlg, PM_NEW_PROGRAM, GROUP_ActiveGroup() != NULL);
176
177 SendMessageW(hDlg, WM_COMMAND, pNewItem->nDefault, 0);
178 break;
179 }
180
181 case WM_COMMAND:
182 switch (LOWORD(wParam))
183 {
184 case PM_NEW_GROUP:
185 {
186 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam);
187 EnableDlgItem(hDlg, PM_COMMON_GROUP , TRUE);
188 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, TRUE);
189 EnableDlgItem(hDlg, PM_FORMAT_TXT, TRUE);
190 EnableDlgItem(hDlg, PM_FORMAT , TRUE);
191 return TRUE;
192 }
193
194 case PM_NEW_PROGRAM:
195 {
196 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam);
197 EnableDlgItem(hDlg, PM_COMMON_GROUP , FALSE);
198 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, FALSE);
199 EnableDlgItem(hDlg, PM_FORMAT_TXT, FALSE);
200 EnableDlgItem(hDlg, PM_FORMAT , FALSE);
201 return TRUE;
202 }
203
204 case IDHELP:
205 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
206 return TRUE;
207
208 case IDOK:
209 {
210 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETCURSEL, 0, 0);
211
212 format = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETITEMDATA, iItem, 0);
213 format = min(max(format, Win_311), NT_Unicode);
214
215 pNewItem->nResult = !!IsDlgButtonChecked(hDlg, PM_NEW_GROUP);
216 pNewItem->nResult |= (!!IsDlgButtonChecked(hDlg, PM_COMMON_GROUP) << 1);
217 pNewItem->nResult |= (format << 2);
218
219 EndDialog(hDlg, IDOK);
220 return TRUE;
221 }
222
223 case IDCANCEL:
224 EndDialog(hDlg, IDCANCEL);
225 return TRUE;
226 }
227 return FALSE;
228 }
229
230 return FALSE;
231 }
232
233 BOOL DIALOG_New(INT nDefault, PINT pnResult)
234 {
235 INT_PTR ret;
236 NEW_ITEM_CONTEXT NewItem;
237
238 *pnResult = 0;
239
240 NewItem.nDefault = nDefault;
241 NewItem.nResult = 0;
242 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_NEW), Globals.hMainWnd, DIALOG_NEW_DlgProc, (LPARAM)&NewItem);
243 if (ret == IDOK)
244 *pnResult = NewItem.nResult;
245
246 return (ret == IDOK);
247 }
248
249
250 /***********************************************************************
251 *
252 * DIALOG_CopyMove
253 */
254
255 typedef struct _COPY_MOVE_CONTEXT
256 {
257 PROGRAM* Program;
258 PROGGROUP* hToGroup;
259 BOOL bMove;
260 } COPY_MOVE_CONTEXT, *PCOPY_MOVE_CONTEXT;
261
262 static
263 INT_PTR
264 CALLBACK
265 DIALOG_COPY_MOVE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
266 {
267 PROGGROUP* hGrpItem;
268 PROGGROUP* hGroup;
269
270 PCOPY_MOVE_CONTEXT pCopyMove;
271 INT iItem;
272
273 WCHAR text[MAX_STRING_LEN];
274
275 pCopyMove = (PCOPY_MOVE_CONTEXT)GetWindowLongPtrW(hDlg, 8);
276
277 switch (uMsg)
278 {
279 case WM_INITDIALOG:
280 {
281 pCopyMove = (PCOPY_MOVE_CONTEXT)lParam;
282 SetWindowLongPtrW(hDlg, 8, lParam);
283
284 if (pCopyMove->bMove)
285 {
286 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_1, text, ARRAYSIZE(text));
287 SetWindowTextW(hDlg, text);
288 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_2, text, ARRAYSIZE(text));
289 SetDlgItemTextW(hDlg, PM_COPY_MOVE_TXT, text);
290 }
291
292 /* List all the group names but the source group, in case we are doing a move */
293 for (hGroup = Globals.hGroups; hGroup; hGroup = hGroup->hNext)
294 {
295 if (!pCopyMove->bMove || hGroup != pCopyMove->Program->hGroup)
296 {
297 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_ADDSTRING, 0, (LPARAM)hGroup->hName);
298 if (iItem != CB_ERR && iItem != CB_ERRSPACE)
299 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETITEMDATA, iItem, (LPARAM)hGroup);
300 }
301 }
302 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETCURSEL, 0, 0);
303 SetDlgItemTextW(hDlg, PM_PROGRAM , pCopyMove->Program->hName);
304 SetDlgItemTextW(hDlg, PM_FROM_GROUP, pCopyMove->Program->hGroup->hName);
305 break;
306 }
307
308 case WM_COMMAND:
309 switch (LOWORD(wParam))
310 {
311 case IDHELP:
312 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
313 return TRUE;
314
315 case IDOK:
316 {
317 /* Get the selected group */
318 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETCURSEL, 0, 0);
319 hGrpItem = (PROGGROUP *)SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETITEMDATA, iItem, 0);
320 /* Check that it is indeed in the group list */
321 for (hGroup = Globals.hGroups; hGroup && hGroup != hGrpItem; hGroup = hGroup->hNext)
322 ;
323 if (pCopyMove->bMove)
324 {
325 if (hGrpItem == pCopyMove->Program->hGroup)
326 hGrpItem = NULL;
327 }
328 pCopyMove->hToGroup = hGrpItem;
329 EndDialog(hDlg, IDOK);
330 return TRUE;
331 }
332
333 case IDCANCEL:
334 EndDialog(hDlg, IDCANCEL);
335 return TRUE;
336 }
337 return FALSE;
338 }
339
340 return FALSE;
341 }
342
343 PROGGROUP* DIALOG_CopyMove(PROGRAM* hProgram, BOOL bMove)
344 {
345 COPY_MOVE_CONTEXT CopyMove;
346 INT_PTR ret;
347
348 CopyMove.bMove = bMove;
349 CopyMove.Program = hProgram;
350 CopyMove.hToGroup = NULL;
351 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_COPY_MOVE), Globals.hMainWnd, DIALOG_COPY_MOVE_DlgProc, (LPARAM)&CopyMove);
352
353 return (ret == IDOK ? CopyMove.hToGroup : NULL);
354 }
355
356 /***********************************************************************
357 *
358 * DIALOG_Delete
359 */
360
361 BOOL DIALOG_Delete(UINT ids_text_s, LPCWSTR lpszName)
362 {
363 return (MAIN_MessageBoxIDS_s(ids_text_s, lpszName, IDS_DELETE, MB_YESNO | MB_DEFBUTTON2) == IDYES);
364 }
365
366
367 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnableOkButtonFromEditContents */
368 BOOL ValidateEditContents(HWND hDlg, INT nIDEditItem)
369 {
370 BOOL Enable = FALSE;
371 LPWSTR psz;
372 INT Length, n;
373 HWND Edit;
374
375 Edit = GetDlgItem(hDlg, nIDEditItem);
376 Length = GetWindowTextLengthW(Edit);
377
378 if (Length <= 0)
379 return FALSE;
380
381 psz = Alloc(0, (Length + 1) * sizeof(WCHAR));
382 if (psz)
383 {
384 GetWindowTextW(Edit, psz, Length + 1);
385 for (n = 0; n < Length && !Enable; ++n)
386 Enable = (psz[n] != ' ');
387 Free(psz);
388 }
389 else
390 {
391 Enable = TRUE;
392 }
393
394 return Enable;
395 }
396
397
398 /***********************************************************************
399 *
400 * DIALOG_GroupAttributes
401 */
402
403 typedef struct _GROUP_ATTRIBUTES_CONTEXT
404 {
405 GROUPFORMAT format;
406 LPWSTR lpszTitle;
407 LPWSTR lpszGrpFile;
408 INT nSize;
409 } GROUP_ATTRIBUTES_CONTEXT, *PGROUP_ATTRIBUTES_CONTEXT;
410
411 static
412 INT_PTR
413 CALLBACK
414 DIALOG_GROUP_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
415 {
416 PGROUP_ATTRIBUTES_CONTEXT pGroupAttributes;
417
418 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8);
419
420 switch (uMsg)
421 {
422 case WM_INITDIALOG:
423 {
424 DWORD evMask;
425
426 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)lParam;
427 SetWindowLongPtrW(hDlg, 8, lParam);
428
429 /* Configure Richedit control for sending notification changes */
430 evMask = SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE;
431 SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_SETEVENTMASK, 0, (LPARAM)evMask);
432
433 SetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle);
434
435 if (pGroupAttributes->format != Win_311)
436 {
437 EnableDlgItem(hDlg, PM_FILE, FALSE);
438 }
439 else
440 {
441 EnableDlgItem(hDlg, PM_FILE, TRUE);
442 SetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile);
443 }
444
445 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION));
446 break;
447 }
448
449 case WM_COMMAND:
450 switch (LOWORD(wParam))
451 {
452 case IDHELP:
453 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
454 return TRUE;
455
456 case PM_DESCRIPTION:
457 {
458 if (HIWORD(wParam) == EN_CHANGE)
459 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION));
460 return FALSE;
461 }
462
463 case IDOK:
464 {
465 GetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle, pGroupAttributes->nSize);
466 if (pGroupAttributes->format)
467 *pGroupAttributes->lpszGrpFile = '\0';
468 else
469 GetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile, pGroupAttributes->nSize);
470 EndDialog(hDlg, IDOK);
471 return TRUE;
472 }
473
474 case IDCANCEL:
475 EndDialog(hDlg, IDCANCEL);
476 return TRUE;
477 }
478 return FALSE;
479 }
480
481 return FALSE;
482 }
483
484 BOOL DIALOG_GroupAttributes(GROUPFORMAT format, LPWSTR lpszTitle, LPWSTR lpszGrpFile, INT nSize)
485 {
486 INT_PTR ret;
487 GROUP_ATTRIBUTES_CONTEXT GroupAttributes;
488
489 GroupAttributes.format = format;
490 GroupAttributes.nSize = nSize;
491 GroupAttributes.lpszTitle = lpszTitle;
492 GroupAttributes.lpszGrpFile = lpszGrpFile;
493
494 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_GROUP), Globals.hMainWnd, DIALOG_GROUP_DlgProc, (LPARAM)&GroupAttributes);
495
496 return (ret == IDOK);
497 }
498
499
500 /***********************************************************************
501 *
502 * DIALOG_Symbol
503 */
504
505 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnumPickIconResourceProc */
506 static
507 BOOL
508 CALLBACK
509 EnumPickIconResourceProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
510 {
511 HICON hIcon;
512 HWND hDlgCtrl = (HWND)lParam;
513 WCHAR szName[100];
514
515 if (IS_INTRESOURCE(lpszName))
516 StringCbPrintfW(szName, sizeof(szName), L"%u", (unsigned)(UINT_PTR)lpszName);
517 else
518 StringCbCopyW(szName, sizeof(szName), lpszName);
519
520 hIcon = (HICON)LoadImageW(hModule, lpszName, IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
521 if (hIcon == NULL)
522 return TRUE;
523
524 SendMessageW(hDlgCtrl, LB_ADDSTRING, 0, (LPARAM)hIcon);
525 return TRUE;
526 }
527
528 static
529 VOID
530 DestroyIconList(HWND hDlgCtrl)
531 {
532 HICON hIcon;
533 UINT count;
534
535 count = SendMessageA(hDlgCtrl, LB_GETCOUNT, 0, 0);
536 if (count == LB_ERR || count == 0)
537 return;
538
539 while (count-- > 0)
540 {
541 hIcon = (HICON)SendMessageA(hDlgCtrl, LB_GETITEMDATA, 0, 0);
542 DestroyIcon(hIcon);
543 SendMessageA(hDlgCtrl, LB_DELETESTRING, 0, 0);
544 }
545 }
546
547 typedef struct _PICK_ICON_CONTEXT
548 {
549 HMODULE hLibrary;
550 HWND hDlgCtrl;
551 WCHAR szName[MAX_PATH]; // LPWSTR lpszIconFile; // INT nSize;
552 INT Index;
553 HICON hIcon;
554 } PICK_ICON_CONTEXT, *PPICK_ICON_CONTEXT;
555
556 #if 0
557
558 static struct
559 {
560 LPSTR lpszIconFile;
561 INT nSize;
562 HICON *lphIcon;
563 INT *lpnIconIndex;
564 } Symbol;
565
566 #endif
567
568 static
569 INT_PTR
570 CALLBACK
571 DIALOG_SYMBOL_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
572 {
573 WCHAR filename[MAX_PATHNAME_LEN];
574 PPICK_ICON_CONTEXT pIconContext;
575
576 pIconContext = (PPICK_ICON_CONTEXT)GetWindowLongPtrW(hDlg, 8);
577
578 switch (uMsg)
579 {
580 case WM_INITDIALOG:
581 {
582 pIconContext = (PPICK_ICON_CONTEXT)lParam;
583 SetWindowLongPtrW(hDlg, 8, lParam);
584
585 pIconContext->hDlgCtrl = GetDlgItem(hDlg, PM_SYMBOL_LIST);
586 SetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName);
587 SendMessageA(pIconContext->hDlgCtrl, LB_SETITEMHEIGHT, 0, 32);
588
589 pIconContext->hLibrary = LoadLibraryExW(pIconContext->szName, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
590 if (pIconContext->hLibrary)
591 {
592 EnumResourceNamesW(pIconContext->hLibrary,
593 (LPCWSTR)RT_GROUP_ICON,
594 EnumPickIconResourceProc,
595 (LONG_PTR)pIconContext->hDlgCtrl);
596 FreeLibrary(pIconContext->hLibrary);
597 pIconContext->hLibrary = NULL;
598 }
599 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, pIconContext->Index, 0);
600 return TRUE;
601 }
602
603 case WM_MEASUREITEM:
604 {
605 PMEASUREITEMSTRUCT measure = (PMEASUREITEMSTRUCT)lParam;
606 measure->itemWidth = 32;
607 measure->itemHeight = 32;
608 return TRUE;
609 }
610
611 case WM_DRAWITEM:
612 {
613 PDRAWITEMSTRUCT dis = (PDRAWITEMSTRUCT)lParam;
614
615 if (dis->itemState & ODS_SELECTED)
616 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1));
617 else
618 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_WINDOW + 1));
619
620 DrawIcon(dis->hDC, dis->rcItem.left, dis->rcItem.top, (HICON)dis->itemData);
621 return TRUE;
622 }
623
624 case WM_COMMAND:
625 switch (LOWORD(wParam))
626 {
627 case PM_BROWSE:
628 {
629 filename[0] = '\0';
630 if (!DIALOG_BrowseSymbols(hDlg, filename, ARRAYSIZE(filename)))
631 return TRUE;
632
633 if (_wcsnicmp(pIconContext->szName, filename, ARRAYSIZE(pIconContext->szName)) == 0)
634 return TRUE;
635
636 SetDlgItemTextW(hDlg, PM_ICON_FILE, filename);
637 DestroyIconList(pIconContext->hDlgCtrl);
638 pIconContext->hLibrary = LoadLibraryExW(filename, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
639 if (pIconContext->hLibrary)
640 {
641 EnumResourceNamesW(pIconContext->hLibrary,
642 (LPCWSTR)RT_GROUP_ICON,
643 EnumPickIconResourceProc,
644 (LONG_PTR)pIconContext->hDlgCtrl);
645 FreeLibrary(pIconContext->hLibrary);
646 pIconContext->hLibrary = NULL;
647 }
648 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, 0, 0);
649 return TRUE;
650 }
651
652 case IDHELP:
653 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
654 return TRUE;
655
656 case IDOK:
657 {
658 INT nCurSel = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0);
659 GetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName, ARRAYSIZE(pIconContext->szName));
660 pIconContext->hIcon = (HICON)SendMessageA(pIconContext->hDlgCtrl, LB_GETITEMDATA, nCurSel, 0);
661 pIconContext->hIcon = CopyIcon(pIconContext->hIcon);
662 DestroyIconList(pIconContext->hDlgCtrl);
663 EndDialog(hDlg, IDOK);
664 return TRUE;
665 }
666
667 case IDCANCEL:
668 DestroyIconList(pIconContext->hDlgCtrl);
669 EndDialog(hDlg, IDCANCEL);
670 return TRUE;
671 }
672 return FALSE;
673 }
674
675 return FALSE;
676 }
677
678 static
679 VOID
680 DIALOG_Symbol(HWND hWnd, HICON *lphIcon, LPWSTR lpszIconFile, INT *lpnIconIndex, INT nSize)
681 {
682 PICK_ICON_CONTEXT IconContext;
683
684 IconContext.Index = *lpnIconIndex;
685 StringCchCopyNW(IconContext.szName, ARRAYSIZE(IconContext.szName), lpszIconFile, nSize);
686
687 if (DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_SYMBOL), hWnd, DIALOG_SYMBOL_DlgProc, (LPARAM)&IconContext) != IDOK)
688 return;
689
690 StringCchCopyNW(lpszIconFile, nSize, IconContext.szName, ARRAYSIZE(IconContext.szName));
691 *lpnIconIndex = IconContext.Index;
692 *lphIcon = IconContext.hIcon;
693 }
694
695
696 /***********************************************************************
697 *
698 * DIALOG_ProgramAttributes
699 */
700
701 typedef struct _PROGRAM_ATTRIBUTES_CONTEXT
702 {
703 LPWSTR lpszTitle;
704 LPWSTR lpszCmdLine;
705 LPWSTR lpszWorkDir;
706 LPWSTR lpszIconFile;
707 LPWSTR lpszTmpIconFile;
708 INT nSize;
709 INT* lpnCmdShow;
710 INT* lpnHotKey;
711 // HWND hSelGroupWnd;
712 BOOL* lpbNewVDM; // unused!
713 HICON* lphIcon;
714 HICON hTmpIcon;
715 INT* lpnIconIndex;
716 INT nTmpIconIndex;
717 BOOL bCheckBinaryType;
718 } PROGRAM_ATTRIBUTES_CONTEXT, *PPROGRAM_ATTRIBUTES_CONTEXT;
719
720 static
721 INT_PTR
722 CALLBACK
723 DIALOG_PROGRAM_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
724 {
725 BOOL bEnable;
726 WCHAR filename[MAX_PATHNAME_LEN];
727 DWORD evMask;
728 DWORD dwBinaryType;
729 PPROGRAM_ATTRIBUTES_CONTEXT pProgramAttributes;
730
731 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8);
732
733 switch (uMsg)
734 {
735 case WM_INITDIALOG:
736 {
737 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)lParam;
738 SetWindowLongPtrW(hDlg, 8, lParam);
739
740 evMask = SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE;
741 SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_SETEVENTMASK, 0, evMask);
742
743 SetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle);
744 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine);
745 SetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir);
746
747 /* 0x0F 0x06 */
748 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETRULES, HKCOMB_C | HKCOMB_A | HKCOMB_S | HKCOMB_NONE, HOTKEYF_CONTROL | HOTKEYF_ALT);
749 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETHOTKEY, *pProgramAttributes->lpnHotKey, 0);
750
751 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE);
752 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable);
753 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable);
754
755 CheckDlgButton(hDlg, PM_SYMBOL, *pProgramAttributes->lpnCmdShow == SW_SHOWMINNOACTIVE);
756
757 if (pProgramAttributes->bCheckBinaryType &&
758 (!GetBinaryTypeW(pProgramAttributes->lpszCmdLine, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY) )
759 {
760 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE);
761 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
762 }
763 else
764 {
765 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE);
766 CheckDlgButton(hDlg, PM_NEW_VDM, *pProgramAttributes->lpbNewVDM);
767 }
768 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0);
769 break;
770 }
771
772 case WM_COMMAND:
773 switch (LOWORD(wParam))
774 {
775 case PM_NEW_VDM:
776 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM));
777 return TRUE;
778
779 case PM_BROWSE:
780 {
781 filename[0] = '\0';
782 if (DIALOG_BrowsePrograms(hDlg, filename, ARRAYSIZE(filename)))
783 {
784 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, filename);
785 if (pProgramAttributes->bCheckBinaryType &&
786 (!GetBinaryTypeW(filename, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY))
787 {
788 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE);
789 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
790 }
791 else
792 {
793 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE);
794 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED);
795 }
796 }
797 return TRUE;
798 }
799
800 case IDHELP:
801 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
802 return TRUE;
803
804 case PM_SYMBOL:
805 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL));
806 return TRUE;
807
808 case PM_OTHER_SYMBOL:
809 {
810 DIALOG_Symbol(hDlg,
811 &pProgramAttributes->hTmpIcon,
812 pProgramAttributes->lpszTmpIconFile,
813 &pProgramAttributes->nTmpIconIndex,
814 MAX_PATHNAME_LEN);
815
816 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0);
817 return TRUE;
818 }
819
820 case PM_COMMAND_LINE:
821 {
822 if (HIWORD(wParam) == EN_CHANGE)
823 {
824 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE);
825 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable);
826 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable);
827 }
828 return FALSE;
829 }
830
831 case IDOK:
832 {
833 GetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle , pProgramAttributes->nSize);
834 GetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine, pProgramAttributes->nSize);
835 GetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir, pProgramAttributes->nSize);
836 if (pProgramAttributes->hTmpIcon)
837 {
838 #if 0
839 if (*pProgramAttributes->lphIcon)
840 DestroyIcon(*pProgramAttributes->lphIcon);
841 #endif
842 *pProgramAttributes->lphIcon = pProgramAttributes->hTmpIcon;
843 *pProgramAttributes->lpnIconIndex = pProgramAttributes->nTmpIconIndex;
844 lstrcpynW(pProgramAttributes->lpszIconFile, pProgramAttributes->lpszTmpIconFile, pProgramAttributes->nSize);
845 }
846 *pProgramAttributes->lpnHotKey = SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_GETHOTKEY, 0, 0);
847 *pProgramAttributes->lpnCmdShow = IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL;
848 *pProgramAttributes->lpbNewVDM = IsDlgButtonChecked(hDlg, PM_NEW_VDM);
849 EndDialog(hDlg, IDOK);
850 return TRUE;
851 }
852
853 case IDCANCEL:
854 EndDialog(hDlg, IDCANCEL);
855 return TRUE;
856 }
857 return FALSE;
858 }
859
860 return FALSE;
861 }
862
863 BOOL
864 DIALOG_ProgramAttributes(LPWSTR lpszTitle, LPWSTR lpszCmdLine, LPWSTR lpszWorkDir, LPWSTR lpszIconFile,
865 HICON* lphIcon, INT* lpnIconIndex, INT* lpnHotKey, INT* lpnCmdShow, BOOL* lpbNewVDM, INT nSize)
866 {
867 INT_PTR ret;
868 WCHAR szTmpIconFile[MAX_PATHNAME_LEN];
869 PROGRAM_ATTRIBUTES_CONTEXT ProgramAttributes;
870 DWORD dwSize;
871 DWORD dwType;
872
873 ProgramAttributes.nSize = nSize;
874 ProgramAttributes.lpszTitle = lpszTitle;
875 ProgramAttributes.lpszCmdLine = lpszCmdLine;
876 ProgramAttributes.lpszWorkDir = lpszWorkDir;
877 ProgramAttributes.lpszIconFile = lpszIconFile;
878 ProgramAttributes.lpnCmdShow = lpnCmdShow;
879 ProgramAttributes.lpnHotKey = lpnHotKey;
880 ProgramAttributes.lpbNewVDM = lpbNewVDM;
881 ProgramAttributes.lphIcon = lphIcon;
882 ProgramAttributes.lpnIconIndex = lpnIconIndex;
883
884 dwSize = sizeof(ProgramAttributes.bCheckBinaryType);
885 if (RegQueryValueExW(Globals.hKeyPMSettings,
886 L"CheckBinaryType",
887 0,
888 &dwType,
889 (LPBYTE)&ProgramAttributes.bCheckBinaryType,
890 &dwSize) != ERROR_SUCCESS
891 || dwType != REG_DWORD)
892 {
893 ProgramAttributes.bCheckBinaryType = TRUE;
894 }
895
896 #if 0
897 ProgramAttributes.hTmpIcon = NULL;
898 #else
899 ProgramAttributes.hTmpIcon = *lphIcon;
900 #endif
901 ProgramAttributes.nTmpIconIndex = *lpnIconIndex;
902 ProgramAttributes.lpszTmpIconFile = szTmpIconFile;
903 wcsncpy(szTmpIconFile, lpszIconFile, ARRAYSIZE(szTmpIconFile));
904
905 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_PROGRAM), Globals.hMainWnd, DIALOG_PROGRAM_DlgProc, (LPARAM)&ProgramAttributes);
906 return (ret == IDOK);
907 }
908
909
910 /***********************************************************************
911 *
912 * DIALOG_Execute
913 */
914
915 typedef struct _EXECUTE_CONTEXT
916 {
917 HKEY hKeyPMRecentFilesList;
918 DWORD dwMaxFiles;
919 BOOL bCheckBinaryType;
920 } EXECUTE_CONTEXT, *PEXECUTE_CONTEXT;
921
922 static
923 INT_PTR
924 CALLBACK
925 DIALOG_EXECUTE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
926 {
927 WCHAR szFile[MAX_PATHNAME_LEN]; // filename
928 DWORD BinaryType;
929 PEXECUTE_CONTEXT pExecuteContext;
930
931 pExecuteContext = (PEXECUTE_CONTEXT)GetWindowLongPtrW(hDlg, 8);
932
933 switch (uMsg)
934 {
935 case WM_INITDIALOG:
936 {
937 pExecuteContext = (PEXECUTE_CONTEXT)lParam;
938 SetWindowLongPtrW(hDlg, 8, lParam);
939
940 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND));
941
942 if (pExecuteContext->bCheckBinaryType)
943 {
944 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE);
945 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
946 }
947 else
948 {
949 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE);
950 }
951
952 break;
953 }
954
955 case WM_COMMAND:
956 switch (LOWORD(wParam))
957 {
958 case PM_SYMBOL:
959 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL));
960 return TRUE;
961
962 case PM_NEW_VDM:
963 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM));
964 return TRUE;
965
966 case PM_BROWSE:
967 {
968 szFile[0] = '\0';
969 if (DIALOG_BrowsePrograms(hDlg, szFile, ARRAYSIZE(szFile)))
970 {
971 SetWindowTextW(GetDlgItem(hDlg, PM_COMMAND), szFile);
972 SetFocus(GetDlgItem(hDlg, IDOK));
973 if (pExecuteContext->bCheckBinaryType &&
974 (!GetBinaryTypeW(szFile, &BinaryType) || BinaryType != SCS_WOW_BINARY) )
975 {
976 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE);
977 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
978 }
979 else
980 {
981 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE);
982 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED);
983 }
984 }
985 return TRUE;
986 }
987
988 case PM_COMMAND:
989 {
990 if (HIWORD(wParam) == CBN_EDITCHANGE)
991 {
992 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND));
993 }
994 return FALSE;
995 }
996
997 case IDHELP:
998 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
999 return TRUE;
1000
1001 case IDOK:
1002 {
1003 GetDlgItemTextW(hDlg, PM_COMMAND, szFile, ARRAYSIZE(szFile));
1004 ShellExecuteW(NULL, NULL, szFile, NULL, NULL, IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL);
1005 if (Globals.bMinOnRun)
1006 CloseWindow(Globals.hMainWnd);
1007 EndDialog(hDlg, IDOK);
1008 return TRUE;
1009 }
1010
1011 case IDCANCEL:
1012 EndDialog(hDlg, IDCANCEL);
1013 return TRUE;
1014 }
1015 return FALSE;
1016 }
1017
1018 return FALSE;
1019 }
1020
1021 VOID DIALOG_Execute(VOID)
1022 {
1023 EXECUTE_CONTEXT ExecuteContext;
1024 LONG lRet;
1025 DWORD dwSize;
1026 DWORD dwType;
1027
1028 ExecuteContext.hKeyPMRecentFilesList = NULL;
1029 ExecuteContext.bCheckBinaryType = TRUE;
1030
1031 lRet = RegCreateKeyExW(Globals.hKeyProgMan,
1032 L"Recent File List",
1033 0,
1034 NULL,
1035 0,
1036 KEY_READ | KEY_WRITE,
1037 NULL,
1038 &ExecuteContext.hKeyPMRecentFilesList,
1039 NULL);
1040 if (lRet == ERROR_SUCCESS)
1041 {
1042 dwSize = sizeof(ExecuteContext.dwMaxFiles);
1043 lRet = RegQueryValueExW(ExecuteContext.hKeyPMRecentFilesList,
1044 L"Max Files",
1045 NULL,
1046 &dwType,
1047 (LPBYTE)&ExecuteContext.dwMaxFiles,
1048 &dwSize);
1049 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD)
1050 {
1051 ExecuteContext.dwMaxFiles = 4;
1052 dwSize = sizeof(ExecuteContext.dwMaxFiles);
1053 lRet = RegSetValueExW(ExecuteContext.hKeyPMRecentFilesList,
1054 L"Max Files",
1055 0,
1056 REG_DWORD,
1057 (LPBYTE)&ExecuteContext.dwMaxFiles,
1058 sizeof(ExecuteContext.dwMaxFiles));
1059 }
1060
1061 dwSize = sizeof(ExecuteContext.bCheckBinaryType);
1062 lRet = RegQueryValueExW(Globals.hKeyPMSettings,
1063 L"CheckBinaryType",
1064 NULL,
1065 &dwType,
1066 (LPBYTE)&ExecuteContext.bCheckBinaryType,
1067 &dwSize);
1068 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD)
1069 {
1070 ExecuteContext.bCheckBinaryType = TRUE;
1071 }
1072 }
1073
1074 DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_EXECUTE), Globals.hMainWnd, DIALOG_EXECUTE_DlgProc, (LPARAM)&ExecuteContext);
1075
1076 if (ExecuteContext.hKeyPMRecentFilesList)
1077 RegCloseKey(ExecuteContext.hKeyPMRecentFilesList);
1078 }