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