[RAPPS]
[reactos.git] / reactos / base / applications / rapps / gui.cpp
index 3b870c4..5f3edf2 100644 (file)
@@ -3,8 +3,11 @@
  * AUTHORS:     David Quintana             <gigaherz@gmail.com>
  *              Alexander Shaposhnikov     <chaez.san@gmail.com>
  */
+#include "defines.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,
+                                                      const ATL::CStringW& szText,
+                                                      DWORD StringFlags,
+                                                      DWORD TextFlags)
+    {
+        ATL::CStringW szLoadedText;
+        if (!szText.IsEmpty() && szLoadedText.LoadStringW(uStringID))
+        {
+            InsertRichEditText(szLoadedText, StringFlags);
+            InsertRichEditText(szText, TextFlags);
+        }
+    }
+
+    static inline VOID InsertLoadedTextNewl_RichEdit(UINT uStringID,
+                                                     DWORD StringFlags)
+    {
+        ATL::CStringW szLoadedText;
+        if (szLoadedText.LoadStringW(uStringID))
+        {
+            InsertRichEditText(L"\n", 0);
+            InsertRichEditText(szLoadedText, StringFlags);
+            InsertRichEditText(L"\n", 0);
+        }
+    }
+
+    static VOID InsertVersionInfo_RichEdit(CAvailableApplicationInfo* Info)
+    {
+        if (Info->IsInstalled())
+        {
+            if (Info->HasInstalledVersion())
+            {
+                if (Info->HasUpdate())
+                    InsertLoadedTextNewl_RichEdit(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
+                else
+                    InsertLoadedTextNewl_RichEdit(IDS_STATUS_INSTALLED, CFE_ITALIC);
+
+                InsertTextAfterLoaded_RichEdit(IDS_AINFO_VERSION, Info->szInstalledVersion, CFE_BOLD, 0);
+            }
+            else
+            {
+                InsertLoadedTextNewl_RichEdit(IDS_STATUS_INSTALLED, CFE_ITALIC);
+            }
+        }
+        else
+        {
+            InsertLoadedTextNewl_RichEdit(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
+        }
+
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_AVAILABLEVERSION, Info->szVersion, CFE_BOLD, 0);
+    }
+
+    static VOID InsertLicenseInfo_RichEdit(CAvailableApplicationInfo* Info)
+    {
+        ATL::CStringW szLicense;
+        switch (Info->LicenseType)
+        {
+        case LICENSE_TYPE::OpenSource:
+            szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE);
+            break;
+        case LICENSE_TYPE::Freeware:
+            szLicense.LoadStringW(IDS_LICENSE_FREEWARE);
+            break;
+        case LICENSE_TYPE::Trial:
+            szLicense.LoadStringW(IDS_LICENSE_TRIAL);
+            break;
+        default:
+            InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, Info->szLicense, CFE_BOLD, 0);
+            return;
+        }
+
+        szLicense += L" (" + Info->szLicense + L")";
+        InsertTextAfterLoaded_RichEdit(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0);
+    }
+
+    static VOID InsertLanguageInfo_RichEdit(CAvailableApplicationInfo* Info)
+    {
+        if (!Info->HasLanguageInfo())
+        {
+            return;
+        }
+
+        const INT nTranslations = Info->Languages.GetSize();
+        ATL::CStringW szLangInfo;
+        ATL::CStringW szLoadedTextAvailability;
+        ATL::CStringW szLoadedAInfoText;
+
+        szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
+
+        //TODO: replace those hardcoded strings
+        if (Info->HasNativeLanguage())
+        {
+            szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
+            if (nTranslations > 1)
+            {
+                ATL::CStringW buf;
+                buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER);
+                szLangInfo.Format(buf, nTranslations - 1);
+            }
+            else
+            {
+                szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
+                szLangInfo = L" (" + szLangInfo + L")";
+            }
+        }
+        else if (Info->HasEnglishLanguage())
+        {
+            szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
+            if (nTranslations > 1)
+            {
+                ATL::CStringW buf;
+                buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER);
+                szLangInfo.Format(buf, nTranslations - 1);
+            }
+            else
+            {
+                szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
+                szLangInfo = L" (" + szLangInfo + L")";
+            }
+        }
+        else
+        {
+            szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION);
+        }
+
+        InsertRichEditText(szLoadedAInfoText, CFE_BOLD);
+        InsertRichEditText(szLoadedTextAvailability, NULL);
+        InsertRichEditText(szLangInfo, CFE_ITALIC);
+    }
+
+public:
+    static BOOL ShowAvailableAppInfo(INT Index)
+    {
+        CAvailableApplicationInfo* Info = (CAvailableApplicationInfo*) ListViewGetlParam(Index);
+        if (!Info) return FALSE;
+
+        NewRichEditText(Info->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);
+
+        return TRUE;
+    }
+};
+
 class CMainToolbar :
     public CUiWindow< CToolbar<> >
 {
@@ -32,17 +212,18 @@ class CMainToolbar :
     WCHAR szInstallBtn[MAX_STR_LEN];
     WCHAR szUninstallBtn[MAX_STR_LEN];
     WCHAR szModifyBtn[MAX_STR_LEN];
+    WCHAR szSelectAll[MAX_STR_LEN];
 
     VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
     {
         HICON hImage;
 
-        if (!(hImage = (HICON) LoadImage(hInst,
-                                         MAKEINTRESOURCE(ImageIndex),
-                                         IMAGE_ICON,
-                                         TOOLBAR_HEIGHT,
-                                         TOOLBAR_HEIGHT,
-                                         0)))
+        if (!(hImage = (HICON) LoadImageW(hInst,
+                                          MAKEINTRESOURCE(ImageIndex),
+                                          IMAGE_ICON,
+                                          TOOLBAR_HEIGHT,
+                                          TOOLBAR_HEIGHT,
+                                          0)))
         {
             /* TODO: Error message */
         }
@@ -51,7 +232,7 @@ class CMainToolbar :
         DeleteObject(hImage);
     }
 
-    HIMAGELIST InitImageList(VOID)
+    HIMAGELIST InitImageList()
     {
         HIMAGELIST hImageList;
 
@@ -59,8 +240,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 */
@@ -70,6 +250,7 @@ class CMainToolbar :
         AddImageToImageList(hImageList, IDI_INSTALL);
         AddImageToImageList(hImageList, IDI_UNINSTALL);
         AddImageToImageList(hImageList, IDI_MODIFY);
+        AddImageToImageList(hImageList, IDI_CHECK_ALL);
         AddImageToImageList(hImageList, IDI_REFRESH);
         AddImageToImageList(hImageList, IDI_UPDATE_DB);
         AddImageToImageList(hImageList, IDI_SETTINGS);
@@ -86,31 +267,31 @@ public:
         switch (idButton)
         {
         case ID_EXIT:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT);
             break;
 
         case ID_INSTALL:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_INSTALL);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL);
             break;
 
         case ID_UNINSTALL:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL);
             break;
 
         case ID_MODIFY:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_MODIFY);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY);
             break;
 
         case ID_SETTINGS:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SETTINGS);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS);
             break;
 
         case ID_REFRESH:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH);
             break;
 
         case ID_RESETDB:
