Added skin/section (if available) to logging.

This commit is contained in:
Brian Ferguson 2013-06-29 10:59:18 -06:00
parent 6d87614d4c
commit eeef84dfa0
29 changed files with 344 additions and 136 deletions

View File

@ -167,4 +167,5 @@ STRINGTABLE
ID_STR_EDITORSC, "Editor:"
ID_STR_ELLIPSIS, "..."
ID_STR_SHOWNOTIFICATIONAREAICON, "Show notification area icon"
ID_STR_SOURCE, "Source"
}

View File

@ -165,7 +165,7 @@ void DoBang(const BangInfo& bangInfo, std::vector<std::wstring>& args, MeterWind
}
else
{
LogErrorF(L"!%s: Skin \"%s\" not found", folderPath.c_str(), bangInfo.name);
LogErrorF(skin, L"!%s: Skin \"%s\" not found", folderPath.c_str(), bangInfo.name);
}
return;
}
@ -191,13 +191,13 @@ void DoBang(const BangInfo& bangInfo, std::vector<std::wstring>& args, MeterWind
firstArg.erase(0, pos + 1);
args.insert(args.begin(), newArg);
LogWarningF(L"!%s: Two parameters required, only one given", bangInfo.name);
LogWarningF(skin, L"!%s: Two parameters required, only one given", bangInfo.name);
DoBang(bangInfo, args, skin);
return;
}
}
LogErrorF(L"!%s: Incorrect number of arguments", bangInfo.name);
LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name);
}
}
@ -218,7 +218,7 @@ void DoGroupBang(const BangInfo& bangInfo, std::vector<std::wstring>& args, Mete
}
else
{
LogErrorF(L"!%s: Incorrect number of arguments", bangInfo.name);
LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name);
}
}
@ -401,7 +401,7 @@ void CommandHandler::ExecuteBang(const WCHAR* name, std::vector<std::wstring>& a
}
}
LogErrorF(L"Invalid bang: !%s", name);
LogErrorF(skin, L"Invalid bang: !%s", name);
}
/*
@ -584,7 +584,7 @@ void CommandHandler::DoActivateSkinBang(std::vector<std::wstring>& args, MeterWi
if (GetRainmeter().ActivateSkin(args[0], args[1])) return;
}
LogError(L"!ActivateConfig: Invalid parameters");
LogErrorF(skin, L"!ActivateConfig: Invalid parameters");
}
void CommandHandler::DoDeactivateSkinBang(std::vector<std::wstring>& args, MeterWindow* skin)
@ -625,7 +625,7 @@ void CommandHandler::DoToggleSkinBang(std::vector<std::wstring>& args, MeterWind
}
else
{
LogError(L"!ToggleConfig: Invalid parameters");
LogErrorF(skin, L"!ToggleConfig: Invalid parameters");
}
}
@ -642,7 +642,7 @@ void CommandHandler::DoDeactivateSkinGroupBang(std::vector<std::wstring>& args,
}
else
{
LogError(L"!DeactivateConfigGroup: Invalid parameters");
LogErrorF(skin, L"!DeactivateConfigGroup: Invalid parameters");
}
}
@ -674,7 +674,7 @@ void CommandHandler::DoSetClipBang(std::vector<std::wstring>& args, MeterWindow*
}
else
{
LogError(L"!SetClip: Invalid parameter");
LogErrorF(skin, L"!SetClip: Invalid parameter");
}
}
@ -695,7 +695,7 @@ void CommandHandler::DoSetWallpaperBang(std::vector<std::wstring>& args, MeterWi
}
else
{
LogError(L"!SetWallpaper: Invalid parameters");
LogErrorF(skin, L"!SetWallpaper: Invalid parameters");
}
}
@ -752,7 +752,7 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
}
else if (args.size() < 4)
{
LogError(L"!WriteKeyValue: Invalid parameters");
LogErrorF(skin, L"!WriteKeyValue: Invalid parameters");
return;
}
@ -766,21 +766,21 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
if (strIniFile.find(L"..\\") != std::wstring::npos || strIniFile.find(L"../") != std::wstring::npos)
{
LogErrorF(L"!WriteKeyValue: Illegal path: %s", iniFile);
LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile);
return;
}
if (_wcsnicmp(iniFile, GetRainmeter().m_SkinPath.c_str(), GetRainmeter().m_SkinPath.size()) != 0 &&
_wcsnicmp(iniFile, GetRainmeter().m_SettingsPath.c_str(), GetRainmeter().m_SettingsPath.size()) != 0)
{
LogErrorF(L"!WriteKeyValue: Illegal path: %s", iniFile);
LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile);
return;
}
// Verify whether the file exists.
if (_waccess(iniFile, 0) == -1)
{
LogErrorF(L"!WriteKeyValue: File not found: %s", iniFile);
LogErrorF(skin, L"!WriteKeyValue: File not found: %s", iniFile);
return;
}
@ -788,7 +788,7 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
DWORD attr = GetFileAttributes(iniFile);
if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY))
{
LogWarningF(L"!WriteKeyValue: File is read-only: %s", iniFile);
LogWarningF(skin, L"!WriteKeyValue: File is read-only: %s", iniFile);
return;
}
@ -806,14 +806,14 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
{
if (GetRainmeter().GetDebug())
{
LogDebugF(L"!WriteKeyValue: Writing to: %s (Temp: %s)", iniFile, strIniWrite.c_str());
LogDebugF(skin, L"!WriteKeyValue: Writing to: %s (Temp: %s)", iniFile, strIniWrite.c_str());
}
}
else
{
if (GetRainmeter().GetDebug())
{
LogDebugF(L"!WriteKeyValue: Writing to: %s", iniFile);
LogDebugF(skin, L"!WriteKeyValue: Writing to: %s", iniFile);
}
strIniWrite = strIniFile;
}
@ -854,12 +854,12 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
// Copy the file back.
if (!System::CopyFiles(strIniWrite, strIniFile))
{
LogErrorF(L"!WriteKeyValue: Failed to copy temporary file to original filepath: %s (Temp: %s)", iniFile, iniWrite);
LogErrorF(skin, L"!WriteKeyValue: Failed to copy temporary file to original filepath: %s (Temp: %s)", iniFile, iniWrite);
}
}
else // failed
{
LogErrorF(L"!WriteKeyValue: Failed to write to: %s (Temp: %s)", iniFile, iniWrite);
LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s (Temp: %s)", iniFile, iniWrite);
}
// Remove the temporary file.
@ -869,7 +869,7 @@ void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, MeterW
{
if (write == 0) // failed
{
LogErrorF(L"!WriteKeyValue: Failed to write to: %s", iniFile);
LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s", iniFile);
}
}
}
@ -896,12 +896,18 @@ void CommandHandler::DoLogBang(std::vector<std::wstring>& args, MeterWindow* ski
}
else if (_wcsicmp(type, L"NOTICE") != 0)
{
LogError(L"!Log: Invalid type");
LogErrorF(skin, L"!Log: Invalid type");
return;
}
}
GetLogger().Log(level, args[0].c_str());
std::wstring source;
if (skin)
{
source = skin->GetSkinPath();
}
GetLogger().Log(level, source.c_str(), args[0].c_str());
}
}

View File

@ -849,7 +849,7 @@ int ConfigParser::ReadInt(LPCTSTR section, LPCTSTR key, int defValue)
return (int)dblValue;
}
LogErrorF(L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
}
else if (*string)
{
@ -881,7 +881,7 @@ uint32_t ConfigParser::ReadUInt(LPCTSTR section, LPCTSTR key, uint32_t defValue)
return (uint32_t)dblValue;
}
LogErrorF(L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
}
else if (*string)
{
@ -913,7 +913,7 @@ uint64_t ConfigParser::ReadUInt64(LPCTSTR section, LPCTSTR key, uint64_t defValu
return (uint64_t)dblValue;
}
LogErrorF(L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
}
else if (*string)
{
@ -945,7 +945,7 @@ double ConfigParser::ReadFloat(LPCTSTR section, LPCTSTR key, double defValue)
return value;
}
LogErrorF(L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section);
}
else if (*string)
{
@ -971,7 +971,7 @@ bool ConfigParser::ParseFormula(const std::wstring& formula, double* resultValue
const WCHAR* errMsg = MathParser::CheckedParse(string, resultValue);
if (errMsg != nullptr)
{
LogErrorF(L"Formula: %s: %s", errMsg, string);
LogErrorF(m_MeterWindow, L"Formula: %s: %s", errMsg, string);
return false;
}
@ -1294,7 +1294,7 @@ void ConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection,
// Verify whether the file exists
if (_waccess(iniFile.c_str(), 0) == -1)
{
LogErrorF(L"Unable to read file: %s", iniFile.c_str());
LogErrorF(m_MeterWindow, L"Unable to read file: %s", iniFile.c_str());
return;
}
@ -1304,11 +1304,11 @@ void ConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection,
if (temporary)
{
if (GetRainmeter().GetDebug()) LogDebugF(L"Reading file: %s (Temp: %s)", iniFile.c_str(), iniRead.c_str());
if (GetRainmeter().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s (Temp: %s)", iniFile.c_str(), iniRead.c_str());
}
else
{
if (GetRainmeter().GetDebug()) LogDebugF(L"Reading file: %s", iniFile.c_str());
if (GetRainmeter().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s", iniFile.c_str());
iniRead = iniFile;
}

View File

@ -112,11 +112,11 @@ void DialogAbout::ShowAboutLog()
}
}
void DialogAbout::AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR message)
void DialogAbout::AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message)
{
if (c_Dialog && c_Dialog->m_TabLog.IsInitialized())
{
c_Dialog->m_TabLog.AddItem(level, time, message);
c_Dialog->m_TabLog.AddItem(level, time, source, message);
}
}
@ -176,7 +176,7 @@ INT_PTR DialogAbout::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_GETMINMAXINFO:
{
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMinTrackSize.x = 550;
mmi->ptMinTrackSize.x = 700;
mmi->ptMinTrackSize.y = 350;
}
return TRUE;
@ -402,14 +402,25 @@ void DialogAbout::TabLog::Initialize()
lvc.pszText = GetString(ID_STR_TIME);
ListView_InsertColumn(item, 1, &lvc);
lvc.iSubItem = 2;
lvc.cx = 370;
lvc.pszText = GetString(ID_STR_MESSAGE);
lvc.cx = 225;
lvc.pszText = GetString(ID_STR_SOURCE);
ListView_InsertColumn(item, 2, &lvc);
lvc.iSubItem = 4;
// Start 4th column at max width
RECT rect = {0};
if (GetWindowRect(item, &rect))
lvc.cx = rect.right - rect.left - 405;
else
lvc.cx = 180;
lvc.pszText = GetString(ID_STR_MESSAGE);
ListView_InsertColumn(item, 3, &lvc);
// Add stored entires
for (const auto& entry : GetLogger().GetEntries())
{
AddItem(entry.level, entry.timestamp.c_str(), entry.message.c_str());
AddItem(entry.level, entry.timestamp.c_str(), entry.source.c_str(), entry.message.c_str());
}
item = GetControl(Id_ErrorCheckBox);
@ -453,18 +464,21 @@ void DialogAbout::TabLog::Resize(int w, int h)
item = GetControl(Id_ItemsListView);
SetWindowPos(item, nullptr, 0, 0, w, h - r.bottom - 7, SWP_NOMOVE | SWP_NOZORDER);
// Adjust third colum
// Adjust 4th colum
LVCOLUMN lvc;
lvc.mask = LVCF_WIDTH;
lvc.cx = w - 183;
ListView_SetColumn(item, 2, &lvc);
lvc.cx = w - 20 -
(ListView_GetColumnWidth(item, 0) +
ListView_GetColumnWidth(item, 1) +
ListView_GetColumnWidth(item, 2));
ListView_SetColumn(item, 3, &lvc);
}
/*
** Adds item to log.
**
*/
void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR message)
void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message)
{
WCHAR buffer[32];
LVITEM vitem;
@ -505,7 +519,8 @@ void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR mes
item = GetControl(Id_ItemsListView);
ListView_InsertItem(item, &vitem);
ListView_SetItemText(item, vitem.iItem, 1, (WCHAR*)time);
ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)message);
ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)source);
ListView_SetItemText(item, vitem.iItem, 3, (WCHAR*)message);
if (!ListView_IsItemVisible(item, 0))
{
ListView_Scroll(item, 0, 16);
@ -579,9 +594,25 @@ INT_PTR DialogAbout::TabLog::OnNotify(WPARAM wParam, LPARAM lParam)
int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED);
if (sel != -1)
{
std::wstring tmpSz(512, L'0');
ListView_GetItemText(nm->hwndFrom, sel, 2, &tmpSz[0], 512);
System::SetClipboardText(tmpSz);
WCHAR* buffer = new WCHAR[512];
std::wstring message;
// Get Source (if any)
ListView_GetItemText(nm->hwndFrom, sel, 2, buffer, 512);
if (*buffer)
{
message = L"Source: ";
message += buffer;
message += L"\n";
}
// Get message
ListView_GetItemText(nm->hwndFrom, sel, 3, buffer, 512);
message += L"Message: ";
message += buffer;
delete [] buffer;
System::SetClipboardText(message);
}
}
}
@ -657,7 +688,14 @@ void DialogAbout::TabSkins::Initialize()
lvc.pszText = GetString(ID_STR_RANGE);
ListView_InsertColumn(item, 1, &lvc);
lvc.iSubItem = 2;
lvc.cx = 130;
// Start 3rd column at max width
RECT rect = {0};
if (GetWindowRect(item, &rect))
lvc.cx = rect.right - rect.left - 230;
else
lvc.cx = 130;
lvc.pszText = GetString(ID_STR_VALUE);
ListView_InsertColumn(item, 2, &lvc);
@ -675,16 +713,17 @@ void DialogAbout::TabSkins::Resize(int w, int h)
SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER);
HWND item = GetControl(Id_SkinsListBox);
int wList = (w < 650) ? (w - 373) : 277;
SetWindowPos(item, nullptr, 0, 0, wList, h, SWP_NOMOVE | SWP_NOZORDER);
SetWindowPos(item, nullptr, 0, 0, 265, h, SWP_NOMOVE | SWP_NOZORDER);
item = GetControl(Id_ItemsListView);
SetWindowPos(item, nullptr, (w < 650) ? (w - 365) : 285, 0, w - wList - 10, h, SWP_NOZORDER);
SetWindowPos(item, nullptr, 275, 0, w - 275, h, SWP_NOZORDER);
// Adjust third column
LVCOLUMN lvc;
lvc.mask = LVCF_WIDTH;
lvc.cx = w - wList - 243;
lvc.cx = w - 275 - 20 -
(ListView_GetColumnWidth(item, 0) +
ListView_GetColumnWidth(item, 1));
ListView_SetColumn(item, 2, &lvc);
}
@ -972,7 +1011,14 @@ void DialogAbout::TabPlugins::Initialize()
lvc.pszText = GetString(ID_STR_VERSION);
ListView_InsertColumn(item, 1, &lvc);
lvc.iSubItem = 2;
lvc.cx = 310;
// Start 3rd column at max width
RECT rect = {0};
if (GetWindowRect(item, &rect))
lvc.cx = rect.right - rect.left - 193;
else
lvc.cx = 290;
lvc.pszText = GetString(ID_STR_AUTHOR);
ListView_InsertColumn(item, 2, &lvc);
@ -1081,7 +1127,7 @@ void DialogAbout::TabPlugins::Initialize()
}
else
{
LogErrorF(L"Unable to load plugin: %s (%u)", tmpSz.c_str(), err);
LogErrorF(L"About Dialog - Unable to load plugin: %s (%u)", tmpSz.c_str(), err);
}
}
while (FindNextFile(hSearch, &fd));
@ -1111,7 +1157,9 @@ void DialogAbout::TabPlugins::Resize(int w, int h)
// Adjust third colum
LVCOLUMN lvc;
lvc.mask = LVCF_WIDTH;
lvc.cx = w - 242;
lvc.cx = w - 20 -
(ListView_GetColumnWidth(item, 0) +
ListView_GetColumnWidth(item, 1));
ListView_SetColumn(item, 2, &lvc);
}

