[RAPPS]
[reactos.git] / reactos / base / applications / rapps / gui.cpp
index 9e4fc25..66cb10a 100644 (file)
@@ -1,10 +1,16 @@
-/* PROJECT:     ReactOS CE Applications Manager
- * LICENSE:     GPL - See COPYING in the top level directory
- * AUTHORS:     David Quintana             <gigaherz@gmail.com>
- *              Alexander Shaposhnikov     <chaez.san@gmail.com>
+/*
+ * PROJECT:     ReactOS Applications Manager
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * FILE:        base/applications/rapps/gui.cpp
+ * PURPOSE:     GUI classes for RAPPS
+ * COPYRIGHT:   Copyright 2015 David Quintana           (gigaherz@gmail.com)
+ *              Copyright 2017 Alexander Shaposhnikov   (sanchaez@reactos.org)
  */
+#include "rapps.h"
 
 #include "rapps.h"
+#include "rosui.h"
+#include "crichedit.h"
 
 #include <shlobj_undoc.h>
 #include <shlguid_undoc.h>
 #include <atlwin.h>
 #include <wininet.h>
 #include <shellutils.h>
-
 #include <rosctrls.h>
 
-#include "rosui.h"
-#include "crichedit.h"
-
 #define SEARCH_TIMER_ID 'SR'
+#define LISTVIEW_ICON_SIZE 24
+#define TREEVIEW_ICON_SIZE 24
 
 HWND hListView = NULL;
 
+INT GetSystemColorDepth()
+{
+    DEVMODEW pDevMode;
+    INT ColorDepth;
+
+    pDevMode.dmSize = sizeof(pDevMode);
+    pDevMode.dmDriverExtra = 0;
+
+    if (!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &pDevMode))
+    {
+        /* TODO: Error message */
+        return ILC_COLOR;
+    }
+
+    switch (pDevMode.dmBitsPerPel)
+    {
+    case 32: ColorDepth = ILC_COLOR32; break;
+    case 24: ColorDepth = ILC_COLOR24; break;
+    case 16: ColorDepth = ILC_COLOR16; break;
+    case  8: ColorDepth = ILC_COLOR8;  break;
+    case  4: ColorDepth = ILC_COLOR4;  break;
+    default: ColorDepth = ILC_COLOR;   break;
+    }
+
+    return ColorDepth;
+}
+
 class CAvailableAppView
 {
     static inline VOID InsertTextAfterLoaded_RichEdit(UINT uStringID,
@@ -32,7 +63,7 @@ class CAvailableAppView
                                                       DWORD TextFlags)
     {
         ATL::CStringW szLoadedText;
-        if (!szText.IsEmpty() && szLoadedText.LoadStringW(hInst, uStringID))
+        if (!szText.IsEmpty() && szLoadedText.LoadStringW(uStringID))
         {
             InsertRichEditText(szLoadedText, StringFlags);
             InsertRichEditText(szText, TextFlags);
@@ -43,7 +74,7 @@ class CAvailableAppView
                                                      DWORD StringFlags)
     {
         ATL::CStringW szLoadedText;
-        if (szLoadedText.LoadStringW(hInst, uStringID))
+        if (szLoadedText.LoadStringW(uStringID))
         {
             InsertRichEditText(L"\n", 0);
             InsertRichEditText(szLoadedText, StringFlags);
@@ -62,7 +93,7 @@ class CAvailableAppView
                 else
                     InsertLoadedTextNewl_RichEdit(IDS_STATUS_INSTALLED, CFE_ITALIC);
 
-                InsertTextAfterLoaded_RichEdit(IDS_AINFO_VERSION, Info->szInstalledVersion, CFE_BOLD, 0);
+                InsertTextAfterLoaded_RichEdit(IDS_AINFO_VERSION, Info->m_szInstalledVersion, CFE_BOLD, 0);
             }
             else
             {
@@ -74,29 +105,29 @@ class CAvailableAppView
             InsertLoadedTextNewl_RichEdit(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
         }
 
-        InsertTextAfterLoaded_RichEdit(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_AVAILABLEVERSION, Info->m_szVersion, CFE_BOLD, 0);
     }
 
     static VOID InsertLicenseInfo_RichEdit(CAvailableApplicationInfo* Info)
     {
         ATL::CStringW szLicense;
-        switch (Info->LicenseType)
+        switch (Info->m_LicenseType)
         {
-        case LICENSE_TYPE::OpenSource:
-            szLicense.LoadStringW(hInst, IDS_LICENSE_OPENSOURCE);
+        case LICENSE_OPENSOURCE:
+            szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE);
             break;
-        case LICENSE_TYPE::Freeware:
-            szLicense.LoadStringW(hInst, IDS_LICENSE_FREEWARE);
+        case LICENSE_FREEWARE:
+            szLicense.LoadStringW(IDS_LICENSE_FREEWARE);
             break;
-        case LICENSE_TYPE::Trial:
-            szLicense.LoadStringW(hInst, IDS_LICENSE_TRIAL);
+        case LICENSE_TRIAL:
+            szLicense.LoadStringW(IDS_LICENSE_TRIAL);
             break;
         default:
-            InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
+            InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, Info->m_szLicense, CFE_BOLD, 0);
             return;
         }
 
-        szLicense += L" (" + Info->szLicense + L")";
+        szLicense += L" (" + Info->m_szLicense + L")";
         InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0);
     }
 