-            lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE_DB);
+            lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB);
             break;
         }
     }
@@ -125,17 +306,19 @@ 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 },
-            { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
-            { 3, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
-            { 4, ID_RESETDB,   TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, 0},
-            { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
-            { 5, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
-            { 6, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 }
+            { 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 },
+            {-1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
+            { 6, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
+            { 7, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
         };
 
         LoadStringW(hInst, IDS_INSTALL, szInstallBtn, _countof(szInstallBtn));
         LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, _countof(szUninstallBtn));
         LoadStringW(hInst, IDS_MODIFY, szModifyBtn, _countof(szModifyBtn));
+        LoadStringW(hInst, IDS_SELECT_ALL, szSelectAll, _countof(szSelectAll));
 
         m_hWnd = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL,
                                  WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST,
@@ -174,15 +357,17 @@ class CAppsListView :
     struct SortContext
     {
         CAppsListView * lvw;
-        int iSubItem;
+        INT iSubItem;
     };
 
-public:
+    BOOL bHasAllChecked;
     BOOL bAscending;
 
-    CAppsListView()
+public:
+    CAppsListView() :
+        bAscending(TRUE),
+        bHasAllChecked(FALSE)
     {
-        bAscending = TRUE;
     }
 
     VOID ColumnClick(LPNMLISTVIEW pnmv)
@@ -197,7 +382,7 @@ public:
     PVOID GetLParam(INT Index)
     {
         INT ItemIndex;
-        LVITEM Item;
+        LVITEMW Item;
 
         if (Index == -1)
         {
@@ -222,20 +407,18 @@ public:
 
     BOOL AddColumn(INT Index, ATL::CStringW& Text, INT Width, INT Format)
     {
-        BOOL result = AddColumn(Index, Text.GetBuffer(), Width, Format);
-
-        return result;
+        return AddColumn(Index, const_cast<LPWSTR>(Text.GetString()), Width, Format);
     }
 
     BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
     {
-        LV_COLUMN Column;
+        LVCOLUMNW Column;
 
         ZeroMemory(&Column, sizeof(Column));
 
         Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
         Column.iSubItem = Index;
-        Column.pszText = (LPTSTR) lpText;
+        Column.pszText = lpText;
         Column.cx = Width;
         Column.fmt = Format;
 
@@ -244,7 +427,7 @@ public:
 
     INT AddItem(INT ItemIndex, INT IconIndex, LPWSTR lpText, LPARAM lParam)
     {
-        LV_ITEMW Item;
+        LVITEMW Item;
 
         ZeroMemory(&Item, sizeof(Item));
 
@@ -266,7 +449,7 @@ public:
     INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
     {
         ATL::CStringW Item1, Item2;
-        LVFINDINFO IndexInfo;
+        LVFINDINFOW IndexInfo;
         INT Index;
 
         IndexInfo.flags = LVFI_PARAM;
@@ -298,11 +481,48 @@ public:
         HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
 
         if (hwnd)
-            SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
+        {
+            SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
+        }
 
         return hwnd;
     }
 
+    BOOL GetCheckState(INT item)
+    {
+        return (BOOL) (GetItemState(item, LVIS_STATEIMAGEMASK) >> 12) - 1;
+    }
+
+    VOID SetCheckState(INT item, BOOL fCheck)
+    {
+        SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
+    }
+
+    VOID CheckAll()
+    {
+        bHasAllChecked = !bHasAllChecked;
+        SetCheckState(-1, bHasAllChecked);
+    }
+
+    ATL::CSimpleArray<PAPPLICATION_INFO> GetCheckedItems()
+    {
+        ATL::CSimpleArray<PAPPLICATION_INFO> list;
+        for (INT i = 0; i >= 0; i = GetNextItem(i, LVNI_ALL))
+        {
+            if (GetCheckState(i) != FALSE)
+            {
+                PAPPLICATION_INFO pAppInfo = (PAPPLICATION_INFO) GetItemData(i);
+                list.Add(pAppInfo);
+            }
+        }
+        return list;
+    }
+
+    PAPPLICATION_INFO GetSelectedData()
+    {
+        INT item = GetSelectionMark();
+        return (PAPPLICATION_INFO) GetItemData(item);
+    }
 };
 
 class CSideTreeView :
@@ -315,9 +535,7 @@ class CSideTreeView :
 public:
     HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam)
     {
-        HTREEITEM result = CUiWindow<CTreeView>::AddItem(hParent, Text.GetBuffer(), Image, SelectedImage, lParam);
-        Text.ReleaseBuffer();
-        return result;
+        return CUiWindow<CTreeView>::AddItem(hParent, const_cast<LPWSTR>(Text.GetString()), Image, SelectedImage, lParam);
     }
 
     HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
@@ -326,19 +544,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);
     }
 
@@ -366,7 +584,7 @@ class CSearchBar :
 public:
     VOID SetText(LPCWSTR lpszText)
     {
-        SendMessage(SB_SETTEXT, SBT_NOBORDERS, (LPARAM) lpszText);
+        SendMessageW(SB_SETTEXT, SBT_NOBORDERS, (LPARAM) lpszText);
     }
 
     HWND Create(HWND hwndParent)
@@ -379,7 +597,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;
     }
@@ -401,36 +619,39 @@ class CMainWindow :
     CUiWindow<CRichEdit> * m_RichEdit;
 
     CUiWindow<CSearchBar> * m_SearchBar;
+    CAvailableApps m_AvailableApps;
 
     LPWSTR pLink;
 
-    BOOL SearchEnabled;
+    INT nSelectedApps;
 
+    BOOL bSearchEnabled;
+    BOOL bUpdating;
 public:
     CMainWindow() :
         m_ClientPanel(NULL),
         pLink(NULL),
-        SearchEnabled(TRUE)
+        bSearchEnabled(FALSE)
     {
     }
 
 private:
-
-    VOID InitApplicationsList(VOID)
+    VOID InitApplicationsList()
     {
         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);
 
-        UpdateApplicationsList(ENUM_ALL_COMPONENTS);
+        // Unnesesary since the list updates on every TreeView selection
+        // UpdateApplicationsList(ENUM_ALL_COMPONENTS);
     }
 
     HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
@@ -438,30 +659,35 @@ private:
         return m_TreeView->AddCategory(hRootItem, TextIndex, IconIndex);
     }
 
-    VOID InitCategoriesList(VOID)
+    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()
@@ -538,13 +764,13 @@ private:
         m_HSplitter->m_Horizontal = TRUE;
         m_HSplitter->m_Pos = 32768;
         m_HSplitter->m_MinFirst = 300;
-        m_HSplitter->m_MinSecond = 80;
+        m_HSplitter->m_MinSecond = 150;
         m_VSplitter->Second().Append(m_HSplitter);
 
         return m_HSplitter->Create(m_hWnd) != NULL;
     }
 
-    BOOL CreateSearchBar(VOID)
+    BOOL CreateSearchBar()
     {
         m_SearchBar = new CUiWindow<CSearchBar>();
         m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
@@ -557,7 +783,8 @@ private:
 
     BOOL CreateLayout()
     {
-        bool b = TRUE;
+        BOOL b = TRUE;
+        bUpdating = TRUE;
 
         m_ClientPanel = new CUiPanel();
         m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
@@ -583,7 +810,7 @@ private:
             RECT rBottom;
 
             /* Size status bar */
-            m_StatusBar->SendMessage(WM_SIZE, 0, 0);
+            m_StatusBar->SendMessageW(WM_SIZE, 0, 0);
 
             /* Size tool bar */
             m_Toolbar->AutoSize();
@@ -595,6 +822,7 @@ private:
             m_VSplitter->m_Margin.bottom = rBottom.bottom - rBottom.top;
         }
 
+        bUpdating = FALSE;
         return b;
     }
 
@@ -602,16 +830,13 @@ private:
     {
         if (CreateLayout())
         {
-            ATL::CStringW szBuffer1, szBuffer2;
 
             InitApplicationsList();
-
             InitCategoriesList();
 
-            szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
-            szBuffer1.Format(szBuffer2, m_ListView->GetItemCount());
+            nSelectedApps = 0;
+            UpdateStatusBarText();
 
-            m_StatusBar->SetText(szBuffer1);
             return TRUE;
         }
 
@@ -626,21 +851,31 @@ private:
         /* Size tool bar */
         m_Toolbar->AutoSize();
 
-
         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) hdwp = m_ClientPanel->OnParentSize(r, hdwp);
-        if (hdwp) EndDeferWindowPos(hdwp);
+        if (hdwp)
+        {
+            hdwp = m_ClientPanel->OnParentSize(r, hdwp);
+        }
+        if (hdwp)
+        {
+            EndDeferWindowPos(hdwp);
+        }
 
         // TODO: Sub-layouts for children of children
         count = m_SearchBar->CountSizableChildren();
         hdwp = BeginDeferWindowPos(count);
-        if (hdwp) hdwp = m_SearchBar->OnParentSize(r, hdwp);
-        if (hdwp) EndDeferWindowPos(hdwp);
+        if (hdwp)
+        {
+            hdwp = m_SearchBar->OnParentSize(r, hdwp);
+        }
+        if (hdwp)
+        {
+            EndDeferWindowPos(hdwp);
+        }
     }
 
     BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