View File

@ -35,7 +35,7 @@ public:
static void Open(const WCHAR* name);
static void ShowAboutLog();
static void AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR message);
static void AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message);
static void UpdateSkins();
static void UpdateMeasures(MeterWindow* meterWindow);
@ -65,7 +65,7 @@ private:
virtual void Initialize();
virtual void Resize(int w, int h);
void AddItem(Logger::Level level, LPCWSTR time, LPCWSTR message);
void AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message);
protected:
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);

View File

@ -112,7 +112,7 @@ BOOL LSLog(int nLevel, LPCWSTR unused, LPCWSTR pszMessage)
// Ignore Level::Debug messages from plugins unless in debug mode
if (nLevel != (int)Logger::Level::Debug || GetRainmeter().GetDebug())
{
GetLogger().Log((Logger::Level)nLevel, pszMessage);
GetLogger().Log((Logger::Level)nLevel, L"", pszMessage);
}
return TRUE;

View File

@ -99,7 +99,7 @@ void Logger::SetLogToFile(bool logToFile)
L"Rainmeter", L"Logging", logToFile ? L"1" : L"0", GetRainmeter().GetIniFile().c_str());
}
void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* msg)
void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg)
{
WCHAR timestampSz[128];
size_t len = _snwprintf_s(
@ -112,14 +112,14 @@ void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* msg)
timestamp % 1000);
// Store up to MAX_LOG_ENTIRES entries.
Entry entry = {level, std::wstring(timestampSz, len), msg};
Entry entry = {level, std::wstring(timestampSz, len), source, msg};
m_Entries.push_back(entry);
if (m_Entries.size() > MAX_LOG_ENTIRES)
{
m_Entries.pop_front();
}
DialogAbout::AddLogItem(level, timestampSz, msg);
DialogAbout::AddLogItem(level, timestampSz, source, msg);
WriteToLogFile(entry);
}
@ -139,6 +139,8 @@ void Logger::WriteToLogFile(Entry& entry)
message += L" (";
message.append(entry.timestamp);
message += L") ";
message += entry.source;
message += L": ";
message += entry.message;
message += L'\n';
@ -164,7 +166,7 @@ void Logger::WriteToLogFile(Entry& entry)
}
}
void Logger::Log(Level level, const WCHAR* msg)
void Logger::Log(Level level, const WCHAR* source, const WCHAR* msg)
{
struct DelayedEntry
{
@ -185,7 +187,7 @@ void Logger::Log(Level level, const WCHAR* msg)
while (!s_DelayedEntries.empty())
{
DelayedEntry& entry = s_DelayedEntries.front();
LogInternal(entry.level, entry.elapsed, entry.message.c_str());
LogInternal(entry.level, entry.elapsed, source, entry.message.c_str());
s_DelayedEntries.erase(s_DelayedEntries.begin());
}
@ -193,7 +195,7 @@ void Logger::Log(Level level, const WCHAR* msg)
LeaveCriticalSection(&m_CsLogDelay);
// Log the actual message.
LogInternal(level, elapsed, msg);
LogInternal(level, elapsed, source, msg);
LeaveCriticalSection(&m_CsLog);
}
@ -209,11 +211,9 @@ void Logger::Log(Level level, const WCHAR* msg)
}
}
void Logger::LogF(Level level, const WCHAR* format, ...)
void Logger::LogF(Level level, const WCHAR* source, const WCHAR* format, va_list args)
{
WCHAR* buffer = new WCHAR[1024];
va_list args;
va_start(args, format);
_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler);
_CrtSetReportMode(_CRT_ASSERT, 0);
@ -228,8 +228,133 @@ void Logger::LogF(Level level, const WCHAR* format, ...)
_set_invalid_parameter_handler(oldHandler);
Log(level, buffer);
va_end(args);
Log(level, source, buffer);
delete [] buffer;
}
void LogSection(Logger::Level level, Section* section, const WCHAR* format, va_list args)
{
std::wstring source;
if (section)
{
MeterWindow* meterWindow = section->GetMeterWindow();
if (meterWindow)
{
source = meterWindow->GetSkinPath();
source += L" - ";
}
source += L"[";
source += section->GetOriginalName();
source += L"]";
}
GetLogger().LogF(level, source.c_str(), format, args);
}
void LogMeterWindow(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args)
{
std::wstring source;
if (meterWindow)
{
source = meterWindow->GetSkinPath();
}
GetLogger().LogF(level, source.c_str(), format, args);
}
void LogErrorF(const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
GetLogger().LogF(Logger::Level::Error, L"", format, args);
va_end(args);
}
void LogErrorF(Section* section, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogSection(Logger::Level::Error, section, format, args);
va_end(args);
}
void LogErrorF(MeterWindow* meterWindow, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogMeterWindow(Logger::Level::Error, meterWindow, format, args);
va_end(args);
}
void LogWarningF(const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
GetLogger().LogF(Logger::Level::Warning, L"", format, args);
va_end(args);
}
void LogWarningF(Section* section, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogSection(Logger::Level::Warning, section, format, args);
va_end(args);
}
void LogWarningF(MeterWindow* meterWindow, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogMeterWindow(Logger::Level::Warning, meterWindow, format, args);
va_end(args);
}
void LogNoticeF(const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
GetLogger().LogF(Logger::Level::Notice, L"", format, args);
va_end(args);
}
void LogNoticeF(Section* section, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogSection(Logger::Level::Notice, section, format, args);
va_end(args);
}
void LogNoticeF(MeterWindow* meterWindow, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogMeterWindow(Logger::Level::Notice, meterWindow, format, args);
va_end(args);
}
void LogDebugF(const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
GetLogger().LogF(Logger::Level::Debug, L"", format, args);
va_end(args);
}
void LogDebugF(Section* section, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogSection(Logger::Level::Debug, section, format, args);
va_end(args);
}
void LogDebugF(MeterWindow* meterWindow, const WCHAR* format, ...)
{
va_list args;
va_start(args, format);
LogMeterWindow(Logger::Level::Debug, meterWindow, format, args);
va_end(args);
}

