diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index 206d7043..d2fce8a4 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -604,6 +604,27 @@ double CConfigParser::ReadFormula(LPCTSTR section, LPCTSTR key, double defValue) return ParseDouble(result, defValue); } +// Returns an int if the formula was read successfully, -1 for failure. +// Pass a pointer to a double. +int CConfigParser::ReadFormula(std::wstring& result, double* resultValue) +{ + // Formulas must be surrounded by parenthesis + if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')') + { + char* errMsg = MathParser_Parse(m_Parser, ConvertToAscii(result.substr(1, result.size() - 2).c_str()).c_str(), resultValue); + + if (errMsg != NULL) + { + DebugLog(ConvertToWide(errMsg).c_str()); + return -1; + } + + return 1; + } + + return -1; +} + Color CConfigParser::ReadColor(LPCTSTR section, LPCTSTR key, Color defValue) { TCHAR buffer[256]; diff --git a/Library/ConfigParser.h b/Library/ConfigParser.h index a69cec4f..a02e0d98 100644 --- a/Library/ConfigParser.h +++ b/Library/ConfigParser.h @@ -54,6 +54,10 @@ public: std::wstring& GetFilename() { return m_Filename; } const std::vector& GetSections(); + + // Returns an int if the formula was read successfully, -1 for failure. + int ReadFormula(std::wstring& result, double* number); + static std::vector Tokenize(const std::wstring& str, const std::wstring delimiters); static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } diff --git a/Library/MeterString.cpp b/Library/MeterString.cpp index 50080bdd..c1e3e602 100644 --- a/Library/MeterString.cpp +++ b/Library/MeterString.cpp @@ -27,6 +27,10 @@ using namespace Gdiplus; std::map CMeterString::c_FontFamilies; std::map CMeterString::c_Fonts; +std::wstring StringToUpper(std::wstring str); +std::wstring StringToLower(std::wstring str); +std::wstring StringToProper(std::wstring str); + /* ** CMeterString ** @@ -51,6 +55,7 @@ CMeterString::CMeterString(CMeterWindow* meterWindow) : CMeter(meterWindow) m_NumOfDecimals = -1; m_DimensionsDefined = false; m_Angle = 0.0; + m_textCase = TEXTCASE_NONE; } /* @@ -299,6 +304,28 @@ void CMeterString::ReadConfig(const WCHAR* section) throw CError(std::wstring(L"No such StringAlign: ") + align, __LINE__, __FILE__); } + std::wstring stringCase; + stringCase = parser.ReadString(section, L"StringCase", L"NONE"); + + if(_wcsicmp(stringCase.c_str(), L"NONE") == 0) + { + m_textCase = TEXTCASE_NONE; + } + else if(_wcsicmp(stringCase.c_str(), L"UPPER") == 0) + { + m_textCase = TEXTCASE_UPPER; + } + else if(_wcsicmp(stringCase.c_str(), L"LOWER") == 0) + { + m_textCase = TEXTCASE_LOWER; + } + else if(_wcsicmp(stringCase.c_str(), L"PROPER") == 0) + { + m_textCase = TEXTCASE_PROPER; + } + + + std::wstring style; style = parser.ReadString(section, L"StringStyle", L"NORMAL"); @@ -417,6 +444,20 @@ bool CMeterString::Update() } m_String += m_Postfix; + switch(m_textCase) + { + case TEXTCASE_UPPER: + m_String = StringToUpper(m_String); + break; + case TEXTCASE_LOWER: + m_String = StringToLower(m_String); + break; + case TEXTCASE_PROPER: + m_String = StringToProper(m_String); + break; + } + + if (!m_DimensionsDefined) { // Calculate the text size @@ -623,4 +664,57 @@ std::wstring CMeterString::FontPropertiesToString(FontFamily* fontFamily, REAL s return stream.str(); } -// EOF \ No newline at end of file +/* +** FontPropertiesToString +** +** Static helper to convert font properties to a string so it can be used as a key for the cache map. +** +*/ +std::wstring StringToUpper(std::wstring str) +{ + //change each element of the string to upper case + for(unsigned int i = 0; i < str.length(); i++) + { + str[i] = toupper( str[i] ); + } + + return str; //return the converted string +} + +std::wstring StringToLower(std::wstring str) +{ + //change each element of the string to lower case + for(unsigned int i = 0; i < str.length(); i++) + { + str[i] = tolower(str[i]); + } + + return str;//return the converted string +} + +std::wstring StringToProper(std::wstring str) +{ + //change each element of the string to lower case + for(unsigned int i = 0; i < str.length(); i++) + { + if(i == 0) + { + str[i] = toupper( str[i] ); + } + else + { + if(str[i-1] == ' ') + { + str[i] = toupper(str[i]); + } + else + { + str[i] = tolower(str[i]); + } + } + } + + return str;//return the converted string +} + +// EOF diff --git a/Library/MeterString.h b/Library/MeterString.h index fb7ced42..ad1b5329 100644 --- a/Library/MeterString.h +++ b/Library/MeterString.h @@ -58,26 +58,35 @@ private: EFFECT_BORDER }; + enum TEXTCASE + { + TEXTCASE_NONE, + TEXTCASE_UPPER, + TEXTCASE_LOWER, + TEXTCASE_PROPER, + }; + bool DrawString(Gdiplus::Graphics& graphics, Gdiplus::RectF* rect); - Gdiplus::Color m_Color; // The color of the text + Gdiplus::Color m_Color; // The color of the text Gdiplus::Color m_EffectColor; // The color of the text effect - std::wstring m_Postfix; // The postfix of the text - std::wstring m_Prefix; // The prefix of the text - std::wstring m_Text; // The text - std::wstring m_FontFace; // name of the font face - bool m_AutoScale; // true, if the value should be autoscaled - METER_ALIGNMENT m_Align; // Alignment of the text - TEXTSTYLE m_Style; // Style of the text - TEXTEFFECT m_Effect; // Text effect - int m_FontSize; // Size of the fonts - double m_Scale; // Scaling if autoscale is not used - bool m_NoDecimals; // Number of decimals to use - bool m_Percentual; // True, if the value should be given as % - bool m_ClipString; // True, the text is clipped in borders (adds ellipsis to the end of the string) - Gdiplus::Font* m_Font; // The font - Gdiplus::FontFamily* m_FontFamily; // The font family - int m_NumOfDecimals; // Number of decimals to be displayed + std::wstring m_Postfix; // The postfix of the text + std::wstring m_Prefix; // The prefix of the text + std::wstring m_Text; // The text + std::wstring m_FontFace; // name of the font face + bool m_AutoScale; // true, if the value should be autoscaled + METER_ALIGNMENT m_Align; // Alignment of the text + TEXTSTYLE m_Style; // Style of the text + TEXTEFFECT m_Effect; // Text effect + TEXTCASE m_textCase; // Case of the text + int m_FontSize; // Size of the fonts + double m_Scale; // Scaling if autoscale is not used + bool m_NoDecimals; // Number of decimals to use + bool m_Percentual; // True, if the value should be given as % + bool m_ClipString; // True, the text is clipped in borders (adds ellipsis to the end of the string) + Gdiplus::Font* m_Font; // The font + Gdiplus::FontFamily* m_FontFamily; // The font family + int m_NumOfDecimals; // Number of decimals to be displayed bool m_DimensionsDefined; Gdiplus::REAL m_Angle; diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 5809da77..c18962cd 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -732,7 +732,23 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) { std::wstring strVariable(arg, pos - arg); std::wstring strValue(pos + 1); - m_Parser.SetVariable(strVariable, strValue); + double value; + int result = m_Parser.ReadFormula(strValue, &value); + + // Formula read fine + if(result != -1) + { + TCHAR buffer[256]; + swprintf(buffer, L"%f", value); + + const std::wstring& resultString = buffer; + + m_Parser.SetVariable(strVariable, resultString); + } + else + { + m_Parser.SetVariable(strVariable, strValue); + } } else { @@ -2437,7 +2453,6 @@ void CMeterWindow::Redraw() } } - /* ** Update ** @@ -2454,6 +2469,7 @@ void CMeterWindow::Update(bool nodraw) // Update all measures std::list::iterator i = m_Measures.begin(); + for( ; i != m_Measures.end(); i++) { try @@ -2490,6 +2506,7 @@ void CMeterWindow::Update(bool nodraw) // Statistics CMeasureNet::UpdateStats(); + OutputDebugString(L"Butts"); Rainmeter->WriteStats(false); if (!nodraw)