@@ -107,7 +138,7 @@ class CAvailableAppView
             return;
         }
 
-        const INT nTranslations = Info->Languages.GetSize();
+        const INT nTranslations = Info->m_LanguageLCIDs.GetSize();
         ATL::CStringW szLangInfo;
         ATL::CStringW szLoadedTextAvailability;
         ATL::CStringW szLoadedAInfoText;
@@ -120,7 +151,9 @@ class CAvailableAppView
             szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
             if (nTranslations > 1)
             {
-                szLangInfo.Format(L" (+%d more)", nTranslations - 1);
+                ATL::CStringW buf;
+                buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER);
+                szLangInfo.Format(buf, nTranslations - 1);
             }
             else
             {
@@ -133,7 +166,9 @@ class CAvailableAppView
             szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
             if (nTranslations > 1)
             {
-                szLangInfo.Format(L" (+%d available)", nTranslations - 1);
+                ATL::CStringW buf;
+                buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER);
+                szLangInfo.Format(buf, nTranslations - 1);
             }
             else
             {
@@ -157,15 +192,15 @@ public:
         CAvailableApplicationInfo* Info = (CAvailableApplicationInfo*) ListViewGetlParam(Index);
         if (!Info) return FALSE;
 
-        NewRichEditText(Info->szName, CFE_BOLD);
+        NewRichEditText(Info->m_szName, CFE_BOLD);
         InsertVersionInfo_RichEdit(Info);
         InsertLicenseInfo_RichEdit(Info);
         InsertLanguageInfo_RichEdit(Info);
 
-        InsertTextAfterLoaded_RichEdit(IDS_AINFO_SIZE, Info->szSize, CFE_BOLD, 0);
-        InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLSITE, Info->szUrlSite, CFE_BOLD, CFE_LINK);
-        InsertTextAfterLoaded_RichEdit(IDS_AINFO_DESCRIPTION, Info->szDesc, CFE_BOLD, 0);
-        InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLDOWNLOAD, Info->szUrlDownload, CFE_BOLD, CFE_LINK);
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_SIZE, Info->m_szSize, CFE_BOLD, 0);
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLSITE, Info->m_szUrlSite, CFE_BOLD, CFE_LINK);
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_DESCRIPTION, Info->m_szDesc, CFE_BOLD, 0);
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_URLDOWNLOAD, Info->m_szUrlDownload, CFE_BOLD, CFE_LINK);
 
         return TRUE;
     }
@@ -207,8 +242,7 @@ class CMainToolbar :
         hImageList = ImageList_Create(TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CXSMICON),
                                       TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CYSMICON),
                                       ILC_MASK | GetSystemColorDepth(),
