/* Copyright (C) 2004 Kimmo Pekkola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #pragma warning(disable: 4786) #pragma warning(disable: 4996) #include "ConfigParser.h" #include "Litestep.h" #include "Rainmeter.h" #include extern CRainmeter* Rainmeter; using namespace Gdiplus; /* ** CConfigParser ** ** The constructor ** */ CConfigParser::CConfigParser() { } /* ** ~CConfigParser ** ** The destructor ** */ CConfigParser::~CConfigParser() { } /* ** Initialize ** ** */ void CConfigParser::Initialize(LPCTSTR filename) { m_Filename = filename; ReadVariables(); } /* ** ReadVariables ** ** */ void CConfigParser::ReadVariables() { DWORD size; TCHAR* buffer; TCHAR* variable; int bufferSize = 4096; bool loop; m_Variables.clear(); do { loop = false; buffer = new TCHAR[bufferSize]; size = GetPrivateProfileString(L"Variables", NULL, L"", buffer, bufferSize, m_Filename.c_str()); if (size == bufferSize - 1) { // Buffer too small, increase it and retry delete [] buffer; bufferSize *= 2; loop = true; } } while(loop); if (size > 0) { variable = new TCHAR[bufferSize]; // Read all variables WCHAR* pos = buffer; while(wcslen(pos) > 0) { do { loop = false; size = GetPrivateProfileString(L"Variables", pos, L"", variable, bufferSize, m_Filename.c_str()); if (size == bufferSize - 1) { // Buffer too small, increase it and retry delete [] variable; bufferSize *= 2; variable = new TCHAR[bufferSize]; loop = true; } } while(loop); if (wcslen(variable) > 0) { m_Variables[pos] = variable; } pos = pos + wcslen(pos) + 1; } delete [] variable; } delete [] buffer; } /* ** ReadString ** ** */ const std::wstring& CConfigParser::ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue) { static std::wstring result; DWORD size; TCHAR* buffer; int bufferSize = 4096; bool loop; do { loop = false; buffer = new TCHAR[bufferSize]; buffer[0] = 0; size = GetPrivateProfileString(section, key, defValue, buffer, bufferSize, m_Filename.c_str()); if (size == bufferSize - 1) { // Buffer too small, increase it and retry delete [] buffer; bufferSize *= 2; loop = true; } } while(loop); result = buffer; delete [] buffer; // Check Litestep vars if (Rainmeter && !Rainmeter->GetDummyLitestep()) { std::string ansi = ConvertToAscii(result.c_str()); char buffer[4096]; // lets hope the buffer is large enough... if (ansi.size() < 4096) { VarExpansion(buffer, ansi.c_str()); result = ConvertToWide(buffer); } } if (result.find(L'%') != std::wstring::npos) { WCHAR buffer[4096]; // lets hope the buffer is large enough... // Expand the environment variables DWORD ret = ExpandEnvironmentStrings(result.c_str(), buffer, 4096); if (ret != 0 && ret < 4096) { result = buffer; } else { DebugLog(L"Unable to expand the environment strings."); } } // Check for variables (#VAR#) size_t start = 0; size_t end = std::wstring::npos; size_t pos = std::wstring::npos; loop = true; do { pos = result.find(L'#', start); if (pos != std::wstring::npos) { size_t end = result.find(L'#', pos + 1); if (end != std::wstring::npos) { std::wstring var(result.begin() + pos + 1, result.begin() + end); std::map::iterator iter = m_Variables.find(var); if (iter != m_Variables.end()) { // Variable found, replace it with the value result.replace(result.begin() + pos, result.begin() + end + 1, (*iter).second); start = pos + (*iter).second.length(); } else { start = end; } } else { loop = false; } } else { loop = false; } } while(loop); return result; } double CConfigParser::ReadFloat(LPCTSTR section, LPCTSTR key, double defValue) { TCHAR buffer[256]; swprintf(buffer, L"%f", defValue); const std::wstring& result = ReadString(section, key, buffer); return wcstod(result.c_str(), NULL); } int CConfigParser::ReadInt(LPCTSTR section, LPCTSTR key, int defValue) { TCHAR buffer[256]; swprintf(buffer, L"%i", defValue); const std::wstring& result = ReadString(section, key, buffer); return _wtoi(result.c_str()); } Color CConfigParser::ReadColor(LPCTSTR section, LPCTSTR key, Color defValue) { TCHAR buffer[256]; swprintf(buffer, L"%i, %i, %i, %i", defValue.GetR(), defValue.GetG(), defValue.GetB(), defValue.GetA()); const std::wstring& result = ReadString(section, key, buffer); return ParseColor(result.c_str()); } /* ** ParseColor ** ** This is a helper method that parses the color values from the given string. ** The color can be supplied as three/four comma separated values or as one ** hex-value. ** */ Color CConfigParser::ParseColor(LPCTSTR string) { int R, G, B, A; if(wcschr(string, L',') != NULL) { WCHAR* parseSz = _wcsdup(string); WCHAR* token; token = wcstok(parseSz, L","); if (token != NULL) { R = _wtoi(token); } else { R = 255; } token = wcstok( NULL, L","); if (token != NULL) { G = _wtoi(token); } else { G = 255; } token = wcstok( NULL, L","); if (token != NULL) { B = _wtoi(token); } else { B = 255; } token = wcstok( NULL, L","); if (token != NULL) { A = _wtoi(token); } else { A = 255; } free(parseSz); } else { const WCHAR* start = string; if (wcsncmp(string, L"0x", 2) == 0) { start = string + 2; } if (wcslen(string) > 6 && !isspace(string[6])) { swscanf(string, L"%02x%02x%02x%02x", &R, &G, &B, &A); } else { swscanf(string, L"%02x%02x%02x", &R, &G, &B); A = 255; // Opaque } } return Color(A, R, G, B); }