View File

@ -20,8 +20,11 @@
#define RM_LOGGER_H_
#include <Windows.h>
#include <cstdarg>
#include <string>
#include <list>
#include "Section.h"
#include "MeterWindow.h"
// Singleton class to handle and store log messages and control the log file.
class Logger
@ -39,6 +42,7 @@ public:
{
Level level;
std::wstring timestamp;
std::wstring source;
std::wstring message;
};
@ -53,15 +57,15 @@ public:
bool IsLogToFile() { return m_LogToFile; }
void SetLogToFile(bool logToFile);
void Log(Level level, const WCHAR* msg);
void LogF(Level level, const WCHAR* format, ...);
void Log(Level level, const WCHAR* source, const WCHAR* msg);
void LogF(Level level, const WCHAR* source, const WCHAR* format, va_list args);
const std::wstring& GetLogFilePath() { return m_LogFilePath; }
const std::list<Entry>& GetEntries() { return m_Entries; }
private:
void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* msg);
void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg);
// Appends |entry| to the log file.
void WriteToLogFile(Entry& entry);
@ -84,7 +88,7 @@ inline Logger& GetLogger() { return Logger::GetInstance(); }
#define RM_LOGGER_DEFINE_LOG_FUNCTION(name) \
inline void Log ## name(const WCHAR* msg) \
{ \
GetLogger().Log(Logger::Level::name, msg); \
GetLogger().Log(Logger::Level::name, L"", msg); \
} \
/* \
template<typename... Args> \
@ -100,11 +104,23 @@ RM_LOGGER_DEFINE_LOG_FUNCTION(Notice)
RM_LOGGER_DEFINE_LOG_FUNCTION(Debug)
// FIXME: Temporary solution until VS support variadic templates.
#define RM_LOGGER_LOGF_HELPER(name, format, ...) \
GetLogger().LogF(Logger::Level::name, format, __VA_ARGS__)
#define LogErrorF(format, ...) RM_LOGGER_LOGF_HELPER(Error, format, __VA_ARGS__)
#define LogWarningF(format, ...) RM_LOGGER_LOGF_HELPER(Warning, format, __VA_ARGS__)
#define LogNoticeF(format, ...) RM_LOGGER_LOGF_HELPER(Notice, format, __VA_ARGS__)
#define LogDebugF(format, ...) RM_LOGGER_LOGF_HELPER(Debug, format, __VA_ARGS__)
void LogSection(Logger::Level level, Section* section, const WCHAR* format, va_list args);
void LogMeterWindow(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args);
void LogErrorF(const WCHAR* format, ...);
void LogErrorF(Section* section, const WCHAR* format, ...);
void LogErrorF(MeterWindow* meterWindow, const WCHAR* format, ...);
void LogWarningF(const WCHAR* format, ...);
void LogWarningF(Section* section, const WCHAR* format, ...);
void LogWarningF(MeterWindow* meterWindow, const WCHAR* format, ...);
void LogNoticeF(const WCHAR* format, ...);
void LogNoticeF(Section* section, const WCHAR* format, ...);
void LogNoticeF(MeterWindow* meterWindow, const WCHAR* format, ...);
void LogDebugF(const WCHAR* format, ...);
void LogDebugF(Section* section, const WCHAR* format, ...);
void LogDebugF(MeterWindow* meterWindow, const WCHAR* format, ...);
#endif

View File

@ -160,7 +160,7 @@ void Measure::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
if (!ParseSubstitute(subs))
{
LogErrorF(L"Measure: Invalid Substitute=%s", subs.c_str());
LogErrorF(this, L"Measure: Invalid Substitute=%s", subs.c_str());
}
}
@ -258,7 +258,7 @@ const WCHAR* Measure::CheckSubstitute(const WCHAR* buffer)
if (re == nullptr)
{
MakePlainSubstitute(str, i);
LogNoticeF(L"Substitute: %S", error);
LogNoticeF(this, L"Substitute: %S", error);
}
else
{
@ -845,7 +845,7 @@ Measure* Measure::Create(const WCHAR* measure, MeterWindow* meterWindow, const W
return new MeasureScript(meterWindow, name);
}
LogErrorF(L"Measure=%s is not valid in [%s]", measure, name);
LogErrorF(meterWindow, L"Measure=%s is not valid in [%s]", measure, name);
return nullptr;
}
@ -856,5 +856,5 @@ Measure* Measure::Create(const WCHAR* measure, MeterWindow* meterWindow, const W
*/
void Measure::Command(const std::wstring& command)
{
LogWarningF(L"!CommandMeasure: Not supported by [%s]", m_Name.c_str());
LogWarningF(this, L"!CommandMeasure: Not supported by [%s]", m_Name.c_str());
}