-                                      1,
-                                      1);
+                                      1, 1);
         if (!hImageList)
         {
             /* TODO: Error message */
@@ -274,7 +308,7 @@ public:
             { 0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szInstallBtn },
             { 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szUninstallBtn },
             { 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szModifyBtn },
-            { 3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE,{0}, 0, (INT_PTR) szSelectAll},
+            { 3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szSelectAll},
             {-1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
             { 4, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
             { 5, ID_RESETDB,   TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
@@ -325,19 +359,35 @@ class CAppsListView :
     struct SortContext
     {
         CAppsListView * lvw;
-        int iSubItem;
+        INT iSubItem;
     };
 
     BOOL bHasAllChecked;
     BOOL bAscending;
+    BOOL bHasCheckboxes;
 
 public:
     CAppsListView() :
+        bHasAllChecked(FALSE),
         bAscending(TRUE),
-        bHasAllChecked(FALSE)
+        bHasCheckboxes(FALSE)
     {
     }
 
+    VOID SetCheckboxesVisible(BOOL bIsVisible)
+    {
+        if (bIsVisible)
+        {
+            SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+        }
+        else
+        {
+            SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
+        }
+
+        bHasCheckboxes = bIsVisible;
+    }
+
     VOID ColumnClick(LPNMLISTVIEW pnmv)
     {
         SortContext ctx = {this, pnmv->iSubItem};
@@ -450,7 +500,7 @@ public:
 
         if (hwnd)
         {
-            SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+            SetCheckboxesVisible(FALSE);
         }
 
         return hwnd;
@@ -463,44 +513,61 @@ public:
 
     VOID SetCheckState(INT item, BOOL fCheck)
     {
-        SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
+        if (bHasCheckboxes)
+        {
+            SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
+        }
     }
 
     VOID CheckAll()
     {
-        bHasAllChecked = !bHasAllChecked;
-        SetCheckState(-1, bHasAllChecked);
+        if (bHasCheckboxes)
+        {
+            bHasAllChecked = !bHasAllChecked;
+            SetCheckState(-1, bHasAllChecked);
+        }
     }
 
-    ATL::CSimpleArray<PAPPLICATION_INFO> GetCheckedItems()
+    ATL::CSimpleArray<CAvailableApplicationInfo*> GetCheckedItems()
     {
-        ATL::CSimpleArray<PAPPLICATION_INFO> list;
+        if (!bHasCheckboxes)
+        {
+            return ATL::CSimpleArray<CAvailableApplicationInfo*>();
+        }
+
+        ATL::CSimpleArray<CAvailableApplicationInfo*> list;
         for (INT i = 0; i >= 0; i = GetNextItem(i, LVNI_ALL))
         {
             if (GetCheckState(i) != FALSE)
             {
-                PAPPLICATION_INFO pAppInfo = (PAPPLICATION_INFO) GetItemData(i);
+                CAvailableApplicationInfo* pAppInfo = (CAvailableApplicationInfo*) GetItemData(i);
                 list.Add(pAppInfo);
             }
         }
         return list;
     }
-    
-    PAPPLICATION_INFO GetSelectedData()
+
+    CAvailableApplicationInfo* GetSelectedData()
     {
         INT item = GetSelectionMark();
-        return (PAPPLICATION_INFO) GetItemData(item);
+        return (CAvailableApplicationInfo*) GetItemData(item);
     }
 };
 
 class CSideTreeView :
     public CUiWindow<CTreeView>
 {
-    HIMAGELIST hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
-                                                 GetSystemColorDepth() | ILC_MASK,
-                                                 0, 1);
+    HIMAGELIST hImageTreeView;
 
 public:
+    CSideTreeView() :
+        CUiWindow(),
+        hImageTreeView(ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
+                                        GetSystemColorDepth() | ILC_MASK,
+                                        0, 1))
+    {
+    }
+
     HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam)
     {
         return CUiWindow<CTreeView>::AddItem(hParent, const_cast<LPWSTR>(Text.GetString()), Image, SelectedImage, lParam);
@@ -512,19 +579,19 @@ public:
         INT Index;
         HICON hIcon;
 
-        hIcon = (HICON) LoadImage(hInst,
-                                  MAKEINTRESOURCE(IconIndex),
-                                  IMAGE_ICON,
-                                  TREEVIEW_ICON_SIZE,
-                                  TREEVIEW_ICON_SIZE,
-                                  LR_CREATEDIBSECTION);
+        hIcon = (HICON) LoadImageW(hInst,
+                                   MAKEINTRESOURCE(IconIndex),
+                                   IMAGE_ICON,
+                                   TREEVIEW_ICON_SIZE,
+                                   TREEVIEW_ICON_SIZE,
+                                   LR_CREATEDIBSECTION);
         if (hIcon)
         {
             Index = ImageList_AddIcon(hImageTreeView, hIcon);
             DestroyIcon(hIcon);
         }
 
-        szText.LoadStringW(hInst, TextIndex);
+        szText.LoadStringW(TextIndex);
         return AddItem(hRootItem, szText, Index, Index, TextIndex);
     }
 
@@ -542,7 +609,6 @@ public:
     ~CSideTreeView()
     {
         DestroyImageList();
-        CUiWindow<CTreeView>::~CUiWindow();
     }
 };
 
@@ -565,7 +631,7 @@ public:
                                  hInst, 0);
 
         SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
