Added support for @Resources

This commit is contained in:
Birunthan Mohanathas 2012-05-20 16:12:13 +03:00
parent 965a400657
commit cb0fd823e7
10 changed files with 152 additions and 66 deletions

View File

@ -51,10 +51,8 @@ CConfigParser::~CConfigParser()
{
}
void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow, LPCTSTR config)
void CConfigParser::Initialize(const std::wstring& filename, CMeterWindow* meterWindow, LPCTSTR config)
{
m_Filename = filename;
m_Measures.clear();
m_Sections.clear();
m_Values.clear();
@ -70,12 +68,19 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW
m_CurrentSection = NULL;
// Set the built-in variables. Do this before the ini file is read so that the paths can be used with @include
SetBuiltInVariables(pRainmeter, meterWindow);
SetBuiltInVariables(filename, meterWindow);
ResetMonitorVariables(meterWindow);
CSystem::UpdateIniFileMappingList();
ReadIniFile(m_Filename, config);
std::wstring resourcePath;
if (meterWindow)
{
resourcePath = meterWindow->GetSkinRootPath();
resourcePath += L"@Resources\\";
}
ReadIniFile(filename, resourcePath, config);
ReadVariables();
// Clear and minimize
@ -83,18 +88,16 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW
m_ListVariables.clear();
}
void CConfigParser::SetBuiltInVariables(CRainmeter* pRainmeter, CMeterWindow* meterWindow)
void CConfigParser::SetBuiltInVariables(const std::wstring& filename, CMeterWindow* meterWindow)
{
if (pRainmeter)
{
SetBuiltInVariable(L"PROGRAMPATH", pRainmeter->GetPath());
SetBuiltInVariable(L"PROGRAMDRIVE", pRainmeter->GetDrive());
SetBuiltInVariable(L"SETTINGSPATH", pRainmeter->GetSettingsPath());
SetBuiltInVariable(L"SKINSPATH", pRainmeter->GetSkinPath());
SetBuiltInVariable(L"PLUGINSPATH", pRainmeter->GetPluginPath());
SetBuiltInVariable(L"CURRENTPATH", CRainmeter::ExtractPath(m_Filename));
SetBuiltInVariable(L"ADDONSPATH", pRainmeter->GetAddonPath());
}
SetBuiltInVariable(L"PROGRAMPATH", Rainmeter->GetPath());
SetBuiltInVariable(L"PROGRAMDRIVE", Rainmeter->GetDrive());
SetBuiltInVariable(L"SETTINGSPATH", Rainmeter->GetSettingsPath());
SetBuiltInVariable(L"SKINSPATH", Rainmeter->GetSkinPath());
SetBuiltInVariable(L"PLUGINSPATH", Rainmeter->GetPluginPath());
SetBuiltInVariable(L"CURRENTPATH", CRainmeter::ExtractPath(filename));
SetBuiltInVariable(L"ADDONSPATH", Rainmeter->GetAddonPath());
if (meterWindow)
{
SetBuiltInVariable(L"CURRENTFILE", meterWindow->GetSkinIniFile());
@ -1152,7 +1155,7 @@ RECT CConfigParser::ParseRECT(LPCTSTR string)
** Reads the given ini file and fills the m_Values and m_Keys maps.
**
*/
void CConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR config, int depth)
void CConfigParser::ReadIniFile(const std::wstring& iniFile, const std::wstring& resourcePath, LPCTSTR config, int depth)
{
if (depth > 100) // Is 100 enough to assume the include loop never ends?
{
@ -1316,10 +1319,18 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR config, int
ReplaceVariables(value);
if (!CSystem::IsAbsolutePath(value))
{
// It's a relative path so add the current path as a prefix
value.insert(0, CRainmeter::ExtractPath(iniFile));
if (!resourcePath.empty() &&
value[0] == L'@' && value[1] == L'\\') // value[1] == L'\0' if value.size() == 1
{
value.replace(0, 2, resourcePath);
}
else
{
// Relative to the ini folder
value.insert(0, CRainmeter::ExtractPath(iniFile));
}
}
ReadIniFile(value, config, depth + 1);
ReadIniFile(value, resourcePath, config, depth + 1);
}
}
else

View File

@ -40,7 +40,7 @@ public:
CConfigParser();
~CConfigParser();
void Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterWindow* meterWindow = NULL, LPCTSTR config = NULL);
void Initialize(const std::wstring& filename, CMeterWindow* meterWindow = NULL, LPCTSTR config = NULL);
void AddMeasure(CMeasure* pMeasure);
bool GetVariable(const std::wstring& strVariable, std::wstring& strValue);
@ -81,7 +81,6 @@ public:
bool ParseFormula(const std::wstring& formula, double* resultValue);
const std::wstring& GetFilename() { return m_Filename; }
const std::list<std::wstring>& GetSections() { return m_Sections; }
bool ReplaceVariables(std::wstring& result);
@ -101,13 +100,13 @@ public:
static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); }
private:
void SetBuiltInVariables(CRainmeter* pRainmeter, CMeterWindow* meterWindow);
void SetBuiltInVariables(const std::wstring& filename, CMeterWindow* meterWindow);
void ReadVariables();
CMeasure* GetMeasure(const std::wstring& name);
void ReadIniFile(const std::wstring& strFileName, LPCTSTR config = NULL, int depth = 0);
void ReadIniFile(const std::wstring& iniFile, const std::wstring& resourcePath, LPCTSTR config = NULL, int depth = 0);
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
@ -122,8 +121,6 @@ private:
static std::wstring StrToUpper(const WCHAR* str) { std::wstring strTmp(str); StrToUpperC(strTmp); return strTmp; }
static std::wstring& StrToUpperC(std::wstring& str) { _wcsupr(&str[0]); return str; }
std::wstring m_Filename;
std::unordered_map<std::wstring, CMeasure*> m_Measures;
std::vector<std::wstring> m_StyleTemplate;