View File

@ -91,7 +91,7 @@ void MeasureCPU::ReadOptions(ConfigParser& parser, const WCHAR* section)
if (processor < 0 || processor > c_NumOfProcessors)
{
LogWarningF(L"CPU: Processor=%i invalid in [%s]", processor, section);
LogWarningF(this, L"CPU: Processor=%i invalid in [%s]", processor, section);
processor = 0;
}

View File

@ -61,7 +61,7 @@ void MeasureCalc::UpdateValue()
{
if (!m_ParseError)
{
LogErrorF(L"Calc: %s in [%s]", errMsg, m_Name.c_str());
LogErrorF(this, L"Calc: %s", errMsg);
m_ParseError = true;
}
}
@ -105,7 +105,7 @@ void MeasureCalc::ReadOptions(ConfigParser& parser, const WCHAR* section)
const WCHAR* errMsg = MathParser::Check(m_Formula.c_str());
if (errMsg != nullptr)
{
LogErrorF(L"Calc: %s in [%s]", errMsg, m_Name.c_str());
LogErrorF(this, L"Calc: %s", errMsg);
m_Formula.clear();
}
}

View File

@ -183,7 +183,7 @@ void MeasureDiskSpace::ReadOptions(ConfigParser& parser, const WCHAR* section)
m_Drive = parser.ReadString(section, L"Drive", L"C:\\");
if (m_Drive.empty())
{
LogWarning(L"FreeDiskSpace: Drive= empty");
LogWarningF(this, L"FreeDiskSpace: Drive= empty");
m_Value = 0.0;
m_MaxValue = 0.0;
m_OldTotalBytes = 0;

View File

@ -141,7 +141,7 @@ void MeasurePlugin::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
if (!m_Plugin)
{
LogErrorF(L"Plugin: \"%s\" not found", pluginName.c_str());
LogErrorF(this, L"Plugin: \"%s\" not found", pluginName.c_str());
return;
}
}