-        szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+        szBuf.LoadStringW(IDS_SEARCH_TEXT);
         SetWindowTextW(szBuf);
         return m_hWnd;
     }
@@ -575,18 +641,18 @@ public:
 class CMainWindow :
     public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
 {
-    CUiPanel * m_ClientPanel;
-    CUiSplitPanel * m_VSplitter;
-    CUiSplitPanel * m_HSplitter;
+    CUiPanel* m_ClientPanel;
+    CUiSplitPanel* m_VSplitter;
+    CUiSplitPanel* m_HSplitter;
 
-    CMainToolbar * m_Toolbar;
-    CAppsListView * m_ListView;
+    CMainToolbar* m_Toolbar;
+    CAppsListView* m_ListView;
 
-    CSideTreeView * m_TreeView;
-    CUiWindow<CStatusBar> * m_StatusBar;
-    CUiWindow<CRichEdit> * m_RichEdit;
+    CSideTreeView* m_TreeView;
+    CUiWindow<CStatusBar>* m_StatusBar;
+    CUiWindow<CRichEdit>* m_RichEdit;
 
-    CUiWindow<CSearchBar> * m_SearchBar;
+    CUiWindow<CSearchBar>* m_SearchBar;
     CAvailableApps m_AvailableApps;
 
     LPWSTR pLink;
@@ -609,13 +675,13 @@ private:
         ATL::CStringW szText;
 
         /* Add columns to ListView */
-        szText.LoadStringW(hInst, IDS_APP_NAME);
+        szText.LoadStringW(IDS_APP_NAME);
         m_ListView->AddColumn(0, szText, 200, LVCFMT_LEFT);
 
-        szText.LoadStringW(hInst, IDS_APP_INST_VERSION);
+        szText.LoadStringW(IDS_APP_INST_VERSION);
         m_ListView->AddColumn(1, szText, 90, LVCFMT_RIGHT);
 
-        szText.LoadStringW(hInst, IDS_APP_DESCRIPTION);
+        szText.LoadStringW(IDS_APP_DESCRIPTION);
         m_ListView->AddColumn(3, szText, 250, LVCFMT_LEFT);
 
         // Unnesesary since the list updates on every TreeView selection
@@ -629,28 +695,33 @@ private:
 
     VOID InitCategoriesList()
     {
-        HTREEITEM hRootItem;
-
-        hRootItem = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
-        AddCategory(hRootItem, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
-        AddCategory(hRootItem, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
-        AddCategory(hRootItem, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
-        AddCategory(hRootItem, IDS_CAT_GAMES, IDI_CAT_GAMES);
-        AddCategory(hRootItem, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
-        AddCategory(hRootItem, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
-        AddCategory(hRootItem, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
-        AddCategory(hRootItem, IDS_CAT_EDU, IDI_CAT_EDU);
-        AddCategory(hRootItem, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
-        AddCategory(hRootItem, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
-        AddCategory(hRootItem, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
-        AddCategory(hRootItem, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
-        AddCategory(hRootItem, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
-        AddCategory(hRootItem, IDS_CAT_LIBS, IDI_CAT_LIBS);
-        AddCategory(hRootItem, IDS_CAT_OTHER, IDI_CAT_OTHER);
+        HTREEITEM hRootItem1, hRootItem2;
+
+        hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
+        AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
+        AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
+
+        hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
+        AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
+        AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
+        AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
+        AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
+        AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
+        AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
+        AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
+        AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
+        AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
+        AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
+        AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
+        AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
+        AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
+        AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
+        AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
 
         m_TreeView->SetImageList();
-        m_TreeView->Expand(hRootItem, TVE_EXPAND);
-        m_TreeView->SelectItem(hRootItem);
+        m_TreeView->Expand(hRootItem1, TVE_EXPAND);
+        m_TreeView->Expand(hRootItem2, TVE_EXPAND);
+        m_TreeView->SelectItem(hRootItem1);
     }
 
     BOOL CreateStatusBar()
@@ -711,8 +782,9 @@ private:
         m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch;
         m_VSplitter->m_DynamicFirst = FALSE;
         m_VSplitter->m_Horizontal = FALSE;
-        m_VSplitter->m_MinFirst = 240;
-        m_VSplitter->m_MinSecond = 300;
+        m_VSplitter->m_MinFirst = 0;
+        m_VSplitter->m_MinSecond = 320;
+        m_VSplitter->m_Pos = 240;
         m_ClientPanel->Children().Append(m_VSplitter);
 
         return m_VSplitter->Create(m_hWnd) != NULL;
@@ -725,9 +797,9 @@ private:
         m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch;
         m_HSplitter->m_DynamicFirst = TRUE;
         m_HSplitter->m_Horizontal = TRUE;
-        m_HSplitter->m_Pos = 32768;
-        m_HSplitter->m_MinFirst = 300;
-        m_HSplitter->m_MinSecond = 150;
+        m_HSplitter->m_Pos = INT_MAX;        //set INT_MAX to use lowest possible position (m_MinSecond)
+        m_HSplitter->m_MinFirst = 10;
+        m_HSplitter->m_MinSecond = 140;
         m_VSplitter->Second().Append(m_HSplitter);
 
         return m_HSplitter->Create(m_hWnd) != NULL;
@@ -816,7 +888,7 @@ private:
 
         RECT r = {0, 0, LOWORD(lParam), HIWORD(lParam)};
         HDWP hdwp = NULL;
-        int count = m_ClientPanel->CountSizableChildren();
+        INT count = m_ClientPanel->CountSizableChildren();
 
         hdwp = BeginDeferWindowPos(count);
         if (hdwp)
@@ -857,8 +929,9 @@ private:
             SaveSettings(hwnd);
 
             FreeLogs();
+            m_AvailableApps.FreeCachedEntries();
 
-            if (IS_INSTALLED_ENUM(SelectedEnumType))
+            if (IsInstalledEnum(SelectedEnumType))
                 FreeInstalledAppList();
 
             delete m_ClientPanel;
@@ -884,11 +957,11 @@ private:
                     switch (((LPNMTREEVIEW) lParam)->itemNew.lParam)
                     {
                     case IDS_INSTALLED:
-                        UpdateApplicationsList(ENUM_ALL_COMPONENTS);
+                        UpdateApplicationsList(ENUM_ALL_INSTALLED);
                         break;
 
                     case IDS_APPLICATIONS:
-                        UpdateApplicationsList(ENUM_APPLICATIONS);
+                        UpdateApplicationsList(ENUM_INSTALLED_APPLICATIONS);
                         break;
 
                     case IDS_UPDATES:
@@ -1022,16 +1095,26 @@ private:
                         (pnic->uNewState & LVIS_FOCUSED) &&
                         !(pnic->uOldState & LVIS_FOCUSED))
                     {
-                        if (IS_INSTALLED_ENUM(SelectedEnumType))
+                        if (IsInstalledEnum(SelectedEnumType))
                             ShowInstalledAppInfo(ItemIndex);
-                        if (IS_AVAILABLE_ENUM(SelectedEnumType))
+                        if (IsAvailableEnum(SelectedEnumType))
                             CAvailableAppView::ShowAvailableAppInfo(ItemIndex);
                     }
                     /* Check if the item is checked */
                     if ((pnic->uNewState & LVIS_STATEIMAGEMASK) && !bUpdating)
                     {
                         BOOL checked = ListView_GetCheckState(pnic->hdr.hwndFrom, pnic->iItem);
-                        nSelectedApps += (checked) ? 1 : -1;
+                        /* FIXME: HAX!
+                        - preventing decremention below zero as a safeguard for ReactOS
+                          In ReactOS this action is triggered whenever user changes *selection*, but should be only when *checkbox* state toggled
+                          Maybe LVIS_STATEIMAGEMASK is set incorrectly
+                        */
+                        nSelectedApps +=
+                            (checked)
+                            ? 1
+                            : ((nSelectedApps > 0)
+                               ? -1
+                               : 0);
                         UpdateStatusBarText();
                     }
                 }
@@ -1050,9 +1133,9 @@ private:
             {
                 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
                 {
-                    if (IS_INSTALLED_ENUM(SelectedEnumType))
+                    if (IsInstalledEnum(SelectedEnumType))
                         ShowInstalledAppInfo(-1);
-                    if (IS_AVAILABLE_ENUM(SelectedEnumType))
+                    if (IsAvailableEnum(SelectedEnumType))
                         CAvailableAppView::ShowAvailableAppInfo(-1);
                 }
             }
@@ -1122,7 +1205,7 @@ private:
                 if (bSearchEnabled)
                     UpdateApplicationsList(-1);
             }
-        break;
+            break;
         }
 
         return FALSE;
@@ -1188,7 +1271,7 @@ private:
             {
                 ATL::CStringW szWndText;
 
-                szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+                szBuf.LoadStringW(IDS_SEARCH_TEXT);
                 m_SearchBar->GetWindowTextW(szWndText);
                 if (szBuf == szWndText)
                 {
@@ -1203,7 +1286,7 @@ private:
                 m_SearchBar->GetWindowTextW(szBuf);
                 if (szBuf.IsEmpty())
                 {
-                    szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+                    szBuf.LoadStringW(IDS_SEARCH_TEXT);
                     bSearchEnabled = FALSE;
                     m_SearchBar->SetWindowTextW(szBuf.GetString());
                 }
@@ -1220,7 +1303,7 @@ private:
                     break;
                 }
 
-                szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+                szBuf.LoadStringW(IDS_SEARCH_TEXT);
                 m_SearchBar->GetWindowTextW(szWndText);
                 if (szBuf == szWndText)
                 {
@@ -1262,16 +1345,19 @@ private:
             break;
 
         case ID_INSTALL:
-            if (nSelectedApps)
+            if (IsAvailableEnum(SelectedEnumType))
             {
-                СDownloadManager::DownloadListOfApplications(m_ListView->GetCheckedItems());
-                UpdateApplicationsList(-1);
-            } 
-            else if(СDownloadManager::DownloadApplication(m_ListView->GetSelectedData()))
-            {
-                UpdateApplicationsList(-1);
+                if (nSelectedApps > 0)
+                {
+                    CDownloadManager::DownloadListOfApplications(m_ListView->GetCheckedItems());
+                    UpdateApplicationsList(-1);
+                }
+                else if (CDownloadManager::DownloadApplication(m_ListView->GetSelectedData()))
+                {
+                    UpdateApplicationsList(-1);
+                }
+
             }
-            
             break;
 
         case ID_UNINSTALL:
@@ -1293,7 +1379,7 @@ private:
             break;
 
         case ID_RESETDB:
-            m_AvailableApps.UpdateAppsDB();
+            CAvailableApps::ForceUpdateAppsDB();
             UpdateApplicationsList(-1);
             break;
 
@@ -1328,7 +1414,7 @@ private:
         }
     }
 
-    static BOOL SearchPatternMatch(PCWSTR szHaystack, PCWSTR szNeedle)
+    static BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle)
     {
         if (!*szNeedle)
             return TRUE;
@@ -1336,28 +1422,26 @@ private:
         return StrStrIW(szHaystack, szNeedle) != NULL;
     }
 
-    static BOOL CALLBACK s_EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, PINSTALLED_INFO Info)
+    static BOOL CALLBACK s_EnumInstalledAppProc(INT ItemIndex, ATL::CStringW &m_szName, PINSTALLED_INFO Info)
     {
         PINSTALLED_INFO ItemInfo;
         ATL::CStringW szText;
         INT Index;
 
-        if (!SearchPatternMatch(lpName, szSearchPattern))
+        if (!SearchPatternMatch(m_szName.GetString(), szSearchPattern))
         {
             RegCloseKey(Info->hSubKey);
             return TRUE;
         }
 
-        ItemInfo = (PINSTALLED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
+        ItemInfo = new INSTALLED_INFO(*Info);
         if (!ItemInfo)
         {
             RegCloseKey(Info->hSubKey);
             return FALSE;
         }
 
-        RtlCopyMemory(ItemInfo, Info, sizeof(INSTALLED_INFO));
-
-        Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM) ItemInfo);
+        Index = ListViewAddItem(ItemIndex, 0, m_szName, (LPARAM) ItemInfo);
 
         /* Get version info */
         GetApplicationString(ItemInfo->hSubKey, L"DisplayVersion", szText);
@@ -1370,22 +1454,22 @@ private:
         return TRUE;
     }
 
-    static BOOL CALLBACK s_EnumAvailableAppProc(PAPPLICATION_INFO Info, LPCWSTR szFolderPath)
+    static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo* Info, LPCWSTR szFolderPath)
     {
         INT Index;
         HICON hIcon = NULL;
 
         HIMAGELIST hImageListView = ListView_GetImageList(hListView, LVSIL_SMALL);
 
-        if (!SearchPatternMatch(Info->szName, szSearchPattern) &&
-            !SearchPatternMatch(Info->szDesc, szSearchPattern))
+        if (!SearchPatternMatch(Info->m_szName.GetString(), szSearchPattern) &&
+            !SearchPatternMatch(Info->m_szDesc.GetString(), szSearchPattern))
         {
             return TRUE;
         }
 
         /* Load icon from file */
         ATL::CStringW szIconPath;
-        szIconPath.Format(L"%lsicons\\%ls.ico", szFolderPath, Info->szName);
+        szIconPath.Format(L"%lsicons\\%ls.ico", szFolderPath, Info->m_szName.GetString());
         hIcon = (HICON) LoadImageW(NULL,
                                    szIconPath.GetString(),
                                    IMAGE_ICON,
@@ -1402,11 +1486,11 @@ private:
         Index = ImageList_AddIcon(hImageListView, hIcon);
         DestroyIcon(hIcon);
 
-        Index = ListViewAddItem(Info->Category, Index, Info->szName, (LPARAM) Info);
+        Index = ListViewAddItem(Info->m_Category, Index, Info->m_szName.GetString(), (LPARAM) Info);
         ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
 
-        ListView_SetItemText(hListView, Index, 1, const_cast<LPWSTR>(Info->szVersion.GetString()));
-        ListView_SetItemText(hListView, Index, 2, const_cast<LPWSTR>(Info->szDesc.GetString()));
+        ListView_SetItemText(hListView, Index, 1, const_cast<LPWSTR>(Info->m_szVersion.GetString()));
+        ListView_SetItemText(hListView, Index, 2, const_cast<LPWSTR>(Info->m_szDesc.GetString()));
 
         return TRUE;
     }
@@ -1426,19 +1510,27 @@ private:
     {
         ATL::CStringW szBuffer1, szBuffer2;
         HIMAGELIST hImageListView;
-        bUpdating = TRUE;
+        BOOL bWasInInstalled = IsInstalledEnum(SelectedEnumType);
 
+        bUpdating = TRUE;
         m_ListView->SetRedraw(FALSE);
 
         nSelectedApps = 0;
-        if (EnumType < 0) EnumType = SelectedEnumType;
+        if (EnumType < 0)
+        {
+            EnumType = SelectedEnumType;
+        }
 
-        if (IS_INSTALLED_ENUM(SelectedEnumType))
+        //if previous one was INSTALLED purge the list
+        //TODO: make the Installed category a separate class to avoid doing this
+        if (bWasInInstalled)
+        {
             FreeInstalledAppList();
+        }
 
         m_ListView->DeleteAllItems();
 
-        /* Create new ImageList */
+        // Create new ImageList 
         hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
                                           LISTVIEW_ICON_SIZE,
                                           GetSystemColorDepth() | ILC_MASK,
@@ -1449,21 +1541,41 @@ private:
             ImageList_Destroy(hImageListBuf);
         }
 
-        if (IS_AVAILABLE_ENUM(EnumType))
+        if (IsInstalledEnum(EnumType))
+        {
+            if (!bWasInInstalled)
+            {
+                m_ListView->SetCheckboxesVisible(FALSE);
+            }
+
+            HICON hIcon = (HICON) LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
+            ImageList_AddIcon(hImageListView, hIcon);
+            DestroyIcon(hIcon);
+
+            // Enum installed applications and updates
+            EnumInstalledApplications(EnumType, TRUE, s_EnumInstalledAppProc);
+            EnumInstalledApplications(EnumType, FALSE, s_EnumInstalledAppProc);
+        }
+        else if (IsAvailableEnum(EnumType))
         {
-            /* Enum available applications */
-            m_AvailableApps.EnumAvailableApplications(EnumType, s_EnumAvailableAppProc);
+            if (bWasInInstalled)
+            {
+                m_ListView->SetCheckboxesVisible(TRUE);
+            }
+
+            // Enum available applications
+            m_AvailableApps.Enum(EnumType, s_EnumAvailableAppProc);
         }
 
         SelectedEnumType = EnumType;
-
         UpdateStatusBarText();
-
         SetWelcomeText();
 
-        /* set automatic column width for program names if the list is not empty */
+        // Set automatic column width for program names if the list is not empty
         if (m_ListView->GetItemCount() > 0)
+        {
             ListView_SetColumnWidth(m_ListView->GetWindow(), 0, LVSCW_AUTOSIZE);
+        }
 
         bUpdating = FALSE;
         m_ListView->SetRedraw(TRUE);
@@ -1497,7 +1609,7 @@ public:
     HWND Create()
     {
         ATL::CStringW szWindowName;
-        szWindowName.LoadStringW(hInst, IDS_APPTITLE);
+        szWindowName.LoadStringW(IDS_APPTITLE);
 
         RECT r = {
             (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
@@ -1532,8 +1644,7 @@ public:
     }
 };
 
-// File interface
-
+// global interface
 CMainWindow * g_MainWindow;
 
 HWND CreateMainWindow()
@@ -1571,13 +1682,18 @@ VOID InsertRichEditText(LPCWSTR szText, DWORD flags)
     g_MainWindow->GetRichEdit()->InsertText(szText, flags);
 }
 
-/* ATL version of functions */
+CAvailableApps* GetAvailableApps()
+{
+    return g_MainWindow->GetAvailableApps();
+}
+
+// ATL version of functions above
 VOID SetStatusBarText(const ATL::CStringW& szText)
 {
     SetStatusBarText(szText.GetString());
 }
 
-INT ListViewAddItem(INT ItemIndex, INT IconIndex, ATL::CStringW & Name, LPARAM lParam)
+INT ListViewAddItem(INT ItemIndex, INT IconIndex, const ATL::CStringW& Name, LPARAM lParam)
 {
     return ListViewAddItem(ItemIndex, IconIndex, const_cast<LPWSTR>(Name.GetString()), lParam);
 }
@@ -1591,8 +1707,3 @@ VOID InsertRichEditText(const ATL::CStringW& szText, DWORD flags)
 {
     InsertRichEditText(szText.GetString(), flags);
 }
-
-CAvailableApps* GetAvailableApps()
-{
-    return g_MainWindow->GetAvailableApps();
-}