@@ -659,8 +894,7 @@ private:
             SaveSettings(hwnd);
 
             FreeLogs();
-
-            FreeCachedAvailableEntries();
+            m_AvailableApps.FreeCachedEntries();
 
             if (IS_INSTALLED_ENUM(SelectedEnumType))
                 FreeInstalledAppList();
@@ -781,10 +1015,10 @@ private:
                     EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_ENABLED);
                     EnableMenuItem(lvwMenu, ID_MODIFY, MF_ENABLED);
 
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
                 }
                 else
                 {
@@ -798,10 +1032,10 @@ private:
                     EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_GRAYED);
                     EnableMenuItem(lvwMenu, ID_MODIFY, MF_GRAYED);
 
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_INSTALL, TRUE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
-                    m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_MODIFY, FALSE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, TRUE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
+                    m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, FALSE);
                 }
             }
             break;
@@ -828,8 +1062,25 @@ private:
                     {
                         if (IS_INSTALLED_ENUM(SelectedEnumType))
                             ShowInstalledAppInfo(ItemIndex);
-                        if (IS_AVAILABLE_ENUM(SelectedEnumType))
-                            ShowAvailableAppInfo(ItemIndex);
+                        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);
+                        /* 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();
                     }
                 }
             }
@@ -849,8 +1100,8 @@ private:
                 {
                     if (IS_INSTALLED_ENUM(SelectedEnumType))
                         ShowInstalledAppInfo(-1);
-                    if (IS_AVAILABLE_ENUM(SelectedEnumType))
-                        ShowAvailableAppInfo(-1);
+                    if (isAvailableEnum(SelectedEnumType))
+                        CAvailableAppView::ShowAvailableAppInfo(-1);
                 }
             }
             break;
@@ -860,7 +1111,7 @@ private:
                 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
                 {
                     /* this won't do anything if the program is already installed */