View File

@ -135,7 +135,7 @@ void MeasureRegistry::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"RegHKey=%s is not valid in [%s]", keyname, m_Name.c_str());
LogErrorF(this, L"RegHKey=%s is not valid", keyname);
}
m_RegKeyName = parser.ReadString(section, L"RegKey", L"");

View File

@ -121,7 +121,7 @@ void MeasureScript::ReadOptions(ConfigParser& parser, const WCHAR* section)
if (m_HasGetStringFunction)
{
LogWarningF(L"Script: Using deprecated GetStringValue() in [%s]", m_Name.c_str());
LogWarningF(this, L"Script: Using deprecated GetStringValue()");
}
lua_rawgeti(L, LUA_GLOBALSINDEX, m_LuaScript.GetRef());
@ -183,7 +183,7 @@ void MeasureScript::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
}
LogErrorF(L"Script: File not valid in [%s]", m_Name.c_str());
LogErrorF(this, L"Script: File not valid");
UninitializeLuaScript();
}

View File

@ -73,7 +73,7 @@ void MeasureTime::TimeToString(WCHAR* buf, size_t bufLen, const WCHAR* format, c
wcsftime(buf, bufLen, format, time);
if (errno == EINVAL)
{
LogErrorF(L"Time: \"Format=%s\" invalid in [%s]", format, m_Name.c_str());
LogErrorF(this, L"Time: \"Format=%s\" invalid", format);
buf[0] = 0;
}

View File

@ -95,7 +95,7 @@ const WCHAR* MeasureUptime::GetStringValue()
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
LogErrorF(L"Uptime: \"Format=%s\" invalid in [%s]", m_Format.c_str(), m_Name.c_str());
LogErrorF(this, L"Uptime: \"Format=%s\" invalid", m_Format.c_str());
buffer[0] = 0;
}

