diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index 2c619a7e..104818d8 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -80,10 +80,9 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW SetBuiltInVariables(pRainmeter, meterWindow); ResetMonitorVariables(meterWindow); - std::vector iniFileMappings; - CSystem::GetIniFileMappingList(iniFileMappings); + CSystem::UpdateIniFileMappingList(); - ReadIniFile(iniFileMappings, m_Filename, config); + ReadIniFile(m_Filename, config); ReadVariables(); // Clear and minimize @@ -449,35 +448,35 @@ bool CConfigParser::ReplaceVariables(std::wstring& result) } // Check for variables (#VAR#) - size_t start = 0; - size_t end = std::wstring::npos; - size_t pos = std::wstring::npos; + size_t start = 0, end; bool loop = true; do { - pos = result.find(L'#', start); - if (pos != std::wstring::npos) + start = result.find(L'#', start); + if (start != std::wstring::npos) { - end = result.find(L'#', pos + 1); + size_t si = start + 1; + end = result.find(L'#', si); if (end != std::wstring::npos) { - if (result[pos + 1] == L'*' && result[end - 1] == L'*') + size_t ei = end - 1; + if (result[si] == L'*' && result[ei] == L'*') { - result.erase(pos + 1, 1); - result.erase(end - 2, 1); - start = end - 1; + result.erase(ei, 1); + result.erase(si, 1); + start = ei; } else { - std::wstring strVariable = result.substr(pos + 1, end - (pos + 1)); + std::wstring strVariable = result.substr(si, end - si); std::wstring strValue; if (GetVariable(strVariable, strValue)) { // Variable found, replace it with the value - result.replace(pos, end - pos + 1, strValue); - start = pos + strValue.length(); + result.replace(start, end - start + 1, strValue); + start += strValue.length(); replaced = true; } else @@ -513,40 +512,40 @@ bool CConfigParser::ReplaceMeasures(std::wstring& result) // Check for measures ([Measure]) if (!m_Measures.empty()) { - size_t start = 0; - size_t end = std::wstring::npos; - size_t pos = std::wstring::npos; - size_t pos2 = std::wstring::npos; + size_t start = 0, end, next; bool loop = true; + do { - pos = result.find(L'[', start); - if (pos != std::wstring::npos) + start = result.find(L'[', start); + if (start != std::wstring::npos) { - end = result.find(L']', pos + 1); + size_t si = start + 1; + end = result.find(L']', si); if (end != std::wstring::npos) { - pos2 = result.find(L'[', pos + 1); - if (pos2 == std::wstring::npos || end < pos2) + next = result.find(L'[', si); + if (next == std::wstring::npos || end < next) { - if (result[pos + 1] == L'*' && result[end - 1] == L'*') + size_t ei = end - 1; + if (result[si] == L'*' && result[ei] == L'*') { - result.erase(pos + 1, 1); - result.erase(end - 2, 1); - start = end - 1; + result.erase(ei, 1); + result.erase(si, 1); + start = ei; } else { - std::wstring var = result.substr(pos + 1, end - (pos + 1)); + std::wstring var = result.substr(si, end - si); CMeasure* measure = GetMeasure(var); if (measure) { - std::wstring value = measure->GetStringValue(AUTOSCALE_OFF, 1, -1, false); + const std::wstring& value = measure->GetStringValue(AUTOSCALE_OFF, 1, -1, false); // Measure found, replace it with the value - result.replace(pos, end - pos + 1, value); - start = pos + value.length(); + result.replace(start, end - start + 1, value); + start += value.length(); replaced = true; } else @@ -557,7 +556,7 @@ bool CConfigParser::ReplaceMeasures(std::wstring& result) } else { - start = pos2; + start = next; } } else @@ -835,8 +834,8 @@ void CConfigParser::Shrink(std::vector& vec) { if (!vec.empty()) { - std::vector::iterator iter = vec.begin(); - while (iter != vec.end()) + std::vector::reverse_iterator iter = vec.rbegin(); + while (iter != vec.rend()) { std::wstring::size_type pos = (*iter).find_first_not_of(L" \t\r\n"); if (pos != std::wstring::npos) @@ -852,7 +851,7 @@ void CConfigParser::Shrink(std::vector& vec) else { // Remove empty element - iter = vec.erase(iter); + vec.erase((++iter).base()); } } } @@ -1042,7 +1041,7 @@ RECT CConfigParser::ParseRECT(LPCTSTR string) ** ** \param iniFile The ini file to be read. */ -void CConfigParser::ReadIniFile(const std::vector& iniFileMappings, const std::wstring& iniFile, LPCTSTR config, int depth) +void CConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR config, int depth) { if (depth > 100) // Is 100 enough to assume the include loop never ends? { @@ -1058,7 +1057,7 @@ void CConfigParser::ReadIniFile(const std::vector& iniFileMappings } // Avoid "IniFileMapping" - std::wstring iniRead = CSystem::GetTemporaryFile(iniFileMappings, iniFile); + std::wstring iniRead = CSystem::GetTemporaryFile(iniFile); bool temporary = (!iniRead.empty() && (iniRead.size() != 1 || iniRead[0] != L'?')); if (temporary) @@ -1196,7 +1195,7 @@ void CConfigParser::ReadIniFile(const std::vector& iniFileMappings // It's a relative path so add the current path as a prefix value.insert(0, CRainmeter::ExtractPath(iniFile)); } - ReadIniFile(iniFileMappings, value, config, depth + 1); + ReadIniFile(value, config, depth + 1); } else { diff --git a/Library/ConfigParser.h b/Library/ConfigParser.h index d37f4696..117ac34f 100644 --- a/Library/ConfigParser.h +++ b/Library/ConfigParser.h @@ -100,7 +100,7 @@ private: CMeasure* GetMeasure(const std::wstring& name); - void ReadIniFile(const std::vector& iniFileMappings, const std::wstring& strFileName, LPCTSTR config = NULL, int depth = 0); + void ReadIniFile(const std::wstring& strFileName, LPCTSTR config = NULL, int depth = 0); void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow); diff --git a/Library/MeterString.cpp b/Library/MeterString.cpp index 700804d1..b80b73ea 100644 --- a/Library/MeterString.cpp +++ b/Library/MeterString.cpp @@ -114,7 +114,7 @@ int CMeterString::GetX(bool abs) switch (m_Align) { case ALIGN_CENTER: - x = x - (m_W / 2); + x -= m_W / 2; break; case ALIGN_RIGHT: diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index f0006f32..bf02ade1 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -649,9 +649,8 @@ void CRainmeter::RainmeterWriteKeyValue(const WCHAR* arg) } // Avoid "IniFileMapping" - std::vector iniFileMappings; - CSystem::GetIniFileMappingList(iniFileMappings); - std::wstring iniWrite = CSystem::GetTemporaryFile(iniFileMappings, iniFile); + CSystem::UpdateIniFileMappingList(); + std::wstring iniWrite = CSystem::GetTemporaryFile(iniFile); if (iniWrite.size() == 1 && iniWrite[0] == L'?') // error occurred { return; @@ -869,7 +868,7 @@ int CRainmeter::Initialize(HWND hParent, HINSTANCE hInstance, LPCWSTR szPath) { iniFile += L"Rainmeter.ini"; } - else if (iniFile.length() <= 4 || _wcsicmp(iniFile.substr(iniFile.length() - 4).c_str(), L".ini") != 0) + else if (iniFile.length() <= 4 || _wcsicmp(iniFile.c_str() + (iniFile.length() - 4), L".ini") != 0) { iniFile += L"\\Rainmeter.ini"; } @@ -912,7 +911,7 @@ int CRainmeter::Initialize(HWND hParent, HINSTANCE hInstance, LPCWSTR szPath) // Set the log file and stats file location m_LogFile = m_StatsFile = m_IniFile; size_t logFileLen = m_LogFile.length(); - if (logFileLen > 4 && _wcsicmp(m_LogFile.substr(logFileLen - 4).c_str(), L".ini") == 0) + if (logFileLen > 4 && _wcsicmp(m_LogFile.c_str() + (logFileLen - 4), L".ini") == 0) { m_LogFile.replace(logFileLen - 4, 4, L".log"); m_StatsFile.replace(logFileLen - 4, 4, L".stats"); diff --git a/Library/System.cpp b/Library/System.cpp index 124e51c4..f0b96036 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -36,9 +36,10 @@ enum TIMER }; enum INTERVAL { - INTERVAL_SHOWDESKTOP = 250, - INTERVAL_NETSTATS = 60000, - INTERVAL_DELETELATER = 1000 + INTERVAL_SHOWDESKTOP = 250, + INTERVAL_RESTOREWINDOWS = 100, + INTERVAL_NETSTATS = 60000, + INTERVAL_DELETELATER = 1000 }; MULTIMONITOR_INFO CSystem::c_Monitors = { 0 }; @@ -54,6 +55,8 @@ OSPLATFORM CSystem::c_Platform = OSPLATFORM_UNKNOWN; std::wstring CSystem::c_WorkingDirectory; +std::vector CSystem::c_IniFileMappings; + extern CRainmeter* Rainmeter; /* @@ -909,12 +912,10 @@ bool CSystem::CheckDesktopState(HWND WorkerW) if (c_ShowDesktop) { - KillTimer(c_Window, TIMER_SHOWDESKTOP); - SetTimer(c_Window, TIMER_SHOWDESKTOP, 100, NULL); + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_RESTOREWINDOWS, NULL); } else { - KillTimer(c_Window, TIMER_SHOWDESKTOP); SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); } } @@ -1240,30 +1241,65 @@ bool CSystem::RemoveFolder(const std::wstring& strFolder) } /* -** GetIniFileMappingList +** UpdateIniFileMappingList ** ** Retrieves the "IniFileMapping" entries from Registry. ** */ -void CSystem::GetIniFileMappingList(std::vector& iniFileMappings) +void CSystem::UpdateIniFileMappingList() { - HKEY hKey; - LONG ret; + static ULARGE_INTEGER s_LastWriteTime = {0}; - ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_ENUMERATE_SUB_KEYS, &hKey); + HKEY hKey; + LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey); if (ret == ERROR_SUCCESS) { - WCHAR buffer[MAX_PATH]; - DWORD index = 0, cch = MAX_PATH; + DWORD numSubKeys; + ULARGE_INTEGER ftLastWriteTime; + bool changed = false; - while ((ret = RegEnumKeyEx(hKey, index++, buffer, &cch, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS) + ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, (LPFILETIME)&ftLastWriteTime); + if (ret == ERROR_SUCCESS) { - if (ret == ERROR_SUCCESS) + //LogWithArgs(LOG_DEBUG, L"IniFileMapping: numSubKeys=%u, ftLastWriteTime=%llu", numSubKeys, ftLastWriteTime.QuadPart); + + if (ftLastWriteTime.QuadPart != s_LastWriteTime.QuadPart || + numSubKeys != c_IniFileMappings.size()) { - iniFileMappings.push_back(buffer); + s_LastWriteTime.QuadPart = ftLastWriteTime.QuadPart; + if (numSubKeys > c_IniFileMappings.capacity()) + { + c_IniFileMappings.reserve(numSubKeys); + } + changed = true; } - cch = MAX_PATH; } + else + { + s_LastWriteTime.QuadPart = 0; + changed = true; + } + + if (changed) + { + if (!c_IniFileMappings.empty()) + { + c_IniFileMappings.clear(); + } + + WCHAR buffer[MAX_PATH]; + DWORD index = 0, cch = MAX_PATH; + + while ((ret = RegEnumKeyEx(hKey, index++, buffer, &cch, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS) + { + if (ret == ERROR_SUCCESS) + { + c_IniFileMappings.push_back(buffer); + } + cch = MAX_PATH; + } + } + RegCloseKey(hKey); } } @@ -1276,28 +1312,19 @@ void CSystem::GetIniFileMappingList(std::vector& iniFileMappings) ** Note that a temporary file must be deleted by caller. ** */ -std::wstring CSystem::GetTemporaryFile(const std::vector& iniFileMappings, const std::wstring& iniFile) +std::wstring CSystem::GetTemporaryFile(const std::wstring& iniFile) { std::wstring temporary; - if (!iniFileMappings.empty()) + if (!c_IniFileMappings.empty()) { std::wstring::size_type pos = iniFile.find_last_of(L"\\/"); - std::wstring filename; + const WCHAR* filename = iniFile.c_str() + ((pos != std::wstring::npos) ? pos + 1 : 0); - if (pos != std::wstring::npos) + std::vector::const_iterator iter = c_IniFileMappings.begin(); + for ( ; iter != c_IniFileMappings.end(); ++iter) { - filename.assign(iniFile, pos + 1, iniFile.length() - (pos + 1)); - } - else - { - filename = iniFile; - } - - std::vector::const_iterator iter = iniFileMappings.begin(); - for ( ; iter != iniFileMappings.end(); ++iter) - { - if (_wcsicmp((*iter).c_str(), filename.c_str()) == 0) + if (_wcsicmp((*iter).c_str(), filename) == 0) { WCHAR buffer[MAX_PATH]; @@ -1307,7 +1334,7 @@ std::wstring CSystem::GetTemporaryFile(const std::vector& iniFileM { temporary = buffer; - std::wstring tmp = GetTemporaryFile(iniFileMappings, temporary); + std::wstring tmp = GetTemporaryFile(temporary); if (tmp.empty() && CopyFiles(iniFile, temporary)) { return temporary; diff --git a/Library/System.h b/Library/System.h index 2c13c07c..087bf53c 100644 --- a/Library/System.h +++ b/Library/System.h @@ -85,8 +85,8 @@ public: static bool RemoveFile(const std::wstring& file); static bool RemoveFolder(const std::wstring& strFolder); - static void GetIniFileMappingList(std::vector& iniFileMappings); - static std::wstring GetTemporaryFile(const std::vector& iniFileMappings, const std::wstring& iniFile); + static void UpdateIniFileMappingList(); + static std::wstring GetTemporaryFile(const std::wstring& iniFile); private: static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime); @@ -118,6 +118,8 @@ private: static OSPLATFORM c_Platform; static std::wstring c_WorkingDirectory; + + static std::vector c_IniFileMappings; }; #endif