-                    SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0);
+                    SendMessageW(hwnd, WM_COMMAND, ID_INSTALL, 0);
                 }
             }
             break;
@@ -905,10 +1156,10 @@ private:
         case WM_SYSCOLORCHANGE:
         {
             /* Forward WM_SYSCOLORCHANGE to common controls */
-            m_ListView->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
-            m_TreeView->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
-            m_Toolbar->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
-            m_ListView->SendMessage(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
+            m_ListView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
+            m_TreeView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
+            m_Toolbar->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
+            m_ListView->SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
         }
         break;
 
@@ -916,7 +1167,8 @@ private:
             if (wParam == SEARCH_TIMER_ID)
             {
                 ::KillTimer(hwnd, SEARCH_TIMER_ID);
-                UpdateApplicationsList(-1);
+                if (bSearchEnabled)
+                    UpdateApplicationsList(-1);
             }
             break;
         }
@@ -951,7 +1203,7 @@ private:
         }
     }
 
-    BOOL IsSelectedNodeInstalled(void)
+    BOOL IsSelectedNodeInstalled()
     {
         HTREEITEM hSelectedItem = m_TreeView->GetSelection();
         TV_ITEM tItem;
@@ -984,11 +1236,11 @@ private:
             {
                 ATL::CStringW szWndText;
 
-                szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+                szBuf.LoadStringW(IDS_SEARCH_TEXT);
                 m_SearchBar->GetWindowTextW(szWndText);
                 if (szBuf == szWndText)
                 {
-                    SearchEnabled = FALSE;
+                    bSearchEnabled = FALSE;
                     m_SearchBar->SetWindowTextW(L"");
                 }
             }
@@ -999,8 +1251,8 @@ private:
                 m_SearchBar->GetWindowTextW(szBuf);
                 if (szBuf.IsEmpty())
                 {
-                    szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
-                    SearchEnabled = FALSE;
+                    szBuf.LoadStringW(IDS_SEARCH_TEXT);
+                    bSearchEnabled = FALSE;
                     m_SearchBar->SetWindowTextW(szBuf.GetString());
                 }
             }
