summaryrefslogtreecommitdiff
path: root/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-03-02 12:32:44 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-03-02 12:32:55 +0300
commit931a7dc1ac0dbc7e6c1083583ced915e572f5b47 (patch)
tree9fe9a6448d44030e26aa7107ce16044ed413e0d0 /plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
parentdd7d9954042254e66e3bbbec7195c6be8b1a0663 (diff)
all protocols (even virtual ones) moved to the Protocols folder
Diffstat (limited to 'plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp')
-rw-r--r--plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp935
1 files changed, 0 insertions, 935 deletions
diff --git a/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp b/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
deleted file mode 100644
index 592fd551ba..0000000000
--- a/plugins/CurrencyRates/src/CurrencyRatesProviderBase.cpp
+++ /dev/null
@@ -1,935 +0,0 @@
-#include "StdAfx.h"
-
-extern bool g_bAutoUpdate;
-extern HANDLE g_hEventWorkThreadStop;
-
-struct CXMLFileInfo
-{
- CXMLFileInfo() : m_qs(L"Unknown") {}
- ICurrencyRatesProvider::CProviderInfo m_pi;
- CCurrencyRateSection m_qs;
- tstring m_sURL;
-};
-
-inline tstring get_ini_file_name(LPCTSTR pszFileName)
-{
- return CreateFilePath(pszFileName);
-}
-
-bool parse_currencyrate(const TiXmlNode *pTop, CCurrencyRate &q)
-{
- tstring sSymbol, sDescription, sID;
-
- for (auto *pNode : TiXmlEnum(pTop)) {
- const char *sName = pNode->Value();
- if (!mir_strcmpi(sName, "symbol")) {
- sSymbol = GetNodeText(pNode);
- if (sSymbol.empty())
- return false;
- }
- else if (!mir_strcmpi(sName, "description")) {
- sDescription = GetNodeText(pNode);
- }
- else if (!mir_strcmpi(sName, "id")) {
- sID = GetNodeText(pNode);
- if (sID.empty())
- return false;
- }
- }
-
- q = CCurrencyRate(sID, TranslateW(sSymbol.c_str()), TranslateW(sDescription.c_str()));
- return true;
-}
-
-bool parse_section(const TiXmlNode *pTop, CCurrencyRateSection &qs)
-{
- CCurrencyRateSection::TSections aSections;
- CCurrencyRateSection::TCurrencyRates aCurrencyRates;
- tstring sSectionName;
-
- for (auto *pNode : TiXmlEnum(pTop)) {
- const char *sName = pNode->Value();
- if (!mir_strcmpi(sName, "section")) {
- CCurrencyRateSection qs1;
- if (true == parse_section(pNode, qs1))
- aSections.push_back(qs1);
- }
- else if (!mir_strcmpi(sName, "currencyrate")) {
- CCurrencyRate q;
- if (true == parse_currencyrate(pNode, q))
- aCurrencyRates.push_back(q);
- }
- else if (!mir_strcmpi(sName, "name")) {
- sSectionName = GetNodeText(pNode);
- if (sSectionName.empty())
- return false;
- }
- }
-
- qs = CCurrencyRateSection(TranslateW(sSectionName.c_str()), aSections, aCurrencyRates);
- return true;
-}
-
-const TiXmlNode* find_provider(const TiXmlNode *pRoot)
-{
- for (auto *pNode : TiXmlEnum(pRoot)) {
- const char *sName = pNode->Value();
- if (!mir_strcmpi(sName, "Provider"))
- return pNode;
-
- if (auto *pProvider = find_provider(pNode))
- return pProvider;
- }
-
- return nullptr;
-}
-
-CXMLFileInfo parse_ini_file(const tstring &rsXMLFile, bool &rbSucceded)
-{
- CXMLFileInfo res;
- CCurrencyRateSection::TSections aSections;
-
- TiXmlDocument doc;
- if (doc.LoadFile(_T2A(rsXMLFile.c_str())) == tinyxml2::XML_SUCCESS) {
- const TiXmlNode *pProvider = find_provider(&doc);
- if (pProvider) {
- rbSucceded = true;
- for (auto *pNode : TiXmlEnum(pProvider)) {
- const char *sName = pNode->Value();
- if (!mir_strcmpi(sName, "section")) {
- CCurrencyRateSection qs;
- if (parse_section(pNode, qs))
- aSections.push_back(qs);
- }
- else if (!mir_strcmpi(sName, "Name"))
- res.m_pi.m_sName = GetNodeText(pNode);
- else if (!mir_strcmpi(sName, "ref"))
- res.m_pi.m_sURL = GetNodeText(pNode);
- else if (!mir_strcmpi(sName, "url"))
- res.m_sURL = GetNodeText(pNode);
- }
- }
- }
-
- res.m_qs = CCurrencyRateSection(res.m_pi.m_sName, aSections);
- return res;
-}
-
-CXMLFileInfo init_xml_info(LPCTSTR pszFileName, bool& rbSucceded)
-{
- rbSucceded = false;
- tstring sIniFile = get_ini_file_name(pszFileName);
- return parse_ini_file(sIniFile, rbSucceded);
-}
-
-CCurrencyRatesProviderBase::CCurrencyRatesProviderBase() :
- m_hEventSettingsChanged(::CreateEvent(nullptr, FALSE, FALSE, nullptr)),
- m_hEventRefreshContact(::CreateEvent(nullptr, FALSE, FALSE, nullptr)),
- m_bRefreshInProgress(false)
-{
-}
-
-CCurrencyRatesProviderBase::~CCurrencyRatesProviderBase()
-{
- delete m_pXMLInfo;
-
- ::CloseHandle(m_hEventSettingsChanged);
- ::CloseHandle(m_hEventRefreshContact);
-}
-
-bool CCurrencyRatesProviderBase::Init()
-{
- bool bSucceded = (m_pXMLInfo == nullptr);
- if (!m_pXMLInfo)
- m_pXMLInfo = new CXMLFileInfo(init_xml_info(DB_DEF_IniFileName, bSucceded));
-
- return bSucceded;
-}
-
-const CCurrencyRatesProviderBase::CProviderInfo& CCurrencyRatesProviderBase::GetInfo() const
-{
- return m_pXMLInfo->m_pi;
-}
-
-const CCurrencyRateSection& CCurrencyRatesProviderBase::GetCurrencyRates() const
-{
- return m_pXMLInfo->m_qs;
-}
-
-const tstring& CCurrencyRatesProviderBase::GetURL() const
-{
- return m_pXMLInfo->m_sURL;
-}
-
-bool CCurrencyRatesProviderBase::IsOnline()
-{
- return /*g_bAutoUpdate*/true;
-}
-
-void CCurrencyRatesProviderBase::AddContact(MCONTACT hContact)
-{
- // CCritSection cs(m_cs);
- assert(m_aContacts.end() == std::find(m_aContacts.begin(), m_aContacts.end(), hContact));
-
- m_aContacts.push_back(hContact);
-}
-
-void CCurrencyRatesProviderBase::DeleteContact(MCONTACT hContact)
-{
- mir_cslock lck(m_cs);
-
- TContacts::iterator i = std::find(m_aContacts.begin(), m_aContacts.end(), hContact);
- if (i != m_aContacts.end())
- m_aContacts.erase(i);
-}
-
-void CCurrencyRatesProviderBase::SetContactStatus(MCONTACT hContact, int nNewStatus)
-{
- int nStatus = db_get_w(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_STATUS, ID_STATUS_OFFLINE);
- if (nNewStatus != nStatus) {
- db_set_w(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_STATUS, nNewStatus);
-
- if (ID_STATUS_ONLINE != nNewStatus) {
- db_unset(hContact, LIST_MODULE_NAME, STATUS_MSG_NAME);
- tstring sSymbol = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL);
- if (false == sSymbol.empty())
- db_set_ws(hContact, LIST_MODULE_NAME, CONTACT_LIST_NAME, sSymbol.c_str());
-
- SetContactExtraImage(hContact, eiEmpty);
- }
- }
-}
-
-class CTendency
-{
- enum { NumValues = 2 };
- enum EComparison
- {
- NonValid,
- Greater,
- Less,
- Equal,
- GreaterOrEqual,
- LessOrEqual
- };
-
-public:
- enum EResult
- {
- NotChanged,
- Up,
- Down
- };
-
-public:
- CTendency() : m_nComparison(NonValid) {}
-
- bool Parse(CCurrencyRatesProviderBase *pProvider, const tstring& rsFrmt, MCONTACT hContact)
- {
- m_abValueFlags[0] = false;
- m_abValueFlags[1] = false;
- m_nComparison = NonValid;
- bool bValid = true;
- int nCurValue = 0;
- for (tstring::const_iterator i = rsFrmt.begin(); i != rsFrmt.end() && bValid && nCurValue < NumValues;) {
- wchar_t chr = *i;
- switch (chr) {
- default:
- if (false == std::isspace(chr))
- bValid = false;
- else
- ++i;
- break;
-
- case '%':
- ++i;
- if (i != rsFrmt.end()) {
- wchar_t t = *i;
- ++i;
-
- double d;
- bValid = pProvider->ParseSymbol(hContact, t, d);
- if (bValid) {
- m_adValues[nCurValue] = d;
- m_abValueFlags[nCurValue] = true;
- ++nCurValue;
- }
- }
- else bValid = false;
- break;
- case '>':
- m_nComparison = Greater;
- ++i;
- break;
- case '<':
- m_nComparison = Less;
- ++i;
- break;
- case '=':
- switch (m_nComparison) {
- default:
- bValid = false;
- break;
- case NonValid:
- m_nComparison = Equal;
- break;
- case Greater:
- m_nComparison = GreaterOrEqual;
- break;
- case Less:
- m_nComparison = LessOrEqual;
- break;
- }
- ++i;
- break;
- }
- }
-
- return (bValid && IsValid());
- }
-
- bool IsValid() const { return (m_abValueFlags[0] && m_abValueFlags[1] && (m_nComparison != NonValid)); }
-
- EResult Compare() const
- {
- switch (m_nComparison) {
- case Greater:
- if (true == IsWithinAccuracy(m_adValues[0], m_adValues[1]))
- return NotChanged;
-
- if (m_adValues[0] > m_adValues[1])
- return Up;
- return Down;
-
- case GreaterOrEqual:
- if ((true == IsWithinAccuracy(m_adValues[0], m_adValues[1])) || (m_adValues[0] > m_adValues[1]))
- return Up;
- return Down;
-
- case Less:
- if (true == IsWithinAccuracy(m_adValues[0], m_adValues[1]))
- return NotChanged;
-
- if (m_adValues[0] < m_adValues[1])
- return Up;
- return Down;
-
- case LessOrEqual:
- if ((true == IsWithinAccuracy(m_adValues[0], m_adValues[1])) || (m_adValues[0] < m_adValues[1]))
- return Up;
- return Down;
-
- case Equal:
- if (true == IsWithinAccuracy(m_adValues[0], m_adValues[1]))
- return Up;
- return Down;
- }
- return NotChanged;
- }
-
-private:
- double m_adValues[NumValues];
- bool m_abValueFlags[NumValues];
- EComparison m_nComparison;
-};
-
-tstring format_rate(const ICurrencyRatesProvider *pProvider, MCONTACT hContact, const tstring &rsFrmt)
-{
- tstring sResult;
-
- for (tstring::const_iterator i = rsFrmt.begin(); i != rsFrmt.end();) {
- wchar_t chr = *i;
- switch (chr) {
- default:
- sResult += chr;
- ++i;
- break;
-
- case '\\':
- ++i;
- if (i != rsFrmt.end()) {
- wchar_t t = *i;
- switch (t) {
- case '%': sResult += L"%"; break;
- case 't': sResult += L"\t"; break;
- case 'n': sResult += L"\n"; break;
- case '\\': sResult += L"\\"; break;
- default: sResult += chr; sResult += t; break;
- }
- ++i;
- }
- else sResult += chr;
- break;
-
- case '%':
- ++i;
- if (i != rsFrmt.end()) {
- chr = *i;
-
- byte nWidth = 0;
- if (::isdigit(chr)) {
- nWidth = chr - 0x30;
- ++i;
- if (i == rsFrmt.end()) {
- sResult += chr;
- break;
- }
- else chr = *i;
- }
-
- sResult += pProvider->FormatSymbol(hContact, chr, nWidth);
- ++i;
- }
- else sResult += chr;
- break;
- }
- }
-
- return sResult;
-}
-
-void log_to_file(const ICurrencyRatesProvider *pProvider,
- MCONTACT hContact,
- const tstring& rsLogFileName,
- const tstring& rsFormat)
-{
- CreatePathToFileW(rsLogFileName.c_str());
-
- tofstream file(rsLogFileName.c_str(), std::ios::app | std::ios::out);
- file.imbue(GetSystemLocale());
- if (file.good()) {
- tstring s = format_rate(pProvider, hContact, rsFormat);
- file << s;
- }
-}
-
-void log_to_history(const ICurrencyRatesProvider *pProvider,
- MCONTACT hContact,
- time_t nTime,
- const tstring& rsFormat)
-{
- tstring s = format_rate(pProvider, hContact, rsFormat);
- T2Utf psz(s.c_str());
-
- DBEVENTINFO dbei = {};
- dbei.szModule = CURRENCYRATES_MODULE_NAME;
- dbei.timestamp = static_cast<DWORD>(nTime);
- dbei.flags = DBEF_READ | DBEF_UTF;
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.cbBlob = (int)::mir_strlen(psz) + 1;
- dbei.pBlob = (PBYTE)(char*)psz;
- db_event_add(hContact, &dbei);
-}
-
-bool do_set_contact_extra_icon(MCONTACT hContact, const CTendency& tendency)
-{
- CTendency::EResult nComparison = tendency.Compare();
-
- if (CTendency::NotChanged == nComparison)
- return SetContactExtraImage(hContact, eiNotChanged);
-
- if (CTendency::Up == nComparison)
- return SetContactExtraImage(hContact, eiUp);
-
- if (CTendency::Down == nComparison)
- return SetContactExtraImage(hContact, eiDown);
-
- return false;
-}
-
-bool show_popup(const ICurrencyRatesProvider *pProvider,
- MCONTACT hContact,
- const CTendency& tendency,
- const tstring& rsFormat,
- const CPopupSettings& ps)
-{
- if (!ServiceExists(MS_POPUP_ADDPOPUPW))
- return false;
-
- POPUPDATAW ppd;
- memset(&ppd, 0, sizeof(ppd));
- ppd.lchContact = hContact;
-
- if (tendency.IsValid()) {
- CTendency::EResult nComparison = tendency.Compare();
- if (CTendency::NotChanged == nComparison)
- ppd.lchIcon = CurrencyRates_LoadIconEx(IDI_ICON_NOTCHANGED);
- else if (CTendency::Up == nComparison)
- ppd.lchIcon = CurrencyRates_LoadIconEx(IDI_ICON_UP);
- else if (CTendency::Down == nComparison)
- ppd.lchIcon = CurrencyRates_LoadIconEx(IDI_ICON_DOWN);
- }
-
- mir_wstrncpy(ppd.lpwzContactName, pProvider->FormatSymbol(hContact, 's').c_str(), MAX_CONTACTNAME);
- {
- ptrW ss(variables_parsedup((wchar_t*)rsFormat.c_str(), nullptr, hContact));
- tstring sText = format_rate(pProvider, hContact, tstring(ss));
- mir_wstrncpy(ppd.lpwzText, sText.c_str(), MAX_SECONDLINE);
- }
-
- if (CPopupSettings::colourDefault == ps.GetColourMode()) {
- ppd.colorText = CPopupSettings::GetDefColourText();
- ppd.colorBack = CPopupSettings::GetDefColourBk();
- }
- else {
- ppd.colorText = ps.GetColourText();
- ppd.colorBack = ps.GetColourBk();
- }
-
- switch (ps.GetDelayMode()) {
- default:
- assert(!"Unknown popup delay mode");
- case CPopupSettings::delayFromPopup:
- ppd.iSeconds = 0;
- break;
- case CPopupSettings::delayPermanent:
- ppd.iSeconds = -1;
- break;
- case CPopupSettings::delayCustom:
- ppd.iSeconds = ps.GetDelayTimeout();
- break;
- }
-
- LPARAM lp = 0;
- if (false == ps.GetHistoryFlag())
- lp |= 0x08;
-
- return (0 == CallService(MS_POPUP_ADDPOPUPW, reinterpret_cast<WPARAM>(&ppd), lp));
-}
-
-void CCurrencyRatesProviderBase::WriteContactRate(MCONTACT hContact, double dRate, const tstring& rsSymbol/* = ""*/)
-{
- time_t nTime = ::time(0);
-
- if (false == rsSymbol.empty())
- db_set_ws(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL, rsSymbol.c_str());
-
- double dPrev = 0.0;
- bool bValidPrev = CurrencyRates_DBReadDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_CURR_VALUE, dPrev);
- if (true == bValidPrev)
- CurrencyRates_DBWriteDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_PREV_VALUE, dPrev);
-
- CurrencyRates_DBWriteDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_CURR_VALUE, dRate);
- db_set_dw(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_FETCH_TIME, nTime);
-
- tstring sSymbol = rsSymbol;
-
- tostringstream oNick;
- oNick.imbue(GetSystemLocale());
- if (false == m_sContactListFormat.empty()) {
- tstring s = format_rate(this, hContact, m_sContactListFormat);
- oNick << s;
- }
- else {
- if (true == sSymbol.empty())
- sSymbol = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL);
-
- oNick << std::setfill(L' ') << std::setw(10) << std::left << sSymbol << std::setw(6) << std::right << dRate;
- }
- CTendency tendency;
-
- if (true == tendency.Parse(this, m_sTendencyFormat, hContact))
- do_set_contact_extra_icon(hContact, tendency);
-
- db_set_ws(hContact, LIST_MODULE_NAME, CONTACT_LIST_NAME, oNick.str().c_str());
-
- tstring sStatusMsg = format_rate(this, hContact, m_sStatusMsgFormat);
- if (false == sStatusMsg.empty())
- db_set_ws(hContact, LIST_MODULE_NAME, STATUS_MSG_NAME, sStatusMsg.c_str());
- else
- db_unset(hContact, LIST_MODULE_NAME, STATUS_MSG_NAME);
-
- bool bUseContactSpecific = (db_get_b(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CONTACT_SPEC_SETTINGS, 0) > 0);
-
- CAdvProviderSettings global_settings(this);
-
- WORD dwMode = (bUseContactSpecific)
- ? db_get_w(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_LOG, static_cast<WORD>(lmDisabled))
- : global_settings.GetLogMode();
- if (dwMode&lmExternalFile) {
- bool bAdd = true;
- bool bOnlyIfChanged = (bUseContactSpecific)
- ? (db_get_w(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_LOG_FILE_CONDITION, 1) > 0)
- : global_settings.GetLogOnlyChangedFlag();
- if (true == bOnlyIfChanged) {
- bAdd = ((false == bValidPrev) || (false == IsWithinAccuracy(dRate, dPrev)));
- }
- if (true == bAdd) {
- tstring sLogFileName = (bUseContactSpecific)
- ? CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_LOG_FILE, global_settings.GetLogFileName().c_str())
- : global_settings.GetLogFileName();
-
- if (true == sSymbol.empty()) {
- sSymbol = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL);
- }
-
- sLogFileName = GenerateLogFileName(sLogFileName, sSymbol);
-
- tstring sFormat = global_settings.GetLogFormat();
- if (bUseContactSpecific)
- sFormat = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_FORMAT_LOG_FILE, DB_DEF_LogFormat);
-
- log_to_file(this, hContact, sLogFileName, sFormat);
- }
- }
- if (dwMode&lmInternalHistory) {
- bool bAdd = true;
- bool bOnlyIfChanged = (bUseContactSpecific)
- ? (db_get_w(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_HISTORY_CONDITION, 1) > 0)
- : global_settings.GetHistoryOnlyChangedFlag();
-
- if (true == bOnlyIfChanged) {
- bAdd = ((false == bValidPrev) || (false == IsWithinAccuracy(dRate, dPrev)));
- }
- if (true == bAdd) {
- tstring sFormat = (bUseContactSpecific)
- ? CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_FORMAT_HISTORY, global_settings.GetHistoryFormat().c_str())
- : global_settings.GetHistoryFormat();
-
- log_to_history(this, hContact, nTime, sFormat);
- }
- }
-
- if (dwMode&lmPopup) {
- bool bOnlyIfChanged = (bUseContactSpecific)
- ? (1 == db_get_b(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_POPUP_CONDITION, 1) > 0)
- : global_settings.GetShowPopupIfValueChangedFlag();
- if ((false == bOnlyIfChanged)
- || ((true == bOnlyIfChanged) && (true == bValidPrev) && (false == IsWithinAccuracy(dRate, dPrev)))) {
- tstring sFormat = (bUseContactSpecific)
- ? CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_FORMAT_POPUP, global_settings.GetPopupFormat().c_str())
- : global_settings.GetPopupFormat();
-
- CPopupSettings ps = *(global_settings.GetPopupSettingsPtr());
- ps.InitForContact(hContact);
- show_popup(this, hContact, tendency, sFormat, ps);
- }
- }
-
- SetContactStatus(hContact, ID_STATUS_ONLINE);
-}
-
-MCONTACT CCurrencyRatesProviderBase::CreateNewContact(const tstring& rsName)
-{
- MCONTACT hContact = db_add_contact();
- if (hContact) {
- if (0 == Proto_AddToContact(hContact, CURRENCYRATES_PROTOCOL_NAME)) {
- tstring sProvName = GetInfo().m_sName;
- db_set_ws(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_PROVIDER, sProvName.c_str());
- db_set_ws(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL, rsName.c_str());
- db_set_ws(hContact, LIST_MODULE_NAME, CONTACT_LIST_NAME, rsName.c_str());
-
- mir_cslock lck(m_cs);
- m_aContacts.push_back(hContact);
- }
- else {
- db_delete_contact(hContact);
- hContact = NULL;
- }
- }
-
- return hContact;
-}
-
-DWORD get_refresh_timeout_miliseconds()
-{
- if (!g_bAutoUpdate)
- return INFINITE;
-
- int nRefreshRateType = db_get_w(0, CURRENCYRATES_MODULE_NAME, DB_KEY_RefreshRateType, RRT_MINUTES);
- if (nRefreshRateType < RRT_SECONDS || nRefreshRateType > RRT_HOURS)
- nRefreshRateType = RRT_MINUTES;
-
- DWORD nTimeout = db_get_w(0, CURRENCYRATES_MODULE_NAME, DB_KEY_RefreshRateValue, 1);
- switch (nRefreshRateType) {
- default:
- case RRT_SECONDS:
- if (nTimeout < 1 || nTimeout > 60)
- nTimeout = 1;
-
- nTimeout *= 1000;
- break;
- case RRT_MINUTES:
- if (nTimeout < 1 || nTimeout > 60)
- nTimeout = 1;
-
- nTimeout *= 1000 * 60;
- break;
- case RRT_HOURS:
- if (nTimeout < 1 || nTimeout > 24)
- nTimeout = 1;
-
- nTimeout *= 1000 * 60 * 60;
- break;
- }
-
- return nTimeout;
-}
-
-class CBoolGuard
-{
-public:
- CBoolGuard(bool& rb) : m_b(rb) { m_b = true; }
- ~CBoolGuard() { m_b = false; }
-
-private:
- bool m_b;
-};
-
-void CCurrencyRatesProviderBase::Run()
-{
- DWORD nTimeout = get_refresh_timeout_miliseconds();
- m_sContactListFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_DisplayNameFormat, DB_DEF_DisplayNameFormat);
- m_sStatusMsgFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_StatusMsgFormat, DB_DEF_StatusMsgFormat);
- m_sTendencyFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_TendencyFormat, DB_DEF_TendencyFormat);
-
- enum
- {
- STOP_THREAD = 0,
- SETTINGS_CHANGED = 1,
- REFRESH_CONTACT = 2,
- COUNT_SYNC_OBJECTS = 3
- };
-
- HANDLE anEvents[COUNT_SYNC_OBJECTS];
- anEvents[STOP_THREAD] = g_hEventWorkThreadStop;
- anEvents[SETTINGS_CHANGED] = m_hEventSettingsChanged;
- anEvents[REFRESH_CONTACT] = m_hEventRefreshContact;
-
- TContacts anContacts;
- {
- mir_cslock lck(m_cs);
- anContacts = m_aContacts;
- }
-
- bool bGoToBed = false;
-
- if (g_bAutoUpdate) {
- CBoolGuard bg(m_bRefreshInProgress);
- RefreshCurrencyRates(anContacts);
- }
-
- while (false == bGoToBed) {
- anContacts.clear();
-
- DWORD dwBegin = ::GetTickCount();
- DWORD dwResult = ::WaitForMultipleObjects(COUNT_SYNC_OBJECTS, anEvents, FALSE, nTimeout);
- switch (dwResult) {
- case WAIT_FAILED:
- assert(!"WaitForMultipleObjects failed");
- bGoToBed = true;
- break;
-
- case WAIT_ABANDONED_0 + STOP_THREAD:
- case WAIT_ABANDONED_0 + SETTINGS_CHANGED:
- case WAIT_ABANDONED_0 + REFRESH_CONTACT:
- assert(!"WaitForMultipleObjects abandoned");
-
- case WAIT_OBJECT_0 + STOP_THREAD:
- bGoToBed = true;
- break;
-
- case WAIT_OBJECT_0 + SETTINGS_CHANGED:
- nTimeout = get_refresh_timeout_miliseconds();
- m_sContactListFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_DisplayNameFormat, DB_DEF_DisplayNameFormat);
- m_sStatusMsgFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_StatusMsgFormat, DB_DEF_StatusMsgFormat);
- m_sTendencyFormat = CurrencyRates_DBGetStringW(NULL, CURRENCYRATES_MODULE_NAME, DB_KEY_TendencyFormat, DB_DEF_TendencyFormat);
- {
- mir_cslock lck(m_cs);
- anContacts = m_aContacts;
- }
- break;
-
- case WAIT_OBJECT_0 + REFRESH_CONTACT:
- {
- DWORD dwTimeRest = ::GetTickCount() - dwBegin;
- if (INFINITE != nTimeout && dwTimeRest < nTimeout)
- nTimeout -= dwTimeRest;
-
- {
- mir_cslock lck(m_cs);
- anContacts = m_aRefreshingContacts;
- m_aRefreshingContacts.clear();
- }
-
- CBoolGuard bg(m_bRefreshInProgress);
- RefreshCurrencyRates(anContacts);
- }
- break;
-
- case WAIT_TIMEOUT:
- nTimeout = get_refresh_timeout_miliseconds();
- {
- mir_cslock lck(m_cs);
- anContacts = m_aContacts;
- }
- {
- CBoolGuard bg(m_bRefreshInProgress);
- RefreshCurrencyRates(anContacts);
- }
- break;
-
- default:
- assert(!"What is the hell?");
- }
- }
-
- OnEndRun();
-}
-
-void CCurrencyRatesProviderBase::OnEndRun()
-{
- TContacts anContacts;
- {
- mir_cslock lck(m_cs);
- anContacts = m_aContacts;
- m_aRefreshingContacts.clear();
- }
-
- CBoolGuard bg(m_bRefreshInProgress);
- for (auto &it : anContacts)
- SetContactStatus(it, ID_STATUS_OFFLINE);
-}
-
-void CCurrencyRatesProviderBase::RefreshSettings()
-{
- ::SetEvent(m_hEventSettingsChanged);
-}
-
-void CCurrencyRatesProviderBase::RefreshAllContacts()
-{
- { mir_cslock lck(m_cs);
- m_aRefreshingContacts.clear();
- for (auto &hContact : m_aContacts)
- m_aRefreshingContacts.push_back(hContact);
- }
-
- ::SetEvent(m_hEventRefreshContact);
-}
-
-void CCurrencyRatesProviderBase::RefreshContact(MCONTACT hContact)
-{
- { mir_cslock lck(m_cs);
- m_aRefreshingContacts.push_back(hContact);
- }
-
- ::SetEvent(m_hEventRefreshContact);
-}
-
-void CCurrencyRatesProviderBase::FillFormat(TFormatSpecificators &array) const
-{
- array.push_back(CFormatSpecificator(L"%S", TranslateT("Source of Information")));
- array.push_back(CFormatSpecificator(L"%r", TranslateT("Rate Value")));
- array.push_back(CFormatSpecificator(L"%p", TranslateT("Previous Rate Value")));
- array.push_back(CFormatSpecificator(L"%X", TranslateT("Fetch Time")));
- array.push_back(CFormatSpecificator(L"%x", TranslateT("Fetch Date")));
- array.push_back(CFormatSpecificator(L"%t", TranslateT("Fetch Time and Date")));
- array.push_back(CFormatSpecificator(L"\\%", TranslateT("Percentage Character (%)")));
- array.push_back(CFormatSpecificator(L"\\t", TranslateT("Tabulation")));
- array.push_back(CFormatSpecificator(L"\\\\", TranslateT("Left slash (\\)")));
-}
-
-bool CCurrencyRatesProviderBase::ParseSymbol(MCONTACT hContact, wchar_t c, double &d)
-{
- switch (c) {
- case 'r':
- case 'R':
- return CurrencyRates_DBReadDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_CURR_VALUE, d);
-
- case 'p':
- case 'P':
- return CurrencyRates_DBReadDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_PREV_VALUE, d);
- }
-
- return false;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static bool get_fetch_time(MCONTACT hContact, time_t &rTime)
-{
- DBVARIANT dbv;
- if (db_get(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_FETCH_TIME, &dbv) || (DBVT_DWORD != dbv.type))
- return false;
-
- rTime = dbv.dVal;
- return true;
-}
-
-static tstring format_fetch_time(MCONTACT hContact, const tstring &rsFormat)
-{
- time_t nTime;
- if (true == get_fetch_time(hContact, nTime)) {
- boost::posix_time::ptime time = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(boost::posix_time::from_time_t(nTime));
- tostringstream k;
- k.imbue(std::locale(GetSystemLocale(), new ttime_facet(rsFormat.c_str())));
- k << time;
- return k.str();
- }
-
- return tstring();
-}
-
-static tstring format_double(double dValue, int nWidth)
-{
- tostringstream o;
- o.imbue(GetSystemLocale());
-
- if (nWidth > 0 && nWidth <= 9)
- o << std::setprecision(nWidth) << std::showpoint << std::fixed;
-
- o << dValue;
-
- return o.str();
-}
-
-tstring CCurrencyRatesProviderBase::FormatSymbol(MCONTACT hContact, wchar_t c, int nWidth) const
-{
- tstring ret;
- double d = 0.0;
-
- switch (c) {
- case '%':
- case '\t':
- case '\\':
- ret = c;
- break;
- case 'S':
- ret = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_PROVIDER);
- break;
- case 's':
- ret = CurrencyRates_DBGetStringW(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_SYMBOL);
- break;
- case 'X':
- ret = format_fetch_time(hContact, CurrencyRates_GetTimeFormat(true));
- break;
- case 'x':
- ret = format_fetch_time(hContact, CurrencyRates_GetDateFormat(true));
- break;
- case 't':
- {
- tstring sFrmt = CurrencyRates_GetDateFormat(true);
- sFrmt += L" ";
- sFrmt += CurrencyRates_GetTimeFormat(true);
- ret = format_fetch_time(hContact, sFrmt);
- }
- break;
- case 'r':
- case 'R':
- if (true == CurrencyRates_DBReadDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_CURR_VALUE, d))
- ret = format_double(d, nWidth);
- else
- ret = L"-";
- break;
-
- case 'p':
- case 'P':
- if (true == CurrencyRates_DBReadDouble(hContact, CURRENCYRATES_MODULE_NAME, DB_STR_CURRENCYRATE_PREV_VALUE, d))
- ret = format_double(d, nWidth);
- else
- ret = L"-";
- break;
- }
-
- return ret;
-}