summaryrefslogtreecommitdiff
path: root/protocols/Quotes/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Quotes/src')
-rw-r--r--protocols/Quotes/src/Base64.cpp43
-rw-r--r--protocols/Quotes/src/Base64.h12
-rw-r--r--protocols/Quotes/src/Chart.h280
-rw-r--r--protocols/Quotes/src/ComHelper.cpp39
-rw-r--r--protocols/Quotes/src/ComHelper.h9
-rw-r--r--protocols/Quotes/src/CommonOptionDlg.cpp272
-rw-r--r--protocols/Quotes/src/CommonOptionDlg.h17
-rw-r--r--protocols/Quotes/src/CreateFilePath.cpp45
-rw-r--r--protocols/Quotes/src/CreateFilePath.h8
-rw-r--r--protocols/Quotes/src/CurrencyConverter.cpp309
-rw-r--r--protocols/Quotes/src/CurrencyConverter.h6
-rw-r--r--protocols/Quotes/src/DBUtils.cpp70
-rw-r--r--protocols/Quotes/src/DBUtils.h13
-rw-r--r--protocols/Quotes/src/EconomicRateInfo.h59
-rw-r--r--protocols/Quotes/src/ExtraImages.cpp143
-rw-r--r--protocols/Quotes/src/ExtraImages.h39
-rw-r--r--protocols/Quotes/src/Forex.cpp478
-rw-r--r--protocols/Quotes/src/HTMLParserMS.cpp313
-rw-r--r--protocols/Quotes/src/HTMLParserMS.h36
-rw-r--r--protocols/Quotes/src/HTTPSession.cpp262
-rw-r--r--protocols/Quotes/src/HTTPSession.h27
-rw-r--r--protocols/Quotes/src/IHTMLEngine.h18
-rw-r--r--protocols/Quotes/src/IHTMLParser.h41
-rw-r--r--protocols/Quotes/src/IQuotesProvider.h41
-rw-r--r--protocols/Quotes/src/IXMLEngine.h43
-rw-r--r--protocols/Quotes/src/IconLib.cpp106
-rw-r--r--protocols/Quotes/src/IconLib.h21
-rw-r--r--protocols/Quotes/src/ImportExport.cpp850
-rw-r--r--protocols/Quotes/src/ImportExport.h11
-rw-r--r--protocols/Quotes/src/IsWithinAccuracy.h15
-rw-r--r--protocols/Quotes/src/LightMutex.cpp22
-rw-r--r--protocols/Quotes/src/LightMutex.h34
-rw-r--r--protocols/Quotes/src/Locale.cpp75
-rw-r--r--protocols/Quotes/src/Locale.h9
-rw-r--r--protocols/Quotes/src/Log.cpp56
-rw-r--r--protocols/Quotes/src/Log.h13
-rw-r--r--protocols/Quotes/src/ModuleInfo.cpp135
-rw-r--r--protocols/Quotes/src/ModuleInfo.h43
-rw-r--r--protocols/Quotes/src/OptionDukasCopy.cpp414
-rw-r--r--protocols/Quotes/src/OptionDukasCopy.h8
-rw-r--r--protocols/Quotes/src/QuoteChart.cpp408
-rw-r--r--protocols/Quotes/src/QuoteChart.h12
-rw-r--r--protocols/Quotes/src/QuoteInfoDlg.cpp350
-rw-r--r--protocols/Quotes/src/QuoteInfoDlg.h11
-rw-r--r--protocols/Quotes/src/QuotesProviderBase.cppbin0 -> 58860 bytes
-rw-r--r--protocols/Quotes/src/QuotesProviderBase.h112
-rw-r--r--protocols/Quotes/src/QuotesProviderDukasCopy.cppbin0 -> 15324 bytes
-rw-r--r--protocols/Quotes/src/QuotesProviderDukasCopy.h38
-rw-r--r--protocols/Quotes/src/QuotesProviderFinance.cpp318
-rw-r--r--protocols/Quotes/src/QuotesProviderFinance.h21
-rw-r--r--protocols/Quotes/src/QuotesProviderGoogle.cpp543
-rw-r--r--protocols/Quotes/src/QuotesProviderGoogle.h42
-rw-r--r--protocols/Quotes/src/QuotesProviderGoogleFinance.cpp366
-rw-r--r--protocols/Quotes/src/QuotesProviderGoogleFinance.h25
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitor.h25
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorDbSettings.cpp157
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorDbSettings.h49
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp63
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.h36
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorFormater.cpp216
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorFormater.h32
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorTendency.cpp70
-rw-r--r--protocols/Quotes/src/QuotesProviderVisitorTendency.h29
-rw-r--r--protocols/Quotes/src/QuotesProviderYahoo.cpp193
-rw-r--r--protocols/Quotes/src/QuotesProviderYahoo.h20
-rw-r--r--protocols/Quotes/src/QuotesProviders.cpp120
-rw-r--r--protocols/Quotes/src/QuotesProviders.h32
-rw-r--r--protocols/Quotes/src/SettingsDlg.cpp1148
-rw-r--r--protocols/Quotes/src/SettingsDlg.h118
-rw-r--r--protocols/Quotes/src/WinCtrlHelper.cpp49
-rw-r--r--protocols/Quotes/src/WinCtrlHelper.h37
-rw-r--r--protocols/Quotes/src/WorkingThread.cpp15
-rw-r--r--protocols/Quotes/src/WorkingThread.h6
-rw-r--r--protocols/Quotes/src/XMLEngineMI.cpp230
-rw-r--r--protocols/Quotes/src/XMLEngineMI.h17
-rw-r--r--protocols/Quotes/src/resource.h109
-rw-r--r--protocols/Quotes/src/stdafx.cpp8
-rw-r--r--protocols/Quotes/src/stdafx.h154
-rw-r--r--protocols/Quotes/src/targetver.h24
-rw-r--r--protocols/Quotes/src/version.h21
80 files changed, 9659 insertions, 0 deletions
diff --git a/protocols/Quotes/src/Base64.cpp b/protocols/Quotes/src/Base64.cpp
new file mode 100644
index 0000000000..1854fb42fd
--- /dev/null
+++ b/protocols/Quotes/src/Base64.cpp
@@ -0,0 +1,43 @@
+#include "StdAfx.h"
+#include "Base64.h"
+
+bool base64::encode(const BYTE* in, size_t inlen,std::vector<char>& out)
+{
+ int nOutLength = Base64EncodeGetRequiredLength((int)inlen);
+ out.resize(nOutLength);
+ char* p = &*out.begin();
+ bool bResult = (TRUE == Base64Encode(in,(int)inlen,p,&nOutLength));
+ if(false == bResult)
+ {
+ out.resize(nOutLength);
+ p = &*out.begin();
+ bResult = (TRUE == Base64Encode(in,(int)inlen,p,&nOutLength));
+ }
+ if(bResult)
+ {
+ out.resize(nOutLength);
+ }
+
+ return bResult;
+}
+
+
+bool base64::decode(const char* in, size_t inlen,std::vector<BYTE>& out)
+{
+ int nOutLength = (int)inlen;
+ out.resize(nOutLength);
+ BYTE* p = &*out.begin();
+ bool bResult = TRUE == Base64Decode(in,(int)inlen,p,&nOutLength);
+ if(false == bResult)
+ {
+ out.resize(nOutLength);
+ p = &*out.begin();
+ bResult = TRUE == Base64Decode(in,(int)inlen,p,&nOutLength);
+ }
+ if(bResult)
+ {
+ out.resize(nOutLength);
+ }
+
+ return true;
+}
diff --git a/protocols/Quotes/src/Base64.h b/protocols/Quotes/src/Base64.h
new file mode 100644
index 0000000000..3f911bfeb8
--- /dev/null
+++ b/protocols/Quotes/src/Base64.h
@@ -0,0 +1,12 @@
+#ifndef __FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__
+#define __FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__
+
+#pragma once
+
+namespace base64
+{
+ bool encode(const BYTE* in, size_t inlen,std::vector<char>& out);
+ bool decode(const char* in, size_t inlen,std::vector<BYTE>& out);
+}
+
+#endif //__FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__
diff --git a/protocols/Quotes/src/Chart.h b/protocols/Quotes/src/Chart.h
new file mode 100644
index 0000000000..62a658d818
--- /dev/null
+++ b/protocols/Quotes/src/Chart.h
@@ -0,0 +1,280 @@
+#ifndef __FAE7F26E_61ED_4951_BE87_5E022CDF21DF_Chart_h__
+#define __FAE7F26E_61ED_4951_BE87_5E022CDF21DF_Chart_h__
+
+#pragma once
+
+namespace detail
+{
+ template<class T> struct CConverter
+ {
+ static double Convert(const T& v)
+ {
+ return boost::numeric_cast<double>(v);
+ }
+
+ static tstring ToString(const T& v)
+ {
+ return boost::lexical_cast<tstring>(v);
+ }
+ };
+
+ template<> struct CConverter<double>
+ {
+ static double Convert(double v)
+ {
+ return v;
+ }
+
+ static tstring ToString(double v)
+ {
+ tostringstream s;
+ s.imbue(std::locale(""));
+ s << std::fixed << v;
+ return s.str();
+ }
+ };
+}
+
+template<class TXValue,class TYValue,class TXConverter = detail::CConverter<TXValue>,class TYConverter = detail::CConverter<TYValue> >
+class CChart
+{
+private:
+ typedef std::pair<TXValue,TYValue> TValue;
+ typedef std::vector<TValue> TValues;
+
+public:
+ CChart() : m_MaxY(),m_MinY()
+ {
+ ZeroMemory(&m_rect,sizeof(m_rect));
+ }
+
+ ~CChart()
+ {
+ }
+
+ void AddValue(const TXValue& x,const TYValue& y)
+ {
+ if(m_aValues.empty())
+ {
+ m_MaxY = m_MinY = y;
+ }
+ else
+ {
+ m_MaxY = __max(y,m_MaxY);
+ m_MinY = __min(y,m_MinY);
+ }
+ m_aValues.push_back(std::make_pair(x,y));
+ }
+
+ void SetRect(int x,int y,int cx,int cy)
+ {
+ m_rect.left = x;
+ m_rect.right = x + cx;
+ m_rect.top = y;
+ m_rect.bottom = y + cy;
+ }
+
+ void Draw(HDC hdc)const
+ {
+ RECT rc = m_rect;
+ DrawBackground(hdc,rc);
+ if(false == m_aValues.empty())
+ {
+ ::InflateRect(&rc,-10,-10);
+ DrawGrid(hdc,rc);
+ DrawAxis(hdc,rc);
+ DrawPoints(hdc,rc);
+ }
+ else
+ {
+ HFONT hFont = static_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
+ HFONT hOldFont = static_cast<HFONT>(::SelectObject(hdc,hFont));
+
+ LPCTSTR pszText = TranslateT("There is no to show");
+ int nDrawTextResult = ::DrawText(hdc,pszText,::lstrlen(pszText),&rc,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
+ assert(0 != nDrawTextResult);
+
+ ::SelectObject(hdc,hOldFont);
+ BOOL bResult = ::DeleteObject(hFont);
+ assert(TRUE == bResult);
+ }
+ }
+
+private:
+ void DrawBackground(HDC hdc,RECT& rc)const
+ {
+// HBRUSH hBrush = ::CreateSolidBrush(RGB(255,0,0));//user preferable background color here!
+// ::FillRect(hdc,&m_rect,hBrush);
+// ::DeleteBrush(hBrush);
+ }
+
+ void DrawGrid(HDC hdc,RECT& rc)const
+ {
+ enum{number_of_lines = 5};
+ HPEN hPen = ::CreatePen(PS_SOLID,1,RGB(125,125,125));
+ HPEN hPenOld = static_cast<HPEN>(::SelectObject(hdc,hPen));
+ HFONT hFont = static_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
+ HFONT hOldFont = static_cast<HFONT>(::SelectObject(hdc,hFont));
+
+ //vertical grid
+ int step = (rc.bottom-rc.top)/number_of_lines;
+ TYValue y_val = m_MinY + ((m_MaxY-m_MinY)/number_of_lines);
+ int nXIndent = 0;
+ for(int y = rc.bottom-step;y > rc.top;y-=step,y_val+=((m_MaxY-m_MinY)/number_of_lines))
+ {
+ tstring sY = TYConverter::ToString(y_val);
+ SIZE sizeText = {0,0};
+ BOOL bResult = ::GetTextExtentPoint32(hdc,sY.c_str(), (int)sY.size(), &sizeText);
+ assert(TRUE == bResult);
+ nXIndent = __max(nXIndent,sizeText.cx);
+ }
+
+ y_val = m_MinY + ((m_MaxY-m_MinY)/number_of_lines);
+ nXIndent += 2;
+ rc.left += nXIndent;
+ for(int y = rc.bottom-step;y > rc.top;y-=step,y_val+=((m_MaxY-m_MinY)/number_of_lines))
+ {
+ tstring sY = TYConverter::ToString(y_val);
+ SIZE sizeText = {0,0};
+ BOOL bResult = ::GetTextExtentPoint32(hdc, sY.c_str(), (int)sY.size(), &sizeText);
+ assert(TRUE == bResult);
+
+ RECT rcText = {rc.left-nXIndent,y-(sizeText.cy/2),rc.left-1,y+(sizeText.cy/2)};
+ int nDrawTextResult = ::DrawText(hdc, sY.c_str(), (int)sY.size(), &rcText, DT_SINGLELINE|DT_VCENTER|DT_RIGHT);
+ assert(0 != nDrawTextResult);
+
+ bResult = ::MoveToEx(hdc,rc.left,y,NULL);
+ assert(TRUE == bResult);
+
+ bResult = ::LineTo(hdc,rc.right,y);
+ assert(TRUE == bResult);
+ }
+
+ // horizontal grid
+ HRGN rgnAllLables = ::CreateRectRgn(0,0,0,0);
+ HRGN rgnTemporary = ::CreateRectRgn(0,0,0,0);
+ bool bFixedRect = false;
+ step = (rc.right-rc.left)/number_of_lines;
+ TXValue x_val = m_aValues[0].first + ((m_aValues[m_aValues.size()-1].first-m_aValues[0].first)/number_of_lines);
+ for(int x = rc.left+step;x < rc.right;x+=step,x_val+=((m_aValues[m_aValues.size()-1].first-m_aValues[0].first)/number_of_lines))
+ {
+ tstring sX = TXConverter::ToString(x_val);
+ SIZE sizeText = {0,0};
+ BOOL bResult = ::GetTextExtentPoint32(hdc, sX.c_str(), (int)sX.size(), &sizeText);
+ assert(TRUE == bResult);
+
+ if(false == bFixedRect)
+ {
+ rc.bottom -= sizeText.cy+2;
+ bFixedRect = true;
+ }
+
+ RECT rcText = {x-(sizeText.cx/2),rc.bottom,x+(sizeText.cx/2),rc.bottom+sizeText.cy-1};
+ // Draw a label if it doesn't overlap with previous ones
+ HRGN rgnCurrentLable = ::CreateRectRgnIndirect(&rcText);
+ if(NULLREGION == ::CombineRgn(rgnTemporary,rgnCurrentLable,rgnAllLables,RGN_AND))
+ {
+ int nDrawTextResult = ::DrawText(hdc, sX.c_str(), (int)sX.size(), &rcText, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
+ assert(0 != nDrawTextResult);
+ int nCombineRgnResult = ::CombineRgn(rgnTemporary,rgnCurrentLable,rgnAllLables,RGN_OR);
+ assert(ERROR != nCombineRgnResult);
+ nCombineRgnResult = ::CombineRgn(rgnAllLables,rgnTemporary,NULL,RGN_COPY);
+ assert(ERROR != nCombineRgnResult);
+ }
+ bResult = ::DeleteObject(rgnCurrentLable);
+ assert(TRUE == bResult);
+
+ bResult = ::MoveToEx(hdc,x,rc.bottom,NULL);
+ assert(TRUE == bResult);
+
+ bResult = ::LineTo(hdc,x,rc.top);
+ assert(TRUE == bResult);
+ }
+
+ BOOL bResult = ::DeleteObject(rgnAllLables);
+ assert(TRUE == bResult);
+ bResult = ::DeleteObject(rgnTemporary);
+ assert(TRUE == bResult);
+
+ ::SelectObject(hdc,hOldFont);
+ ::SelectObject(hdc,hPenOld);
+ bResult = ::DeleteObject(hFont);
+ assert(TRUE == bResult);
+ bResult = ::DeleteObject(hPen);
+ assert(TRUE == bResult);
+ }
+
+ void DrawAxis(HDC hdc,RECT& rc)const
+ {
+ HPEN hPen = ::CreatePen(PS_SOLID,2,RGB(0,0,0));
+ HPEN hPenOld = static_cast<HPEN>(::SelectObject(hdc,hPen));
+
+ // draw Y-axes
+ BOOL bResult = ::MoveToEx(hdc,rc.left+1,rc.bottom-1,NULL);
+ assert(TRUE == bResult);
+ bResult = ::LineTo(hdc,rc.left+1,rc.top+1);
+ assert(TRUE == bResult);
+
+ // draw X-axes
+ bResult = ::MoveToEx(hdc,rc.left+1,rc.bottom-1,NULL);
+ assert(TRUE == bResult);
+ bResult = ::LineTo(hdc,rc.right-1,rc.bottom-1);
+ assert(TRUE == bResult);
+
+ ::SelectObject(hdc,hPenOld);
+ bResult = ::DeleteObject(hPen);
+ assert(TRUE == bResult);
+ }
+
+ void DrawPoints(HDC hdc,RECT& rc)const
+ {
+ TXValue xMin(m_aValues[0].first);
+ double dx = TXConverter::Convert(m_aValues[m_aValues.size()-1].first-xMin);
+ double dY = TYConverter::Convert(m_MaxY-m_MinY);
+
+ HPEN hPen = ::CreatePen(PS_SOLID,1,RGB(255,0,0));
+ HGDIOBJ hPenOld = ::SelectObject(hdc,hPen);
+
+ HBRUSH hBrush = ::CreateSolidBrush(RGB(255,0,0));
+ HGDIOBJ hBrushOld = ::SelectObject(hdc,hBrush);
+
+ bool bPrevValid = false;
+ int xPrex,yPrev;
+
+ BOOST_FOREACH(const TValue& v,m_aValues)
+ {
+ double k = TXConverter::Convert(v.first-xMin);
+
+ int x = rc.left+boost::numeric_cast<int>((rc.right-rc.left)*(k/dx));
+ k = TYConverter::Convert(v.second-m_MinY);
+ int y = rc.bottom-boost::numeric_cast<int>((rc.bottom-rc.top)*(k/dY));
+ ::Ellipse(hdc,x-5,y-5,x+5,y+5);
+ if(bPrevValid)
+ {
+ BOOL bResult = ::MoveToEx(hdc,xPrex,yPrev,NULL);
+ assert(TRUE == bResult);
+ bResult = ::LineTo(hdc,x,y);
+ assert(TRUE == bResult);
+ }
+
+ xPrex = x,yPrev = y;
+ bPrevValid = true;
+ }
+
+ ::SelectObject(hdc,hPenOld);
+ BOOL bResult = ::DeleteObject(hPen);
+ assert(TRUE == bResult);
+
+ ::SelectObject(hdc,hBrushOld);
+ bResult = ::DeleteObject(hBrush);
+ assert(TRUE == bResult);
+ }
+
+private:
+ TValues m_aValues;
+ RECT m_rect;
+ TYValue m_MaxY;
+ TYValue m_MinY;
+};
+
+#endif // __FAE7F26E_61ED_4951_BE87_5E022CDF21DF_Chart_h__
diff --git a/protocols/Quotes/src/ComHelper.cpp b/protocols/Quotes/src/ComHelper.cpp
new file mode 100644
index 0000000000..e15d05d739
--- /dev/null
+++ b/protocols/Quotes/src/ComHelper.cpp
@@ -0,0 +1,39 @@
+#include "StdAfx.h"
+#include "ComHelper.h"
+#include "Log.h"
+#include "WinCtrlHelper.h"
+
+tstring ComException2Msg(_com_error& e,const tstring& rsAdditionalInfo)
+{
+ HRESULT hError = e.Error();
+ tostringstream o;
+ if(false == rsAdditionalInfo.empty())
+ {
+ o << rsAdditionalInfo << "\n";
+ }
+
+ o << e.ErrorMessage() << _T(" (") << std::hex << hError << _T(")");
+
+ IErrorInfo* p = e.ErrorInfo();
+ CComPtr<IErrorInfo> pErrorInfo(p);
+ if(NULL != p)
+ {
+ p->Release();
+ }
+
+ if(pErrorInfo)
+ {
+ o << _T("\n") << e.Description();
+ }
+
+ return o.str();
+}
+
+void ShowComError(_com_error& e,const tstring& rsAdditionalInfo)
+{
+ tstring sErrorMsg = ComException2Msg(e,rsAdditionalInfo);
+ LogIt(Error,sErrorMsg);
+ Quotes_MessageBox(NULL,sErrorMsg.c_str(),MB_OK|MB_ICONERROR);
+}
+
+
diff --git a/protocols/Quotes/src/ComHelper.h b/protocols/Quotes/src/ComHelper.h
new file mode 100644
index 0000000000..0b4140d80d
--- /dev/null
+++ b/protocols/Quotes/src/ComHelper.h
@@ -0,0 +1,9 @@
+#ifndef __37ae28ab_c414_4aba_bbef_d23dd68643a5_ComHelper_h__
+#define __37ae28ab_c414_4aba_bbef_d23dd68643a5_ComHelper_h__
+
+#include <string>
+
+void ShowComError(_com_error& e,const tstring& rsAdditionalInfo);
+tstring ComException2Msg(_com_error& e,const tstring& rsAdditionalInfo);
+
+#endif//__37ae28ab_c414_4aba_bbef_d23dd68643a5_ComHelper_h__
diff --git a/protocols/Quotes/src/CommonOptionDlg.cpp b/protocols/Quotes/src/CommonOptionDlg.cpp
new file mode 100644
index 0000000000..0b460665c5
--- /dev/null
+++ b/protocols/Quotes/src/CommonOptionDlg.cpp
@@ -0,0 +1,272 @@
+#include "StdAfx.h"
+#include "CommonOptionDlg.h"
+#include "QuotesProviderBase.h"
+#include "resource.h"
+#include "EconomicRateInfo.h"
+#include "DBUtils.h"
+#include "QuotesProviderVisitorDbSettings.h"
+#include "WinCtrlHelper.h"
+#include "SettingsDlg.h"
+
+namespace
+{
+ typedef boost::shared_ptr<CAdvProviderSettings> TAdvSettingsPtr;
+ typedef std::map<const IQuotesProvider*,TAdvSettingsPtr> TAdvSettings;
+
+ TAdvSettings g_aAdvSettings;
+
+ CAdvProviderSettings* get_adv_settings(const IQuotesProvider* pProvider,bool bCreateIfNonExist)
+ {
+ TAdvSettings::iterator i = g_aAdvSettings.find(pProvider);
+ if(i != g_aAdvSettings.end())
+ {
+ return i->second.get();
+ }
+ else if(true == bCreateIfNonExist)
+ {
+ TAdvSettingsPtr pAdvSet(new CAdvProviderSettings(pProvider));
+ g_aAdvSettings.insert(std::make_pair(pProvider,pAdvSet));
+ return pAdvSet.get();
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ void remove_adv_settings(const IQuotesProvider* pProvider)
+ {
+ TAdvSettings::iterator i = g_aAdvSettings.find(pProvider);
+ if(i != g_aAdvSettings.end())
+ {
+ g_aAdvSettings.erase(i);
+ }
+ }
+}
+
+void CommonOptionDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp,CCommonDlgProcData& rData)
+{
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ assert(rData.m_pQuotesProvider);
+
+ CQuotesProviderVisitorDbSettings visitor;
+ rData.m_pQuotesProvider->Accept(visitor);
+ assert(visitor.m_pszDbRefreshRateType);
+ assert(visitor.m_pszDbRefreshRateValue);
+ assert(visitor.m_pszDbDisplayNameFormat);
+ assert(visitor.m_pszDbStatusMsgFormat);
+ assert(visitor.m_pszDbTendencyFormat);
+
+ // set contact list display format
+ tstring sDspNameFrmt = Quotes_DBGetStringT(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbDisplayNameFormat,visitor.m_pszDefDisplayFormat);
+ ::SetDlgItemText(hWnd,IDC_EDIT_CONTACT_LIST_FORMAT,sDspNameFrmt.c_str());
+
+ // set status message display format
+ tstring sStatusMsgFrmt = Quotes_DBGetStringT(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbStatusMsgFormat,visitor.m_pszDefStatusMsgFormat);
+ ::SetDlgItemText(hWnd,IDC_EDIT_STATUS_MESSAGE_FORMAT,sStatusMsgFrmt.c_str());
+
+ // set tendency format
+ tstring sTendencyFrmt = Quotes_DBGetStringT(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbTendencyFormat,visitor.m_pszDefTendencyFormat);
+ ::SetDlgItemText(hWnd,IDC_EDIT_TENDENCY_FORMAT,sTendencyFrmt.c_str());
+
+ // refresh rate
+ HWND hwndCombo = ::GetDlgItem(hWnd,IDC_COMBO_REFRESH_RATE);
+ LPCTSTR pszRefreshRateTypes[] = {TranslateT("Seconds"),TranslateT("Minutes"),TranslateT("Hours")};
+ for(int i = 0;i < SIZEOF(pszRefreshRateTypes);++i)
+ {
+ ::SendMessage(hwndCombo,CB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszRefreshRateTypes[i]));
+ }
+
+ int nRefreshRateType = DBGetContactSettingWord(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbRefreshRateType,RRT_MINUTES);
+ if(nRefreshRateType < RRT_SECONDS || nRefreshRateType > RRT_HOURS)
+ {
+ nRefreshRateType = RRT_MINUTES;
+ }
+
+ UINT nRate = DBGetContactSettingWord(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbRefreshRateValue,1);
+ switch(nRefreshRateType)
+ {
+ default:
+ case RRT_SECONDS:
+ case RRT_MINUTES:
+ if(nRate < 1 || nRate > 60)
+ {
+ nRate = 1;
+ }
+ spin_set_range(::GetDlgItem(hWnd,IDC_SPIN_REFRESH_RATE),1,60);
+ break;
+ case RRT_HOURS:
+ if(nRate < 1 || nRate > 24)
+ {
+ nRate = 1;
+ }
+ spin_set_range(::GetDlgItem(hWnd,IDC_SPIN_REFRESH_RATE),1,24);
+ break;
+ }
+
+ ::SendMessage(hwndCombo,CB_SETCURSEL,nRefreshRateType,0);
+ ::SetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,nRate,FALSE);
+
+ PropSheet_UnChanged(::GetParent(hWnd),hWnd);
+ }
+ break;
+ case WM_COMMAND:
+ switch(HIWORD(wp))
+ {
+ case CBN_SELCHANGE:
+ if(IDC_COMBO_REFRESH_RATE == LOWORD(wp))
+ {
+ ERefreshRateType nType = static_cast<ERefreshRateType>(::SendMessage(reinterpret_cast<HWND>(lp),CB_GETCURSEL,0,0));
+ switch(nType)
+ {
+ default:
+ case RRT_SECONDS:
+ case RRT_MINUTES:
+ spin_set_range(::GetDlgItem(hWnd,IDC_SPIN_REFRESH_RATE),1,60);
+ break;
+ case RRT_HOURS:
+ {
+ spin_set_range(::GetDlgItem(hWnd,IDC_SPIN_REFRESH_RATE),1,24);
+ BOOL bOk = FALSE;
+ UINT nRefreshRate = ::GetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,&bOk,FALSE);
+ if(TRUE == bOk && nRefreshRate > 24)
+ {
+ ::SetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,24,FALSE);
+ }
+ }
+ break;
+ }
+
+ PropSheet_Changed(::GetParent(hWnd),hWnd);
+ }
+ break;
+ case EN_CHANGE:
+ switch(LOWORD(wp))
+ {
+ case IDC_EDIT_REFRESH_RATE:
+ case IDC_EDIT_CONTACT_LIST_FORMAT:
+ case IDC_EDIT_STATUS_MESSAGE_FORMAT:
+ case IDC_EDIT_TENDENCY_FORMAT:
+ if(reinterpret_cast<HWND>(lp) == ::GetFocus())
+ {
+ PropSheet_Changed(::GetParent(hWnd),hWnd);
+ }
+ break;
+ }
+ break;
+ case BN_CLICKED:
+ switch( LOWORD(wp))
+ {
+ case IDC_BUTTON_DESCRIPTION:
+ show_variable_list(hWnd,rData.m_pQuotesProvider);
+ break;
+ case IDC_BUTTON_ADVANCED_SETTINGS:
+ {
+ CAdvProviderSettings* pAdvSet = get_adv_settings(rData.m_pQuotesProvider,true);
+ assert(pAdvSet);
+ if(true == ShowSettingsDlg(hWnd,pAdvSet))
+ {
+ PropSheet_Changed(::GetParent(hWnd),hWnd);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lp);
+ switch(pNMHDR->code)
+ {
+ case PSN_KILLACTIVE:
+ {
+ BOOL bOk = FALSE;
+ UINT nRefreshRate = ::GetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,&bOk,FALSE);
+ ERefreshRateType nType = static_cast<ERefreshRateType>(::SendMessage(::GetDlgItem(hWnd,IDC_COMBO_REFRESH_RATE),CB_GETCURSEL,0,0));
+ switch(nType)
+ {
+ default:
+ case RRT_MINUTES:
+ case RRT_SECONDS:
+ if(FALSE == bOk || nRefreshRate < 1 || nRefreshRate > 60)
+ {
+ prepare_edit_ctrl_for_error(::GetDlgItem(hWnd,IDC_EDIT_REFRESH_RATE));
+ Quotes_MessageBox(hWnd,TranslateT("Enter integer value between 1 and 60."),MB_OK|MB_ICONERROR);
+ bOk = FALSE;
+ }
+ break;
+ case RRT_HOURS:
+ if(FALSE == bOk || nRefreshRate < 1 || nRefreshRate > 24)
+ {
+ prepare_edit_ctrl_for_error(::GetDlgItem(hWnd,IDC_EDIT_REFRESH_RATE));
+ Quotes_MessageBox(hWnd,TranslateT("Enter integer value between 1 and 24."),MB_OK|MB_ICONERROR);
+ bOk = FALSE;
+ }
+ break;
+ }
+
+ if(TRUE == bOk)
+ {
+ HWND hEdit = ::GetDlgItem(hWnd,IDC_EDIT_CONTACT_LIST_FORMAT);
+ assert(IsWindow(hEdit));
+
+ tstring s = get_window_text(hEdit);
+ if(true == s.empty())
+ {
+ prepare_edit_ctrl_for_error(hEdit);
+ Quotes_MessageBox(hWnd,TranslateT("Enter text to display in contact list."),MB_OK|MB_ICONERROR);
+ bOk = FALSE;
+ }
+ }
+
+ ::SetWindowLongPtr(hWnd,DWLP_MSGRESULT,(TRUE == bOk) ? FALSE : TRUE);
+ }
+ break;
+ case PSN_APPLY:
+ {
+ BOOL bOk = FALSE;
+ UINT nRefreshRate = ::GetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,&bOk,FALSE);
+ assert(TRUE == bOk);
+ ERefreshRateType nType = static_cast<ERefreshRateType>(::SendMessage(::GetDlgItem(hWnd,IDC_COMBO_REFRESH_RATE),CB_GETCURSEL,0,0));
+
+ assert(rData.m_pQuotesProvider);
+
+ CQuotesProviderVisitorDbSettings visitor;
+ rData.m_pQuotesProvider->Accept(visitor);
+ assert(visitor.m_pszDbRefreshRateType);
+ assert(visitor.m_pszDbRefreshRateValue);
+ assert(visitor.m_pszDbDisplayNameFormat);
+ assert(visitor.m_pszDbStatusMsgFormat);
+
+ rData.m_bFireSetingsChangedEvent = true;
+ DBWriteContactSettingWord(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbRefreshRateType,nType);
+ DBWriteContactSettingWord(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbRefreshRateValue,nRefreshRate);
+
+ tstring s = get_window_text(::GetDlgItem(hWnd,IDC_EDIT_CONTACT_LIST_FORMAT));
+ DBWriteContactSettingTString(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbDisplayNameFormat,s.c_str());
+
+ s = get_window_text(::GetDlgItem(hWnd,IDC_EDIT_STATUS_MESSAGE_FORMAT));
+ DBWriteContactSettingTString(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbStatusMsgFormat,s.c_str());
+
+ s = get_window_text(::GetDlgItem(hWnd,IDC_EDIT_TENDENCY_FORMAT));
+ DBWriteContactSettingTString(NULL,QUOTES_MODULE_NAME,visitor.m_pszDbTendencyFormat,s.c_str());
+
+ CAdvProviderSettings* pAdvSet = get_adv_settings(rData.m_pQuotesProvider,false);
+ if(pAdvSet)
+ {
+ pAdvSet->SaveToDb();
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case WM_DESTROY:
+ remove_adv_settings(rData.m_pQuotesProvider);
+ break;
+ }
+} \ No newline at end of file
diff --git a/protocols/Quotes/src/CommonOptionDlg.h b/protocols/Quotes/src/CommonOptionDlg.h
new file mode 100644
index 0000000000..b9f696362a
--- /dev/null
+++ b/protocols/Quotes/src/CommonOptionDlg.h
@@ -0,0 +1,17 @@
+#ifndef __c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__
+#define __c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__
+
+class CQuotesProviderBase;
+
+struct CCommonDlgProcData
+{
+ CCommonDlgProcData(const CQuotesProviderBase* pQuotesProvider)
+ : m_pQuotesProvider(pQuotesProvider),m_bFireSetingsChangedEvent(false){}
+
+ const CQuotesProviderBase* m_pQuotesProvider;
+ bool m_bFireSetingsChangedEvent;
+};
+
+void CommonOptionDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp,CCommonDlgProcData& rData);
+
+#endif//__c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__
diff --git a/protocols/Quotes/src/CreateFilePath.cpp b/protocols/Quotes/src/CreateFilePath.cpp
new file mode 100644
index 0000000000..23c0c345b0
--- /dev/null
+++ b/protocols/Quotes/src/CreateFilePath.cpp
@@ -0,0 +1,45 @@
+#include "StdAfx.h"
+#include "CreateFilePath.h"
+
+#include <sstream>
+#include "ModuleInfo.h"
+
+namespace
+{
+ TCHAR replace_invalid_symbol(TCHAR chr)
+ {
+ TCHAR InvaliSymbols[] = {_T('\\'),_T('/'),_T(':'),_T('*'),_T('?'),_T('"'),_T('<'),_T('>'),_T('|')};
+ for(int i = 0; i < sizeof(InvaliSymbols)/sizeof(InvaliSymbols[0]);++i)
+ {
+ if(chr == InvaliSymbols[i])
+ {
+ return _T('_');
+ }
+ }
+
+ return chr;
+ }
+
+ void prepare_name(tstring& rsName)
+ {
+ std::transform(rsName.begin(),rsName.end(),rsName.begin(),boost::bind(replace_invalid_symbol,_1));
+ }
+}
+
+tstring CreateFilePath(const tstring& rsName)
+{
+ TCHAR szPath[_MAX_PATH];
+ ::GetModuleFileName(g_hInstance,szPath,_MAX_PATH);
+
+ TCHAR* p = _tcsrchr(szPath,_T('\\'));
+ if(p)
+ {
+ *p = 0;
+ }
+
+ tstring s(rsName);
+ prepare_name(s);
+ tostringstream o;
+ o << szPath << _T("\\Quotes\\") << s;
+ return o.str();
+} \ No newline at end of file
diff --git a/protocols/Quotes/src/CreateFilePath.h b/protocols/Quotes/src/CreateFilePath.h
new file mode 100644
index 0000000000..f097e59a52
--- /dev/null
+++ b/protocols/Quotes/src/CreateFilePath.h
@@ -0,0 +1,8 @@
+#ifndef _aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__
+#define _aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__
+
+#include <string>
+
+tstring CreateFilePath(const tstring& rsName);
+
+#endif //_aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__
diff --git a/protocols/Quotes/src/CurrencyConverter.cpp b/protocols/Quotes/src/CurrencyConverter.cpp
new file mode 100644
index 0000000000..7124677567
--- /dev/null
+++ b/protocols/Quotes/src/CurrencyConverter.cpp
@@ -0,0 +1,309 @@
+#include "StdAfx.h"
+#include "CurrencyConverter.h"
+#include "ModuleInfo.h"
+#include "resource.h"
+
+#include "QuotesProviderGoogle.h"
+#include "QuotesProviders.h"
+#include "WinCtrlHelper.h"
+#include "EconomicRateInfo.h"
+#include "Locale.h"
+#include "DBUtils.h"
+#include "IconLib.h"
+
+#define WINDOW_PREFIX "CurrenyConverter_"
+
+#define DB_STR_CC_QUOTE_FROM_ID "CurrencyConverter_FromID"
+#define DB_STR_CC_QUOTE_TO_ID "CurrencyConverter_ToID"
+#define DB_STR_CC_AMOUNT "CurrencyConverter_Amount"
+
+namespace
+{
+ CQuotesProviderGoogle* get_google_provider()
+ {
+ CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapQuotesProviders = pProviders->GetProviders();
+ for(CQuotesProviders::TQuotesProviders::const_iterator i = rapQuotesProviders.begin();i != rapQuotesProviders.end();++i)
+ {
+ const CQuotesProviders::TQuotesProviderPtr& pProvider = *i;
+ CQuotesProviderGoogle* pGoogle = dynamic_cast<CQuotesProviderGoogle*>(pProvider.get());
+ if(pGoogle)
+ {
+ return pGoogle;
+ }
+ }
+
+ assert(!"We should never get here!");
+ return NULL;
+ }
+
+
+ CQuotesProviderGoogle::CQuoteSection get_quotes(const CQuotesProviderGoogle* pProvider = NULL)
+ {
+ if(NULL == pProvider)
+ {
+ pProvider = get_google_provider();
+ }
+
+ if(pProvider)
+ {
+ const CQuotesProviderGoogle::CQuoteSection& rQuotes = pProvider->GetQuotes();
+ if(rQuotes.GetSectionCount() > 0)
+ {
+ return rQuotes.GetSection(0);
+ }
+ }
+
+ return CQuotesProviderGoogle::CQuoteSection();
+ }
+
+ inline tstring make_quote_name(const CQuotesProviderGoogle::CQuote& rQuote)
+ {
+ const tstring& rsDesc = rQuote.GetName();
+ return((false == rsDesc.empty()) ? rsDesc : rQuote.GetSymbol());
+ }
+
+ inline void update_convert_button(HWND hDlg)
+ {
+ int nFrom = static_cast<int>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0));
+ int nTo = static_cast<int>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_INTO),CB_GETCURSEL,0,0));
+ bool bEnableButton = ((CB_ERR != nFrom)
+ && (CB_ERR != nTo)
+ && (nFrom != nTo)
+ && (GetWindowTextLength(GetDlgItem(hDlg,IDC_EDIT_VALUE)) > 0));
+ EnableWindow(GetDlgItem(hDlg,IDC_BUTTON_CONVERT),bEnableButton);
+ }
+
+ inline void update_swap_button(HWND hDlg)
+ {
+ int nFrom = static_cast<int>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0));
+ int nTo = static_cast<int>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_INTO),CB_GETCURSEL,0,0));
+ bool bEnableButton = ((CB_ERR != nFrom)
+ && (CB_ERR != nTo)
+ && (nFrom != nTo));
+ EnableWindow(GetDlgItem(hDlg,IDC_BUTTON_SWAP),bEnableButton);
+ }
+
+ inline tstring double2str(double dValue)
+ {
+ tostringstream output;
+ output.imbue(GetSystemLocale());
+ output << std::fixed << std::setprecision(2) << dValue;
+ return output.str();
+ }
+
+ inline bool str2double(const tstring& s,double& d)
+ {
+ tistringstream input(s);
+ input.imbue(GetSystemLocale());
+ input >> d;
+ return ((false == input.bad()) && (false == input.fail()));
+ }
+
+
+ INT_PTR CALLBACK CurrencyConverterDlgProc(HWND hDlg,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,false);
+ assert(hWL);
+ WindowList_Add(hWL,hDlg,NULL);
+
+ TranslateDialogDefault(hDlg);
+
+ ::SendMessage(hDlg,WM_SETICON,FALSE,reinterpret_cast<LPARAM>(Quotes_LoadIconEx(ICON_STR_CURRENCY_CONVERTER)));
+ ::SendMessage(hDlg,WM_SETICON,TRUE,reinterpret_cast<LPARAM>(Quotes_LoadIconEx(ICON_STR_CURRENCY_CONVERTER,true)));
+
+ HWND hcbxFrom = ::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM);
+ HWND hcbxTo = ::GetDlgItem(hDlg,IDC_COMBO_CONVERT_INTO);
+
+ tstring sFromQuoteID = Quotes_DBGetStringT(NULL,QUOTES_MODULE_NAME,DB_STR_CC_QUOTE_FROM_ID);
+ tstring sToQuoteID = Quotes_DBGetStringT(NULL,QUOTES_MODULE_NAME,DB_STR_CC_QUOTE_TO_ID);
+
+ const CQuotesProviderGoogle* pProvider = get_google_provider();
+ const CQuotesProviderGoogle::CQuoteSection& rSection = get_quotes(pProvider);
+ size_t cQuotes = rSection.GetQuoteCount();
+ for(size_t i = 0;i < cQuotes;++i)
+ {
+ const CQuotesProviderGoogle::CQuote& rQuote = rSection.GetQuote(i);
+ tstring sName = make_quote_name(rQuote);
+ LPCTSTR pszName = sName.c_str();
+ LRESULT nFrom = ::SendMessage(hcbxFrom,CB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszName));
+ LRESULT nTo = ::SendMessage(hcbxTo,CB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszName));
+
+ if(0 == quotes_stricmp(rQuote.GetID().c_str(),sFromQuoteID.c_str()))
+ {
+ ::SendMessage(hcbxFrom,CB_SETCURSEL,nFrom,0);
+ }
+
+ if(0 == quotes_stricmp(rQuote.GetID().c_str(),sToQuoteID.c_str()))
+ {
+ ::SendMessage(hcbxTo,CB_SETCURSEL,nTo,0);
+ }
+ }
+
+ double dAmount = 1.0;
+ Quotes_DBReadDouble(NULL,QUOTES_MODULE_NAME,DB_STR_CC_AMOUNT,dAmount);
+ ::SetDlgItemText(hDlg,IDC_EDIT_VALUE,double2str(dAmount).c_str());
+
+ const IQuotesProvider::CProviderInfo& pi = pProvider->GetInfo();
+ tostringstream o;
+ o << TranslateT("Info provided by") << _T(" <a href=\"") << pi.m_sURL << _T("\">") << pi.m_sName << _T("</a>");
+
+ ::SetDlgItemText(hDlg,IDC_SYSLINK_PROVIDER,o.str().c_str());
+
+ ::SendMessage(::GetDlgItem(hDlg,IDC_BUTTON_SWAP),BM_SETIMAGE,IMAGE_ICON,
+ reinterpret_cast<LPARAM>(Quotes_LoadIconEx(ICON_STR_SWAP)));
+
+ update_convert_button(hDlg);
+ update_swap_button(hDlg);
+
+ Utils_RestoreWindowPositionNoSize(hDlg,NULL,QUOTES_PROTOCOL_NAME,WINDOW_PREFIX);
+ ::ShowWindow(hDlg,SW_SHOW);
+ }
+ return (TRUE);
+ case WM_CLOSE:
+ {
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,false);
+ assert(hWL);
+ WindowList_Remove(hWL,hDlg);
+ Utils_SaveWindowPosition(hDlg,NULL,QUOTES_PROTOCOL_NAME,WINDOW_PREFIX);
+ EndDialog(hDlg,0);
+ }
+ return (TRUE);
+ case WM_COMMAND:
+ switch(LOWORD(wp))
+ {
+ case IDC_COMBO_CONVERT_FROM:
+ case IDC_COMBO_CONVERT_INTO:
+ if(CBN_SELCHANGE == HIWORD(wp))
+ {
+ update_convert_button(hDlg);
+ update_swap_button(hDlg);
+ }
+ return TRUE;
+ case IDC_EDIT_VALUE:
+ if(EN_CHANGE == HIWORD(wp))
+ {
+ update_convert_button(hDlg);
+ }
+ return TRUE;
+ case IDCANCEL:
+ {
+ SendMessage(hDlg, WM_CLOSE, 0, 0);
+ }
+ return (TRUE);
+ case IDC_BUTTON_SWAP:
+ {
+ HWND wndFrom = ::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM);
+ HWND wndTo = ::GetDlgItem(hDlg,IDC_COMBO_CONVERT_INTO);
+ WPARAM nFrom = ::SendMessage(wndFrom,CB_GETCURSEL,0,0);
+ WPARAM nTo = ::SendMessage(wndTo,CB_GETCURSEL,0,0);
+
+ ::SendMessage(wndFrom,CB_SETCURSEL,nTo,0);
+ ::SendMessage(wndTo,CB_SETCURSEL,nFrom,0);
+ }
+ return (TRUE);
+ case IDC_BUTTON_CONVERT:
+ {
+ HWND hwndAmount = GetDlgItem(hDlg,IDC_EDIT_VALUE);
+ tstring sText = get_window_text(hwndAmount);
+
+ double dAmount = 1.0;
+ if ((true == str2double(sText,dAmount)) && (dAmount > 0.0))
+ {
+ Quotes_DBWriteDouble(NULL,QUOTES_MODULE_NAME,DB_STR_CC_AMOUNT,dAmount);
+
+ size_t nFrom = static_cast<size_t>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0));
+ size_t nTo = static_cast<size_t>(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_INTO),CB_GETCURSEL,0,0));
+ if ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo))
+ {
+ const CQuotesProviderGoogle::CQuoteSection& rSection = get_quotes();
+ size_t cQuotes = rSection.GetQuoteCount();
+ if ((nFrom < cQuotes) && (nTo < cQuotes))
+ {
+ CQuotesProviderGoogle::CRateInfo ri;
+ CQuotesProviderGoogle::CQuote from = rSection.GetQuote(nFrom);
+ CQuotesProviderGoogle::CQuote to = rSection.GetQuote(nTo);
+
+ DBWriteContactSettingTString(NULL,QUOTES_MODULE_NAME,DB_STR_CC_QUOTE_FROM_ID,from.GetID().c_str());
+ DBWriteContactSettingTString(NULL,QUOTES_MODULE_NAME,DB_STR_CC_QUOTE_TO_ID,to.GetID().c_str());
+
+ const CQuotesProviderGoogle* pProvider = get_google_provider();
+ assert(pProvider);
+ if(pProvider)
+ {
+ tstring sResult;
+ std::string sError;
+ try
+ {
+ double dResult = pProvider->Convert(dAmount,from,to);
+ tostringstream ss;
+ ss.imbue(GetSystemLocale());
+ ss << std::fixed << std::setprecision(2) << dAmount << " " << from.GetName() << " = " << dResult << " " << to.GetName();
+ sResult = ss.str();
+ }
+ catch(std::exception& e)
+ {
+ sError = e.what();
+ //Quotes_MessageBox(hDlg,sResult.c_str());
+ }
+
+ if(false == sError.empty())
+ {
+ //USES_CONVERSION;
+ sResult = quotes_a2t(sError.c_str());//A2T(sError.c_str());
+ }
+
+ SetDlgItemText(hDlg,IDC_EDIT_RESULT,sResult.c_str());
+ }
+ }
+ }
+ }
+ else
+ {
+ Quotes_MessageBox(hDlg,TranslateT("Enter positive number."),MB_OK|MB_ICONERROR);
+ prepare_edit_ctrl_for_error(GetDlgItem(hDlg,IDC_EDIT_VALUE));
+ }
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lp);
+ switch(pNMHDR->code)
+ {
+ case NM_CLICK:
+ if(IDC_SYSLINK_PROVIDER == wp)
+ {
+ PNMLINK pNMLink = reinterpret_cast<PNMLINK>(pNMHDR);
+ ::ShellExecute(hDlg,_T("open"),pNMLink->item.szUrl,NULL,NULL,SW_SHOWNORMAL);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return (FALSE);
+ }
+}
+
+INT_PTR QuotesMenu_CurrencyConverter(WPARAM wp,LPARAM lp)
+{
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,true);
+ HWND hWnd = WindowList_Find(hWL,NULL);
+ if(NULL != hWnd)
+ {
+ SetForegroundWindow(hWnd);
+ SetFocus(hWnd);
+ }
+ else
+ {
+ CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_CURRENCY_CONVERTER), NULL, CurrencyConverterDlgProc, 0);
+ }
+
+ return 0;
+}
diff --git a/protocols/Quotes/src/CurrencyConverter.h b/protocols/Quotes/src/CurrencyConverter.h
new file mode 100644
index 0000000000..9af7c6bca1
--- /dev/null
+++ b/protocols/Quotes/src/CurrencyConverter.h
@@ -0,0 +1,6 @@
+#ifndef __4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__
+#define __4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__
+
+INT_PTR QuotesMenu_CurrencyConverter(WPARAM wp,LPARAM lp);
+
+#endif //__4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__
diff --git a/protocols/Quotes/src/DBUtils.cpp b/protocols/Quotes/src/DBUtils.cpp
new file mode 100644
index 0000000000..11c0fb3d0d
--- /dev/null
+++ b/protocols/Quotes/src/DBUtils.cpp
@@ -0,0 +1,70 @@
+#include "StdAfx.h"
+#include "DBUtils.h"
+
+std::string Quotes_DBGetStringA(HANDLE hContact,const char* szModule,const char* szSetting,const char* pszDefValue /*= NULL*/)
+{
+ std::string sResult;
+ char* pszSymbol = DBGetString(hContact,szModule,szSetting);
+ if(NULL != pszSymbol)
+ {
+ sResult = pszSymbol;
+ mir_free(pszSymbol);
+ }
+ else if(NULL != pszDefValue)
+ {
+ sResult = pszDefValue;
+ }
+
+ return sResult;
+}
+
+std::wstring Quotes_DBGetStringW(HANDLE hContact,const char* szModule,const char* szSetting,const wchar_t* pszDefValue/* = NULL*/)
+{
+ std::wstring sResult;
+ wchar_t* pszSymbol = DBGetStringW(hContact,szModule,szSetting);
+ if(NULL != pszSymbol)
+ {
+ sResult = pszSymbol;
+ mir_free(pszSymbol);
+ }
+ else if(NULL != pszDefValue)
+ {
+ sResult = pszDefValue;
+ }
+
+ return sResult;
+}
+
+bool Quotes_DBWriteDouble(HANDLE hContact,const char* szModule,const char* szSetting,double dValue)
+{
+ DBCONTACTWRITESETTING cws = {0};
+
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_BLOB;
+ cws.value.cpbVal = sizeof(dValue);
+ cws.value.pbVal = reinterpret_cast<BYTE*>(&dValue);
+ return 0 == CallService(MS_DB_CONTACT_WRITESETTING,reinterpret_cast<WPARAM>(hContact),reinterpret_cast<LPARAM>(&cws));
+}
+
+bool Quotes_DBReadDouble(HANDLE hContact,const char* szModule,const char* szSetting,double& rdValue)
+{
+ DBVARIANT dbv = {0};
+ DBCONTACTGETSETTING cgs;
+ cgs.szModule=szModule;
+ cgs.szSetting=szSetting;
+ cgs.pValue = &dbv;
+ dbv.type = DBVT_BLOB;
+
+ bool bResult = ((0 == CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))
+ && (DBVT_BLOB == dbv.type));
+
+ if(bResult)
+ {
+ rdValue = *reinterpret_cast<double*>(dbv.pbVal);
+ }
+
+ DBFreeVariant(&dbv);
+ return bResult;
+}
+
diff --git a/protocols/Quotes/src/DBUtils.h b/protocols/Quotes/src/DBUtils.h
new file mode 100644
index 0000000000..27e3de5038
--- /dev/null
+++ b/protocols/Quotes/src/DBUtils.h
@@ -0,0 +1,13 @@
+#ifndef __54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__
+#define __54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__
+
+std::string Quotes_DBGetStringA(HANDLE hContact,const char* szModule,const char* szSetting,const char* pszDefValue = NULL);
+std::wstring Quotes_DBGetStringW(HANDLE hContact,const char* szModule,const char* szSetting,const wchar_t* pszDefValue = NULL);
+
+
+#define Quotes_DBGetStringT Quotes_DBGetStringW
+
+bool Quotes_DBWriteDouble(HANDLE hContact,const char* szModule,const char* szSetting,double dValue);
+bool Quotes_DBReadDouble(HANDLE hContact,const char* szModule,const char* szSetting,double& rdValue);
+
+#endif //__54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__
diff --git a/protocols/Quotes/src/EconomicRateInfo.h b/protocols/Quotes/src/EconomicRateInfo.h
new file mode 100644
index 0000000000..73e269619c
--- /dev/null
+++ b/protocols/Quotes/src/EconomicRateInfo.h
@@ -0,0 +1,59 @@
+#ifndef __87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__
+#define __87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__
+
+#define QUOTES_PROTOCOL_NAME "Quotes"// protocol name
+
+#define QUOTES_MODULE_NAME QUOTES_PROTOCOL_NAME // db settings module path
+
+enum ERefreshRateType
+{
+ RRT_SECONDS = 0,
+ RRT_MINUTES = 1,
+ RRT_HOURS = 2
+};
+
+#define DB_STR_ENABLE_LOG "EnableLog"
+#define DB_STR_QUOTE_PROVIDER "QuoteProvider"
+#define DB_STR_QUOTE_ID "QuoteID"
+#define DB_STR_QUOTE_SYMBOL "QuoteSymbol"
+#define DB_STR_QUOTE_DESCRIPTION "QuoteDescription"
+#define DB_STR_QUOTE_PREV_VALUE "PreviousQuoteValue"
+#define DB_STR_QUOTE_CURR_VALUE "CurrentQuoteValue"
+#define DB_STR_QUOTE_FETCH_TIME "FetchTime"
+
+
+enum ELogMode
+{
+ lmDisabled = 0x0000,
+ lmInternalHistory = 0x0001,
+ lmExternalFile = 0x0002,
+ lmPopup = 0x0004,
+};
+
+#define DB_STR_CONTACT_SPEC_SETTINGS "ContactSpecSettings"
+#define DB_STR_QUOTE_LOG "Log"
+#define DB_STR_QUOTE_LOG_FILE "LogFile"
+#define DB_STR_QUOTE_FORMAT_LOG_FILE "LogFileFormat"
+#define DB_STR_QUOTE_FORMAT_HISTORY "HistoryFormat"
+#define DB_STR_QUOTE_LOG_FILE_CONDITION "AddToLogOnlyIfValueIsChanged"
+#define DB_STR_QUOTE_HISTORY_CONDITION "AddToHistoryOnlyIfValueIsChanged"
+#define DB_STR_QUOTE_EXTRA_IMAGE_SLOT "ExtraImageSlot"
+#define DB_STR_QUOTE_FORMAT_POPUP "PopupFormat"
+#define DB_STR_QUOTE_POPUP_CONDITION "ShowPopupOnlyIfValueIsChanged"
+
+#define DB_STR_QUOTE_POPUP_COLOUR_MODE "PopupColourMode"
+#define DB_STR_QUOTE_POPUP_COLOUR_BK "PopupColourBk"
+#define DB_STR_QUOTE_POPUP_COLOUR_TEXT "PopupColourText"
+#define DB_STR_QUOTE_POPUP_DELAY_MODE "PopupDelayMode"
+#define DB_STR_QUOTE_POPUP_DELAY_TIMEOUT "PopupDelayTimeout"
+#define DB_STR_QUOTE_POPUP_HISTORY_FLAG "PopupHistoryFlag"
+
+
+// #define DB_STR_NICK "Nick"
+#define DB_STR_STATUS "Status"
+
+#define LIST_MODULE_NAME "CList"
+#define CONTACT_LIST_NAME "MyHandle"
+#define STATUS_MSG_NAME "StatusMsg"
+
+#endif //__87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__
diff --git a/protocols/Quotes/src/ExtraImages.cpp b/protocols/Quotes/src/ExtraImages.cpp
new file mode 100644
index 0000000000..35a59a8c1d
--- /dev/null
+++ b/protocols/Quotes/src/ExtraImages.cpp
@@ -0,0 +1,143 @@
+#include "StdAfx.h"
+#include "ExtraImages.h"
+#include "IconLib.h"
+#include "EconomicRateInfo.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "IQuotesProvider.h"
+#include "Log.h"
+#include "DBUtils.h"
+
+namespace
+{
+ inline HANDLE extra_add_icon(const char* psz)
+ {
+ return reinterpret_cast<HANDLE>(
+ CallService(MS_CLIST_EXTRA_ADD_ICON,reinterpret_cast<WPARAM>(Quotes_LoadIconEx(psz)),0));
+ }
+
+ const HANDLE INVALID_IMAGE_HANDLE = reinterpret_cast<HANDLE>(-1);
+}
+
+CExtraImages::CExtraImages()
+ : m_hExtraIcons(ExtraIcon_Register(ICON_STR_QUOTE,QUOTES_PROTOCOL_NAME,Quotes_MakeIconName(ICON_STR_MAIN).c_str())),
+ m_bExtraImagesInit(false),
+ m_nSlot(DBGetContactSettingWord(NULL,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_EXTRA_IMAGE_SLOT,EXTRA_ICON_ADV1))
+{
+ m_ahExtraImages[eiUp] = INVALID_IMAGE_HANDLE;
+ m_ahExtraImages[eiDown] = INVALID_IMAGE_HANDLE;
+ m_ahExtraImages[eiNotChanged] = INVALID_IMAGE_HANDLE;
+}
+
+CExtraImages::~CExtraImages()
+{
+}
+
+CExtraImages& CExtraImages::GetInstance()
+{
+ static CExtraImages s_ei;
+ return s_ei;
+}
+
+void CExtraImages::RebuildExtraImages()
+{
+ if(NULL == m_hExtraIcons)
+ {
+ m_bExtraImagesInit = false;
+ CGuard<CLightMutex> cs(m_lmExtraImages);
+ m_ahExtraImages[eiUp] = extra_add_icon(ICON_STR_QUOTE_UP);
+ m_ahExtraImages[eiDown] = extra_add_icon(ICON_STR_QUOTE_DOWN);
+ m_ahExtraImages[eiNotChanged] = extra_add_icon(ICON_STR_QUOTE_NOT_CHANGED);
+ m_bExtraImagesInit = true;
+ }
+}
+
+
+bool CExtraImages::SetContactExtraImage(HANDLE hContact,EImageIndex nIndex)const
+{
+// tstring s = Quotes_DBGetStringT(hContact,LIST_MODULE_NAME,CONTACT_LIST_NAME);
+// tostringstream o;
+// o << _T("SetContactExtraImage for ") << s << _T("\nExtra image list init: ") << m_bExtraImagesInit << _T("\n");
+
+ bool bResult = false;
+ if(m_hExtraIcons)
+ {
+// o << "Using extra icon interface\n";
+ std::string sIconName;
+ switch(nIndex)
+ {
+ case eiUp:
+ sIconName = Quotes_MakeIconName(ICON_STR_QUOTE_UP);
+ break;
+ case eiDown:
+ sIconName = Quotes_MakeIconName(ICON_STR_QUOTE_DOWN);
+ break;
+ case eiNotChanged:
+ sIconName = Quotes_MakeIconName(ICON_STR_QUOTE_NOT_CHANGED);
+ break;
+ }
+ bResult = (0 == ExtraIcon_SetIcon(m_hExtraIcons,hContact,sIconName.c_str()));
+ }
+ else if(m_bExtraImagesInit && ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+// o << "Using contact list interface index is ";
+ IconExtraColumn iec = {0};
+ iec.cbSize = sizeof(iec);
+ iec.ColumnType = m_nSlot;
+
+ {
+ CGuard<CLightMutex> cs(m_lmExtraImages);
+ switch(nIndex)
+ {
+ case eiUp:
+// o << "up\n";
+ iec.hImage = m_ahExtraImages[eiUp];
+ break;
+ case eiDown:
+// o << "down\n";
+ iec.hImage = m_ahExtraImages[eiDown];
+ break;
+ case eiNotChanged:
+// o << "not changed\n";
+ iec.hImage = m_ahExtraImages[eiNotChanged];
+ break;
+ default:
+// o << "invalid\n";
+ iec.hImage = INVALID_IMAGE_HANDLE;
+ break;
+ }
+ }
+
+ bResult = (0 == CallService(MS_CLIST_EXTRA_SET_ICON,reinterpret_cast<WPARAM>(hContact),reinterpret_cast<LPARAM>(&iec)));
+ }
+
+// o << "Result is " << bResult;
+// LogIt(Info,o.str());
+ return bResult;
+}
+
+int QuotesEventFunc_onExtraImageListRebuild(WPARAM /*wp*/,LPARAM /*lp*/)
+{
+ if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ CExtraImages::GetInstance().RebuildExtraImages();
+ }
+
+ return 0;
+}
+
+int QuotesEventFunc_onExtraImageApply(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+
+ const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ pProvider->SetContactExtraIcon(hContact);
+ }
+
+ return 0;
+}
+
+
diff --git a/protocols/Quotes/src/ExtraImages.h b/protocols/Quotes/src/ExtraImages.h
new file mode 100644
index 0000000000..ec8ae01e39
--- /dev/null
+++ b/protocols/Quotes/src/ExtraImages.h
@@ -0,0 +1,39 @@
+#ifndef __9d0dac0c_12e4_46ce_809a_db6dc7d6f269_ExtraImages_h__
+#define __9d0dac0c_12e4_46ce_809a_db6dc7d6f269_ExtraImages_h__
+
+#include "LightMutex.h"
+
+class CExtraImages : private boost::noncopyable
+{
+public:
+ enum EImageIndex
+ {
+ eiUp = 0,
+ eiDown = 1,
+ eiNotChanged = 2,
+ eiEmpty = 3,
+ ImageCount = 3
+ };
+
+private:
+ CExtraImages();
+ ~CExtraImages();
+
+public:
+ static CExtraImages& GetInstance();
+
+ void RebuildExtraImages();
+ bool SetContactExtraImage(HANDLE hContact,EImageIndex nIndex)const;
+
+private:
+ mutable CLightMutex m_lmExtraImages;
+ HANDLE m_ahExtraImages[ImageCount];
+ HANDLE m_hExtraIcons;
+ bool m_bExtraImagesInit;
+ int m_nSlot;
+};
+
+int QuotesEventFunc_onExtraImageListRebuild(WPARAM wp,LPARAM lp);
+int QuotesEventFunc_onExtraImageApply(WPARAM wp,LPARAM lp);
+
+#endif //__9d0dac0c_12e4_46ce_809a_db6dc7d6f269_ExtraImages_h__
diff --git a/protocols/Quotes/src/Forex.cpp b/protocols/Quotes/src/Forex.cpp
new file mode 100644
index 0000000000..ab27ba41c3
--- /dev/null
+++ b/protocols/Quotes/src/Forex.cpp
@@ -0,0 +1,478 @@
+// Forex.cpp : Defines the exported functions for the DLL application.
+//
+
+#include "stdafx.h"
+
+#pragma warning(disable:4996)
+#include <m_protocols.h>
+#include <m_protomod.h>
+#pragma warning(default:4996)
+#include "WorkingThread.h"
+#include <m_protosvc.h>
+#include "resource.h"
+#include "IconLib.h"
+#include <m_options.h>
+#include <m_userinfo.h>
+#include "QuoteInfoDlg.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "IQuotesProvider.h"
+#include "EconomicRateInfo.h"
+#include "DBUtils.h"
+#include "ExtraImages.h"
+#include "HTTPSession.h"
+#include "CurrencyConverter.h"
+#ifdef CHART_IMPLEMENT
+#include "QuoteChart.h"
+#endif
+#include "WinCtrlHelper.h"
+#include "ImportExport.h"
+#include "m_Quotes.h"
+#include "version.h"
+
+int hLangpack;
+HINSTANCE g_hInstance = NULL;
+HANDLE g_hEventWorkThreadStop;
+int g_nStatus = ID_STATUS_OFFLINE;
+HGENMENU g_hMenuEditSettings = NULL;
+HGENMENU g_hMenuOpenLogFile = NULL;
+#ifdef CHART_IMPLEMENT
+HGENMENU g_hMenuChart = NULL;
+#endif
+HGENMENU g_hMenuRefresh = NULL;
+
+namespace
+{
+ typedef std::vector<HANDLE> THandles;
+ THandles g_ahEvents;
+ THandles g_ahServices;
+ THandles g_ahThreads;
+ std::vector<HGENMENU> g_ahMenus;
+
+ PLUGININFOEX Global_pluginInfo =
+ {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {E882056D-0D1D-4131-9A98-404CBAEA6A9C}
+ {0xe882056d, 0xd1d, 0x4131, { 0x9a, 0x98, 0x40, 0x4c, 0xba, 0xea, 0x6a, 0x9c } }
+ };
+
+ INT_PTR QuotesMenu_RefreshAll(WPARAM wp,LPARAM lp)
+ {
+ const CQuotesProviders::TQuotesProviders& apProviders = CModuleInfo::GetQuoteProvidersPtr()->GetProviders();
+ std::for_each(apProviders.begin(),apProviders.end(),boost::bind(&IQuotesProvider::RefreshAll,_1));
+ return 0;
+ }
+
+ void InitMenu()
+ {
+// USES_CONVERSION;
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ //mi.ptszPopupName = _T("Quotes");
+ mi.ptszName = _T("Quotes");
+ mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTPOPUP;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN);
+ HGENMENU hMenuRoot = Menu_AddMainMenuItem(&mi);
+ g_ahMenus.push_back(hMenuRoot);
+
+ mi.ptszName = _T("Refresh All Quotes\\Rates");
+ mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE;
+ //mi.position = 0x0FFFFFFF;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN);
+ mi.pszService = "Quotes/RefreshAll";
+ mi.hParentMenu = hMenuRoot;
+ HGENMENU hMenu = Menu_AddMainMenuItem(&mi);
+ g_ahMenus.push_back(hMenu);
+ HANDLE h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshAll);
+ g_ahServices.push_back(h);
+
+ mi.ptszName = _T("Currency Converter...");
+ //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE;
+ //mi.position = 0x0FFFFFFF;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_CURRENCY_CONVERTER);
+ mi.pszService = "Quotes/CurrencyConverter";
+ hMenu = Menu_AddMainMenuItem(&mi);
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_CurrencyConverter);
+ g_ahServices.push_back(h);
+
+#ifdef TEST_IMPORT_EXPORT
+ mi.ptszName = _T("Export All Quotes");
+ //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_EXPORT);
+ mi.pszService = "Quotes/ExportAll";
+ hMenu = Menu_AddMainMenuItem(&mi);
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_ExportAll);
+ g_ahServices.push_back(h);
+
+ mi.ptszName =_T("Import All Quotes");
+ //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_IMPORT);
+ mi.pszService = "Quotes/ImportAll";
+ hMenu = Menu_AddMainMenuItem(&mi);
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_ImportAll);
+ g_ahServices.push_back(h);
+#endif
+
+ bool bSubGroups = 1 == ServiceExists(MS_CLIST_MENUBUILDSUBGROUP);
+
+ h = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,Quotes_PrebuildContactMenu);
+ g_ahEvents.push_back(h);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.pszContactOwner = QUOTES_PROTOCOL_NAME;
+ hMenuRoot = NULL;
+ if(bSubGroups)
+ {
+ mi.pszPopupName=(char *)-1;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN);
+ mi.flags = CMIF_ICONFROMICOLIB|CMIF_TCHAR|CMIF_ROOTPOPUP;
+ tstring sProtocolName = quotes_a2t(QUOTES_PROTOCOL_NAME);
+ mi.ptszName = const_cast<TCHAR*>(sProtocolName.c_str());//A2T(QUOTES_PROTOCOL_NAME);
+ mi.position = 0;
+
+ hMenuRoot = Menu_AddContactMenuItem(&mi);
+ }
+
+ mi.flags = CMIF_TCHAR;
+ if(bSubGroups)
+ {
+ mi.flags |= CMIF_CHILDPOPUP;
+ mi.pszPopupName = (char*)hMenuRoot;
+ }
+
+ mi.ptszName = _T("Refresh");
+ mi.popupPosition = 0;
+ mi.flags |= CMIF_ICONFROMICOLIB;
+ mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_REFRESH);
+ mi.pszService = "Quotes/RefreshContact";
+ hMenu = Menu_AddContactMenuItem(&mi);
+ g_hMenuRefresh = hMenu;
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshContact);
+ g_ahServices.push_back(h);
+
+ mi.ptszName = _T("Open Log File...");
+ mi.popupPosition = 1;
+ mi.icolibItem = NULL;
+ mi.pszService = "Quotes/OpenLogFile";
+ hMenu = Menu_AddContactMenuItem(&mi);
+ g_hMenuOpenLogFile = hMenu;
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_OpenLogFile);
+ g_ahServices.push_back(h);
+
+#ifdef CHART_IMPLEMENT
+ mi.ptszName = _T("Chart...");
+ mi.popupPosition = 2;
+ mi.icolibItem = NULL;
+ mi.pszService = "Quotes/Chart";
+ hMenu = Menu_AddContactMenuItem(&mi);
+ g_hMenuChart = hMenu;
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_Chart);
+ g_ahServices.push_back(h);
+#endif
+
+ mi.ptszName = _T("Edit Settings...");
+#ifdef CHART_IMPLEMENT
+ mi.popupPosition = 3;
+#else
+ mi.popupPosition = 2;
+#endif
+ mi.icolibItem = NULL;
+ mi.pszService = "Quotes/EditSettings";
+ hMenu = Menu_AddContactMenuItem(&mi);
+ g_hMenuEditSettings = hMenu;
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_EditSettings);
+ g_ahServices.push_back(h);
+ }
+
+
+ int QuotesEventFunc_OnModulesLoaded(WPARAM, LPARAM)
+ {
+ CHTTPSession::Init();
+
+ HANDLE h = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD,QuotesEventFunc_onExtraImageListRebuild);
+ g_ahEvents.push_back(h);
+// QuotesEventFunc_onExtraImageListRebuild(0,0);
+
+ h = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY,QuotesEventFunc_onExtraImageApply);
+ g_ahEvents.push_back(h);
+
+ g_hEventWorkThreadStop = ::CreateEvent(NULL,TRUE,FALSE,NULL);
+ h = (ME_USERINFO_INITIALISE,QuotesEventFunc_OnUserInfoInit);
+ g_ahEvents.push_back(h);
+
+
+ h = HookEvent(ME_CLIST_DOUBLECLICKED,Quotes_OnContactDoubleClick);
+ g_ahEvents.push_back(h);
+
+ InitMenu();
+
+ return 0;
+ }
+
+ int QuotesEventFunc_OnContactDeleted(WPARAM wParam, LPARAM)
+ {
+ HANDLE hContact = reinterpret_cast<HANDLE>(wParam);
+
+ const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ pProvider->DeleteContact(hContact);
+ }
+
+ return 0;
+ }
+
+ INT_PTR QuoteProtoFunc_GetStatus(WPARAM/* wp*/,LPARAM/* lp*/)
+ {
+ return g_nStatus;
+ }
+
+ void WaitForWorkingThreads()
+ {
+ size_t cThreads = g_ahThreads.size();
+ if(cThreads > 0)
+ {
+ HANDLE* paHandles = &*(g_ahThreads.begin());
+ ::WaitForMultipleObjects((DWORD)cThreads,paHandles,TRUE,INFINITE);
+ }
+ }
+
+ INT_PTR QuoteProtoFunc_SetStatus(WPARAM wp,LPARAM /*lp*/)
+ {
+ int nStatus = wp;
+ if ((ID_STATUS_ONLINE == nStatus) || (ID_STATUS_OFFLINE == nStatus))
+ {
+ int nOldStatus = g_nStatus;
+ if(nStatus != g_nStatus)
+ {
+ g_nStatus = nStatus;
+ if ((ID_STATUS_ONLINE == nOldStatus) && (ID_STATUS_OFFLINE == g_nStatus))
+ {
+ BOOL b = ::SetEvent(g_hEventWorkThreadStop);
+ assert(b);
+ }
+ else if ((ID_STATUS_ONLINE == g_nStatus) && (ID_STATUS_OFFLINE == nOldStatus))
+ {
+ BOOL b = ::ResetEvent(g_hEventWorkThreadStop);
+ assert(b && "Failed to reset event");
+
+ const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapProviders = pProviders->GetProviders();
+ for(CQuotesProviders::TQuotesProviders::const_iterator i = rapProviders.begin();i != rapProviders.end();++i)
+ {
+ const CQuotesProviders::TQuotesProviderPtr& pProvider = *i;
+ HANDLE hThread = reinterpret_cast<HANDLE>(mir_forkthread(WorkingThread,pProvider.get()));
+ g_ahThreads.push_back(hThread);
+ }
+ }
+
+ ProtoBroadcastAck(QUOTES_PROTOCOL_NAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,reinterpret_cast<HANDLE>(nOldStatus),g_nStatus);
+ }
+
+ }
+
+ return 0;
+ }
+
+ int QuotesEventFunc_PreShutdown(WPARAM wParam, LPARAM lParam)
+ {
+ QuoteProtoFunc_SetStatus(ID_STATUS_OFFLINE,0);
+ //WindowList_Broadcast(g_hWindowListEditSettings,WM_CLOSE,0,0);
+ CModuleInfo::GetInstance().OnMirandaShutdown();
+ return 0;
+ }
+
+ INT_PTR QuoteProtoFunc_GetName(WPARAM wParam, LPARAM lParam)
+ {
+ if(lParam)
+ {
+ lstrcpynA(reinterpret_cast<char*>(lParam),QUOTES_PROTOCOL_NAME,wParam);
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ INT_PTR QuoteProtoFunc_GetCaps(WPARAM wp,LPARAM lp)
+ {
+ int ret = 0;
+ switch(wp)
+ {
+ case PFLAGNUM_1:
+ ret = PF1_PEER2PEER;
+ break;
+ case PFLAGNUM_3:
+ case PFLAGNUM_2:
+ ret = PF2_ONLINE|PF2_LONGAWAY;
+ if(CModuleInfo::GetInstance().GetExtendedStatusFlag())
+ {
+ ret |= PF2_LIGHTDND;
+ }
+ break;
+ }
+
+ return ret;
+ }
+
+ INT_PTR QuoteProtoFunc_LoadIcon(WPARAM wp,LPARAM /*lp*/)
+ {
+ if ((wp & 0xffff) == PLI_PROTOCOL)
+ {
+ return reinterpret_cast<int>(::CopyIcon(Quotes_LoadIconEx(ICON_STR_MAIN)));
+ }
+
+ return 0;
+ }
+
+ int QuotesEventFunc_OptInitialise(WPARAM wp,LPARAM/* lp*/)
+ {
+ const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapProviders = pProviders->GetProviders();
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = 910000000;
+ odp.hInstance = g_hInstance;
+ odp.ptszTitle = _T(QUOTES_PROTOCOL_NAME);
+ odp.ptszGroup = LPGENT("Network");
+ odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN);
+ odp.flags = ODPF_USERINFOTAB | ODPF_TCHAR;
+
+ std::for_each(rapProviders.begin(),rapProviders.end(),boost::bind(&IQuotesProvider::ShowPropertyPage,_1,wp,boost::ref(odp)));
+ return 0;
+ }
+
+ inline int Quotes_DestroyServiceFunction(HANDLE h)
+ {
+ return DestroyServiceFunction(h);
+ }
+
+ inline int Quotes_UnhookEvent(HANDLE h)
+ {
+ return UnhookEvent(h);
+ }
+
+ inline int Quotes_RemoveMenuItem(HGENMENU h)
+ {
+ return CallService(MS_CLIST_REMOVECONTACTMENUITEM,reinterpret_cast<WPARAM>(h),0);
+ }
+
+// PROTO_INTERFACE* protoInit(const char* pszProtoName, const TCHAR* tszUserName)
+// {
+// CAimProto *ppro = new CAimProto(pszProtoName, tszUserName);
+// g_Instances.insert(ppro);
+// return ppro;
+// }
+//
+// int protoUninit(PROTO_INTERFACE* ppro)
+// {
+// g_Instances.remove((CAimProto*)ppro);
+// return 0;
+// }
+
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ g_hInstance = hinstDLL;
+ return TRUE;
+}
+
+extern "C"
+{
+ __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+ {
+ return &Global_pluginInfo;
+ }
+
+
+ #define MIID_QUOTES {0x723243c2, 0x8d4b, 0x4c29, { 0x8a, 0x37, 0xc0, 0x11, 0x48, 0x65, 0xb0, 0x80}}
+
+ __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL,MIID_QUOTES,MIID_LAST};
+
+ int __declspec(dllexport) Load(void)
+ {
+
+ mir_getLP(&Global_pluginInfo);
+// if ((mirandaVersion >= 0x0800) && (1 == mir_getXI(&xi)))
+// {
+// CModuleInfo::SetXMLEnginePtr(CModuleInfo::TXMLEnginePtr(new CXMLEngineMI));
+// }
+
+ if(false == CModuleInfo::Verify())
+ {
+ return 1;
+ }
+
+ Quotes_IconsInit();
+
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize = /*sizeof(pd)*/PROTOCOLDESCRIPTOR_V3_SIZE;
+ pd.szName = QUOTES_PROTOCOL_NAME;
+ pd.type = PROTOTYPE_PROTOCOL;
+// pd.fnInit = protoInit;
+// pd.fnUninit = protoUninit;
+
+ CallService( MS_PROTO_REGISTERMODULE, 0, ( LPARAM )&pd );
+
+ HANDLE h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETNAME, QuoteProtoFunc_GetName);
+ g_ahServices.push_back(h);
+ h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETCAPS, QuoteProtoFunc_GetCaps);
+ g_ahServices.push_back(h);
+ h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_SETSTATUS, QuoteProtoFunc_SetStatus);
+ g_ahServices.push_back(h);
+ h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETSTATUS, QuoteProtoFunc_GetStatus);
+ g_ahServices.push_back(h);
+ h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_LOADICON, QuoteProtoFunc_LoadIcon);
+ g_ahServices.push_back(h);
+
+ h = HookEvent(ME_SYSTEM_MODULESLOADED,QuotesEventFunc_OnModulesLoaded);
+ g_ahEvents.push_back(h);
+ h = HookEvent(ME_DB_CONTACT_DELETED,QuotesEventFunc_OnContactDeleted);
+ g_ahEvents.push_back(h);
+ h = HookEvent(ME_SYSTEM_PRESHUTDOWN,QuotesEventFunc_PreShutdown);
+ g_ahEvents.push_back(h);
+ h = HookEvent(ME_OPT_INITIALISE,QuotesEventFunc_OptInitialise);
+ g_ahEvents.push_back(h);
+
+ h = CreateServiceFunction(MS_QUOTES_EXPORT, Quotes_Export);
+ g_ahServices.push_back(h);
+ h = CreateServiceFunction(MS_QUOTES_IMPORT, Quotes_Import);
+ g_ahServices.push_back(h);
+
+ return 0;
+ }
+
+ __declspec(dllexport) int Unload(void)
+ {
+ std::for_each(g_ahServices.begin(),g_ahServices.end(),boost::bind(Quotes_DestroyServiceFunction,_1));
+ std::for_each(g_ahEvents.begin(),g_ahEvents.end(),boost::bind(Quotes_UnhookEvent,_1));
+ std::for_each(g_ahMenus.begin(),g_ahMenus.end(),boost::bind(Quotes_RemoveMenuItem,_1));
+
+ WaitForWorkingThreads();
+
+ ::CloseHandle(g_hEventWorkThreadStop);
+
+ return 0;
+ }
+}
diff --git a/protocols/Quotes/src/HTMLParserMS.cpp b/protocols/Quotes/src/HTMLParserMS.cpp
new file mode 100644
index 0000000000..bfe58b43b1
--- /dev/null
+++ b/protocols/Quotes/src/HTMLParserMS.cpp
@@ -0,0 +1,313 @@
+#include "StdAfx.h"
+#include "HTMLParserMS.h"
+
+using _com_util::CheckError;
+
+namespace
+{
+ class CHTMLNode : public IHTMLNode
+ {
+ public:
+ typedef CComPtr<IDispatch> TComPtr;
+ typedef CComPtr<IHTMLDocument3> TDocumentPtr;
+
+ protected:
+ typedef CComPtr<IHTMLElementCollection> TElementCollectionPtr;
+
+ public:
+ CHTMLNode(const TComPtr& pElement,const TDocumentPtr& pDocument)
+ : m_pElement(pElement),m_pDocument(pDocument){}
+
+ virtual THTMLNodePtr GetElementByID(const tstring& rsID)const
+ {
+ if(m_pDocument)
+ {
+ CComPtr<IHTMLElement> pElement;
+ if(SUCCEEDED(m_pDocument->getElementById(bstr_t(rsID.c_str()),&pElement))
+ && pElement)
+ {
+ TComPtr p(pElement);
+ return THTMLNodePtr(new CHTMLNode(p,m_pDocument));
+ }
+ }
+
+ return THTMLNodePtr();
+ }
+
+ virtual size_t GetChildCount()const
+ {
+ TElementCollectionPtr pColl = GetElementCollectionPtr();
+ if(pColl)
+ {
+ LONG celem = 0;
+ HRESULT hr = pColl->get_length(&celem);
+ if(S_OK == hr)
+ {
+ return celem;
+ }
+ }
+
+ return 0;
+ }
+
+ virtual THTMLNodePtr GetChildPtr(size_t nIndex)
+ {
+ TElementCollectionPtr pColl = GetElementCollectionPtr();
+ if(pColl)
+ {
+ VARIANT varIndex;
+ varIndex.vt = VT_UINT;
+ varIndex.lVal = (LONG)nIndex;
+ VARIANT var2;
+ VariantInit(&var2);
+ TComPtr pDisp;
+ HRESULT hr = pColl->item(varIndex,var2,&pDisp);
+ if(S_OK == hr && pDisp)
+ {
+ return THTMLNodePtr(new CHTMLNode(pDisp,m_pDocument));
+ }
+ }
+
+ return THTMLNodePtr();
+ }
+
+ virtual bool Is(EType nType)const
+ {
+ switch(nType)
+ {
+ case Table:
+ {
+ CComPtr<IHTMLTable> pTable;
+ return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTable,reinterpret_cast<void**>(&pTable))) && (pTable));
+ }
+ case TableRow:
+ {
+ CComPtr<IHTMLTableRow> pRow;
+ return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTableRow,reinterpret_cast<void**>(&pRow))) && (pRow));
+ }
+ case TableColumn:
+ {
+ CComPtr<IHTMLTableCol> pCol;
+ return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTableCol,reinterpret_cast<void**>(&pCol))) && (pCol));
+ }
+ }
+
+ return false;
+ }
+
+ virtual tstring GetAttribute(const tstring& rsAttrName)const
+ {
+ USES_CONVERSION;
+
+ tstring sAttr;
+ CComPtr<IHTMLElement> pElement;
+ if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast<void**>(&pElement))) && pElement)
+ {
+ _variant_t vAttribute;
+ BSTR pbstrAttrName = T2BSTR(rsAttrName.c_str());
+ if(SUCCEEDED(pElement->getAttribute(pbstrAttrName,1,&vAttribute))
+ && VT_NULL != vAttribute.vt && VT_EMPTY != vAttribute.vt)
+ {
+ try
+ {
+ _bstr_t b(vAttribute);
+ LPCTSTR psz = b;
+ if(psz)
+ {
+ sAttr = psz;
+ }
+ }
+ catch(_com_error&)
+ {
+ }
+ }
+ }
+
+ return sAttr;
+ }
+
+ virtual tstring GetText()const
+ {
+// USES_CONVERSION;
+
+ tstring sText;
+ CComPtr<IHTMLElement> pElement;
+ if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast<void**>(&pElement))) && pElement)
+ {
+ BSTR bstrText;
+ if(SUCCEEDED(pElement->get_innerText(&bstrText)) && bstrText)
+ {
+ try
+ {
+ sText = _bstr_t(bstrText);
+ }
+ catch(_com_error&)
+ {
+ }
+
+ ::SysFreeString(bstrText);
+ }
+ }
+
+ return sText;
+ }
+
+ protected:
+ virtual TElementCollectionPtr GetElementCollectionPtr()const
+ {
+ TElementCollectionPtr pColl;
+ HRESULT hr = m_pElement->QueryInterface(IID_IHTMLElementCollection,reinterpret_cast<void**>(&pColl));
+ if(FAILED(hr))
+ {
+ CComPtr<IHTMLElement> pElement;
+ if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast<void**>(&pElement))) && pElement)
+ {
+ CComPtr<IDispatch> pDisp;
+ if(SUCCEEDED(pElement->get_children(&pDisp)) && pDisp)
+ {
+ hr = pDisp->QueryInterface(IID_IHTMLElementCollection,reinterpret_cast<void**>(&pColl));
+ }
+ }
+ }
+
+ return pColl;
+ }
+
+ private:
+ TComPtr m_pElement;
+ TDocumentPtr m_pDocument;
+ };
+}
+
+CHTMLParserMS::CHTMLParserMS() : m_bCallUninit(false)
+{
+ try
+ {
+ CheckError(::CoInitialize(NULL));
+
+ m_bCallUninit = true;
+
+ _com_util::CheckError(
+ ::CoCreateInstance(CLSID_HTMLDocument,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IHTMLDocument2,
+ (LPVOID*)&m_pDoc)
+ );
+
+ CComPtr<IPersistStreamInit> pPersist;
+ _com_util::CheckError(m_pDoc->QueryInterface(IID_IPersistStreamInit,
+ (LPVOID*)&pPersist));
+
+ _com_util::CheckError(pPersist->InitNew());
+
+ _com_util::CheckError(m_pDoc->QueryInterface(IID_IMarkupServices,
+ (LPVOID*)&m_pMS));
+
+ if(m_pMS)
+ {
+ _com_util::CheckError(m_pMS->CreateMarkupPointer(&m_pMkStart));
+ _com_util::CheckError(m_pMS->CreateMarkupPointer(&m_pMkFinish));
+ }
+ }
+ catch(_com_error&/* e*/)
+ {
+// show_com_error_msg(e);
+ }
+
+}
+
+CHTMLParserMS::~CHTMLParserMS()
+{
+ if(true == m_bCallUninit)
+ {
+ ::CoUninitialize();
+ }
+}
+
+CHTMLParserMS::THTMLNodePtr CHTMLParserMS::ParseString(const tstring& rsHTML)
+{
+ USES_CONVERSION;
+
+ try
+ {
+ CGuard<CLightMutex> cs(m_cs);
+
+ OLECHAR* p = T2OLE(const_cast<LPTSTR>(rsHTML.c_str()));
+ CComPtr<IMarkupContainer> pMC;
+ _com_util::CheckError(m_pMS->ParseString(p,0,&pMC,m_pMkStart,m_pMkFinish));
+
+ if(pMC)
+ {
+ CComPtr<IHTMLDocument2> pNewDoc;
+
+ _com_util::CheckError(pMC->QueryInterface(IID_IHTMLDocument,
+ (LPVOID*)&pNewDoc));
+
+ if(pNewDoc)
+ {
+ CComPtr<IHTMLElementCollection> pColl;
+ _com_util::CheckError(pNewDoc->get_all(&pColl));
+
+ CHTMLNode::TDocumentPtr pDoc;
+ pMC->QueryInterface(IID_IHTMLDocument3,(LPVOID*)&pDoc);
+
+
+ return THTMLNodePtr(new CHTMLNode(CHTMLNode::TComPtr(pColl),pDoc));
+ }
+ }
+ }
+ catch(_com_error&/* e*/)
+ {
+// show_com_error_msg(e);
+ }
+
+ return THTMLNodePtr();
+}
+
+bool CHTMLParserMS::IsInstalled()
+{
+ bool bResult = true;
+ bool bCallUninit = false;
+ try
+ {
+ CheckError(::CoInitialize(NULL));
+
+ bCallUninit = true;
+
+ CComPtr<IHTMLDocument2> pDoc;
+ _com_util::CheckError(
+ ::CoCreateInstance(CLSID_HTMLDocument,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IHTMLDocument2,
+ reinterpret_cast<LPVOID*>(&pDoc))
+ );
+ }
+ catch(_com_error&/* e*/)
+ {
+ bResult = false;
+ }
+
+ if(bCallUninit)
+ {
+ ::CoUninitialize();
+ }
+
+ return bResult;
+}
+
+CHTMLEngineMS::CHTMLEngineMS()
+{
+
+}
+
+CHTMLEngineMS::~CHTMLEngineMS()
+{
+
+}
+
+CHTMLEngineMS::THTMLParserPtr CHTMLEngineMS::GetParserPtr()const
+{
+ return THTMLParserPtr(new CHTMLParserMS);
+}
diff --git a/protocols/Quotes/src/HTMLParserMS.h b/protocols/Quotes/src/HTMLParserMS.h
new file mode 100644
index 0000000000..0773efa42a
--- /dev/null
+++ b/protocols/Quotes/src/HTMLParserMS.h
@@ -0,0 +1,36 @@
+#ifndef __3c99e3f7_ecd9_4d9b_8f86_fe293c5fc8e6_HTMLParserMS_h__
+#define __3c99e3f7_ecd9_4d9b_8f86_fe293c5fc8e6_HTMLParserMS_h__
+
+#include "ihtmlparser.h"
+#include "LightMutex.h"
+#include "IHTMLEngine.h"
+
+class CHTMLParserMS : public IHTMLParser
+{
+public:
+ CHTMLParserMS();
+ ~CHTMLParserMS();
+
+ virtual THTMLNodePtr ParseString(const tstring& rsHTML);
+
+ static bool IsInstalled();
+
+private:
+ bool m_bCallUninit;
+ CComPtr<IHTMLDocument2> m_pDoc;
+ CComPtr<IMarkupServices> m_pMS;
+ CComPtr<IMarkupPointer> m_pMkStart;
+ CComPtr<IMarkupPointer> m_pMkFinish;
+ mutable CLightMutex m_cs;
+};
+
+class CHTMLEngineMS : public IHTMLEngine
+{
+public:
+ CHTMLEngineMS();
+ ~CHTMLEngineMS();
+
+ virtual THTMLParserPtr GetParserPtr()const;
+};
+
+#endif //__3c99e3f7_ecd9_4d9b_8f86_fe293c5fc8e6_HTMLParserMS_h__
diff --git a/protocols/Quotes/src/HTTPSession.cpp b/protocols/Quotes/src/HTTPSession.cpp
new file mode 100644
index 0000000000..aa66948ae9
--- /dev/null
+++ b/protocols/Quotes/src/HTTPSession.cpp
@@ -0,0 +1,262 @@
+#include "StdAfx.h"
+#include "HTTPSession.h"
+#include "EconomicRateInfo.h"
+#include "LightMutex.h"
+
+class CHTTPSession::CImpl
+{
+public:
+ CImpl() {}
+ virtual ~CImpl() {}
+
+ virtual bool OpenURL(const tstring& rsURL) = 0;
+ virtual bool ReadResponce(tstring& rsResponce)const = 0;
+};
+
+namespace
+{
+// class CImplMS : public CHTTPSession::CImpl
+// {
+// public:
+// CImplMS()
+// : m_hSession(::InternetOpen(_T("Dioksin"),PRE_CONFIG_INTERNET_ACCESS,NULL,INTERNET_INVALID_PORT_NUMBER,0)),
+// m_hRequest(NULL)
+// {
+//
+// }
+//
+// ~CImplMS()
+// {
+// if(m_hRequest)
+// {
+// ::InternetCloseHandle(m_hRequest);
+// }
+//
+// if(m_hSession)
+// {
+// ::InternetCloseHandle(m_hSession);
+// }
+// }
+//
+// virtual bool OpenURL(const tstring& rsURL)
+// {
+// if(NULL == m_hSession)
+// {
+// return false;
+// }
+//
+// if(NULL != m_hRequest)
+// {
+// ::InternetCloseHandle(m_hRequest);
+// m_hRequest = NULL;
+// }
+//
+// m_hRequest = ::InternetOpenUrl(m_hSession,rsURL.c_str(),NULL,0,INTERNET_FLAG_RELOAD,0);
+// return NULL != m_hRequest;
+// }
+//
+// virtual bool ReadResponce(tstring& rsResponce)const
+// {
+// if(NULL == m_hRequest)
+// {
+// return false;
+// }
+//
+// std::string sBuffer;
+// bool bResult = true;
+// DWORD cbRead = 0;
+// char szBuffer[1024];
+// do{
+// if(FALSE == ::InternetReadFile(m_hRequest,szBuffer,1024,&cbRead))
+// {
+// bResult = false;
+// break;
+// }
+// if (0 == cbRead)
+// {
+// break; // Stop.
+// }
+// else
+// {
+// sBuffer.insert(sBuffer.size(),szBuffer,cbRead);
+// }
+// }while(true);
+//
+// if(true == bResult)
+// {
+// USES_CONVERSION;
+// rsResponce = A2CT(sBuffer.c_str());
+// }
+//
+// return bResult;
+// }
+// private:
+// HINTERNET m_hSession;
+// HINTERNET m_hRequest;
+// };
+//
+ int find_header(const NETLIBHTTPREQUEST* pRequest,const char* hdr)
+ {
+ for(int i = 0;i < pRequest->headersCount; ++i)
+ {
+ if (0 == _stricmp(pRequest->headers[i].szName,hdr))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+
+ class CImplMI : public CHTTPSession::CImpl
+ {
+ public:
+ CImplMI() {}
+
+ static bool Init()
+ {
+ assert(NULL == g_hNetLib);
+
+ NETLIBUSER nlu = {0};
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION|NUF_TCHAR;
+ nlu.szSettingsModule = QUOTES_PROTOCOL_NAME;
+ nlu.ptszDescriptiveName = TranslateT("Quotes HTTP connections");
+ g_hNetLib = reinterpret_cast<HANDLE>(CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu));
+ return (NULL != g_hNetLib);
+ }
+
+ static bool IsValid(){return NULL != g_hNetLib;}
+
+ virtual bool OpenURL(const tstring& rsURL)
+ {
+// USES_CONVERSION;
+
+ m_aURL.swap(TBuffer());
+
+ std::string s = quotes_t2a(rsURL.c_str());
+ const char* psz = s.c_str();//T2CA(rsURL.c_str());
+ m_aURL.insert(m_aURL.begin(),psz,psz+strlen(psz)+1);
+ return true;
+
+ }
+ virtual bool ReadResponce(tstring& rsResponce)const
+ {
+ if(true == m_aURL.empty())
+ {
+ return false;
+ }
+
+
+ NETLIBHTTPREQUEST nlhr = {0};
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_DUMPASTEXT|NLHRF_HTTP11|NLHRF_REDIRECT;
+ char* pURL = &*(m_aURL.begin());
+ nlhr.szUrl = pURL;
+
+ nlhr.headersCount = 4;
+ nlhr.headers=(NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount);
+ nlhr.headers[0].szName = "User-Agent";
+ nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
+ nlhr.headers[1].szName = "Connection";
+ nlhr.headers[1].szValue = "close";
+ nlhr.headers[2].szName = "Cache-Control";
+ nlhr.headers[2].szValue = "no-cache";
+ nlhr.headers[3].szName = "Pragma";
+ nlhr.headers[3].szValue = "no-cache";
+ // nlhr.headers[4].szName = "Accept-Encoding";
+ // nlhr.headers[4].szValue = "deflate, gzip";
+ // nlhr.headers[5].szName = "Cookie";
+ // nlhr.headers[5].szValue = cookie;
+
+ bool bResult = false;
+ NETLIBHTTPREQUEST* pReply = NULL;
+
+ {
+ CGuard<CLightMutex> guard(m_mx);
+ pReply = reinterpret_cast<NETLIBHTTPREQUEST*>(CallService(MS_NETLIB_HTTPTRANSACTION,
+ reinterpret_cast<WPARAM>(g_hNetLib),reinterpret_cast<LPARAM>(&nlhr)));
+ }
+
+ if(pReply)
+ {
+ if ((200 == pReply->resultCode) && (pReply->dataLength > 0))
+ {
+ TBuffer apBuffer;
+ apBuffer.insert(apBuffer.begin(),pReply->pData,pReply->pData+pReply->dataLength);
+ apBuffer.push_back('\0');
+
+ char* pResult = &*(apBuffer.begin());
+ int nIndex = find_header(pReply,"Content-Type");
+ if ((-1 != nIndex) && (NULL != strstr(_strlwr(pReply->headers[nIndex].szValue),"utf-8")))
+ {
+ TCHAR* p = mir_utf8decodeT(pResult);
+ rsResponce = p;
+ mir_free(p);
+ }
+ else
+ {
+// USES_CONVERSION;
+// LPCTSTR p = A2CT(pResult);
+ rsResponce = quotes_a2t(pResult);//p;
+ }
+
+ bResult = true;
+ }
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,reinterpret_cast<LPARAM>(pReply));
+ }
+
+ mir_free(nlhr.headers);
+
+ return bResult;
+ }
+
+ private:
+ static HANDLE g_hNetLib;
+ typedef std::vector<char> TBuffer;
+ mutable TBuffer m_aURL;
+ mutable CLightMutex m_mx;
+ };
+
+ HANDLE CImplMI::g_hNetLib = NULL;
+
+// CHTTPSession::CImpl* create_impl()
+// {
+// if(true == CImplMI::IsValid())
+// {
+// return new CImplMI;
+// }
+// else
+// {
+// return new CImplMS;
+// }
+// }
+}
+
+
+CHTTPSession::CHTTPSession()
+ : m_pImpl(new CImplMI)
+{
+}
+
+CHTTPSession::~CHTTPSession()
+{
+}
+
+bool CHTTPSession::OpenURL(const tstring& rsURL)
+{
+ return m_pImpl->OpenURL(rsURL);
+}
+
+bool CHTTPSession::ReadResponce(tstring& rsResponce)const
+{
+ return m_pImpl->ReadResponce(rsResponce);
+}
+
+bool CHTTPSession::Init()
+{
+ return CImplMI::Init();
+} \ No newline at end of file
diff --git a/protocols/Quotes/src/HTTPSession.h b/protocols/Quotes/src/HTTPSession.h
new file mode 100644
index 0000000000..fe93a2dce5
--- /dev/null
+++ b/protocols/Quotes/src/HTTPSession.h
@@ -0,0 +1,27 @@
+#ifndef __8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__
+#define __8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__
+
+#include <string>
+
+class CHTTPSession
+{
+public:
+ CHTTPSession();
+ ~CHTTPSession();
+
+ static bool Init();
+
+ bool OpenURL(const tstring& rsURL);
+ bool ReadResponce(tstring& rsResponce)const;
+
+
+public:
+ class CImpl;
+private:
+ typedef boost::scoped_ptr<CImpl> TImpl;
+
+private:
+ TImpl m_pImpl;
+};
+
+#endif //__8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__
diff --git a/protocols/Quotes/src/IHTMLEngine.h b/protocols/Quotes/src/IHTMLEngine.h
new file mode 100644
index 0000000000..7df3074d3e
--- /dev/null
+++ b/protocols/Quotes/src/IHTMLEngine.h
@@ -0,0 +1,18 @@
+#ifndef __85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__
+#define __85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__
+
+class IHTMLParser;
+
+class IHTMLEngine
+{
+public:
+ typedef boost::shared_ptr<IHTMLParser> THTMLParserPtr;
+
+public:
+ IHTMLEngine(void){}
+ virtual ~IHTMLEngine() {}
+
+ virtual THTMLParserPtr GetParserPtr()const = 0;
+};
+
+#endif //__85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__
diff --git a/protocols/Quotes/src/IHTMLParser.h b/protocols/Quotes/src/IHTMLParser.h
new file mode 100644
index 0000000000..defc6f61cb
--- /dev/null
+++ b/protocols/Quotes/src/IHTMLParser.h
@@ -0,0 +1,41 @@
+#ifndef __98ad6d6d_2a27_43fd_bf3e_c18416a45e54_IHTMLParser_h__
+#define __98ad6d6d_2a27_43fd_bf3e_c18416a45e54_IHTMLParser_h__
+
+class IHTMLNode
+{
+public:
+ typedef boost::shared_ptr<IHTMLNode> THTMLNodePtr;
+
+ enum EType
+ {
+ Table = 1,
+ TableRow,
+ TableColumn
+ };
+
+public:
+ IHTMLNode() {}
+ virtual ~IHTMLNode() {}
+
+ virtual size_t GetChildCount()const = 0;
+ virtual THTMLNodePtr GetChildPtr(size_t nIndex) = 0;
+ virtual bool Is(EType nType)const = 0;
+
+ virtual THTMLNodePtr GetElementByID(const tstring& rsID)const = 0;
+
+ virtual tstring GetAttribute(const tstring& rsAttrName)const = 0;
+ virtual tstring GetText()const = 0;
+};
+
+class IHTMLParser
+{
+public:
+ typedef IHTMLNode::THTMLNodePtr THTMLNodePtr;
+public:
+ IHTMLParser() {}
+ virtual ~IHTMLParser() {}
+
+ virtual THTMLNodePtr ParseString(const tstring& rsHTML) = 0;
+};
+
+#endif //__98ad6d6d_2a27_43fd_bf3e_c18416a45e54_IHTMLParser_h__
diff --git a/protocols/Quotes/src/IQuotesProvider.h b/protocols/Quotes/src/IQuotesProvider.h
new file mode 100644
index 0000000000..a03a2a9bcd
--- /dev/null
+++ b/protocols/Quotes/src/IQuotesProvider.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#ifndef __ac71e133_786c_41a7_ab07_625b76ff2a8c_QuotesProvider_h__
+#define __ac71e133_786c_41a7_ab07_625b76ff2a8c_QuotesProvider_h__
+
+#include <boost\noncopyable.hpp>
+#include <string>
+
+class CQuotesProviderVisitor;
+
+class IQuotesProvider : private boost::noncopyable
+{
+public:
+ struct CProviderInfo
+ {
+ tstring m_sName;
+ tstring m_sURL;
+
+ };
+
+public:
+ IQuotesProvider() {}
+ virtual ~IQuotesProvider() {}
+
+ virtual bool Init() = 0;
+ virtual const CProviderInfo& GetInfo()const = 0;
+
+ virtual void AddContact(HANDLE hContact) = 0;
+ virtual void DeleteContact(HANDLE hContact) = 0;
+
+ virtual void ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp) = 0;
+ virtual void RefreshAll() = 0;
+ virtual void RefreshContact(HANDLE hContact) = 0;
+ virtual void SetContactExtraIcon(HANDLE hContact)const = 0;
+
+ virtual void Run() = 0;
+
+ virtual void Accept(CQuotesProviderVisitor& visitor)const = 0;
+};
+
+#endif //__ac71e133_786c_41a7_ab07_625b76ff2a8c_QuotesProvider_h__
diff --git a/protocols/Quotes/src/IXMLEngine.h b/protocols/Quotes/src/IXMLEngine.h
new file mode 100644
index 0000000000..910c3efea0
--- /dev/null
+++ b/protocols/Quotes/src/IXMLEngine.h
@@ -0,0 +1,43 @@
+#ifndef __f88e20d7_5e65_40fb_a7b5_7c7af1ee1c78_IXMLEngine_h__
+#define __f88e20d7_5e65_40fb_a7b5_7c7af1ee1c78_IXMLEngine_h__
+
+class IXMLNode
+{
+public:
+ typedef boost::shared_ptr<IXMLNode> TXMLNodePtr;
+
+public:
+ IXMLNode() {}
+ virtual ~IXMLNode() {}
+
+ virtual size_t GetChildCount()const = 0;
+ virtual TXMLNodePtr GetChildNode(size_t nIndex)const = 0;
+
+ virtual tstring GetText()const = 0;
+ virtual tstring GetName()const = 0;
+
+ virtual bool AddChild(const TXMLNodePtr& pNode) = 0;
+ virtual bool AddAttribute(const tstring& rsName,const tstring& rsValue) = 0;
+ virtual tstring GetAttributeValue(const tstring& rsAttrName) = 0;
+ virtual void Write(tostream& o)const = 0;
+};
+
+inline tostream& operator<<(tostream& o,const IXMLNode& node)
+{
+ node.Write(o);
+ return o;
+}
+
+class IXMLEngine
+{
+public:
+ IXMLEngine() {}
+
+ virtual ~IXMLEngine() {}
+
+ virtual IXMLNode::TXMLNodePtr LoadFile(const tstring& rsFileName)const = 0;
+ virtual bool SaveFile(const tstring& rsFileName,const IXMLNode::TXMLNodePtr& pNode)const = 0;
+ virtual IXMLNode::TXMLNodePtr CreateNode(const tstring& rsName,const tstring& rsText)const = 0;
+};
+
+#endif //__f88e20d7_5e65_40fb_a7b5_7c7af1ee1c78_IXMLEngine_h__
diff --git a/protocols/Quotes/src/IconLib.cpp b/protocols/Quotes/src/IconLib.cpp
new file mode 100644
index 0000000000..b131aa7009
--- /dev/null
+++ b/protocols/Quotes/src/IconLib.cpp
@@ -0,0 +1,106 @@
+#include "StdAfx.h"
+#include "IconLib.h"
+#include <m_icolib.h>
+#include "resource.h"
+#include "EconomicRateInfo.h"
+// #include <newpluginapi.h>
+#include <m_langpack.h>
+#include <sstream>
+#pragma warning (disable:4996)
+#include <m_utils.h>
+#pragma warning (default:4996)
+#include "ModuleInfo.h"
+
+// extern HMODULE g_hInstance;
+
+namespace
+{
+ struct CIconList
+ {
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+// TCHAR* szSection;
+ HANDLE hIconLibItem;
+ };
+
+ CIconList iconList[] =
+ {
+ {_T("Protocol icon"),ICON_STR_MAIN,IDI_ICON_MAIN},
+ {_T("Quote/Rate up"),ICON_STR_QUOTE_UP,IDI_ICON_UP},
+ {_T("Quote/Rate down"),ICON_STR_QUOTE_DOWN,IDI_ICON_DOWN},
+ {_T("Quote/Rate not changed"),ICON_STR_QUOTE_NOT_CHANGED,IDI_ICON_NOTCHANGED},
+ {_T("Quote Section"),ICON_STR_SECTION,IDI_ICON_SECTION},
+ {_T("Quote"),ICON_STR_QUOTE,IDI_ICON_QUOTE},
+ {_T("Currency Converter"),ICON_STR_CURRENCY_CONVERTER,IDI_ICON_CURRENCY_CONVERTER},
+ {_T("Refresh"),ICON_STR_REFRESH,IDI_ICON_REFRESH},
+ {_T("Export"),ICON_STR_EXPORT,IDI_ICON_EXPORT},
+ {_T("Swap button"),ICON_STR_SWAP,IDI_ICON_SWAP},
+ {_T("Import"),ICON_STR_IMPORT,IDI_ICON_IMPORT},
+ };
+}
+
+void Quotes_IconsInit()
+{
+ USES_CONVERSION;
+
+ SKINICONDESC sid = {0};
+ TCHAR szFile[MAX_PATH];
+ ::GetModuleFileName(g_hInstance, szFile, MAX_PATH);
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszDefaultFile = szFile;
+ sid.cx = sid.cy = 16;
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszSection = A2T(QUOTES_PROTOCOL_NAME);
+
+// TCHAR* szRootSection = TranslateTS(A2T(QUOTES_PROTOCOL_NAME));
+
+ for ( int i = 0; i < SIZEOF(iconList); i++ )
+ {
+// char szSettingName[100];
+// TCHAR szSectionName[100];
+// mir_snprintf( szSettingName, sizeof( szSettingName ),"%s_%s",QUOTES_PROTOCOL_NAME, iconList[i].szName );
+// {
+// mir_sntprintf( szSectionName, SIZEOF( szSectionName ),_T("%s/%s"), TranslateT("Protocols"), szRootSection);
+// sid.ptszSection = szSectionName;
+// }
+
+ std::string sName = Quotes_MakeIconName( iconList[i].szName);
+ sid.pszName = const_cast<char*>(sName.c_str());
+ sid.ptszDescription = iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIconLibItem = Skin_AddIcon(&sid);
+ }
+}
+
+std::string Quotes_MakeIconName(const char* name)
+{
+ assert(name);
+ //char szSettingName[100];
+ //mir_snprintf(szSettingName,SIZEOF(szSettingName),"%s_%s",QUOTES_PROTOCOL_NAME,name);
+ std::string sName(QUOTES_PROTOCOL_NAME);
+ sName += "_";
+ sName += name;
+ return sName;
+}
+
+HICON Quotes_LoadIconEx(const char* name,bool bBig /*= false*/)
+{
+ std::string sIconName = Quotes_MakeIconName(name);
+ return reinterpret_cast<HICON>(CallService( MS_SKIN2_GETICON,((bBig) ? 1 : 0),reinterpret_cast<LPARAM>(sIconName.c_str())));
+}
+
+HANDLE Quotes_GetIconHandle(int iconId)
+{
+ for(int i=0;i < SIZEOF(iconList);i++)
+ {
+ if(iconList[i].defIconID == iconId)
+ {
+ return iconList[i].hIconLibItem;
+ }
+ }
+
+ return NULL;
+}
+
diff --git a/protocols/Quotes/src/IconLib.h b/protocols/Quotes/src/IconLib.h
new file mode 100644
index 0000000000..29b0326622
--- /dev/null
+++ b/protocols/Quotes/src/IconLib.h
@@ -0,0 +1,21 @@
+#ifndef __8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__
+#define __8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__
+
+#define ICON_STR_MAIN "main"
+#define ICON_STR_QUOTE_UP "quote_up"
+#define ICON_STR_QUOTE_DOWN "quote_down"
+#define ICON_STR_QUOTE_NOT_CHANGED "quote_not_changed"
+#define ICON_STR_SECTION "quote_section"
+#define ICON_STR_QUOTE "quote"
+#define ICON_STR_CURRENCY_CONVERTER "currency_converter"
+#define ICON_STR_REFRESH "refresh"
+#define ICON_STR_IMPORT "import"
+#define ICON_STR_EXPORT "export"
+#define ICON_STR_SWAP "swap"
+
+void Quotes_IconsInit();
+HICON Quotes_LoadIconEx(const char* name,bool bBig = false);
+HANDLE Quotes_GetIconHandle(int iconId);
+std::string Quotes_MakeIconName(const char* name);
+
+#endif //__8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__
diff --git a/protocols/Quotes/src/ImportExport.cpp b/protocols/Quotes/src/ImportExport.cpp
new file mode 100644
index 0000000000..80ab41d309
--- /dev/null
+++ b/protocols/Quotes/src/ImportExport.cpp
@@ -0,0 +1,850 @@
+#include "StdAfx.h"
+#include "ImportExport.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#ifdef TEST_IMPORT_EXPORT
+#include "m_Quotes.h"
+#endif
+#include "IXMLEngine.h"
+#include "Base64.h"
+#include "EconomicRateInfo.h"
+#include "IQuotesProvider.h"
+#include "QuotesProviderVisitor.h"
+#include "QuotesProviderDukasCopy.h"
+#include "QuotesProviderGoogle.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "Locale.h"
+
+namespace
+{
+ LPCTSTR g_pszXmlValue = _T("Value");
+ LPCTSTR g_pszXmlName = _T("Name");
+ LPCTSTR g_pszXmlSetting = _T("Setting");
+ LPCTSTR g_pszXmlModule = _T("Module");
+ LPCTSTR g_pszXmlContact = _T("Contact");
+ LPCTSTR g_pszXmlContacts = _T("Contacts");
+ LPCTSTR g_pszXmlType = _T("type");
+ LPCTSTR g_pszXmlTypeByte = _T("byte");
+ LPCTSTR g_pszXmlTypeWord = _T("word");
+ LPCTSTR g_pszXmlTypeDword = _T("dword");
+ LPCTSTR g_pszXmlTypeAsciiz = _T("asciiz");
+ LPCTSTR g_pszXmlTypeWchar = _T("wchar");
+ LPCTSTR g_pszXmlTypeUtf8 = _T("utf8");
+ LPCTSTR g_pszXmlTypeBlob = _T("blob");
+
+ struct CEnumContext
+ {
+ CModuleInfo::TXMLEnginePtr m_pXmlEngine;
+ IXMLNode::TXMLNodePtr m_pNode;
+ HANDLE m_hContact;
+ LPCSTR m_pszModule;
+ };
+
+ struct mir_safety_dbvar
+ {
+ mir_safety_dbvar(DBVARIANT* p) : m_p(p){}
+ ~mir_safety_dbvar(){DBFreeVariant(m_p);}
+ DBVARIANT* m_p;
+ };
+
+ static int enum_contact_settings(const char* szSetting,LPARAM lp)
+ {
+// USES_CONVERSION;
+ CEnumContext* ctx = reinterpret_cast<CEnumContext*>(lp);
+
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+
+ cgs.szModule = ctx->m_pszModule;
+ cgs.szSetting = szSetting;
+ cgs.pValue = &dbv;
+ if(0 == CallService(MS_DB_CONTACT_GETSETTING,
+ reinterpret_cast<WPARAM>(ctx->m_hContact),
+ reinterpret_cast<LPARAM>(&cgs)))
+ {
+ mir_safety_dbvar sdbvar(&dbv);
+
+ tstring sType;
+ tostringstream sValue;
+ sValue.imbue(GetSystemLocale());
+
+ switch(dbv.type)
+ {
+ case DBVT_BYTE:
+ sValue << dbv.bVal;
+ sType = g_pszXmlTypeByte;
+ break;
+ case DBVT_WORD:
+ sValue << dbv.wVal;
+ sType = g_pszXmlTypeWord;
+ break;
+ case DBVT_DWORD:
+ sValue << dbv.dVal;
+ sType = g_pszXmlTypeDword;
+ break;
+ case DBVT_ASCIIZ:
+ sType = g_pszXmlTypeAsciiz;
+ if(dbv.pszVal)
+ {
+ sValue << dbv.pszVal;
+// mir_safe_string<char> mss(mir_utf8encode(dbv.pszVal));
+// if(mss.m_p)
+// {
+// sValue << mss.m_p;
+// }
+ }
+ break;
+ case DBVT_WCHAR:
+ sType = g_pszXmlTypeWchar;
+ if(dbv.pwszVal)
+ {
+ sValue << dbv.pwszVal;
+// mir_safe_string<char> mss(mir_utf8encodeW(dbv.pwszVal));
+// if(mss.m_p)
+// {
+// sValue << mss.m_p;
+// }
+ }
+ break;
+ case DBVT_UTF8:
+ sType = g_pszXmlTypeUtf8;
+ if(dbv.pszVal)
+ {
+ sValue << dbv.pszVal;
+ }
+ break;
+ case DBVT_BLOB:
+ sType = g_pszXmlTypeBlob;
+ if(dbv.pbVal)
+ {
+ std::vector<char> buf;
+ if(true == base64::encode(dbv.pbVal,dbv.cpbVal,buf))
+ {
+ buf.push_back('\0');
+ sValue << &*buf.begin();
+ }
+ }
+ break;
+ }
+
+// mir_safe_string<char> mssSetting(mir_utf8encode(szSetting));
+// if(mssSetting.m_p)
+ {
+ IXMLNode::TXMLNodePtr pXmlSet = ctx->m_pXmlEngine->CreateNode(g_pszXmlSetting,tstring());
+ if(pXmlSet)
+ {
+ IXMLNode::TXMLNodePtr pXmlName = ctx->m_pXmlEngine->CreateNode(g_pszXmlName,quotes_a2t(szSetting));
+
+ IXMLNode::TXMLNodePtr pXmlValue = ctx->m_pXmlEngine->CreateNode(g_pszXmlValue,sValue.str());
+ if(pXmlName && pXmlValue)
+ {
+ pXmlValue->AddAttribute(g_pszXmlType,sType);
+
+ pXmlSet->AddChild(pXmlName);
+ pXmlSet->AddChild(pXmlValue);
+ ctx->m_pNode->AddChild(pXmlSet);
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ int EnumDbModules(const char* szModuleName, DWORD ofsModuleName, LPARAM lp)
+ {
+// USES_CONVERSION;
+ CEnumContext* ctx = reinterpret_cast<CEnumContext*>(lp);
+ IXMLNode::TXMLNodePtr pXml = ctx->m_pNode;
+ IXMLNode::TXMLNodePtr pModule = ctx->m_pXmlEngine->CreateNode(g_pszXmlModule,quotes_a2t(szModuleName)/*A2CT(szModuleName)*/);
+ if(pModule)
+ {
+ ctx->m_pszModule = szModuleName;
+ ctx->m_pNode = pModule;
+
+ DBCONTACTENUMSETTINGS dbces;
+ dbces.pfnEnumProc = &enum_contact_settings;
+ dbces.szModule = szModuleName;
+ dbces.lParam = reinterpret_cast<LPARAM>(ctx);
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,reinterpret_cast<WPARAM>(ctx->m_hContact),reinterpret_cast<LPARAM>(&dbces));
+ if(pModule->GetChildCount() > 0)
+ {
+ pXml->AddChild(pModule);
+ }
+ ctx->m_pNode = pXml;
+ }
+
+ return 0;
+ }
+
+ IXMLNode::TXMLNodePtr export_contact(HANDLE hContact,const CModuleInfo::TXMLEnginePtr& pXmlEngine)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlEngine->CreateNode(g_pszXmlContact,tstring());
+ if(pNode)
+ {
+ CEnumContext ctx;
+ ctx.m_pXmlEngine = pXmlEngine;
+ ctx.m_pNode = pNode;
+ ctx.m_hContact = hContact;
+
+ CallService(MS_DB_MODULES_ENUM,reinterpret_cast<WPARAM>(&ctx),reinterpret_cast<LPARAM>(EnumDbModules));
+ }
+ return pNode;
+ }
+
+ LPCTSTR prepare_filter(LPTSTR pszBuffer,size_t cBuffer)
+ {
+ LPTSTR p = pszBuffer;
+ LPCTSTR pszXml = TranslateT("Xml File (*.xml)");
+ lstrcpyn(p,pszXml, (int)cBuffer);
+ size_t nLen = (int)lstrlen(pszXml)+1;
+ p+= nLen;
+ if(nLen < cBuffer)
+ {
+ lstrcpyn(p,_T("*.xml"),(int)(cBuffer-nLen));
+ p+= 6;
+ nLen += 6;
+ }
+
+ if(nLen < cBuffer)
+ {
+ LPCTSTR pszAll = TranslateT("All files (*.*)");
+ lstrcpyn(p,pszAll,(int)(cBuffer-nLen));
+ size_t n = lstrlen(pszAll)+1;
+ nLen += n;
+ p+= n;
+ }
+
+ if(nLen < cBuffer)
+ {
+ lstrcpyn(p,_T("*.*"),(int)(cBuffer-nLen));
+ p+= 4;
+ nLen += 4;
+ }
+
+ if(nLen < cBuffer)
+ {
+ *p = _T('\0');
+ }
+
+ return pszBuffer;
+ }
+
+ bool show_open_file_dialog(bool bOpen,tstring& rsFile)
+ {
+ TCHAR szBuffer[MAX_PATH];
+ TCHAR szFilter[MAX_PATH];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+
+ ofn.hwndOwner = NULL;
+ ofn.lpstrFilter = prepare_filter(szFilter,MAX_PATH);
+ ofn.Flags = OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_EXPLORER;
+ ofn.lpstrDefExt = _T("xml");
+ if(true == bOpen)
+ {
+ ofn.Flags |= OFN_FILEMUSTEXIST;
+ }
+ else
+ {
+ ofn.Flags |= OFN_OVERWRITEPROMPT;
+ }
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFile = szBuffer;
+ ofn.lpstrFile[0] = _T('\0');
+
+ if(bOpen)
+ {
+ if(FALSE == GetOpenFileName(&ofn))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if(FALSE == GetSaveFileName(&ofn))
+ {
+ return false;
+ }
+ }
+
+ rsFile = szBuffer;
+
+ return true;
+ }
+}
+
+INT_PTR Quotes_Export(WPARAM wp,LPARAM lp)
+{
+// USES_CONVERSION;
+
+ tstring sFileName;
+ const char* pszFile = reinterpret_cast<const char*>(lp);
+ if(NULL == pszFile)
+ {
+ if(false == show_open_file_dialog(false,sFileName))
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ sFileName = quotes_a2t(pszFile);//A2CT(pszFile);
+ }
+
+ CModuleInfo::TXMLEnginePtr pXmlEngine = CModuleInfo::GetInstance().GetXMLEnginePtr();
+ CModuleInfo::TQuotesProvidersPtr pProviders = CModuleInfo::GetInstance().GetQuoteProvidersPtr();
+ IXMLNode::TXMLNodePtr pRoot = pXmlEngine->CreateNode(g_pszXmlContacts,tstring());
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(hContact)
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ IXMLNode::TXMLNodePtr pNode = export_contact(hContact,pXmlEngine);
+ if(pNode)
+ {
+ pRoot->AddChild(pNode);
+ }
+ }
+ }
+ else
+ {
+ for(hContact = db_find_first(); hContact; hContact = db_find_next(hContact))
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ IXMLNode::TXMLNodePtr pNode = export_contact(hContact,pXmlEngine);
+ if(pNode)
+ {
+ pRoot->AddChild(pNode);
+ }
+ }
+ }
+ }
+
+ return ((true == pXmlEngine->SaveFile(sFileName,pRoot)) ? 0 : 1);
+}
+
+namespace
+{
+ bool set_contact_settings(HANDLE hContact,DBCONTACTWRITESETTING& dbs)
+ {
+ assert(DBVT_DELETED != dbs.value.type);
+ return (0 == CallService(MS_DB_CONTACT_WRITESETTING,reinterpret_cast<WPARAM>(hContact),
+ reinterpret_cast<LPARAM>(&dbs)));
+ }
+
+ bool handle_module(HANDLE hContact,const IXMLNode::TXMLNodePtr& pXmlModule,UINT nFlags)
+ {
+// USES_CONVERSION;
+
+ size_t cCreatedRecords = 0;
+ tstring sModuleName = pXmlModule->GetText();
+ if(false == sModuleName.empty())
+ {
+ DBCONTACTWRITESETTING dbs;
+ std::string s = quotes_t2a(sModuleName.c_str());
+ dbs.szModule = s.c_str();//T2CA(sModuleName.c_str());
+
+ bool bCListModule = 0 == quotes_stricmp(sModuleName.c_str(),_T("CList"));
+
+ size_t cChild = pXmlModule->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pSetting = pXmlModule->GetChildNode(i);
+ tstring sSetting = pSetting->GetName();
+ if(0 == quotes_stricmp(g_pszXmlSetting,sSetting.c_str()))
+ {
+ size_t cSetChild = pSetting->GetChildCount();
+ if(cSetChild >= 2)
+ {
+ tstring sName;
+ tstring sValue;
+ tstring sType;
+ for(size_t i = 0;i < cSetChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pSetting->GetChildNode(i);
+ tstring sNode = pNode->GetName();
+ if(0 == quotes_stricmp(g_pszXmlName,sNode.c_str()))
+ {
+ sName = pNode->GetText();
+ }
+ else if(0 == quotes_stricmp(g_pszXmlValue,sNode.c_str()))
+ {
+ sValue = pNode->GetText();
+ sType = pNode->GetAttributeValue(g_pszXmlType);
+ }
+ }
+
+ if ((false == sName.empty()) && (false == sType.empty()))
+ {
+ std::string s = quotes_t2a(sName.c_str());
+ dbs.szSetting = s.c_str();//T2CA(sName.c_str());
+ if(0 == quotes_stricmp(g_pszXmlTypeByte,sType.c_str()))
+ {
+ tistringstream in(sValue.c_str());
+ in.imbue(GetSystemLocale());
+ dbs.value.cVal = in.get();
+ if(in.good() && in.eof())
+ {
+ dbs.value.type = DBVT_BYTE;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ }
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeWord,sType.c_str()))
+ {
+ tistringstream in(sValue.c_str());
+ in.imbue(GetSystemLocale());
+ in >> dbs.value.wVal;
+ if(in.good() || in.eof())
+ {
+ dbs.value.type = DBVT_WORD;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ }
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeDword,sType.c_str()))
+ {
+ tistringstream in(sValue.c_str());
+ in.imbue(GetSystemLocale());
+ in >> dbs.value.dVal;
+ if(in.good() || in.eof())
+ {
+ dbs.value.type = DBVT_DWORD;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ }
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeAsciiz,sType.c_str()))
+ {
+ CT2A v(sValue.c_str());
+ dbs.value.pszVal = v;
+ dbs.value.type = DBVT_ASCIIZ;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeUtf8,sType.c_str()))
+ {
+ dbs.value.pszVal = mir_utf8encodeT(sValue.c_str());
+ dbs.value.type = DBVT_UTF8;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ mir_free(dbs.value.pszVal);
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeWchar,sType.c_str()))
+ {
+ CT2W val(sValue.c_str());
+ dbs.value.pwszVal = val;
+ dbs.value.type = DBVT_WCHAR;
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ mir_free(dbs.value.pwszVal);
+ }
+ else if(0 == quotes_stricmp(g_pszXmlTypeBlob,sType.c_str()))
+ {
+ std::vector<BYTE> blob_buf;
+ std::string p = quotes_t2a(sValue.c_str());//T2A(sValue.c_str());
+ if(true == base64::decode(p.c_str(),lstrlenA(p.c_str()),blob_buf))
+ {
+ dbs.value.pbVal = &*blob_buf.begin();
+ dbs.value.cpbVal = (WORD)blob_buf.size();
+ dbs.value.type = DBVT_BLOB;
+
+ if(set_contact_settings(hContact,dbs))
+ {
+ ++cCreatedRecords;
+ }
+ }
+ }
+
+ if ((true == bCListModule) && (0 == quotes_stricmp(sName.c_str(),_T("Group"))))
+ {
+ CallService(MS_CLIST_GROUPCREATE,NULL,reinterpret_cast<LPARAM>(sValue.c_str()));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ size_t count_contacts(const IXMLNode::TXMLNodePtr& pXmlRoot,bool bInContactsGroup)
+ {
+ size_t cContacts = 0;
+ size_t cChild = pXmlRoot->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlRoot->GetChildNode(i);
+ tstring sName = pNode->GetName();
+ if(false == bInContactsGroup)
+ {
+ if(0 == quotes_stricmp(g_pszXmlContacts,sName.c_str()))
+ {
+ cContacts += count_contacts(pNode,true);
+ }
+ else
+ {
+ cContacts += count_contacts(pNode,false);
+ }
+ }
+ else
+ {
+ if(0 == quotes_stricmp(g_pszXmlContact,sName.c_str()))
+ {
+ ++ cContacts;
+ }
+ }
+ }
+
+ return cContacts;
+ }
+
+ struct CImportContext
+ {
+ CImportContext(size_t cTotalContacts) : m_cTotalContacts(cTotalContacts),m_cHandledContacts(0),m_nFlags(0){}
+
+ size_t m_cTotalContacts;
+ size_t m_cHandledContacts;
+ UINT m_nFlags;
+ };
+
+ struct CContactState
+ {
+ CContactState() : m_hContact(NULL),m_bNewContact(false){}
+ HANDLE m_hContact;
+ CQuotesProviders::TQuotesProviderPtr m_pProvider;
+ bool m_bNewContact;
+ };
+
+ IXMLNode::TXMLNodePtr find_quotes_module(const IXMLNode::TXMLNodePtr& pXmlContact)
+ {
+// USES_CONVERSION;
+// LPCTSTR pszQuotes = A2T(QUOTES_MODULE_NAME);
+ static const tstring g_sQuotes = quotes_a2t(QUOTES_MODULE_NAME);
+ size_t cChild = pXmlContact->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlContact->GetChildNode(i);
+ tstring sName = pNode->GetName();
+ if ((0 == quotes_stricmp(g_pszXmlModule,sName.c_str()))
+ && (0 == quotes_stricmp(g_sQuotes.c_str(),pNode->GetText().c_str())))
+ {
+ return pNode;
+ }
+ }
+
+ return IXMLNode::TXMLNodePtr();
+ }
+
+ typedef std::pair<tstring,tstring> TNameValue;//first is name,second is value
+ TNameValue parse_setting_node(const IXMLNode::TXMLNodePtr& pXmlSetting)
+ {
+ assert(pXmlSetting);
+
+ tstring sName,sValue;
+ size_t cSettingChildItems = pXmlSetting->GetChildCount();
+ for(size_t j = 0;j < cSettingChildItems;++j)
+ {
+ IXMLNode::TXMLNodePtr pXMLSetChild = pXmlSetting->GetChildNode(j);
+ if(pXMLSetChild)
+ {
+ if(0 == quotes_stricmp(g_pszXmlName,pXMLSetChild->GetName().c_str()))
+ {
+ sName = pXMLSetChild->GetText();
+ }
+ else if(0 == quotes_stricmp(g_pszXmlValue,pXMLSetChild->GetName().c_str()))
+ {
+ sValue = pXMLSetChild->GetText();
+ }
+ }
+ }
+
+ return std::make_pair(sName,sValue);
+ }
+
+ CQuotesProviders::TQuotesProviderPtr find_provider(const IXMLNode::TXMLNodePtr& pXmlQuotesModule)
+ {
+// USES_CONVERSION;
+ static const tstring g_sQuotesProvider = quotes_a2t(DB_STR_QUOTE_PROVIDER);//A2CT(DB_STR_QUOTE_PROVIDER);
+ size_t cChild = pXmlQuotesModule->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pXMLSetting = pXmlQuotesModule->GetChildNode(i);
+ if(pXMLSetting && (0 == quotes_stricmp(g_pszXmlSetting,pXMLSetting->GetName().c_str())))
+ {
+ TNameValue Item = parse_setting_node(pXMLSetting);
+ if ((0 == quotes_stricmp(g_sQuotesProvider.c_str(),Item.first.c_str())) && (false == Item.second.empty()))
+ {
+ return CModuleInfo::GetInstance().GetQuoteProvidersPtr()->FindProvider(Item.second);
+ }
+ }
+ }
+
+ return CQuotesProviders::TQuotesProviderPtr();
+ }
+
+ bool get_contact_state(const IXMLNode::TXMLNodePtr& pXmlContact,CContactState& cst)
+ {
+ class visitor : public CQuotesProviderVisitor
+ {
+ public:
+ visitor(const IXMLNode::TXMLNodePtr& pXmlQuotes)
+ : m_hContact(NULL),m_pXmlQuotes(pXmlQuotes){}
+
+ HANDLE GetContact()const{return m_hContact;}
+
+ private:
+ virtual void Visit(const CQuotesProviderDukasCopy& rProvider)
+ {
+ tstring sQuoteID = GetXMLNodeValue(DB_STR_QUOTE_ID);
+ if(false == sQuoteID.empty())
+ {
+ m_hContact = rProvider.GetContactByQuoteID(sQuoteID);
+ }
+ }
+
+ virtual void Visit(const CQuotesProviderGoogle& rProvider)
+ {
+// USES_CONVERSION;
+ static const tstring g_sFromID = quotes_a2t(DB_STR_FROM_ID);//A2CT(DB_STR_FROM_ID);
+ static const tstring g_sToID = quotes_a2t(DB_STR_TO_ID);//A2CT(DB_STR_TO_ID);
+
+ tstring sFromID;
+ tstring sToID;
+ size_t cChild = m_pXmlQuotes->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = m_pXmlQuotes->GetChildNode(i);
+ if(pNode && (0 == quotes_stricmp(g_pszXmlSetting, pNode->GetName().c_str())))
+ {
+ TNameValue Item = parse_setting_node(pNode);
+ if(0 == quotes_stricmp(g_sFromID.c_str(),Item.first.c_str()))
+ {
+ sFromID = Item.second;
+ }
+ else if(0 == quotes_stricmp(g_sToID.c_str(),Item.first.c_str()))
+ {
+ sToID = Item.second;
+ }
+ }
+ }
+
+ if ((false == sFromID.empty()) && (false == sToID.empty()))
+ {
+ m_hContact = rProvider.GetContactByID(sFromID,sToID);
+ }
+ }
+
+ virtual void Visit(const CQuotesProviderFinance& rProvider)
+ {
+ tstring sQuoteID = GetXMLNodeValue(DB_STR_QUOTE_ID);
+ if(false == sQuoteID.empty())
+ {
+ m_hContact = rProvider.GetContactByQuoteID(sQuoteID);
+ }
+ }
+
+ tstring GetXMLNodeValue(const char* pszXMLNodeName)const
+ {
+// USES_CONVERSION;
+ tstring sXMLNodeName = quotes_a2t(pszXMLNodeName);//A2CT(pszXMLNodeName);
+
+ tstring sValue;
+ size_t cChild = m_pXmlQuotes->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = m_pXmlQuotes->GetChildNode(i);
+ if(pNode && (0 == quotes_stricmp(g_pszXmlSetting, pNode->GetName().c_str())))
+ {
+ TNameValue Item = parse_setting_node(pNode);
+ if(0 == quotes_stricmp(Item.first.c_str(),sXMLNodeName.c_str()))
+ {
+ sValue = Item.second;
+ break;
+ }
+ }
+ }
+
+ return sValue;
+ }
+
+ private:
+ HANDLE m_hContact;
+ IXMLNode::TXMLNodePtr m_pXmlQuotes;
+ };
+
+ IXMLNode::TXMLNodePtr pXmlQuotes = find_quotes_module(pXmlContact);
+ if(pXmlQuotes)
+ {
+ cst.m_pProvider = find_provider(pXmlQuotes);
+ if(cst.m_pProvider)
+ {
+ visitor vs(pXmlQuotes);
+ cst.m_pProvider->Accept(vs);
+ cst.m_hContact = vs.GetContact();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool import_contact(const IXMLNode::TXMLNodePtr& pXmlContact,CImportContext& impctx)
+ {
+ ++ impctx.m_cHandledContacts;
+
+ CContactState cst;
+ bool bResult = get_contact_state(pXmlContact,cst);
+ if(bResult)
+ {
+ if(NULL == cst.m_hContact)
+ {
+ cst.m_hContact = reinterpret_cast<HANDLE>(CallService(MS_DB_CONTACT_ADD,0,0));
+ cst.m_bNewContact = true;
+ }
+ else if(impctx.m_nFlags&QUOTES_IMPORT_SKIP_EXISTING_CONTACTS)
+ {
+ return true;
+ }
+
+ if(cst.m_hContact)
+ {
+ size_t cChild = pXmlContact->GetChildCount();
+ for(size_t i = 0;i < cChild && bResult;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlContact->GetChildNode(i);
+ tstring sName = pNode->GetName();
+ if(0 == quotes_stricmp(g_pszXmlModule,sName.c_str()))
+ {
+ bResult &= handle_module(cst.m_hContact,pNode,impctx.m_nFlags);
+ }
+ }
+
+ if(cst.m_bNewContact && bResult)
+ {
+ cst.m_pProvider->AddContact(cst.m_hContact);
+ cst.m_pProvider->RefreshContact(cst.m_hContact);
+ }
+ }
+ else
+ {
+ bResult = false;
+ }
+ }
+
+ return bResult;
+
+ }
+
+ size_t import_contacts(const IXMLNode::TXMLNodePtr& pXmlContacts,CImportContext& impctx)
+ {
+ size_t cContacts = 0;
+ size_t cChild = pXmlContacts->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlContacts->GetChildNode(i);
+ tstring sName = pNode->GetName();
+ if(0 == quotes_stricmp(g_pszXmlContact,sName.c_str()))
+ {
+ if(true == import_contact(pNode,impctx))
+ {
+ ++ cContacts;
+ }
+ }
+ }
+
+ return cContacts;
+
+ }
+
+ size_t handle_contacts_node(const IXMLNode::TXMLNodePtr& pXmlRoot,CImportContext& impctx)
+ {
+ size_t cContacts = 0;
+ size_t cChild = pXmlRoot->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IXMLNode::TXMLNodePtr pNode = pXmlRoot->GetChildNode(i);
+ tstring sName = pNode->GetName();
+ if(0 == quotes_stricmp(g_pszXmlContacts,sName.c_str()))
+ {
+ cContacts += import_contacts(pNode,impctx);
+ }
+ else
+ {
+ cContacts += handle_contacts_node(pNode,impctx);
+ }
+ }
+
+ return cContacts;
+
+ }
+
+ bool do_import(const IXMLNode::TXMLNodePtr& pXmlRoot,UINT nFlags)
+ {
+ CImportContext imctx(count_contacts(pXmlRoot,false));
+ imctx.m_cHandledContacts = 0;
+ imctx.m_nFlags = nFlags;
+
+ return (handle_contacts_node(pXmlRoot,imctx) > 0);
+ }
+}
+
+INT_PTR Quotes_Import(WPARAM wp,LPARAM lp)
+{
+// USES_CONVERSION;
+
+ tstring sFileName;
+ const char* pszFile = reinterpret_cast<const char*>(lp);
+ if(NULL == pszFile)
+ {
+ if(false == show_open_file_dialog(true,sFileName))
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ sFileName = quotes_a2t(pszFile);//A2CT(pszFile);
+ }
+ CModuleInfo::TXMLEnginePtr pXmlEngine = CModuleInfo::GetInstance().GetXMLEnginePtr();
+ IXMLNode::TXMLNodePtr pXmlRoot = pXmlEngine->LoadFile(sFileName);
+ if(pXmlRoot)
+ {
+ return ((true == do_import(pXmlRoot,wp)) ? 0 : 1);
+ }
+
+ return 1;
+}
+
+#ifdef TEST_IMPORT_EXPORT
+INT_PTR QuotesMenu_ImportAll(WPARAM wp,LPARAM lp)
+{
+ return CallService(MS_QUOTES_IMPORT,0,0);
+}
+
+INT_PTR QuotesMenu_ExportAll(WPARAM wp,LPARAM lp)
+{
+ return CallService(MS_QUOTES_EXPORT,0,0);
+}
+#endif
+
diff --git a/protocols/Quotes/src/ImportExport.h b/protocols/Quotes/src/ImportExport.h
new file mode 100644
index 0000000000..da2053e9a3
--- /dev/null
+++ b/protocols/Quotes/src/ImportExport.h
@@ -0,0 +1,11 @@
+#ifndef __F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__
+#define __F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__
+
+INT_PTR Quotes_Export(WPARAM wp,LPARAM lp);
+INT_PTR Quotes_Import(WPARAM wp,LPARAM lp);
+
+#ifdef TEST_IMPORT_EXPORT
+INT_PTR QuotesMenu_ImportAll(WPARAM wp,LPARAM lp);
+INT_PTR QuotesMenu_ExportAll(WPARAM wp,LPARAM lp);
+#endif
+#endif //__F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__
diff --git a/protocols/Quotes/src/IsWithinAccuracy.h b/protocols/Quotes/src/IsWithinAccuracy.h
new file mode 100644
index 0000000000..5e39281719
--- /dev/null
+++ b/protocols/Quotes/src/IsWithinAccuracy.h
@@ -0,0 +1,15 @@
+#ifndef __C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__
+#define __C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__
+
+inline bool IsWithinAccuracy(double dValue1, double dValue2, double dAccuracy = 1e-4)
+{
+ double dDifference = dValue1 - dValue2 ;
+
+ if ((-dAccuracy <= dDifference) && (dDifference <= dAccuracy))
+ return true ;
+ else
+ return false ;
+}
+
+
+#endif //__C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__
diff --git a/protocols/Quotes/src/LightMutex.cpp b/protocols/Quotes/src/LightMutex.cpp
new file mode 100644
index 0000000000..8d14e8e7bb
--- /dev/null
+++ b/protocols/Quotes/src/LightMutex.cpp
@@ -0,0 +1,22 @@
+#include "StdAfx.h"
+#include "LightMutex.h"
+
+CLightMutex::CLightMutex()
+{
+ InitializeCriticalSection(&m_cs);
+}
+
+CLightMutex::~CLightMutex()
+{
+ ::DeleteCriticalSection(&m_cs);
+}
+
+void CLightMutex::Lock()
+{
+ ::EnterCriticalSection(&m_cs);
+}
+
+void CLightMutex::Unlock()
+{
+ ::LeaveCriticalSection(&m_cs);
+}
diff --git a/protocols/Quotes/src/LightMutex.h b/protocols/Quotes/src/LightMutex.h
new file mode 100644
index 0000000000..e8c7363ba1
--- /dev/null
+++ b/protocols/Quotes/src/LightMutex.h
@@ -0,0 +1,34 @@
+#ifndef __a33da2bb_d4fe4aa7_aaf5_f9f8c3156ce6_LightMutex_h__
+#define __a33da2bb_d4fe4aa7_aaf5_f9f8c3156ce6_LightMutex_h__
+
+class CLightMutex
+{
+public:
+ CLightMutex();
+ ~CLightMutex();
+
+ void Lock();
+ void Unlock();
+
+private:
+ CRITICAL_SECTION m_cs;
+};
+
+template<class TObject> class CGuard
+{
+public:
+ CGuard(TObject& obj) : m_obj(obj)
+ {
+ m_obj.Lock();
+ }
+
+ ~CGuard()
+ {
+ m_obj.Unlock();
+ }
+
+private:
+ TObject& m_obj;
+};
+
+#endif //__a33da2bb_d4fe4aa7_aaf5_f9f8c3156ce6_LightMutex_h__
diff --git a/protocols/Quotes/src/Locale.cpp b/protocols/Quotes/src/Locale.cpp
new file mode 100644
index 0000000000..c01f67148a
--- /dev/null
+++ b/protocols/Quotes/src/Locale.cpp
@@ -0,0 +1,75 @@
+#include "StdAfx.h"
+#include "Locale.h"
+
+const std::locale GetSystemLocale()
+{
+ return std::locale("");
+}
+
+namespace
+{
+ tstring get_int_registry_value(LPCTSTR pszValueName)
+ {
+ tstring sResult;
+ HKEY hKey = NULL;
+ LONG lResult = ::RegOpenKeyEx(HKEY_CURRENT_USER,
+ _T("Control Panel\\International"),0,KEY_QUERY_VALUE,&hKey);
+ if ((ERROR_SUCCESS == lResult) && (NULL != hKey))
+ {
+ DWORD dwType = 0;
+ DWORD dwSize = 0;
+ lResult = ::RegQueryValueEx(hKey,pszValueName,nullptr,&dwType,nullptr,&dwSize);
+ if ((ERROR_SUCCESS == lResult) && ((REG_SZ == dwType) || (REG_EXPAND_SZ == dwType)))
+ {
+ std::vector<TCHAR> aBuffer(dwSize);
+ lResult = ::RegQueryValueEx(hKey,pszValueName,nullptr,nullptr,reinterpret_cast<LPBYTE>(&*aBuffer.begin()),&dwSize);
+ if(ERROR_SUCCESS == lResult)
+ {
+ std::copy(aBuffer.begin(),aBuffer.end(),std::back_inserter(sResult));
+ }
+ }
+ }
+
+ if(NULL != hKey)
+ {
+ lResult = ::RegCloseKey(hKey);
+ assert(ERROR_SUCCESS == lResult);
+ }
+
+ return sResult;
+ }
+
+ tstring date_win_2_boost(const tstring& sFrmt)
+ {
+ tstring sResult(_T("%d.%m.%y"));
+ if(sFrmt == _T("dd/MM/yy"))
+ {
+ sResult = _T("%d/%m/%y");
+ }
+ else if(sFrmt == _T("yyyy-MM-dd"))
+ {
+ sResult = _T("%y-%m-%d");
+ }
+ return sResult;
+ }
+
+ tstring time_win_2_boost(const tstring& sFrmt)
+ {
+ tstring sResult = _T("%H:%M:%S");
+ if(sFrmt == _T("H:mm") || sFrmt == _T("HH:mm"))
+ {
+ sResult = _T("%H:%M");
+ }
+ return sResult;
+ }
+}
+
+tstring Quotes_GetDateFormat(bool bShort)
+{
+ return date_win_2_boost(get_int_registry_value(bShort ? _T("sShortDate") : _T("sLongDate")));
+}
+
+tstring Quotes_GetTimeFormat(bool bShort)
+{
+ return time_win_2_boost(get_int_registry_value(bShort ? _T("sShortTime") : _T("sTimeFormat")));
+} \ No newline at end of file
diff --git a/protocols/Quotes/src/Locale.h b/protocols/Quotes/src/Locale.h
new file mode 100644
index 0000000000..92d3a56ed4
--- /dev/null
+++ b/protocols/Quotes/src/Locale.h
@@ -0,0 +1,9 @@
+#ifndef __11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_
+#define __11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_
+
+// std::string GetLocaleInfoString(LCTYPE LCType,LCID Locale = LOCALE_USER_DEFAULT);
+const std::locale GetSystemLocale();
+tstring Quotes_GetDateFormat(bool bShort);
+tstring Quotes_GetTimeFormat(bool bShort);
+
+#endif //__11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_
diff --git a/protocols/Quotes/src/Log.cpp b/protocols/Quotes/src/Log.cpp
new file mode 100644
index 0000000000..d692763bad
--- /dev/null
+++ b/protocols/Quotes/src/Log.cpp
@@ -0,0 +1,56 @@
+#include "StdAfx.h"
+#include "Log.h"
+#include "LightMutex.h"
+#include "EconomicRateInfo.h"
+#include "CreateFilePath.h"
+
+namespace
+{
+ CLightMutex g_Mutex;
+
+ tstring get_log_file_name()
+ {
+ return CreateFilePath(_T("Quotes.log"));
+ }
+
+ bool is_log_enabled()
+ {
+#ifdef _DEBUG
+ return true;
+#else
+ return (1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,DB_STR_ENABLE_LOG,false));
+#endif
+ }
+
+ void do_log(const tstring& rsFileName,ESeverity nSeverity,const tstring& rsMsg)
+ {
+ CGuard<CLightMutex> guard(g_Mutex);
+ tofstream file(rsFileName.c_str(),std::ios::ate|std::ios::app);
+ if(file.good())
+ {
+ TCHAR szTime[20];
+// TCHAR sz[10000+1];
+ _tstrtime_s(szTime);
+ file << szTime << _T(" ================================>\n") << rsMsg << _T("\n\n");
+
+// size_t cBytes = rsMsg.size();
+// const TCHAR* p = rsMsg.c_str();
+// for(size_t c = 0;c < cBytes;c += 10000,p+=10000)
+// {
+// _tcsncpy_s(sz,p,10000);
+// file << sz;
+// }
+//
+// file << "\n\n";
+ }
+ }
+}
+
+void LogIt(ESeverity nSeverity,const tstring& rsMsg)
+{
+ if(is_log_enabled())
+ {
+ tstring sFileName = get_log_file_name();
+ do_log(sFileName,nSeverity,rsMsg);
+ }
+}
diff --git a/protocols/Quotes/src/Log.h b/protocols/Quotes/src/Log.h
new file mode 100644
index 0000000000..274fcfec06
--- /dev/null
+++ b/protocols/Quotes/src/Log.h
@@ -0,0 +1,13 @@
+#ifndef __653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__
+#define __653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__
+
+enum ESeverity
+{
+ Info,
+ Warning,
+ Error
+};
+
+void LogIt(ESeverity nSeverity,const tstring& rsMsg);
+
+#endif //__653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__
diff --git a/protocols/Quotes/src/ModuleInfo.cpp b/protocols/Quotes/src/ModuleInfo.cpp
new file mode 100644
index 0000000000..4caec96368
--- /dev/null
+++ b/protocols/Quotes/src/ModuleInfo.cpp
@@ -0,0 +1,135 @@
+#include "StdAfx.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "HTMLParserMS.h"
+#include "LightMutex.h"
+#include "WinCtrlHelper.h"
+#include "EconomicRateInfo.h"
+#include "XMLEngineMI.h"
+
+namespace
+{
+ CModuleInfo::TXMLEnginePtr g_pXMLEngine;
+ CModuleInfo::THTMLEnginePtr g_pHTMLEngine;
+ CLightMutex g_lmParsers;
+}
+
+CModuleInfo::CModuleInfo()
+ : m_bExtendedStatusInfo(1 == DBGetContactSettingByte(NULL,QUOTES_MODULE_NAME,"ExtendedStatus",false))
+{
+}
+
+CModuleInfo::~CModuleInfo()
+{
+}
+
+CModuleInfo& CModuleInfo::GetInstance()
+{
+ static CModuleInfo mi;
+ return mi;
+}
+
+HANDLE CModuleInfo::GetWindowList(const std::string& rsKey,bool bAllocateIfNonExist /*= true*/)
+{
+ HANDLE hResult = NULL;
+ THandles::const_iterator i = m_ahWindowLists.find(rsKey);
+ if(i != m_ahWindowLists.end())
+ {
+ hResult = i->second;
+ }
+ else if(bAllocateIfNonExist)
+ {
+ hResult = reinterpret_cast<HANDLE>(CallService(MS_UTILS_ALLOCWINDOWLIST,0,0));
+ if(hResult)
+ {
+ m_ahWindowLists.insert(std::make_pair(rsKey,hResult));
+ }
+ }
+
+ return hResult;
+}
+
+void CModuleInfo::OnMirandaShutdown()
+{
+ BOOST_FOREACH(THandles::value_type p,m_ahWindowLists)
+ {
+ WindowList_Broadcast(p.second,WM_CLOSE,0,0);
+ }
+}
+
+CModuleInfo::TQuotesProvidersPtr CModuleInfo::GetQuoteProvidersPtr()
+{
+ static TQuotesProvidersPtr pProviders(new CQuotesProviders);
+ return pProviders;
+}
+
+CModuleInfo::TXMLEnginePtr CModuleInfo::GetXMLEnginePtr()
+{
+ if (!g_pXMLEngine)
+ {
+ CGuard<CLightMutex> cs(g_lmParsers);
+ if (!g_pXMLEngine)
+ {
+ mir_getXI(&xi);
+ g_pXMLEngine = TXMLEnginePtr(new CXMLEngineMI);
+ }
+ }
+
+ return g_pXMLEngine;
+}
+
+// void CModuleInfo::SetXMLEnginePtr(TXMLEnginePtr pEngine)
+// {
+// g_pXMLEngine = pEngine;
+// }
+
+CModuleInfo::THTMLEnginePtr CModuleInfo::GetHTMLEngine()
+{
+ if (!g_pHTMLEngine)
+ {
+ CGuard<CLightMutex> cs(g_lmParsers);
+ if (!g_pHTMLEngine)
+ {
+ g_pHTMLEngine = THTMLEnginePtr(new CHTMLEngineMS);
+ }
+ }
+
+ return g_pHTMLEngine;
+}
+
+void CModuleInfo::SetHTMLEngine(THTMLEnginePtr pEngine)
+{
+ g_pHTMLEngine = pEngine;
+}
+
+bool CModuleInfo::Verify()
+{
+ INITCOMMONCONTROLSEX icc = {0};
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_WIN95_CLASSES|ICC_LINK_CLASS;
+ if(FALSE == ::InitCommonControlsEx(&icc))
+ {
+ return false;
+ }
+
+ if (!GetXMLEnginePtr())
+ {
+ Quotes_MessageBox(NULL,TranslateT("Miranda could not load Quotes plugin. XML parser is missing."),MB_OK|MB_ICONERROR);
+ return false;
+ }
+
+ if (!g_pHTMLEngine && (false == CHTMLParserMS::IsInstalled()))
+ {
+ Quotes_MessageBox(NULL,
+ TranslateT("Miranda could not load Quotes plugin. Microsoft HTML parser is missing."),
+ MB_YESNO|MB_ICONQUESTION);
+ return false;
+ }
+
+ return true;
+}
+
+bool CModuleInfo::GetExtendedStatusFlag()const
+{
+ return m_bExtendedStatusInfo;
+}
diff --git a/protocols/Quotes/src/ModuleInfo.h b/protocols/Quotes/src/ModuleInfo.h
new file mode 100644
index 0000000000..2882dfae6d
--- /dev/null
+++ b/protocols/Quotes/src/ModuleInfo.h
@@ -0,0 +1,43 @@
+#ifndef __d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__
+#define __d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__
+
+class CQuotesProviders;
+class IXMLEngine;
+class IHTMLEngine;
+// class IHTMLParser;
+
+class CModuleInfo
+{
+public:
+ typedef boost::shared_ptr<CQuotesProviders> TQuotesProvidersPtr;
+ typedef boost::shared_ptr<IXMLEngine> TXMLEnginePtr;
+ typedef boost::shared_ptr<IHTMLEngine> THTMLEnginePtr;
+
+private:
+ CModuleInfo();
+ ~CModuleInfo(void);
+
+public:
+ static CModuleInfo& GetInstance();
+
+ void OnMirandaShutdown();
+ HANDLE GetWindowList(const std::string& rsKey,bool bAllocateIfNonExist = true);
+ bool GetExtendedStatusFlag()const;
+
+ static bool Verify();
+
+ static TQuotesProvidersPtr GetQuoteProvidersPtr();
+
+ static TXMLEnginePtr GetXMLEnginePtr();
+// static void SetXMLEnginePtr(TXMLEnginePtr pEngine);
+
+ static THTMLEnginePtr GetHTMLEngine();
+ static void SetHTMLEngine(THTMLEnginePtr pEngine);
+
+private:
+ typedef std::map<std::string,HANDLE> THandles;
+ THandles m_ahWindowLists;
+ bool m_bExtendedStatusInfo;
+};
+
+#endif //__d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__
diff --git a/protocols/Quotes/src/OptionDukasCopy.cpp b/protocols/Quotes/src/OptionDukasCopy.cpp
new file mode 100644
index 0000000000..6fcc542b09
--- /dev/null
+++ b/protocols/Quotes/src/OptionDukasCopy.cpp
@@ -0,0 +1,414 @@
+#include "StdAfx.h"
+#include "OptionDukasCopy.h"
+#include "IconLib.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "QuotesProviderDukasCopy.h"
+#include "resource.h"
+#include "EconomicRateInfo.h"
+#include "CommonOptionDlg.h"
+
+// extern HANDLE g_hEventSettingsCnanged;
+
+namespace
+{
+ enum ETreeCheckBoxState
+ {
+ // tree check box state
+ TCBS_NOSTATEBOX = 0,
+ TCBS_UNCHECKED = 1,
+ TCBS_CHECKED = 2,
+ };
+
+ enum
+ {
+ TREE_VIEW_CHECK_STATE_CHANGE = WM_USER + 100,
+ IMAGE_INDEX_SECTION = 0,
+ IMAGE_INDEX_QUOTE = 1
+ };
+
+ // typedef CQuotesProviders::TQuotesProviders TQuotesProviders;
+ // typedef CQuotesProviders::TQuotesProviderPtr TQuotesProviderPtr;
+
+ HTREEITEM tree_insert_item(HWND hwndTree,
+ const tstring& rsName,
+ HTREEITEM htiParent,
+ int nImage,
+ LPARAM lp = 0)
+ {
+// USES_CONVERSION;
+ TVINSERTSTRUCT tvi;
+ ZeroMemory(&tvi,sizeof(tvi));
+
+ tvi.hParent = htiParent;
+ tvi.hInsertAfter = TVI_LAST;
+ tvi.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+
+// CA2T name(rsName.c_str());
+
+ tvi.item.pszText = const_cast<LPTSTR>(rsName.c_str());//name;
+ tvi.item.lParam = lp;
+ tvi.item.iImage = nImage;
+ tvi.item.iSelectedImage = nImage;
+ return TreeView_InsertItem(hwndTree,&tvi);
+ }
+
+ bool add_quote_to_tree(const CQuotesProviderDukasCopy::CQuote& q,HWND hwndTree,HTREEITEM htiParent,const CQuotesProviderDukasCopy* pQuotesProvier)
+ {
+ bool bChecked = pQuotesProvier->IsQuoteWatched(q);
+ HTREEITEM hti = tree_insert_item(hwndTree,((false == q.GetName().empty()) ? q.GetName() : q.GetSymbol()),htiParent,IMAGE_INDEX_QUOTE);
+ if(hti && bChecked)
+ {
+ HWND hDlg = ::GetParent(hwndTree);
+ assert(::IsWindow(hDlg));
+ ::PostMessage(hDlg,TREE_VIEW_CHECK_STATE_CHANGE,MAKEWPARAM(0,TCBS_CHECKED),reinterpret_cast<LPARAM>(hti));
+ }
+
+ return (NULL != hti && bChecked);
+ }
+
+ void add_section_to_tree(const CQuotesProviderDukasCopy::CQuoteSection& qs,
+ HWND hwndTree,
+ HTREEITEM htiParent,
+ const CQuotesProviderDukasCopy* pQuotesProvier,
+ bool& rbIsChecked,
+ bool& rbIsExpended,
+ bool bExpand = false)
+ {
+ rbIsChecked = false;
+ rbIsExpended = false;
+ HTREEITEM hti = tree_insert_item(hwndTree,qs.GetName(),htiParent,IMAGE_INDEX_SECTION);
+
+ size_t cCheckedItems = 0;
+ size_t cSection = qs.GetSectionCount();
+ for(size_t i = 0;i < cSection;++i)
+ {
+ bool bIsChecked = false;
+ bool bIsExpanded = false;
+ CQuotesProviderDukasCopy::CQuoteSection other = qs.GetSection(i);
+ add_section_to_tree(other,hwndTree,hti,pQuotesProvier,bIsChecked,bIsExpanded);
+
+ if(bIsChecked)
+ {
+ ++cCheckedItems;
+ }
+
+ if(bIsExpanded)
+ {
+ bExpand = true;
+ }
+ }
+
+ size_t cQuotes = qs.GetQuoteCount();
+ for(size_t i = 0;i < cQuotes;++i)
+ {
+ CQuotesProviderDukasCopy::CQuote q = qs.GetQuote(i);
+ if(true == add_quote_to_tree(q,hwndTree,hti,pQuotesProvier))
+ {
+ ++ cCheckedItems;
+ }
+ }
+
+ if(bExpand || cCheckedItems > 0)
+ {
+ rbIsExpended = true;
+ TreeView_Expand(hwndTree,hti,TVE_EXPAND);
+ }
+
+ if(cCheckedItems == (cSection+cQuotes))
+ {
+ rbIsChecked = true;
+ HWND hDlg = ::GetParent(hwndTree);
+ assert(::IsWindow(hDlg));
+ ::PostMessage(hDlg,TREE_VIEW_CHECK_STATE_CHANGE,MAKEWPARAM(0,TCBS_CHECKED),reinterpret_cast<LPARAM>(hti));
+ }
+ }
+
+ void add_provider_to_tree(const CQuotesProviderDukasCopy* pQuotesProvier,HWND hwndTree)
+ {
+ CQuotesProviderDukasCopy::CQuoteSection qs = pQuotesProvier->GetQuotes();
+ bool bIsChecked = false;
+ bool bIsExpanded = false;
+ add_section_to_tree(qs,hwndTree,TVI_ROOT,pQuotesProvier,bIsChecked,bIsExpanded,true);
+ }
+
+ inline HTREEITEM tree_get_child_item(HWND hwndTree,HTREEITEM hti)
+ {
+ return reinterpret_cast<HTREEITEM>(::SendMessage(hwndTree, TVM_GETNEXTITEM, TVGN_CHILD,reinterpret_cast<LPARAM>(hti)));
+ }
+
+ inline HTREEITEM tree_get_next_sibling_item(HWND hwndTree,HTREEITEM hti)
+ {
+ return reinterpret_cast<HTREEITEM>(::SendMessage(hwndTree, TVM_GETNEXTITEM, TVGN_NEXT,reinterpret_cast<LPARAM>(hti)));
+ }
+
+ inline ETreeCheckBoxState tree_get_state_image(HWND hwndTree,HTREEITEM hti)
+ {
+ TVITEM tvi;
+ tvi.hItem = hti;
+ tvi.mask = TVIF_STATE|TVIF_HANDLE;
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ if(TRUE == ::SendMessage(hwndTree,TVM_GETITEM,0,reinterpret_cast<LPARAM>(&tvi)))
+ {
+ UINT nState = (tvi.state >> 12);
+ return static_cast<ETreeCheckBoxState>(nState);
+ }
+ else
+ {
+ return TCBS_UNCHECKED;
+ }
+ }
+
+ void tree_do_set_item_state(HWND hwndTree,HTREEITEM hti,ETreeCheckBoxState nState)
+ {
+ TVITEM tvi;
+ ZeroMemory(&tvi,sizeof(tvi));
+
+ tvi.mask = TVIF_STATE|TVIF_HANDLE;
+ tvi.hItem = hti;
+
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state = INDEXTOSTATEIMAGEMASK(nState);
+
+ ::SendMessage(hwndTree,TVM_SETITEM,0,reinterpret_cast<LPARAM>(&tvi));
+ }
+
+ void tree_set_item_state(HWND hwndTree,HTREEITEM hti,ETreeCheckBoxState nState,bool bRecursively)
+ {
+ if(true == bRecursively)
+ {
+ for(hti = tree_get_child_item(hwndTree,hti);hti;hti = tree_get_next_sibling_item(hwndTree,hti))
+ {
+ tree_do_set_item_state(hwndTree,hti,nState);
+ tree_set_item_state(hwndTree,hti,nState,bRecursively);
+ }
+ }
+ else
+ {
+ tree_do_set_item_state(hwndTree,hti,nState);
+ }
+ }
+
+ void save_quote_selection(HWND hwndTree,HTREEITEM h,const CQuotesProviderDukasCopy::CQuote& q,CQuotesProviderDukasCopy* pQuotesProvier)
+ {
+ ETreeCheckBoxState nState = tree_get_state_image(hwndTree,h);
+ pQuotesProvier->WatchForQuote(q,(TCBS_CHECKED == nState));
+ }
+
+ void recursive_save_quote_section_selection(HWND hwndTree,HTREEITEM h,const CQuotesProviderDukasCopy::CQuoteSection& qs,CQuotesProviderDukasCopy* pQuotesProvier)
+ {
+ size_t cSection = qs.GetSectionCount();
+ h = tree_get_child_item(hwndTree,h);
+ for(size_t i = 0;h && (i < cSection);++i,h = tree_get_next_sibling_item(hwndTree,h))
+ {
+ CQuotesProviderDukasCopy::CQuoteSection other = qs.GetSection(i);
+ recursive_save_quote_section_selection(hwndTree,h,other,pQuotesProvier);
+ }
+
+ size_t cQuotes = qs.GetQuoteCount();
+ for(size_t i = 0;h && (i < cQuotes);++i,h = tree_get_next_sibling_item(hwndTree,h))
+ {
+ CQuotesProviderDukasCopy::CQuote q = qs.GetQuote(i);
+ save_quote_selection(hwndTree,h,q,pQuotesProvier);
+ }
+ }
+
+ void recursive_save_selection(HWND hwndTree,CQuotesProviderDukasCopy* pQuotesProvider)
+ {
+ // CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ // const TQuotesProviders& rapQuotesProviders = pProviders->GetProviders();
+ //
+ // TQuotesProviders::const_iterator i = rapQuotesProviders.begin();
+ // TQuotesProviders::const_iterator iE = rapQuotesProviders.end();
+ // for(HTREEITEM h = tree_get_child_item(hwndTree,TVI_ROOT);h && (i!=iE);++i,h = tree_get_next_sibling_item(hwndTree,h))
+ // {
+ // const TQuotesProviderPtr& pQuotesProvier = *i;
+ CQuotesProviderDukasCopy::CQuoteSection qs = pQuotesProvider->GetQuotes();
+ recursive_save_quote_section_selection(hwndTree,tree_get_child_item(hwndTree,TVI_ROOT),qs,pQuotesProvider);
+ // }
+ }
+
+ class CImageListWrapper
+ {
+ public:
+ CImageListWrapper()
+ : m_hImageList(ImageList_Create(::GetSystemMetrics(SM_CXSMICON),
+ ::GetSystemMetrics(SM_CYSMICON),
+ ILC_COLOR24|ILC_MASK,2,0))
+ {
+ if(m_hImageList)
+ {
+ ImageList_AddIcon(m_hImageList,Quotes_LoadIconEx(ICON_STR_SECTION));
+ ImageList_AddIcon(m_hImageList,Quotes_LoadIconEx(ICON_STR_QUOTE));
+ }
+ }
+
+ ~CImageListWrapper()
+ {
+ if(m_hImageList)
+ {
+ ImageList_Destroy(m_hImageList);
+ }
+ }
+
+ operator HIMAGELIST()const
+ {
+ return m_hImageList;
+ }
+
+ private:
+ HIMAGELIST m_hImageList;
+ };
+
+ HIMAGELIST get_image_list()
+ {
+ static CImageListWrapper wrapper;
+ return wrapper;
+ }
+
+ CQuotesProviderDukasCopy* get_dukas_copy_provider()
+ {
+ CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapQuotesProviders = pProviders->GetProviders();
+ for(CQuotesProviders::TQuotesProviders::const_iterator i = rapQuotesProviders.begin();i != rapQuotesProviders.end();++i)
+ {
+ const CQuotesProviders::TQuotesProviderPtr& pProvider = *i;
+ CQuotesProviderDukasCopy* pDukas = dynamic_cast<CQuotesProviderDukasCopy*>(pProvider.get());
+ if(pDukas)
+ {
+ return pDukas;
+ }
+ }
+
+ assert(!"We should never get here!");
+ return NULL;
+ }
+
+ INT_PTR CALLBACK EconomicRatesDlgProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam)
+ {
+ CCommonDlgProcData d(get_dukas_copy_provider());
+ CommonOptionDlgProc(hdlg,message,wParam,lParam,d);
+
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hdlg);
+
+ HWND hwndTree = ::GetDlgItem(hdlg,IDC_TREE_ECONOMIC_RATES);
+ HIMAGELIST hImage = get_image_list();
+ if(hImage)
+ {
+ TreeView_SetImageList(hwndTree,hImage,TVSIL_NORMAL);
+ }
+
+ const CQuotesProviderDukasCopy* pDukasProvider = get_dukas_copy_provider();
+ if(pDukasProvider)
+ {
+ add_provider_to_tree(pDukasProvider,hwndTree);
+ }
+ // Window_SetIcon_IcoLib(hdlg, SKINICON_OTHER_MIRANDA);
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lParam);
+ switch(pNMHDR->code)
+ {
+ case TVN_KEYDOWN:
+ if(IDC_TREE_ECONOMIC_RATES == wParam)
+ {
+ LPNMTVKEYDOWN pKeyDown = reinterpret_cast<LPNMTVKEYDOWN>(lParam);
+ if(VK_SPACE == pKeyDown->wVKey)
+ {
+ HTREEITEM hti = TreeView_GetSelection(::GetDlgItem(hdlg,IDC_TREE_ECONOMIC_RATES));
+ ::PostMessage(hdlg,TREE_VIEW_CHECK_STATE_CHANGE,MAKEWPARAM(1,0),reinterpret_cast<LPARAM>(hti));
+ PropSheet_Changed(::GetParent(hdlg),hdlg);
+ }
+ }
+ break;
+ case NM_CLICK:
+ if(IDC_TREE_ECONOMIC_RATES == wParam)
+ {
+ DWORD pos = ::GetMessagePos();
+
+ HWND hwndTree = ::GetDlgItem(hdlg,IDC_TREE_ECONOMIC_RATES);
+
+ TVHITTESTINFO tvhti;
+ tvhti.pt.x = LOWORD(pos);
+ tvhti.pt.y = HIWORD(pos);
+ ::ScreenToClient(hwndTree,&(tvhti.pt));
+
+ HTREEITEM hti = reinterpret_cast<HTREEITEM>(::SendMessage(hwndTree,TVM_HITTEST,0,reinterpret_cast<LPARAM>(&tvhti)));
+ if(hti && (tvhti.flags&TVHT_ONITEMSTATEICON))
+ {
+ ::PostMessage(hdlg,TREE_VIEW_CHECK_STATE_CHANGE,MAKEWPARAM(1,0),reinterpret_cast<LPARAM>(hti));
+ PropSheet_Changed(::GetParent(hdlg),hdlg);
+ }
+ }
+ break;
+ case PSN_APPLY:
+ {
+ CQuotesProviderDukasCopy* pDukasProvider = get_dukas_copy_provider();
+ if(pDukasProvider)
+ {
+ recursive_save_selection(::GetDlgItem(hdlg,IDC_TREE_ECONOMIC_RATES),pDukasProvider);
+ pDukasProvider->RefreshAll();
+ }
+ }
+ break;
+ }
+ }
+ return TRUE;
+
+ case TREE_VIEW_CHECK_STATE_CHANGE:
+ {
+ HWND hwndTree = ::GetDlgItem(hdlg,IDC_TREE_ECONOMIC_RATES);
+ HTREEITEM hti = reinterpret_cast<HTREEITEM>(lParam);
+
+ ETreeCheckBoxState nState;
+
+ bool bRecursively = 1 == LOWORD(wParam);
+ if(bRecursively)
+ {
+ nState = tree_get_state_image(hwndTree,hti);
+ }
+ else
+ {
+ nState = static_cast<ETreeCheckBoxState>(HIWORD(wParam));
+ }
+
+ tree_set_item_state(hwndTree,hti,nState,bRecursively);
+ }
+ break;
+ // case WM_CLOSE:
+ // DestroyWindow(hdlg);
+ // break;
+ // case WM_DESTROY:
+ // g_hwndEconomicRates = NULL;
+ // break;
+ }
+
+ return FALSE;
+ }
+}
+
+void ShowDukasCopyPropPage(CQuotesProviderDukasCopy* pProvider,WPARAM wp,OPTIONSDIALOGPAGE& odp)
+{
+ const IQuotesProvider::CProviderInfo& pi = pProvider->GetInfo();
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_ECONOMIC_RATES);
+ odp.pfnDlgProc = EconomicRatesDlgProc;
+// #if MIRANDA_VER >= 0x0600
+ //odp.ptszTab = TranslateTS(const_cast<LPTSTR>(pi.m_sName.c_str()));
+ odp.ptszTab = const_cast<LPTSTR>(pi.m_sName.c_str());
+// #else
+// tostringstream o;
+// o << TranslateTS(QUOTES_PROTOCOL_NAME) << _T(" - ") << TranslateTS(pi.m_sName.c_str());
+// tstring sTitle = o.str();
+// odp.ptszTitle = TranslateTS(const_cast<LPTSTR>(sTitle.c_str()));
+// #endif
+
+ Options_AddPage(wp, &odp);
+}
diff --git a/protocols/Quotes/src/OptionDukasCopy.h b/protocols/Quotes/src/OptionDukasCopy.h
new file mode 100644
index 0000000000..0674119e83
--- /dev/null
+++ b/protocols/Quotes/src/OptionDukasCopy.h
@@ -0,0 +1,8 @@
+#ifndef __60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__
+#define __60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__
+
+class CQuotesProviderDukasCopy;
+
+void ShowDukasCopyPropPage(CQuotesProviderDukasCopy* pProvider,WPARAM wp,OPTIONSDIALOGPAGE& odp);
+
+#endif //__60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__
diff --git a/protocols/Quotes/src/QuoteChart.cpp b/protocols/Quotes/src/QuoteChart.cpp
new file mode 100644
index 0000000000..3746540d23
--- /dev/null
+++ b/protocols/Quotes/src/QuoteChart.cpp
@@ -0,0 +1,408 @@
+#include "StdAfx.h"
+#include "QuoteChart.h"
+
+#ifdef CHART_IMPLEMENT
+
+// #include "QuotesProviderDukasCopy.h"
+// #include "QuotesProviders.h"
+#include "ModuleInfo.h"
+#include "EconomicRateInfo.h"
+// #include "WinCtrlHelper.h"
+#include "resource.h"
+#include "DBUtils.h"
+#include "Locale.h"
+#include "SettingsDlg.h"
+#include "Chart.h"
+#include "WinCtrlHelper.h"
+
+#define WINDOW_PREFIX "Quotes Chart_"
+#define CHART_CTRL_CLASS _T("DioksinChart")
+
+namespace
+{
+ struct CTimeConvert
+ {
+ static double Convert(const boost::posix_time::time_duration& v)
+ {
+ return boost::numeric_cast<double>(v.ticks());
+ }
+
+ static tstring ToString(const boost::posix_time::ptime& v)
+ {
+ tostringstream k;
+ k.imbue(std::locale(GetSystemLocale(),new ttime_facet(_T("%d/%m/%y %H:%M:%S"))));
+ k << v;
+ return k.str();
+ }
+ };
+
+ typedef CChart<boost::posix_time::ptime,double,CTimeConvert> TChart;
+
+ inline TChart* get_chart_ptr(HWND hWnd)
+ {
+ TChart* pChart = reinterpret_cast<TChart*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ return pChart;
+ }
+
+ bool read_log_file(HANDLE hContact,TChart& rChart)
+ {
+ tstring sLogFileName = GetContactLogFileName(hContact);
+ if(false == sLogFileName.empty())
+ {
+ std::locale loc(GetSystemLocale(),new ttime_input_facet(_T("%d.%m.%y %H:%M:%S")));
+ boost::posix_time::ptime oDateTime;
+ double dRate;
+
+ tifstream file(sLogFileName.c_str());
+ file.imbue(loc);
+ while((false == file.fail()) && (false == file.eof()))
+ {
+ tstring sLine;
+ std::getline(file,sLine);
+
+ tistringstream line(sLine);
+ line.imbue(loc);
+
+ tstring sName;
+ std::getline(line,sName,_T('\t'));
+ line >> oDateTime >> dRate;
+ if ((false == line.fail()) && (true == line.eof()))
+ {
+ rChart.AddValue(oDateTime,dRate);
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+
+ enum
+ {
+ ID_CHART = 0x1969,
+
+ srcLogFile = 0,
+ srcHistory = 1,
+
+ filterAll = 0,
+ filterLastDay = 1,
+ filterLastWeek = 2,
+ filterLastMonth = 3,
+ filterLastYear = 4,
+ filterUserDefined = 5,
+
+ CHART_SET_SOURCE = WM_USER + 1,
+ CHART_SET_FILTER = WM_USER + 2,
+ };
+
+ LRESULT CALLBACK ChartWndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_CREATE:
+ {
+ CREATESTRUCT* pCS = reinterpret_cast<CREATESTRUCT*>(lp);
+ HANDLE hContact = reinterpret_cast<HANDLE>(pCS->lpCreateParams);
+
+ TChart* pChart = new TChart;
+ read_log_file(hContact,*pChart);
+
+ ::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast<LONG_PTR>(pChart));
+ }
+ return 0;
+
+ case CHART_SET_SOURCE:
+ break;
+
+ case CHART_SET_FILTER:
+ break;
+
+ case WM_SIZE:
+ {
+ TChart* pChart = get_chart_ptr(hWnd);
+ pChart->SetRect(0,0,LOWORD(lp),HIWORD(lp));
+ }
+ return 0;
+
+ case WM_PAINT:
+ if(TRUE == ::GetUpdateRect(hWnd,NULL,FALSE))
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = ::BeginPaint(hWnd,&ps);
+ if(NULL != hdc)
+ {
+ TChart* pChart = get_chart_ptr(hWnd);
+ pChart->Draw(hdc);
+ ::EndPaint(hWnd,&ps);
+ }
+ }
+
+ return 0;
+ case WM_DESTROY:
+ {
+ TChart* pChart = get_chart_ptr(hWnd);
+ ::SetWindowLongPtr(hWnd,GWLP_USERDATA,NULL);
+ delete pChart;
+ }
+ break;
+ }
+
+ return ::DefWindowProc(hWnd,msg,wp,lp);
+ }
+
+ void register_chart_control()
+ {
+ static bool g_bRegister = false;
+ if(g_bRegister)
+ {
+ return;
+ }
+
+ WNDCLASS wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = ChartWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = CModuleInfo::GetInstance().GetModuleHandle();
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = CHART_CTRL_CLASS;
+
+ if(RegisterClass(&wc))
+ {
+ g_bRegister = true;
+ }
+ }
+
+
+ bool screen_2_client(HWND hWnd,LPRECT pRect)
+ {
+ POINT pt;
+ pt.x = pRect->left;
+ pt.y = pRect->top;
+ bool bResult = TRUE == ::ScreenToClient(hWnd,&pt);
+ pRect->left = pt.x;
+ pRect->top = pt.y;
+ pt.x = pRect->right;
+ pt.y = pRect->bottom;
+ bResult |= TRUE == ::ScreenToClient(hWnd,&pt);
+ pRect->right = pt.x;
+ pRect->bottom = pt.y;
+ return bResult;
+ }
+
+ inline HANDLE get_contact(HWND hWnd)
+ {
+ HANDLE hContact = reinterpret_cast<HANDLE>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ return hContact;
+ }
+
+ void update_filter_controls(HWND hDlg)
+ {
+ int nSel = ::SendDlgItemMessage(hDlg,IDC_COMBO_FILTER,CB_GETCURSEL,0,0);
+
+ ::ShowWindow(::GetDlgItem(hDlg,IDC_EDIT_FROM),(filterUserDefined == nSel) ? SW_SHOW : SW_HIDE);
+ ::ShowWindow(::GetDlgItem(hDlg,IDC_EDIT_TO),(filterUserDefined == nSel) ? SW_SHOW : SW_HIDE);
+ }
+
+ INT_PTR CALLBACK ChartDlgProc(HWND hDlg,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ HANDLE hContact = reinterpret_cast<HANDLE>(lp);
+
+ TranslateDialogDefault(hDlg);
+
+ tstring sName = get_window_text(hDlg);
+ sName += _T(" - ");
+ sName += GetContactName(hContact);
+ ::SetWindowText(hDlg,sName.c_str());
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,false);
+ assert(hWL);
+ WindowList_Add(hWL,hDlg,hContact);
+
+ ::SetWindowLongPtr(hDlg,GWLP_USERDATA,reinterpret_cast<LONG_PTR>(hContact));
+
+ static LPCTSTR szSources[] = {_T("Log File"),_T("Miranda's History")};
+ static LPCTSTR szFilters[] = {_T("All"),_T("Last Day"),_T("Last Week"),_T("Last Month"),_T("Last Year"),_T("User-Defined")};
+
+ for(int i = 0;i < sizeof(szSources)/sizeof(szSources[0]);++i)
+ {
+ LPCTSTR p = TranslateTS(szSources[i]);
+ ::SendDlgItemMessage(hDlg,IDC_COMBO_DATA_SOURCE,CB_INSERTSTRING,-1,reinterpret_cast<LPARAM>(p));
+ }
+
+ int nSel = DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,"Chart_Source",srcLogFile);
+ ::SendDlgItemMessage(hDlg,IDC_COMBO_DATA_SOURCE,CB_SETCURSEL,nSel,0);
+
+ for(int i = 0;i < sizeof(szFilters)/sizeof(szFilters[0]);++i)
+ {
+ LPCTSTR p = TranslateTS(szSources[i]);
+ ::SendDlgItemMessage(hDlg,IDC_COMBO_FILTER,CB_INSERTSTRING,-1,reinterpret_cast<LPARAM>(szFilters[i]));
+ }
+
+ nSel = DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,"Chart_Filter",filterAll);
+ ::SendDlgItemMessage(hDlg,IDC_COMBO_FILTER,CB_SETCURSEL,nSel,0);
+
+ update_filter_controls(hDlg);
+
+ register_chart_control();
+ HWND hwndImage = ::GetDlgItem(hDlg,IDC_STATIC_IMAGE);
+ RECT rcImage;
+ ::GetWindowRect(hwndImage,&rcImage);
+ screen_2_client(hDlg,&rcImage);
+ //BOOL bResult = ShowWindow(hwndImage,SW_HIDE);
+ //assert(bResult);
+
+ HWND hChart = ::CreateWindowEx(0L,CHART_CTRL_CLASS,NULL,WS_CHILDWINDOW|WS_VISIBLE,
+ rcImage.left,rcImage.top,rcImage.right-rcImage.left,rcImage.bottom-rcImage.top,
+ hDlg,reinterpret_cast<HMENU>(ID_CHART),CModuleInfo::GetInstance().GetModuleHandle(),hContact);
+ assert(NULL != hChart);
+
+ Utils_RestoreWindowPosition(hDlg,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX);
+ BOOL bResult = ::ShowWindow(hDlg,SW_SHOW);
+ assert(bResult);
+ }
+ return (TRUE);
+ case WM_CLOSE:
+ {
+ HANDLE hContact = get_contact(hDlg);
+ SetWindowLongPtr(hDlg,GWLP_USERDATA,0);
+
+// save_options(hDlg,hContact);
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,false);
+ assert(hWL);
+ WindowList_Remove(hWL,hDlg);
+ Utils_SaveWindowPosition(hDlg,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX);
+
+ HWND hwndChart = ::GetDlgItem(hDlg,ID_CHART);
+ BOOL bResult = ::DestroyWindow(hwndChart);
+ assert(bResult);
+
+ ::EndDialog(hDlg,0);
+ }
+ return (TRUE);
+ case WM_COMMAND:
+ switch(LOWORD(wp))
+ {
+ case IDCANCEL:
+ {
+ SendMessage(hDlg, WM_CLOSE, 0, 0);
+ }
+ return (TRUE);
+ case IDC_COMBO_FILTER:
+ if(CBN_SELCHANGE == HIWORD(wp))
+ {
+ ::SendDlgItemMessage(hDlg,ID_CHART,CHART_SET_FILTER,::SendDlgItemMessage(hDlg,IDC_COMBO_FILTER,CB_GETCURSEL,0,0),0);
+ update_filter_controls(hDlg);
+ }
+ break;
+ case IDC_COMBO_DATA_SOURCE:
+ if(CBN_SELCHANGE == HIWORD(wp))
+ {
+ ::SendDlgItemMessage(hDlg,ID_CHART,CHART_SET_SOURCE,::SendDlgItemMessage(hDlg,IDC_COMBO_DATA_SOURCE,CB_GETCURSEL,0,0),0);
+ }
+ break;
+ }
+ return (FALSE);
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lp);
+ switch(pNMHDR->code)
+ {
+ case NM_CLICK:
+ if(IDC_SYSLINK_PROVIDER == wp)
+ {
+ PNMLINK pNMLink = reinterpret_cast<PNMLINK>(pNMHDR);
+ ::ShellExecute(hDlg,_T("open"),pNMLink->item.szUrl,NULL,NULL,SW_SHOWNORMAL);
+ }
+ break;
+ }
+ }
+ break;
+// case WM_ERASEBKGND:
+// {
+// HDC hdc = reinterpret_cast<HDC>(wp);
+// TChart* pChart = get_chart_ptr(hDlg);
+// pChart->DrawBackground(hdc);
+// return TRUE;
+// }
+// break;
+ case WM_SIZE:
+ {
+ enum{ INDENT = 7};
+
+ int nWidth = LOWORD(lp);
+ int nHeight = HIWORD(lp);
+
+ HWND hwndChart = GetDlgItem(hDlg,ID_CHART);
+ HWND hwndLink = GetDlgItem(hDlg,IDC_SYSLINK_PROVIDER);
+ HWND hwndClose = GetDlgItem(hDlg,IDCANCEL);
+
+ RECT rcDlg;
+ GetClientRect(hDlg,&rcDlg);
+
+ RECT rcChart;
+ GetWindowRect(hwndChart,&rcChart);
+ screen_2_client(hDlg,&rcChart);
+
+ RECT rcLink;
+ GetWindowRect(hwndLink,&rcLink);
+ screen_2_client(hDlg,&rcLink);
+ SetWindowPos(hwndLink,NULL,rcDlg.left + INDENT,
+ rcDlg.bottom-INDENT-(rcLink.bottom-rcLink.top),
+ 0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+
+ RECT rcClose;
+ GetWindowRect(hwndClose,&rcClose);
+ screen_2_client(hDlg,&rcClose);
+ SetWindowPos(hwndClose,NULL,rcDlg.right - INDENT - (rcClose.right-rcClose.left),
+ rcDlg.bottom-INDENT-(rcClose.bottom-rcClose.top),
+ 0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+
+ SetWindowPos(hwndChart,NULL,rcDlg.left + INDENT,
+ rcChart.top,
+ (nWidth-INDENT*2),
+ nHeight-(rcClose.bottom-rcClose.top)-INDENT*2-rcChart.top,
+ SWP_NOZORDER|SWP_NOACTIVATE);
+
+ }
+ break;
+ }
+ return (FALSE);
+ }
+}
+
+INT_PTR QuotesMenu_Chart(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,true);
+ assert(hWL);
+ HWND hWnd = WindowList_Find(hWL,hContact);
+ if(NULL != hWnd)
+ {
+ SetForegroundWindow(hWnd);
+ SetFocus(hWnd);
+ }
+ else
+ {
+ CreateDialogParam(CModuleInfo::GetModuleHandle(), MAKEINTRESOURCE(IDD_DUKASCOPY_CHART), NULL, ChartDlgProc, reinterpret_cast<LPARAM>(hContact));
+ }
+
+ return 0;
+}
+
+#endif //CHART_IMPLEMENT
diff --git a/protocols/Quotes/src/QuoteChart.h b/protocols/Quotes/src/QuoteChart.h
new file mode 100644
index 0000000000..1b40f428b5
--- /dev/null
+++ b/protocols/Quotes/src/QuoteChart.h
@@ -0,0 +1,12 @@
+#ifndef __39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__
+#define __39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__
+
+#ifdef CHART_IMPLEMENT
+
+#pragma once
+
+INT_PTR QuotesMenu_Chart(WPARAM wp,LPARAM lp);
+
+#endif
+
+#endif //__39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__
diff --git a/protocols/Quotes/src/QuoteInfoDlg.cpp b/protocols/Quotes/src/QuoteInfoDlg.cpp
new file mode 100644
index 0000000000..61b6fb5f11
--- /dev/null
+++ b/protocols/Quotes/src/QuoteInfoDlg.cpp
@@ -0,0 +1,350 @@
+#include "StdAfx.h"
+#include "QuoteInfoDlg.h"
+#include "EconomicRateInfo.h"
+#include "resource.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "IconLib.h"
+#include "DBUtils.h"
+#include "IQuotesProvider.h"
+#include "Locale.h"
+#include "SettingsDlg.h"
+
+// extern HANDLE g_hWindowListEditSettings;
+extern HGENMENU g_hMenuEditSettings;
+extern HGENMENU g_hMenuOpenLogFile;
+#ifdef CHART_IMPLEMENT
+extern HGENMENU g_hMenuChart;
+#endif
+extern HGENMENU g_hMenuRefresh;
+
+
+#define WINDOW_PREFIX_INFO "Quote Info"
+
+
+namespace
+{
+ HANDLE g_hContact;
+
+ inline bool IsMyContact(HANDLE hContact)
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact);
+ return (NULL != pProvider);
+ }
+
+ inline HANDLE get_contact(HWND hWnd)
+ {
+ return reinterpret_cast<HANDLE>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ }
+
+
+ bool get_fetch_time(time_t& rTime,HANDLE hContact)
+ {
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+
+ cgs.szModule=QUOTES_PROTOCOL_NAME;
+ cgs.szSetting=DB_STR_QUOTE_FETCH_TIME;
+ cgs.pValue=&dbv;
+ if(CallService(MS_DB_CONTACT_GETSETTING,reinterpret_cast<WPARAM>(hContact),reinterpret_cast<LPARAM>(&cgs))
+ || (DBVT_DWORD != dbv.type))
+ {
+ return false;
+ }
+
+ rTime = dbv.dVal;
+ return true;
+ }
+
+ INT_PTR CALLBACK QuoteInfoDlgProcImpl(HANDLE hContact,HWND hdlg,UINT msg,WPARAM wParam,LPARAM lParam)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ assert(hContact);
+
+ TranslateDialogDefault(hdlg);
+
+ tstring sDescription = GetContactName(hContact);
+ ::SetDlgItemText(hdlg,IDC_STATIC_QUOTE_NAME,sDescription.c_str());
+
+ double dRate = 0.0;
+ if(true == Quotes_DBReadDouble(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_PREV_VALUE,dRate))
+ {
+ tostringstream o;
+ o.imbue(GetSystemLocale());
+ o << dRate;
+
+ ::SetDlgItemText(hdlg,IDC_EDIT_PREVIOUS_RATE,o.str().c_str());
+ }
+
+ dRate = 0.0;
+ if(true == Quotes_DBReadDouble(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_CURR_VALUE,dRate))
+ {
+ tostringstream o;
+ o.imbue(GetSystemLocale());
+ o << dRate;
+
+ ::SetDlgItemText(hdlg,IDC_EDIT_RATE,o.str().c_str());
+ }
+
+ time_t nFetchTime;
+ if(true == get_fetch_time(nFetchTime,hContact))
+ {
+ TCHAR szTime[50];
+ if(0 == _tctime_s(szTime,50,&nFetchTime))
+ {
+ szTime[::_tcslen(szTime)-1] = _T('\0');
+ ::SetDlgItemText(hdlg,IDC_EDIT_RATE_FETCH_TIME,szTime);
+ }
+ }
+
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact);
+
+ const IQuotesProvider::CProviderInfo& pi = pProvider->GetInfo();
+ tostringstream o;
+ o << TranslateT("Info provided by") << _T(" <a href=\"") << pi.m_sURL << _T("\">") << pi.m_sName << _T("</a>");
+
+ ::SetDlgItemText(hdlg,IDC_SYSLINK_PROVIDER,o.str().c_str());
+ }
+ return TRUE;
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lParam);
+ switch(pNMHDR->code)
+ {
+ case NM_CLICK:
+ if(IDC_SYSLINK_PROVIDER == wParam)
+ {
+ PNMLINK pNMLink = reinterpret_cast<PNMLINK>(pNMHDR);
+ ::ShellExecute(hdlg,_T("open"),pNMLink->item.szUrl,NULL,NULL,SW_SHOWNORMAL);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+ }
+
+ INT_PTR CALLBACK QuoteInfoDlgProc(HWND hdlg,UINT msg,WPARAM wParam,LPARAM lParam)
+ {
+ return QuoteInfoDlgProcImpl(g_hContact,hdlg,msg,wParam,lParam);
+ }
+}
+
+int QuotesEventFunc_OnUserInfoInit(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(lp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+
+ if(false == IsMyContact(hContact))
+ {
+ return 0;
+ }
+
+ g_hContact = hContact;
+
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof( odp );
+ odp.hInstance = g_hInstance;
+
+ odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN);
+ odp.pfnDlgProc = QuoteInfoDlgProc;
+ odp.position = -2000000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_QUOTE_INFO);
+ odp.pszTitle = LPGEN("Quote");
+ UserInfo_AddPage(wp, &odp);
+ return 0;
+}
+
+
+INT_PTR QuotesMenu_EditSettings(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+ ShowSettingsDlg(hContact);
+
+ return 0;
+}
+
+namespace
+{
+ bool get_log_file(HANDLE hContact,tstring& rsLogfile)
+ {
+ rsLogfile = GetContactLogFileName(hContact);
+ return ((rsLogfile.empty()) ? false : true);
+ }
+}
+
+INT_PTR QuotesMenu_OpenLogFile(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+ tstring sLogFileName;
+ if ((true == get_log_file(hContact,sLogFileName)) && (false == sLogFileName.empty()))
+ {
+ ::ShellExecute(NULL,_T("open"),sLogFileName.c_str(),NULL,NULL,SW_SHOWNORMAL);
+ }
+
+ return 0;
+}
+
+INT_PTR QuotesMenu_RefreshContact(WPARAM wp,LPARAM lp)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact);
+ if (!pProvider)
+ {
+ return 0;
+ }
+
+ pProvider->RefreshContact(hContact);
+
+ return 0;
+}
+
+namespace
+{
+ INT_PTR CALLBACK QuoteInfoDlgProc1(HWND hdlg,UINT msg,WPARAM wParam,LPARAM lParam)
+ {
+ HANDLE hContact = NULL;
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ hContact = reinterpret_cast<HANDLE>(lParam);
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_INFO,false);
+ assert(hWL);
+ WindowList_Add(hWL,hdlg,hContact);
+
+ ::SetWindowLongPtr(hdlg,GWLP_USERDATA,reinterpret_cast<LONG>(hContact));
+ Utils_RestoreWindowPositionNoSize(hdlg,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_INFO);
+ ::ShowWindow(hdlg,SW_SHOW);
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hdlg);
+ return FALSE;
+ case WM_DESTROY:
+ {
+ HANDLE hContact = get_contact(hdlg);
+ if(hContact)
+ {
+ SetWindowLongPtr(hdlg,GWLP_USERDATA,0);
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_INFO,false);
+ assert(hWL);
+ WindowList_Remove(hWL,hdlg);
+ Utils_SaveWindowPosition(hdlg,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_INFO);
+ }
+ }
+ return FALSE;
+ case WM_COMMAND:
+ if(LOWORD(wParam) == IDOK)
+ {
+ ::DestroyWindow(hdlg);
+ return FALSE;
+ }
+
+ default:
+ hContact = get_contact(hdlg);
+ break;
+ }
+
+ return QuoteInfoDlgProcImpl(hContact,hdlg,msg,wParam,lParam);
+ }
+}
+
+int Quotes_OnContactDoubleClick(WPARAM wp,LPARAM/* lp*/)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact))
+ {
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_INFO,true);
+ assert(hWL);
+ HWND hWnd = WindowList_Find(hWL,hContact);
+ if(NULL != hWnd)
+ {
+ SetForegroundWindow(hWnd);
+ SetFocus(hWnd);
+ }
+ else if(true == IsMyContact(hContact))
+ {
+ CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_DIALOG_QUOTE_INFO_1),NULL,QuoteInfoDlgProc1,reinterpret_cast<LPARAM>(hContact));
+ }
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+namespace
+{
+ void enable_menu(HANDLE hMenu,bool bEnable)
+ {
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof( CLISTMENUITEM );
+ clmi.flags = CMIM_FLAGS;
+ if(false == bEnable)
+ {
+ clmi.flags |= /*CMIF_HIDDEN*/CMIF_GRAYED;
+ }
+
+ CallService(MS_CLIST_MODIFYMENUITEM,reinterpret_cast<WPARAM>(hMenu),reinterpret_cast<LPARAM>(&clmi));
+ }
+}
+
+int Quotes_PrebuildContactMenu(WPARAM wp,LPARAM lp)
+{
+ enable_menu(g_hMenuEditSettings,false);
+ enable_menu(g_hMenuOpenLogFile,false);
+#ifdef CHART_IMPLEMENT
+ enable_menu(g_hMenuChart,false);
+#endif
+ enable_menu(g_hMenuRefresh,false);
+
+ HANDLE hContact = reinterpret_cast<HANDLE>(wp);
+ if(NULL == hContact)
+ {
+ return 0;
+ }
+
+ enable_menu(g_hMenuEditSettings,true);
+
+ enable_menu(g_hMenuRefresh,true);
+
+ tstring sLogFileName;
+ bool bThereIsLogFile = (true == get_log_file(hContact,sLogFileName))
+ && (false == sLogFileName.empty()) && (0 == _taccess(sLogFileName.c_str(),04));
+ if(true == bThereIsLogFile)
+ {
+#ifdef CHART_IMPLEMENT
+ enable_menu(g_hMenuChart,true);
+#endif
+ enable_menu(g_hMenuOpenLogFile,true);
+ }
+
+ return 0;
+}
diff --git a/protocols/Quotes/src/QuoteInfoDlg.h b/protocols/Quotes/src/QuoteInfoDlg.h
new file mode 100644
index 0000000000..c4a1999a4c
--- /dev/null
+++ b/protocols/Quotes/src/QuoteInfoDlg.h
@@ -0,0 +1,11 @@
+#ifndef __aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__
+#define __aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__
+
+int QuotesEventFunc_OnUserInfoInit(WPARAM wp,LPARAM lp);
+INT_PTR QuotesMenu_EditSettings(WPARAM wp,LPARAM lp);
+INT_PTR QuotesMenu_OpenLogFile(WPARAM wp,LPARAM lp);
+INT_PTR QuotesMenu_RefreshContact(WPARAM wp,LPARAM lp);
+int Quotes_PrebuildContactMenu(WPARAM wp,LPARAM lp);
+int Quotes_OnContactDoubleClick(WPARAM wp,LPARAM lp);
+
+#endif //__aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__
diff --git a/protocols/Quotes/src/QuotesProviderBase.cpp b/protocols/Quotes/src/QuotesProviderBase.cpp
new file mode 100644
index 0000000000..681afb0d38
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderBase.cpp
Binary files differ
diff --git a/protocols/Quotes/src/QuotesProviderBase.h b/protocols/Quotes/src/QuotesProviderBase.h
new file mode 100644
index 0000000000..76db155f4c
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderBase.h
@@ -0,0 +1,112 @@
+#ifndef __3e6cb4ec_fc47_468f_a2c8_a77941176bc9_QuotesProviderBase_h__
+#define __3e6cb4ec_fc47_468f_a2c8_a77941176bc9_QuotesProviderBase_h__
+
+#include "iquotesprovider.h"
+#include <vector>
+#include "LightMutex.h"
+
+class CQuotesProviderBase : public IQuotesProvider
+{
+public:
+ class CQuote
+ {
+ public:
+ CQuote(const tstring& rsID = _T(""),const tstring& rsSymbol = _T(""),const tstring& rsName = _T(""))
+ : m_sSymbol(rsSymbol),m_sName(rsName),m_sID(rsID){}
+
+ const tstring& GetSymbol()const{return m_sSymbol;}
+ const tstring& GetName()const{return m_sName;}
+ const tstring& GetID()const{return m_sID;}
+
+ private:
+ tstring m_sSymbol;
+ tstring m_sName;
+ tstring m_sID;
+ };
+
+ class CQuoteSection
+ {
+ public:
+ typedef std::vector<CQuoteSection> TSections;
+ typedef std::vector<CQuote> TQuotes;
+
+ public:
+ CQuoteSection(const tstring& rsName = _T(""),const TSections& raSections = TSections(),const TQuotes& raQuotes = TQuotes())
+ : m_sName(rsName),m_aSections(raSections),m_aQuotes(raQuotes){}
+
+ const tstring& GetName()const
+ {return m_sName;}
+
+ size_t GetSectionCount()const
+ {return m_aSections.size();}
+ CQuoteSection GetSection(size_t nIndex)const
+ {return ((nIndex < m_aSections.size()) ? m_aSections[nIndex] : CQuoteSection());}
+
+ size_t GetQuoteCount()const
+ {return m_aQuotes.size();}
+ CQuote GetQuote(size_t nIndex)const
+ {return ((nIndex < m_aQuotes.size()) ? m_aQuotes[nIndex] : CQuote());}
+
+ private:
+ tstring m_sName;
+ TSections m_aSections;
+ TQuotes m_aQuotes;
+ };
+
+protected:
+ typedef std::vector<HANDLE> TContracts;
+
+public:
+ struct CXMLFileInfo;
+
+public:
+ CQuotesProviderBase();
+ ~CQuotesProviderBase();
+
+
+ const CQuoteSection& GetQuotes()const;
+// void SetSettingsEvent();
+
+ virtual bool Init();
+ virtual const CProviderInfo& GetInfo()const;
+ virtual void AddContact(HANDLE hContact);
+ virtual void DeleteContact(HANDLE hContact);
+ virtual void Run();
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+ virtual void RefreshAll();
+ virtual void RefreshContact(HANDLE hContact);
+ virtual void SetContactExtraIcon(HANDLE hContact)const;
+
+protected:
+ const tstring& GetURL()const;
+ HANDLE CreateNewContact(const tstring& rsName);
+ static bool IsOnline();
+ static void SetContactStatus(HANDLE hContact,int nNewStatus);
+ void WriteContactRate(HANDLE hContact,double dRate,const tstring& rsSymbol = _T(""));
+
+private:
+ virtual void RefreshQuotes(TContracts& anContacts) = 0;
+
+private:
+ virtual void OnEndRun();
+
+private:
+ CXMLFileInfo* GetXMLFileInfo()const;
+
+protected:
+ TContracts m_aContacts;
+ mutable CLightMutex m_cs;
+
+private:
+ typedef boost::scoped_ptr<CXMLFileInfo> TXMLFileInfoPtr;
+ mutable TXMLFileInfoPtr m_pXMLInfo;
+ HANDLE m_hEventSettingsChanged;
+ HANDLE m_hEventRefreshContact;
+ tstring m_sContactListFormat;
+ tstring m_sStatusMsgFormat;
+ tstring m_sTendencyFormat;
+ TContracts m_aRefreshingContacts;
+ bool m_bRefreshInProgress;
+};
+
+#endif //__3e6cb4ec_fc47_468f_a2c8_a77941176bc9_QuotesProviderBase_h__
diff --git a/protocols/Quotes/src/QuotesProviderDukasCopy.cpp b/protocols/Quotes/src/QuotesProviderDukasCopy.cpp
new file mode 100644
index 0000000000..a7ffc5331a
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderDukasCopy.cpp
Binary files differ
diff --git a/protocols/Quotes/src/QuotesProviderDukasCopy.h b/protocols/Quotes/src/QuotesProviderDukasCopy.h
new file mode 100644
index 0000000000..d6ec498bcf
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderDukasCopy.h
@@ -0,0 +1,38 @@
+#ifndef __93121758_68c7_4836_b571_da84dfe82b84_QuotesProviderDukasCopy_h__
+#define __93121758_68c7_4836_b571_da84dfe82b84_QuotesProviderDukasCopy_h__
+
+#include "quotesproviderbase.h"
+#include <vector>
+
+#define DB_STR_REFRESH_RATE_TYPE "RefreshRateType"
+#define DB_STR_REFRESH_RATE_VALUE "RefreshRateValue"
+#define DB_STR_DC_DISPLAY_NAME_FORMAT "DC_DisplayNameFormat"
+// #define DB_STR_DC_LOG_FILE_FORMAT "DC_LogFileFormat"
+// #define DB_STR_DC_HISTORY_FORMAT "DC_HistoryFormat"
+
+class CQuotesProviderDukasCopy : public CQuotesProviderBase
+{
+public:
+ CQuotesProviderDukasCopy();
+ ~CQuotesProviderDukasCopy();
+
+ bool WatchForQuote(const CQuote& rQuote,bool bWatch);
+ bool IsQuoteWatched(const CQuote& rQuote)const;
+
+ HANDLE GetContactByQuoteID(const tstring& rsQuoteID)const;
+// #ifdef CHART_IMPLEMENT
+// bool Chart(HANDLE hContact,const tstring& url)const;
+// #endif
+
+private:
+ //IQuotesProvider implementation
+ virtual void RefreshQuotes(TContracts& anContacts);
+ virtual void ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp);
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+
+private:
+ tstring BuildHTTPURL()const;
+
+};
+
+#endif //__93121758_68c7_4836_b571_da84dfe82b84_QuotesProviderDukasCopy_h__
diff --git a/protocols/Quotes/src/QuotesProviderFinance.cpp b/protocols/Quotes/src/QuotesProviderFinance.cpp
new file mode 100644
index 0000000000..e8b335035d
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderFinance.cpp
@@ -0,0 +1,318 @@
+#include "stdafx.h"
+#include "QuotesProviderFinance.h"
+#include "EconomicRateInfo.h"
+#include "DBUtils.h"
+#include "QuotesProviderVisitor.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "CommonOptionDlg.h"
+#include "resource.h"
+#include "WinCtrlHelper.h"
+
+void CQuotesProviderFinance::GetWatchedQuotes(TQuotes& raQuotes)const
+{
+ raQuotes.clear();
+ BOOST_FOREACH(HANDLE hContact,m_aContacts)
+ {
+ tstring sID = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID);
+ tstring sSymbol = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_SYMBOL,sID.c_str());
+ tstring sDescr = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION);
+ CQuotesProviderBase::CQuote quote(sID,sSymbol,sDescr);
+
+ raQuotes.push_back(quote);
+ }
+}
+
+namespace
+{
+ inline tstring get_quote_id(HANDLE hContact)
+ {
+ return Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID);
+ }
+
+ inline bool is_quote_id_equal(HANDLE hContact,const tstring& sID)
+ {
+ return sID == get_quote_id(hContact);
+ }
+}
+
+bool CQuotesProviderFinance::WatchForQuote(const CQuote& rQuote,bool bWatch)
+{
+ const tstring& sQuoteID = rQuote.GetID();
+ TContracts::iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(),
+ boost::bind(is_quote_id_equal,_1,sQuoteID));
+
+ if ((false == bWatch) && (i != m_aContacts.end()))
+ {
+ HANDLE hContact = *i;
+ {// for CCritSection
+ CGuard<CLightMutex> cs(m_cs);
+ m_aContacts.erase(i);
+ }
+
+ CallService(MS_DB_CONTACT_DELETE,reinterpret_cast<WPARAM>(hContact),0);
+ return true;
+ }
+ else if ((true == bWatch) && (i == m_aContacts.end()))
+ {
+ HANDLE hContact = CreateNewContact(rQuote.GetSymbol());
+ if(hContact)
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_ID,sQuoteID.c_str());
+ if(false == rQuote.GetName().empty())
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_DESCRIPTION,rQuote.GetName().c_str());
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+HANDLE CQuotesProviderFinance::GetContactByQuoteID(const tstring& rsQuoteID)const
+{
+ CGuard<CLightMutex> cs(m_cs);
+
+ TContracts::const_iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(),
+ boost::bind(std::equal_to<tstring>(),rsQuoteID,boost::bind(get_quote_id,_1)));
+ if(i != m_aContacts.end())
+ {
+ return *i;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void CQuotesProviderFinance::Accept(CQuotesProviderVisitor& visitor)const
+{
+ CQuotesProviderBase::Accept(visitor);
+ visitor.Visit(*this);
+}
+
+namespace
+{
+ inline tstring make_quote_name(const CQuotesProviderBase::CQuote& rQuote)
+ {
+ const tstring& rsDesc = rQuote.GetName();
+ return((false == rsDesc.empty()) ? rsDesc : rQuote.GetSymbol());
+ }
+
+ int add_quote_to_wnd(const CQuotesProviderBase::CQuote& rQuote,HWND hwnd)
+ {
+ tstring sName = make_quote_name(rQuote);
+ int nIndex = ::SendMessage(hwnd,LB_ADDSTRING,0,reinterpret_cast<LPARAM>(sName.c_str()));
+ if(nIndex >= 0)
+ {
+ CQuotesProviderBase::CQuote* pQuote = new CQuotesProviderBase::CQuote(rQuote);
+ if(LB_ERR == ::SendMessage(hwnd,LB_SETITEMDATA,nIndex,reinterpret_cast<LPARAM>(pQuote)))
+ {
+ delete pQuote;
+ }
+ }
+ return nIndex;
+ }
+
+// typedef CQuotesProviderFinance::TQuotes TQuotes;
+// TQuotes g_aWatchedQuotes;
+
+// inline bool cmp_quotes(const tstring& rsQuoteId,const CQuotesProviderBase::CQuote& quote)
+// {
+// return (0 == quotes_stricmp(rsQuoteId.c_str(),quote.GetID().c_str()));
+// }
+
+ CQuotesProviderBase::CQuote* get_quote_ptr_from_lb_index(HWND hwndListBox,int nIndex)
+ {
+ LRESULT lResult = ::SendMessage(hwndListBox,LB_GETITEMDATA,nIndex,0);
+ return (((LB_ERR != lResult) && (0 != lResult)) ? (reinterpret_cast<CQuotesProviderBase::CQuote*>(lResult)) : nullptr);
+ }
+
+ int is_quote_added(HWND hwndList,const tstring& rsQuoteID)
+ {
+ int cItems = ::SendMessage(hwndList,LB_GETCOUNT,0,0);
+ for(int i = 0;i < cItems;++i)
+ {
+ const CQuotesProviderBase::CQuote* pQuote = get_quote_ptr_from_lb_index(hwndList,i);
+ if ((nullptr != pQuote)
+ && ((0 == quotes_stricmp(rsQuoteID.c_str(),pQuote->GetID().c_str()))
+ || (0 == quotes_stricmp(rsQuoteID.c_str(),pQuote->GetName().c_str()))
+ || (0 == quotes_stricmp(rsQuoteID.c_str(),pQuote->GetSymbol().c_str()))))
+ {
+ return i;
+ }
+ }
+ return LB_ERR;
+ }
+
+ INT_PTR CALLBACK GoogleFinanceOptDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
+ {
+ CQuotesProviderFinance* pProvider = nullptr;
+ if(WM_INITDIALOG == message)
+ {
+ pProvider = reinterpret_cast<CQuotesProviderFinance*>(lParam);
+ SetWindowLongPtr(hDlg,GWLP_USERDATA,lParam);
+ }
+ else
+ {
+ pProvider = reinterpret_cast<CQuotesProviderFinance*>(GetWindowLongPtr(hDlg,GWLP_USERDATA));
+ }
+
+ CCommonDlgProcData d(pProvider);
+ CommonOptionDlgProc(hDlg,message,wParam,lParam,d);
+
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hDlg);
+
+ CQuotesProviderFinance::TQuotes aQuotes;
+ pProvider->GetWatchedQuotes(aQuotes);
+
+ HWND hwndList = GetDlgItem(hDlg,IDC_LIST_RATES);
+ std::for_each(aQuotes.begin(),aQuotes.end(),
+ boost::bind(add_quote_to_wnd,_1,hwndList));
+
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_ADD),FALSE);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_REMOVE),FALSE);
+ }
+ return (TRUE);
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_EDIT_QUOTE:
+ if(EN_CHANGE == HIWORD(wParam))
+ {
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_ADD),GetWindowTextLength(GetDlgItem(hDlg,IDC_EDIT_QUOTE)) > 0);
+ }
+ return (TRUE);
+ case IDC_BUTTON_ADD:
+ if(BN_CLICKED == HIWORD(wParam))
+ {
+ HWND hEdit = GetDlgItem(hDlg,IDC_EDIT_QUOTE);
+ tstring sQuoteSymbol = get_window_text(hEdit);
+ assert(false == sQuoteSymbol.empty());
+ HWND hwndList = GetDlgItem(hDlg,IDC_LIST_RATES);
+ if(LB_ERR == is_quote_added(hwndList,sQuoteSymbol))
+ {
+ CQuotesProviderBase::CQuote quote(sQuoteSymbol,sQuoteSymbol);
+ if(add_quote_to_wnd(quote,hwndList) >= 0)
+ {
+ SetDlgItemText(hDlg,IDC_EDIT_QUOTE,_T(""));
+ SetFocus(hEdit);
+ PropSheet_Changed(::GetParent(hDlg),hDlg);
+ }
+ else
+ {
+ ::MessageBeep(MB_ICONERROR);
+ }
+ }
+ }
+ return (TRUE);
+ case IDC_BUTTON_REMOVE:
+ if(BN_CLICKED == HIWORD(wParam))
+ {
+ HWND hWnd = ::GetDlgItem(hDlg,IDC_LIST_RATES);
+ int nSel = ::SendMessage(hWnd,LB_GETCURSEL,0,0);
+ if(LB_ERR != nSel)
+ {
+ CQuotesProviderBase::CQuote* pQuote = get_quote_ptr_from_lb_index(hWnd,nSel);
+ delete pQuote;
+ if(LB_ERR != ::SendMessage(hWnd,LB_DELETESTRING,nSel,0))
+ {
+ PropSheet_Changed(::GetParent(hDlg),hDlg);
+ }
+ }
+
+ nSel = ::SendMessage(hWnd,LB_GETCURSEL,0,0);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_REMOVE),(LB_ERR != nSel));
+ }
+ return (TRUE);
+ case IDC_LIST_RATES:
+ if(CBN_SELCHANGE == HIWORD(wParam))
+ {
+ int nSel = ::SendMessage(::GetDlgItem(hDlg,IDC_LIST_RATES),LB_GETCURSEL,0,0);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_REMOVE),(LB_ERR != nSel));
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lParam);
+ switch(pNMHDR->code)
+ {
+ case PSN_APPLY:
+ if(pProvider)
+ {
+ CQuotesProviderFinance::TQuotes aTemp;
+ pProvider->GetWatchedQuotes(aTemp);
+
+ typedef std::vector<const CQuotesProviderBase::CQuote*> TQuotesPtr;
+ TQuotesPtr apCurrent;
+ HWND hwndListBox = GetDlgItem(hDlg,IDC_LIST_RATES);
+ int cItems = ::SendMessage(hwndListBox,LB_GETCOUNT,0,0);
+ for(int i = 0;i < cItems;++i)
+ {
+ const CQuotesProviderBase::CQuote* pQuote = get_quote_ptr_from_lb_index(hwndListBox,i);
+ if(pQuote)
+ {
+ apCurrent.push_back(pQuote);
+ }
+ }
+
+ std::for_each(aTemp.begin(),aTemp.end(),
+ [&apCurrent,pProvider](const CQuotesProviderBase::CQuote& quote)
+ {
+ if(apCurrent.end() == std::find_if(apCurrent.begin(),apCurrent.end(),
+ [&quote](const CQuotesProviderBase::CQuote* pQuote){return 0 == quotes_stricmp(pQuote->GetID().c_str(),quote.GetID().c_str());}))
+ {
+ pProvider->WatchForQuote(quote,false);
+ }
+ });
+
+ std::for_each(apCurrent.begin(),apCurrent.end(),
+ [&aTemp,pProvider](const CQuotesProviderBase::CQuote* pQuote)
+ {
+ if(aTemp.end() ==
+ std::find_if(aTemp.begin(),aTemp.end(),
+ [pQuote](const CQuotesProviderBase::CQuote& quote){return 0 == quotes_stricmp(pQuote->GetID().c_str(),quote.GetID().c_str());}))
+ {
+ pProvider->WatchForQuote(*pQuote,true);
+ }
+
+ });
+
+ pProvider->RefreshAll();
+ }
+
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+ case WM_DESTROY:
+ HWND hwndListBox = GetDlgItem(hDlg,IDC_LIST_RATES);
+ int cItems = ::SendMessage(hwndListBox,LB_GETCOUNT,0,0);
+ for(int i = 0;i < cItems;++i)
+ {
+ const CQuotesProviderBase::CQuote* pQuote = get_quote_ptr_from_lb_index(hwndListBox,i);
+ delete pQuote;
+ }
+ return (FALSE);
+ }
+ return (FALSE);
+ }
+}
+
+void CQuotesProviderFinance::ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp)
+{
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_OPT_FINANCE);
+ odp.pfnDlgProc = GoogleFinanceOptDlgProc;
+ odp.dwInitParam = reinterpret_cast<DWORD>(static_cast<CQuotesProviderFinance*>(this));
+ odp.ptszTab = const_cast<LPTSTR>(GetInfo().m_sName.c_str());
+ Options_AddPage(wp, &odp);
+}
diff --git a/protocols/Quotes/src/QuotesProviderFinance.h b/protocols/Quotes/src/QuotesProviderFinance.h
new file mode 100644
index 0000000000..f63077071d
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderFinance.h
@@ -0,0 +1,21 @@
+#ifndef __95A13A68_0DF0_43FA_B6C1_81D83AED59AA_QuotesProviderFinance_h__
+#define __95A13A68_0DF0_43FA_B6C1_81D83AED59AA_QuotesProviderFinance_h__
+
+#include "QuotesProviderBase.h"
+
+class CQuotesProviderFinance : public CQuotesProviderBase
+{
+public:
+ typedef std::vector<CQuotesProviderBase::CQuote> TQuotes;
+
+public:
+ void GetWatchedQuotes(TQuotes& raQuotes)const;
+ bool WatchForQuote(const CQuote& rQuote,bool bWatch);
+ HANDLE GetContactByQuoteID(const tstring& rsQuoteID)const;
+
+protected:
+ virtual void ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp);
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+};
+
+#endif //__95A13A68_0DF0_43FA_B6C1_81D83AED59AA_QuotesProviderFinance_h__ \ No newline at end of file
diff --git a/protocols/Quotes/src/QuotesProviderGoogle.cpp b/protocols/Quotes/src/QuotesProviderGoogle.cpp
new file mode 100644
index 0000000000..c2b30a9a6a
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderGoogle.cpp
@@ -0,0 +1,543 @@
+#include "StdAfx.h"
+#include "QuotesProviderGoogle.h"
+#include "resource.h"
+#include "HTTPSession.h"
+#include "Log.h"
+#include "DBUtils.h"
+#include "EconomicRateInfo.h"
+#include "ModuleInfo.h"
+#include "QuotesProviders.h"
+#include "IHTMLParser.h"
+#include "IHTMLEngine.h"
+#include "CommonOptionDlg.h"
+#include "QuotesProviderVisitor.h"
+
+CQuotesProviderGoogle::CQuotesProviderGoogle()
+{
+}
+
+CQuotesProviderGoogle::~CQuotesProviderGoogle()
+{
+}
+
+namespace
+{
+ inline tstring make_contact_name(const tstring& rsSymbolFrom,const tstring& rsSymbolTo)
+ {
+ tostringstream o;
+ o << rsSymbolFrom << _T("/") << rsSymbolTo;
+ return o.str();
+ }
+
+ inline bool is_rate_watched(HANDLE hContact,
+ const CQuotesProviderBase::CQuote& from,
+ const CQuotesProviderBase::CQuote& to)
+ {
+ tstring sFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID);
+ tstring sTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID);
+ return ((0 == quotes_stricmp(from.GetID().c_str(),sFrom.c_str()))
+ && (0 == quotes_stricmp(to.GetID().c_str(),sTo.c_str())));
+ }
+}
+
+bool CQuotesProviderGoogle::WatchForRate(const CRateInfo& ri,
+ bool bWatch)
+{
+ TContracts::const_iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(),
+ boost::bind(is_rate_watched,_1,ri.m_from,ri.m_to));
+ if ((true == bWatch) && (i == m_aContacts.end()))
+ {
+ tstring sName = make_contact_name(ri.m_from.GetSymbol(),ri.m_to.GetSymbol());
+ HANDLE hContact = CreateNewContact(sName);
+ if(hContact)
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID,ri.m_from.GetID().c_str());
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID,ri.m_to.GetID().c_str());
+ if(false == ri.m_from.GetName().empty())
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_DESCRIPTION,ri.m_from.GetName().c_str());
+ }
+ if(false == ri.m_to.GetName().empty())
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_DESCRIPTION,ri.m_to.GetName().c_str());
+ }
+
+ return true;
+ }
+ }
+ else if ((false == bWatch) && (i != m_aContacts.end()))
+ {
+ HANDLE hContact = *i;
+ {// for CCritSection
+ CGuard<CLightMutex> cs(m_cs);
+ m_aContacts.erase(i);
+ }
+
+ CallService(MS_DB_CONTACT_DELETE,reinterpret_cast<WPARAM>(hContact),0);
+ return true;
+ }
+
+ return false;
+}
+
+size_t CQuotesProviderGoogle::GetWatchedRateCount()const
+{
+ return m_aContacts.size();
+}
+
+bool CQuotesProviderGoogle::GetWatchedRateInfo(size_t nIndex,CRateInfo& rRateInfo)
+{
+ if(nIndex < m_aContacts.size())
+ {
+ HANDLE hContact = m_aContacts[nIndex];
+ tstring sSymbolFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID);
+ tstring sSymbolTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID);
+ tstring sDescFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_DESCRIPTION);
+ tstring sDescTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_DESCRIPTION);
+
+ rRateInfo.m_from = CQuote(sSymbolFrom,sSymbolFrom,sDescFrom);
+ rRateInfo.m_to = CQuote(sSymbolTo,sSymbolTo,sDescTo);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+namespace
+{
+ tstring build_url(const tstring& rsURL,const tstring& from,const tstring& to,double dAmount)
+ {
+ tostringstream o;
+ o << rsURL << _T("?a=") << std::fixed << dAmount << _T("&from=") << from << _T("&to=") << to;
+ return o.str();
+ }
+ tstring build_url(HANDLE hContact,const tstring& rsURL,double dAmount = 1.0)
+ {
+ tstring sFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID);
+ tstring sTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID);
+ return build_url(rsURL,sFrom,sTo,dAmount);
+ }
+
+ typedef IHTMLNode::THTMLNodePtr THTMLNodePtr;
+
+ bool parse_html_node(const THTMLNodePtr& pNode,double& rdRate)
+ {
+ tstring sID = pNode->GetAttribute(_T("id"));
+ if ((false == sID.empty()) && (0 == quotes_stricmp(sID.c_str(),_T("currency_converter_result"))))
+ {
+ size_t cChild = pNode->GetChildCount();
+// assert(1 == cChild);
+ if(cChild > 0)
+ {
+ THTMLNodePtr pChild = pNode->GetChildPtr(0);
+ tstring sRate = pChild->GetText();
+
+ tistringstream input(sRate);
+ input >> rdRate;
+
+ return ((false == input.bad()) && (false == input.fail()));
+ }
+ }
+ else
+ {
+ size_t cChild = pNode->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ THTMLNodePtr pChild = pNode->GetChildPtr(i);
+ if(pChild && (true == parse_html_node(pChild,rdRate)))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool parse_responce(const tstring& rsHTML,double& rdRate)
+ {
+ IHTMLEngine::THTMLParserPtr pHTMLParser = CModuleInfo::GetHTMLEngine()->GetParserPtr();
+ THTMLNodePtr pRoot = pHTMLParser->ParseString(rsHTML);
+ if(pRoot)
+ {
+ return parse_html_node(pRoot,rdRate);
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
+
+void CQuotesProviderGoogle::RefreshQuotes(TContracts& anContacts)
+{
+ CHTTPSession http;
+ tstring sURL = GetURL();
+
+ bool bUseExtendedStatus = CModuleInfo::GetInstance().GetExtendedStatusFlag();
+
+ for(TContracts::const_iterator i = anContacts.begin();i != anContacts.end() && IsOnline();++i)
+ {
+ HANDLE hContact = *i;
+
+ if(bUseExtendedStatus)
+ {
+ SetContactStatus(hContact,ID_STATUS_OCCUPIED);
+ }
+
+ tstring sFullURL = build_url(hContact,sURL);
+// LogIt(Info,sFullURL);
+ if ((true == http.OpenURL(sFullURL)) && (true == IsOnline()))
+ {
+ tstring sHTML;
+ if ((true == http.ReadResponce(sHTML)) && (true == IsOnline()))
+ {
+// LogIt(Info,sHTML);
+
+ double dRate = 0.0;
+ if ((true == parse_responce(sHTML,dRate)) && (true == IsOnline()))
+ {
+ WriteContactRate(hContact,dRate);
+ continue;
+ }
+ }
+ }
+
+ SetContactStatus(hContact,ID_STATUS_NA);
+ }
+}
+
+namespace
+{
+ inline tstring make_quote_name(const CQuotesProviderGoogle::CQuote& rQuote)
+ {
+ const tstring& rsDesc = rQuote.GetName();
+ return((false == rsDesc.empty()) ? rsDesc : rQuote.GetSymbol());
+ }
+
+ CQuotesProviderGoogle* get_google_provider()
+ {
+ CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapQuotesProviders = pProviders->GetProviders();
+ for(CQuotesProviders::TQuotesProviders::const_iterator i = rapQuotesProviders.begin();i != rapQuotesProviders.end();++i)
+ {
+ const CQuotesProviders::TQuotesProviderPtr& pProvider = *i;
+ CQuotesProviderGoogle* pGoogle = dynamic_cast<CQuotesProviderGoogle*>(pProvider.get());
+ if(pGoogle)
+ {
+ return pGoogle;
+ }
+ }
+
+ assert(!"We should never get here!");
+ return NULL;
+ }
+
+ CQuotesProviderGoogle::CQuoteSection get_quotes()
+ {
+ const CQuotesProviderGoogle* pProvider = get_google_provider();
+ if(pProvider)
+ {
+ const CQuotesProviderGoogle::CQuoteSection& rQuotes = pProvider->GetQuotes();
+ if(rQuotes.GetSectionCount() > 0)
+ {
+ return rQuotes.GetSection(0);
+ }
+ }
+
+ return CQuotesProviderGoogle::CQuoteSection();
+ }
+
+ tstring make_rate_name(const CQuotesProviderGoogle::CQuote& rFrom,
+ const CQuotesProviderGoogle::CQuote& rTo)
+ {
+ if ((false == rFrom.GetName().empty()) && (false == rTo.GetName().empty()))
+ {
+ return make_contact_name(rFrom.GetName(),rTo.GetName());
+ }
+ else
+ {
+ return make_contact_name(rFrom.GetSymbol(),rTo.GetSymbol());
+ }
+ }
+
+ typedef std::vector<CQuotesProviderGoogle::CRateInfo> TWatchedRates;
+ TWatchedRates g_aWatchedRates;
+
+ bool is_equal_rate(const CQuotesProviderGoogle::CRateInfo& riL,const CQuotesProviderGoogle::CRateInfo& riR)
+ {
+ return ((0 == quotes_stricmp(riL.m_from.GetID().c_str(),riR.m_from.GetID().c_str()))
+ && ((0 == quotes_stricmp(riL.m_to.GetID().c_str(),riR.m_to.GetID().c_str()))));
+ }
+
+ INT_PTR CALLBACK GoogleOptDlgProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam)
+ {
+ CQuotesProviderGoogle* pProvider = get_google_provider();
+
+ CCommonDlgProcData d(pProvider);
+ CommonOptionDlgProc(hdlg,message,wParam,lParam,d);
+
+ switch(message)
+ {
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNMHDR = reinterpret_cast<LPNMHDR>(lParam);
+ switch(pNMHDR->code)
+ {
+ case PSN_APPLY:
+ {
+ if(pProvider)
+ {
+ TWatchedRates aTemp(g_aWatchedRates);
+ TWatchedRates aRemove;
+ size_t cWatchedRates = pProvider->GetWatchedRateCount();
+ for(size_t i = 0;i < cWatchedRates;++i)
+ {
+ CQuotesProviderGoogle::CRateInfo ri;
+ if(true == pProvider->GetWatchedRateInfo(i,ri))
+ {
+ TWatchedRates::iterator it =
+ std::find_if(aTemp.begin(),aTemp.end(),
+ boost::bind(is_equal_rate,_1,boost::cref(ri)));
+ if(it == aTemp.end())
+ {
+ aRemove.push_back(ri);
+ }
+ else
+ {
+ aTemp.erase(it);
+ }
+ }
+ }
+
+ std::for_each(aRemove.begin(),aRemove.end(),boost::bind(&CQuotesProviderGoogle::WatchForRate,pProvider,_1,false));
+ std::for_each(aTemp.begin(),aTemp.end(),boost::bind(&CQuotesProviderGoogle::WatchForRate,pProvider,_1,true));
+
+ pProvider->RefreshAll();
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hdlg);
+
+ g_aWatchedRates.clear();
+
+ HWND hcbxFrom = ::GetDlgItem(hdlg,IDC_COMBO_CONVERT_FROM);
+ HWND hcbxTo = ::GetDlgItem(hdlg,IDC_COMBO_CONVERT_INTO);
+
+ const CQuotesProviderGoogle::CQuoteSection& rSection = get_quotes();
+ size_t cQuotes = rSection.GetQuoteCount();
+ for(size_t i = 0;i < cQuotes;++i)
+ {
+ const CQuotesProviderGoogle::CQuote& rQuote = rSection.GetQuote(i);
+ tstring sName = make_quote_name(rQuote);
+ LPCTSTR pszName = sName.c_str();
+ ::SendMessage(hcbxFrom,CB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszName));
+ ::SendMessage(hcbxTo,CB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszName));
+ }
+
+ CQuotesProviderGoogle* pProvider = get_google_provider();
+ if(pProvider)
+ {
+ size_t cWatchedRates = pProvider->GetWatchedRateCount();
+ for(size_t i = 0;i < cWatchedRates;++i)
+ {
+ CQuotesProviderGoogle::CRateInfo ri;
+ if(true == pProvider->GetWatchedRateInfo(i,ri))
+ {
+ g_aWatchedRates.push_back(ri);
+ tstring sRate = make_rate_name(ri.m_from,ri.m_to);
+ LPCTSTR pszRateName = sRate.c_str();
+ ::SendMessage(::GetDlgItem(hdlg,IDC_LIST_RATES),LB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszRateName));
+ }
+ }
+ }
+
+ ::EnableWindow(::GetDlgItem(hdlg,IDC_BUTTON_ADD),FALSE);
+ ::EnableWindow(::GetDlgItem(hdlg,IDC_BUTTON_REMOVE),FALSE);
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+ switch(LOWORD(wParam))
+ {
+ case IDC_COMBO_REFRESH_RATE:
+ break;
+ case IDC_COMBO_CONVERT_FROM:
+ case IDC_COMBO_CONVERT_INTO:
+ {
+ int nFrom = static_cast<int>(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0));
+ int nTo = static_cast<int>(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_INTO),CB_GETCURSEL,0,0));
+ bool bEnableAddButton = ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo));
+ EnableWindow(GetDlgItem(hdlg,IDC_BUTTON_ADD),bEnableAddButton);
+ }
+ break;
+ case IDC_LIST_RATES:
+ {
+ int nSel = ::SendMessage(::GetDlgItem(hdlg,IDC_LIST_RATES),LB_GETCURSEL,0,0);
+ ::EnableWindow(::GetDlgItem(hdlg,IDC_BUTTON_REMOVE),(LB_ERR != nSel));
+ }
+ break;
+ }
+ break;
+ case BN_CLICKED:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BUTTON_ADD:
+ {
+ size_t nFrom = static_cast<size_t>(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0));
+ size_t nTo = static_cast<size_t>(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_INTO),CB_GETCURSEL,0,0));
+ if ((CB_ERR != nFrom) && (CB_ERR != nTo) && (nFrom != nTo))
+ {
+ const CQuotesProviderGoogle::CQuoteSection& rSection = get_quotes();
+ size_t cQuotes = rSection.GetQuoteCount();
+ if ((nFrom < cQuotes) && (nTo < cQuotes))
+ {
+ CQuotesProviderGoogle::CRateInfo ri;
+ ri.m_from = rSection.GetQuote(nFrom);
+ ri.m_to = rSection.GetQuote(nTo);
+
+ g_aWatchedRates.push_back(ri);
+
+ tstring sRate = make_rate_name(ri.m_from,ri.m_to);
+ LPCTSTR pszRateName = sRate.c_str();
+ ::SendMessage(::GetDlgItem(hdlg,IDC_LIST_RATES),LB_ADDSTRING,0,reinterpret_cast<LPARAM>(pszRateName));
+ PropSheet_Changed(::GetParent(hdlg),hdlg);
+ }
+ }
+ }
+ break;
+ case IDC_BUTTON_REMOVE:
+ {
+ HWND hWnd = ::GetDlgItem(hdlg,IDC_LIST_RATES);
+ int nSel = ::SendMessage(hWnd,LB_GETCURSEL,0,0);
+ if(LB_ERR != nSel)
+ {
+ if ((LB_ERR != ::SendMessage(hWnd, LB_DELETESTRING,nSel,0))
+ && (nSel < static_cast<int>(g_aWatchedRates.size())))
+ {
+
+ TWatchedRates::iterator i = g_aWatchedRates.begin();
+ std::advance(i,nSel);
+ g_aWatchedRates.erase(i);
+ PropSheet_Changed(::GetParent(hdlg),hdlg);
+ }
+ }
+
+ nSel = ::SendMessage(hWnd,LB_GETCURSEL,0,0);
+ ::EnableWindow(::GetDlgItem(hdlg,IDC_BUTTON_REMOVE),(LB_ERR != nSel));
+ }
+ break;
+ }
+ break;
+// case LBN_SELCHANGE:
+// switch(LOWORD(lParam))
+// {
+// case IDC_LIST_RATES:
+// {
+// int nSel = ::SendMessage(::GetDlgItem(hdlg,IDC_LIST_RATES),LB_GETCURSEL,0,0);
+// ::EnableWindow(::GetDlgItem(hdlg,IDC_BUTTON_REMOVE),(-1 != nSel));
+// }
+// }
+// break;
+ }
+ break;
+
+ }
+
+ return FALSE;
+ }
+}
+
+void CQuotesProviderGoogle::ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp)
+{
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_OPT_GOOGLE);
+ odp.pfnDlgProc = GoogleOptDlgProc;
+// #if MIRANDA_VER >= 0x0600
+ //odp.ptszTab = TranslateTS(const_cast<LPTSTR>(GetInfo().m_sName.c_str()));
+ odp.ptszTab = const_cast<LPTSTR>(GetInfo().m_sName.c_str());
+// #else
+// tostringstream o;
+// o << TranslateTS(QUOTES_PROTOCOL_NAME) << _T(" - ") << TranslateTS(GetInfo().m_sName.c_str());
+// tstring sTitle = o.str();
+// odp.ptszTitle = TranslateTS(const_cast<LPTSTR>(sTitle.c_str()));
+// #endif
+ Options_AddPage(wp, &odp);
+}
+
+void CQuotesProviderGoogle::Accept(CQuotesProviderVisitor& visitor)const
+{
+ CQuotesProviderBase::Accept(visitor);
+ visitor.Visit(*this);
+}
+
+double CQuotesProviderGoogle::Convert(double dAmount,const CQuote& from,const CQuote& to)const
+{
+ tstring sFullURL = build_url(GetURL(),from.GetID(),to.GetID(),dAmount);
+// LogIt(Info,sFullURL);
+
+ CHTTPSession http;
+ if ((true == http.OpenURL(sFullURL)))
+ {
+ tstring sHTML;
+ if ((true == http.ReadResponce(sHTML)))
+ {
+// LogIt(Info,sHTML);
+
+ double dResult = 0.0;
+ if ((true == parse_responce(sHTML,dResult)))
+ {
+ return dResult;
+ }
+ else
+ {
+ throw std::runtime_error(Translate("Error occurred during html parsing."));
+ }
+ }
+ else
+ {
+ throw std::runtime_error(Translate("Error occurred during site access."));
+ }
+ }
+ else
+ {
+ throw std::runtime_error(Translate("Error occurred during site access."));
+ }
+
+ return 0.0;
+}
+
+namespace
+{
+ bool is_equal_ids(HANDLE hContact,const tstring& rsFromID,const tstring& rsToID)
+ {
+ tstring sFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID);
+ tstring sTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID);
+ return ((0 == quotes_stricmp(rsFromID.c_str(),sFrom.c_str()))
+ && (0 == quotes_stricmp(rsToID.c_str(),sTo.c_str())));
+ }
+}
+
+HANDLE CQuotesProviderGoogle::GetContactByID(const tstring& rsFromID,const tstring& rsToID)const
+{
+ CGuard<CLightMutex> cs(m_cs);
+
+ TContracts::const_iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(),
+ boost::bind(is_equal_ids,_1,boost::cref(rsFromID),boost::cref(rsToID)));
+ if(i != m_aContacts.end())
+ {
+ return *i;
+ }
+ else
+ {
+ return NULL;
+ }
+}
diff --git a/protocols/Quotes/src/QuotesProviderGoogle.h b/protocols/Quotes/src/QuotesProviderGoogle.h
new file mode 100644
index 0000000000..4289861178
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderGoogle.h
@@ -0,0 +1,42 @@
+#ifndef __c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__
+#define __c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__
+
+#include "quotesproviderBase.h"
+
+#define DB_STR_FROM_ID "FromID"
+#define DB_STR_TO_ID "ToID"
+#define DB_STR_FROM_DESCRIPTION "FromDesc"
+#define DB_STR_TO_DESCRIPTION "ToDesc"
+#define DB_STR_GOOGLE_REFRESH_RATE_TYPE "Google_RefreshRateType"
+#define DB_STR_GOOGLE_REFRESH_RATE_VALUE "Google_RefreshRateValue"
+#define DB_STR_GOOGLE_DISPLAY_NAME_FORMAT "Google_DspNameFrmt"
+// #define DB_STR_GOOGLE_LOG_FILE_FORMAT "Google_LogFileFormat"
+// #define DB_STR_GOOGLE_HISTORY_FORMAT "Google_HistoryFormat"
+
+class CQuotesProviderGoogle : public CQuotesProviderBase
+{
+public:
+ struct CRateInfo
+ {
+ CQuotesProviderBase::CQuote m_from;
+ CQuotesProviderBase::CQuote m_to;
+ };
+public:
+ CQuotesProviderGoogle();
+ ~CQuotesProviderGoogle();
+
+ bool WatchForRate(const CRateInfo& ri,bool bWatch);
+ size_t GetWatchedRateCount()const;
+ bool GetWatchedRateInfo(size_t nIndex,CRateInfo& rRateInfo);
+
+ HANDLE GetContactByID(const tstring& rsFromID,const tstring& rsToID)const;
+
+ double Convert(double dAmount,const CQuote& from,const CQuote& to)const;
+
+private:
+ virtual void RefreshQuotes(TContracts& anContacts);
+ virtual void ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp);
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+};
+
+#endif //__c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__
diff --git a/protocols/Quotes/src/QuotesProviderGoogleFinance.cpp b/protocols/Quotes/src/QuotesProviderGoogleFinance.cpp
new file mode 100644
index 0000000000..8a129b6b8b
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderGoogleFinance.cpp
@@ -0,0 +1,366 @@
+#include "StdAfx.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "QuotesProviderVisitor.h"
+#include "EconomicRateInfo.h"
+#include "DBUtils.h"
+#include "resource.h"
+#include "ModuleInfo.h"
+// #include "QuotesProviders.h"
+// #include "CommonOptionDlg.h"
+// #include "WinCtrlHelper.h"
+#include "IHTMLParser.h"
+#include "IHTMLEngine.h"
+#include "HTTPSession.h"
+#include "Log.h"
+#include "Locale.h"
+
+CQuotesProviderGoogleFinance::CQuotesProviderGoogleFinance()
+{
+}
+
+CQuotesProviderGoogleFinance::~CQuotesProviderGoogleFinance()
+{
+}
+
+namespace
+{
+ tstring build_url(HANDLE hContact,const tstring& rsURL)
+ {
+ tostringstream o;
+ o << rsURL << _T("?q=") << Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID);
+ return o.str();
+ }
+
+ struct CGoogleInfo
+ {
+ enum
+ {
+ giRate = 0x0001,
+ giOpen = 0x0002,
+ giPercentChangeAfterHours = 0x0004,
+ giPercentChangeToYesterdayClose = 0x0008
+ };
+ CGoogleInfo()
+ : m_dRate(0.0),m_dOpenValue(0.0),m_dPercentChangeAfterHours(0.0),m_dPercentChangeToYersterdayClose(0.0),m_nFlags(0){}
+// tstring m_sCmpID;
+ tstring m_sCmpName;
+ double m_dRate;
+ double m_dOpenValue;
+ double m_dPercentChangeAfterHours;
+ double m_dPercentChangeToYersterdayClose;
+
+// tstring m_sRateID;
+// tstring m_sDiffID;
+ byte m_nFlags;
+ };
+
+ tstring make_rate_id_value(const tstring& rsCmpID,int nFlags)
+ {
+ tostringstream o;
+ o << _T("ref_") << rsCmpID;
+ switch(nFlags)
+ {
+ default:
+ assert(!"Unknown type of value");
+ case CGoogleInfo::giRate:
+ o << _T("_l");
+ break;
+ case CGoogleInfo::giPercentChangeAfterHours:
+ o << _T("_ecp");
+ break;
+ case CGoogleInfo::giPercentChangeToYesterdayClose:
+ o << _T("_cp");
+ break;
+ }
+
+ return o.str();
+ }
+
+ tstring get_var_value(const tstring& rsHTML,LPCTSTR pszVarName,size_t cVarNameLength)
+ {
+ tstring sResult;
+ tstring::size_type n = rsHTML.find(pszVarName);
+ if(tstring::npos != n)
+ {
+ size_t cLengthHTML = rsHTML.size();
+ for(size_t i = n + cVarNameLength;i < cLengthHTML;++i)
+ {
+ TCHAR c = rsHTML[i];
+ if(_T(';') == c)
+ {
+ break;
+ }
+ else
+ {
+ sResult.push_back(c);
+ }
+ }
+ }
+
+ return sResult;
+ }
+
+ tstring get_company_id(const tstring& rsHTML)
+ {
+ static LPCTSTR pszVarName = _T("setCompanyId(");
+ static size_t cVarNameLength = _tcslen(pszVarName);
+
+ tstring sResult;
+ tstring::size_type n = rsHTML.find(pszVarName);
+ if(tstring::npos != n)
+ {
+ size_t cLengthHTML = rsHTML.size();
+ for(size_t i = n + cVarNameLength;i < cLengthHTML;++i)
+ {
+ TCHAR c = rsHTML[i];
+ if(_T(')') == c)
+ {
+ break;
+ }
+ else
+ {
+ sResult.push_back(c);
+ }
+ }
+ }
+ return sResult;
+// return get_var_value(rsHTML,pszVarName,cVarNameLength);
+ }
+
+ tstring get_company_name(const tstring& rsHTML)
+ {
+ static LPCTSTR pszVarName = _T("var _companyName = ");
+ static size_t cVarNameLength = _tcslen(pszVarName);
+
+ tstring s = get_var_value(rsHTML,pszVarName,cVarNameLength);
+ if(s.size() > 0 && _T('\'') == s[0])
+ {
+ s.erase(s.begin());
+ }
+
+ if(s.size() > 0 && _T('\'') == s[s.size()-1])
+ {
+ s.erase(s.rbegin().base()-1);
+ }
+
+ return s;
+ }
+
+ bool get_double_value(const tstring& rsText,double& rdValue)
+ {
+ tistringstream input(rsText);
+ input.imbue(std::locale("English_United States.1252"));
+ input >> rdValue;
+
+ if ((true == input.bad()) || (true == input.fail()))
+ {
+ tistringstream inputSys(rsText);
+ input.imbue(GetSystemLocale());
+ input >> rdValue;
+ return (false == inputSys.bad()) && (false == inputSys.fail());
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ bool get_rate(const IHTMLNode::THTMLNodePtr& pRate,CGoogleInfo& rInfo)
+ {
+ tstring sRate = pRate->GetText();
+
+ if(true == get_double_value(sRate,rInfo.m_dRate))
+ {
+ rInfo.m_nFlags |= CGoogleInfo::giRate;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool get_inline_data(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo)
+ {
+ size_t cChild = pNode->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IHTMLNode::THTMLNodePtr pChild = pNode->GetChildPtr(i);
+ size_t c = pChild->GetChildCount();
+ assert(2 == c);
+ if(c >= 2)
+ {
+ IHTMLNode::THTMLNodePtr pName = pChild->GetChildPtr(0);
+
+ tstring sName = pName->GetText();
+ if(0 == quotes_stricmp(sName.c_str(),_T("Open")))
+ {
+ IHTMLNode::THTMLNodePtr pValue = pChild->GetChildPtr(1);
+ tstring sValue = pValue->GetText();
+ if(true == get_double_value(sValue,rInfo.m_dOpenValue))
+ {
+ rInfo.m_nFlags |= CGoogleInfo::giOpen;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool get_dif_value(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo,int nItem)
+ {
+ tstring sDiff = pNode->GetText();
+ // this value is in brackets and it has percentage sign.
+ // Remove these symbols.
+ for(tstring::iterator i = sDiff.begin();i != sDiff.end();)
+ {
+ TCHAR s = *i;
+ if(_T('(') == s || _T(')') == s || _T('%') == s)
+ {
+ i = sDiff.erase(i);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ double* pValue = NULL;
+ switch(nItem)
+ {
+ case CGoogleInfo::giPercentChangeAfterHours:
+ pValue = &rInfo.m_dPercentChangeAfterHours;
+ break;
+ case CGoogleInfo::giPercentChangeToYesterdayClose:
+ pValue = &rInfo.m_dPercentChangeToYersterdayClose;
+ break;
+ }
+
+ assert(pValue);
+
+ if ((pValue) && (true == get_double_value(sDiff,*pValue)))
+ {
+ rInfo.m_nFlags |= nItem;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+ bool parse_responce(const tstring& rsHTML,CGoogleInfo& rInfo)
+ {
+ IHTMLEngine::THTMLParserPtr pHTMLParser = CModuleInfo::GetHTMLEngine()->GetParserPtr();
+ IHTMLNode::THTMLNodePtr pRoot = pHTMLParser->ParseString(rsHTML);
+ if(pRoot)
+ {
+ tstring sCmpID = get_company_id(rsHTML);
+ if(false == sCmpID.empty())
+ {
+ tstring sRateID = make_rate_id_value(sCmpID,CGoogleInfo::giRate);
+ IHTMLNode::THTMLNodePtr pRate = pRoot->GetElementByID(sRateID);
+ if(pRate && get_rate(pRate,rInfo))
+ {
+ rInfo.m_sCmpName = get_company_name(rsHTML);
+
+ IHTMLNode::THTMLNodePtr pInline = pRoot->GetElementByID(_T("snap-data"));
+ if(pInline)
+ {
+ get_inline_data(pInline,rInfo);
+ }
+
+ tstring sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeAfterHours);
+ IHTMLNode::THTMLNodePtr pDiff = pRoot->GetElementByID(sDiffID);
+ if(pDiff)
+ {
+ get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeAfterHours);
+ }
+
+ sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeToYesterdayClose);
+ pDiff = pRoot->GetElementByID(sDiffID);
+ if(pDiff)
+ {
+ get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeToYesterdayClose);
+ }
+
+ return true;
+ }
+
+ //return (true == parse_html_node(pRoot,rInfo));
+ }
+ }
+
+ return false;
+ }
+}
+
+void CQuotesProviderGoogleFinance::RefreshQuotes(TContracts& anContacts)
+{
+ CHTTPSession http;
+ tstring sURL = GetURL();
+ bool bUseExtendedStatus = CModuleInfo::GetInstance().GetExtendedStatusFlag();
+
+ for(TContracts::const_iterator i = anContacts.begin();i != anContacts.end() && IsOnline();++i)
+ {
+ HANDLE hContact = *i;
+
+ if(bUseExtendedStatus)
+ {
+ SetContactStatus(hContact,ID_STATUS_OCCUPIED);
+ }
+
+ tstring sFullURL = build_url(hContact,sURL);
+// LogIt(Info,sFullURL);
+ if ((true == http.OpenURL(sFullURL)) && (true == IsOnline()))
+ {
+ tstring sHTML;
+ if ((true == http.ReadResponce(sHTML)) && (true == IsOnline()))
+ {
+// LogIt(Info,sHTML);
+
+ CGoogleInfo Info;
+ parse_responce(sHTML,Info);
+ if(true == IsOnline())
+ {
+ if(Info.m_nFlags&CGoogleInfo::giRate)
+ {
+ if(Info.m_nFlags&CGoogleInfo::giOpen)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_OPEN_VALUE,Info.m_dOpenValue);
+ }
+ if(Info.m_nFlags&CGoogleInfo::giPercentChangeAfterHours)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_DIFF,Info.m_dPercentChangeAfterHours);
+ }
+ if(Info.m_nFlags&CGoogleInfo::giPercentChangeToYesterdayClose)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE,Info.m_dPercentChangeToYersterdayClose);
+ }
+ if(false == Info.m_sCmpName.empty())
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION,Info.m_sCmpName.c_str());
+ }
+
+ WriteContactRate(hContact,Info.m_dRate);
+ continue;
+ }
+ }
+ }
+ }
+
+ SetContactStatus(hContact,ID_STATUS_NA);
+ }
+
+}
+
+
+void CQuotesProviderGoogleFinance::Accept(CQuotesProviderVisitor& visitor)const
+{
+ CQuotesProviderFinance::Accept(visitor);
+ visitor.Visit(*this);
+}
+
diff --git a/protocols/Quotes/src/QuotesProviderGoogleFinance.h b/protocols/Quotes/src/QuotesProviderGoogleFinance.h
new file mode 100644
index 0000000000..075498a4dd
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderGoogleFinance.h
@@ -0,0 +1,25 @@
+#ifndef __89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__
+#define __89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__
+
+#include "QuotesProviderFinance.h"
+
+#define DB_STR_GOOGLE_FINANCE_OPEN_VALUE "OpenQuotePrice"
+#define DB_STR_GOOGLE_FINANCE_DIFF "DifferentFromStartOfDay"
+#define DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE "PercentChangeToYersterdayClose"
+
+// #define DB_STR_GOOGLE_FINANCE_COMP_NAME "CompanyName"
+
+
+class CQuotesProviderGoogleFinance : public CQuotesProviderFinance
+{
+
+public:
+ CQuotesProviderGoogleFinance();
+ ~CQuotesProviderGoogleFinance();
+
+private:
+ virtual void RefreshQuotes(TContracts& anContacts);
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+};
+
+#endif //__89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__
diff --git a/protocols/Quotes/src/QuotesProviderVisitor.h b/protocols/Quotes/src/QuotesProviderVisitor.h
new file mode 100644
index 0000000000..9ae601f2a1
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitor.h
@@ -0,0 +1,25 @@
+#ifndef __7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__
+#define __7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__
+
+class CQuotesProviderBase;
+class CQuotesProviderFinance;
+class CQuotesProviderDukasCopy;
+class CQuotesProviderGoogle;
+class CQuotesProviderGoogleFinance;
+class CQuotesProviderYahoo;
+
+class CQuotesProviderVisitor
+{
+public:
+ CQuotesProviderVisitor() {}
+ virtual ~CQuotesProviderVisitor() {}
+
+ virtual void Visit(const CQuotesProviderBase& rProvider){}
+ virtual void Visit(const CQuotesProviderFinance& rProvider){}
+ virtual void Visit(const CQuotesProviderDukasCopy& rProvider){}
+ virtual void Visit(const CQuotesProviderGoogle& rProvider){}
+ virtual void Visit(const CQuotesProviderGoogleFinance& rProvider){}
+ virtual void Visit(const CQuotesProviderYahoo& rProvider){}
+};
+
+#endif //__7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__
diff --git a/protocols/Quotes/src/QuotesProviderVisitorDbSettings.cpp b/protocols/Quotes/src/QuotesProviderVisitorDbSettings.cpp
new file mode 100644
index 0000000000..5caea48685
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorDbSettings.cpp
@@ -0,0 +1,157 @@
+#include "StdAfx.h"
+#include "QuotesProviderVisitorDbSettings.h"
+
+#include "QuotesProviderGoogle.h"
+#include "QuotesProviderDukasCopy.h"
+
+CQuotesProviderVisitorDbSettings::CQuotesProviderVisitorDbSettings()
+ : m_pszDbRefreshRateType(NULL),
+ m_pszDbRefreshRateValue(NULL),
+ m_pszDbDisplayNameFormat(NULL),
+ m_pszDefDisplayFormat(NULL),
+ m_pszDefLogFileFormat(NULL),
+ m_pszDefHistoryFormat(NULL),
+ m_pszXMLIniFileName(NULL),
+ m_pszDbStatusMsgFormat(NULL),
+ m_pszDefStatusMsgFormat(NULL),
+ m_pszDbLogMode(NULL),
+ m_pszDbHistoryFormat(NULL),
+ m_pszDbHistoryCondition(NULL),
+ m_pszDbLogFile(NULL),
+ m_pszDbLogFormat(NULL),
+ m_pszDbLogCondition(NULL),
+ m_pszDbPopupFormat(NULL),
+ m_pszDefPopupFormat(NULL),
+ m_pszDbPopupCondition(NULL),
+ m_pszDbPopupColourMode(NULL),
+ m_pszDbPopupBkColour(NULL),
+ m_pszDbPopupTextColour(NULL),
+ m_pszDbPopupDelayMode(NULL),
+ m_pszDbPopupDelayTimeout(NULL),
+ m_pszDbPopupHistoryFlag(NULL),
+ m_pszDbTendencyFormat(nullptr),
+ m_pszDefTendencyFormat(_T("%r>%p"))
+{
+}
+
+CQuotesProviderVisitorDbSettings::~CQuotesProviderVisitorDbSettings()
+{
+}
+
+void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderBase&/* rProvider*/)
+{
+ m_pszDefLogFileFormat = _T("%s\\t%t\\t%r\\n");
+ m_pszDefHistoryFormat = _T("%s %r");
+ m_pszDefPopupFormat = _T("\\nCurrent = %r\\nPrevious = %p");
+}
+
+void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderDukasCopy&/* rProvider*/)
+{
+ m_pszDbRefreshRateType = DB_STR_REFRESH_RATE_TYPE;
+ m_pszDbRefreshRateValue = DB_STR_REFRESH_RATE_VALUE;
+ m_pszDbDisplayNameFormat = DB_STR_DC_DISPLAY_NAME_FORMAT;
+ m_pszDefDisplayFormat = _T("%s %r");
+ m_pszXMLIniFileName = _T("Dukascopy.xml");
+ m_pszDbStatusMsgFormat = "DC_StatusMessageFormat";
+
+ m_pszDbLogMode = "DC_LogMode";
+ m_pszDbHistoryFormat = "DC_HistoryFormat";
+ m_pszDbHistoryCondition = "DC_AddToHistoryOnlyIfValueIsChanged";
+ m_pszDbLogFile = "DC_LogFile";
+ m_pszDbLogFormat = "DC_LogFileFormat";
+ m_pszDbLogCondition = "DC_AddToLogOnlyIfValueIsChanged";
+ m_pszDbPopupFormat ="DC_PopupFormat";
+ m_pszDbPopupCondition = "DC_ShowPopupOnlyIfValueChanged";
+
+ m_pszDbPopupColourMode = "DC_PopupColourMode";
+ m_pszDbPopupBkColour = "DC_PopupColourBk";
+ m_pszDbPopupTextColour = "DC_PopupColourText";
+ m_pszDbPopupDelayMode = "DC_PopupDelayMode";
+ m_pszDbPopupDelayTimeout = "DC_PopupDelayTimeout";
+ m_pszDbPopupHistoryFlag = "DC_PopupHistoryFlag";
+ m_pszDbTendencyFormat = "DC_TendencyFormat";
+}
+
+void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderGoogle&/* rProvider*/)
+{
+ m_pszDbRefreshRateType = DB_STR_GOOGLE_REFRESH_RATE_TYPE;
+ m_pszDbRefreshRateValue = DB_STR_GOOGLE_REFRESH_RATE_VALUE;
+ m_pszDbDisplayNameFormat = DB_STR_GOOGLE_DISPLAY_NAME_FORMAT;
+ m_pszDefDisplayFormat = _T("1 %f = %r %i");
+ m_pszXMLIniFileName = _T("Google.xml");
+ m_pszDbStatusMsgFormat = "Google_StatusMessageFormat";
+
+ m_pszDbLogMode = "Google_LogMode";
+ m_pszDbHistoryFormat = "Google_HistoryFormat";
+ m_pszDbHistoryCondition = "Google_AddToHistoryOnlyIfValueIsChanged";
+ m_pszDbLogFile = "Google_LogFile";
+ m_pszDbLogFormat = "Google_LogFileFormat";
+ m_pszDbLogCondition = "Google_AddToLogOnlyIfValueIsChanged";
+ m_pszDbPopupFormat ="Google_PopupFormat";
+ m_pszDbPopupCondition = "Google_ShowPopupOnlyIfValueChanged";
+
+ m_pszDbPopupColourMode = "Google_PopupColourMode";
+ m_pszDbPopupBkColour = "Google_PopupColourBk";
+ m_pszDbPopupTextColour = "Google_PopupColourText";
+ m_pszDbPopupDelayMode = "Google_PopupDelayMode";
+ m_pszDbPopupDelayTimeout = "Google_PopupDelayTimeout";
+ m_pszDbPopupHistoryFlag = "Google_PopupHistoryFlag";
+
+ m_pszDbTendencyFormat = "Google_TendencyFormat";
+}
+
+void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderGoogleFinance&/* rProvider*/)
+{
+ m_pszDbRefreshRateType = "GoogleFinance_RefreshRateType";
+ m_pszDbRefreshRateValue = "GoogleFinance_RefreshRateValue";
+ m_pszDbDisplayNameFormat = "GoogleFinance_DspNameFrmt";
+ m_pszDefDisplayFormat = _T("%s %r");
+ m_pszXMLIniFileName = _T("GoogleFinance.xml");
+ m_pszDbStatusMsgFormat = "GoogleFinance_StatusMessageFormat";
+
+ m_pszDbLogMode = "GoogleFinance_LogMode";
+ m_pszDbHistoryFormat = "GoogleFinance_HistoryFormat";
+ m_pszDbHistoryCondition = "GoogleFinance_AddToHistoryOnlyIfValueIsChanged";
+ m_pszDbLogFile = "GoogleFinance_LogFile";
+ m_pszDbLogFormat = "GoogleFinance_LogFileFormat";
+ m_pszDbLogCondition = "GoogleFinance_AddToLogOnlyIfValueIsChanged";
+ m_pszDbPopupFormat ="GoogleFinance_PopupFormat";
+ m_pszDbPopupCondition = "GoogleFinance_ShowPopupOnlyIfValueChanged";
+
+ m_pszDbPopupColourMode = "GoogleFinance_PopupColourMode";
+ m_pszDbPopupBkColour = "GoogleFinance_PopupColourBk";
+ m_pszDbPopupTextColour = "GoogleFinance_PopupColourText";
+ m_pszDbPopupDelayMode = "GoogleFinance_PopupDelayMode";
+ m_pszDbPopupDelayTimeout = "GoogleFinance_PopupDelayTimeout";
+ m_pszDbPopupHistoryFlag = "GoogleFinance_PopupHistoryFlag";
+
+ m_pszDbTendencyFormat = "GoogleFinance_TendencyFormat";
+}
+
+void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderYahoo& rProvider)
+{
+ m_pszDbRefreshRateType = "Yahoo_RefreshRateType";
+ m_pszDbRefreshRateValue = "Yahoo_RefreshRateValue";
+ m_pszDbDisplayNameFormat = "Yahoo_DspNameFrmt";
+ m_pszDefDisplayFormat = _T("%s %r");
+ m_pszXMLIniFileName = _T("Yahoo.xml");
+ m_pszDbStatusMsgFormat = "Yahoo_StatusMessageFormat";
+
+ m_pszDbLogMode = "Yahoo_LogMode";
+ m_pszDbHistoryFormat = "Yahoo_HistoryFormat";
+ m_pszDbHistoryCondition = "Yahoo_AddToHistoryOnlyIfValueIsChanged";
+ m_pszDbLogFile = "Yahoo_LogFile";
+ m_pszDbLogFormat = "Yahoo_LogFileFormat";
+ m_pszDbLogCondition = "Yahoo_AddToLogOnlyIfValueIsChanged";
+ m_pszDbPopupFormat ="Yahoo_PopupFormat";
+ m_pszDbPopupCondition = "Yahoo_ShowPopupOnlyIfValueChanged";
+
+ m_pszDbPopupColourMode = "Yahoo_PopupColourMode";
+ m_pszDbPopupBkColour = "Yahoo_PopupColourBk";
+ m_pszDbPopupTextColour = "Yahoo_PopupColourText";
+ m_pszDbPopupDelayMode = "Yahoo_PopupDelayMode";
+ m_pszDbPopupDelayTimeout = "Yahoo_PopupDelayTimeout";
+ m_pszDbPopupHistoryFlag = "Yahoo_PopupHistoryFlag";
+
+ m_pszDbTendencyFormat = "Yahoo_TendencyFormat";
+}
diff --git a/protocols/Quotes/src/QuotesProviderVisitorDbSettings.h b/protocols/Quotes/src/QuotesProviderVisitorDbSettings.h
new file mode 100644
index 0000000000..728a436dfa
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorDbSettings.h
@@ -0,0 +1,49 @@
+#ifndef __97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__
+#define __97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__
+
+#include "quotesprovidervisitor.h"
+
+class CQuotesProviderVisitorDbSettings : public CQuotesProviderVisitor
+{
+public:
+ CQuotesProviderVisitorDbSettings();
+ ~CQuotesProviderVisitorDbSettings();
+
+private:
+ virtual void Visit(const CQuotesProviderBase& rProvider);
+ virtual void Visit(const CQuotesProviderDukasCopy& rProvider);
+ virtual void Visit(const CQuotesProviderGoogle& rProvider);
+ virtual void Visit(const CQuotesProviderGoogleFinance& rProvider);
+ virtual void Visit(const CQuotesProviderYahoo& rProvider);
+public:
+ LPCSTR m_pszDbRefreshRateType;
+ LPCSTR m_pszDbRefreshRateValue;
+ LPCSTR m_pszDbDisplayNameFormat;
+ LPCTSTR m_pszDefDisplayFormat;
+ LPCTSTR m_pszDefLogFileFormat;
+ LPCTSTR m_pszDefHistoryFormat;
+ LPCTSTR m_pszXMLIniFileName;
+ LPCSTR m_pszDbStatusMsgFormat;
+ LPCTSTR m_pszDefStatusMsgFormat;
+ LPCTSTR m_pszDefPopupFormat;
+ LPCSTR m_pszDbTendencyFormat;
+ LPCTSTR m_pszDefTendencyFormat;
+
+ //global settings
+ LPCSTR m_pszDbLogMode;
+ LPCSTR m_pszDbHistoryFormat;
+ LPCSTR m_pszDbHistoryCondition;
+ LPCSTR m_pszDbLogFile;
+ LPCSTR m_pszDbLogFormat;
+ LPCSTR m_pszDbLogCondition;
+ LPCSTR m_pszDbPopupFormat;
+ LPCSTR m_pszDbPopupCondition;
+ LPCSTR m_pszDbPopupColourMode;
+ LPCSTR m_pszDbPopupBkColour;
+ LPCSTR m_pszDbPopupTextColour;
+ LPCSTR m_pszDbPopupDelayMode;
+ LPCSTR m_pszDbPopupDelayTimeout;
+ LPCSTR m_pszDbPopupHistoryFlag;
+};
+
+#endif //__97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__
diff --git a/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp b/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp
new file mode 100644
index 0000000000..9e643fe1b6
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp
@@ -0,0 +1,63 @@
+#include "StdAfx.h"
+#include "QuotesProviderVisitorFormatSpecificator.h"
+
+CQuotesProviderVisitorFormatSpecificator::CQuotesProviderVisitorFormatSpecificator()
+{
+}
+
+CQuotesProviderVisitorFormatSpecificator::~CQuotesProviderVisitorFormatSpecificator()
+{
+}
+
+void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderDukasCopy&/* rProvider*/)
+{
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%d"),TranslateT("Quote Name")));
+}
+
+void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderGoogle&/* rProvider*/)
+{
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%F"),TranslateT("From Currency Full Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%f"),TranslateT("From Currency Short Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%I"),TranslateT("Into Currency Full Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%i"),TranslateT("Into Currency Short Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Short notation for \"%f/%i\"")));
+}
+
+void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderBase&/* rProvider*/)
+{
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%S"),TranslateT("Source of Information")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%r"),TranslateT("Rate Value")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%p"),TranslateT("Previous Rate Value")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%X"),TranslateT("Fetch Time")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%x"),TranslateT("Fetch Date")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%t"),TranslateT("Fetch Time and Date")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("\\%"),TranslateT("Percentage Character (%)")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("\\t"),TranslateT("Tabulation")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("\\\\"),TranslateT("Left slash (\\)")));
+}
+
+void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderGoogleFinance&/* rProvider*/)
+{
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%n"),TranslateT("Quote Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%o"),TranslateT("Open Price")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%d"),TranslateT("Percent Change to After Hours")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%y"),TranslateT("Percent Change to Yesterday Close")));
+}
+
+const CQuotesProviderVisitorFormatSpecificator::TFormatSpecificators& CQuotesProviderVisitorFormatSpecificator::GetSpecificators()const
+{
+ return m_aSpecificators;
+}
+
+void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderYahoo& rProvider)
+{
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%n"),TranslateT("Quote Name")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%o"),TranslateT("Open Price")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%h"),TranslateT("Day's High")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%g"),TranslateT("Day's Low")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%P"),TranslateT("Previous Close")));
+ m_aSpecificators.push_back(CFormatSpecificator(_T("%c"),TranslateT("Change")));
+}
diff --git a/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.h b/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.h
new file mode 100644
index 0000000000..870ab00634
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorFormatSpecificator.h
@@ -0,0 +1,36 @@
+#ifndef __00c159f3_525a_41e9_8fc5_00464b6fafa3_QuotesProviderVisitorFormatSpecificator_h__
+#define __00c159f3_525a_41e9_8fc5_00464b6fafa3_QuotesProviderVisitorFormatSpecificator_h__
+
+#include "quotesprovidervisitor.h"
+
+class CQuotesProviderVisitorFormatSpecificator : public CQuotesProviderVisitor
+{
+public:
+ struct CFormatSpecificator
+ {
+ CFormatSpecificator(const tstring& rsSymbol = _T(""),const tstring& rsDec = _T(""))
+ : m_sSymbol(rsSymbol),m_sDesc(rsDec){}
+
+ tstring m_sSymbol;
+ tstring m_sDesc;
+ };
+ typedef std::vector<CFormatSpecificator> TFormatSpecificators;
+
+public:
+ CQuotesProviderVisitorFormatSpecificator();
+ ~CQuotesProviderVisitorFormatSpecificator();
+
+ const TFormatSpecificators& GetSpecificators()const;
+
+private:
+ virtual void Visit(const CQuotesProviderDukasCopy& rProvider);
+ virtual void Visit(const CQuotesProviderGoogle& rProvider);
+ virtual void Visit(const CQuotesProviderBase& rProvider);
+ virtual void Visit(const CQuotesProviderGoogleFinance& rProvider);
+ virtual void Visit(const CQuotesProviderYahoo& rProvider);
+
+private:
+ TFormatSpecificators m_aSpecificators;
+};
+
+#endif//__00c159f3_525a_41e9_8fc5_00464b6fafa3_QuotesProviderVisitorFormatSpecificator_h__
diff --git a/protocols/Quotes/src/QuotesProviderVisitorFormater.cpp b/protocols/Quotes/src/QuotesProviderVisitorFormater.cpp
new file mode 100644
index 0000000000..4b1d73bb05
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorFormater.cpp
@@ -0,0 +1,216 @@
+#include "StdAfx.h"
+#include "QuotesProviderVisitorFormater.h"
+#include "DBUtils.h"
+#include "EconomicRateInfo.h"
+#include "QuotesProviderGoogle.h"
+#include "Locale.h"
+#include "IsWithinAccuracy.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "QuotesProviderYahoo.h"
+
+CQuotesProviderVisitorFormater::CQuotesProviderVisitorFormater(HANDLE hContact,TCHAR chr,int nWidth)
+ : m_hContact(hContact),
+ m_chr(chr),
+ m_nWidth(nWidth)
+{
+}
+
+CQuotesProviderVisitorFormater::~CQuotesProviderVisitorFormater()
+{
+}
+
+const tstring& CQuotesProviderVisitorFormater::GetResult()const
+{
+ return m_sResult;
+}
+
+void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderDukasCopy& rProvider)
+{
+ if(_T('d') == m_chr || _T('D') == m_chr)
+ {
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION);
+ }
+}
+
+void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderGoogle& rProvider)
+{
+ switch(m_chr)
+ {
+ case _T('F'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_FROM_DESCRIPTION);
+ break;
+ case _T('f'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_FROM_ID);
+ break;
+ case _T('I'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_TO_DESCRIPTION);
+ break;
+ case _T('i'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_TO_ID);
+ break;
+ }
+}
+
+namespace
+{
+ bool get_fetch_time(HANDLE hContact,time_t& rTime)
+ {
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING cgs;
+
+ cgs.szModule=QUOTES_MODULE_NAME;
+ cgs.szSetting=DB_STR_QUOTE_FETCH_TIME;
+ cgs.pValue=&dbv;
+ if(CallService(MS_DB_CONTACT_GETSETTING,reinterpret_cast<WPARAM>(hContact),reinterpret_cast<LPARAM>(&cgs))
+ || (DBVT_DWORD != dbv.type))
+ {
+ return false;
+ }
+
+ rTime = dbv.dVal;
+ return true;
+ }
+
+ tstring format_fetch_time(const CQuotesProviderBase& rProvider,HANDLE 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();
+ }
+}
+
+void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderBase& rProvider)
+{
+ switch(m_chr)
+ {
+// default:
+// m_sResult = m_chr;
+// break;
+ case _T('%'):
+ case _T('\t'):
+ case _T('\\'):
+ m_sResult = m_chr;
+ break;
+ case _T('S'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_PROVIDER);
+ break;
+ case _T('s'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_SYMBOL);
+ break;
+ case _T('X'):
+ //m_sResult = format_fetch_time(rProvider,m_hContact,_T("%H:%M:%S"));
+ m_sResult = format_fetch_time(rProvider,m_hContact,Quotes_GetTimeFormat(true));
+ break;
+ case _T('x'):
+ //m_sResult = format_fetch_time(rProvider,m_hContact,_T("%d.%m.%y"));
+ m_sResult = format_fetch_time(rProvider,m_hContact,Quotes_GetDateFormat(true));
+ break;
+ case _T('t'):
+ {
+ tstring sFrmt = Quotes_GetDateFormat(true);
+ sFrmt += _T(" ");
+ sFrmt += Quotes_GetTimeFormat(true);
+ m_sResult = format_fetch_time(rProvider,m_hContact,sFrmt);
+
+ //m_sResult = format_fetch_time(rProvider,m_hContact,_T("%d.%m.%y %H:%M:%S"));
+ }
+ break;
+ case _T('r'):
+ case _T('R'):
+ FormatDoubleHelper(DB_STR_QUOTE_CURR_VALUE);
+ break;
+ case _T('p'):
+ FormatDoubleHelper(DB_STR_QUOTE_PREV_VALUE);
+ break;
+// case _T('c'):
+// FormatChangeValueHelper(false);
+// break;
+// case _T('C'):
+// FormatChangeValueHelper(true);
+// break;
+ }
+}
+
+void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderGoogleFinance&/* rProvider*/)
+{
+ switch(m_chr)
+ {
+ case _T('o'):
+ FormatDoubleHelper(DB_STR_GOOGLE_FINANCE_OPEN_VALUE);
+ break;
+ case _T('d'):
+ FormatDoubleHelper(DB_STR_GOOGLE_FINANCE_DIFF,_T("0"));
+ break;
+ case _T('y'):
+ FormatDoubleHelper(DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE,_T("0"));
+ break;
+ case _T('n'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION);
+ break;
+ }
+}
+
+namespace
+{
+ 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();
+ }
+}
+
+void CQuotesProviderVisitorFormater::FormatDoubleHelper(LPCSTR pszDbSet,
+ const tstring sInvalid/* = _T("-")*/)
+{
+ double d = 0.0;
+ if(true == Quotes_DBReadDouble(m_hContact,QUOTES_MODULE_NAME,pszDbSet,d))
+ {
+ m_sResult = format_double(d,m_nWidth);
+ }
+ else
+ {
+ m_sResult = sInvalid;
+ }
+}
+
+void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderYahoo& rProvider)
+{
+ switch(m_chr)
+ {
+ case _T('o'):
+ FormatDoubleHelper(DB_STR_YAHOO_OPEN_VALUE);
+ break;
+ case _T('h'):
+ FormatDoubleHelper(DB_STR_YAHOO_DAY_HIGH);
+ break;
+ case _T('P'):
+ FormatDoubleHelper(DB_STR_YAHOO_PREVIOUS_CLOSE);
+ break;
+ case _T('c'):
+ FormatDoubleHelper(DB_STR_YAHOO_CHANGE);
+ break;
+ case _T('g'):
+ FormatDoubleHelper(DB_STR_YAHOO_DAY_LOW);
+ break;
+ case _T('n'):
+ m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION);
+ break;
+ }
+
+}
diff --git a/protocols/Quotes/src/QuotesProviderVisitorFormater.h b/protocols/Quotes/src/QuotesProviderVisitorFormater.h
new file mode 100644
index 0000000000..7c9c222269
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorFormater.h
@@ -0,0 +1,32 @@
+#ifndef __2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__
+#define __2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__
+
+#include "quotesprovidervisitor.h"
+
+class CQuotesProviderVisitorFormater : public CQuotesProviderVisitor
+{
+public:
+ CQuotesProviderVisitorFormater(HANDLE hContact,TCHAR chr,int nWidth);
+ ~CQuotesProviderVisitorFormater();
+
+ const tstring& GetResult()const;
+
+private:
+ virtual void Visit(const CQuotesProviderDukasCopy& rProvider);
+ virtual void Visit(const CQuotesProviderGoogle& rProvider);
+ virtual void Visit(const CQuotesProviderBase& rProvider);
+ virtual void Visit(const CQuotesProviderGoogleFinance& rProvider);
+ virtual void Visit(const CQuotesProviderYahoo& rProvider);
+
+private:
+ void FormatDoubleHelper(LPCSTR pszDbSet,const tstring sInvalid = _T("-"));
+// void FormatChangeValueHelper(bool bPercentage);
+
+private:
+ HANDLE m_hContact;
+ TCHAR m_chr;
+ tstring m_sResult;
+ int m_nWidth;
+};
+
+#endif //__2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__
diff --git a/protocols/Quotes/src/QuotesProviderVisitorTendency.cpp b/protocols/Quotes/src/QuotesProviderVisitorTendency.cpp
new file mode 100644
index 0000000000..00703521b3
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorTendency.cpp
@@ -0,0 +1,70 @@
+#include "stdafx.h"
+#include "QuotesProviderVisitorTendency.h"
+#include "DBUtils.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "EconomicRateInfo.h"
+#include "QuotesProviderYahoo.h"
+
+CQuotesProviderVisitorTendency::CQuotesProviderVisitorTendency(HANDLE hContact,TCHAR chr)
+ : m_hContact(hContact),m_chr(chr),m_bValid(false),m_dResult(0.0)
+{
+}
+
+void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderBase& rProvider)
+{
+ switch(m_chr)
+ {
+ case _T('r'):
+ case _T('R'):
+ GetValue(DB_STR_QUOTE_CURR_VALUE);
+ break;
+ case _T('p'):
+ GetValue(DB_STR_QUOTE_PREV_VALUE);
+ break;
+ }
+}
+
+void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderGoogleFinance& rProvider)
+{
+ switch(m_chr)
+ {
+ case _T('o'):
+ GetValue(DB_STR_GOOGLE_FINANCE_OPEN_VALUE);
+ break;
+ case _T('d'):
+ GetValue(DB_STR_GOOGLE_FINANCE_DIFF);
+ break;
+ case _T('y'):
+ GetValue(DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE);
+ break;
+ }
+}
+
+void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderYahoo& rProvider)
+{
+ switch(m_chr)
+ {
+ case _T('o'):
+ GetValue(DB_STR_YAHOO_OPEN_VALUE);
+ break;
+ case _T('h'):
+ GetValue(DB_STR_YAHOO_DAY_HIGH);
+ break;
+ case _T('P'):
+ GetValue(DB_STR_YAHOO_PREVIOUS_CLOSE);
+ break;
+ case _T('c'):
+ GetValue(DB_STR_YAHOO_CHANGE);
+ break;
+ case _T('g'):
+ GetValue(DB_STR_YAHOO_DAY_LOW);
+ break;
+ }
+
+}
+
+
+void CQuotesProviderVisitorTendency::GetValue(LPCSTR pszDbKeyName)
+{
+ m_bValid = Quotes_DBReadDouble(m_hContact,QUOTES_MODULE_NAME,pszDbKeyName,m_dResult);
+}
diff --git a/protocols/Quotes/src/QuotesProviderVisitorTendency.h b/protocols/Quotes/src/QuotesProviderVisitorTendency.h
new file mode 100644
index 0000000000..fa0f04c5f0
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderVisitorTendency.h
@@ -0,0 +1,29 @@
+#ifndef __AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__
+#define __AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__
+
+#include "quotesprovidervisitor.h"
+
+class CQuotesProviderVisitorTendency : public CQuotesProviderVisitor
+{
+public:
+ CQuotesProviderVisitorTendency(HANDLE hContact,TCHAR chr);
+
+ bool IsValid()const{return m_bValid;}
+ double GetResult()const{return m_dResult;}
+
+private:
+ virtual void Visit(const CQuotesProviderBase& rProvider);
+ virtual void Visit(const CQuotesProviderGoogleFinance& rProvider);
+ virtual void Visit(const CQuotesProviderYahoo& rProvider);
+
+private:
+ void GetValue(LPCSTR pszDbKeyName);
+
+private:
+ HANDLE m_hContact;
+ TCHAR m_chr;
+ bool m_bValid;
+ double m_dResult;
+};
+
+#endif //__AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__
diff --git a/protocols/Quotes/src/QuotesProviderYahoo.cpp b/protocols/Quotes/src/QuotesProviderYahoo.cpp
new file mode 100644
index 0000000000..35edb3207c
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderYahoo.cpp
@@ -0,0 +1,193 @@
+#include "stdafx.h"
+#include "QuotesProviderYahoo.h"
+#include "QuotesProviderVisitor.h"
+#include "ModuleInfo.h"
+#include "DBUtils.h"
+#include "EconomicRateInfo.h"
+#include "HTTPSession.h"
+
+namespace
+{
+ void remove_quotes(tstring& s)
+ {
+ if (*s.begin() == _T('"'))
+ {
+ s.erase(s.begin());
+ }
+ if (*s.rbegin() == _T('"'))
+ {
+ tstring::iterator i(s.begin());
+ std::advance(i,s.size()-1);
+ s.erase(i);
+ }
+ }
+
+ void remove_end_of_line(tstring& s)
+ {
+ if (*s.rbegin() == _T('\n'))
+ {
+ tstring::iterator i(s.begin());
+ std::advance(i,s.size()-1);
+ s.erase(i);
+ }
+ if (*s.rbegin() == _T('\r'))
+ {
+ tstring::iterator i(s.begin());
+ std::advance(i,s.size()-1);
+ s.erase(i);
+ }
+ }
+
+ bool t2d(const tstring& s,double& d)
+ {
+ tistringstream stream(s);
+ stream >> d;
+ return ((false == stream.fail()) && (false == stream.bad()));
+// try
+// {
+// d = boost::lexical_cast<double>(s);
+// return true;
+// }
+// catch(boost::bad_lexical_cast& e)
+// {
+// }
+// return false;
+ }
+
+ typedef std::vector<tstring> TStrings;
+
+ bool get_double_from_parsed_line(HANDLE hContact,const TStrings& rasParsedLine,size_t nIndex,const char* pszDbName)
+ {
+ if(rasParsedLine.size() > nIndex)
+ {
+ double d = 0.0;
+ if(true == t2d(rasParsedLine[nIndex],d))
+ {
+ return Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,pszDbName,d);
+ }
+ }
+
+ DBWriteContactSettingTString(hContact,QUOTES_MODULE_NAME,pszDbName,_T(""));
+ return false;
+ }
+}
+
+void CQuotesProviderYahoo::RefreshQuotes(TContracts& anContacts)
+{
+ tstring sURL = GetURL();
+ bool bUseExtendedStatus = CModuleInfo::GetInstance().GetExtendedStatusFlag();
+
+ typedef std::map<tstring,HANDLE> TQuoteID2ContractHandles;
+ TQuoteID2ContractHandles aQuoteID2Handles;
+ tostringstream oURL;
+ oURL << sURL << _T("dioksin.txt?s=");
+ for(TContracts::const_iterator i = anContacts.begin();i != anContacts.end() && IsOnline();++i)
+ {
+ HANDLE hContact = *i;
+ if(bUseExtendedStatus)
+ {
+ SetContactStatus(hContact,ID_STATUS_OCCUPIED);
+ }
+
+ tstring sQuoteID = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID);
+ aQuoteID2Handles[sQuoteID] = hContact;
+ if(i != anContacts.begin())
+ {
+ oURL << _T("+");
+ }
+ oURL << sQuoteID;
+ }
+
+ if(true == IsOnline())
+ {
+ oURL << _T("&f=snl1ohgpc1");
+ CHTTPSession http;
+ if ((true == http.OpenURL(oURL.str())) && (true == IsOnline()))
+ {
+ tstring sFile;
+ if ((true == http.ReadResponce(sFile)) && (true == IsOnline()))
+ {
+ tistringstream out_str(sFile.c_str());
+ while(false == out_str.eof())
+ {
+ tstring sLine;
+ std::getline(out_str,sLine);
+ if(false == sLine.empty())
+ {
+ remove_end_of_line(sLine);
+
+ TStrings asStrings;
+ for(tstring::size_type nPos = sLine.find(_T(','));nPos != tstring::npos; nPos = sLine.find(_T(',')))
+ {
+ tstring::iterator i(sLine.begin());
+ std::advance(i,nPos);
+ tstring s(sLine.begin(),i);
+ remove_quotes(s);
+ asStrings.push_back(s);
+
+ if(i != sLine.end())
+ {
+ std::advance(i,1);
+ }
+ sLine.erase(sLine.begin(),i);
+ }
+
+ if(false == sLine.empty())
+ {
+ remove_quotes(sLine);
+
+ if(false == sLine.empty())
+ asStrings.push_back(sLine);
+ }
+
+ size_t cItems = asStrings.size();
+ if(cItems >= 3)
+ {
+ enum
+ {
+ indexSymbol = 0,
+ indexName,
+ indexLastTrade,
+ indexOpen,
+ indexDayHigh,
+ indexDayLow,
+ indexPreviousClose,
+ indexChange
+ };
+ auto it3 = aQuoteID2Handles.find(asStrings[indexSymbol]);
+ if(it3 != aQuoteID2Handles.end())
+ {
+ HANDLE hContact = it3->second;
+ double dRate = 0.0;
+ if(true == t2d(asStrings[indexLastTrade],dRate))
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION,asStrings[indexName].c_str());
+
+ get_double_from_parsed_line(hContact,asStrings,indexOpen,DB_STR_YAHOO_OPEN_VALUE);
+ get_double_from_parsed_line(hContact,asStrings,indexDayHigh,DB_STR_YAHOO_DAY_HIGH);
+ get_double_from_parsed_line(hContact,asStrings,indexDayLow,DB_STR_YAHOO_DAY_LOW);
+ get_double_from_parsed_line(hContact,asStrings,indexPreviousClose,DB_STR_YAHOO_PREVIOUS_CLOSE);
+ get_double_from_parsed_line(hContact,asStrings,indexChange,DB_STR_YAHOO_CHANGE);
+ WriteContactRate(hContact,dRate);
+ aQuoteID2Handles.erase(it3);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(true == IsOnline())
+ {
+ std::for_each(aQuoteID2Handles.begin(),aQuoteID2Handles.end(),
+ [](const TQuoteID2ContractHandles::value_type& pair){SetContactStatus(pair.second,ID_STATUS_NA);});
+ }
+ }
+}
+
+void CQuotesProviderYahoo::Accept(CQuotesProviderVisitor& visitor)const
+{
+ CQuotesProviderFinance::Accept(visitor);
+ visitor.Visit(*this);
+}
diff --git a/protocols/Quotes/src/QuotesProviderYahoo.h b/protocols/Quotes/src/QuotesProviderYahoo.h
new file mode 100644
index 0000000000..feadefbca4
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviderYahoo.h
@@ -0,0 +1,20 @@
+#ifndef __E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__
+#define __E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__
+
+#include "QuotesProviderFinance.h"
+
+
+#define DB_STR_YAHOO_OPEN_VALUE "OpenQuotePrice"
+#define DB_STR_YAHOO_DAY_HIGH "DayHigh"
+#define DB_STR_YAHOO_DAY_LOW "DayLow"
+#define DB_STR_YAHOO_PREVIOUS_CLOSE "PreviousClose"
+#define DB_STR_YAHOO_CHANGE "Change"
+
+class CQuotesProviderYahoo : public CQuotesProviderFinance
+{
+private:
+ virtual void RefreshQuotes(TContracts& anContacts);
+ virtual void Accept(CQuotesProviderVisitor& visitor)const;
+};
+
+#endif //__E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__
diff --git a/protocols/Quotes/src/QuotesProviders.cpp b/protocols/Quotes/src/QuotesProviders.cpp
new file mode 100644
index 0000000000..c7d6823cec
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviders.cpp
@@ -0,0 +1,120 @@
+#include "StdAfx.h"
+#include "QuotesProviders.h"
+
+#include "QuotesProviderDukasCopy.h"
+#include "EconomicRateInfo.h"
+#include "QuotesProviderGoogle.h"
+#include "DBUtils.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "QuotesProviderYahoo.h"
+
+#define LAST_RUN_VERSION "LastRunVersion"
+
+CQuotesProviders::CQuotesProviders()
+{
+ InitProviders();
+}
+
+CQuotesProviders::~CQuotesProviders()
+{
+ ClearProviders();
+}
+
+const CQuotesProviders::TQuotesProviders& CQuotesProviders::GetProviders()const
+{
+ return m_apProviders;
+}
+
+namespace
+{
+ template<class T>void create_provider(CQuotesProviders::TQuotesProviders& apProviders)
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider(new T);
+ if(pProvider->Init())
+ {
+ apProviders.push_back(pProvider);
+ }
+ }
+}
+
+void CQuotesProviders::CreateProviders()
+{
+ create_provider<CQuotesProviderDukasCopy>(m_apProviders);
+ create_provider<CQuotesProviderGoogle>(m_apProviders);
+ create_provider<CQuotesProviderGoogleFinance>(m_apProviders);
+ create_provider<CQuotesProviderYahoo>(m_apProviders);
+}
+
+void CQuotesProviders::ClearProviders()
+{
+ m_apProviders.clear();
+}
+
+namespace
+{
+ void convert_contact_settings(HANDLE hContact)
+ {
+ WORD dwLogMode = DBGetContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG,static_cast<WORD>(lmDisabled));
+ if ((dwLogMode&lmInternalHistory) || (dwLogMode&lmExternalFile))
+ {
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,1);
+ }
+ }
+}
+void CQuotesProviders::InitProviders()
+{
+ CreateProviders();
+
+ const WORD nCurrentVersion = 17;
+ WORD nVersion = DBGetContactSettingWord(NULL,QUOTES_MODULE_NAME,LAST_RUN_VERSION,1);
+
+ for(HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact))
+ {
+ TQuotesProviderPtr pProvider = GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ pProvider->AddContact(hContact);
+ if(nVersion < nCurrentVersion)
+ {
+ convert_contact_settings(hContact);
+ }
+ }
+ }
+
+ DBWriteContactSettingWord(NULL,QUOTES_MODULE_NAME,LAST_RUN_VERSION,nCurrentVersion);
+}
+
+CQuotesProviders::TQuotesProviderPtr CQuotesProviders::GetContactProviderPtr(HANDLE hContact)const
+{
+ char* szProto = reinterpret_cast<char*>(CallService(MS_PROTO_GETCONTACTBASEPROTO,
+ reinterpret_cast<WPARAM>(hContact),0));
+ if(NULL == szProto || 0 != ::_stricmp(szProto,QUOTES_PROTOCOL_NAME))
+ {
+ return TQuotesProviderPtr();
+ }
+
+ tstring sProvider = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_PROVIDER);
+ if(true == sProvider.empty())
+ {
+ return TQuotesProviderPtr();
+ }
+
+ return FindProvider(sProvider);
+}
+
+CQuotesProviders::TQuotesProviderPtr CQuotesProviders::FindProvider(const tstring& rsName)const
+{
+ TQuotesProviderPtr pResult;
+ for(TQuotesProviders::const_iterator i = m_apProviders.begin();i != m_apProviders.end();++i)
+ {
+ const TQuotesProviderPtr& pProvider = *i;
+ const IQuotesProvider::CProviderInfo& rInfo = pProvider->GetInfo();
+ if(0 == ::quotes_stricmp(rsName.c_str(),rInfo.m_sName.c_str()))
+ {
+ pResult = pProvider;
+ break;
+ }
+ }
+
+ return pResult;
+}
diff --git a/protocols/Quotes/src/QuotesProviders.h b/protocols/Quotes/src/QuotesProviders.h
new file mode 100644
index 0000000000..02aa5184c9
--- /dev/null
+++ b/protocols/Quotes/src/QuotesProviders.h
@@ -0,0 +1,32 @@
+#ifndef __148306d1_da2a_43df_b1ad_0cdc8ef8a79e_QuotesProviders_h__
+#define __148306d1_da2a_43df_b1ad_0cdc8ef8a79e_QuotesProviders_h__
+
+#include <boost\shared_ptr.hpp>
+#include <vector>
+
+class IQuotesProvider;
+
+class CQuotesProviders
+{
+public:
+ typedef boost::shared_ptr<IQuotesProvider> TQuotesProviderPtr;
+ typedef std::vector<TQuotesProviderPtr> TQuotesProviders;
+
+public:
+ CQuotesProviders();
+ ~CQuotesProviders();
+
+ TQuotesProviderPtr FindProvider(const tstring& rsName)const;
+ TQuotesProviderPtr GetContactProviderPtr(HANDLE hContact)const;
+ const TQuotesProviders& GetProviders()const;
+
+private:
+ void InitProviders();
+ void CreateProviders();
+ void ClearProviders();
+
+private:
+ TQuotesProviders m_apProviders;
+};
+
+#endif //__148306d1_da2a_43df_b1ad_0cdc8ef8a79e_QuotesProviders_h__
diff --git a/protocols/Quotes/src/SettingsDlg.cpp b/protocols/Quotes/src/SettingsDlg.cpp
new file mode 100644
index 0000000000..0011d2e917
--- /dev/null
+++ b/protocols/Quotes/src/SettingsDlg.cpp
@@ -0,0 +1,1148 @@
+#include "StdAfx.h"
+#include "SettingsDlg.h"
+#include "EconomicRateInfo.h"
+#include "ModuleInfo.h"
+#include "WinCtrlHelper.h"
+#include "CreateFilePath.h"
+#include "QuotesProviderVisitorDbSettings.h"
+#include "DBUtils.h"
+#include "resource.h"
+#include "QuotesProviders.h"
+#include "IQuotesProvider.h"
+
+#define WINDOW_PREFIX_SETTINGS "Edit Settings_"
+
+namespace
+{
+ LPCTSTR g_pszVariableQuoteName = _T("%quotename%");
+ LPCTSTR g_pszVariableUserProfile = _T("%miranda_userdata%");
+
+ void update_file_controls(HWND hDlg)
+ {
+ bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_EXTERNAL_FILE));
+
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_FILE_NAME),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_SELECT_FILE),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_BROWSE),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_LOG_FILE_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_LOG_FILE_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_LOG_FILE_DESCRIPTION),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_LOG_FILE_CONDITION),bEnable);
+ }
+
+ void update_history_controls(HWND hDlg)
+ {
+ bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_INTERNAL_HISTORY));
+
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_HISTORY_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_HISTORY_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_HISTORY_DESCRIPTION),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_HISTORY_CONDITION),bEnable);
+ }
+
+ void update_popup_controls(HWND hDlg)
+ {
+ bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_SHOW_POPUP));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),bEnable);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),bEnable);
+ }
+
+ bool enable_popup_controls(HWND hDlg)
+ {
+ bool bIsPopupServiceEnabled = 1 == ServiceExists(MS_POPUP_ADDPOPUPT);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP),bIsPopupServiceEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),bIsPopupServiceEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),bIsPopupServiceEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),bIsPopupServiceEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),bIsPopupServiceEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),bIsPopupServiceEnabled);
+
+ return bIsPopupServiceEnabled;
+ }
+
+ void update_all_controls(HWND hDlg)
+ {
+ bool bIsCheckedContactSpec = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_CONTACT_SPECIFIC));
+ bool bIsCheckedExternal = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_EXTERNAL_FILE));
+
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_EXTERNAL_FILE),bIsCheckedContactSpec);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_FILE_NAME),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_SELECT_FILE),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_BROWSE),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_LOG_FILE_FORMAT),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_LOG_FILE_FORMAT),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_LOG_FILE_DESCRIPTION),(bIsCheckedContactSpec&&bIsCheckedExternal));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_LOG_FILE_CONDITION),(bIsCheckedContactSpec&&bIsCheckedExternal));
+
+ bool bIsCheckedHistory = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_INTERNAL_HISTORY));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_INTERNAL_HISTORY),bIsCheckedContactSpec);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_HISTORY_FORMAT),(bIsCheckedContactSpec&&bIsCheckedHistory));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_HISTORY_FORMAT),(bIsCheckedContactSpec&&bIsCheckedHistory));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_HISTORY_DESCRIPTION),(bIsCheckedContactSpec&&bIsCheckedHistory));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_HISTORY_CONDITION),(bIsCheckedContactSpec&&bIsCheckedHistory));
+
+ bool bIsPopupServiceEnabled = 1 == ServiceExists(MS_POPUP_ADDPOPUPT);
+ bool bIsCheckedShowPopup = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_SHOW_POPUP));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP),(bIsCheckedContactSpec&&bIsPopupServiceEnabled));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup));
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),(bIsCheckedContactSpec&&bIsPopupServiceEnabled));
+ }
+
+ std::vector<TCHAR> get_filter()
+ {
+ std::vector<TCHAR> aFilter;
+ LPCTSTR pszFilterParts[] = {_T("Log Files (*.txt,*.log)"),_T("*.txt;*.log"),_T("All files (*.*)"),_T("*.*")};
+ for(int i = 0;i < sizeof(pszFilterParts)/sizeof(pszFilterParts[0]);++i)
+ {
+ tstring sPart = TranslateTS(pszFilterParts[i]);
+ std::copy(sPart.begin(),sPart.end(),std::back_inserter(aFilter));
+ aFilter.push_back(_T('\0'));
+
+ }
+ aFilter.push_back(_T('\0'));
+ return aFilter;
+ }
+ void select_log_file(HWND hDlg)
+ {
+// tstring sFileName = GenerateLogFileName(
+// get_window_text(::GetDlgItem(hDlg,IDC_EDIT_FILE_NAME)),tstring(),glfnResolveUserProfile);
+ std::vector<TCHAR> aFileBuffer(_MAX_PATH*2,_T('\0'));
+// std::copy(sFileName.begin(),sFileName.end(),aFileBuffer.begin());
+ LPTSTR pszFile = &*aFileBuffer.begin();
+
+ std::vector<TCHAR> aFilterBuffer = get_filter();
+ LPCTSTR pszFilter = &*aFilterBuffer.begin();
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hDlg;
+ ofn.lpstrFile = pszFile;
+ ofn.nMaxFile = (DWORD)aFileBuffer.size();
+ ofn.lpstrFilter = pszFilter;
+ ofn.nFilterIndex = 1;
+ ofn.hInstance = g_hInstance;
+ ofn.lpstrDefExt = _T("log");
+// ofn.lpstrFileTitle = NULL;
+// ofn.nMaxFileTitle = 0;
+// ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_EXPLORER;
+
+ BOOL b = GetOpenFileName(&ofn);
+ if(TRUE == b)
+ {
+ SetDlgItemText(hDlg,IDC_EDIT_FILE_NAME,ofn.lpstrFile);
+ }
+ }
+
+ struct CSettingWindowParam
+ {
+ CSettingWindowParam(HANDLE hContact) : m_hContact(hContact),m_pPopupSettings(NULL){}
+ ~CSettingWindowParam(){delete m_pPopupSettings;}
+
+ HANDLE m_hContact;
+ CPopupSettings* m_pPopupSettings;
+ };
+
+ inline CSettingWindowParam* get_param(HWND hWnd)
+ {
+ return reinterpret_cast<CSettingWindowParam*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ }
+
+
+// inline HANDLE get_contact(HWND hWnd)
+// {
+// return reinterpret_cast<HANDLE>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+// }
+
+ void update_popup_controls_settings(HWND hDlg)
+ {
+ bool bIsColoursEnabled = 1 == IsDlgButtonChecked(hDlg,IDC_RADIO_USER_DEFINED_COLOURS);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_BGCOLOR),bIsColoursEnabled);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_TEXTCOLOR),bIsColoursEnabled);
+
+ bool bIsDelayEnabled = 1 == IsDlgButtonChecked(hDlg,IDC_DELAYCUSTOM);
+ ::EnableWindow(::GetDlgItem(hDlg,IDC_DELAY),bIsDelayEnabled);
+
+ }
+
+ INT_PTR CALLBACK EditPopupSettingsDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ CPopupSettings* pSettings = reinterpret_cast<CPopupSettings*>(lp);
+ TranslateDialogDefault( hWnd );
+// ::SendDlgItemMessage(hWnd,IDC_BGCOLOR,CPM_SETDEFAULTCOLOUR,0,::GetSysColor(COLOR_BTNFACE));
+// ::SendDlgItemMessage(hWnd,IDC_TEXTCOLOR,CPM_SETDEFAULTCOLOUR,0,::GetSysColor(COLOR_BTNTEXT));
+ ::SendDlgItemMessage(hWnd,IDC_BGCOLOR,CPM_SETCOLOUR,0,pSettings->GetColourBk());
+ ::SendDlgItemMessage(hWnd,IDC_TEXTCOLOR,CPM_SETCOLOUR,0,pSettings->GetColourText());
+
+ ::CheckDlgButton(hWnd,IDC_CHECK_DONT_USE_POPUPHISTORY,pSettings->GetHistoryFlag());
+
+ ::CheckRadioButton(hWnd,IDC_RADIO_DEFAULT_COLOURS,IDC_RADIO_USER_DEFINED_COLOURS,(CPopupSettings::colourDefault == pSettings->GetColourMode()) ? IDC_RADIO_DEFAULT_COLOURS : IDC_RADIO_USER_DEFINED_COLOURS);
+ UINT n;
+ switch(pSettings->GetDelayMode())
+ {
+ default:
+ assert(!"Unknown delay mode. Please, fix it");
+ case CPopupSettings::delayFromPopup:
+ n = IDC_DELAYFROMPU;
+ break;
+ case CPopupSettings::delayCustom:
+ n = IDC_DELAYCUSTOM;
+ break;
+ case CPopupSettings::delayPermanent:
+ n = IDC_DELAYPERMANENT;
+ break;
+ }
+ ::CheckRadioButton(hWnd,IDC_DELAYFROMPU,IDC_DELAYPERMANENT,n);
+
+ ::SetDlgItemInt(hWnd,IDC_DELAY,pSettings->GetDelayTimeout(),FALSE);
+
+ update_popup_controls_settings(hWnd);
+
+ ::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast<LONG_PTR>(pSettings));
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wp))
+ {
+ case IDC_RADIO_DEFAULT_COLOURS:
+ case IDC_RADIO_USER_DEFINED_COLOURS:
+ case IDC_DELAYFROMPU:
+ case IDC_DELAYCUSTOM:
+ case IDC_DELAYPERMANENT:
+ update_popup_controls_settings(hWnd);
+ break;
+
+ case IDCANCEL:
+ ::EndDialog(hWnd,IDCANCEL);
+ break;
+ case IDOK:
+ {
+ CPopupSettings* pSettings = reinterpret_cast<CPopupSettings*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+
+ bool bError = false;
+ BOOL bOk = FALSE;
+ UINT nDelay = ::GetDlgItemInt(hWnd,IDC_DELAY,&bOk,FALSE);
+ CPopupSettings::EDelayMode nModeDelay = pSettings->GetDelayMode();
+ if(1 == ::IsDlgButtonChecked(hWnd,IDC_DELAYFROMPU))
+ {
+ nModeDelay = CPopupSettings::delayFromPopup;
+ }
+ else if(1 == ::IsDlgButtonChecked(hWnd,IDC_DELAYCUSTOM))
+ {
+ if(TRUE == bOk)
+ {
+ nModeDelay = CPopupSettings::delayCustom;
+ }
+ else
+ {
+ prepare_edit_ctrl_for_error(::GetDlgItem(hWnd,IDC_DELAY));
+ Quotes_MessageBox(hWnd,TranslateT("Enter integer value"),MB_OK|MB_ICONERROR);
+ bError = true;
+ }
+ }
+ else if(1 == ::IsDlgButtonChecked(hWnd,IDC_DELAYPERMANENT))
+ {
+ nModeDelay = CPopupSettings::delayPermanent;
+ }
+ if(false == bError)
+ {
+ pSettings->SetDelayMode(nModeDelay);
+ if(TRUE == bOk)
+ {
+ pSettings->SetDelayTimeout(nDelay);
+ }
+ pSettings->SetHistoryFlag((1 == IsDlgButtonChecked(hWnd,IDC_CHECK_DONT_USE_POPUPHISTORY)));
+
+ if(1 == ::IsDlgButtonChecked(hWnd,IDC_RADIO_DEFAULT_COLOURS))
+ {
+ pSettings->SetColourMode(CPopupSettings::colourDefault);
+ }
+ else if(1 == ::IsDlgButtonChecked(hWnd,IDC_RADIO_USER_DEFINED_COLOURS))
+ {
+ pSettings->SetColourMode(CPopupSettings::colourUserDefined);
+ }
+
+ pSettings->SetColourBk(static_cast<COLORREF>(::SendDlgItemMessage(hWnd,IDC_BGCOLOR,CPM_GETCOLOUR,0,0)));
+ pSettings->SetColourText(static_cast<COLORREF>(::SendDlgItemMessage(hWnd,IDC_TEXTCOLOR,CPM_GETCOLOUR,0,0)));
+
+ ::EndDialog(hWnd,IDOK);
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ return FALSE;
+ }
+
+ INT_PTR CALLBACK EditSettingsPerContactDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ HANDLE hContact = reinterpret_cast<HANDLE>(lp);
+ TranslateDialogDefault(hWnd);
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_SETTINGS,false);
+ assert(hWL);
+ WindowList_Add(hWL,hWnd,hContact);
+
+ tstring sName = GetContactName(hContact);
+ ::SetDlgItemText(hWnd,IDC_EDIT_NAME,sName.c_str());
+
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact);
+
+ BYTE bUseContactSpecific = DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,0);
+ ::CheckDlgButton(hWnd,IDC_CHECK_CONTACT_SPECIFIC,bUseContactSpecific);
+
+ CAdvProviderSettings setGlobal(pProvider.get());
+ // log to history
+ WORD dwLogMode = DBGetContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG,setGlobal.GetLogMode());
+ UINT nCheck = (dwLogMode&lmInternalHistory) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_INTERNAL_HISTORY,nCheck);
+
+ tstring sHistoryFrmt = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_HISTORY,setGlobal.GetHistoryFormat().c_str());
+ ::SetDlgItemText(hWnd,IDC_EDIT_HISTORY_FORMAT,sHistoryFrmt.c_str());
+
+ WORD wOnlyIfChanged = DBGetContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_HISTORY_CONDITION,setGlobal.GetHistoryOnlyChangedFlag());
+ ::CheckDlgButton(hWnd,IDC_CHECK_HISTORY_CONDITION,(1 == wOnlyIfChanged) ? 1 : 0);
+
+ // log to file
+ nCheck = (dwLogMode&lmExternalFile) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_EXTERNAL_FILE,nCheck);
+
+ tstring sLogFileName = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE);
+ if(true == sLogFileName.empty())
+ {
+ sLogFileName = GenerateLogFileName(setGlobal.GetLogFileName(),Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_SYMBOL),glfnResolveQuoteName);
+ }
+ ::SetDlgItemText(hWnd,IDC_EDIT_FILE_NAME,sLogFileName.c_str());
+
+ tstring sLogFileFrmt = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_LOG_FILE,setGlobal.GetLogFormat().c_str());
+ ::SetDlgItemText(hWnd,IDC_EDIT_LOG_FILE_FORMAT,sLogFileFrmt.c_str());
+
+ wOnlyIfChanged = DBGetContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE_CONDITION,setGlobal.GetLogOnlyChangedFlag());
+ ::CheckDlgButton(hWnd,IDC_CHECK_LOG_FILE_CONDITION,(1 == wOnlyIfChanged) ? 1 : 0);
+
+ // popup
+ nCheck = (dwLogMode&lmPopup) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_SHOW_POPUP,nCheck);
+ tstring sPopupFrmt = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_POPUP,setGlobal.GetPopupFormat().c_str());
+ ::SetDlgItemText(hWnd,IDC_EDIT_POPUP_FORMAT,sPopupFrmt.c_str());
+ bool bOnlyIfChanged = 1 == DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_CONDITION,setGlobal.GetShowPopupIfValueChangedFlag());
+ ::CheckDlgButton(hWnd,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED,(true == bOnlyIfChanged) ? 1 : 0);
+
+ update_all_controls(hWnd);
+
+ CSettingWindowParam* pParam = new CSettingWindowParam(hContact);
+ ::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast<LONG_PTR>(pParam));
+ Utils_RestoreWindowPositionNoSize(hWnd,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_SETTINGS);
+ ::ShowWindow(hWnd,SW_SHOW);
+ }
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wp))
+ {
+ case IDC_BUTTON_HISTORY_DESCRIPTION:
+ case IDC_BUTTON_LOG_FILE_DESCRIPTION:
+ case IDC_BUTTON_POPUP_FORMAT_DESCRIPTION:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(get_param(hWnd)->m_hContact);
+ show_variable_list(hWnd,pProvider.get());
+ }
+ break;
+
+ case IDC_CHECK_CONTACT_SPECIFIC:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_all_controls(hWnd);
+ }
+ break;
+ case IDC_CHECK_EXTERNAL_FILE:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_file_controls(hWnd);
+ }
+ break;
+ case IDC_CHECK_INTERNAL_HISTORY:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_history_controls(hWnd);
+ }
+ break;
+ case IDC_CHECK_SHOW_POPUP:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_popup_controls(hWnd);
+ }
+ break;
+ case IDC_BUTTON_BROWSE:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ select_log_file(hWnd);
+ }
+ break;
+ case IDC_BUTTON_POPUP_SETTINGS:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ CSettingWindowParam* pParam = get_param(hWnd);
+ if (!pParam->m_pPopupSettings)
+ {
+ CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(pParam->m_hContact);
+
+ pParam->m_pPopupSettings = new CPopupSettings(pProvider.get());
+ pParam->m_pPopupSettings->InitForContact(pParam->m_hContact);
+ }
+
+ DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_DIALOG_POPUP),
+ hWnd,
+ EditPopupSettingsDlgProc,reinterpret_cast<LPARAM>(pParam->m_pPopupSettings));
+ }
+ break;
+
+ case IDOK:
+ {
+ CSettingWindowParam* pParam = get_param(hWnd);
+ HANDLE hContact = pParam->m_hContact;
+
+ bool bUseContactSpec = 1 == ::IsDlgButtonChecked(hWnd,IDC_CHECK_CONTACT_SPECIFIC);
+
+ WORD nLogMode = lmDisabled;
+ UINT nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_EXTERNAL_FILE);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmExternalFile;
+ }
+
+ nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_INTERNAL_HISTORY);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmInternalHistory;
+ }
+
+ nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmPopup;
+ }
+
+ bool bOk = true;
+ HWND hwndLogFile = ::GetDlgItem(hWnd,IDC_EDIT_FILE_NAME);
+ HWND hwndLogFileFrmt = ::GetDlgItem(hWnd,IDC_EDIT_LOG_FILE_FORMAT);
+ HWND hwndHistoryFrmt = ::GetDlgItem(hWnd,IDC_EDIT_HISTORY_FORMAT);
+ tstring sLogFile = get_window_text(hwndLogFile);
+ tstring sLogFileFormat = get_window_text(hwndLogFileFrmt);
+ tstring sHistoryFormat = get_window_text(hwndHistoryFrmt);
+ if ((nLogMode&lmExternalFile))
+ {
+ if(true == sLogFile.empty())
+ {
+ prepare_edit_ctrl_for_error(hwndLogFile);
+ Quotes_MessageBox(hWnd,TranslateT("Enter log file name."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+ else if(true == sLogFileFormat.empty())
+ {
+ prepare_edit_ctrl_for_error(hwndLogFileFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter log file format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+ }
+
+ if ((true == bOk) && (nLogMode&lmInternalHistory) && (true == sHistoryFormat.empty()))
+ {
+ prepare_edit_ctrl_for_error(hwndHistoryFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter history format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+
+ HWND hwndPopupFrmt = ::GetDlgItem(hWnd,IDC_EDIT_POPUP_FORMAT);
+ tstring sPopupFormat = get_window_text(hwndPopupFrmt);
+ if ((true == bOk) && (nLogMode&lmPopup) && (true == sPopupFormat.empty()))
+ {
+ prepare_edit_ctrl_for_error(hwndPopupFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter popup window format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+
+ if(true == bOk)
+ {
+ UINT nIfChangedHistory = IsDlgButtonChecked(hWnd,IDC_CHECK_HISTORY_CONDITION);
+ UINT nIfChangedFile = IsDlgButtonChecked(hWnd,IDC_CHECK_LOG_FILE_CONDITION);
+ bool bIfChangedPopup = (1 == IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED));
+
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,bUseContactSpec);
+ DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG,nLogMode);
+ DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE_CONDITION,nIfChangedFile);
+ DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_HISTORY_CONDITION,nIfChangedHistory);
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_CONDITION,bIfChangedPopup);
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE,sLogFile.c_str());
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_LOG_FILE,sLogFileFormat.c_str());
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_HISTORY,sHistoryFormat.c_str());
+ DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_POPUP,sPopupFormat.c_str());
+
+ if(pParam->m_pPopupSettings)
+ {
+ pParam->m_pPopupSettings->SaveForContact(hContact);
+ }
+
+ ::DestroyWindow(hWnd);
+ }
+ }
+ break;
+ case IDCANCEL:
+ DestroyWindow(hWnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hWnd);
+ break;
+ case WM_DESTROY:
+ {
+ CSettingWindowParam* pParam = get_param(hWnd);
+ SetWindowLongPtr(hWnd,GWLP_USERDATA,0);
+
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_SETTINGS,false);
+ assert(hWL);
+ WindowList_Remove(hWL,hWnd);
+ Utils_SaveWindowPosition(hWnd,pParam->m_hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_SETTINGS);
+ delete pParam;
+ }
+ break;
+ }
+
+ return FALSE;
+ }
+}
+
+
+void ShowSettingsDlg(HANDLE hContact)
+{
+ HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_SETTINGS,true);
+ assert(hWL);
+ HWND hWnd = WindowList_Find(hWL,hContact);
+ if(NULL != hWnd)
+ {
+ SetForegroundWindow(hWnd);
+ SetFocus(hWnd);
+ }
+ else
+ {
+ CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_CONTACT_SETTINGS),NULL,EditSettingsPerContactDlgProc,reinterpret_cast<LPARAM>(hContact));
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+ INT_PTR CALLBACK EditSettingsPerProviderDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hWnd);
+ CAdvProviderSettings* pAdvSettings = reinterpret_cast<CAdvProviderSettings*>(lp);
+
+ ::SetDlgItemText(hWnd,IDC_EDIT_NAME,pAdvSettings->GetProviderPtr()->GetInfo().m_sName.c_str());
+
+ // log to history
+ WORD dwLogMode = pAdvSettings->GetLogMode();
+ UINT nCheck = (dwLogMode&lmInternalHistory) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_INTERNAL_HISTORY,nCheck);
+ ::SetDlgItemText(hWnd,IDC_EDIT_HISTORY_FORMAT,pAdvSettings->GetHistoryFormat().c_str());
+ ::CheckDlgButton(hWnd,IDC_CHECK_HISTORY_CONDITION,(true == pAdvSettings->GetHistoryOnlyChangedFlag()) ? 1 : 0);
+
+ // log to file
+ nCheck = (dwLogMode&lmExternalFile) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_EXTERNAL_FILE,nCheck);
+ ::SetDlgItemText(hWnd,IDC_EDIT_FILE_NAME,pAdvSettings->GetLogFileName().c_str());
+ ::SetDlgItemText(hWnd,IDC_EDIT_LOG_FILE_FORMAT,pAdvSettings->GetLogFormat().c_str());
+ ::CheckDlgButton(hWnd,IDC_CHECK_LOG_FILE_CONDITION,(true == pAdvSettings->GetLogOnlyChangedFlag()) ? 1 : 0);
+
+ update_file_controls(hWnd);
+ update_history_controls(hWnd);
+
+ // popup
+ nCheck = (dwLogMode&lmPopup) ? 1 : 0;
+ ::CheckDlgButton(hWnd,IDC_CHECK_SHOW_POPUP,nCheck);
+ ::SetDlgItemText(hWnd,IDC_EDIT_POPUP_FORMAT,pAdvSettings->GetPopupFormat().c_str());
+ ::CheckDlgButton(hWnd,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED,(true == pAdvSettings->GetShowPopupIfValueChangedFlag()) ? 1 : 0);
+
+ if(true == enable_popup_controls(hWnd))
+ {
+ update_popup_controls(hWnd);
+ }
+
+ ::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast<LONG>(pAdvSettings));
+ }
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wp))
+ {
+ case IDOK:
+ {
+ WORD nLogMode = lmDisabled;
+ UINT nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_EXTERNAL_FILE);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmExternalFile;
+ }
+
+ nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_INTERNAL_HISTORY);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmInternalHistory;
+ }
+
+ nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP);
+ if(1 == nCheck)
+ {
+ nLogMode |= lmPopup;
+ }
+
+ bool bOk = true;
+ HWND hwndLogFile = ::GetDlgItem(hWnd,IDC_EDIT_FILE_NAME);
+ HWND hwndLogFileFrmt = ::GetDlgItem(hWnd,IDC_EDIT_LOG_FILE_FORMAT);
+
+ tstring sLogFile = get_window_text(hwndLogFile);
+ tstring sLogFileFormat = get_window_text(hwndLogFileFrmt);
+
+ if ((nLogMode&lmExternalFile))
+ {
+ if(true == sLogFile.empty())
+ {
+ prepare_edit_ctrl_for_error(hwndLogFile);
+ Quotes_MessageBox(hWnd,TranslateT("Enter log file name."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+ else if(true == sLogFileFormat.empty())
+ {
+ prepare_edit_ctrl_for_error(hwndLogFileFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter log file format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+ }
+
+ HWND hwndHistoryFrmt = ::GetDlgItem(hWnd,IDC_EDIT_HISTORY_FORMAT);
+ tstring sHistoryFormat = get_window_text(hwndHistoryFrmt);
+ if ((true == bOk) && (nLogMode&lmInternalHistory) && (true == sHistoryFormat.empty()))
+ {
+ prepare_edit_ctrl_for_error(hwndHistoryFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter history format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+
+ HWND hwndPopupFrmt = ::GetDlgItem(hWnd,IDC_EDIT_POPUP_FORMAT);
+ tstring sPopupFormat = get_window_text(hwndPopupFrmt);
+ if ((true == bOk) && (nLogMode&lmPopup) && (true == sPopupFormat.empty()))
+ {
+ prepare_edit_ctrl_for_error(hwndPopupFrmt);
+ Quotes_MessageBox(hWnd,TranslateT("Enter popup window format."),MB_OK|MB_ICONERROR);
+ bOk = false;
+ }
+
+ if(true == bOk)
+ {
+ CAdvProviderSettings* pAdvSettings = reinterpret_cast<CAdvProviderSettings*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+
+ pAdvSettings->SetLogMode(nLogMode);
+ pAdvSettings->SetHistoryOnlyChangedFlag(1 == IsDlgButtonChecked(hWnd,IDC_CHECK_HISTORY_CONDITION));
+ pAdvSettings->SetLogOnlyChangedFlag(1 == IsDlgButtonChecked(hWnd,IDC_CHECK_LOG_FILE_CONDITION));
+ pAdvSettings->SetShowPopupIfValueChangedFlag(1 == IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED));
+ pAdvSettings->SetLogFileName(sLogFile);
+ pAdvSettings->SetLogFormat(sLogFileFormat);
+ pAdvSettings->SetHistoryFormat(sHistoryFormat);
+ pAdvSettings->SetPopupFormat(sPopupFormat);
+
+ ::EndDialog(hWnd,IDOK);
+ }
+ }
+ break;
+ case IDCANCEL:
+ ::EndDialog(hWnd,IDCANCEL);
+ break;
+ case IDC_BUTTON_HISTORY_DESCRIPTION:
+ case IDC_BUTTON_LOG_FILE_DESCRIPTION:
+ case IDC_BUTTON_POPUP_FORMAT_DESCRIPTION:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ const CAdvProviderSettings* pAdvSettings = reinterpret_cast<CAdvProviderSettings*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ show_variable_list(hWnd,pAdvSettings->GetProviderPtr());
+ }
+ break;
+ case IDC_CHECK_EXTERNAL_FILE:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_file_controls(hWnd);
+ }
+ break;
+ case IDC_CHECK_INTERNAL_HISTORY:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_history_controls(hWnd);
+ }
+ break;
+ case IDC_CHECK_SHOW_POPUP:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ update_popup_controls(hWnd);
+ }
+ break;
+ case IDC_BUTTON_BROWSE:
+ if(BN_CLICKED == HIWORD(wp))
+ {
+ select_log_file(hWnd);
+ }
+ break;
+ case IDC_BUTTON_POPUP_SETTINGS:
+ {
+ const CAdvProviderSettings* pAdvSettings = reinterpret_cast<CAdvProviderSettings*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
+ DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_DIALOG_POPUP),
+ hWnd,
+ EditPopupSettingsDlgProc,reinterpret_cast<LPARAM>(pAdvSettings->GetPopupSettingsPtr()));
+
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+ }
+}
+
+CAdvProviderSettings::CAdvProviderSettings(const IQuotesProvider* pQuotesProvider)
+ : m_pQuotesProvider(pQuotesProvider),
+ m_wLogMode(lmDisabled),
+ m_bIsOnlyChangedHistory(false),
+ m_bIsOnlyChangedLogFile(false),
+ m_bShowPopupIfValueChanged(false),
+ m_pPopupSettings(nullptr)
+{
+ assert(m_pQuotesProvider);
+
+ CQuotesProviderVisitorDbSettings visitor;
+ m_pQuotesProvider->Accept(visitor);
+
+ assert(visitor.m_pszDefLogFileFormat);
+ assert(visitor.m_pszDefHistoryFormat);
+ assert(visitor.m_pszDbLogMode);
+ assert(visitor.m_pszDbHistoryFormat);
+ assert(visitor.m_pszDbHistoryCondition);
+ assert(visitor.m_pszDbLogFile);
+ assert(visitor.m_pszDbLogFormat);
+ assert(visitor.m_pszDbLogCondition);
+
+ m_wLogMode = DBGetContactSettingWord(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogMode,static_cast<WORD>(lmDisabled));
+ m_sFormatHistory = Quotes_DBGetStringT(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbHistoryFormat,visitor.m_pszDefHistoryFormat);
+ m_bIsOnlyChangedHistory = 1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbHistoryCondition,0);
+
+ m_sLogFileName = Quotes_DBGetStringT(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogFile);
+ if(true == m_sLogFileName.empty())
+ {
+ m_sLogFileName = g_pszVariableUserProfile;
+ m_sLogFileName += _T("\\Quotes\\");
+ m_sLogFileName += g_pszVariableQuoteName;
+ m_sLogFileName += _T(".log");
+ }
+
+ m_sFormatLogFile = Quotes_DBGetStringT(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogFormat,visitor.m_pszDefLogFileFormat);
+ m_bIsOnlyChangedLogFile = (1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogCondition,0));
+
+ m_sPopupFormat = Quotes_DBGetStringT(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupFormat,visitor.m_pszDefPopupFormat);
+ m_bShowPopupIfValueChanged = (1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupCondition,0));
+}
+
+CAdvProviderSettings::~CAdvProviderSettings()
+{
+ delete m_pPopupSettings;
+}
+
+const IQuotesProvider* CAdvProviderSettings::GetProviderPtr()const
+{
+ return m_pQuotesProvider;
+}
+
+void CAdvProviderSettings::SaveToDb()const
+{
+ CQuotesProviderVisitorDbSettings visitor;
+ m_pQuotesProvider->Accept(visitor);
+
+ assert(visitor.m_pszDbLogMode);
+ assert(visitor.m_pszDbHistoryFormat);
+ assert(visitor.m_pszDbHistoryCondition);
+ assert(visitor.m_pszDbLogFile);
+ assert(visitor.m_pszDbLogFormat);
+ assert(visitor.m_pszDbLogCondition);
+ assert(visitor.m_pszDbPopupColourMode);
+ assert(visitor.m_pszDbPopupBkColour);
+ assert(visitor.m_pszDbPopupTextColour);
+ assert(visitor.m_pszDbPopupDelayMode);
+ assert(visitor.m_pszDbPopupDelayTimeout);
+ assert(visitor.m_pszDbPopupHistoryFlag);
+
+ DBWriteContactSettingWord(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogMode,m_wLogMode);
+ DBWriteContactSettingTString(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbHistoryFormat,m_sFormatHistory.c_str());
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbHistoryCondition,m_bIsOnlyChangedHistory);
+ DBWriteContactSettingTString(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogFile,m_sLogFileName.c_str());
+ DBWriteContactSettingTString(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogFormat,m_sFormatLogFile.c_str());
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbLogCondition,m_bIsOnlyChangedLogFile);
+ DBWriteContactSettingTString(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupFormat,m_sPopupFormat.c_str());
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupCondition,m_bShowPopupIfValueChanged);
+
+ if(nullptr != m_pPopupSettings)
+ {
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupColourMode,static_cast<BYTE>(m_pPopupSettings->GetColourMode()));
+ DBWriteContactSettingDword(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupBkColour,m_pPopupSettings->GetColourBk());
+ DBWriteContactSettingDword(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupTextColour,m_pPopupSettings->GetColourText());
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupDelayMode,static_cast<BYTE>(m_pPopupSettings->GetDelayMode()));
+ DBWriteContactSettingWord(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupDelayTimeout,m_pPopupSettings->GetDelayTimeout());
+ DBWriteContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupHistoryFlag,m_pPopupSettings->GetHistoryFlag());
+ }
+}
+
+WORD CAdvProviderSettings::GetLogMode()const
+{
+ return m_wLogMode;
+}
+
+void CAdvProviderSettings::SetLogMode(WORD wMode)
+{
+ m_wLogMode = wMode;
+}
+
+tstring CAdvProviderSettings::GetHistoryFormat()const
+{
+ return m_sFormatHistory;
+}
+
+void CAdvProviderSettings::SetHistoryFormat(const tstring& rsFormat)
+{
+ m_sFormatHistory = rsFormat;
+}
+
+bool CAdvProviderSettings::GetHistoryOnlyChangedFlag()const
+{
+ return m_bIsOnlyChangedHistory;
+}
+
+void CAdvProviderSettings::SetHistoryOnlyChangedFlag(bool bMode)
+{
+ m_bIsOnlyChangedHistory = bMode;
+}
+
+tstring CAdvProviderSettings::GetLogFileName()const
+{
+ return m_sLogFileName;
+}
+
+void CAdvProviderSettings::SetLogFileName(const tstring& rsFile)
+{
+ m_sLogFileName = rsFile;
+}
+
+tstring CAdvProviderSettings::GetLogFormat()const
+{
+ return m_sFormatLogFile;
+}
+
+void CAdvProviderSettings::SetLogFormat(const tstring& rsFormat)
+{
+ m_sFormatLogFile = rsFormat;
+}
+
+bool CAdvProviderSettings::GetLogOnlyChangedFlag()const
+{
+ return m_bIsOnlyChangedLogFile;
+}
+
+void CAdvProviderSettings::SetLogOnlyChangedFlag(bool bMode)
+{
+ m_bIsOnlyChangedLogFile = bMode;
+}
+
+const tstring& CAdvProviderSettings::GetPopupFormat() const
+{
+ return m_sPopupFormat;
+}
+
+void CAdvProviderSettings::SetPopupFormat(const tstring& val)
+{
+ m_sPopupFormat = val;
+}
+
+bool CAdvProviderSettings::GetShowPopupIfValueChangedFlag() const
+{
+ return m_bShowPopupIfValueChanged;
+}
+
+void CAdvProviderSettings::SetShowPopupIfValueChangedFlag(bool val)
+{
+ m_bShowPopupIfValueChanged = val;
+}
+
+CPopupSettings* CAdvProviderSettings::GetPopupSettingsPtr()const
+{
+ if(nullptr == m_pPopupSettings)
+ {
+ m_pPopupSettings = new CPopupSettings(m_pQuotesProvider);
+ }
+
+ return m_pPopupSettings;
+}
+
+CPopupSettings::CPopupSettings(const IQuotesProvider* pQuotesProvider)
+ : m_modeColour(colourDefault),
+ m_modeDelay(delayFromPopup),
+ m_rgbBkg(GetDefColourBk()),
+ m_rgbText(GetDefColourText()),
+ m_wDelay(3),
+ m_bUseHistory(false)
+
+{
+ CQuotesProviderVisitorDbSettings visitor;
+ pQuotesProvider->Accept(visitor);
+
+ assert(visitor.m_pszDbPopupColourMode);
+ assert(visitor.m_pszDbPopupBkColour);
+ assert(visitor.m_pszDbPopupTextColour);
+ assert(visitor.m_pszDbPopupDelayMode);
+ assert(visitor.m_pszDbPopupDelayTimeout);
+ assert(visitor.m_pszDbPopupHistoryFlag);
+
+ BYTE m = DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupColourMode,static_cast<BYTE>(m_modeColour));
+ if(m >= colourDefault && m <= colourUserDefined)
+ {
+ m_modeColour = static_cast<EColourMode>(m);
+ }
+
+ m_rgbBkg = DBGetContactSettingDword(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupBkColour,m_rgbBkg);
+ m_rgbText = DBGetContactSettingDword(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupTextColour,m_rgbText);
+
+ m = DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupDelayMode,static_cast<BYTE>(m_modeDelay));
+ if(m >= delayFromPopup && m <= delayPermanent)
+ {
+ m_modeDelay = static_cast<EDelayMode>(m);
+ }
+ m_wDelay = DBGetContactSettingWord(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupDelayTimeout,m_wDelay);
+ m_bUseHistory = (1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,visitor.m_pszDbPopupHistoryFlag,m_bUseHistory));
+}
+
+/*static */
+COLORREF CPopupSettings::GetDefColourBk()
+{
+ return ::GetSysColor(COLOR_BTNFACE);
+}
+
+/*static */
+COLORREF CPopupSettings::GetDefColourText()
+{
+ return ::GetSysColor(COLOR_BTNTEXT);
+}
+
+void CPopupSettings::InitForContact(HANDLE hContact)
+{
+ BYTE m = DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_MODE,static_cast<BYTE>(m_modeColour));
+ if(m >= CPopupSettings::colourDefault && m <= CPopupSettings::colourUserDefined)
+ {
+ m_modeColour = static_cast<CPopupSettings::EColourMode>(m);
+ }
+
+ m_rgbBkg = DBGetContactSettingDword(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_BK,m_rgbBkg);
+ m_rgbText = DBGetContactSettingDword(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_TEXT,m_rgbText);
+
+ m = DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_DELAY_MODE,static_cast<BYTE>(m_modeDelay));
+ if(m >= CPopupSettings::delayFromPopup && m <= CPopupSettings::delayPermanent)
+ {
+ m_modeDelay = static_cast<CPopupSettings::EDelayMode>(m);
+ }
+ m_wDelay = DBGetContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_DELAY_TIMEOUT,m_wDelay);
+ m_bUseHistory = 1 == DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_HISTORY_FLAG,m_bUseHistory);
+}
+
+void CPopupSettings::SaveForContact(HANDLE hContact)const
+{
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_MODE,static_cast<BYTE>(m_modeColour));
+ DBWriteContactSettingDword(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_BK,m_rgbBkg);
+ DBWriteContactSettingDword(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_COLOUR_TEXT,m_rgbText);
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_DELAY_MODE,static_cast<BYTE>(m_modeDelay));
+ DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_DELAY_TIMEOUT,m_wDelay);
+ DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_HISTORY_FLAG,m_bUseHistory);
+}
+
+CPopupSettings::EColourMode CPopupSettings::GetColourMode()const
+{
+ return m_modeColour;
+}
+
+void CPopupSettings::SetColourMode(EColourMode nMode)
+{
+ m_modeColour = nMode;
+}
+
+COLORREF CPopupSettings::GetColourBk()const
+{
+ return m_rgbBkg;
+}
+
+void CPopupSettings::SetColourBk(COLORREF rgb)
+{
+ m_rgbBkg = rgb;
+}
+
+COLORREF CPopupSettings::GetColourText()const
+{
+ return m_rgbText;
+}
+
+void CPopupSettings::SetColourText(COLORREF rgb)
+{
+ m_rgbText = rgb;
+}
+
+CPopupSettings::EDelayMode CPopupSettings::GetDelayMode()const
+{
+ return m_modeDelay;
+}
+
+void CPopupSettings::SetDelayMode(EDelayMode nMode)
+{
+ m_modeDelay = nMode;
+}
+
+WORD CPopupSettings::GetDelayTimeout()const
+{
+ return m_wDelay;
+}
+
+void CPopupSettings::SetDelayTimeout(WORD delay)
+{
+ m_wDelay = delay;
+}
+
+bool CPopupSettings::GetHistoryFlag()const
+{
+ return m_bUseHistory;
+}
+
+void CPopupSettings::SetHistoryFlag(bool flag)
+{
+ m_bUseHistory = flag;
+}
+
+bool ShowSettingsDlg(HWND hWndParent,CAdvProviderSettings* pAdvSettings)
+{
+ assert(pAdvSettings);
+
+ return (IDOK == DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_PROVIDER_ADV_SETTINGS),
+ hWndParent,
+ EditSettingsPerProviderDlgProc,
+ reinterpret_cast<LPARAM>(pAdvSettings)));
+}
+
+namespace
+{
+ void replace_invalid_char(tstring::value_type& rChar,tstring::value_type repl)
+ {
+ static const TCHAR charInvalidSigns[] = {_T('\\'), _T('/'), _T(':'), _T('*'), _T('?'), _T('\"'), _T('<'), _T('>'), _T('|')};
+
+ for(int i = 0; i < sizeof(charInvalidSigns)/sizeof(charInvalidSigns[0]);++i)
+ {
+ if(rChar == charInvalidSigns[i])
+ {
+ rChar = repl;
+ break;
+ }
+ }
+ }
+
+}
+
+tstring GenerateLogFileName(const tstring& rsLogFilePattern,
+ const tstring& rsQuoteSymbol,
+ int nFlags/* = glfnResolveAll*/)
+{
+ tstring sPath = rsLogFilePattern;
+ if(nFlags&glfnResolveQuoteName)
+ {
+ assert(false == rsQuoteSymbol.empty());
+
+ tstring::size_type n = sPath.find(g_pszVariableQuoteName);
+ if(tstring::npos != n)
+ {
+ tstring s = rsQuoteSymbol;
+ std::for_each(s.begin(),s.end(),boost::bind(replace_invalid_char,_1,_T('_')));
+ sPath.replace(n,lstrlen(g_pszVariableQuoteName),s.c_str());
+ }
+ }
+
+ if(nFlags&glfnResolveUserProfile)
+ {
+ REPLACEVARSDATA dat = {0};
+ dat.cbSize = sizeof(dat);
+ dat.dwFlags = RVF_TCHAR;
+
+ TCHAR* ptszParsedName = reinterpret_cast<TCHAR*>(CallService(MS_UTILS_REPLACEVARS,
+ reinterpret_cast<WPARAM>(sPath.c_str()),reinterpret_cast<LPARAM>(&dat)));
+ if(ptszParsedName)
+ {
+ sPath = ptszParsedName;
+ mir_free(ptszParsedName);
+ }
+ }
+
+ return sPath;
+}
+
+tstring GetContactLogFileName(HANDLE hContact)
+{
+ tstring result;
+
+ const CQuotesProviders::TQuotesProviderPtr& pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact);
+ if(pProvider)
+ {
+ tstring sPattern;
+ bool bUseContactSpecific = (DBGetContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,0) > 0);
+ if(bUseContactSpecific)
+ {
+ sPattern = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE);
+ }
+ else
+ {
+ CAdvProviderSettings global_settings(pProvider.get());
+ sPattern = global_settings.GetLogFileName();
+ }
+
+ result = GenerateLogFileName(sPattern,Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_SYMBOL));
+ }
+
+ return result;
+}
+
+tstring GetContactName(HANDLE hContact)
+{
+ tstring sDescription = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_DESCRIPTION);
+ if(sDescription.empty())
+ {
+ sDescription = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_SYMBOL);
+ }
+ return sDescription;
+}
diff --git a/protocols/Quotes/src/SettingsDlg.h b/protocols/Quotes/src/SettingsDlg.h
new file mode 100644
index 0000000000..569d0b7d2c
--- /dev/null
+++ b/protocols/Quotes/src/SettingsDlg.h
@@ -0,0 +1,118 @@
+#ifndef __E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__
+#define __E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__
+
+class IQuotesProvider;
+
+class CPopupSettings
+{
+public:
+ enum EColourMode
+ {
+ colourDefault,
+ colourUserDefined,
+ };
+
+ enum EDelayMode
+ {
+ delayFromPopup,
+ delayCustom,
+ delayPermanent
+ };
+
+public:
+ CPopupSettings(const IQuotesProvider* pQuotesProvider);
+
+ static COLORREF GetDefColourBk();
+ static COLORREF GetDefColourText();
+
+ void InitForContact(HANDLE hContact);
+ void SaveForContact(HANDLE hContact)const;
+
+ EColourMode GetColourMode()const;
+ void SetColourMode(EColourMode nMode);
+
+ COLORREF GetColourBk()const;
+ void SetColourBk(COLORREF rgb);
+
+ COLORREF GetColourText()const;
+ void SetColourText(COLORREF rgb);
+
+ EDelayMode GetDelayMode()const;
+ void SetDelayMode(EDelayMode nMode);
+
+ WORD GetDelayTimeout()const;
+ void SetDelayTimeout(WORD delay);
+
+ bool GetHistoryFlag()const;
+ void SetHistoryFlag(bool flag);
+
+private:
+ EColourMode m_modeColour;
+ EDelayMode m_modeDelay;
+ COLORREF m_rgbBkg;
+ COLORREF m_rgbText;
+ WORD m_wDelay;
+ bool m_bUseHistory;
+};
+
+
+class CAdvProviderSettings
+{
+public:
+ CAdvProviderSettings(const IQuotesProvider* pQuotesProvider);
+ ~CAdvProviderSettings();
+
+ void SaveToDb()const;
+
+ const IQuotesProvider* GetProviderPtr()const;
+
+ WORD GetLogMode()const;
+ void SetLogMode(WORD wMode);
+ tstring GetHistoryFormat()const;
+ void SetHistoryFormat(const tstring& rsFormat);
+ bool GetHistoryOnlyChangedFlag()const;
+ void SetHistoryOnlyChangedFlag(bool bMode);
+
+ tstring GetLogFileName()const;
+ void SetLogFileName(const tstring& rsFile);
+ tstring GetLogFormat()const;
+ void SetLogFormat(const tstring& rsFormat);
+ bool GetLogOnlyChangedFlag()const;
+ void SetLogOnlyChangedFlag(bool bMode);
+
+ const tstring& GetPopupFormat() const;
+ void SetPopupFormat(const tstring& val);
+
+ bool GetShowPopupIfValueChangedFlag() const;
+ void SetShowPopupIfValueChangedFlag(bool val);
+
+ CPopupSettings* GetPopupSettingsPtr()const;
+
+private:
+ const IQuotesProvider* m_pQuotesProvider;
+ WORD m_wLogMode;
+ tstring m_sFormatHistory;
+ bool m_bIsOnlyChangedHistory;
+ tstring m_sLogFileName;
+ tstring m_sFormatLogFile;
+ bool m_bIsOnlyChangedLogFile;
+ tstring m_sPopupFormat;
+ bool m_bShowPopupIfValueChanged;
+ mutable CPopupSettings* m_pPopupSettings;
+};
+
+void ShowSettingsDlg(HANDLE hContact);
+bool ShowSettingsDlg(HWND hWndParent,CAdvProviderSettings* pAdvSettings);
+
+enum
+{
+ glfnResolveQuoteName = 0x0001,
+ glfnResolveUserProfile = 0x0002,
+ glfnResolveAll = glfnResolveQuoteName|glfnResolveUserProfile,
+};
+tstring GenerateLogFileName(const tstring& rsLogFilePattern,const tstring& rsQuoteSymbol,int nFlags = glfnResolveAll);
+tstring GetContactLogFileName(HANDLE hContact);
+tstring GetContactName(HANDLE hContact);
+
+#endif //__E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__
+
diff --git a/protocols/Quotes/src/WinCtrlHelper.cpp b/protocols/Quotes/src/WinCtrlHelper.cpp
new file mode 100644
index 0000000000..619fe3d41b
--- /dev/null
+++ b/protocols/Quotes/src/WinCtrlHelper.cpp
@@ -0,0 +1,49 @@
+#include "stdafx.h"
+#include "QuotesProviderVisitorFormatSpecificator.h"
+#include "IQuotesProvider.h"
+#include "resource.h"
+#include "ModuleInfo.h"
+
+namespace
+{
+ INT_PTR CALLBACK VariableListDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
+ {
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hWnd);
+ const IQuotesProvider* pProvider = reinterpret_cast<const IQuotesProvider*>(lp);
+ CQuotesProviderVisitorFormatSpecificator visitor;
+ pProvider->Accept(visitor);
+
+ tostringstream o;
+ const CQuotesProviderVisitorFormatSpecificator::TFormatSpecificators& raSpec = visitor.GetSpecificators();
+ std::for_each(raSpec.begin(),raSpec.end(),
+ [&o](const CQuotesProviderVisitorFormatSpecificator::CFormatSpecificator& spec)
+ {
+ o << spec.m_sSymbol << _T('\t') << spec.m_sDesc << _T("\r\n");
+ });
+ ::SetDlgItemText(hWnd,IDC_EDIT_VARIABLE,o.str().c_str());
+ }
+ break;
+ case WM_COMMAND:
+ if(BN_CLICKED == HIWORD(wp) && (IDOK == LOWORD(wp) || IDCANCEL == LOWORD(wp)))
+ {
+ ::EndDialog(hWnd,IDOK);
+ }
+ break;
+ }
+
+ return FALSE;
+ }
+}
+
+void show_variable_list(HWND hwndParent,const IQuotesProvider* pProvider)
+{
+ ::DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_DIALOG_VARIABLE_LIST),
+ hwndParent,
+ VariableListDlgProc,
+ reinterpret_cast<LPARAM>(pProvider));
+}
diff --git a/protocols/Quotes/src/WinCtrlHelper.h b/protocols/Quotes/src/WinCtrlHelper.h
new file mode 100644
index 0000000000..d7f8957a86
--- /dev/null
+++ b/protocols/Quotes/src/WinCtrlHelper.h
@@ -0,0 +1,37 @@
+#ifndef __a05d6852_4497_4f28_85e1_48a15a170738_WinCtrlHelper_h__
+#define __a05d6852_4497_4f28_85e1_48a15a170738_WinCtrlHelper_h__
+
+class IQuotesProvider;
+
+inline tstring get_window_text(HWND hWnd)
+{
+ int cBytes = ::GetWindowTextLength(hWnd);
+
+ std::vector<TCHAR> aBuf(cBytes+1);
+ LPTSTR pBuffer = &*(aBuf.begin());
+ ::GetWindowText(hWnd,pBuffer,cBytes+1);
+
+ return tstring(pBuffer);
+}
+
+inline void prepare_edit_ctrl_for_error(HWND hwndEdit)
+{
+ ::SetFocus(hwndEdit);
+ ::SendMessage(hwndEdit, EM_SETSEL, 0, -1);
+ ::SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
+}
+
+void show_variable_list(HWND hwndParent,const IQuotesProvider* pProvider);
+
+inline int Quotes_MessageBox(HWND hWnd,LPCTSTR pszText,UINT nType = MB_OK)
+{
+ return ::MessageBox(hWnd,pszText,quotes_a2t(MIRANDANAME).c_str(),nType);
+}
+
+inline void spin_set_range(HWND hwndSpin,short nLower,short nUpper)
+{
+ ::SendMessage(hwndSpin,UDM_SETRANGE,0,MAKELPARAM(nUpper,nLower));
+}
+
+
+#endif //__a05d6852_4497_4f28_85e1_48a15a170738_WinCtrlHelper_h__
diff --git a/protocols/Quotes/src/WorkingThread.cpp b/protocols/Quotes/src/WorkingThread.cpp
new file mode 100644
index 0000000000..bc4d80b734
--- /dev/null
+++ b/protocols/Quotes/src/WorkingThread.cpp
@@ -0,0 +1,15 @@
+#include "StdAfx.h"
+#include "WorkingThread.h"
+
+#include "IQuotesProvider.h"
+
+void WorkingThread(void* pParam)
+{
+ IQuotesProvider* pProvider = reinterpret_cast<IQuotesProvider*>(pParam);
+ assert(pProvider);
+
+ if(pProvider)
+ {
+ pProvider->Run();
+ }
+}
diff --git a/protocols/Quotes/src/WorkingThread.h b/protocols/Quotes/src/WorkingThread.h
new file mode 100644
index 0000000000..a77734bb85
--- /dev/null
+++ b/protocols/Quotes/src/WorkingThread.h
@@ -0,0 +1,6 @@
+#ifndef __cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__
+#define __cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__
+
+void WorkingThread(void* pParam);
+
+#endif //__cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__
diff --git a/protocols/Quotes/src/XMLEngineMI.cpp b/protocols/Quotes/src/XMLEngineMI.cpp
new file mode 100644
index 0000000000..7e2adfb7d9
--- /dev/null
+++ b/protocols/Quotes/src/XMLEngineMI.cpp
@@ -0,0 +1,230 @@
+#include "StdAfx.h"
+#include "XMLEngineMI.h"
+
+XML_API xi;
+
+namespace
+{
+ class CXMLNodeMI : public IXMLNode,
+ private boost::noncopyable
+ {
+ public:
+ typedef boost::shared_ptr<IXMLNode> TXMLNodePtr;
+
+ public:
+ explicit CXMLNodeMI(HXML hXMl,bool bDestroy = false) : m_hXML(hXMl),m_bDestroy(bDestroy)
+ {
+ assert(m_hXML);
+ }
+
+ virtual ~CXMLNodeMI()
+ {
+ if(m_bDestroy)
+ {
+ xi.destroyNode(m_hXML);
+ }
+ }
+
+ virtual size_t GetChildCount()const
+ {
+ return xi.getChildCount(m_hXML);
+ }
+
+ virtual TXMLNodePtr GetChildNode(size_t nIndex)const
+ {
+ HXML h = xi.getChild(m_hXML, (int)nIndex);
+ if(h)
+ {
+ return TXMLNodePtr(new CXMLNodeMI(h));
+ }
+ else
+ {
+ return TXMLNodePtr();
+ }
+ }
+
+ virtual tstring GetText()const
+ {
+ tstring sResult;
+ LPCTSTR psz = xi.getText(m_hXML);
+ if(psz)
+ {
+ sResult = psz;
+ }
+
+ return sResult;
+ }
+
+ virtual tstring GetName()const
+ {
+ tstring sResult;
+ LPCTSTR psz = xi.getName(m_hXML);
+ if(psz)
+ {
+ sResult = psz;
+ }
+
+ return sResult;
+ }
+
+ virtual bool AddChild(const TXMLNodePtr& pNode)
+ {
+ CXMLNodeMI* pXML = dynamic_cast<CXMLNodeMI*>(pNode.get());
+ if(pXML)
+ {
+ xi.addChild2(pXML->m_hXML,m_hXML);
+ pXML->m_bDestroy = false;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ virtual bool AddAttribute(const tstring& rsName,const tstring& rsValue)
+ {
+ xi.addAttr(m_hXML,rsName.c_str(),rsValue.c_str());
+ return true;
+ }
+
+ virtual tstring GetAttributeValue(const tstring& rsAttrName)
+ {
+ LPCTSTR pszValue = xi.getAttrValue(m_hXML,rsAttrName.c_str());
+ return ((NULL != pszValue) ? tstring(pszValue) : tstring());
+ }
+
+ virtual void Write(tostream& o)const
+ {
+// struct safe_string
+// {
+// safe_string(LPTSTR p):m_p(p){}
+// ~safe_string(){xi.freeMem(m_p);}
+//
+// LPTSTR m_p;
+// };
+//
+// struct mir_safe_string
+// {
+// mir_safe_string(LPSTR p) : m_p(p){}
+// ~mir_safe_string(){mir_free(m_p);}
+//
+// LPSTR m_p;
+// };
+
+
+ safe_string<TCHAR> ss(xi.toString(m_hXML,NULL));
+ if(ss.m_p)
+ {
+ mir_safe_string<char> mss(mir_utf8encodeT(ss.m_p));
+ if(mss.m_p)
+ {
+ o << mss.m_p;
+ }
+ }
+ }
+
+ private:
+ HXML m_hXML;
+ bool m_bDestroy;
+ };
+}
+
+CXMLEngineMI::CXMLEngineMI()
+{
+}
+
+CXMLEngineMI::~CXMLEngineMI()
+{
+}
+
+IXMLNode::TXMLNodePtr CXMLEngineMI::LoadFile(const tstring& rsFileName)const
+{
+// struct mir_safe_string
+// {
+// mir_safe_string(LPTSTR p) : m_p(p){}
+// ~mir_safe_string(){mir_free(m_p);}
+//
+// LPTSTR m_p;
+// };
+
+
+ IXMLNode::TXMLNodePtr pResult;
+ FILE* stream;
+ if(0 == ::_tfopen_s(&stream,rsFileName.c_str(),_T("r")))
+ {
+ struct _stat st;
+ if (-1 != ::_fstat(::_fileno(stream),&st))
+ {
+ std::vector<char> aBuffer(st.st_size+1);
+ char* pBuffer = &*(aBuffer.begin());
+ size_t cBytes = ::fread(pBuffer,sizeof(char),st.st_size,stream);
+ if(cBytes > 0 && cBytes <= static_cast<size_t>(st.st_size))
+ {
+ pBuffer[cBytes] = '\0';
+
+ int nLen = (int)cBytes;
+ mir_safe_string<TCHAR> ss(mir_utf8decodeT(pBuffer));
+ if(ss.m_p)
+ {
+ HXML h = xi.parseString(ss.m_p,&nLen,NULL);
+ if(h)
+ {
+ pResult = IXMLNode::TXMLNodePtr(new CXMLNodeMI(h,true));
+ }
+ }
+ }
+ }
+ ::fclose(stream);
+ }
+
+ return pResult;
+}
+
+namespace
+{
+ IXMLNode::TXMLNodePtr create_node(const tstring& rsName,const tstring& rsText,bool bIsDecl)
+ {
+ IXMLNode::TXMLNodePtr pResult;
+ HXML h = xi.createNode(rsName.c_str(),rsText.c_str(),bIsDecl);
+ if(h)
+ {
+ pResult = IXMLNode::TXMLNodePtr(new CXMLNodeMI(h,true));
+ }
+
+ return pResult;
+ }
+}
+
+bool CXMLEngineMI::SaveFile(const tstring& rsFileName,const IXMLNode::TXMLNodePtr& pNode)const
+{
+ CXMLNodeMI* pXML = dynamic_cast<CXMLNodeMI*>(pNode.get());
+ if(pXML)
+ {
+ tofstream file(rsFileName.c_str());
+ if(file.good())
+ {
+ IXMLNode::TXMLNodePtr pRoot(create_node(_T("xml"),tstring(),true));
+ if(pRoot)
+ {
+ pRoot->AddAttribute(_T("version"),_T("1.0"));
+ pRoot->AddAttribute(_T("encoding"),_T("UTF-8"));
+ file << *pRoot;
+ }
+
+ if(file.good())
+ {
+ file << *pNode;
+ }
+ }
+
+ return file.good();
+ }
+
+ return false;
+}
+
+IXMLNode::TXMLNodePtr CXMLEngineMI::CreateNode(const tstring& rsName,const tstring& rsText)const
+{
+ return create_node(rsName,rsText,false);
+} \ No newline at end of file
diff --git a/protocols/Quotes/src/XMLEngineMI.h b/protocols/Quotes/src/XMLEngineMI.h
new file mode 100644
index 0000000000..5e5a51232f
--- /dev/null
+++ b/protocols/Quotes/src/XMLEngineMI.h
@@ -0,0 +1,17 @@
+#ifndef __0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__
+#define __0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__
+
+#include "ixmlengine.h"
+
+class CXMLEngineMI : public IXMLEngine
+{
+public:
+ CXMLEngineMI();
+ ~CXMLEngineMI();
+
+ virtual IXMLNode::TXMLNodePtr LoadFile(const tstring& rsFileName)const;
+ virtual bool SaveFile(const tstring& rsFileName,const IXMLNode::TXMLNodePtr& pNode)const;
+ virtual IXMLNode::TXMLNodePtr CreateNode(const tstring& rsName,const tstring& rsText)const;
+};
+
+#endif //__0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__
diff --git a/protocols/Quotes/src/resource.h b/protocols/Quotes/src/resource.h
new file mode 100644
index 0000000000..50ee0a637b
--- /dev/null
+++ b/protocols/Quotes/src/resource.h
@@ -0,0 +1,109 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Forex.rc
+//
+#define IDD_DIALOG_ECONOMIC_RATES 101
+#define IDI_ICON_MAIN 102
+#define IDD_DIALOG_QUOTE_INFO 102
+#define IDD_DIALOG_OPT_GOOGLE 103
+#define IDI_ICON_SECTION 110
+#define IDI_ICON_QUOTE 111
+#define IDI_ICON_UP 113
+#define IDI_ICON_DOWN 114
+#define IDD_CONTACT_SETTINGS 115
+#define IDI_ICON_NOTCHANGED 116
+#define IDD_CURRENCY_CONVERTER 116
+#define IDI_ICON_CURRENCY_CONVERTER 117
+#define IDD_DUKASCOPY_CHART 117
+#define IDD_CHART 117
+#define IDD_DIALOG_QUOTE_INFO_1 118
+#define IDI_ICON_REFRESH 118
+#define IDD_DIALOG_OPT_FINANCE 119
+#define IDI_ICON_IMPORT 119
+#define IDI_ICON_EXPORT 120
+#define IDD_PROVIDER_ADV_SETTINGS 120
+#define IDI_ICON_SWAP 121
+#define IDD_DIALOG_POPUP 121
+#define IDD_DIALOG_VARIABLE_LIST 123
+#define IDC_TREE_ECONOMIC_RATES 1001
+#define IDC_EDIT_REFRESH_RATE 1002
+#define IDC_SPIN_REFRESH_RATE 1003
+#define IDC_COMBO_REFRESH_RATE 1004
+#define IDC_STATIC_QUOTE_NAME 1008
+#define IDC_SYSLINK_PROVIDER 1009
+#define IDC_STATIC_CHART 1010
+#define IDC_STATIC_QUOTE_CHART 1010
+#define IDC_COMBO_CONVERT_FROM 1011
+#define IDC_COMBO_CONVERT_INTO 1012
+#define IDC_BUTTON_ADD 1013
+#define IDC_LIST_RATES 1014
+#define IDC_BUTTON_REMOVE 1015
+#define IDC_EDIT_RATE 1016
+#define IDC_EDIT_RATE_FETCH_TIME 1017
+#define IDC_EDIT_CONTACT_LIST_FORMAT 1018
+#define IDC_EDIT_PREVIOUS_RATE 1018
+#define IDC_BUTTON_DESCRIPTION 1019
+#define IDC_CHECK_INTERNAL_HISTORY 1020
+#define IDC_EDIT_STATUS_MESSAGE_FORMAT 1020
+#define IDC_CHECK_EXTERNAL_FILE 1021
+#define IDC_EDIT_FILE_NAME 1022
+#define IDC_EDIT_TENDENCY_FORMAT 1022
+#define IDC_BUTTON_BROWSE 1023
+#define IDC_STATIC_SELECT_FILE 1024
+#define IDC_EDIT_NAME 1025
+#define IDC_EDIT_HISTORY_FORMAT 1026
+#define IDC_EDIT_LOG_FILE_FORMAT 1027
+#define IDC_BUTTON_DESCRIPTION2 1028
+#define IDC_BUTTON_LOG_FILE_DESCRIPTION 1028
+#define IDC_STATIC_HISTORY_FORMAT 1029
+#define IDC_BUTTON_HISTORY_DESCRIPTION 1030
+#define IDC_STATIC_LOG_FILE_FORMAT 1031
+#define IDC_CHECK_HISTORY_CONDITION 1032
+#define IDC_CHECK_LOG_CONDITION2 1033
+#define IDC_CHECK_LOG_FILE_CONDITION 1033
+#define IDC_EDIT_VALUE 1033
+#define IDC_BUTTON_CONVERT 1034
+#define IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED 1034
+#define IDC_STATIC_POPUP_FORMAT 1035
+#define IDC_EDIT_POPUP_FORMAT 1036
+#define IDC_BUTTON_LOG_FILE_DESCRIPTION2 1037
+#define IDC_BUTTON_POPUP_FORMAT_DESCRIPTION 1037
+#define IDC_EDIT_RESULT 1039
+#define IDC_STATIC_IMAGE 1056
+#define IDC_EDIT_QUOTE 1059
+#define IDC_BUTTON_SWAP 1060
+#define IDC_BUTTON_ADVANCED_SETTINGS 1061
+#define IDC_BUTTON_POPUP_SETTINGS 1061
+#define IDC_CHECK_CONTACT_SPECIFIC 1062
+#define IDC_RADIO_DEFAULT_COLOURS 1063
+#define IDC_CHECK_SHOW_POPUP 1064
+#define IDC_RADIO_USER_DEFINED_COLOURS 1064
+#define IDC_MFCCOLORBUTTON1 1066
+#define IDC_CHECK1 1067
+#define IDC_CHECK_DONT_USE_POPUPHISTORY 1067
+#define IDC_COMBO_DATA_SOURCE 1068
+#define IDC_COMBO_FILTER 1069
+#define IDC_EDIT_FROM 1070
+#define IDC_EDIT_FROM2 1071
+#define IDC_EDIT_TO 1071
+#define IDC_STATIC_PROVIDER_NAME 1071
+#define IDC_DELAY 1072
+#define IDC_EDIT1 1072
+#define IDC_EDIT_VARIABLE 1072
+#define IDC_BGCOLOR 1074
+#define IDC_TEXTCOLOR 1075
+#define IDC_PREV 1076
+#define IDC_DELAYFROMPU 1093
+#define IDC_DELAYCUSTOM 1094
+#define IDC_DELAYPERMANENT 1095
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 124
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1073
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/protocols/Quotes/src/stdafx.cpp b/protocols/Quotes/src/stdafx.cpp
new file mode 100644
index 0000000000..e4738d8f60
--- /dev/null
+++ b/protocols/Quotes/src/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// Forex.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/protocols/Quotes/src/stdafx.h b/protocols/Quotes/src/stdafx.h
new file mode 100644
index 0000000000..5e72bc0e0b
--- /dev/null
+++ b/protocols/Quotes/src/stdafx.h
@@ -0,0 +1,154 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+#define MIRANDA_VER 0x0A00
+// #define CHART_IMPLEMENT
+#define TEST_IMPORT_EXPORT
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <string>
+#include <wininet.h>
+#include <atlbase.h>
+#include <atlconv.h>
+#include <mshtml.h>
+#include <atlcomcli.h>
+#include <comutil.h>
+#include <comdef.h>
+#include <commctrl.h>
+#include <ShellAPI.h>
+#include <msxml2.h>
+#include <sys\stat.h>
+#include <CommDlg.h>
+#include <windowsx.h>
+#include <atlenc.h>
+
+
+// Miranda headers
+#pragma warning(disable: 4996)
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#pragma warning(default: 4996)
+#include <win2k.h>
+#include <m_xml.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_cluiframes.h>
+#include <m_extraicons.h>
+#include <m_icolib.h>
+#include <m_clist.h>
+#include <m_genmenu.h>
+#include <m_netlib.h>
+#include <m_popup.h>
+#include <m_userinfo.h>
+#include <m_variables.h>
+
+// boost headers
+#include <boost\shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost\lexical_cast.hpp>
+#include <boost\noncopyable.hpp>
+#include <boost\scoped_ptr.hpp>
+#include <boost\foreach.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost\cast.hpp>
+#include "boost/date_time/c_local_time_adjustor.hpp"
+
+// stl headers
+#include <string>
+#include <vector>
+#include <sstream>
+#include <iomanip>
+#include <fstream>
+#include <map>
+
+
+typedef std::wstring tstring;
+typedef std::wostringstream tostringstream;
+typedef std::wistringstream tistringstream;
+typedef std::wofstream tofstream;
+typedef std::wifstream tifstream;
+typedef std::wostream tostream;
+typedef std::wistream tistream;
+typedef boost::posix_time::wtime_input_facet ttime_input_facet;
+typedef boost::posix_time::wtime_facet ttime_facet;
+
+inline int quotes_stricmp(LPCTSTR p1,LPCTSTR p2)
+{
+ return _tcsicmp(p1,p2);
+}
+
+inline std::string quotes_t2a(const TCHAR* t)
+{
+ std::string s;
+ char* p = mir_t2a(t);
+ if(p)
+ {
+ s = p;
+ mir_free(p);
+ }
+ return s;
+}
+
+inline tstring quotes_a2t(const char* s)
+{
+ tstring t;
+ TCHAR* p = mir_a2t(s);
+ if(p)
+ {
+ t = p;
+ mir_free(p);
+ }
+ return t;
+}
+namespace detail
+{
+ template<typename T,typename TD> struct safe_string_impl
+ {
+ typedef T* PTR;
+
+ safe_string_impl(PTR p) : m_p(p){}
+ ~safe_string_impl(){TD::dealloc(m_p);}
+
+ PTR m_p;
+ };
+
+ template<typename T> struct MirandaFree
+ {
+ static void dealloc(T* p){mir_free(p);}
+ };
+
+ template<typename T> struct OwnerFree
+ {
+ static void dealloc(T* p){::free(p);}
+ };
+}
+
+template<typename T> struct mir_safe_string : public detail::safe_string_impl<T,detail::MirandaFree<T>>
+{
+ mir_safe_string(PTR p) : detail::safe_string_impl<T,detail::MirandaFree<T>>(p){}
+};
+
+template<typename T> struct safe_string : public detail::safe_string_impl<T,detail::OwnerFree<T>>
+{
+ safe_string(PTR p) : detail::safe_string_impl<T,detail::OwnerFree<T>>(p){}
+};
+
+extern HINSTANCE g_hInstance;
+
+// #ifdef MIRANDA_VER
+// #undef MIRANDA_VER
+// #endif
+
+// TODO: reference additional headers your program requires here
diff --git a/protocols/Quotes/src/targetver.h b/protocols/Quotes/src/targetver.h
new file mode 100644
index 0000000000..f583181dfd
--- /dev/null
+++ b/protocols/Quotes/src/targetver.h
@@ -0,0 +1,24 @@
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Specifies that the minimum required platform is Windows Vista.
+#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
+#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
+#endif
diff --git a/protocols/Quotes/src/version.h b/protocols/Quotes/src/version.h
new file mode 100644
index 0000000000..4c954fff11
--- /dev/null
+++ b/protocols/Quotes/src/version.h
@@ -0,0 +1,21 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 0
+#define __RELEASE_NUM 24
+#define __BUILD_NUM 0
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+
+#define __STRINGIFY_IMPL(x) #x
+#define __STRINGIFY(x) __STRINGIFY_IMPL(x)
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS)
+
+#define __PLUGIN_NAME "Quotes"
+#define __INTERNAL_NAME "Quotes"
+#define __FILENAME "Quotes.dll"
+#define __DESCRIPTION "Show currency rates and economic quotes."
+#define __AUTHOR "Dioksin"
+#define __AUTHOREMAIL "dioksin@ua.fm"
+#define __AUTHORWEB "http://miranda-ng.org/"
+#define __COPYRIGHT "Don't worry!"
+#define SPECIAL_BUILD_STRING "5388"