View File

@ -349,7 +349,7 @@ void Meter::ReadOptions(ConfigParser& parser, const WCHAR* section)
delete m_Transformation;
m_Transformation = nullptr;
LogErrorF(L"Meter: Incorrect number of values in TransformationMatrix=%s", parser.ReadString(section, L"TransformationMatrix", L"").c_str());
LogErrorF(this, L"Meter: Incorrect number of values in TransformationMatrix=%s", parser.ReadString(section, L"TransformationMatrix", L"").c_str());
}
}
@ -407,7 +407,7 @@ Meter* Meter::Create(const WCHAR* meter, MeterWindow* meterWindow, const WCHAR*
return new MeterButton(meterWindow, name);
}
LogErrorF(L"Meter=%s is not valid in [%s]", meter, name);
LogErrorF(meterWindow, L"Meter=%s is not valid in [%s]", meter, name);
return nullptr;
}
@ -441,7 +441,7 @@ bool Meter::BindPrimaryMeasure(ConfigParser& parser, const WCHAR* section, bool
}
else if (!optional)
{
LogErrorF(L"MeasureName=%s is not valid in [%s]", measureName.c_str(), section);
LogErrorF(this, L"MeasureName=%s is not valid", measureName.c_str());
}
return false;
@ -471,7 +471,7 @@ void Meter::BindSecondaryMeasures(ConfigParser& parser, const WCHAR* section)
{
if (!measureName.empty())
{
LogErrorF(L"MeasureName%i=%s is not valid in [%s]", i, measureName.c_str(), section);
LogErrorF(this, L"MeasureName%i=%s is not valid", i, measureName.c_str());
}
break;

View File

@ -118,7 +118,7 @@ void MeterBar::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"BarOrientation=%s is not valid in [%s]", orientation, m_Name.c_str());
LogErrorF(this, L"BarOrientation=%s is not valid", orientation);
}
if (m_Initialized)