@@ -1010,13 +1262,13 @@ private:
             {
                 ATL::CStringW szWndText;
 
-                if (!SearchEnabled)
+                if (!bSearchEnabled)
                 {
-                    SearchEnabled = TRUE;
+                    bSearchEnabled = TRUE;
                     break;
                 }
 
-                szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
+                szBuf.LoadStringW(IDS_SEARCH_TEXT);
                 m_SearchBar->GetWindowTextW(szWndText);
                 if (szBuf == szWndText)
                 {
@@ -1028,7 +1280,7 @@ private:
                 }
 
                 DWORD dwDelay;
-                SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0);
+                SystemParametersInfoW(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0);
                 SetTimer(SEARCH_TIMER_ID, dwDelay);
             }
             break;
@@ -1058,11 +1310,16 @@ private:
             break;
 
         case ID_INSTALL:
-            if (DownloadApplication(-1))
-                /* TODO: Implement install dialog
-                *   if (InstallApplication(-1))
-                */
+            if (nSelectedApps > 0)
+            {
+                CDownloadManager::DownloadListOfApplications(m_ListView->GetCheckedItems());
+                UpdateApplicationsList(-1);
+            }
+            else if (CDownloadManager::DownloadApplication(m_ListView->GetSelectedData()))
+            {
                 UpdateApplicationsList(-1);
+            }
+
             break;
 
         case ID_UNINSTALL:
@@ -1084,7 +1341,7 @@ private:
             break;
 
         case ID_RESETDB:
-            UpdateAppsDB();
+            CAvailableApps::ForceUpdateAppsDB();
             UpdateApplicationsList(-1);
             break;
 
@@ -1095,12 +1352,16 @@ private:
         case ID_ABOUT:
             ShowAboutDialog();
             break;
+
+        case ID_CHECK_ALL:
+            m_ListView->CheckAll();
+            break;
         }
     }
 
-    VOID FreeInstalledAppList(VOID)
+    VOID FreeInstalledAppList()
     {
-        INT Count = ListView_GetItemCount(hListView) - 1;
+        INT Count = m_ListView->GetItemCount() - 1;
         PINSTALLED_INFO Info;
 
         while (Count >= 0)
@@ -1123,13 +1384,13 @@ 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 &szName, PINSTALLED_INFO Info)
     {
         PINSTALLED_INFO ItemInfo;
         ATL::CStringW szText;
         INT Index;
 
-        if (!SearchPatternMatch(lpName, szSearchPattern))
+        if (!SearchPatternMatch(szName.GetString(), szSearchPattern))
         {
             RegCloseKey(Info->hSubKey);
             return TRUE;
@@ -1144,25 +1405,24 @@ private:
 
         RtlCopyMemory(ItemInfo, Info, sizeof(INSTALLED_INFO));
 
-        Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM) ItemInfo);
+        Index = ListViewAddItem(ItemIndex, 0, szName, (LPARAM) ItemInfo);
 
         /* Get version info */
         GetApplicationString(ItemInfo->hSubKey, L"DisplayVersion", szText);
-        ListView_SetItemText(hListView, Index, 1, szText.GetBuffer());
-        szText.ReleaseBuffer();
+        ListView_SetItemText(hListView, Index, 1, const_cast<LPWSTR>(szText.GetString()));
 
         /* Get comments */
         GetApplicationString(ItemInfo->hSubKey, L"Comments", szText);
