mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[RAPPS] Speed up app loading by caching the INI sections
This commit is contained in:
parent
6f9dd96dcf
commit
9bdeaca56e
6 changed files with 156 additions and 98 deletions
|
@ -1705,6 +1705,12 @@ BOOL CApplicationView::CreateAppInfoDisplay()
|
||||||
return m_AppsInfo->Create(m_hWnd) != NULL;
|
return m_AppsInfo->Create(m_hWnd) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CApplicationView::SetRedraw(BOOL bRedraw)
|
||||||
|
{
|
||||||
|
CWindow::SetRedraw(bRedraw);
|
||||||
|
m_ListView->SetRedraw(bRedraw);
|
||||||
|
}
|
||||||
|
|
||||||
VOID CApplicationView::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
VOID CApplicationView::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (wParam == SIZE_MINIMIZED)
|
if (wParam == SIZE_MINIMIZED)
|
||||||
|
|
|
@ -2,18 +2,31 @@
|
||||||
* PROJECT: ReactOS Applications Manager
|
* PROJECT: ReactOS Applications Manager
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Config parser
|
* PURPOSE: Config parser
|
||||||
* COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
|
* COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
|
||||||
* Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
|
* Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
|
||||||
* Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
|
* Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
|
||||||
|
* Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
#include "rapps.h"
|
#include "rapps.h"
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
CConfigParser::CConfigParser(const ATL::CStringW& FileName) : szConfigPath(GetINIFullPath(FileName))
|
struct CLocaleSections
|
||||||
{
|
{
|
||||||
CacheINILocale();
|
CStringW Locale;
|
||||||
}
|
CStringW LocaleNeutral;
|
||||||
|
CStringW Section;
|
||||||
|
};
|
||||||
|
|
||||||
ATL::CStringW CConfigParser::GetINIFullPath(const ATL::CStringW& FileName)
|
struct CSectionNames
|
||||||
|
{
|
||||||
|
CLocaleSections ArchSpecific;
|
||||||
|
CLocaleSections ArchNeutral;
|
||||||
|
};
|
||||||
|
static CSectionNames g_Names;
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName)
|
||||||
{
|
{
|
||||||
ATL::CStringW szDir;
|
ATL::CStringW szDir;
|
||||||
ATL::CStringW szBuffer;
|
ATL::CStringW szBuffer;
|
||||||
|
@ -24,79 +37,124 @@ ATL::CStringW CConfigParser::GetINIFullPath(const ATL::CStringW& FileName)
|
||||||
return szBuffer;
|
return szBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID CConfigParser::CacheINILocale()
|
CConfigParser::CConfigParser(const ATL::CStringW& FileName)
|
||||||
|
: szConfigPath(GetINIFullPath(FileName))
|
||||||
{
|
{
|
||||||
// TODO: Set default locale if call fails
|
CacheINI();
|
||||||
// find out what is the current system lang code (e.g. "0a") and append it to SectionLocale
|
|
||||||
GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE,
|
|
||||||
m_szLocaleID.GetBuffer(m_cchLocaleSize), m_cchLocaleSize);
|
|
||||||
|
|
||||||
m_szLocaleID.ReleaseBuffer();
|
|
||||||
m_szCachedINISectionLocale = L"Section." + m_szLocaleID;
|
|
||||||
|
|
||||||
// turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
|
|
||||||
if (m_szLocaleID.GetLength() >= 2)
|
|
||||||
m_szCachedINISectionLocaleNeutral = L"Section." + m_szLocaleID.Right(2);
|
|
||||||
else
|
|
||||||
m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CConfigParser::GetStringWorker(const ATL::CStringW& KeyName, PCWSTR Suffix, ATL::CStringW& ResultString)
|
void CConfigParser::ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Section, BOOL isArch)
|
||||||
{
|
{
|
||||||
DWORD dwResult;
|
DWORD len = 512;
|
||||||
|
DWORD result;
|
||||||
|
|
||||||
LPWSTR ResultStringBuffer = ResultString.GetBuffer(MAX_PATH);
|
do
|
||||||
// 1st - find localized strings (e.g. "Section.0c0a")
|
|
||||||
dwResult = GetPrivateProfileStringW((m_szCachedINISectionLocale + Suffix).GetString(),
|
|
||||||
KeyName.GetString(),
|
|
||||||
NULL,
|
|
||||||
ResultStringBuffer,
|
|
||||||
MAX_PATH,
|
|
||||||
szConfigPath.GetString());
|
|
||||||
|
|
||||||
if (!dwResult)
|
|
||||||
{
|
{
|
||||||
// 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a")
|
len *= 2;
|
||||||
dwResult = GetPrivateProfileStringW((m_szCachedINISectionLocaleNeutral + Suffix).GetString(),
|
|
||||||
KeyName.GetString(),
|
result = GetPrivateProfileSectionW(Section, Buffer.GetBuffer(len), len, szConfigPath);
|
||||||
NULL,
|
Buffer.ReleaseBuffer(result);
|
||||||
ResultStringBuffer,
|
} while (result == len - 2);
|
||||||
MAX_PATH,
|
|
||||||
szConfigPath.GetString());
|
len = 0;
|
||||||
if (!dwResult)
|
while (len < result)
|
||||||
|
{
|
||||||
|
// Explicitly use the null terminator!
|
||||||
|
CString tmp = Buffer.GetBuffer() + len;
|
||||||
|
if (tmp.GetLength() > 0)
|
||||||
{
|
{
|
||||||
// 3rd - if they weren't present fallback to standard english strings (just "Section")
|
len += tmp.GetLength() + 1;
|
||||||
dwResult = GetPrivateProfileStringW((ATL::CStringW(L"Section") + Suffix).GetString(),
|
|
||||||
KeyName.GetString(),
|
int idx = tmp.Find('=');
|
||||||
NULL,
|
if (idx >= 0)
|
||||||
ResultStringBuffer,
|
{
|
||||||
MAX_PATH,
|
CString key = tmp.Left(idx);
|
||||||
szConfigPath.GetString());
|
|
||||||
|
#ifndef _M_IX86
|
||||||
|
// On non-x86 architecture we need the architecture specific URL
|
||||||
|
if (!isArch && key == "URLDownload")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Is this key already present from a more specific translation?
|
||||||
|
if (m_Keys.FindKey(key) >= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CString value = tmp.Mid(idx+1);
|
||||||
|
m_Keys.Add(key, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("ERROR: invalid key/value pair: '%S'\n", tmp.GetString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResultString.ReleaseBuffer();
|
VOID CConfigParser::CacheINI()
|
||||||
return (dwResult != 0 ? TRUE : FALSE);
|
{
|
||||||
|
// Cache section names
|
||||||
|
if (g_Names.ArchSpecific.Locale.IsEmpty())
|
||||||
|
{
|
||||||
|
CString szLocaleID;
|
||||||
|
const INT cchLocaleSize = 5;
|
||||||
|
|
||||||
|
GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, szLocaleID.GetBuffer(cchLocaleSize), cchLocaleSize);
|
||||||
|
szLocaleID.ReleaseBuffer();
|
||||||
|
CString INISectionLocale = L"Section." + szLocaleID;
|
||||||
|
|
||||||
|
g_Names.ArchSpecific.Locale = INISectionLocale + L"." CurrentArchitecture;
|
||||||
|
g_Names.ArchNeutral.Locale = INISectionLocale;
|
||||||
|
|
||||||
|
// turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
|
||||||
|
if (szLocaleID.GetLength() >= 2)
|
||||||
|
{
|
||||||
|
g_Names.ArchSpecific.LocaleNeutral = L"Section." + szLocaleID.Right(2) + L"." CurrentArchitecture;
|
||||||
|
g_Names.ArchNeutral.LocaleNeutral = L"Section." + szLocaleID.Right(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_Names.ArchSpecific.Section = L"Section." CurrentArchitecture;
|
||||||
|
g_Names.ArchNeutral.Section = L"Section";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a shared buffer so that we don't have to re-allocate it every time
|
||||||
|
CStringW Buffer;
|
||||||
|
|
||||||
|
ReadSection(Buffer, g_Names.ArchSpecific.Locale, TRUE);
|
||||||
|
if (!g_Names.ArchSpecific.LocaleNeutral.IsEmpty())
|
||||||
|
{
|
||||||
|
ReadSection(Buffer, g_Names.ArchSpecific.LocaleNeutral, TRUE);
|
||||||
|
}
|
||||||
|
ReadSection(Buffer, g_Names.ArchSpecific.Section, TRUE);
|
||||||
|
|
||||||
|
|
||||||
|
ReadSection(Buffer, g_Names.ArchNeutral.Locale, FALSE);
|
||||||
|
if (!g_Names.ArchNeutral.LocaleNeutral.IsEmpty())
|
||||||
|
{
|
||||||
|
ReadSection(Buffer, g_Names.ArchNeutral.LocaleNeutral, FALSE);
|
||||||
|
}
|
||||||
|
ReadSection(Buffer, g_Names.ArchNeutral.Section, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
|
BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
|
||||||
{
|
{
|
||||||
/* First try */
|
int nIndex = m_Keys.FindKey(KeyName);
|
||||||
if (GetStringWorker(KeyName, L"." CurrentArchitecture, ResultString))
|
if (nIndex >= 0)
|
||||||
{
|
{
|
||||||
|
ResultString = m_Keys.GetValueAt(nIndex);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _M_IX86
|
ResultString.Empty();
|
||||||
/* On non-x86 architecture we need the architecture specific URL */
|
return FALSE;
|
||||||
if (KeyName == L"URLDownload")
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fall back to default */
|
|
||||||
return GetStringWorker(KeyName, L"", ResultString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult)
|
BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult)
|
||||||
|
|
|
@ -351,42 +351,31 @@ private:
|
||||||
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
|
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
|
||||||
|
|
||||||
BOOL CreateToolbar();
|
BOOL CreateToolbar();
|
||||||
|
|
||||||
BOOL CreateSearchBar();
|
BOOL CreateSearchBar();
|
||||||
|
|
||||||
BOOL CreateComboBox();
|
BOOL CreateComboBox();
|
||||||
|
|
||||||
BOOL CreateHSplitter();
|
BOOL CreateHSplitter();
|
||||||
|
|
||||||
BOOL CreateListView();
|
BOOL CreateListView();
|
||||||
|
|
||||||
BOOL CreateAppInfoDisplay();
|
BOOL CreateAppInfoDisplay();
|
||||||
|
|
||||||
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
|
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
VOID OnCommand(WPARAM wParam, LPARAM lParam);
|
VOID OnCommand(WPARAM wParam, LPARAM lParam);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CApplicationView(CMainWindow *MainWindow);
|
CApplicationView(CMainWindow *MainWindow);
|
||||||
|
|
||||||
~CApplicationView();
|
~CApplicationView();
|
||||||
|
|
||||||
static ATL::CWndClassInfo &GetWndClassInfo();
|
static ATL::CWndClassInfo &GetWndClassInfo();
|
||||||
|
|
||||||
HWND Create(HWND hwndParent);
|
HWND Create(HWND hwndParent);
|
||||||
|
void SetRedraw(BOOL bRedraw);
|
||||||
BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
|
BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
|
||||||
|
|
||||||
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID param);
|
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID param);
|
||||||
|
|
||||||
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID param);
|
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID param);
|
||||||
|
|
||||||
void CheckAll();
|
void CheckAll();
|
||||||
|
|
||||||
PVOID GetFocusedItemData();
|
PVOID GetFocusedItemData();
|
||||||
|
|
||||||
int GetItemCount();
|
int GetItemCount();
|
||||||
|
|
||||||
VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList);
|
VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList);
|
||||||
|
|
||||||
// this function is called when a item of listview get focus.
|
// this function is called when a item of listview get focus.
|
||||||
|
|
|
@ -5,18 +5,11 @@
|
||||||
|
|
||||||
class CConfigParser
|
class CConfigParser
|
||||||
{
|
{
|
||||||
// Locale names cache
|
|
||||||
const static INT m_cchLocaleSize = 5;
|
|
||||||
|
|
||||||
ATL::CStringW m_szLocaleID;
|
|
||||||
ATL::CStringW m_szCachedINISectionLocale;
|
|
||||||
ATL::CStringW m_szCachedINISectionLocaleNeutral;
|
|
||||||
|
|
||||||
const ATL::CStringW szConfigPath;
|
const ATL::CStringW szConfigPath;
|
||||||
|
CSimpleMap<CStringW, CStringW> m_Keys;
|
||||||
|
|
||||||
ATL::CStringW GetINIFullPath(const ATL::CStringW& FileName);
|
void CacheINI();
|
||||||
VOID CacheINILocale();
|
void ReadSection(ATL::CStringW& Buffer, const ATL::CStringW& Section, BOOL isArch);
|
||||||
BOOL GetStringWorker(const ATL::CStringW& KeyName, PCWSTR Suffix, ATL::CStringW& ResultString);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CConfigParser(const ATL::CStringW& FileName);
|
CConfigParser(const ATL::CStringW& FileName);
|
||||||
|
|
|
@ -71,13 +71,9 @@ private:
|
||||||
VOID InitCategoriesList();
|
VOID InitCategoriesList();
|
||||||
|
|
||||||
BOOL CreateStatusBar();
|
BOOL CreateStatusBar();
|
||||||
|
|
||||||
BOOL CreateTreeView();
|
BOOL CreateTreeView();
|
||||||
|
|
||||||
BOOL CreateApplicationView();
|
BOOL CreateApplicationView();
|
||||||
|
|
||||||
BOOL CreateVSplitter();
|
BOOL CreateVSplitter();
|
||||||
|
|
||||||
BOOL CreateLayout();
|
BOOL CreateLayout();
|
||||||
|
|
||||||
VOID LayoutCleanup();
|
VOID LayoutCleanup();
|
||||||
|
@ -99,11 +95,8 @@ private:
|
||||||
VOID OnCommand(WPARAM wParam, LPARAM lParam);
|
VOID OnCommand(WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
BOOL CALLBACK EnumInstalledAppProc(CInstalledApplicationInfo *Info);
|
BOOL CALLBACK EnumInstalledAppProc(CInstalledApplicationInfo *Info);
|
||||||
|
|
||||||
BOOL CALLBACK EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState);
|
BOOL CALLBACK EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState);
|
||||||
|
|
||||||
static BOOL CALLBACK s_EnumInstalledAppProc(CInstalledApplicationInfo *Info, PVOID param);
|
static BOOL CALLBACK s_EnumInstalledAppProc(CInstalledApplicationInfo *Info, PVOID param);
|
||||||
|
|
||||||
static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
|
static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
|
||||||
|
|
||||||
static BOOL CALLBACK s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
|
static BOOL CALLBACK s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
|
||||||
|
|
|
@ -140,17 +140,36 @@ BOOL StartProcess(const ATL::CStringW& Path, BOOL Wait)
|
||||||
|
|
||||||
BOOL GetStorageDirectory(ATL::CStringW& Directory)
|
BOOL GetStorageDirectory(ATL::CStringW& Directory)
|
||||||
{
|
{
|
||||||
LPWSTR DirectoryStr = Directory.GetBuffer(MAX_PATH);
|
static CStringW CachedDirectory;
|
||||||
if (!SHGetSpecialFolderPathW(NULL, DirectoryStr, CSIDL_LOCAL_APPDATA, TRUE))
|
static BOOL CachedDirectoryInitialized = FALSE;
|
||||||
|
|
||||||
|
if (!CachedDirectoryInitialized)
|
||||||
{
|
{
|
||||||
Directory.ReleaseBuffer();
|
LPWSTR DirectoryStr = CachedDirectory.GetBuffer(MAX_PATH);
|
||||||
return FALSE;
|
BOOL bHasPath = SHGetSpecialFolderPathW(NULL, DirectoryStr, CSIDL_LOCAL_APPDATA, TRUE);
|
||||||
|
if (bHasPath)
|
||||||
|
{
|
||||||
|
PathAppendW(DirectoryStr, L"rapps");
|
||||||
|
}
|
||||||
|
CachedDirectory.ReleaseBuffer();
|
||||||
|
|
||||||
|
if (bHasPath)
|
||||||
|
{
|
||||||
|
if (!CreateDirectoryW(CachedDirectory, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
CachedDirectory.Empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CachedDirectory.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedDirectoryInitialized = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathAppendW(DirectoryStr, L"rapps");
|
Directory = CachedDirectory;
|
||||||
Directory.ReleaseBuffer();
|
return !Directory.IsEmpty();
|
||||||
|
|
||||||
return (CreateDirectoryW(Directory.GetString(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID InitLogs()
|
VOID InitLogs()
|
||||||
|
|
Loading…
Reference in a new issue