View File

@ -197,7 +197,7 @@ void MeterBitmap::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"BitmapAlign=%s is not valid in [%s]", align, m_Name.c_str());
LogErrorF(this, L"BitmapAlign=%s is not valid", align);
}
if (m_Initialized)

View File

@ -118,7 +118,7 @@ void MeterHistogram::Initialize()
// A sanity check
if (secondaryMeasure && !m_PrimaryImageName.empty() && (m_OverlapImageName.empty() || m_SecondaryImageName.empty()))
{
LogWarning(L"Histogram: SecondaryImage and BothImage not defined");
LogWarningF(this, L"Histogram: SecondaryImage and BothImage not defined");
m_PrimaryImage.DisposeImage();
m_SecondaryImage.DisposeImage();
@ -254,7 +254,7 @@ void MeterHistogram::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"GraphStart=%s is not valid in [%s]", graph, m_Name.c_str());
LogErrorF(this, L"GraphStart=%s is not valid", graph);
}
graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str();
@ -268,7 +268,7 @@ void MeterHistogram::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"GraphOrientation=%s is not valid in [%s]", graph, m_Name.c_str());
LogErrorF(this, L"GraphOrientation=%s is not valid", graph);
}
if (m_Initialized)

View File

@ -159,7 +159,7 @@ void MeterLine::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"GraphStart=%s is not valid in [%s]", graph, m_Name.c_str());
LogErrorF(this, L"GraphStart=%s is not valid", graph);
}
graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str();
@ -173,7 +173,7 @@ void MeterLine::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"GraphOrientation=%s is not valid in [%s]", graph, m_Name.c_str());
LogErrorF(this, L"GraphOrientation=%s is not valid", graph);
}
if (m_Initialized)

View File