-        ListView_SetItemText(hListView, Index, 2, szText.GetBuffer());
-        szText.ReleaseBuffer();
+        ListView_SetItemText(hListView, Index, 2, const_cast<LPWSTR>(szText.GetString()));
+
         return TRUE;
     }
 
-    static BOOL CALLBACK s_EnumAvailableAppProc(PAPPLICATION_INFO Info)
+    static BOOL CALLBACK s_EnumAvailableAppProc(PAPPLICATION_INFO Info, LPCWSTR szFolderPath)
     {
         INT Index;
         HICON hIcon = NULL;
-        ATL::CStringW szIconPath;
+
         HIMAGELIST hImageListView = ListView_GetImageList(hListView, LVSIL_SMALL);
 
         if (!SearchPatternMatch(Info->szName, szSearchPattern) &&
@@ -1171,80 +1431,98 @@ private:
             return TRUE;
         }
 
-        if (GetStorageDirectory(szIconPath))
-        {
-            /* Load icon from file */
-            szIconPath += L"\\rapps\\icons\\" + Info->szName + L".ico";
-            hIcon = (HICON) LoadImageW(NULL,
-                                       szIconPath.GetString(),
-                                       IMAGE_ICON,
-                                       LISTVIEW_ICON_SIZE,
-                                       LISTVIEW_ICON_SIZE,
-                                       LR_LOADFROMFILE);
-        }
-
-        if (!hIcon)
+        /* Load icon from file */
+        ATL::CStringW szIconPath;
+        szIconPath.Format(L"%lsicons\\%ls.ico", szFolderPath, Info->szName);
+        hIcon = (HICON) LoadImageW(NULL,
+                                   szIconPath.GetString(),
+                                   IMAGE_ICON,
+                                   LISTVIEW_ICON_SIZE,
+                                   LISTVIEW_ICON_SIZE,
+                                   LR_LOADFROMFILE);
+
+        if (!hIcon || GetLastError() != ERROR_SUCCESS)
         {
             /* Load default icon */
-            hIcon = (HICON) LoadIcon(hInst, MAKEINTRESOURCEW(IDI_MAIN));
+            hIcon = (HICON) LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
         }
+
         Index = ImageList_AddIcon(hImageListView, hIcon);
         DestroyIcon(hIcon);
 
         Index = ListViewAddItem(Info->Category, Index, Info->szName, (LPARAM) Info);
-        hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
+        ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
 
-        ListView_SetItemText(hListView, Index, 1, Info->szVersion.GetBuffer());
-        Info->szVersion.ReleaseBuffer();
+        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, 2, Info->szDesc.GetBuffer());
-        Info->szDesc.ReleaseBuffer();
         return TRUE;
     }
 
+    VOID UpdateStatusBarText()
+    {
+        if (m_StatusBar)
+        {
+            ATL::CStringW szBuffer;
+
+            szBuffer.Format(IDS_APPS_COUNT, m_ListView->GetItemCount(), nSelectedApps);
+            m_StatusBar->SetText(szBuffer);
+        }
+    }
 
     VOID UpdateApplicationsList(INT EnumType)
     {
         ATL::CStringW szBuffer1, szBuffer2;
-        HIMAGELIST hImageListView = NULL;
+        HIMAGELIST hImageListView;
+        bUpdating = TRUE;
 
-        m_ListView->SendMessage(WM_SETREDRAW, FALSE, 0);
+        m_ListView->SetRedraw(FALSE);
 
+        nSelectedApps = 0;
         if (EnumType < 0) EnumType = SelectedEnumType;
 
-        if (IS_INSTALLED_ENUM(SelectedEnumType))
+        if (IS_INSTALLED_ENUM(EnumType))
+        {
             FreeInstalledAppList();
+        }
+
+        m_ListView->DeleteAllItems();
 
-        (VOID) ListView_DeleteAllItems(hListView);
         /* Create new ImageList */
         hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
                                           LISTVIEW_ICON_SIZE,
                                           GetSystemColorDepth() | ILC_MASK,
                                           0, 1);