View File

@ -1429,7 +1429,7 @@ INT_PTR CDialogManage::CTabThemes::OnCommand(WPARAM wParam, LPARAM lParam)
if (Button_GetCheck(item) == BST_CHECKED)
{
CConfigParser parser;
parser.Initialize(path.c_str(), Rainmeter);
parser.Initialize(path);
// Remove sections with Active=0
std::list<std::wstring>::const_iterator iter = parser.GetSections().begin();

View File

@ -569,12 +569,12 @@ void CMeasureNet::ResetStats()
** Reads statistics.
**
*/
void CMeasureNet::ReadStats(const WCHAR* iniFile, std::wstring& statsDate)
void CMeasureNet::ReadStats(const std::wstring& iniFile, std::wstring& statsDate)
{
WCHAR buffer[48];
CConfigParser parser;
parser.Initialize(iniFile, NULL, NULL, L"Statistics");
parser.Initialize(iniFile, NULL, L"Statistics");
const std::wstring& date = parser.ReadString(L"Statistics", L"Since", L"", false);
if (!date.empty())

View File

@ -48,7 +48,7 @@ public:
static void UpdateStats();
static void ResetStats();
static void ReadStats(const WCHAR* iniFile, std::wstring& statsDate);
static void ReadStats(const std::wstring& iniFile, std::wstring& statsDate);
static void WriteStats(const WCHAR* iniFile, const std::wstring& statsDate);
static void InitializeNewApi();

View File

@ -208,7 +208,7 @@ void CMeasurePlugin::ReadConfig(CConfigParser& parser, const WCHAR* section)
if (initializeFunc)
{
maxValue = ((INITIALIZE)initializeFunc)(m_Plugin, parser.GetFilename().c_str(), section, m_ID);
maxValue = ((INITIALIZE)initializeFunc)(m_Plugin, m_MeterWindow->GetSkinFilePath().c_str(), section, m_ID);
}
}

View File

@ -137,6 +137,7 @@ CMeterWindow::CMeterWindow(const std::wstring& config, const std::wstring& iniFi
m_Refreshing(false),
m_Hidden(false),
m_ResizeWindow(RESIZEMODE_NONE),
m_ResourcesFolder(false),
m_UpdateCounter(),
m_MouseMoveCounter(),
m_FontCollection(),
@ -1801,7 +1802,7 @@ void CMeterWindow::ReadConfig()
m_ConfigGroup.clear();
CConfigParser parser;
parser.Initialize(iniFile.c_str(), Rainmeter, NULL, m_SkinName.c_str());
parser.Initialize(iniFile, NULL, m_SkinName.c_str());
for (int i = 0; i < 2; ++i)
{
@ -1958,7 +1959,18 @@ bool CMeterWindow::ReadSkin()
return false;
}
m_Parser.Initialize(iniFile.c_str(), Rainmeter, this);
std::wstring::size_type suiteLen;
if ((suiteLen = m_SkinName.find_first_of(L'\\')) == std::wstring::npos)
{
suiteLen = m_SkinName.size();
}
std::wstring resourcePath = Rainmeter->GetSkinPath();
resourcePath.append(m_SkinName, 0, suiteLen);
resourcePath += L"\\@Resources\\";
m_ResourcesFolder = (_waccess(resourcePath.c_str(), 0) == 0);
m_Parser.Initialize(iniFile, this);
// Check the version
UINT appVersion = m_Parser.ReadUInt(L"Rainmeter", L"AppVersion", 0);
@ -2052,8 +2064,7 @@ bool CMeterWindow::ReadSkin()
{
ResizeBlur(blurRegion, RGN_OR);
// Here we are checking to see if there are more than one blur region
// to be loaded. They will be named BlurRegion2, BlurRegion3, etc.
// Check for BlurRegion2, BlurRegion3, etc.
_snwprintf_s(buffer, _TRUNCATE, L"BlurRegion%i", ++i);
blurRegion = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str();
}
@ -2070,36 +2081,73 @@ bool CMeterWindow::ReadSkin()
}
}
// Load fonts in Resources folder
if (m_ResourcesFolder)
{
WIN32_FIND_DATA fd;
resourcePath += L"Fonts\\*";
HANDLE find = FindFirstFileEx(
resourcePath.c_str(),
(CSystem::GetOSPlatform() >= OSPLATFORM_7) ? FindExInfoBasic : FindExInfoStandard,
&fd,
FindExSearchNameMatch,
NULL,
0);
if (find != INVALID_HANDLE_VALUE)
{
m_FontCollection = new PrivateFontCollection();
do
{
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
std::wstring file(resourcePath, 0, resourcePath.length() - 1);
file += fd.cFileName;
Status status = m_FontCollection->AddFontFile(file.c_str());
if (status != Ok)
{
std::wstring error = L"Unable to load font: ";
error += file.c_str();
Log(LOG_ERROR, error.c_str());
}
}
}
while (FindNextFile(find, &fd));
}
}
// Load local fonts
const WCHAR* localFont = m_Parser.ReadString(L"Rainmeter", L"LocalFont", L"").c_str();
if (*localFont)
{
m_FontCollection = new PrivateFontCollection();
int i = 1;
if (!m_FontCollection)
{
m_FontCollection = new PrivateFontCollection();
}
int i = 1;
do
{
// Try program folder first
std::wstring szFontFile = Rainmeter->GetPath() + L"Fonts\\";
szFontFile += localFont;
Status nResults = m_FontCollection->AddFontFile(szFontFile.c_str());
if (nResults != Ok)
Status status = m_FontCollection->AddFontFile(szFontFile.c_str());
if (status != Ok)
{
szFontFile = localFont;
MakePathAbsolute(szFontFile);
nResults = m_FontCollection->AddFontFile(szFontFile.c_str());
if (nResults != Ok)
status = m_FontCollection->AddFontFile(szFontFile.c_str());
if (status != Ok)
{
std::wstring error = L"Unable to load font file: ";
std::wstring error = L"Unable to load font: ";
error += localFont;
Log(LOG_ERROR, error.c_str());
}
}
// Here we are checking to see if there are more than one local font
// to be loaded. They will be named LocalFont2, LocalFont3, etc.
// Check for LocalFont2, LocalFont3, etc.
_snwprintf_s(buffer, _TRUNCATE, L"LocalFont%i", ++i);
localFont = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str();
}
@ -4640,15 +4688,44 @@ void CMeterWindow::MakePathAbsolute(std::wstring& path)
else
{
std::wstring absolute;
absolute.reserve(Rainmeter->GetSkinPath().size() + m_SkinName.size() + 1 + path.size());
absolute = Rainmeter->GetSkinPath();
absolute += m_SkinName;
absolute += L'\\';
absolute += path;
if (m_ResourcesFolder && (path[0] == L'@' && path[1] == L'\\')) // path[1] == L'\0' if path.size() == 1
{
const std::wstring::size_type resourcesLen = 13; // Count of "\\@Resources\\"
std::wstring::size_type suiteLen;
if ((suiteLen = m_SkinName.find_first_of(L'\\')) == std::wstring::npos)
{
suiteLen = m_SkinName.size();
}
absolute.reserve(Rainmeter->GetSkinPath().size() + suiteLen + resourcesLen + (path.size() - 2));
absolute = Rainmeter->GetSkinPath();
absolute.append(m_SkinName, 0, suiteLen);
absolute += L"\\@Resources\\";
absolute.append(path, 2, path.length() - 1);
}
else
{
absolute.reserve(Rainmeter->GetSkinPath().size() + m_SkinName.size() + 1 + path.size());
absolute = Rainmeter->GetSkinPath();
absolute += m_SkinName;
absolute += L'\\';
absolute += path;
}
absolute.swap(path);
}
}
std::wstring CMeterWindow::GetSkinFilePath()
{
std::wstring file = Rainmeter->GetSkinPath() + m_SkinName;
file += L'\\';
file += m_SkinIniFile;
return file;
}
std::wstring CMeterWindow::GetSkinRootPath()
{
std::wstring path = Rainmeter->GetSkinPath();

View File

@ -203,6 +203,7 @@ public:
const std::wstring& GetSkinName() { return m_SkinName; }
const std::wstring& GetSkinIniFile() { return m_SkinIniFile; }
std::wstring GetSkinFilePath();
std::wstring GetSkinRootPath();
std::list<CMeasure*>& GetMeasures() { return m_Measures; }
@ -450,6 +451,8 @@ private:
const std::wstring m_SkinName; // Name of the current skin folder
const std::wstring m_SkinIniFile; // Name of the current skin iniFile
bool m_ResourcesFolder;
int m_UpdateCounter;
UINT m_MouseMoveCounter;

View File

@ -1552,10 +1552,10 @@ void CRainmeter::ScanForConfigs(const std::wstring& path)
m_ConfigMenu.clear();
m_ConfigOrders.clear();
ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu, false);
ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu);
}
int CRainmeter::ScanForConfigsRecursive(const std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse)
int CRainmeter::ScanForConfigsRecursive(const std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool rootSkinFolder)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
HANDLE hSearch; // Search handle returned by FindFirstFile
@ -1589,7 +1589,8 @@ int CRainmeter::ScanForConfigsRecursive(const std::wstring& path, std::wstring b
{
if (wcscmp(L".", fileData.cFileName) != 0 &&
wcscmp(L"..", fileData.cFileName) != 0 &&
!(first && wcscmp(L"Backup", fileData.cFileName) == 0)) // Skip the backup folder
!(first && wcscmp(L"Backup", fileData.cFileName) == 0) &&
!(rootSkinFolder && wcscmp(L"@Resources", fileData.cFileName) == 0))
{
folders.push_back(filename);
}
@ -1635,16 +1636,13 @@ int CRainmeter::ScanForConfigsRecursive(const std::wstring& path, std::wstring b
menuItem.index = -1;
menu.push_back(std::move(menuItem));
if (!DontRecurse)
{
std::vector<CONFIGMENU>::iterator iter2 = menu.end() - 1;
index = ScanForConfigsRecursive(path, base + (*iter), index, (*iter2).children, false);
std::vector<CONFIGMENU>::iterator iter2 = menu.end() - 1;
index = ScanForConfigsRecursive(path, base + (*iter), index, (*iter2).children, base.empty());
// Remove menu item if it has no child
if ((*iter2).children.empty())
{
menu.erase(iter2);
}
// Remove menu item if it has no child
if ((*iter2).children.empty())
{
menu.erase(iter2);
}
}
@ -2169,7 +2167,7 @@ void CRainmeter::ReadGeneralSettings(const std::wstring& iniFile)
m_DesktopWorkAreas.clear();
CConfigParser parser;
parser.Initialize(iniFile.c_str(), this);
parser.Initialize(iniFile, NULL, NULL);
// Read Logging settings
m_Logging = 0!=parser.ReadInt(L"Rainmeter", L"Logging", 0);
@ -2567,7 +2565,7 @@ void CRainmeter::ReadStats()
}
// Only Net measure has stats at the moment
CMeasureNet::ReadStats(statsFile, m_StatsDate);
CMeasureNet::ReadStats(m_StatsFile, m_StatsDate);
}
/*

View File

@ -258,7 +258,7 @@ private:
void UpdateDesktopWorkArea(bool reset);
HMENU CreateSkinMenu(CMeterWindow* meterWindow, int index, HMENU configMenu);
void ChangeSkinIndex(HMENU subMenu, int index);
int ScanForConfigsRecursive(const std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse);
int ScanForConfigsRecursive(const std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool rootSkinFolder = false);
HMENU CreateConfigMenu(HMENU configMenu, const std::vector<CONFIGMENU>& configMenuData);
void CreateThemeMenu(HMENU themeMenu);
void CreateMonitorMenu(HMENU monitorMenu, CMeterWindow* meterWindow);