@ -199,7 +199,7 @@ void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section)
break;
default:
LogErrorF(L"ClipString=%s is not valid in [%s]", clipping, m_Name.c_str());
LogErrorF(this, L"ClipString=%s is not valid", clipping);
}
m_FontFace = parser.ReadString(section, L"FontFace", L"Arial");
@ -290,7 +290,7 @@ void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"StringCase=%s is not valid in [%s]", stringCase, m_Name.c_str());
LogErrorF(this, L"StringCase=%s is not valid", stringCase);
}
const WCHAR* style = parser.ReadString(section, L"StringStyle", L"NORMAL").c_str();
@ -312,7 +312,7 @@ void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"StringStyle=%s is not valid in [%s]", style, m_Name.c_str());
LogErrorF(this, L"StringStyle=%s is not valid", style);
}
const WCHAR* effect = parser.ReadString(section, L"StringEffect", L"NONE").c_str();
@ -330,7 +330,7 @@ void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section)
}
else
{
LogErrorF(L"StringEffect=%s is not valid in [%s]", effect, m_Name.c_str());
LogErrorF(this, L"StringEffect=%s is not valid", effect);
}
if (m_Initialized &&

View File

@ -402,12 +402,8 @@ void MeterWindow::Refresh(bool init, bool all)
m_State = STATE_REFRESHING;
GetRainmeter().SetCurrentParser(&m_Parser);
std::wstring notice = L"Refreshing skin \"" + m_FolderPath;
notice += L'\\';
notice += m_FileName;
notice += L'"';
LogNotice(notice.c_str());
LogNoticeF(this, L"Refreshing skin");
SetResizeWindowMode(RESIZEMODE_RESET);
@ -908,7 +904,7 @@ void MeterWindow::DoBang(Bang bang, const std::vector<std::wstring>& args)
}
else
{
LogWarningF(L"!CommandMeasure: [%s] not found", measure.c_str());
LogWarningF(this, L"!CommandMeasure: [%s] not found", measure.c_str());
}
}
break;
@ -944,11 +940,11 @@ void MeterWindow::DoBang(Bang bang, const std::vector<std::wstring>& args)
return;
}
LogWarningF(L"!PluginBang: [%s] not found", measure.c_str());
LogWarningF(this, L"!PluginBang: [%s] not found", measure.c_str());
}
else
{
LogError(L"!PluginBang: Invalid parameters");
LogErrorF(this, L"!PluginBang: Invalid parameters");
}
}
break;
@ -1124,7 +1120,7 @@ void MeterWindow::ShowMeter(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!ShowMeter: [%s] not found in \"%s\"", meter, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!ShowMeter: [%s] not found", meter);
}
/*
@ -1146,7 +1142,7 @@ void MeterWindow::HideMeter(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!HideMeter: [%s] not found in \"%s\"", meter, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!HideMeter: [%s] not found", meter);
}
/*
@ -1175,7 +1171,7 @@ void MeterWindow::ToggleMeter(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!ToggleMeter: [%s] not found in \"%s\"", meter, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!ToggleMeter: [%s] not found", meter);
}
/*
@ -1198,7 +1194,7 @@ void MeterWindow::MoveMeter(const std::wstring& name, int x, int y)
}
}
LogErrorF(L"!MoveMeter: [%s] not found in \"%s\"", meter, m_FolderPath.c_str());
LogErrorF(this, L"!MoveMeter: [%s] not found", meter);
}
/*
@ -1248,7 +1244,7 @@ void MeterWindow::UpdateMeter(const std::wstring& name, bool group)
// Post-updates
PostUpdate(bActiveTransition);
if (!group && bContinue) LogErrorF(L"!UpdateMeter: [%s] not found in \"%s\"", meter, m_FolderPath.c_str());
if (!group && bContinue) LogErrorF(this, L"!UpdateMeter: [%s] not found", meter);
}
/*
@ -1269,7 +1265,7 @@ void MeterWindow::EnableMeasure(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!EnableMeasure: [%s] not found in \"%s\"", measure, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!EnableMeasure: [%s] not found", measure);
}
/*
@ -1290,7 +1286,7 @@ void MeterWindow::DisableMeasure(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!DisableMeasure: [%s] not found in \"%s\"", measure, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!DisableMeasure: [%s] not found", measure);
}
/*
@ -1318,7 +1314,7 @@ void MeterWindow::ToggleMeasure(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!ToggleMeasure: [%s] not found in \"%s\"", measure, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!ToggleMeasure: [%s] not found", measure);
}
/*
@ -1358,7 +1354,7 @@ void MeterWindow::UpdateMeasure(const std::wstring& name, bool group)
}
}
if (!group) LogErrorF(L"!UpdateMeasure: [%s] not found in \"%s\"", measure, m_FolderPath.c_str());
if (!group) LogErrorF(this, L"!UpdateMeasure: [%s] not found", measure);
}
/*
@ -2104,9 +2100,7 @@ bool MeterWindow::ReadSkin()
file += fd.cFileName;
if (!m_FontCollection->AddFile(file.c_str()))
{
std::wstring error = L"Unable to load font: ";
error += file.c_str();
LogError(error.c_str());
LogErrorF(this, L"Unable to load font: %s", file.c_str());
}
}
}
@ -2137,9 +2131,7 @@ bool MeterWindow::ReadSkin()
MakePathAbsolute(szFontFile);
if (!m_FontCollection->AddFile(szFontFile.c_str()))
{
std::wstring error = L"Unable to load font: ";
error += localFont;
LogError(error.c_str());
LogErrorF(this, L"Unable to load font: %s", localFont);
}
}
@ -4759,6 +4751,24 @@ std::wstring MeterWindow::GetResourcesPath()
return path;
}
std::wstring MeterWindow::GetSkinPath()
{
std::wstring path = L"";
if (!m_FolderPath.empty())
{
path += m_FolderPath;
path += L"\\";
}
if (!m_FileName.empty())
{
path += m_FileName;
}
return path;
}
Meter* MeterWindow::GetMeter(const std::wstring& meterName)
{
const WCHAR* name = meterName.c_str();

View File

@ -161,6 +161,7 @@ public:
std::wstring GetFilePath();
std::wstring GetRootPath();
std::wstring GetResourcesPath();
std::wstring GetSkinPath();
const std::vector<Measure*>& GetMeasures() { return m_Measures; }
const std::vector<Meter*>& GetMeters() { return m_Meters; }

View File

@ -130,7 +130,7 @@ void Mouse::ReadOptions(ConfigParser& parser, const WCHAR* section)
if (!m_CustomCursor)
{
m_CursorType = MOUSECURSOR_ARROW;
LogErrorF(L"Invalid cursor: %s", cursorPath.c_str());
LogErrorF(m_MeterWindow, L"Invalid cursor: %s", cursorPath.c_str());
}
}
}

View File

@ -855,7 +855,7 @@ void Rainmeter::ActivateSkin(int folderIndex, int fileIndex)
{
if (wcscmp(((*iter).second)->GetFileName().c_str(), fileSz) == 0)
{
LogWarningF(L"!ActivateConfig: \"%s\" already active", folderPath.c_str());
LogWarningF((*iter).second, L"!ActivateConfig: \"%s\" already active", folderPath.c_str());
return;
}
else

View File

@ -380,7 +380,7 @@ void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways)
}
else
{
LogErrorF(L"%s: Unable to load: %s", m_Name, filename.c_str());
LogErrorF(m_MeterWindow, L"%s: Unable to load: %s", m_Name, filename.c_str());
}
}
CloseHandle(fileHandle);
@ -412,7 +412,7 @@ void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways)
}
else
{
LogErrorF(L"%s: Unable to open: %s", m_Name, filename.c_str());
LogErrorF(m_MeterWindow, L"%s: Unable to open: %s", m_Name, filename.c_str());
if (fileHandle != INVALID_HANDLE_VALUE)
{
@ -684,7 +684,7 @@ void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const
if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C)
{
m_CropMode = CROPMODE_TL;
LogErrorF(L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section);
LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section);
}
}
}
@ -788,7 +788,7 @@ void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const
}
else
{
LogErrorF(L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section);
LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section);
}
if (!m_DisableTransform)

View File

@ -147,6 +147,7 @@
#define ID_STR_EDITORSC 2136
#define ID_STR_ELLIPSIS 2137
#define ID_STR_SHOWNOTIFICATIONAREAICON 2138
#define ID_STR_SOURCE 2139
#define IDM_REFRESH 4001
#define IDM_QUIT 4002