diff options
author | George Hazan <george.hazan@gmail.com> | 2014-03-04 23:23:45 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2014-03-04 23:23:45 +0000 |
commit | 15855fa84a09fd1fd486d357c38db0f2bd181e74 (patch) | |
tree | c98d1ae74abca41c776522059343eda13a7e0a31 /plugins/HistoryStats/src/utils.cpp | |
parent | 819f8efabea6b0d7d971f9e6e4b21bbc18838874 (diff) |
HistoryStats compiles ok now
git-svn-id: http://svn.miranda-ng.org/main/trunk@8399 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/HistoryStats/src/utils.cpp')
-rw-r--r-- | plugins/HistoryStats/src/utils.cpp | 1206 |
1 files changed, 1206 insertions, 0 deletions
diff --git a/plugins/HistoryStats/src/utils.cpp b/plugins/HistoryStats/src/utils.cpp new file mode 100644 index 0000000000..ba1cabc53f --- /dev/null +++ b/plugins/HistoryStats/src/utils.cpp @@ -0,0 +1,1206 @@ +#include "_globals.h"
+#include "utils.h"
+
+#include <ctime>
+#include <clocale>
+#include <cstdio>
+#include <stack>
+
+/*
+ * utils
+ */
+
+namespace utils
+{
+ ext::string timestampToString(DWORD value, const mu_text* format)
+ {
+ mu_text temp[100] = { 0 };
+
+ return (ext::strfunc::ftime(temp, 100, format, gmtime(reinterpret_cast<time_t*>(&value))) > 0) ? temp : muT("");
+ }
+
+ ext::string tmStructToString(const tm& value, const mu_text* format)
+ {
+ mu_text temp[100] = { 0 };
+
+ return (ext::strfunc::ftime(temp, 100, format, &value) > 0) ? temp : muT("");
+ }
+
+ ext::string durationToString(DWORD value)
+ {
+ mu_text temp[100] = { 0 };
+
+ value += 59;
+ value /= 60;
+
+ if (value >= 1440)
+ {
+ ext::strfunc::sprintf(temp, muT("%dd %02d:%02d"), value / 1440, (value / 60) % 24, value % 60);
+ }
+ else
+ {
+ ext::strfunc::sprintf(temp, muT("%02d:%02d"), value / 60, value % 60);
+ }
+
+ return temp;
+ }
+
+ DWORD parseDate(const ext::string& date)
+ {
+ if (date.length() != 10 || date[4] != muC('-') || date[7] != muC('-'))
+ {
+ return 0;
+ }
+
+ struct tm dateTM;
+
+ dateTM.tm_year = _ttoi(date.c_str() + 0) - 1900;
+ dateTM.tm_mon = _ttoi(date.c_str() + 5) - 1;
+ dateTM.tm_mday = _ttoi(date.c_str() + 8);
+ dateTM.tm_hour = dateTM.tm_min = dateTM.tm_sec = 0;
+ dateTM.tm_isdst = dateTM.tm_wday = dateTM.tm_yday = 0;
+
+ time_t dateTT = mktime(&dateTM);
+
+ if (dateTT == -1)
+ {
+ return 0;
+ }
+
+ dateTM.tm_year = 1970 - 1900;
+ dateTM.tm_mon = 1 - 1;
+ dateTM.tm_mday = 3;
+ dateTM.tm_hour = dateTM.tm_min = dateTM.tm_sec = 0;
+ dateTM.tm_isdst = dateTM.tm_wday = dateTM.tm_yday = 0;
+
+ time_t baseTT = mktime(&dateTM);
+
+ if (baseTT == -1)
+ {
+ return 0;
+ }
+
+ return dateTT - baseTT + 2 * 86400;
+ }
+
+ ext::string intToString(int value)
+ {
+ mu_text temp[100] = { 0 };
+
+ ext::strfunc::sprintf(temp, muT("%d"), value);
+
+ return temp;
+ }
+
+ ext::string intToPadded(int value, int len)
+ {
+ mu_text temp[100] = { 0 };
+
+ ext::strfunc::sprintf(temp, muT("%0*d"), len, value);
+
+ return temp;
+ }
+
+ ext::string intToGrouped(int value)
+ {
+ mu_text temp[100] = { 0 };
+ const char* grouping = Locale::grouping();
+
+ ext::strfunc::sprintf(temp, muT("%d"), value);
+
+ if (*grouping == CHAR_MAX || *grouping <= 0)
+ {
+ return temp;
+ }
+
+ ext::string str = temp;
+ ext::string::size_type pos = str.length();
+ ext::string::size_type prefix = (temp[0] == muC('+') || temp[0] == muC('-')) ? 1 : 0;
+
+ while (*grouping != CHAR_MAX && *grouping > 0 && pos > prefix + *grouping)
+ {
+ str.insert(pos -= *grouping, 1, Locale::thousandSep());
+
+ if (grouping[1] > 0)
+ {
+ ++grouping;
+ }
+ }
+
+ return str;
+ }
+
+ ext::string floatToString(double value, int precision)
+ {
+ mu_text temp[100] = { 0 };
+
+ ext::strfunc::sprintf(temp, muT("%.*f"), precision, value);
+
+ return temp;
+ }
+
+ ext::string floatToGrouped(double value, int precision)
+ {
+ mu_text temp[100] = { 0 };
+ const char* grouping = Locale::grouping();
+
+ ext::strfunc::sprintf(temp, muT("%.*f"), precision, value);
+
+ if (*grouping == CHAR_MAX || *grouping <= 0)
+ {
+ return temp;
+ }
+
+ ext::string str = temp;
+ ext::string::size_type pos = str.find(Locale::decimalPoint());
+ ext::string::size_type prefix = (temp[0] == muC('+') || temp[0] == muC('-')) ? 1 : 0;
+
+ if (pos == ext::string::npos)
+ {
+ pos = str.length();
+ }
+
+ while (*grouping != CHAR_MAX && *grouping > 0 && pos > prefix + *grouping)
+ {
+ str.insert(pos -= *grouping, 1, Locale::thousandSep());
+
+ if (grouping[1] > 0)
+ {
+ ++grouping;
+ }
+ }
+
+ return str;
+ }
+
+ ext::string ratioToPercent(int numerator, int denominator)
+ {
+ float value = 0.0;
+ mu_text temp[100] = { 0 };
+
+ if (denominator != 0)
+ {
+ value = 1.0f * numerator / denominator;
+ }
+
+ ext::strfunc::sprintf(temp, muT("%.0f%%"), 100.0f * value);
+
+ return temp;
+ }
+
+ void replaceAllInPlace(ext::string& text, const mu_text* find, const mu_text* replace)
+ {
+ ext::string::size_type pos = 0;
+ ext::string::size_type find_len = ext::strfunc::len(find);
+ ext::string::size_type replace_len = ext::strfunc::len(replace);
+
+ while ((pos = text.find(find, pos, find_len)) != ext::string::npos)
+ {
+ text.erase(pos, find_len);
+ text.insert(pos, replace, replace_len);
+ pos += replace_len;
+ }
+ }
+
+ void htmlEscapeInPlace(ext::string& text)
+ {
+ replaceAllInPlace(text, muT("&") , muT("&") );
+ replaceAllInPlace(text, muT("\""), muT("""));
+ replaceAllInPlace(text, muT("<") , muT("<") );
+ replaceAllInPlace(text, muT(">") , muT(">") );
+ }
+
+ const mu_text* stripPrefix(const mu_text* szPrefix, const mu_text* szText)
+ {
+ int i = 0;
+
+ while (szPrefix[i] != muC('\0') && szText[i] != muC('\0') && szPrefix[i] == szText[i])
+ {
+ ++i;
+ }
+
+ if (szPrefix[i] == muC('\0'))
+ {
+ return szText + i;
+ }
+ else
+ {
+ return szText;
+ }
+ }
+
+ ext::string replaceVariables(const ext::string& strFormat, DWORD timeValue, const mu_text* szNick /* = muT("") */)
+ {
+ static const mu_text* szMonthName[][2] = {
+ { I18N(muT("month3:Jan")), I18N(muT("monthF:January")) },
+ { I18N(muT("month3:Feb")), I18N(muT("monthF:February")) },
+ { I18N(muT("month3:Mar")), I18N(muT("monthF:March")) },
+ { I18N(muT("month3:Apr")), I18N(muT("monthF:April")) },
+ { I18N(muT("month3:May")), I18N(muT("monthF:May")) },
+ { I18N(muT("month3:Jun")), I18N(muT("monthF:June")) },
+ { I18N(muT("month3:Jul")), I18N(muT("monthF:July")) },
+ { I18N(muT("month3:Aug")), I18N(muT("monthF:August")) },
+ { I18N(muT("month3:Sep")), I18N(muT("monthF:September")) },
+ { I18N(muT("month3:Oct")), I18N(muT("monthF:October")) },
+ { I18N(muT("month3:Nov")), I18N(muT("monthF:November")) },
+ { I18N(muT("month3:Dec")), I18N(muT("monthF:December")) },
+ };
+
+ static const mu_text* szWDayName[][3] = {
+ { I18N(muT("wday2:Mo")), I18N(muT("wday3:Mon")), I18N(muT("wdayF:Monday")) },
+ { I18N(muT("wday2:Tu")), I18N(muT("wday3:Tue")), I18N(muT("wdayF:Tuesday")) },
+ { I18N(muT("wday2:We")), I18N(muT("wday3:Wed")), I18N(muT("wdayF:Wednesday")) },
+ { I18N(muT("wday2:Th")), I18N(muT("wday3:Thu")), I18N(muT("wdayF:Thursday")) },
+ { I18N(muT("wday2:Fr")), I18N(muT("wday3:Fri")), I18N(muT("wdayF:Friday")) },
+ { I18N(muT("wday2:Sa")), I18N(muT("wday3:Sat")), I18N(muT("wdayF:Saturday")) },
+ { I18N(muT("wday2:Su")), I18N(muT("wday3:Sun")), I18N(muT("wdayF:Sunday")) },
+ };
+
+ struct tm timeTM = *gmtime(reinterpret_cast<time_t*>(&timeValue));
+
+ ext::string strOut = strFormat;
+ ext::string::size_type posOpen = strOut.find(muC('%'));
+
+ while (posOpen != ext::string::npos)
+ {
+ ext::string::size_type posClose = strOut.find(muC('%'), posOpen + 1);
+
+ if (posOpen != ext::string::npos)
+ {
+ ext::string strVar = strOut.substr(posOpen + 1, posClose - posOpen - 1);
+ ext::string strSubst;
+
+ // match variable and generate substitution
+ if (strVar == muT("h"))
+ {
+ strSubst = intToString(timeTM.tm_hour % 12 + (timeTM.tm_hour % 12 == 0 ? 12 : 0));
+ }
+ else if (strVar == muT("hh"))
+ {
+ strSubst = intToPadded(timeTM.tm_hour % 12 + (timeTM.tm_hour % 12 == 0 ? 12 : 0), 2);
+ }
+ else if (strVar == muT("H"))
+ {
+ strSubst = intToString(timeTM.tm_hour);
+ }
+ else if (strVar == muT("HH"))
+ {
+ strSubst = intToPadded(timeTM.tm_hour, 2);
+ }
+ else if (strVar == muT("m"))
+ {
+ strSubst = intToString(timeTM.tm_min);
+ }
+ else if (strVar == muT("mm"))
+ {
+ strSubst = intToPadded(timeTM.tm_min, 2);
+ }
+ else if (strVar == muT("s"))
+ {
+ strSubst = intToString(timeTM.tm_sec);
+ }
+ else if (strVar == muT("ss"))
+ {
+ strSubst = intToPadded(timeTM.tm_sec, 2);
+ }
+ else if (strVar == muT("tt"))
+ {
+ strSubst = timeTM.tm_hour / 12 ? i18n(muT("pm")) : i18n(muT("am"));
+ }
+ else if (strVar == muT("TT"))
+ {
+ strSubst = timeTM.tm_hour / 12 ? i18n(muT("PM")) : i18n(muT("AM"));
+ }
+ else if (strVar == muT("yy"))
+ {
+ strSubst = intToPadded((timeTM.tm_year + 1900) % 100, 2);
+ }
+ else if (strVar == muT("yyyy"))
+ {
+ strSubst = intToPadded(timeTM.tm_year + 1900, 4);
+ }
+ else if (strVar == muT("M"))
+ {
+ strSubst = intToString(timeTM.tm_mon + 1);
+ }
+ else if (strVar == muT("MM"))
+ {
+ strSubst = intToPadded(timeTM.tm_mon + 1, 2);
+ }
+ else if (strVar == muT("MMM"))
+ {
+ strSubst = stripPrefix(muT("month3:"), i18n(szMonthName[timeTM.tm_mon % 12][0]));
+ }
+ else if (strVar == muT("MMMM"))
+ {
+ strSubst = stripPrefix(muT("monthF:"), i18n(szMonthName[timeTM.tm_mon % 12][1]));
+ }
+ else if (strVar == muT("d"))
+ {
+ strSubst = intToString(timeTM.tm_mday);
+ }
+ else if (strVar == muT("dd"))
+ {
+ strSubst = intToPadded(timeTM.tm_mday, 2);
+ }
+ else if (strVar == muT("ww"))
+ {
+ strSubst = stripPrefix(muT("wday2:"), i18n(szWDayName[(timeTM.tm_wday + 6) % 7][0]));
+ }
+ else if (strVar == muT("www"))
+ {
+ strSubst = stripPrefix(muT("wday3:"), i18n(szWDayName[(timeTM.tm_wday + 6) % 7][1]));
+ }
+ else if (strVar == muT("wwww"))
+ {
+ strSubst = stripPrefix(muT("wdayF:"), i18n(szWDayName[(timeTM.tm_wday + 6) % 7][2]));
+ }
+ else if (strVar == muT("miranda_path"))
+ {
+ strSubst = getMirandaPath();
+ }
+ else if (strVar == muT("profile_path"))
+ {
+ strSubst = getProfilePath();
+ }
+ else if (strVar == muT("profile_name"))
+ {
+ strSubst = getProfileName();
+ }
+ else if (strVar == muT("nick"))
+ {
+ strSubst = szNick;
+ }
+ else if (strVar == muT(""))
+ {
+ strSubst = muT("%");
+ }
+
+ // perform actual substitution
+ if (!strSubst.empty())
+ {
+ strOut.replace(posOpen, posClose - posOpen + 1, strSubst);
+ posClose += strSubst.length() - strVar.length() - 2;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ posOpen = strOut.find(muC('%'), posClose + 1);
+ }
+
+ return strOut;
+ }
+
+ ext::string toLowerCase(const ext::string& text)
+ {
+ int len = text.length();
+ mu_text* buf = new mu_text[len + 1];
+
+ LCID lcid = GetUserDefaultLCID();
+
+ len = LCMapString(lcid, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, text.c_str(), len, buf, len);
+
+ buf[len] = 0;
+
+ ext::string ret_str(buf, len);
+
+ delete[] buf;
+
+ return ret_str;
+ }
+
+ ext::string toUpperCase(const ext::string& text)
+ {
+ int len = text.length();
+ mu_text* buf = new mu_text[len + 1];
+
+ LCID lcid = GetUserDefaultLCID();
+
+ len = LCMapString(lcid, LCMAP_LINGUISTIC_CASING | LCMAP_UPPERCASE, text.c_str(), len, buf, len);
+
+ buf[len] = 0;
+
+ ext::string ret_str(buf, len);
+
+ delete[] buf;
+
+ return ret_str;
+ }
+
+ DWORD dottedToVersion(ext::string version)
+ {
+ union {
+ __int32 combined;
+ __int8 parts[4];
+ } res = { 0 };
+
+ int part = 3;
+
+ while (!version.empty() && part >= 0)
+ {
+ ext::string::size_type dotPos = version.find(muT("."));
+
+ if (dotPos == ext::string::npos)
+ {
+ dotPos = version.length();
+ }
+
+ res.parts[part--] = _ttoi(version.substr(0, dotPos).c_str());
+
+ version.erase(0, dotPos + 1);
+ }
+
+ return res.combined;
+ }
+
+ ext::string versionToDotted(DWORD version)
+ {
+ mu_text temp[16] = { 0 };
+
+ ext::strfunc::sprintf(
+ temp,
+ muT("%d.%d.%d.%d"),
+ (version >> 24) & 0xFF,
+ (version >> 16) & 0xFF,
+ (version >> 8) & 0xFF,
+ version & 0xFF);
+
+ return temp;
+ }
+
+ ext::a::string convertWToA(const mu_wide* str, size_t len)
+ {
+ mu_ansi* buf = new mu_ansi[len + 1];
+
+ len = WideCharToMultiByte(CP_ACP, 0, str, len, buf, len, NULL, NULL);
+
+ buf[len] = muC('\0');
+
+ ext::a::string ret_str(buf, len);
+
+ delete[] buf;
+
+ return ret_str;
+ }
+
+ ext::w::string convertAToW(const mu_ansi* str, size_t len)
+ {
+ mu_wide* buf = new mu_wide[len + 1];
+
+ len = MultiByteToWideChar(CP_ACP, 0, str, len, buf, len);
+
+ buf[len] = muC('\0');
+
+ ext::w::string ret_str(buf, len);
+
+ delete[] buf;
+
+ return ret_str;
+ }
+
+ ext::a::string convertTToUTF8(const mu_text* str, size_t str_len)
+ {
+#if defined(MU_WIDE)
+ const mu_wide* conv_str = str;
+#else // MU_WIDE
+ const ext::w::string conv_strX = convertAToW(str, str_len);
+ const mu_wide* conv_str = conv_strX.c_str();
+#endif // MU_WIDE
+
+ int len = 0;
+
+ upto_each_(i, str_len)
+ {
+ mu_wide c = conv_str[i];
+
+ if (c <= 0x007F)
+ {
+ len++;
+ }
+ else if (c <= 0x07FF)
+ {
+ len += 2;
+ }
+ else
+ {
+ len += 3;
+ }
+ }
+
+ ext::a::string out_str(len, muC('_'));
+
+ int pos = 0;
+
+ upto_each_(i, str_len)
+ {
+ mu_wide c = conv_str[i];
+
+ if (c <= 0x007F)
+ {
+ out_str[pos++] = (unsigned char) c;
+ }
+ else if (c <= 0x07FF)
+ {
+ out_str[pos++] = (unsigned char) 0xC0 | (c >> 6);
+ out_str[pos++] = (unsigned char) 0x80 | (c & 0x3F);
+ }
+ else
+ {
+ out_str[pos++] = (unsigned char) 0xE0 | (c >> 12);
+ out_str[pos++] = (unsigned char) 0x80 | ((c >> 6) & 0x3F);
+ out_str[pos++] = (unsigned char) 0x80 | (c & 0x3F);
+ }
+ }
+
+ return out_str;
+ }
+
+ ext::string convertUTF8ToT(const mu_ansi* str, size_t str_len)
+ {
+ size_t len = 0, in_pos = 0;
+
+ while (in_pos < str_len)
+ {
+ mu_ansi c = str[in_pos];
+
+ if ((c & 0x80) == 0x00)
+ {
+ in_pos++;
+ }
+ else if ((c & 0xE0) == 0xC0)
+ {
+ in_pos += 2;
+ }
+ else if ((c & 0xF0) == 0xE0)
+ {
+ in_pos += 3;
+ }
+ else
+ {
+ in_pos++;
+ }
+
+ len++;
+ }
+
+ ext::w::string out_str(len, muC('_'));
+
+ size_t out_pos = 0;
+ in_pos = 0;
+
+ while (in_pos < str_len)
+ {
+ unsigned char c = (unsigned char) str[in_pos];
+
+ if ((c & 0x80) == 0x00)
+ {
+ out_str[out_pos] = (mu_wide) c;
+ in_pos++;
+ }
+ else if ((c & 0xE0) == 0xC0)
+ {
+ out_str[out_pos] = (mu_wide) (((c & 0x1F) << 6) | ((unsigned char) str[in_pos + 1] & 0x3F));
+ in_pos += 2;
+ }
+ else if ((c & 0xF0) == 0xE0)
+ {
+ out_str[out_pos] = (mu_wide) (((c & 0x0F) << 12) | (((unsigned char) str[in_pos + 1] & 0x3F) << 6) | ((unsigned char) str[in_pos + 2] & 0x3F));
+ in_pos += 3;
+ }
+ else
+ {
+ in_pos++;
+ }
+
+ out_pos++;
+ }
+
+#if defined(MU_WIDE)
+ return out_str;
+#else // MU_WIDE
+ return convertWToA(out_str.c_str(), out_str.length());
+#endif // MU_WIDE
+ }
+
+ size_t rawUTF8Encode(const mu_wide* pIn, size_t lenIn, mu_ansi* pOut)
+ {
+ mu_ansi* pOutBegin = pOut;
+
+ upto_each_(i, lenIn)
+ {
+ mu_wide c = pIn[i];
+
+ if (c <= 0x007F)
+ {
+ *pOut++ = (unsigned char) c;
+ }
+ else if (c <= 0x07FF)
+ {
+ *pOut++ = (unsigned char) 0xC0 | (c >> 6);
+ *pOut++ = (unsigned char) 0x80 | (c & 0x3F);
+ }
+ else
+ {
+ *pOut++ = (unsigned char) 0xE0 | (c >> 12);
+ *pOut++ = (unsigned char) 0x80 | ((c >> 6) & 0x3F);
+ *pOut++ = (unsigned char) 0x80 | (c & 0x3F);
+ }
+ }
+
+ return (pOut - pOutBegin);
+ }
+
+ size_t getUTF8Len(const mu_ansi* str)
+ {
+ size_t len = 0, in_pos = 0, str_len = ext::a::strfunc::len(str);
+
+ while (in_pos < str_len)
+ {
+ mu_ansi c = str[in_pos];
+
+ if ((c & 0x80) == 0x00)
+ {
+ in_pos++;
+ }
+ else if ((c & 0xE0) == 0xC0)
+ {
+ in_pos += 2;
+ }
+ else if ((c & 0xF0) == 0xE0)
+ {
+ in_pos += 3;
+ }
+ else
+ {
+ in_pos++;
+ }
+
+ len++;
+ }
+
+ return len;
+ }
+
+ bool fileExists(const ext::string& fileName)
+ {
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind = FindFirstFile(fileName.c_str(), &wfd);
+
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool pathExists(const ext::string& path)
+ {
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind = FindFirstFile((path + muT(".")).c_str(), &wfd);
+
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+
+ return (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool isRelative(const ext::string& fileName)
+ {
+ if (fileName.length() > 2)
+ {
+ if ((fileName[1] == muC(':') && fileName[2] == muC('\\')) || (fileName[0] == muC('\\') && fileName[1] == muC('\\')))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool isValidFilePart(ext::string filePart)
+ {
+ // check for disallowed chars
+ if (filePart.find_first_of(muT("<>:\"/\\|?*")) != ext::string::npos)
+ {
+ return false;
+ }
+
+ // check for dots only
+ if (filePart.find_first_not_of(muC('.')) == ext::string::npos)
+ {
+ return false;
+ }
+
+ // check for disallowed names
+ static const mu_text* disallowedNames[] = {
+ muT("clock$"),
+ muT("aux"),
+ muT("con"),
+ muT("nul"),
+ muT("prn"),
+ muT("com1"),
+ muT("com2"),
+ muT("com3"),
+ muT("com4"),
+ muT("com5"),
+ muT("com6"),
+ muT("com7"),
+ muT("com8"),
+ muT("com9"),
+ muT("lpt1"),
+ muT("lpt2"),
+ muT("lpt3"),
+ muT("lpt4"),
+ muT("lpt5"),
+ muT("lpt6"),
+ muT("lpt7"),
+ muT("lpt8"),
+ muT("lpt9")
+ };
+
+ ext::string::size_type pos = filePart.find(muC('.'));
+
+ if (pos != ext::string::npos)
+ {
+ filePart.erase(pos);
+ }
+
+ array_each_(i, disallowedNames)
+ {
+ if (filePart == disallowedNames[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool isValidFile(const ext::string& fileName)
+ {
+ // find the last backslash to extract file name
+ ext::string::size_type pos = fileName.rfind(muC('\\'));
+
+ if (pos == ext::string::npos)
+ {
+ pos = 0;
+ }
+ else
+ {
+ // is a path, if ends with a backslash
+ if (pos == fileName.length() - 1)
+ return false;
+
+ ++pos;
+ }
+
+ // extract file part
+ return isValidFilePart(fileName.substr(pos));
+ }
+
+ ext::string extractPath(const ext::string& fileName)
+ {
+ ext::string::size_type pos = fileName.rfind(muC('\\'));
+
+ if (pos == ext::string::npos)
+ {
+ return muT("");
+ }
+ else
+ {
+ return fileName.substr(0, pos + 1);
+ }
+ }
+
+ ext::string extractFile(const ext::string& fileName)
+ {
+ ext::string::size_type pos = fileName.rfind(muC('\\'));
+
+ if (pos == ext::string::npos)
+ {
+ return fileName;
+ }
+ else
+ {
+ return fileName.substr(pos + 1);
+ }
+ }
+
+ bool createPath(const ext::string& path)
+ {
+ ext::string curPath = extractPath(path);
+ std::stack<ext::string> subDirs;
+
+ // create stack of missing subdirs and validate them
+ while (curPath.length() > 3 && !pathExists(curPath))
+ {
+ ext::string::size_type pos = curPath.rfind(muC('\\'), curPath.length() - 2);
+
+ if (pos == ext::string::npos)
+ {
+ pos = -1;
+ }
+
+ subDirs.push(curPath.substr(pos + 1, curPath.length() - pos - 2));
+ curPath.erase(pos + 1);
+
+ if (!isValidFilePart(subDirs.top()))
+ {
+ return false;
+ }
+ }
+
+ // try to create subdirs in reverse order
+ while (!subDirs.empty())
+ {
+ const ext::string& curDir = subDirs.top();
+
+ curPath += curDir;
+
+ if (!CreateDirectory(curPath.c_str(), NULL))
+ {
+ return false;
+ }
+
+ curPath += muT("\\");
+
+ subDirs.pop();
+ }
+
+ return true;
+ }
+
+ ext::string colorToHTML(COLORREF crColor)
+ {
+ static const mu_text hexDigits[] = muT("0123456789ABCDEF");
+
+ ext::string htmlColor(7, muC('#'));
+
+ upto_each_(i, 3)
+ {
+ htmlColor[2 * i + 1] = hexDigits[(crColor >> 4) & 0xF];
+ htmlColor[2 * i + 2] = hexDigits[crColor & 0xF];
+
+ crColor >>= 8;
+ }
+
+ return htmlColor;
+ }
+
+ void generateGradient(COLORREF fromColor, COLORREF toColor, COLORREF colorTab[256])
+ {
+ struct rgb { int r, g, b; };
+
+ rgb fromRGB = { GetRValue(fromColor), GetGValue(fromColor), GetBValue(fromColor) };
+ rgb toRGB = { GetRValue(toColor), GetGValue(toColor), GetBValue(toColor) };
+
+ upto_each_(i, 256)
+ {
+ colorTab[i] = RGB(
+ (toRGB.r * i + fromRGB.r * (255 - i)) / 255,
+ (toRGB.g * i + fromRGB.g * (255 - i)) / 255,
+ (toRGB.b * i + fromRGB.b * (255 - i)) / 255);
+ }
+ }
+
+ void ensureRange(int& value, int min, int max, int fallback)
+ {
+ if (value < min || value > max)
+ {
+ value = fallback;
+ }
+ }
+
+ void ensureRange(unsigned int& value, unsigned int min, unsigned int max, unsigned int fallback)
+ {
+ if (value < min || value > max)
+ {
+ value = fallback;
+ }
+ }
+
+ ext::string getGUID()
+ {
+ static const mu_text hexDigits[] = muT("0123456789ABCDEF");
+ GUID guid;
+
+ CoCreateGuid(&guid);
+
+ ext::string strGUID(2 * sizeof(guid), muC('_'));
+
+ upto_each_(i, sizeof(guid))
+ {
+ BYTE val = reinterpret_cast<BYTE*>(&guid)[i];
+
+ strGUID[2 * i] = hexDigits[(val >> 4) & 0xF];
+ strGUID[2 * i + 1] = hexDigits[val & 0xF];
+ }
+
+ return strGUID;
+ }
+
+ void centerDialog(HWND hDlg, HWND hParent /* = NULL */)
+ {
+ if (!hParent)
+ {
+ hParent = GetParent(hDlg);
+ }
+
+ RECT rDlg, rParent;
+
+ if (GetWindowRect(hParent, &rParent) && GetWindowRect(hDlg, &rDlg))
+ {
+ SetWindowPos(
+ hDlg,
+ 0,
+ (rParent.right + rParent.left - rDlg.right + rDlg.left) / 2,
+ (rParent.bottom + rParent.top - rDlg.bottom + rDlg.top) / 2,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+ else if (GetWindowRect(hDlg, &rDlg))
+ {
+ SetWindowPos(
+ hDlg,
+ 0,
+ (GetSystemMetrics(SM_CXSCREEN) - rDlg.right + rDlg.left) / 2,
+ (GetSystemMetrics(SM_CYSCREEN) - rDlg.bottom + rDlg.top) / 2,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ }
+ }
+
+ RECT getWindowRect(HWND hParent, HWND hWnd)
+ {
+ RECT rWnd;
+
+ GetWindowRect(hWnd, &rWnd);
+
+ ScreenToClient(hParent, reinterpret_cast<POINT*>(&rWnd) + 0);
+ ScreenToClient(hParent, reinterpret_cast<POINT*>(&rWnd) + 1);
+
+ return rWnd;
+ }
+
+ void moveWindow(HWND hWnd, const RECT& rWnd)
+ {
+ MoveWindow(hWnd, rWnd.left, rWnd.top, rWnd.right - rWnd.left, rWnd.bottom - rWnd.top, TRUE);
+ }
+
+ const ext::string& getMirandaPath()
+ {
+ static ext::string strMirandaPath;
+
+ if (strMirandaPath.empty())
+ {
+ mu_text szPath[MAX_PATH] = { 0 };
+
+ mu::utils::pathToAbsolute(muT("x"), szPath);
+ strMirandaPath = extractPath(szPath);
+ }
+
+ return strMirandaPath;
+ }
+
+ const ext::string& getProfilePath()
+ {
+ static ext::string strProfilePath;
+
+ if (strProfilePath.empty())
+ {
+ mu_text szPath[MAX_PATH] = { 0 };
+
+ mu::db::getProfilePath(MAX_PATH, szPath);
+ strProfilePath = szPath;
+
+ if (strProfilePath.empty() || strProfilePath[strProfilePath.length() - 1] != muC('\\'))
+ {
+ strProfilePath += muT("\\");
+ }
+ }
+
+ return strProfilePath;
+ }
+
+ const ext::string& getProfileName()
+ {
+ static ext::string strProfileName;
+
+ if (strProfileName.empty())
+ {
+ mu_text szName[MAX_PATH] = { 0 };
+
+ mu::db::getProfileName(MAX_PATH, szName);
+ strProfileName = szName;
+
+ ext::string::size_type posDot = strProfileName.rfind(muC('.'));
+
+ if (posDot != ext::string::npos && posDot != 0)
+ {
+ strProfileName.erase(posDot);
+ }
+ }
+
+ return strProfileName;
+ }
+};
+
+/*
+ * OS
+ */
+
+OS::OS()
+ : m_bIsXPPlus(false),
+ m_ImageListColor(ILC_COLORDDB) // MEMO: maybe change this to ILC_COLOR{8,16,24}
+{
+ m_SmIcon.cx = 16; // GetSystemMetrics(SM_CXSMICON);
+ m_SmIcon.cy = 16; // GetSystemMetrics(SM_CYSMICON);
+
+ OSVERSIONINFO osvi = { 0 };
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+
+ if (GetVersionEx(&osvi))
+ {
+ m_bIsXPPlus = ((osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 1) || osvi.dwMajorVersion >= 6);
+
+ if (m_bIsXPPlus)
+ {
+ m_ImageListColor = ILC_COLOR32;
+ }
+ }
+}
+
+OS OS::m_Data;
+
+/*
+ * Locale
+ */
+
+void Locale::init()
+{
+ setlocale(LC_ALL, muA(""));
+ // setlocale(LC_ALL, muA("French_France"));
+ // setlocale(LC_ALL, muA("English_USA"));
+ // setlocale(LC_ALL, muA("Russian_Russia"));
+
+ m_Data.m_ThousandSep = utils::fromA(localeconv()->thousands_sep).c_str()[0];
+ m_Data.m_DecimalPoint = utils::fromA(localeconv()->decimal_point).c_str()[0];
+ m_Data.m_Grouping = localeconv()->grouping;
+}
+
+Locale Locale::m_Data;
+
+/*
+ * RTFFilter
+ */
+
+RTFFilter::RTFFilter()
+ : m_hRTFConv(NULL)
+{
+}
+
+void RTFFilter::init()
+{
+ if (!(m_Data.m_hRTFConv = LoadLibrary(muT("rtfconv.dll"))))
+ {
+ if (!(m_Data.m_hRTFConv = LoadLibrary(muT("plugins\\rtfconv.dll"))))
+ {
+ return;
+ }
+ }
+
+ if (!(m_Data.m_RTFConvString = reinterpret_cast<RTFCONVSTRING>(GetProcAddress(m_Data.m_hRTFConv, muA("RtfconvString")))))
+ {
+ FreeLibrary(m_Data.m_hRTFConv);
+
+ m_Data.m_hRTFConv = NULL;
+ }
+
+ InitializeCriticalSection(&m_Data.m_RTFConvCS);
+}
+
+void RTFFilter::uninit()
+{
+ if (m_Data.m_hRTFConv)
+ {
+ DeleteCriticalSection(&m_Data.m_RTFConvCS);
+ FreeLibrary(m_Data.m_hRTFConv);
+
+ m_Data.m_hRTFConv = NULL;
+ m_Data.m_RTFConvString = NULL;
+ }
+}
+
+ext::t::string RTFFilter::filter(const ext::t::string& str)
+{
+ // protect, because library is not thread-safe
+ EnterCriticalSection(&m_Data.m_RTFConvCS);
+
+#if defined(MU_WIDE)
+ const ext::a::string strA = utils::toA(str);
+#else // MU_WIDE
+ const ext::a::string& strA = str;
+#endif // MU_WIDE
+
+ intptr_t len = m_Data.m_RTFConvString(
+ strA.c_str(),
+ NULL,
+ 0,
+ MU_DO_BOTH(GetACP(), CP_UNICODE),
+ CONVMODE_USE_SYSTEM_TABLE | MU_DO_BOTH(0, CONVMODE_NO_OUTPUT_BOM),
+ 0);
+
+ if (len == -1)
+ {
+ // someting went wrong, maybe it's not a real RTF string
+ LeaveCriticalSection(&m_Data.m_RTFConvCS);
+
+ return str;
+ }
+
+ mu_text* out_buf = new mu_text[len / sizeof(mu_text)];
+
+ intptr_t res = m_Data.m_RTFConvString(
+ strA.c_str(),
+ out_buf,
+ 0,
+ MU_DO_BOTH(GetACP(), CP_UNICODE),
+ CONVMODE_USE_SYSTEM_TABLE | MU_DO_BOTH(0, CONVMODE_NO_OUTPUT_BOM),
+ len);
+
+ if (res == -1)
+ {
+ // someting went wrong, maybe it's not a real RTF string
+ delete[] out_buf;
+
+ LeaveCriticalSection(&m_Data.m_RTFConvCS);
+
+ return str;
+ }
+
+ ext::t::string out_str(out_buf, res / sizeof(mu_text) - 1);
+ delete[] out_buf;
+
+ LeaveCriticalSection(&m_Data.m_RTFConvCS);
+
+ return out_str;
+}
+
+RTFFilter RTFFilter::m_Data;
|