Sync with trunk.
[reactos.git] / base / applications / rapps / winmain.c
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/winmain.c
5 * PURPOSE: Main program
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 */
8
9 #include "rapps.h"
10
11 #include <shellapi.h>
12
13 #define SEARCH_TIMER_ID 'SR'
14
15 HWND hMainWnd;
16 HINSTANCE hInst;
17 HIMAGELIST hImageTreeView = NULL;
18 INT SelectedEnumType = ENUM_ALL_COMPONENTS;
19 SETTINGS_INFO SettingsInfo;
20
21 WCHAR szSearchPattern[MAX_STR_LEN] = L"";
22 BOOL SearchEnabled = TRUE;
23
24 BOOL
25 SearchPatternMatch(PCWSTR szHaystack, PCWSTR szNeedle)
26 {
27 if (!*szNeedle)
28 return TRUE;
29 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
30 return StrStrIW(szHaystack, szNeedle) != NULL;
31 }
32
33 VOID
34 FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
35 {
36 pSettingsInfo->bSaveWndPos = TRUE;
37 pSettingsInfo->bUpdateAtStart = FALSE;
38 pSettingsInfo->bLogEnabled = TRUE;
39 StringCbCopyW(pSettingsInfo->szDownloadDir,
40 sizeof(pSettingsInfo->szDownloadDir),
41 L"C:\\Downloads");
42 pSettingsInfo->bDelInstaller = FALSE;
43
44 pSettingsInfo->Maximized = FALSE;
45 pSettingsInfo->Left = 0;
46 pSettingsInfo->Top = 0;
47 pSettingsInfo->Right = 680;
48 pSettingsInfo->Bottom = 450;
49 }
50
51 static BOOL
52 LoadSettings(VOID)
53 {
54 HKEY hKey;
55 DWORD dwSize;
56
57 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
58 {
59 dwSize = sizeof(SETTINGS_INFO);
60 if (RegQueryValueExW(hKey, L"Settings", NULL, NULL, (LPBYTE)&SettingsInfo, &dwSize) == ERROR_SUCCESS)
61 {
62 RegCloseKey(hKey);
63 return TRUE;
64 }
65
66 RegCloseKey(hKey);
67 }
68
69 return FALSE;
70 }
71
72 VOID
73 SaveSettings(HWND hwnd)
74 {
75 WINDOWPLACEMENT wp;
76 HKEY hKey;
77
78 if (SettingsInfo.bSaveWndPos)
79 {
80 wp.length = sizeof(WINDOWPLACEMENT);
81 GetWindowPlacement(hwnd, &wp);
82
83 SettingsInfo.Left = wp.rcNormalPosition.left;
84 SettingsInfo.Top = wp.rcNormalPosition.top;
85 SettingsInfo.Right = wp.rcNormalPosition.right;
86 SettingsInfo.Bottom = wp.rcNormalPosition.bottom;
87 SettingsInfo.Maximized = (IsZoomed(hwnd) || (wp.flags & WPF_RESTORETOMAXIMIZED));
88 }
89
90 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\ReactOS\\rapps", 0, NULL,
91 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
92 {
93 RegSetValueExW(hKey, L"Settings", 0, REG_BINARY, (LPBYTE)&SettingsInfo, sizeof(SETTINGS_INFO));
94 RegCloseKey(hKey);
95 }
96 }
97
98 VOID
99 FreeInstalledAppList(VOID)
100 {
101 INT Count = ListView_GetItemCount(hListView) - 1;
102 PINSTALLED_INFO Info;
103
104 while (Count >= 0)
105 {
106 Info = ListViewGetlParam(Count);
107 if (Info)
108 {
109 RegCloseKey(Info->hSubKey);
110 HeapFree(GetProcessHeap(), 0, Info);
111 }
112 Count--;
113 }
114 }
115
116 BOOL
117 CALLBACK
118 EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, PINSTALLED_INFO Info)
119 {
120 PINSTALLED_INFO ItemInfo;
121 WCHAR szText[MAX_PATH];
122 INT Index;
123
124 if (!SearchPatternMatch(lpName, szSearchPattern))
125 return TRUE;
126
127 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
128 if (!ItemInfo) return FALSE;
129
130 RtlCopyMemory(ItemInfo, Info, sizeof(INSTALLED_INFO));
131
132 Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM)ItemInfo);
133
134 /* Get version info */
135 GetApplicationString(ItemInfo->hSubKey, L"DisplayVersion", szText);
136 ListView_SetItemText(hListView, Index, 1, szText);
137 /* Get comments */
138 GetApplicationString(ItemInfo->hSubKey, L"Comments", szText);
139 ListView_SetItemText(hListView, Index, 2, szText);
140
141 return TRUE;
142 }
143
144 VOID
145 FreeAvailableAppList(VOID)
146 {
147 INT Count = ListView_GetItemCount(hListView) - 1;
148 PVOID Info;
149
150 while (Count >= 0)
151 {
152 Info = ListViewGetlParam(Count);
153 if (Info)
154 HeapFree(GetProcessHeap(), 0, Info);
155 Count--;
156 }
157 }
158
159 BOOL
160 CALLBACK
161 EnumAvailableAppProc(PAPPLICATION_INFO Info)
162 {
163 PAPPLICATION_INFO ItemInfo;
164 INT Index;
165
166 if (!SearchPatternMatch(Info->szName, szSearchPattern) &&
167 !SearchPatternMatch(Info->szDesc, szSearchPattern))
168 {
169 return TRUE;
170 }
171
172 /* Only add a ListView entry if...
173 - no RegName was supplied (so we cannot determine whether the application is installed or not) or
174 - a RegName was supplied and the application is not installed
175 */
176 if (!*Info->szRegName || (!IsInstalledApplication(Info->szRegName, FALSE) && !IsInstalledApplication(Info->szRegName, TRUE)))
177 {
178 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_INFO));
179 if (!ItemInfo) return FALSE;
180
181 RtlCopyMemory(ItemInfo, Info, sizeof(APPLICATION_INFO));
182
183 Index = ListViewAddItem(Info->Category, 0, Info->szName, (LPARAM)ItemInfo);
184 ListView_SetItemText(hListView, Index, 1, Info->szVersion);
185 ListView_SetItemText(hListView, Index, 2, Info->szDesc);
186 }
187
188 return TRUE;
189 }
190
191 VOID
192 UpdateApplicationsList(INT EnumType)
193 {
194 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
195 HICON hIcon;
196 HIMAGELIST hImageListView;
197
198 (VOID) ListView_DeleteAllItems(hListView);
199
200 /* Create image list */
201 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
202 LISTVIEW_ICON_SIZE,
203 GetSystemColorDepth() | ILC_MASK,
204 0, 1);
205
206 hIcon = LoadImage(hInst,
207 MAKEINTRESOURCE(IDI_MAIN),
208 IMAGE_ICON,
209 LISTVIEW_ICON_SIZE,
210 LISTVIEW_ICON_SIZE,
211 LR_CREATEDIBSECTION);
212
213 ImageList_AddIcon(hImageListView, hIcon);
214 DestroyIcon(hIcon);
215
216 if (EnumType == -1) EnumType = SelectedEnumType;
217
218 if (IS_INSTALLED_ENUM(SelectedEnumType))
219 FreeInstalledAppList();
220 else if (IS_AVAILABLE_ENUM(SelectedEnumType))
221 FreeAvailableAppList();
222
223 if (IS_INSTALLED_ENUM(EnumType))
224 {
225 /* Enum installed applications and updates */
226 EnumInstalledApplications(EnumType, TRUE, EnumInstalledAppProc);
227 EnumInstalledApplications(EnumType, FALSE, EnumInstalledAppProc);
228 }
229 else if (IS_AVAILABLE_ENUM(EnumType))
230 {
231 /* Enum availabled applications */
232 EnumAvailableApplications(EnumType, EnumAvailableAppProc);
233 }
234
235 /* Set image list for ListView */
236 hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
237
238 /* Destroy old image list */
239 if (hImageListView)
240 ImageList_Destroy(hImageListView);
241
242 SelectedEnumType = EnumType;
243
244 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
245 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
246 szBuffer2,
247 ListView_GetItemCount(hListView));
248 SetStatusBarText(szBuffer1);
249
250 SetWelcomeText();
251 }
252
253 VOID
254 InitApplicationsList(VOID)
255 {
256 WCHAR szText[MAX_STR_LEN];
257
258 /* Add columns to ListView */
259 LoadStringW(hInst, IDS_APP_NAME, szText, sizeof(szText) / sizeof(WCHAR));
260 ListViewAddColumn(0, szText, 200, LVCFMT_LEFT);
261
262 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, sizeof(szText) / sizeof(WCHAR));
263 ListViewAddColumn(1, szText, 90, LVCFMT_RIGHT);
264
265 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, sizeof(szText) / sizeof(WCHAR));
266 ListViewAddColumn(3, szText, 250, LVCFMT_LEFT);
267
268 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
269 }
270
271 HTREEITEM
272 AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
273 {
274 WCHAR szText[MAX_STR_LEN];
275 INT Index;
276 HICON hIcon;
277
278 hIcon = LoadImage(hInst,
279 MAKEINTRESOURCE(IconIndex),
280 IMAGE_ICON,
281 TREEVIEW_ICON_SIZE,
282 TREEVIEW_ICON_SIZE,
283 LR_CREATEDIBSECTION);
284
285 Index = ImageList_AddIcon(hImageTreeView, hIcon);
286 DestroyIcon(hIcon);
287
288 LoadStringW(hInst, TextIndex, szText, sizeof(szText) / sizeof(TCHAR));
289
290 return TreeViewAddItem(hRootItem, szText, Index, Index, TextIndex);
291 }
292
293 VOID
294 InitCategoriesList(VOID)
295 {
296 HTREEITEM hRootItem1, hRootItem2;
297
298 /* Create image list */
299 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE,
300 TREEVIEW_ICON_SIZE,
301 GetSystemColorDepth() | ILC_MASK,
302 0, 1);
303
304 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
305 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
306 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
307
308 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
309 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
310 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
311 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
312 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
313 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
314 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
315 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
316 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
317 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
318 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
319 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
320 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
321 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
322 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
323 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
324
325 (VOID) TreeView_SetImageList(hTreeView, hImageTreeView, TVSIL_NORMAL);
326
327 (VOID) TreeView_Expand(hTreeView, hRootItem2, TVE_EXPAND);
328 (VOID) TreeView_Expand(hTreeView, hRootItem1, TVE_EXPAND);
329
330 (VOID) TreeView_SelectItem(hTreeView, hRootItem1);
331 }
332
333 BOOL
334 InitControls(HWND hwnd)
335 {
336 if (SettingsInfo.bSaveWndPos)
337 {
338 MoveWindow(hwnd, SettingsInfo.Left, SettingsInfo.Top,
339 SettingsInfo.Right - SettingsInfo.Left,
340 SettingsInfo.Bottom - SettingsInfo.Top, TRUE);
341
342 if (SettingsInfo.Maximized) ShowWindow(hwnd, SW_MAXIMIZE);
343 }
344
345 if (CreateStatusBar(hwnd) &&
346 CreateToolBar(hwnd) &&
347 CreateListView(hwnd) &&
348 CreateTreeView(hwnd) &&
349 CreateRichEdit(hwnd) &&
350 CreateVSplitBar(hwnd) &&
351 CreateHSplitBar(hwnd))
352 {
353 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
354
355 InitApplicationsList();
356
357 InitCategoriesList();
358
359 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
360 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
361 szBuffer2,
362 ListView_GetItemCount(hListView));
363 SetStatusBarText(szBuffer1);
364 return TRUE;
365 }
366
367 return FALSE;
368 }
369
370 VOID CALLBACK
371 SearchTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
372 {
373 KillTimer(hwnd, SEARCH_TIMER_ID);
374 UpdateApplicationsList(-1);
375 }
376
377 VOID
378 MainWndOnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
379 {
380 WORD wCommand = LOWORD(wParam);
381
382 if (lParam == (LPARAM)hSearchBar)
383 {
384 WCHAR szBuf[MAX_STR_LEN];
385
386 switch (HIWORD(wParam))
387 {
388 case EN_SETFOCUS:
389 {
390 WCHAR szWndText[MAX_STR_LEN];
391
392 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
393 GetWindowTextW(hSearchBar, szWndText, MAX_STR_LEN);
394 if (wcscmp(szBuf, szWndText) == 0)
395 {
396 SearchEnabled = FALSE;
397 SetWindowTextW(hSearchBar, L"");
398 }
399 }
400 break;
401
402 case EN_KILLFOCUS:
403 {
404 GetWindowTextW(hSearchBar, szBuf, MAX_STR_LEN);
405 if (wcslen(szBuf) < 1)
406 {
407 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
408 SearchEnabled = FALSE;
409 SetWindowTextW(hSearchBar, szBuf);
410 }
411 }
412 break;
413
414 case EN_CHANGE:
415 {
416 WCHAR szWndText[MAX_STR_LEN];
417
418 if (!SearchEnabled)
419 {
420 SearchEnabled = TRUE;
421 break;
422 }
423
424 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
425 GetWindowTextW(hSearchBar, szWndText, MAX_STR_LEN);
426 if (wcscmp(szBuf, szWndText) != 0)
427 {
428 StringCbCopy(szSearchPattern, sizeof(szSearchPattern),
429 szWndText);
430 }
431 else
432 {
433 szSearchPattern[0] = UNICODE_NULL;
434 }
435
436 SetTimer(hwnd, SEARCH_TIMER_ID, 250, SearchTimerProc);
437 }
438 break;
439 }
440
441 return;
442 }
443
444 switch (wCommand)
445 {
446 case ID_OPEN_LINK:
447 ShellExecuteW(hwnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
448 HeapFree(GetProcessHeap(), 0, pLink);
449 break;
450
451 case ID_COPY_LINK:
452 CopyTextToClipboard(pLink);
453 HeapFree(GetProcessHeap(), 0, pLink);
454 break;
455
456 case ID_SETTINGS:
457 CreateSettingsDlg(hwnd);
458 break;
459
460 case ID_EXIT:
461 PostMessageW(hwnd, WM_CLOSE, 0, 0);
462 break;
463
464 case ID_INSTALL:
465 if (DownloadApplication(-1))
466 /* TODO: Implement install dialog
467 * if (InstallApplication(-1))
468 */
469 UpdateApplicationsList(-1);
470 break;
471
472 case ID_UNINSTALL:
473 if (UninstallApplication(-1, FALSE))
474 UpdateApplicationsList(-1);
475 break;
476
477 case ID_MODIFY:
478 if (UninstallApplication(-1, TRUE))
479 UpdateApplicationsList(-1);
480 break;
481
482 case ID_REGREMOVE:
483 RemoveAppFromRegistry(-1);
484 break;
485
486 case ID_REFRESH:
487 UpdateApplicationsList(-1);
488 break;
489
490 case ID_RESETDB:
491 UpdateAppsDB();
492 UpdateApplicationsList(-1);
493 break;
494
495 case ID_HELP:
496 MessageBoxW(hwnd, L"Help not implemented yet", NULL, MB_OK);
497 break;
498
499 case ID_ABOUT:
500 ShowAboutDialog();
501 break;
502 }
503 }
504
505 VOID
506 MainWndOnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
507 {
508 HDWP hdwp = BeginDeferWindowPos(5);
509 INT SearchBarWidth = GetWindowWidth(hSearchBar);
510 INT RichPos = GetWindowHeight(hRichEdit);
511 INT NewPos = HIWORD(lParam) - (RichPos + SPLIT_WIDTH + GetWindowHeight(hStatusBar));
512 INT VSplitterPos;
513
514 /* Size status bar */
515 SendMessage(hStatusBar, WM_SIZE, 0, 0);
516
517 /* Size tool bar */
518 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
519
520 /* Size SearchBar */
521 MoveWindow(hSearchBar, LOWORD(lParam) - SearchBarWidth - 4, 5, SearchBarWidth, 22, TRUE);
522
523 /*
524 * HIWORD(lParam) - Height of main window
525 * LOWORD(lParam) - Width of main window
526 */
527
528 /* Size vertical splitter bar */
529 DeferWindowPos(hdwp,
530 hVSplitter,
531 0,
532 (VSplitterPos = GetWindowWidth(hTreeView)),
533 GetWindowHeight(hToolBar),
534 SPLIT_WIDTH,
535 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
536 SWP_NOZORDER|SWP_NOACTIVATE);
537
538 /* Size TreeView */
539 DeferWindowPos(hdwp,
540 hTreeView,
541 0,
542 0,
543 GetWindowHeight(hToolBar),
544 VSplitterPos,
545 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
546 SWP_NOZORDER|SWP_NOACTIVATE);
547
548 while (NewPos < SPLIT_WIDTH + GetWindowHeight(hToolBar))
549 {
550 RichPos--;
551 NewPos = HIWORD(lParam) - (RichPos +
552 SPLIT_WIDTH + GetWindowHeight(hStatusBar));
553 }
554 SetHSplitterPos(NewPos);
555
556 /* Size ListView */
557 DeferWindowPos(hdwp,
558 hListView,
559 0,
560 VSplitterPos + SPLIT_WIDTH,
561 GetWindowHeight(hToolBar),
562 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
563 GetHSplitterPos() - GetWindowHeight(hToolBar),
564 SWP_NOZORDER|SWP_NOACTIVATE);
565
566 /* Size RichEdit */
567 DeferWindowPos(hdwp,
568 hRichEdit,
569 0,
570 VSplitterPos + SPLIT_WIDTH,
571 GetHSplitterPos() + SPLIT_WIDTH,
572 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
573 RichPos,
574 SWP_NOZORDER|SWP_NOACTIVATE);
575
576 /* Size horizontal splitter bar */
577 DeferWindowPos(hdwp,
578 hHSplitter,
579 0,
580 VSplitterPos + SPLIT_WIDTH,
581 GetHSplitterPos(),
582 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
583 SPLIT_WIDTH,
584 SWP_NOZORDER|SWP_NOACTIVATE);
585
586 EndDeferWindowPos(hdwp);
587 }
588
589 BOOL IsSelectedNodeInstalled(void)
590 {
591 HTREEITEM hSelectedItem = TreeView_GetSelection(hTreeView);
592 TV_ITEM tItem;
593
594 tItem.mask = TVIF_PARAM | TVIF_HANDLE;
595 tItem.hItem = hSelectedItem;
596 TreeView_GetItem(hTreeView, &tItem);
597 switch (tItem.lParam)
598 {
599 case IDS_INSTALLED:
600 case IDS_APPLICATIONS:
601 case IDS_UPDATES:
602 return TRUE;
603 default:
604 return FALSE;
605 }
606 }
607
608 LRESULT CALLBACK
609 MainWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
610 {
611 switch (Msg)
612 {
613 case WM_CREATE:
614 if (!InitControls(hwnd))
615 PostMessage(hwnd, WM_CLOSE, 0, 0);
616
617 break;
618
619 case WM_COMMAND:
620 MainWndOnCommand(hwnd, wParam, lParam);
621 break;
622
623 case WM_NOTIFY:
624 {
625 LPNMHDR data = (LPNMHDR)lParam;
626
627 switch (data->code)
628 {
629 case TVN_SELCHANGED:
630 {
631 if (data->hwndFrom == hTreeView)
632 {
633 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam)
634 {
635 case IDS_INSTALLED:
636 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
637 break;
638
639 case IDS_APPLICATIONS:
640 UpdateApplicationsList(ENUM_APPLICATIONS);
641 break;
642
643 case IDS_UPDATES:
644 UpdateApplicationsList(ENUM_UPDATES);
645 break;
646
647 case IDS_AVAILABLEFORINST:
648 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
649 break;
650
651 case IDS_CAT_AUDIO:
652 UpdateApplicationsList(ENUM_CAT_AUDIO);
653 break;
654
655 case IDS_CAT_DEVEL:
656 UpdateApplicationsList(ENUM_CAT_DEVEL);
657 break;
658
659 case IDS_CAT_DRIVERS:
660 UpdateApplicationsList(ENUM_CAT_DRIVERS);
661 break;
662
663 case IDS_CAT_EDU:
664 UpdateApplicationsList(ENUM_CAT_EDU);
665 break;
666
667 case IDS_CAT_ENGINEER:
668 UpdateApplicationsList(ENUM_CAT_ENGINEER);
669 break;
670
671 case IDS_CAT_FINANCE:
672 UpdateApplicationsList(ENUM_CAT_FINANCE);
673 break;
674
675 case IDS_CAT_GAMES:
676 UpdateApplicationsList(ENUM_CAT_GAMES);
677 break;
678
679 case IDS_CAT_GRAPHICS:
680 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
681 break;
682
683 case IDS_CAT_INTERNET:
684 UpdateApplicationsList(ENUM_CAT_INTERNET);
685 break;
686
687 case IDS_CAT_LIBS:
688 UpdateApplicationsList(ENUM_CAT_LIBS);
689 break;
690
691 case IDS_CAT_OFFICE:
692 UpdateApplicationsList(ENUM_CAT_OFFICE);
693 break;
694
695 case IDS_CAT_OTHER:
696 UpdateApplicationsList(ENUM_CAT_OTHER);
697 break;
698
699 case IDS_CAT_SCIENCE:
700 UpdateApplicationsList(ENUM_CAT_SCIENCE);
701 break;
702
703 case IDS_CAT_TOOLS:
704 UpdateApplicationsList(ENUM_CAT_TOOLS);
705 break;
706
707 case IDS_CAT_VIDEO:
708 UpdateApplicationsList(ENUM_CAT_VIDEO);
709 break;
710 }
711 }
712
713 /* Disable/enable items based on treeview selection */
714 if (IsSelectedNodeInstalled())
715 {
716 EnableMenuItem(GetMenu(hwnd), ID_REGREMOVE, MF_ENABLED);
717 EnableMenuItem(GetMenu(hwnd), ID_INSTALL, MF_GRAYED);
718 EnableMenuItem(GetMenu(hwnd), ID_UNINSTALL, MF_ENABLED);
719 EnableMenuItem(GetMenu(hwnd), ID_MODIFY, MF_ENABLED);
720
721 EnableMenuItem(GetMenu(hListView), ID_REGREMOVE, MF_ENABLED);
722 EnableMenuItem(GetMenu(hListView), ID_INSTALL, MF_GRAYED);
723 EnableMenuItem(GetMenu(hListView), ID_UNINSTALL, MF_ENABLED);
724 EnableMenuItem(GetMenu(hListView), ID_MODIFY, MF_ENABLED);
725
726 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
727 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_INSTALL, FALSE);
728 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
729 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_MODIFY, TRUE);
730 }
731 else
732 {
733 EnableMenuItem(GetMenu(hwnd), ID_REGREMOVE, MF_GRAYED);
734 EnableMenuItem(GetMenu(hwnd), ID_INSTALL, MF_ENABLED);
735 EnableMenuItem(GetMenu(hwnd), ID_UNINSTALL, MF_GRAYED);
736 EnableMenuItem(GetMenu(hwnd), ID_MODIFY, MF_GRAYED);
737
738 EnableMenuItem(GetMenu(hListView), ID_REGREMOVE, MF_GRAYED);
739 EnableMenuItem(GetMenu(hListView), ID_INSTALL, MF_ENABLED);
740 EnableMenuItem(GetMenu(hListView), ID_UNINSTALL, MF_GRAYED);
741 EnableMenuItem(GetMenu(hListView), ID_MODIFY, MF_GRAYED);
742
743 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
744 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_INSTALL, TRUE);
745 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
746 SendMessage(hToolBar, TB_ENABLEBUTTON, ID_MODIFY, FALSE);
747 }
748 }
749 break;
750
751 case LVN_ITEMCHANGED:
752 {
753 LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
754
755 if (pnic->hdr.hwndFrom == hListView)
756 {
757 /* Check if this is a valid item
758 * (technically, it can be also an unselect) */
759 INT ItemIndex = pnic->iItem;
760 if (ItemIndex == -1 ||
761 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
762 {
763 break;
764 }
765
766 /* Check if the focus has been moved to another item */
767 if ((pnic->uChanged & LVIF_STATE) &&
768 (pnic->uNewState & LVIS_FOCUSED) &&
769 !(pnic->uOldState & LVIS_FOCUSED))
770 {
771 if (IS_INSTALLED_ENUM(SelectedEnumType))
772 ShowInstalledAppInfo(ItemIndex);
773 if (IS_AVAILABLE_ENUM(SelectedEnumType))
774 ShowAvailableAppInfo(ItemIndex);
775 }
776 }
777 }
778 break;
779
780 case LVN_COLUMNCLICK:
781 {
782 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
783
784 (VOID) ListView_SortItems(hListView, ListViewCompareFunc, pnmv->iSubItem);
785 bAscending = !bAscending;
786 }
787 break;
788
789 case NM_CLICK:
790 {
791 if (data->hwndFrom == hListView && ((LPNMLISTVIEW)lParam)->iItem != -1)
792 {
793 if (IS_INSTALLED_ENUM(SelectedEnumType))
794 ShowInstalledAppInfo(-1);
795 if (IS_AVAILABLE_ENUM(SelectedEnumType))
796 ShowAvailableAppInfo(-1);
797 }
798 }
799 break;
800
801 case NM_DBLCLK:
802 {
803 if (data->hwndFrom == hListView && ((LPNMLISTVIEW)lParam)->iItem != -1)
804 {
805 SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0); //Won't do anything if the program is already installed
806 }
807 }
808 break;
809
810 case NM_RCLICK:
811 {
812 if (data->hwndFrom == hListView && ((LPNMLISTVIEW)lParam)->iItem != -1)
813 {
814 ShowPopupMenu(hListView, 0, ID_INSTALL);
815 }
816 }
817 break;
818
819 case EN_LINK:
820 RichEditOnLink(hwnd, (ENLINK*)lParam);
821 break;
822
823 case TTN_GETDISPINFO:
824 ToolBarOnGetDispInfo((LPTOOLTIPTEXT)lParam);
825 break;
826 }
827 }
828 break;
829
830 case WM_PAINT:
831 break;
832
833 case WM_SIZE:
834 {
835 if ((GetClientWindowHeight(hMainWnd) - GetWindowHeight(hStatusBar) - SPLIT_WIDTH) < GetHSplitterPos())
836 {
837 INT NewSplitPos = GetClientWindowHeight(hwnd) - 100 - GetWindowHeight(hStatusBar) - SPLIT_WIDTH;
838 if (NewSplitPos > GetWindowHeight(hToolBar) + SPLIT_WIDTH)
839 SetHSplitterPos(NewSplitPos);
840 }
841
842 MainWndOnSize(hwnd, wParam, lParam);
843 }
844 break;
845
846 case WM_SIZING:
847 {
848 int RichEditHeight = GetWindowHeight(hRichEdit);
849 LPRECT pRect = (LPRECT)lParam;
850
851 while (RichEditHeight <= 100)
852 {
853 if (GetHSplitterPos() - 1 < GetWindowHeight(hToolBar) + GetWindowHeight(hListView) + SPLIT_WIDTH)
854 break;
855 SetHSplitterPos(GetHSplitterPos() - 1);
856 RichEditHeight++;
857 }
858
859 if (pRect->right-pRect->left < 565)
860 pRect->right = pRect->left + 565;
861
862 if (pRect->bottom-pRect->top < 300)
863 pRect->bottom = pRect->top + 300;
864 return TRUE;
865 }
866
867 case WM_SYSCOLORCHANGE:
868 {
869 /* Forward WM_SYSCOLORCHANGE to common controls */
870 SendMessage(hListView, WM_SYSCOLORCHANGE, 0, 0);
871 SendMessage(hTreeView, WM_SYSCOLORCHANGE, 0, 0);
872 SendMessage(hToolBar, WM_SYSCOLORCHANGE, 0, 0);
873 SendMessageW(hRichEdit, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
874 }
875 break;
876
877 case WM_DESTROY:
878 {
879 ShowWindow(hwnd, SW_HIDE);
880 SaveSettings(hwnd);
881
882 FreeLogs();
883
884 if (IS_AVAILABLE_ENUM(SelectedEnumType))
885 FreeAvailableAppList();
886 if (IS_INSTALLED_ENUM(SelectedEnumType))
887 FreeInstalledAppList();
888 if (hImageTreeView) ImageList_Destroy(hImageTreeView);
889
890 PostQuitMessage(0);
891 return 0;
892 }
893 break;
894 }
895
896 return DefWindowProc(hwnd, Msg, wParam, lParam);
897 }
898
899 int WINAPI
900 wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
901 {
902 WNDCLASSEXW WndClass = {0};
903 WCHAR szWindowClass[] = L"ROSAPPMGR";
904 WCHAR szWindowName[MAX_STR_LEN];
905 HANDLE hMutex = NULL;
906 MSG Msg;
907
908 switch (GetUserDefaultUILanguage())
909 {
910 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
911 SetProcessDefaultLayout(LAYOUT_RTL);
912 break;
913
914 default:
915 break;
916 }
917
918 hInst = hInstance;
919
920 hMutex = CreateMutexW(NULL, FALSE, szWindowClass);
921 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
922 {
923 /* If already started, it is found its window */
924 HWND hWindow = FindWindowW(szWindowClass, NULL);
925
926 /* Activate window */
927 ShowWindow(hWindow, SW_SHOWNORMAL);
928 SetForegroundWindow(hWindow);
929 return 1;
930 }
931
932 if (!LoadSettings())
933 {
934 FillDefaultSettings(&SettingsInfo);
935 }
936
937 InitLogs();
938
939 InitCommonControls();
940
941 /* Create the window */
942 WndClass.cbSize = sizeof(WNDCLASSEXW);
943 WndClass.lpszClassName = szWindowClass;
944 WndClass.lpfnWndProc = MainWindowProc;
945 WndClass.hInstance = hInstance;
946 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
947 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
948 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
949 WndClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
950
951 if (RegisterClassExW(&WndClass) == (ATOM)0) goto Exit;
952
953 LoadStringW(hInst, IDS_APPTITLE, szWindowName, sizeof(szWindowName) / sizeof(WCHAR));
954
955 hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
956 szWindowClass,
957 szWindowName,
958 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
959 CW_USEDEFAULT,
960 CW_USEDEFAULT,
961 680,
962 450,
963 NULL,
964 NULL,
965 hInstance,
966 NULL);
967
968 if (!hMainWnd) goto Exit;
969
970 /* Show it */
971 ShowWindow(hMainWnd, nShowCmd);
972 UpdateWindow(hMainWnd);
973
974 if (SettingsInfo.bUpdateAtStart)
975 UpdateAppsDB();
976
977 /* Message Loop */
978 while (GetMessage(&Msg, NULL, 0, 0))
979 {
980 TranslateMessage(&Msg);
981 DispatchMessage(&Msg);
982 }
983
984 Exit:
985 if (hMutex) CloseHandle(hMutex);
986
987 return 0;
988 }