-        hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
-
-        if (hImageListView)
-            ImageList_Destroy(hImageListView);
+        HIMAGELIST hImageListBuf = m_ListView->SetImageList(hImageListView, LVSIL_SMALL);
+        if (hImageListBuf)
+        {
+            ImageList_Destroy(hImageListBuf);
+        }
 
-        if (IS_AVAILABLE_ENUM(EnumType))
+        if (IS_INSTALLED_ENUM(EnumType))
+        {
+            /* Enum installed applications and updates */
+            EnumInstalledApplications(EnumType, TRUE, s_EnumInstalledAppProc);
+            EnumInstalledApplications(EnumType, FALSE, s_EnumInstalledAppProc);
+        }
+        else if (isAvailableEnum(EnumType))
         {
             /* Enum available applications */
-            EnumAvailableApplications(EnumType, s_EnumAvailableAppProc);
+            m_AvailableApps.EnumAvailableApplications(EnumType, s_EnumAvailableAppProc);
         }
 
         SelectedEnumType = EnumType;
-
-        szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
-        szBuffer1.Format(szBuffer2, ListView_GetItemCount(hListView));
-        SetStatusBarText(szBuffer1);
-
+        UpdateStatusBarText();
         SetWelcomeText();
 
-        /* set automatic column width for program names if the list is not empty */
-        if (ListView_GetItemCount(hListView) > 0)
-            ListView_SetColumnWidth(hListView, 0, LVSCW_AUTOSIZE);
+        /* 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);
+        }
 
-        SendMessage(hListView, WM_SETREDRAW, TRUE, 0);
+        bUpdating = FALSE;
+        m_ListView->SetRedraw(TRUE);
     }
 
 public:
@@ -1253,12 +1531,20 @@ public:
         DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
         static ATL::CWndClassInfo wc =
         {
-            { sizeof(WNDCLASSEX), csStyle, StartWindowProc,
-            0, 0, NULL,
-            LoadIcon(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCE(IDI_MAIN)),
-            LoadCursor(NULL, IDC_ARROW),
-            (HBRUSH) (COLOR_BTNFACE + 1), MAKEINTRESOURCE(IDR_MAINMENU),
-            L"RAppsWnd", NULL },
+            {
+                sizeof(WNDCLASSEX),
+                csStyle,
+                StartWindowProc,
+                0,
+                0,
+                NULL,
+                LoadIconW(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN)),
+                LoadCursorW(NULL, IDC_ARROW),
+                (HBRUSH) (COLOR_BTNFACE + 1),
+                MAKEINTRESOURCEW(IDR_MAINMENU),
+                L"RAppsWnd",
+                NULL
+            },
             NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
         };
         return wc;
@@ -1267,7 +1553,7 @@ public:
     HWND Create()
     {
         ATL::CStringW szWindowName;
-        szWindowName.LoadStringW(hInst, IDS_APPTITLE);
+        szWindowName.LoadStringW(IDS_APPTITLE);
 
         RECT r = {
             (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
@@ -1295,8 +1581,15 @@ public:
     {
         return m_RichEdit;
     }
+
+    CAvailableApps * GetAvailableApps()
+    {
+        return &m_AvailableApps;
+    }
 };
 
+// File interface
+
 CMainWindow * g_MainWindow;
 
 HWND CreateMainWindow()
@@ -1340,11 +1633,9 @@ 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)
 {
-    INT result = ListViewAddItem(ItemIndex, IconIndex, Name.GetBuffer(), lParam);
-    Name.ReleaseBuffer();
-    return result;
+    return ListViewAddItem(ItemIndex, IconIndex, const_cast<LPWSTR>(Name.GetString()), lParam);
 }
 
 VOID NewRichEditText(const ATL::CStringW& szText, DWORD flags)
@@ -1357,3 +1648,7 @@ VOID InsertRichEditText(const ATL::CStringW& szText, DWORD flags)
     InsertRichEditText(szText.GetString(), flags);
 }
 
+CAvailableApps* GetAvailableApps()
+{
+    return g_MainWindow->GetAvailableApps();
+}