summaryrefslogtreecommitdiff
path: root/protocols/Quotes
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-06-06 08:58:27 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-06-06 08:58:27 +0000
commitb61ba851da0157ace3bdfc1ebbf87156b0b76413 (patch)
treed6c567db57af1eb09c254a8bee13c305282334f8 /protocols/Quotes
parenta4c70f6bedb25e5cffb08dfc5cbc2597d1642d6b (diff)
protocols plugins moved to protocols
git-svn-id: http://svn.miranda-ng.org/main/trunk@327 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Quotes')
-rw-r--r--protocols/Quotes/Base64.cpp43
-rw-r--r--protocols/Quotes/Base64.h12
-rw-r--r--protocols/Quotes/Chart.h280
-rw-r--r--protocols/Quotes/ComHelper.cpp39
-rw-r--r--protocols/Quotes/ComHelper.h9
-rw-r--r--protocols/Quotes/CommonOptionDlg.cpp272
-rw-r--r--protocols/Quotes/CommonOptionDlg.h17
-rw-r--r--protocols/Quotes/CreateFilePath.cpp45
-rw-r--r--protocols/Quotes/CreateFilePath.h8
-rw-r--r--protocols/Quotes/CurrencyConverter.cpp309
-rw-r--r--protocols/Quotes/CurrencyConverter.h6
-rw-r--r--protocols/Quotes/DBUtils.cpp70
-rw-r--r--protocols/Quotes/DBUtils.h16
-rw-r--r--protocols/Quotes/EconomicRateInfo.h59
-rw-r--r--protocols/Quotes/ExtraImages.cpp143
-rw-r--r--protocols/Quotes/ExtraImages.h39
-rw-r--r--protocols/Quotes/Forex.cpp517
-rw-r--r--protocols/Quotes/Forex.rc573
-rw-r--r--protocols/Quotes/Forex.sln26
-rw-r--r--protocols/Quotes/Forex.vcxproj289
-rw-r--r--protocols/Quotes/Forex.vcxproj.filters307
-rw-r--r--protocols/Quotes/HTMLParserMS.cpp313
-rw-r--r--protocols/Quotes/HTMLParserMS.h36
-rw-r--r--protocols/Quotes/HTTPSession.cpp262
-rw-r--r--protocols/Quotes/HTTPSession.h27
-rw-r--r--protocols/Quotes/IHTMLEngine.h18
-rw-r--r--protocols/Quotes/IHTMLParser.h41
-rw-r--r--protocols/Quotes/IQuotesProvider.h41
-rw-r--r--protocols/Quotes/IXMLEngine.h43
-rw-r--r--protocols/Quotes/IconLib.cpp106
-rw-r--r--protocols/Quotes/IconLib.h21
-rw-r--r--protocols/Quotes/ImportExport.cpp850
-rw-r--r--protocols/Quotes/ImportExport.h11
-rw-r--r--protocols/Quotes/IsWithinAccuracy.h15
-rw-r--r--protocols/Quotes/LightMutex.cpp22
-rw-r--r--protocols/Quotes/LightMutex.h34
-rw-r--r--protocols/Quotes/Locale.cpp75
-rw-r--r--protocols/Quotes/Locale.h9
-rw-r--r--protocols/Quotes/Log.cpp56
-rw-r--r--protocols/Quotes/Log.h13
-rw-r--r--protocols/Quotes/ModuleInfo.cpp150
-rw-r--r--protocols/Quotes/ModuleInfo.h46
-rw-r--r--protocols/Quotes/OptionDukasCopy.cpp414
-rw-r--r--protocols/Quotes/OptionDukasCopy.h8
-rw-r--r--protocols/Quotes/QuoteChart.cpp408
-rw-r--r--protocols/Quotes/QuoteChart.h12
-rw-r--r--protocols/Quotes/QuoteInfoDlg.cpp353
-rw-r--r--protocols/Quotes/QuoteInfoDlg.h11
-rw-r--r--protocols/Quotes/QuotesProviderBase.cppbin0 -> 59044 bytes
-rw-r--r--protocols/Quotes/QuotesProviderBase.h112
-rw-r--r--protocols/Quotes/QuotesProviderDukasCopy.cppbin0 -> 15324 bytes
-rw-r--r--protocols/Quotes/QuotesProviderDukasCopy.h38
-rw-r--r--protocols/Quotes/QuotesProviderFinance.cpp318
-rw-r--r--protocols/Quotes/QuotesProviderFinance.h21
-rw-r--r--protocols/Quotes/QuotesProviderGoogle.cpp543
-rw-r--r--protocols/Quotes/QuotesProviderGoogle.h42
-rw-r--r--protocols/Quotes/QuotesProviderGoogleFinance.cpp366
-rw-r--r--protocols/Quotes/QuotesProviderGoogleFinance.h25
-rw-r--r--protocols/Quotes/QuotesProviderVisitor.h25
-rw-r--r--protocols/Quotes/QuotesProviderVisitorDbSettings.cpp157
-rw-r--r--protocols/Quotes/QuotesProviderVisitorDbSettings.h49
-rw-r--r--protocols/Quotes/QuotesProviderVisitorFormatSpecificator.cpp63
-rw-r--r--protocols/Quotes/QuotesProviderVisitorFormatSpecificator.h36
-rw-r--r--protocols/Quotes/QuotesProviderVisitorFormater.cpp216
-rw-r--r--protocols/Quotes/QuotesProviderVisitorFormater.h32
-rw-r--r--protocols/Quotes/QuotesProviderVisitorTendency.cpp70
-rw-r--r--protocols/Quotes/QuotesProviderVisitorTendency.h29
-rw-r--r--protocols/Quotes/QuotesProviderYahoo.cpp193
-rw-r--r--protocols/Quotes/QuotesProviderYahoo.h20
-rw-r--r--protocols/Quotes/QuotesProviders.cpp120
-rw-r--r--protocols/Quotes/QuotesProviders.h32
-rw-r--r--protocols/Quotes/SettingsDlg.cpp1148
-rw-r--r--protocols/Quotes/SettingsDlg.h118
-rw-r--r--protocols/Quotes/Utility/DukasCopy.py48
-rw-r--r--protocols/Quotes/Utility/Dukascopy.xml1635
-rw-r--r--protocols/Quotes/Utility/Google.py52
-rw-r--r--protocols/Quotes/Utility/GoogleFinance.xml7
-rw-r--r--protocols/Quotes/Utility/Quotes_Readme.txt112
-rw-r--r--protocols/Quotes/Utility/Yahoo.xml7
-rw-r--r--protocols/Quotes/Utility/google.xml91
-rw-r--r--protocols/Quotes/Version.rc41
-rw-r--r--protocols/Quotes/WinCtrlHelper.cpp49
-rw-r--r--protocols/Quotes/WinCtrlHelper.h37
-rw-r--r--protocols/Quotes/WorkingThread.cpp15
-rw-r--r--protocols/Quotes/WorkingThread.h6
-rw-r--r--protocols/Quotes/XMLEngineMI.cpp230
-rw-r--r--protocols/Quotes/XMLEngineMI.h17
-rw-r--r--protocols/Quotes/dllmain.cpp23
-rw-r--r--protocols/Quotes/proto_Quotes/proto_Quotes.rc122
-rw-r--r--protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj129
-rw-r--r--protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj.filters28
-rw-r--r--protocols/Quotes/res/CurrencyConverter.icobin0 -> 5430 bytes
-rw-r--r--protocols/Quotes/res/Export quotes.icobin0 -> 1150 bytes
-rw-r--r--protocols/Quotes/res/Import quotes.icobin0 -> 1150 bytes
-rw-r--r--protocols/Quotes/res/Refresh.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/Section.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/down.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/main.icobin0 -> 1150 bytes
-rw-r--r--protocols/Quotes/res/notchanged.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/proto_na.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/proto_occupied.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/proto_offline.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/proto_online.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/quote.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/res/swap.icobin0 -> 318 bytes
-rw-r--r--protocols/Quotes/res/up.icobin0 -> 1406 bytes
-rw-r--r--protocols/Quotes/resource.h109
-rw-r--r--protocols/Quotes/stdafx.cpp8
-rw-r--r--protocols/Quotes/stdafx.h165
-rw-r--r--protocols/Quotes/targetver.h24
-rw-r--r--protocols/Quotes/version.h25
111 files changed, 13227 insertions, 0 deletions
diff --git a/protocols/Quotes/Base64.cpp b/protocols/Quotes/Base64.cpp
new file mode 100644
index 0000000000..1854fb42fd
--- /dev/null
+++ b/protocols/Quotes/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/Base64.h b/protocols/Quotes/Base64.h
new file mode 100644
index 0000000000..3f911bfeb8
--- /dev/null
+++ b/protocols/Quotes/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/Chart.h b/protocols/Quotes/Chart.h
new file mode 100644
index 0000000000..62a658d818
--- /dev/null
+++ b/protocols/Quotes/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/ComHelper.cpp b/protocols/Quotes/ComHelper.cpp
new file mode 100644
index 0000000000..e15d05d739
--- /dev/null
+++ b/protocols/Quotes/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/ComHelper.h b/protocols/Quotes/ComHelper.h
new file mode 100644
index 0000000000..0b4140d80d
--- /dev/null
+++ b/protocols/Quotes/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/CommonOptionDlg.cpp b/protocols/Quotes/CommonOptionDlg.cpp
new file mode 100644
index 0000000000..0b460665c5
--- /dev/null
+++ b/protocols/Quotes/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/CommonOptionDlg.h b/protocols/Quotes/CommonOptionDlg.h
new file mode 100644
index 0000000000..b9f696362a
--- /dev/null
+++ b/protocols/Quotes/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/CreateFilePath.cpp b/protocols/Quotes/CreateFilePath.cpp
new file mode 100644
index 0000000000..f1a3e4f331
--- /dev/null
+++ b/protocols/Quotes/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(CModuleInfo::GetModuleHandle(),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/CreateFilePath.h b/protocols/Quotes/CreateFilePath.h
new file mode 100644
index 0000000000..f097e59a52
--- /dev/null
+++ b/protocols/Quotes/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/CurrencyConverter.cpp b/protocols/Quotes/CurrencyConverter.cpp
new file mode 100644
index 0000000000..0e04d2562e
--- /dev/null
+++ b/protocols/Quotes/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(CModuleInfo::GetModuleHandle(), MAKEINTRESOURCE(IDD_CURRENCY_CONVERTER), NULL, CurrencyConverterDlgProc, 0);
+ }
+
+ return 0;
+}
diff --git a/protocols/Quotes/CurrencyConverter.h b/protocols/Quotes/CurrencyConverter.h
new file mode 100644
index 0000000000..9af7c6bca1
--- /dev/null
+++ b/protocols/Quotes/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/DBUtils.cpp b/protocols/Quotes/DBUtils.cpp
new file mode 100644
index 0000000000..11c0fb3d0d
--- /dev/null
+++ b/protocols/Quotes/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/DBUtils.h b/protocols/Quotes/DBUtils.h
new file mode 100644
index 0000000000..d154e99075
--- /dev/null
+++ b/protocols/Quotes/DBUtils.h
@@ -0,0 +1,16 @@
+#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);
+
+#ifdef _UNICODE
+#define Quotes_DBGetStringT Quotes_DBGetStringW
+#else
+#define Quotes_DBGetStringT Quotes_DBGetStringA
+#endif
+
+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/EconomicRateInfo.h b/protocols/Quotes/EconomicRateInfo.h
new file mode 100644
index 0000000000..73e269619c
--- /dev/null
+++ b/protocols/Quotes/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/ExtraImages.cpp b/protocols/Quotes/ExtraImages.cpp
new file mode 100644
index 0000000000..35a59a8c1d
--- /dev/null
+++ b/protocols/Quotes/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/ExtraImages.h b/protocols/Quotes/ExtraImages.h
new file mode 100644
index 0000000000..ec8ae01e39
--- /dev/null
+++ b/protocols/Quotes/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/Forex.cpp b/protocols/Quotes/Forex.cpp
new file mode 100644
index 0000000000..3bb25a9f99
--- /dev/null
+++ b/protocols/Quotes/Forex.cpp
@@ -0,0 +1,517 @@
+// 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_updater.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"
+
+PLUGINLINK* pluginLink = NULL;
+struct MM_INTERFACE mmi;
+struct UTF8_INTERFACE utfi;
+int hLangpack;
+
+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,
+ 0
+#ifdef _UNICODE
+ // {E882056D-0D1D-4131-9A98-404CBAEA6A9C}
+ ,{0xe882056d, 0xd1d, 0x4131, { 0x9a, 0x98, 0x40, 0x4c, 0xba, 0xea, 0x6a, 0x9c } }
+#else
+ // {8CE16273-89EA-4e12-8CF1-2D38AB6BF431}
+ ,{0x8ce16273, 0x89ea, 0x4e12, { 0x8c, 0xf1, 0x2d, 0x38, 0xab, 0x6b, 0xf4, 0x31 } }
+#endif
+ };
+
+ 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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast<LPARAM>(&mi)));
+ g_ahMenus.push_back(hMenu);
+ h = CreateServiceFunction(mi.pszService, QuotesMenu_ImportAll);
+ g_ahServices.push_back(h);
+#endif
+
+ bool bSubGroups = 1 == ServiceExists(MS_CLIST_ADDSUBGROUPMENUITEM);
+
+ 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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast<LPARAM>(&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 = reinterpret_cast<HGENMENU>(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast<LPARAM>(&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();
+
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update update = {0};
+ char szVersion[16];
+
+ update.szComponentName = Global_pluginInfo.shortName;
+ update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=4021";
+ update.pbVersionPrefix = (BYTE *)"<span class=\"fileNameHeader\">Quotes ";
+ update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix);
+ update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=4021";
+
+ update.szBetaVersionURL = NULL;
+ update.pbBetaVersionPrefix = NULL;
+ update.cpbBetaVersionPrefix = 0;
+ update.szBetaUpdateURL = NULL;
+
+ update.pbVersion = (BYTE*)CreateVersionString(Global_pluginInfo.version,szVersion);
+ update.cpbVersion = (int)strlen((char *)update.pbVersion);
+
+ update.szBetaChangelogURL = NULL;
+
+ CallService(MS_UPDATE_REGISTER,0,(WPARAM)&update);
+ }
+
+ 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*/)
+ {
+// USES_CONVERSION;
+
+ const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr();
+ const CQuotesProviders::TQuotesProviders& rapProviders = pProviders->GetProviders();
+
+ OPTIONSDIALOGPAGE odp;
+ ZeroMemory(&odp,sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.position = 910000000;
+ odp.hInstance = CModuleInfo::GetModuleHandle();
+ tstring sProtocolName = quotes_a2t(QUOTES_PROTOCOL_NAME);
+ odp.ptszTitle = const_cast<TCHAR*>(sProtocolName.c_str());//A2T(QUOTES_PROTOCOL_NAME);
+ odp.ptszGroup = _T("Network");
+ odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN);
+ odp.flags = ODPF_TCHAR|ODPF_USERINFOTAB;
+
+ 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;
+// }
+
+}
+
+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* MirandaPluginInterfaces()
+ {
+ static const MUUID interfaces[] = {MIID_PROTOCOL,MIID_QUOTES,MIID_LAST};
+ return interfaces;
+ }
+
+ int __declspec(dllexport) Load(PLUGINLINK *link)
+ {
+ pluginLink = link;
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+ 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/Forex.rc b/protocols/Quotes/Forex.rc
new file mode 100644
index 0000000000..2bfbe8eb69
--- /dev/null
+++ b/protocols/Quotes/Forex.rc
@@ -0,0 +1,573 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1251)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON_MAIN ICON "res\\main.ico"
+IDI_ICON_SECTION ICON "res\\Section.ico"
+IDI_ICON_QUOTE ICON "res\\quote.ico"
+IDI_ICON_UP ICON "res\\up.ico"
+IDI_ICON_DOWN ICON "res\\down.ico"
+IDI_ICON_CURRENCY_CONVERTER ICON "res\\CurrencyConverter.ico"
+IDI_ICON_REFRESH ICON "res\\Refresh.ico"
+IDI_ICON_EXPORT ICON "res\\Export quotes.ico"
+IDI_ICON_SWAP ICON "res\\swap.ico"
+IDI_ICON_IMPORT ICON "res\\Import quotes.ico"
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian (Russia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG_VARIABLE_LIST DIALOGEX 0, 0, 216, 182
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Variable List"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,83,161,50,14
+ EDITTEXT IDC_EDIT_VARIABLE,7,7,202,147,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_DIALOG_VARIABLE_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 209
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 175
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Russian (Russia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON_NOTCHANGED ICON "res\\notchanged.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CONTACT_SETTINGS DIALOGEX 0, 0, 323, 269
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Edit Settings"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Use contact specific settings",IDC_CHECK_CONTACT_SPECIFIC,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,22,151,10
+ GROUPBOX "Log",IDC_STATIC,26,35,290,137
+ CONTROL "Use &Internal History",IDC_CHECK_INTERNAL_HISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,49,140,10
+ LTEXT "&Format:",IDC_STATIC_HISTORY_FORMAT,50,63,47,8
+ EDITTEXT IDC_EDIT_HISTORY_FORMAT,101,61,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Variables...",IDC_BUTTON_HISTORY_DESCRIPTION,241,61,65,12
+ CONTROL "&Add to History only if Value Changed",IDC_CHECK_HISTORY_CONDITION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,77,252,10
+ CONTROL "Use &External File",IDC_CHECK_EXTERNAL_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,97,127,10
+ LTEXT "&Select File:",IDC_STATIC_SELECT_FILE,50,113,49,8
+ EDITTEXT IDC_EDIT_FILE_NAME,101,111,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Browse...",IDC_BUTTON_BROWSE,241,111,65,12
+ LTEXT "Variables Allowed: %miranda_userdata%,%quotename%",IDC_STATIC,50,126,257,8,WS_DISABLED
+ LTEXT "F&ormat:",IDC_STATIC_LOG_FILE_FORMAT,50,142,47,8
+ EDITTEXT IDC_EDIT_LOG_FILE_FORMAT,101,140,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "V&ariables...",IDC_BUTTON_LOG_FILE_DESCRIPTION,241,140,65,12
+ CONTROL "Add to &Log only if Value Changed",IDC_CHECK_LOG_FILE_CONDITION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,156,224,10
+ CONTROL "Show &Popup Window",IDC_CHECK_SHOW_POPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,180,120,10
+ LTEXT "F&ormat:",IDC_STATIC_POPUP_FORMAT,30,197,47,8
+ EDITTEXT IDC_EDIT_POPUP_FORMAT,81,195,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "V&ariables...",IDC_BUTTON_POPUP_FORMAT_DESCRIPTION,221,195,65,12
+ CONTROL "Show Popup Window Only if Value &Changed",IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,30,210,245,10
+ DEFPUSHBUTTON "OK",IDOK,107,248,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,163,248,50,14
+ EDITTEXT IDC_EDIT_NAME,7,7,309,12,ES_CENTER | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "Popup settings...",IDC_BUTTON_POPUP_SETTINGS,98,222,111,14
+END
+
+IDD_CURRENCY_CONVERTER DIALOGEX 0, 0, 347, 101
+STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Currency Converter"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ EDITTEXT IDC_EDIT_VALUE,6,7,56,13,ES_AUTOHSCROLL
+ COMBOBOX IDC_COMBO_CONVERT_FROM,68,7,105,44,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&to:",IDC_STATIC,214,9,14,8
+ COMBOBOX IDC_COMBO_CONVERT_INTO,230,7,105,44,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Swap",IDC_BUTTON_SWAP,180,7,24,12,BS_ICON
+ PUSHBUTTON "Convert",IDC_BUTTON_CONVERT,134,24,79,14
+ EDITTEXT IDC_EDIT_RESULT,7,44,328,12,ES_CENTER | ES_AUTOHSCROLL | ES_READONLY
+ CONTROL "Info provided by <a href=""http://www.google.com"">Google</a>",IDC_SYSLINK_PROVIDER,
+ "SysLink",WS_TABSTOP,7,61,159,11
+ PUSHBUTTON "Close",IDCANCEL,148,80,50,14
+END
+
+IDD_CHART DIALOGEX 0, 0, 394, 279
+STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT
+CAPTION "Chart"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Info provided by <a href=""http://www.dukascopy.com"">Dukascopy Swiss Forex Group</a>",IDC_SYSLINK_PROVIDER,
+ "SysLink",WS_TABSTOP,7,261,176,11
+ PUSHBUTTON "Close",IDCANCEL,337,258,50,14
+ CONTROL "",IDC_STATIC_IMAGE,"Static",SS_ETCHEDFRAME | NOT WS_VISIBLE,7,24,380,230,WS_EX_TRANSPARENT
+ LTEXT "Get data from:",IDC_STATIC,7,9,69,8
+ COMBOBOX IDC_COMBO_DATA_SOURCE,79,7,85,54,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Filter:",IDC_STATIC,170,9,29,8
+ COMBOBOX IDC_COMBO_FILTER,204,7,69,47,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_EDIT_FROM,277,7,53,12,ES_AUTOHSCROLL | NOT WS_VISIBLE
+ EDITTEXT IDC_EDIT_TO,334,7,53,12,ES_AUTOHSCROLL | NOT WS_VISIBLE
+END
+
+IDD_PROVIDER_ADV_SETTINGS DIALOGEX 0, 0, 303, 260
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Edit Settings"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Log",IDC_STATIC,7,23,289,139
+ CONTROL "Use &Internal History",IDC_CHECK_INTERNAL_HISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,37,140,10
+ LTEXT "&Format:",IDC_STATIC_HISTORY_FORMAT,30,51,47,8
+ EDITTEXT IDC_EDIT_HISTORY_FORMAT,81,49,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Variables...",IDC_BUTTON_HISTORY_DESCRIPTION,221,49,65,12
+ CONTROL "&Add to History only if Value Changed",IDC_CHECK_HISTORY_CONDITION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,30,65,252,10
+ CONTROL "Use &External File",IDC_CHECK_EXTERNAL_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,85,127,10
+ LTEXT "&Select File:",IDC_STATIC_SELECT_FILE,30,101,49,8
+ EDITTEXT IDC_EDIT_FILE_NAME,81,99,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Browse...",IDC_BUTTON_BROWSE,221,99,65,12
+ LTEXT "Variables Allowed: %miranda_userdata%,%quotename%",IDC_STATIC,30,115,257,8,WS_DISABLED
+ LTEXT "F&ormat:",IDC_STATIC_LOG_FILE_FORMAT,30,131,47,8
+ EDITTEXT IDC_EDIT_LOG_FILE_FORMAT,81,129,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "V&ariables...",IDC_BUTTON_LOG_FILE_DESCRIPTION,221,129,65,12
+ CONTROL "Add to &Log only if Value Changed",IDC_CHECK_LOG_FILE_CONDITION,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,30,145,224,10
+ CONTROL "Show &Popup Window",IDC_CHECK_SHOW_POPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,167,120,10
+ LTEXT "F&ormat:",IDC_STATIC_POPUP_FORMAT,30,184,47,8
+ EDITTEXT IDC_EDIT_POPUP_FORMAT,81,182,137,12,ES_AUTOHSCROLL
+ PUSHBUTTON "V&ariables...",IDC_BUTTON_POPUP_FORMAT_DESCRIPTION,221,182,65,12
+ CONTROL "Show Popup Window Only if Value &Changed",IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,30,197,245,10
+ DEFPUSHBUTTON "OK",IDOK,98,239,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,154,239,50,14
+ EDITTEXT IDC_EDIT_NAME,7,7,289,12,ES_CENTER | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "Popup settings...",IDC_BUTTON_POPUP_SETTINGS,86,210,111,14
+END
+
+IDD_DIALOG_POPUP DIALOGEX 0, 0, 319, 160
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Popup Window Settings"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Colours",IDC_STATIC,7,7,149,82,WS_GROUP
+ CONTROL "Use default colours",IDC_RADIO_DEFAULT_COLOURS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,15,20,82,10
+ CONTROL "Use user-defined colours",IDC_RADIO_USER_DEFINED_COLOURS,
+ "Button",BS_AUTORADIOBUTTON,15,34,97,10
+ LTEXT "Background colour",IDC_STATIC,70,53,66,8
+ CONTROL "",IDC_BGCOLOR,"ColourPicker",WS_TABSTOP,26,49,35,14
+ LTEXT "Text colour",IDC_STATIC,70,71,66,8
+ CONTROL "",IDC_TEXTCOLOR,"ColourPicker",WS_TABSTOP,26,67,35,14
+ GROUPBOX "Delay",IDC_STATIC,162,6,149,82,WS_GROUP
+ CONTROL "From PopUp plugin",IDC_DELAYFROMPU,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,174,20,76,10
+ CONTROL "Custom",IDC_DELAYCUSTOM,"Button",BS_AUTORADIOBUTTON,174,35,47,10
+ CONTROL "Permanent",IDC_DELAYPERMANENT,"Button",BS_AUTORADIOBUTTON,174,50,50,10
+ EDITTEXT IDC_DELAY,252,33,35,14,ES_AUTOHSCROLL | ES_NUMBER | WS_GROUP
+ CONTROL "Do not add to popup's history",IDC_CHECK_DONT_USE_POPUPHISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,96,200,10
+ PUSHBUTTON "Preview",IDC_PREV,134,114,50,14
+ DEFPUSHBUTTON "OK",IDOK,101,139,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,167,139,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_CONTACT_SETTINGS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 316
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 262
+ END
+
+ IDD_CURRENCY_CONVERTER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 335
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 94
+ END
+
+ IDD_CHART, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 387
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 272
+ END
+
+ IDD_PROVIDER_ADV_SETTINGS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 296
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 253
+ END
+
+ IDD_DIALOG_POPUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 312
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 153
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_CHART DLGINIT
+BEGIN
+ IDC_COMBO_DATA_SOURCE, 0x403, 9, 0
+0x6f4c, 0x2067, 0x6946, 0x656c, "\000"
+ IDC_COMBO_DATA_SOURCE, 0x403, 18, 0
+0x694d, 0x6172, 0x646e, 0x2761, 0x2073, 0x6948, 0x7473, 0x726f, 0x0079,
+
+ IDC_COMBO_FILTER, 0x403, 4, 0
+0x6c41, 0x006c,
+ IDC_COMBO_FILTER, 0x403, 9, 0
+0x614c, 0x7473, 0x4420, 0x7961, "\000"
+ IDC_COMBO_FILTER, 0x403, 10, 0
+0x614c, 0x7473, 0x5720, 0x6565, 0x006b,
+ IDC_COMBO_FILTER, 0x403, 11, 0
+0x614c, 0x7473, 0x4d20, 0x6e6f, 0x6874, "\000"
+ IDC_COMBO_FILTER, 0x403, 10, 0
+0x614c, 0x7473, 0x5920, 0x6165, 0x0072,
+ IDC_COMBO_FILTER, 0x403, 13, 0
+0x7355, 0x7265, 0x442d, 0x6665, 0x6e69, 0x6465, "\000"
+ 0
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United Kingdom) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG_ECONOMIC_RATES DIALOGEX 0, 0, 310, 230
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "&Choose Quotes to watch in contact list:",IDC_STATIC,7,7,298,8
+ CONTROL "",IDC_TREE_ECONOMIC_RATES,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_CHECKBOXES | TVS_NOHSCROLL | WS_BORDER | WS_TABSTOP,21,18,284,126
+ LTEXT "&Refresh Quotes Every:",IDC_STATIC,7,150,108,8
+ EDITTEXT IDC_EDIT_REFRESH_RATE,118,148,40,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_SPIN_REFRESH_RATE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,230,147,11,14
+ COMBOBOX IDC_COMBO_REFRESH_RATE,161,148,69,59,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Display in Contact List as:",IDC_STATIC,7,165,109,8
+ EDITTEXT IDC_EDIT_CONTACT_LIST_FORMAT,118,162,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Variables...",IDC_BUTTON_DESCRIPTION,240,162,65,12
+ LTEXT "&Status Message:",IDC_STATIC,7,178,107,8
+ EDITTEXT IDC_EDIT_STATUS_MESSAGE_FORMAT,118,176,120,12,ES_AUTOHSCROLL
+ LTEXT "&Tendency:",IDC_STATIC,7,192,102,8
+ EDITTEXT IDC_EDIT_TENDENCY_FORMAT,118,190,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Advanced Settings...",IDC_BUTTON_ADVANCED_SETTINGS,103,208,110,14
+END
+
+IDD_DIALOG_QUOTE_INFO DIALOGEX 0, 0, 222, 132
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Static",IDC_STATIC_QUOTE_NAME,7,7,208,8
+ CONTROL "<a>SysLink1</a>",IDC_SYSLINK_PROVIDER,"SysLink",WS_TABSTOP,7,110,208,14
+ LTEXT "Current Rate:",IDC_STATIC,21,62,72,8
+ EDITTEXT IDC_EDIT_RATE,97,60,61,12,ES_AUTOHSCROLL | ES_READONLY
+ LTEXT "Rate Fetch Time:",IDC_STATIC,21,47,73,8
+ EDITTEXT IDC_EDIT_RATE_FETCH_TIME,97,45,98,12,ES_AUTOHSCROLL | ES_READONLY
+ LTEXT "Previous Rate:",IDC_STATIC,21,77,71,8
+ EDITTEXT IDC_EDIT_PREVIOUS_RATE,97,75,61,12,ES_AUTOHSCROLL | ES_READONLY
+END
+
+IDD_DIALOG_OPT_GOOGLE DIALOGEX 0, 0, 310, 233
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "&Convert:",IDC_STATIC,7,9,56,8
+ COMBOBOX IDC_COMBO_CONVERT_FROM,64,7,105,44,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&to:",IDC_STATIC,175,9,21,8
+ COMBOBOX IDC_COMBO_CONVERT_INTO,200,7,105,44,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Add",IDC_BUTTON_ADD,255,35,50,14
+ LTEXT "&Watched currency rates:",IDC_STATIC,7,23,110,8
+ LISTBOX IDC_LIST_RATES,19,35,231,111,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Remove",IDC_BUTTON_REMOVE,255,52,50,14
+ LTEXT "&Refresh Rates Every:",IDC_STATIC,7,153,107,8
+ EDITTEXT IDC_EDIT_REFRESH_RATE,117,151,40,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_SPIN_REFRESH_RATE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,234,150,11,14
+ COMBOBOX IDC_COMBO_REFRESH_RATE,160,151,69,59,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Display in Contact List as:",IDC_STATIC,7,168,107,8
+ EDITTEXT IDC_EDIT_CONTACT_LIST_FORMAT,117,165,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Variables...",IDC_BUTTON_DESCRIPTION,240,165,65,12
+ LTEXT "&Status Message:",IDC_STATIC,7,181,108,8
+ EDITTEXT IDC_EDIT_STATUS_MESSAGE_FORMAT,117,179,120,12,ES_AUTOHSCROLL
+ LTEXT "&Tendency:",IDC_STATIC,7,195,102,8
+ EDITTEXT IDC_EDIT_TENDENCY_FORMAT,117,193,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Advanced Settings...",IDC_BUTTON_ADVANCED_SETTINGS,102,211,110,14
+END
+
+IDD_DIALOG_QUOTE_INFO_1 DIALOGEX 0, 0, 222, 143
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Quote\\Rate Info"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Static",IDC_STATIC_QUOTE_NAME,7,7,208,8
+ CONTROL "<a>SysLink1</a>",IDC_SYSLINK_PROVIDER,"SysLink",WS_TABSTOP,7,98,208,14
+ LTEXT "Current Rate:",IDC_STATIC,15,57,81,8
+ EDITTEXT IDC_EDIT_RATE,108,55,61,12,ES_AUTOHSCROLL | ES_READONLY
+ LTEXT "Rate Fetch Time:",IDC_STATIC,15,42,81,8
+ EDITTEXT IDC_EDIT_RATE_FETCH_TIME,108,40,98,12,ES_AUTOHSCROLL | ES_READONLY
+ LTEXT "Previous Rate:",IDC_STATIC,15,72,92,8
+ EDITTEXT IDC_EDIT_PREVIOUS_RATE,108,70,61,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "Close",IDOK,85,122,50,14
+END
+
+IDD_DIALOG_OPT_FINANCE DIALOGEX 0, 0, 310, 232
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Type &Stock Name or Symbol:",IDC_STATIC,7,10,96,8
+ EDITTEXT IDC_EDIT_QUOTE,106,7,143,14,ES_AUTOHSCROLL
+ PUSHBUTTON "&Add",IDC_BUTTON_ADD,255,7,50,14
+ LTEXT "&Watched Quotes:",IDC_STATIC,7,23,110,8
+ LISTBOX IDC_LIST_RATES,19,35,231,112,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Remove",IDC_BUTTON_REMOVE,255,35,50,14
+ LTEXT "&Refresh Rates Every:",IDC_STATIC,7,153,107,8
+ EDITTEXT IDC_EDIT_REFRESH_RATE,117,151,40,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_SPIN_REFRESH_RATE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,234,150,11,14
+ COMBOBOX IDC_COMBO_REFRESH_RATE,160,151,69,59,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Display in Contact List as:",IDC_STATIC,7,168,107,8
+ EDITTEXT IDC_EDIT_CONTACT_LIST_FORMAT,117,165,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Variables...",IDC_BUTTON_DESCRIPTION,240,165,65,12
+ LTEXT "Status &Message:",IDC_STATIC,7,181,108,8
+ EDITTEXT IDC_EDIT_STATUS_MESSAGE_FORMAT,117,179,120,12,ES_AUTOHSCROLL
+ LTEXT "&Tendency:",IDC_STATIC,7,195,102,8
+ EDITTEXT IDC_EDIT_TENDENCY_FORMAT,117,193,120,12,ES_AUTOHSCROLL
+ PUSHBUTTON "&Advanced Settings...",IDC_BUTTON_ADVANCED_SETTINGS,99,210,110,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_DIALOG_ECONOMIC_RATES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 305
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 222
+ END
+
+ IDD_DIALOG_QUOTE_INFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 215
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 124
+ END
+
+ IDD_DIALOG_OPT_GOOGLE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 305
+ VERTGUIDE, 249
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 225
+ END
+
+ IDD_DIALOG_QUOTE_INFO_1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 215
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 135
+ END
+
+ IDD_DIALOG_OPT_FINANCE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 305
+ VERTGUIDE, 249
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 224
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_DIALOG_ECONOMIC_RATES DLGINIT
+BEGIN
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x6553, 0x6f63, 0x646e, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x694d, 0x756e, 0x6574, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ 0
+END
+
+IDD_DIALOG_OPT_GOOGLE DLGINIT
+BEGIN
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x6553, 0x6f63, 0x646e, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x694d, 0x756e, 0x6574, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ 0
+END
+
+IDD_DIALOG_OPT_FINANCE DLGINIT
+BEGIN
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x6553, 0x6f63, 0x646e, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 8, 0
+0x694d, 0x756e, 0x6574, 0x0073,
+ IDC_COMBO_REFRESH_RATE, 0x403, 6, 0
+0x6f48, 0x7275, 0x0073,
+ 0
+END
+
+#endif // English (United Kingdom) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/Quotes/Forex.sln b/protocols/Quotes/Forex.sln
new file mode 100644
index 0000000000..5f0d619104
--- /dev/null
+++ b/protocols/Quotes/Forex.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Quotes", "Forex.vcxproj", "{C619A811-8023-4441-B3D7-785388A09DF0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Debug|Win32.Build.0 = Debug|Win32
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Debug|x64.ActiveCfg = Debug|x64
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Debug|x64.Build.0 = Debug|x64
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Release|Win32.ActiveCfg = Release|Win32
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Release|Win32.Build.0 = Release|Win32
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Release|x64.ActiveCfg = Release|x64
+ {C619A811-8023-4441-B3D7-785388A09DF0}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/protocols/Quotes/Forex.vcxproj b/protocols/Quotes/Forex.vcxproj
new file mode 100644
index 0000000000..4dd737de9c
--- /dev/null
+++ b/protocols/Quotes/Forex.vcxproj
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C619A811-8023-4441-B3D7-785388A09DF0}</ProjectGuid>
+ <ProjectName>Quotes</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;..\plugins\ExternalAPI;..\..\..\boost_1_49_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;FOREX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comsuppw.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>..\..\..\boost_1_49_0\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;..\plugins\ExternalAPI;..\..\..\boost_1_49_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;FOREX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comsuppw.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>..\..\..\boost_1_49_0\lib64</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;..\plugins\ExternalAPI;..\..\..\boost_1_49_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FOREX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comsuppw.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>..\..\..\boost_1_49_0\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;..\plugins\ExternalAPI;..\..\..\boost_1_49_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;FOREX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comsuppw.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>..\..\..\boost_1_49_0\lib64</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Base64.cpp" />
+ <ClCompile Include="ComHelper.cpp" />
+ <ClCompile Include="CommonOptionDlg.cpp" />
+ <ClCompile Include="CreateFilePath.cpp" />
+ <ClCompile Include="CurrencyConverter.cpp" />
+ <ClCompile Include="DBUtils.cpp" />
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="ExtraImages.cpp" />
+ <ClCompile Include="Forex.cpp" />
+ <ClCompile Include="HTMLParserMS.cpp" />
+ <ClCompile Include="HTTPSession.cpp" />
+ <ClCompile Include="IconLib.cpp" />
+ <ClCompile Include="ImportExport.cpp" />
+ <ClCompile Include="LightMutex.cpp" />
+ <ClCompile Include="Locale.cpp" />
+ <ClCompile Include="Log.cpp" />
+ <ClCompile Include="ModuleInfo.cpp" />
+ <ClCompile Include="OptionDukasCopy.cpp" />
+ <ClCompile Include="QuoteChart.cpp" />
+ <ClCompile Include="QuoteInfoDlg.cpp" />
+ <ClCompile Include="QuotesProviderBase.cpp" />
+ <ClCompile Include="QuotesProviderDukasCopy.cpp" />
+ <ClCompile Include="QuotesProviderFinance.cpp" />
+ <ClCompile Include="QuotesProviderGoogle.cpp" />
+ <ClCompile Include="QuotesProviderGoogleFinance.cpp" />
+ <ClCompile Include="QuotesProviders.cpp" />
+ <ClCompile Include="QuotesProviderVisitorDbSettings.cpp" />
+ <ClCompile Include="QuotesProviderVisitorFormater.cpp" />
+ <ClCompile Include="QuotesProviderVisitorFormatSpecificator.cpp" />
+ <ClCompile Include="QuotesProviderVisitorTendency.cpp" />
+ <ClCompile Include="QuotesProviderYahoo.cpp" />
+ <ClCompile Include="SettingsDlg.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="WinCtrlHelper.cpp" />
+ <ClCompile Include="WorkingThread.cpp" />
+ <ClCompile Include="XMLEngineMI.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Base64.h" />
+ <ClInclude Include="Chart.h" />
+ <ClInclude Include="ComHelper.h" />
+ <ClInclude Include="CommonOptionDlg.h" />
+ <ClInclude Include="CreateFilePath.h" />
+ <ClInclude Include="CurrencyConverter.h" />
+ <ClInclude Include="DBUtils.h" />
+ <ClInclude Include="EconomicRateInfo.h" />
+ <ClInclude Include="ExtraImages.h" />
+ <ClInclude Include="HTMLParserMS.h" />
+ <ClInclude Include="HTTPSession.h" />
+ <ClInclude Include="IconLib.h" />
+ <ClInclude Include="IHTMLEngine.h" />
+ <ClInclude Include="IHTMLParser.h" />
+ <ClInclude Include="ImportExport.h" />
+ <ClInclude Include="IQuotesProvider.h" />
+ <ClInclude Include="IsWithinAccuracy.h" />
+ <ClInclude Include="IXMLEngine.h" />
+ <ClInclude Include="LightMutex.h" />
+ <ClInclude Include="Locale.h" />
+ <ClInclude Include="Log.h" />
+ <ClInclude Include="ModuleInfo.h" />
+ <ClInclude Include="OptionDukasCopy.h" />
+ <ClInclude Include="QuoteChart.h" />
+ <ClInclude Include="QuoteInfoDlg.h" />
+ <ClInclude Include="QuotesProviderBase.h" />
+ <ClInclude Include="QuotesProviderDukasCopy.h" />
+ <ClInclude Include="QuotesProviderFinance.h" />
+ <ClInclude Include="QuotesProviderGoogle.h" />
+ <ClInclude Include="QuotesProviderGoogleFinance.h" />
+ <ClInclude Include="QuotesProviders.h" />
+ <ClInclude Include="QuotesProviderVisitor.h" />
+ <ClInclude Include="QuotesProviderVisitorDbSettings.h" />
+ <ClInclude Include="QuotesProviderVisitorFormater.h" />
+ <ClInclude Include="QuotesProviderVisitorFormatSpecificator.h" />
+ <ClInclude Include="QuotesProviderVisitorTendency.h" />
+ <ClInclude Include="QuotesProviderYahoo.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="SettingsDlg.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ <ClInclude Include="version.h" />
+ <ClInclude Include="WinCtrlHelper.h" />
+ <ClInclude Include="WorkingThread.h" />
+ <ClInclude Include="XMLEngineMI.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\CurrencyConverter.ico" />
+ <None Include="res\down.ico" />
+ <None Include="res\Export quotes.ico" />
+ <None Include="res\Import quotes.ico" />
+ <None Include="res\main.ico" />
+ <None Include="res\notchanged.ico" />
+ <None Include="res\quote.ico" />
+ <None Include="res\Refresh.ico" />
+ <None Include="res\Section.ico" />
+ <None Include="res\swap.ico" />
+ <None Include="res\up.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="Forex.rc" />
+ <ResourceCompile Include="Version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties RESOURCE_FILE="Forex.rc" />
+ </VisualStudio>
+ </ProjectExtensions>
+</Project> \ No newline at end of file
diff --git a/protocols/Quotes/Forex.vcxproj.filters b/protocols/Quotes/Forex.vcxproj.filters
new file mode 100644
index 0000000000..127582eda6
--- /dev/null
+++ b/protocols/Quotes/Forex.vcxproj.filters
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Base64.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ComHelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CommonOptionDlg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CreateFilePath.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CurrencyConverter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DBUtils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ExtraImages.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Forex.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HTMLParserMS.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HTTPSession.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="IconLib.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ImportExport.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="LightMutex.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Locale.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Log.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ModuleInfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OptionDukasCopy.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuoteChart.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuoteInfoDlg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderBase.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderDukasCopy.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderGoogle.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderGoogleFinance.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviders.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderVisitorDbSettings.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderVisitorFormater.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderVisitorFormatSpecificator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WinCtrlHelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WorkingThread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="XMLEngineMI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SettingsDlg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderVisitorTendency.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderFinance.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="QuotesProviderYahoo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Base64.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ComHelper.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CommonOptionDlg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CreateFilePath.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CurrencyConverter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="DBUtils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="EconomicRateInfo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ExtraImages.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="HTMLParserMS.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="HTTPSession.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IconLib.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IHTMLEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IHTMLParser.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ImportExport.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IQuotesProvider.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IsWithinAccuracy.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IXMLEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="LightMutex.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Locale.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Log.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ModuleInfo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OptionDukasCopy.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuoteChart.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuoteInfoDlg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderBase.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderDukasCopy.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderGoogle.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderGoogleFinance.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderVisitor.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderVisitorDbSettings.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderVisitorFormater.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderVisitorFormatSpecificator.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="stdafx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="targetver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="WinCtrlHelper.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="WorkingThread.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="XMLEngineMI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SettingsDlg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Chart.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderVisitorTendency.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderFinance.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="QuotesProviderYahoo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\CurrencyConverter.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\down.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Export quotes.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Import quotes.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\main.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\notchanged.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\quote.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Refresh.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Section.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\up.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\swap.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="Forex.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="Version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Quotes/HTMLParserMS.cpp b/protocols/Quotes/HTMLParserMS.cpp
new file mode 100644
index 0000000000..bfe58b43b1
--- /dev/null
+++ b/protocols/Quotes/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/HTMLParserMS.h b/protocols/Quotes/HTMLParserMS.h
new file mode 100644
index 0000000000..0773efa42a
--- /dev/null
+++ b/protocols/Quotes/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/HTTPSession.cpp b/protocols/Quotes/HTTPSession.cpp
new file mode 100644
index 0000000000..aa66948ae9
--- /dev/null
+++ b/protocols/Quotes/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/HTTPSession.h b/protocols/Quotes/HTTPSession.h
new file mode 100644
index 0000000000..fe93a2dce5
--- /dev/null
+++ b/protocols/Quotes/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/IHTMLEngine.h b/protocols/Quotes/IHTMLEngine.h
new file mode 100644
index 0000000000..7df3074d3e
--- /dev/null
+++ b/protocols/Quotes/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/IHTMLParser.h b/protocols/Quotes/IHTMLParser.h
new file mode 100644
index 0000000000..defc6f61cb
--- /dev/null
+++ b/protocols/Quotes/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/IQuotesProvider.h b/protocols/Quotes/IQuotesProvider.h
new file mode 100644
index 0000000000..a03a2a9bcd
--- /dev/null
+++ b/protocols/Quotes/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/IXMLEngine.h b/protocols/Quotes/IXMLEngine.h
new file mode 100644
index 0000000000..910c3efea0
--- /dev/null
+++ b/protocols/Quotes/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/IconLib.cpp b/protocols/Quotes/IconLib.cpp
new file mode 100644
index 0000000000..9702bfe3d8
--- /dev/null
+++ b/protocols/Quotes/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(CModuleInfo::GetModuleHandle(), 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 = reinterpret_cast<HANDLE>(CallService(MS_SKIN2_ADDICON,0,reinterpret_cast<LPARAM>(&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/IconLib.h b/protocols/Quotes/IconLib.h
new file mode 100644
index 0000000000..29b0326622
--- /dev/null
+++ b/protocols/Quotes/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/ImportExport.cpp b/protocols/Quotes/ImportExport.cpp
new file mode 100644
index 0000000000..2e38be0c0f
--- /dev/null
+++ b/protocols/Quotes/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 = reinterpret_cast<HANDLE>(CallService(MS_DB_CONTACT_FINDFIRST,0,0));hContact;hContact = reinterpret_cast<HANDLE>(CallService(MS_DB_CONTACT_FINDNEXT,reinterpret_cast<WPARAM>(hContact),0)))
+ {
+ 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/ImportExport.h b/protocols/Quotes/ImportExport.h
new file mode 100644
index 0000000000..da2053e9a3
--- /dev/null
+++ b/protocols/Quotes/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/IsWithinAccuracy.h b/protocols/Quotes/IsWithinAccuracy.h
new file mode 100644
index 0000000000..5e39281719
--- /dev/null
+++ b/protocols/Quotes/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/LightMutex.cpp b/protocols/Quotes/LightMutex.cpp
new file mode 100644
index 0000000000..8d14e8e7bb
--- /dev/null
+++ b/protocols/Quotes/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/LightMutex.h b/protocols/Quotes/LightMutex.h
new file mode 100644
index 0000000000..e8c7363ba1
--- /dev/null
+++ b/protocols/Quotes/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/Locale.cpp b/protocols/Quotes/Locale.cpp
new file mode 100644
index 0000000000..c01f67148a
--- /dev/null
+++ b/protocols/Quotes/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/Locale.h b/protocols/Quotes/Locale.h
new file mode 100644
index 0000000000..92d3a56ed4
--- /dev/null
+++ b/protocols/Quotes/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/Log.cpp b/protocols/Quotes/Log.cpp
new file mode 100644
index 0000000000..d692763bad
--- /dev/null
+++ b/protocols/Quotes/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/Log.h b/protocols/Quotes/Log.h
new file mode 100644
index 0000000000..274fcfec06
--- /dev/null
+++ b/protocols/Quotes/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/ModuleInfo.cpp b/protocols/Quotes/ModuleInfo.cpp
new file mode 100644
index 0000000000..69a835409e
--- /dev/null
+++ b/protocols/Quotes/ModuleInfo.cpp
@@ -0,0 +1,150 @@
+#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
+{
+ HINSTANCE g_hInstance = NULL;
+ 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);
+ }
+}
+
+void CModuleInfo::SetModuleHandle(HINSTANCE hInstance)
+{
+ assert(NULL == g_hInstance);
+ assert(NULL != hInstance);
+
+ g_hInstance = hInstance;
+}
+
+HINSTANCE CModuleInfo::GetModuleHandle()
+{
+ assert(NULL != g_hInstance);
+ return g_hInstance;
+}
+
+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/ModuleInfo.h b/protocols/Quotes/ModuleInfo.h
new file mode 100644
index 0000000000..5dcf7e5de6
--- /dev/null
+++ b/protocols/Quotes/ModuleInfo.h
@@ -0,0 +1,46 @@
+#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 void SetModuleHandle(HINSTANCE hInstance);
+ static HINSTANCE GetModuleHandle();
+
+ 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/OptionDukasCopy.cpp b/protocols/Quotes/OptionDukasCopy.cpp
new file mode 100644
index 0000000000..1aef56b824
--- /dev/null
+++ b/protocols/Quotes/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
+
+ CallService(MS_OPT_ADDPAGE,wp,reinterpret_cast<LPARAM>(&odp));
+}
diff --git a/protocols/Quotes/OptionDukasCopy.h b/protocols/Quotes/OptionDukasCopy.h
new file mode 100644
index 0000000000..0674119e83
--- /dev/null
+++ b/protocols/Quotes/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/QuoteChart.cpp b/protocols/Quotes/QuoteChart.cpp
new file mode 100644
index 0000000000..3746540d23
--- /dev/null
+++ b/protocols/Quotes/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/QuoteChart.h b/protocols/Quotes/QuoteChart.h
new file mode 100644
index 0000000000..1b40f428b5
--- /dev/null
+++ b/protocols/Quotes/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/QuoteInfoDlg.cpp b/protocols/Quotes/QuoteInfoDlg.cpp
new file mode 100644
index 0000000000..88253ec45d
--- /dev/null
+++ b/protocols/Quotes/QuoteInfoDlg.cpp
@@ -0,0 +1,353 @@
+#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 = CModuleInfo::GetModuleHandle();
+ //odp.dwInitParam = ( LPARAM )this;
+
+ odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN);
+ odp.flags = ODPF_TCHAR;
+ odp.pfnDlgProc = QuoteInfoDlgProc;
+ odp.position = -2000000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_QUOTE_INFO);
+ odp.ptszTitle = TranslateT("Quote");
+ CallService(MS_USERINFO_ADDPAGE,wp,reinterpret_cast<LPARAM>(&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(CModuleInfo::GetModuleHandle(),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/QuoteInfoDlg.h b/protocols/Quotes/QuoteInfoDlg.h
new file mode 100644
index 0000000000..c4a1999a4c
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderBase.cpp b/protocols/Quotes/QuotesProviderBase.cpp
new file mode 100644
index 0000000000..c92c748a02
--- /dev/null
+++ b/protocols/Quotes/QuotesProviderBase.cpp
Binary files differ
diff --git a/protocols/Quotes/QuotesProviderBase.h b/protocols/Quotes/QuotesProviderBase.h
new file mode 100644
index 0000000000..76db155f4c
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderDukasCopy.cpp b/protocols/Quotes/QuotesProviderDukasCopy.cpp
new file mode 100644
index 0000000000..a7ffc5331a
--- /dev/null
+++ b/protocols/Quotes/QuotesProviderDukasCopy.cpp
Binary files differ
diff --git a/protocols/Quotes/QuotesProviderDukasCopy.h b/protocols/Quotes/QuotesProviderDukasCopy.h
new file mode 100644
index 0000000000..d6ec498bcf
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderFinance.cpp b/protocols/Quotes/QuotesProviderFinance.cpp
new file mode 100644
index 0000000000..99d6127b32
--- /dev/null
+++ b/protocols/Quotes/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());
+ CallService(MS_OPT_ADDPAGE,wp,reinterpret_cast<LPARAM>(&odp));
+}
diff --git a/protocols/Quotes/QuotesProviderFinance.h b/protocols/Quotes/QuotesProviderFinance.h
new file mode 100644
index 0000000000..f63077071d
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderGoogle.cpp b/protocols/Quotes/QuotesProviderGoogle.cpp
new file mode 100644
index 0000000000..6458180324
--- /dev/null
+++ b/protocols/Quotes/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
+ CallService(MS_OPT_ADDPAGE,wp,reinterpret_cast<LPARAM>(&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/QuotesProviderGoogle.h b/protocols/Quotes/QuotesProviderGoogle.h
new file mode 100644
index 0000000000..4289861178
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderGoogleFinance.cpp b/protocols/Quotes/QuotesProviderGoogleFinance.cpp
new file mode 100644
index 0000000000..8a129b6b8b
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderGoogleFinance.h b/protocols/Quotes/QuotesProviderGoogleFinance.h
new file mode 100644
index 0000000000..075498a4dd
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitor.h b/protocols/Quotes/QuotesProviderVisitor.h
new file mode 100644
index 0000000000..9ae601f2a1
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorDbSettings.cpp b/protocols/Quotes/QuotesProviderVisitorDbSettings.cpp
new file mode 100644
index 0000000000..5caea48685
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorDbSettings.h b/protocols/Quotes/QuotesProviderVisitorDbSettings.h
new file mode 100644
index 0000000000..728a436dfa
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorFormatSpecificator.cpp b/protocols/Quotes/QuotesProviderVisitorFormatSpecificator.cpp
new file mode 100644
index 0000000000..9e643fe1b6
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorFormatSpecificator.h b/protocols/Quotes/QuotesProviderVisitorFormatSpecificator.h
new file mode 100644
index 0000000000..870ab00634
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorFormater.cpp b/protocols/Quotes/QuotesProviderVisitorFormater.cpp
new file mode 100644
index 0000000000..4b1d73bb05
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorFormater.h b/protocols/Quotes/QuotesProviderVisitorFormater.h
new file mode 100644
index 0000000000..7c9c222269
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorTendency.cpp b/protocols/Quotes/QuotesProviderVisitorTendency.cpp
new file mode 100644
index 0000000000..00703521b3
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderVisitorTendency.h b/protocols/Quotes/QuotesProviderVisitorTendency.h
new file mode 100644
index 0000000000..fa0f04c5f0
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderYahoo.cpp b/protocols/Quotes/QuotesProviderYahoo.cpp
new file mode 100644
index 0000000000..35edb3207c
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviderYahoo.h b/protocols/Quotes/QuotesProviderYahoo.h
new file mode 100644
index 0000000000..feadefbca4
--- /dev/null
+++ b/protocols/Quotes/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/QuotesProviders.cpp b/protocols/Quotes/QuotesProviders.cpp
new file mode 100644
index 0000000000..5fac2af14f
--- /dev/null
+++ b/protocols/Quotes/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 = reinterpret_cast<HANDLE>(CallService(MS_DB_CONTACT_FINDFIRST,0,0));hContact;hContact = reinterpret_cast<HANDLE>(CallService(MS_DB_CONTACT_FINDNEXT,reinterpret_cast<WPARAM>(hContact),0)))
+ {
+ 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/QuotesProviders.h b/protocols/Quotes/QuotesProviders.h
new file mode 100644
index 0000000000..02aa5184c9
--- /dev/null
+++ b/protocols/Quotes/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/SettingsDlg.cpp b/protocols/Quotes/SettingsDlg.cpp
new file mode 100644
index 0000000000..e5795b51d1
--- /dev/null
+++ b/protocols/Quotes/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 = CModuleInfo::GetModuleHandle();
+ 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>(GetWindowLong(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(CModuleInfo::GetModuleHandle(),
+ 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(CModuleInfo::GetModuleHandle(),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(CModuleInfo::GetModuleHandle(),
+ 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(CModuleInfo::GetModuleHandle(),
+ 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/SettingsDlg.h b/protocols/Quotes/SettingsDlg.h
new file mode 100644
index 0000000000..569d0b7d2c
--- /dev/null
+++ b/protocols/Quotes/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/Utility/DukasCopy.py b/protocols/Quotes/Utility/DukasCopy.py
new file mode 100644
index 0000000000..2d12d1c4ec
--- /dev/null
+++ b/protocols/Quotes/Utility/DukasCopy.py
@@ -0,0 +1,48 @@
+from html.parser import HTMLParser
+import sys
+
+class MyHTMLParser(HTMLParser):
+ def __init__(self, in_fn,out_fn):
+ HTMLParser.__init__(self)
+ f_in = open(in_fn,'r')
+ self.quote = 0
+ self.descr = ''
+ self.f_out = open(out_fn,'w')
+ self.feed(f_in.read())
+ f_in.close()
+ self.f_out.close()
+
+ def handle_starttag(self, tag, attrs):
+ #print ("start of a %s" % tag)
+ #print (attrs)
+ self.start = 1
+ if tag == 'input':
+ self.f_out.write('\n<quote>')
+ for k in attrs:
+ if k[0] == 'stname':
+ self.f_out.write('\n\t<symbol>%s</symbol>'%k[1])
+ if k[0] == 'stid':
+ self.f_out.write('\n\t<id>%s</id>'%k[1])
+ self.quote = 1
+
+
+ def handle_endtag(self, tag):
+ self.start = 0
+ if tag == 'tr' and self.quote == 1:
+ if self.descr:
+ self.f_out.write('\n\t<description>%s</description>'%self.descr)
+ self.f_out.write('\n</quote>')
+ self.quote = 0
+ self.descr = 1
+ #print ("end of a %s" % tag)
+
+ def handle_data(self, data):
+ if self.start == 1:
+ self.descr = data
+ #print ("Data %s" % self.descr)
+
+
+
+parser = MyHTMLParser(sys.argv[1],sys.argv[2])
+parser.close()
+ \ No newline at end of file
diff --git a/protocols/Quotes/Utility/Dukascopy.xml b/protocols/Quotes/Utility/Dukascopy.xml
new file mode 100644
index 0000000000..92890888b9
--- /dev/null
+++ b/protocols/Quotes/Utility/Dukascopy.xml
@@ -0,0 +1,1635 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Provider>
+ <name>Dukascopy Swiss Forex Group</name>
+ <ref>http://www.dukascopy.com</ref>
+ <url>http://freeserv.dukascopy.com/qt/?&amp;STOCKS=</url>
+
+ <!--European Stocks-->
+
+ <section>
+ <name>European Stocks</name>
+
+<quote>
+ <id>127</id>
+ <symbol>BA</symbol>
+ <description>BAE Systems</description>
+</quote>
+<quote>
+ <id>130</id>
+ <symbol>BKIR</symbol>
+ <description>Bank of Ireland</description>
+</quote>
+<quote>
+ <id>131</id>
+ <symbol>BP</symbol>
+ <description>British Petroleum</description>
+</quote>
+<quote>
+ <id>138</id>
+ <symbol>SBRY</symbol>
+ <description>Sainsbury</description>
+</quote>
+<quote>
+ <id>142</id>
+ <symbol>AZN</symbol>
+ <description>Astrazeneca</description>
+</quote>
+<quote>
+ <id>145</id>
+ <symbol>CNA</symbol>
+ <description>Centrica</description>
+</quote>
+<quote>
+ <id>153</id>
+ <symbol>MKS</symbol>
+ <description> Spencer</description>
+</quote>
+<quote>
+ <id>155</id>
+ <symbol>RTR</symbol>
+ <description>Reuters Group</description>
+</quote>
+<quote>
+ <id>156</id>
+ <symbol>RR</symbol>
+ <description>Rolls Royce</description>
+</quote>
+<quote>
+ <id>158</id>
+ <symbol>TSCO</symbol>
+ <description>Tesco</description>
+</quote>
+<quote>
+ <id>165</id>
+ <symbol>ALV</symbol>
+ <description>Alliaz AG</description>
+</quote>
+<quote>
+ <id>167</id>
+ <symbol>BAY</symbol>
+ <description>Bayer AG</description>
+</quote>
+<quote>
+ <id>169</id>
+ <symbol>CBK</symbol>
+ <description>Commerzbank AG</description>
+</quote>
+<quote>
+ <id>171</id>
+ <symbol>DBK</symbol>
+ <description>Deutsche Bank AG</description>
+</quote>
+<quote>
+ <id>177</id>
+ <symbol>SIE</symbol>
+ <description>Siemens AG</description>
+</quote>
+<quote>
+ <id>178</id>
+ <symbol>TKA</symbol>
+ <description>Thyssenkrupp AG</description>
+</quote>
+<quote>
+ <id>179</id>
+ <symbol>VOW</symbol>
+ <description>Volkswagen AG</description>
+</quote>
+<quote>
+ <id>183</id>
+ <symbol>FTE</symbol>
+ <description>France Telecom</description>
+</quote>
+<quote>
+ <id>191</id>
+ <symbol>OR</symbol>
+ <description>LOreal</description>
+</quote>
+<quote>
+ <id>192</id>
+ <symbol>ML</symbol>
+ <description>Michelin</description>
+</quote>
+<quote>
+ <id>193</id>
+ <symbol>RNO</symbol>
+ <description>Renault</description>
+</quote>
+<quote>
+ <id>195</id>
+ <symbol>UG</symbol>
+ <description>Peugeot SA</description>
+</quote>
+<quote>
+ <id>198</id>
+ <symbol>LG</symbol>
+ <description>Lafarge</description>
+</quote>
+<quote>
+ <id>206</id>
+ <symbol>PIN</symbol>
+ <description>Pinguin</description>
+</quote>
+<quote>
+ <id>213</id>
+ <symbol>RBACW</symbol>
+ <description>Rabo Agaath Bank</description>
+</quote>
+<quote>
+ <id>221</id>
+ <symbol>ABBN</symbol>
+ <description>ABB Finance</description>
+</quote>
+<quote>
+ <id>222</id>
+ <symbol>ADEN</symbol>
+ <description>Adecco SA</description>
+</quote>
+<quote>
+ <id>224</id>
+ <symbol>RUKN</symbol>
+ <description>Swiss Reinsurance</description>
+</quote>
+<quote>
+ <id>232</id>
+ <symbol>GFC</symbol>
+ <description>Gecina</description>
+</quote>
+<quote>
+ <id>234</id>
+ <symbol>VK</symbol>
+ <description>Vallourec</description>
+</quote>
+<quote>
+ <id>235</id>
+ <symbol>FLE</symbol>
+ <description>Fleury Michon</description>
+</quote>
+<quote>
+ <id>242</id>
+ <symbol>NEX</symbol>
+ <description>National Express Group</description>
+</quote>
+<quote>
+ <id>245</id>
+ <symbol>IMT</symbol>
+ <description>Imperial Tobacco</description>
+</quote>
+<quote>
+ <id>338</id>
+ <symbol>Pseudo</symbol>
+ <description>Pseudo</description>
+</quote>
+<quote>
+ <id>340</id>
+ <symbol>Pseudo1</symbol>
+ <description>Pseudo1</description>
+</quote>
+<quote>
+ <id>321</id>
+ <symbol>ROS</symbol>
+ <description>OAO Rostelecom</description>
+</quote>
+<quote>
+ <id>325</id>
+ <symbol>FIA</symbol>
+ <description>Fiat S.p.A.</description>
+</quote>
+<quote>
+ <id>326</id>
+ <symbol>E</symbol>
+ <description>Eni S.p.A.</description>
+</quote>
+<quote>
+ <id>327</id>
+ <symbol>EN</symbol>
+ <description>Enel S.p.A.</description>
+</quote>
+<quote>
+ <id>152</id>
+ <symbol>LLOY</symbol>
+ <description>Lloyds TSB Bank</description>
+</quote>
+<quote>
+ <id>226</id>
+ <symbol>AKZA</symbol>
+ <description>Akzo Nobel NV</description>
+</quote>
+<quote>
+ <id>135</id>
+ <symbol>BSY</symbol>
+ <description>British Sky Broadcast</description>
+</quote>
+<quote>
+ <id>144</id>
+ <symbol>CW</symbol>
+ <description> Wireless</description>
+</quote>
+<quote>
+ <id>146</id>
+ <symbol>GSK</symbol>
+ <description>Glaxosmithkline</description>
+</quote>
+<quote>
+ <id>149</id>
+ <symbol>HSBA</symbol>
+ <description>HSBC Bank</description>
+</quote>
+<quote>
+ <id>151</id>
+ <symbol>KGF</symbol>
+ <description>Kingfisher</description>
+</quote>
+<quote>
+ <id>166</id>
+ <symbol>BAS</symbol>
+ <description>BASF AG</description>
+</quote>
+<quote>
+ <id>172</id>
+ <symbol>DPW</symbol>
+ <description>Deutsche Post AG</description>
+</quote>
+<quote>
+ <id>173</id>
+ <symbol>DTE</symbol>
+ <description>Deutsche Telecom</description>
+</quote>
+<quote>
+ <id>249</id>
+ <symbol>CA</symbol>
+ <description>Carrefour</description>
+</quote>
+<quote>
+ <id>218</id>
+ <symbol>NESN</symbol>
+ <description>Nestle SA</description>
+</quote>
+<quote>
+ <id>219</id>
+ <symbol>UBSN</symbol>
+ <description>UBS AG</description>
+</quote>
+<quote>
+ <id>229</id>
+ <symbol>DIE</symbol>
+ <description>DIeteren Trading</description>
+</quote>
+<quote>
+ <id>237</id>
+ <symbol>GAM</symbol>
+ <description>Gaumont</description>
+</quote>
+<quote>
+ <id>238</id>
+ <symbol>AGE</symbol>
+ <description>AGFA Gevaert NV</description>
+</quote>
+<quote>
+ <id>243</id>
+ <symbol>CBRY</symbol>
+ <description>Cadbury Schweppes</description>
+</quote>
+<quote>
+ <id>246</id>
+ <symbol>MLW</symbol>
+ <description>Merrill Lynch World</description>
+</quote>
+<quote>
+ <id>248</id>
+ <symbol>MASN</symbol>
+ <description>Micronas Semiconductors</description>
+</quote>
+<quote>
+ <id>255</id>
+ <symbol>ARE</symbol>
+ <description>Groupe Ares</description>
+</quote>
+<quote>
+ <id>200</id>
+ <symbol>DELB</symbol>
+ <description>Delhaize Group</description>
+</quote>
+<quote>
+ <id>215</id>
+ <symbol>PHIA</symbol>
+ <description>Philips Electronics</description>
+</quote>
+<quote>
+ <id>216</id>
+ <symbol>CSGN</symbol>
+ <description>Credit Suisse Groupe CAP</description>
+</quote>
+<quote>
+ <id>772</id>
+ <symbol>VOD</symbol>
+ <description>VODAFONE </description>
+</quote>
+<quote>
+ <id>773</id>
+ <symbol>BA</symbol>
+ <description>British Airways</description>
+</quote>
+
+ </section>
+
+ <!--US Stocks-->
+
+ <section>
+ <name>US Stocks</name>
+
+
+<quote>
+ <id>99</id>
+ <symbol>INTC</symbol>
+ <description>Intel Corp.</description>
+</quote>
+<quote>
+ <id>98</id>
+ <symbol>QCOM</symbol>
+ <description>QUALCOMM Incorporated</description>
+</quote>
+<quote>
+ <id>97</id>
+ <symbol>CSCO</symbol>
+ <description>Cisco Systems, Inc.</description>
+</quote>
+<quote>
+ <id>96</id>
+ <symbol>AMGN</symbol>
+ <description>Amgen Inc.</description>
+</quote>
+<quote>
+ <id>94</id>
+ <symbol>ORCL</symbol>
+ <description>Oracle Corp.</description>
+</quote>
+<quote>
+ <id>92</id>
+ <symbol>MXIM</symbol>
+ <description>Maxim Integrated Products, Inc.</description>
+</quote>
+<quote>
+ <id>85</id>
+ <symbol>SBUX</symbol>
+ <description>Starbucks Corp.</description>
+</quote>
+<quote>
+ <id>82</id>
+ <symbol>CTAS</symbol>
+ <description>Cintas Corp.</description>
+</quote>
+<quote>
+ <id>81</id>
+ <symbol>BMET</symbol>
+ <description>Biomet, Inc.</description>
+</quote>
+<quote>
+ <id>80</id>
+ <symbol>PAYX</symbol>
+ <description>Paychex, Inc</description>
+</quote>
+<quote>
+ <id>79</id>
+ <symbol>XLNX</symbol>
+ <description>Xilinx, Inc.</description>
+</quote>
+<quote>
+ <id>75</id>
+ <symbol>FISV</symbol>
+ <description>Fiserv, Inc.</description>
+</quote>
+<quote>
+ <id>69</id>
+ <symbol>COST</symbol>
+ <description>Costco Wholesale Corp.</description>
+</quote>
+<quote>
+ <id>64</id>
+ <symbol>PCAR</symbol>
+ <description>PACCAR Inc.</description>
+</quote>
+<quote>
+ <id>62</id>
+ <symbol>ADBE</symbol>
+ <description>Adobe Systems Incorporated</description>
+</quote>
+<quote>
+ <id>61</id>
+ <symbol>SPLS</symbol>
+ <description>Staples, Inc.</description>
+</quote>
+<quote>
+ <id>33</id>
+ <symbol>T</symbol>
+ <description>T Corp.</description>
+</quote>
+<quote>
+ <id>31</id>
+ <symbol>AA</symbol>
+ <description>Alcoa</description>
+</quote>
+<quote>
+ <id>32</id>
+ <symbol>AXP</symbol>
+ <description>American Express Co.</description>
+</quote>
+<quote>
+ <id>34</id>
+ <symbol>BA</symbol>
+ <description>The Boeing Co.</description>
+</quote>
+<quote>
+ <id>35</id>
+ <symbol>CAT</symbol>
+ <description>Caterpillar Inc.</description>
+</quote>
+<quote>
+ <id>36</id>
+ <symbol>C</symbol>
+ <description>Citigroup, Inc.</description>
+</quote>
+<quote>
+ <id>37</id>
+ <symbol>KO</symbol>
+ <description>The Coca-Cola Co.</description>
+</quote>
+<quote>
+ <id>40</id>
+ <symbol>EK</symbol>
+ <description>Eastman Kodak Co.</description>
+</quote>
+<quote>
+ <id>43</id>
+ <symbol>GM</symbol>
+ <description>General Motors Corp.</description>
+</quote>
+<quote>
+ <id>49</id>
+ <symbol>JNJ</symbol>
+ <description> Johnson</description>
+</quote>
+<quote>
+ <id>50</id>
+ <symbol>MCD</symbol>
+ <description>McDonald's Corp.</description>
+</quote>
+<quote>
+ <id>51</id>
+ <symbol>MRK</symbol>
+ <description>Merck Company, Inc.</description>
+</quote>
+<quote>
+ <id>52</id>
+ <symbol>MMM</symbol>
+ <description>Manufacturing Co.</description>
+</quote>
+<quote>
+ <id>53</id>
+ <symbol>JPM</symbol>
+ <description>J.P. Morgan Company Inc.</description>
+</quote>
+<quote>
+ <id>57</id>
+ <symbol>UTX</symbol>
+ <description>United Technologies Corp.</description>
+</quote>
+<quote>
+ <id>58</id>
+ <symbol>WMT</symbol>
+ <description>Wal-Mart Stores, Inc.</description>
+</quote>
+<quote>
+ <id>104</id>
+ <symbol>CDWC</symbol>
+ <description>CDW Computer Centers, Inc.</description>
+</quote>
+<quote>
+ <id>116</id>
+ <symbol>SGA</symbol>
+ <description>Saga Communications, Inc.</description>
+</quote>
+<quote>
+ <id>118</id>
+ <symbol>MPP</symbol>
+ <description>Medical Technology System</description>
+</quote>
+<quote>
+ <id>119</id>
+ <symbol>ACU</symbol>
+ <description>Acme United Corp.</description>
+</quote>
+<quote>
+ <id>128</id>
+ <symbol>BAL</symbol>
+ <description>Barclays</description>
+</quote>
+<quote>
+ <id>141</id>
+ <symbol>RBS</symbol>
+ <description>Royal Bank of Scotland</description>
+</quote>
+<quote>
+ <id>250</id>
+ <symbol>BMO</symbol>
+ <description>Bank of Montreal</description>
+</quote>
+<quote>
+ <id>254</id>
+ <symbol>TRP</symbol>
+ <description>TransCanada PipeLines Ltd</description>
+</quote>
+<quote>
+ <id>329</id>
+ <symbol>QQQQ</symbol>
+ <description>TransCanada PipeLines Ltd</description>
+</quote>
+<quote>
+ <id>330</id>
+ <symbol>DIA</symbol>
+ <description>TransCanada PipeLines Ltd</description>
+</quote>
+<quote>
+ <id>332</id>
+ <symbol>SMH</symbol>
+ <description>TransCanada PipeLines Ltd</description>
+</quote>
+<quote>
+ <id>122</id>
+ <symbol>DW</symbol>
+ <description>Drew Industries, Inc.</description>
+</quote>
+<quote>
+ <id>123</id>
+ <symbol>FPU</symbol>
+ <description>Florida Public Utilities</description>
+</quote>
+<quote>
+ <id>280</id>
+ <symbol>NOK</symbol>
+ <description>Nokia</description>
+</quote>
+<quote>
+ <id>281</id>
+ <symbol>UPM</symbol>
+ <description>UPM-Kymmene OYJ</description>
+</quote>
+<quote>
+ <id>282</id>
+ <symbol>SEO</symbol>
+ <description>Stora Enso OYJ</description>
+</quote>
+<quote>
+ <id>287</id>
+ <symbol>BEAS</symbol>
+ <description>BEA System INC.</description>
+</quote>
+<quote>
+ <id>288</id>
+ <symbol>BRCD</symbol>
+ <description>Brocade Communication System Inc.</description>
+</quote>
+<quote>
+ <id>291</id>
+ <symbol>CEPH</symbol>
+ <description>Cephalon Inc.</description>
+</quote>
+<quote>
+ <id>292</id>
+ <symbol>CIEN</symbol>
+ <description>Ciena Corp.</description>
+</quote>
+<quote>
+ <id>293</id>
+ <symbol>CHKP</symbol>
+ <description>Checkpoint Software</description>
+</quote>
+<quote>
+ <id>295</id>
+ <symbol>DISH</symbol>
+ <description>Echostar Communications</description>
+</quote>
+<quote>
+ <id>100</id>
+ <symbol>MSFT</symbol>
+ <description>Microsoft Corp.</description>
+</quote>
+<quote>
+ <id>95</id>
+ <symbol>DELL</symbol>
+ <description>Dell Computer Corp.</description>
+</quote>
+<quote>
+ <id>91</id>
+ <symbol>EBAY</symbol>
+ <description>eBay Inc.</description>
+</quote>
+<quote>
+ <id>88</id>
+ <symbol>BBBY</symbol>
+ <description>Beyond Inc.</description>
+</quote>
+<quote>
+ <id>87</id>
+ <symbol>LLTC</symbol>
+ <description>Linear Technology Corp.</description>
+</quote>
+<quote>
+ <id>84</id>
+ <symbol>IACI</symbol>
+ <description>USA Interactive</description>
+</quote>
+<quote>
+ <id>76</id>
+ <symbol>KLAC</symbol>
+ <description>KLA-Tencor Corp.</description>
+</quote>
+<quote>
+ <id>70</id>
+ <symbol>APOL</symbol>
+ <description>Apollo Group, Inc.</description>
+</quote>
+<quote>
+ <id>68</id>
+ <symbol>TEVA</symbol>
+ <description>Teva Pharmaceutical Industries Limited</description>
+</quote>
+<quote>
+ <id>65</id>
+ <symbol>ALTR</symbol>
+ <description>Altera Corp.</description>
+</quote>
+<quote>
+ <id>63</id>
+ <symbol>SYMC</symbol>
+ <description>Symantec Corp.</description>
+</quote>
+<quote>
+ <id>42</id>
+ <symbol>GE</symbol>
+ <description>General Electric Co.</description>
+</quote>
+<quote>
+ <id>44</id>
+ <symbol>HPQ</symbol>
+ <description>Hewlett-Packard Co.</description>
+</quote>
+<quote>
+ <id>46</id>
+ <symbol>HON</symbol>
+ <description>Honeywell International Inc.</description>
+</quote>
+<quote>
+ <id>47</id>
+ <symbol>IBM</symbol>
+ <description>International Business Machines Corp.</description>
+</quote>
+<quote>
+ <id>54</id>
+ <symbol>MO</symbol>
+ <description>Morris Companies, Inc.</description>
+</quote>
+<quote>
+ <id>55</id>
+ <symbol>PG</symbol>
+ <description>Gamble Co.</description>
+</quote>
+<quote>
+ <id>103</id>
+ <symbol>FLEX</symbol>
+ <description>Flextronics International Ltd.</description>
+</quote>
+<quote>
+ <id>115</id>
+ <symbol>OHB</symbol>
+ <description>Orleans Homebuilders</description>
+</quote>
+<quote>
+ <id>251</id>
+ <symbol>BNS</symbol>
+ <description>Bank of Nova Scotia</description>
+</quote>
+<quote>
+ <id>252</id>
+ <symbol>BCE</symbol>
+ <description>BCE, Inc.</description>
+</quote>
+<quote>
+ <id>331</id>
+ <symbol>SPY</symbol>
+ <description>BCE, Inc.</description>
+</quote>
+<quote>
+ <id>286</id>
+ <symbol>AMCC</symbol>
+ <description>Applied Micro Circuit Corp.</description>
+</quote>
+<quote>
+ <id>294</id>
+ <symbol>CTXS</symbol>
+ <description>Citrix Systems</description>
+</quote>
+<quote>
+ <id>738</id>
+ <symbol>MCHP</symbol>
+ <description>Microchip Technology</description>
+</quote>
+<quote>
+ <id>747</id>
+ <symbol>NTE</symbol>
+ <description>NAM TAI Electronics</description>
+</quote>
+<quote>
+ <id>759</id>
+ <symbol>TTWO</symbol>
+ <description>Take-Two Interactive Software</description>
+</quote>
+<quote>
+ <id>700</id>
+ <symbol>ADI </symbol>
+ <description>Analog Devices </description>
+</quote>
+<quote>
+ <id>701</id>
+ <symbol>ADTN</symbol>
+ <description>Adtran </description>
+</quote>
+<quote>
+ <id>702</id>
+ <symbol>AIG</symbol>
+ <description>American International Group</description>
+</quote>
+<quote>
+ <id>703</id>
+ <symbol>APA</symbol>
+ <description>Apache Corp</description>
+</quote>
+<quote>
+ <id>704</id>
+ <symbol>BAC</symbol>
+ <description>Bank of America Corp</description>
+</quote>
+<quote>
+ <id>705</id>
+ <symbol>BBY</symbol>
+ <description>Best Buy Co </description>
+</quote>
+<quote>
+ <id>706</id>
+ <symbol>BIIB</symbol>
+ <description>Biogen Idec </description>
+</quote>
+<quote>
+ <id>707</id>
+ <symbol>BOBJ</symbol>
+ <description>Business Objects SA</description>
+</quote>
+<quote>
+ <id>708</id>
+ <symbol>BRCM</symbol>
+ <description>Broadcom Corp</description>
+</quote>
+<quote>
+ <id>709</id>
+ <symbol>CALM</symbol>
+ <description>Cal-Maine Foods </description>
+</quote>
+<quote>
+ <id>710</id>
+ <symbol>CCU</symbol>
+ <description>Clear Channel Communications </description>
+</quote>
+<quote>
+ <id>711</id>
+ <symbol>COF</symbol>
+ <description>Capital One Financial Corp</description>
+</quote>
+<quote>
+ <id>714</id>
+ <symbol>DLTR</symbol>
+ <description>Dollar Tree Stores </description>
+</quote>
+<quote>
+ <id>716</id>
+ <symbol>FITB</symbol>
+ <description>Fifth Third Bancorp</description>
+</quote>
+<quote>
+ <id>717</id>
+ <symbol>FNM</symbol>
+ <description>Fannie Mae</description>
+</quote>
+<quote>
+ <id>718</id>
+ <symbol>FRE</symbol>
+ <description>Freddie Mac</description>
+</quote>
+<quote>
+ <id>719</id>
+ <symbol>FRX</symbol>
+ <description>Forest Laboratories </description>
+</quote>
+<quote>
+ <id>720</id>
+ <symbol>GCI</symbol>
+ <description>Gannett Co </description>
+</quote>
+<quote>
+ <id>721</id>
+ <symbol>GD</symbol>
+ <description>General Dynamics Corp</description>
+</quote>
+<quote>
+ <id>724</id>
+ <symbol>GS</symbol>
+ <description>Goldman Sachs Group </description>
+</quote>
+<quote>
+ <id>726</id>
+ <symbol>HOV</symbol>
+ <description>Hovnanian Enterprises </description>
+</quote>
+<quote>
+ <id>727</id>
+ <symbol>ICOS</symbol>
+ <description>ICOS Corp</description>
+</quote>
+<quote>
+ <id>728</id>
+ <symbol>IMCL</symbol>
+ <description>ImClone Systems</description>
+</quote>
+<quote>
+ <id>731</id>
+ <symbol>KSS</symbol>
+ <description>Kohl's Corp</description>
+</quote>
+<quote>
+ <id>732</id>
+ <symbol>LEH</symbol>
+ <description>Lehman Brothers Holdings Inc</description>
+</quote>
+<quote>
+ <id>734</id>
+ <symbol>LLY</symbol>
+ <description> Co</description>
+</quote>
+<quote>
+ <id>737</id>
+ <symbol>LXK</symbol>
+ <description>Lexmark International</description>
+</quote>
+<quote>
+ <id>743</id>
+ <symbol>NEM</symbol>
+ <description>Newmont Mining Corp</description>
+</quote>
+<quote>
+ <id>744</id>
+ <symbol>NFLX</symbol>
+ <description>NetFlix</description>
+</quote>
+<quote>
+ <id>745</id>
+ <symbol>NOC</symbol>
+ <description>Northrop Grumman Corp</description>
+</quote>
+<quote>
+ <id>748</id>
+ <symbol>NTES</symbol>
+ <description>Netease.com</description>
+</quote>
+<quote>
+ <id>749</id>
+ <symbol>NVLS</symbol>
+ <description>Novellus Systems</description>
+</quote>
+<quote>
+ <id>750</id>
+ <symbol>OVTI</symbol>
+ <description>Omnivision Technologies</description>
+</quote>
+<quote>
+ <id>753</id>
+ <symbol>RMBS</symbol>
+ <description>Rambus</description>
+</quote>
+<quote>
+ <id>755</id>
+ <symbol>SINA</symbol>
+ <description>Sina Corp</description>
+</quote>
+<quote>
+ <id>756</id>
+ <symbol>SNDK</symbol>
+ <description>Sandisk Corp</description>
+</quote>
+<quote>
+ <id>757</id>
+ <symbol>SNPS</symbol>
+ <description>Synopsys</description>
+</quote>
+<quote>
+ <id>758</id>
+ <symbol>SOHU</symbol>
+ <description>Sohu.com</description>
+</quote>
+<quote>
+ <id>760</id>
+ <symbol>UTSI</symbol>
+ <description>Utstarcom</description>
+</quote>
+<quote>
+ <id>762</id>
+ <symbol>WLP</symbol>
+ <description>WellPoint Health Networks</description>
+</quote>
+<quote>
+ <id>763</id>
+ <symbol>WY</symbol>
+ <description>Weyerhaeuser Co</description>
+</quote>
+<quote>
+ <id>764</id>
+ <symbol>XMSR</symbol>
+ <description>XM Satellite Radio Holdings</description>
+</quote>
+<quote>
+ <id>765</id>
+ <symbol>YHOO</symbol>
+ <description>Yahoo! </description>
+</quote>
+<quote>
+ <id>38</id>
+ <symbol>DIS</symbol>
+ <description>The Walt Disney Co.</description>
+</quote>
+<quote>
+ <id>39</id>
+ <symbol>DD</symbol>
+ <description>E.I. duPont de Nemours Co.</description>
+</quote>
+<quote>
+ <id>78</id>
+ <symbol>ERTS</symbol>
+ <description>Electronic Arts Inc.</description>
+</quote>
+<quote>
+ <id>77</id>
+ <symbol>GENZ</symbol>
+ <description>Genzyme General</description>
+</quote>
+<quote>
+ <id>766</id>
+ <symbol>GOOGL</symbol>
+ <description>Google!</description>
+</quote>
+<quote>
+ <id>45</id>
+ <symbol>HD</symbol>
+ <description>Home Depot Inc.</description>
+</quote>
+<quote>
+ <id>48</id>
+ <symbol>IP</symbol>
+ <description>International Paper Co.</description>
+</quote>
+<quote>
+ <id>121</id>
+ <symbol>DLA</symbol>
+ <description>Delta Apparel Inc.</description>
+</quote>
+<quote>
+ <id>86</id>
+ <symbol>AMAT</symbol>
+ <description>Applied Materials, Inc.</description>
+</quote>
+<quote>
+ <id>41</id>
+ <symbol>XOM</symbol>
+ <description>Exxon Mobil Corp.</description>
+</quote>
+<quote>
+ <id>102</id>
+ <symbol>AMZN</symbol>
+ <description>Amazon.com, Inc.</description>
+</quote>
+<quote>
+ <id>729</id>
+ <symbol>IVGN</symbol>
+ <description>Invitrogen Corp</description>
+</quote>
+<quote>
+ <id>736</id>
+ <symbol>LRCX</symbol>
+ <description>Lam Research Corp</description>
+</quote>
+<quote>
+ <id>712</id>
+ <symbol>CTSH</symbol>
+ <description>Cognizant Technology Solutions Corp</description>
+</quote>
+<quote>
+ <id>713</id>
+ <symbol>DHI</symbol>
+ <description>DR Horton </description>
+</quote>
+<quote>
+ <id>740</id>
+ <symbol>MNST</symbol>
+ <description>Monster Worldwide</description>
+</quote>
+
+ </section>
+
+
+ <!--Indices-->
+
+ <section>
+ <name>Indices</name>
+ <!--on the basis of US Indices-->
+ <section>
+ <name>on the basis of US Indices</name>
+
+<quote>
+ <id>22</id>
+ <symbol>SandP-500</symbol>
+ <description>P 500</description>
+</quote>
+<quote>
+ <id>23</id>
+ <symbol>NQ-100</symbol>
+ <description>CFD statistics for Nasdaq 100</description>
+</quote>
+<quote>
+ <id>28</id>
+ <symbol>Nyssee-comp</symbol>
+ <description>CFD statistics for NYSE Composite</description>
+</quote>
+<quote>
+ <id>21</id>
+ <symbol>D&amp;J-Ind</symbol>
+ <description>CFD statistics for Dow Jones Industrial Average</description>
+</quote>
+<quote>
+ <id>26</id>
+ <symbol>NQ-comp</symbol>
+ <description>CFD statistics for Nasdaq Composite</description>
+</quote>
+<quote>
+ <id>27</id>
+ <symbol>AMMEKS</symbol>
+ <description>CFD statistics for AMEX</description>
+</quote>
+<quote>
+ <id>768</id>
+ <symbol>VIXX</symbol>
+ <description>Volatility Index</description>
+</quote>
+<quote>
+ <id>769</id>
+ <symbol>10Y note</symbol>
+ <description>10Y note yield</description>
+</quote>
+<quote>
+ <id>770</id>
+ <symbol>5Y note</symbol>
+ <description>5Y note yield</description>
+</quote>
+<quote>
+ <id>771</id>
+ <symbol>ST note</symbol>
+ <description>Short term note yield</description>
+</quote>
+
+ </section>
+ <!--on the basis of European Indices-->
+ <section>
+ <name>on the basis of European Indices</name>
+
+<quote>
+ <id>24</id>
+ <symbol>CAAC-40</symbol>
+ <description>CFD statistics for CAC 40</description>
+</quote>
+<quote>
+ <id>25</id>
+ <symbol>DAAX</symbol>
+ <description>CFD statistics for XETRA DAX</description>
+</quote>
+<quote>
+ <id>225</id>
+ <symbol>SWMI</symbol>
+ <description>CFD statistics for SMI</description>
+</quote>
+<quote>
+ <id>345</id>
+ <symbol>Futsee-100</symbol>
+ <description>CFD statistics for FTSE</description>
+</quote>
+<quote>
+ <id>503</id>
+ <symbol>DJE50XX</symbol>
+ <description>CFD statistics for DJ Euro Stoxx50</description>
+</quote>
+
+ </section>
+ <!--on the basis of Asian Indices-->
+ <section>
+ <name>on the basis of Asian Indices</name>
+
+ <quote>
+ <id>500</id>
+ <symbol>N225Jap</symbol>
+ <description>CFD statistics for Nikkei 225</description>
+</quote>
+<quote>
+ <id>501</id>
+ <symbol>SC-Korea</symbol>
+ <description>CFD statistics for KOSPI</description>
+</quote>
+<quote>
+ <id>502</id>
+ <symbol>H-Kong</symbol>
+ <description>CFD statistics for Hang Seng</description>
+</quote>
+
+ </section>
+ </section>
+
+ <!--FOREX-->
+ <section>
+ <name>FOREX</name>
+ <!--Major-->
+ <section>
+ <name>Major</name>
+
+ <quote>
+ <id>3</id>
+ <symbol>USD/CHF</symbol>
+ <description>USD/CHF</description>
+</quote>
+<quote>
+ <id>9</id>
+ <symbol>USD/CAD</symbol>
+ <description>USD/CAD</description>
+</quote>
+<quote>
+ <id>10</id>
+ <symbol>AUD/USD</symbol>
+ <description>AUD/USD</description>
+</quote>
+<quote>
+ <id>11</id>
+ <symbol>NZD/USD</symbol>
+ <description>NZD/USD</description>
+</quote>
+<quote>
+ <id>1</id>
+ <symbol>EUR/USD</symbol>
+ <description>EUR/USD</description>
+</quote>
+<quote>
+ <id>2</id>
+ <symbol>GBP/USD</symbol>
+ <description>GBP/USD</description>
+</quote>
+
+ </section>
+ <!--Other Currencies-->
+ <section>
+ <name>Other Currencies</name>
+
+
+<quote>
+ <id>12</id>
+ <symbol>USD/NOK</symbol>
+ <description>USD/NOK</description>
+</quote>
+<quote>
+ <id>13</id>
+ <symbol>USD/DKK</symbol>
+ <description>USD/DKK</description>
+</quote>
+<quote>
+ <id>14</id>
+ <symbol>USD/SEK</symbol>
+ <description>USD/SEK</description>
+</quote>
+<quote>
+ <id>15</id>
+ <symbol>USD/SAR</symbol>
+ <description>USD/SAR</description>
+</quote>
+<quote>
+ <id>507</id>
+ <symbol>USD/EUR</symbol>
+ <description>USD/EUR</description>
+</quote>
+<quote>
+ <id>508</id>
+ <symbol>USD/GBP</symbol>
+ <description>USD/GBP</description>
+</quote>
+<quote>
+ <id>512</id>
+ <symbol>JPY/USD</symbol>
+ <description>JPY/USD</description>
+</quote>
+<quote>
+ <id>513</id>
+ <symbol>JPY/EUR</symbol>
+ <description>JPY/EUR</description>
+</quote>
+<quote>
+ <id>516</id>
+ <symbol>GBP/EUR</symbol>
+ <description>GBP/EUR</description>
+</quote>
+<quote>
+ <id>519</id>
+ <symbol>CHF/USD</symbol>
+ <description>CHF/USD</description>
+</quote>
+<quote>
+ <id>521</id>
+ <symbol>CHF/JPY</symbol>
+ <description>CHF/JPY</description>
+</quote>
+<quote>
+ <id>514</id>
+ <symbol>JPY/GBP</symbol>
+ <description>JPY/GBP</description>
+</quote>
+<quote>
+ <id>515</id>
+ <symbol>JPY/CHF</symbol>
+ <description>JPY/CHF</description>
+</quote>
+<quote>
+ <id>520</id>
+ <symbol>CHF/EUR</symbol>
+ <description>CHF/EUR</description>
+</quote>
+<quote>
+ <id>522</id>
+ <symbol>CHF/GBP</symbol>
+ <description>CHF/GBP</description>
+</quote>
+<quote>
+ <id>74</id>
+ <symbol>USD/ZAR</symbol>
+ <description>USD/ZAR</description>
+</quote>
+<quote>
+ <id>30</id>
+ <symbol>USD/SGD</symbol>
+ <description>USD/SGD</description>
+</quote>
+<quote>
+ <id>29</id>
+ <symbol>EUR/SEK</symbol>
+ <description>EUR/SEK</description>
+</quote>
+ </section>
+ <!--Crosses-->
+ <section>
+ <name>Crosses</name>
+
+
+<quote>
+ <id>509</id>
+ <symbol>EUR/JPY</symbol>
+ <description>EUR/JPY</description>
+</quote>
+<quote>
+ <id>510</id>
+ <symbol>EUR/GBP</symbol>
+ <description>EUR/GBP</description>
+</quote>
+<quote>
+ <id>511</id>
+ <symbol>EUR/CHF</symbol>
+ <description>EUR/CHF</description>
+</quote>
+<quote>
+ <id>517</id>
+ <symbol>GBP/JPY</symbol>
+ <description>GBP/JPY</description>
+</quote>
+<quote>
+ <id>518</id>
+ <symbol>GBP/CHF</symbol>
+ <description>GBP/CHF</description>
+</quote>
+<quote>
+ <id>60</id>
+ <symbol>AUD/JPY</symbol>
+ <description>AUD/JPY</description>
+</quote>
+<quote>
+ <id>767</id>
+ <symbol>CAD/JPY</symbol>
+ <description>CAD/JPY</description>
+</quote>
+ </section>
+ <!--Other Arab Currencies-->
+ <section>
+ <name>Other Arab Currencies</name>
+
+
+<quote>
+ <id>4</id>
+ <symbol>USD/JPY</symbol>
+ <description>USD/JPY</description>
+</quote>
+<quote>
+ <id>5</id>
+ <symbol>USD/EGP</symbol>
+ <description>USD/EGP</description>
+</quote>
+<quote>
+ <id>6</id>
+ <symbol>USD/JOD</symbol>
+ <description>USD/JOD</description>
+</quote>
+<quote>
+ <id>7</id>
+ <symbol>USD/QAR</symbol>
+ <description>USD/QAR</description>
+</quote>
+<quote>
+ <id>16</id>
+ <symbol>USD/TND</symbol>
+ <description>USD/TND</description>
+</quote>
+<quote>
+ <id>17</id>
+ <symbol>EUR/EGP</symbol>
+ <description>EUR/EGP</description>
+</quote>
+<quote>
+ <id>18</id>
+ <symbol>EUR/JOD</symbol>
+ <description>EUR/JOD</description>
+</quote>
+<quote>
+ <id>19</id>
+ <symbol>EUR/QAR</symbol>
+ <description>EUR/QAR</description>
+</quote>
+<quote>
+ <id>59</id>
+ <symbol>EUR/TND</symbol>
+ <description>EUR/TND</description>
+</quote>
+<quote>
+ <id>523</id>
+ <symbol>EGP/USD</symbol>
+ <description>EGP/USD</description>
+</quote>
+<quote>
+ <id>524</id>
+ <symbol>EGP/EUR</symbol>
+ <description>EGP/EUR</description>
+</quote>
+<quote>
+ <id>527</id>
+ <symbol>EGP/CHF</symbol>
+ <description>EGP/CHF</description>
+</quote>
+<quote>
+ <id>528</id>
+ <symbol>JOD/USD</symbol>
+ <description>JOD/USD</description>
+</quote>
+<quote>
+ <id>529</id>
+ <symbol>JOD/EUR</symbol>
+ <description>JOD/EUR</description>
+</quote>
+<quote>
+ <id>530</id>
+ <symbol>JOD/JPY</symbol>
+ <description>JOD/JPY</description>
+</quote>
+<quote>
+ <id>531</id>
+ <symbol>JOD/GBP</symbol>
+ <description>JOD/GBP</description>
+</quote>
+<quote>
+ <id>533</id>
+ <symbol>JOD/CHF</symbol>
+ <description>JOD/CHF</description>
+</quote>
+<quote>
+ <id>534</id>
+ <symbol>QAR/EUR</symbol>
+ <description>QAR/EUR</description>
+</quote>
+<quote>
+ <id>535</id>
+ <symbol>QAR/USD</symbol>
+ <description>QAR/USD</description>
+</quote>
+<quote>
+ <id>536</id>
+ <symbol>QAR/JPY</symbol>
+ <description>QAR/JPY</description>
+</quote>
+<quote>
+ <id>537</id>
+ <symbol>QAR/GBP</symbol>
+ <description>QAR/GBP</description>
+</quote>
+<quote>
+ <id>538</id>
+ <symbol>QAR/CHF</symbol>
+ <description>QAR/CHF</description>
+</quote>
+<quote>
+ <id>539</id>
+ <symbol>SAR/USD</symbol>
+ <description>SAR/USD</description>
+</quote>
+<quote>
+ <id>540</id>
+ <symbol>SAR/EUR</symbol>
+ <description>SAR/EUR</description>
+</quote>
+<quote>
+ <id>541</id>
+ <symbol>SAR/JPY</symbol>
+ <description>SAR/JPY</description>
+</quote>
+<quote>
+ <id>542</id>
+ <symbol>SAR/GBP</symbol>
+ <description>SAR/GBP</description>
+</quote>
+<quote>
+ <id>543</id>
+ <symbol>GBP/SAR</symbol>
+ <description>GBP/SAR</description>
+</quote>
+<quote>
+ <id>544</id>
+ <symbol>SAR/CHF</symbol>
+ <description>SAR/CHF</description>
+</quote>
+<quote>
+ <id>545</id>
+ <symbol>TND/USD</symbol>
+ <description>TND/USD</description>
+</quote>
+<quote>
+ <id>546</id>
+ <symbol>TND/EUR</symbol>
+ <description>TND/EUR</description>
+</quote>
+<quote>
+ <id>547</id>
+ <symbol>TND/JPY</symbol>
+ <description>TND/JPY</description>
+</quote>
+<quote>
+ <id>548</id>
+ <symbol>TND/GBP</symbol>
+ <description>TND/GBP</description>
+</quote>
+<quote>
+ <id>549</id>
+ <symbol>TND/CHF</symbol>
+ <description>TND/CHF</description>
+</quote>
+<quote>
+ <id>20</id>
+ <symbol>EUR/SAR</symbol>
+ <description>EUR/SAR</description>
+</quote>
+<quote>
+ <id>525</id>
+ <symbol>EGP/JPY</symbol>
+ <description>EGP/JPY</description>
+</quote>
+<quote>
+ <id>526</id>
+ <symbol>EGP/GBP</symbol>
+ <description>EGP/GBP</description>
+</quote>
+<quote>
+ <id>532</id>
+ <symbol>GBP/JOD</symbol>
+ <description>GBP/JOD</description>
+</quote>
+
+ </section>
+ </section>
+
+ <!--Asian Stocks-->
+ <section>
+ <name>Asian Stocks</name>
+
+
+<quote>
+ <id>307</id>
+ <symbol>TSM</symbol>
+ <description>Taiwan Semiconductor Mfg</description>
+</quote>
+<quote>
+ <id>308</id>
+ <symbol>SNE</symbol>
+ <description>Sony Corp.</description>
+</quote>
+<quote>
+ <id>310</id>
+ <symbol>MITSY</symbol>
+ <description>Mitsui Co., Ltd.</description>
+</quote>
+<quote>
+ <id>314</id>
+ <symbol>NSANY</symbol>
+ <description>Nissan Motor Co., Ltd.</description>
+</quote>
+<quote>
+ <id>317</id>
+ <symbol>CAJ</symbol>
+ <description>Canon, Inc.</description>
+</quote>
+<quote>
+ <id>323</id>
+ <symbol>CHL</symbol>
+ <description>China Mobile Limited</description>
+</quote>
+<quote>
+ <id>324</id>
+ <symbol>SNP</symbol>
+ <description>Chemical Corp.</description>
+</quote>
+<quote>
+ <id>313</id>
+ <symbol>HMC</symbol>
+ <description>Honda Motor Co., Ltd.</description>
+</quote>
+<quote>
+ <id>315</id>
+ <symbol>MC</symbol>
+ <description>Matsushita Electric Ind.</description>
+</quote>
+<quote>
+ <id>311</id>
+ <symbol>NTT</symbol>
+ <description> Telephone</description>
+</quote>
+<quote>
+ <id>312</id>
+ <symbol>HIT</symbol>
+ <description>Hitachi, Ltd.</description>
+</quote>
+
+ </section>
+
+ <!--Commodities-->
+ <section>
+ <name>Commodities</name>
+
+
+<quote>
+ <id>333</id>
+ <symbol>XAU/USD</symbol>
+ <description>XAU/USD</description>
+</quote>
+<quote>
+ <id>334</id>
+ <symbol>XAG/USD</symbol>
+ <description>XAG/USD</description>
+</quote>
+<quote>
+ <id>335</id>
+ <symbol>Platinum</symbol>
+ <description>Platinum</description>
+</quote>
+<quote>
+ <id>336</id>
+ <symbol>Palladium</symbol>
+ <description>Palladium</description>
+</quote>
+<quote>
+ <id>504</id>
+ <symbol>Light</symbol>
+ <description>Light</description>
+</quote>
+<quote>
+ <id>505</id>
+ <symbol>Brent</symbol>
+ <description>Brent</description>
+</quote>
+<quote>
+ <id>506</id>
+ <symbol>Copper</symbol>
+ <description>Copper</description>
+</quote>
+
+ </section>
+</Provider>
diff --git a/protocols/Quotes/Utility/Google.py b/protocols/Quotes/Utility/Google.py
new file mode 100644
index 0000000000..35653a77f6
--- /dev/null
+++ b/protocols/Quotes/Utility/Google.py
@@ -0,0 +1,52 @@
+from html.parser import HTMLParser
+import sys
+from xml.etree.ElementTree import Element, ElementTree, SubElement
+
+class MyHTMLParser(HTMLParser):
+ def __init__(self,in_fn,out_fn):
+ HTMLParser.__init__(self)
+ f_in = open(in_fn,'r')
+ self.quote = 0
+ self.start = 0
+ self.parse_option = 0
+ self.elQuote = Element("fake")
+ elProvider = Element("Provider")
+ SubElement(elProvider,'name').text = 'Google'
+ SubElement(elProvider,'ref').text = 'http://www.google.com'
+ SubElement(elProvider,'url').text = 'http://www.google.com/finance/converter?a=1&'
+ self.root = SubElement(elProvider,'section')
+ SubElement(self.root,'name').text = 'Currencies'
+ self.feed(f_in.read())
+ f_in.close()
+ ElementTree(elProvider).write(out_fn)
+
+ def handle_starttag(self, tag, attrs):
+ self.start = 1
+ if tag == 'select':
+ if self.parse_option == 0:
+ for k in attrs:
+ if k[0] == 'name' and k[1] == 'from':
+ self.parse_option = 1
+ break
+ else:
+ self.parse_option == 0
+ elif self.parse_option == 1 and tag == 'option':
+ for k in attrs:
+ if k[0] == 'value':
+ self.elQuote = SubElement(self.root,'quote')
+ SubElement(self.elQuote,'id').text = k[1]
+ SubElement(self.elQuote,'symbol').text = k[1]
+ break
+
+ def handle_endtag(self, tag):
+ self.start = 0
+ if tag == 'select':
+ self.parse_option == 0
+
+ def handle_data(self, data):
+ if self.start == 1 and self.parse_option == 1:
+ SubElement(self.elQuote,'description').text = data
+
+parser = MyHTMLParser(sys.argv[1],sys.argv[2])
+parser.close()
+
diff --git a/protocols/Quotes/Utility/GoogleFinance.xml b/protocols/Quotes/Utility/GoogleFinance.xml
new file mode 100644
index 0000000000..031afbcdd5
--- /dev/null
+++ b/protocols/Quotes/Utility/GoogleFinance.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Provider>
+ <name>Google Finance</name>
+ <ref>http://www.google.com</ref>
+ <url>http://www.google.com/finance</url>
+</Provider> \ No newline at end of file
diff --git a/protocols/Quotes/Utility/Quotes_Readme.txt b/protocols/Quotes/Utility/Quotes_Readme.txt
new file mode 100644
index 0000000000..7c0bf2ca10
--- /dev/null
+++ b/protocols/Quotes/Utility/Quotes_Readme.txt
@@ -0,0 +1,112 @@
+Quotes version 0.0.24.0 plugin for Miranda
+
+This plugin displays periodically updated economic quotes, currency exchanges and different economic and financial indexes in Miranda contact list.
+
+Author: Dioksin.
+You can always contact me via email dioksin@ua.fm
+
+How to install:
+unpack zip archive;
+copy quotes.dll and Quotes subdirectory from Plugins folder to miranda plugins floder.
+copy proto_Quotes.dll from Icons folder to miranda icons folder
+
+[2011-10-24] Changelog Release 0.0.24.0
+1. Tendency calculation for Yahoo was fixed
+
+[2011-10-18] Changelog Release 0.0.23.0
+1. Previous Close and Change values were added to YAHOO
+2. If there is no xml file corresponding options page is not show in properties window
+
+[2011-10-14] Changelog Release 0.0.22.0
+1. Supports YAHOO
+2. Options location was moved from "Plugins\Quotes" to "Network\Quotes"
+
+[2011-08-19] Changelog Release 0.0.21.0
+1. Tendency format specification
+2. Main icon was changed
+3. Currency converter icon was changed
+4. Popup plugin support
+5. Per-contact options
+6. Menu redesign
+7. Import/export from/to xml file
+
+[2011-08-14] Changelog Release 0.0.20.0
+1. Updation of code to use new format of Google finance HTML page
+
+[2010-09-26] Changelog Release 0.0.19.0
+1. Currency converter shown values in the sientific format
+2. Currency converter didn't convert big values
+3. Currency converter output is formatted with user-defined locale preferences
+4. Swap button in the currency converter has an icon
+5. Big icon is set for the currency converter to correct show in ALT+TAB dialog
+
+[2010-09-19] Changelog Release 0.0.18.0
+1. Thousand separator error for non USA locale in Google Finance
+
+Changelog Release 0.0.17.0
+1. The percent change with respecto to yesterday close variable was added to the Google Finance
+2. The Vietnamese Dong was added to the Currency Converter
+
+Changelog Release 0.0.16.0
+1. It was impossible to get quotes from google finance on non-USA locale
+
+Changelog Release 0.0.15.0
+1. Crash if invalid display name format was used
+
+Changelog Release 0.0.14.0
+1. References to Microsoft's XML parser were removed.
+
+Changelog Release 0.0.12.0
+1. The Swap button had been added to the Currency Converter
+
+Changelog Release 0.0.11.0
+1. Google finance is supported
+2. Occupied status was made optionally (To use it's necessary to set the 'ExtendedStatus' option in the Miranda's database).
+
+Changelog Release 0.0.9.981
+1. Currency converter
+2. Refresh all Quotes\Rates
+3. Refresh particular Quote\Rate
+2. Minor fixings to better support national language pack
+
+Changelog Release 0.0.0.8
+1. Minor changing in logic of status
+2. Minor resource modification to better support national language pack
+
+Changelog Release 0.0.0.7
+1. Status message may be set on per contact basis (second line in contact list)
+2. Two new modes were added. Occupied - it's set if error occurred during rate/quote updation. DND - it's set if updation is in progress.
+3. Open Log File menu item was added and Quotes related menu items are grouped in Quotes popup menu.
+4. Several new variables were added: previous rate, fetch date, fetch time.
+5. New empty icon was added. This icon is used when rate/quote was not changed.
+6. Quotes\rate info page was changed to show both current and previous rates.
+7. Database ForceToAddArrowToNick setting was added. This value governs an up\down arrow appearance in contact name. If it's equal 0 (default value) - arrows will be added only if extraicons were set . It it' equal 1 - arrows will be shown always and if it's equal 2 - arrows will be never shown.
+
+Changelog Release 0.0.0.6
+1. Change to log and to history only if rate (quote) value changed option has been added
+2. Several minor bugs were fixed
+
+Changelog Release 0.0.0.5
+1. Extraicons supporting
+2. Ability to change name in contact list with variables
+3. Log to file
+4. Log to Miranda's history
+5. Proxy server supporting
+6. Protocol icons were changes and removed to separate dll
+
+Changelog Release 0.0.0.4
+1. It is possible to get currency exchange rates from Google site
+2. Unicode supporting was improved
+3. User info page was modified
+4. Option pages were moved under Plugin section
+
+Changelog Release 0.0.0.3
+1. Fix bug when decimal separator was not dot
+2. User info page was added
+
+Changelog Release 0.0.0.2
+1. The size of plugin was reduced
+2. The plugin was statically link with CRT library to resolve some dependencies to system modules
+3. The updater plugin is supported now.
+
+
diff --git a/protocols/Quotes/Utility/Yahoo.xml b/protocols/Quotes/Utility/Yahoo.xml
new file mode 100644
index 0000000000..1c2a156d89
--- /dev/null
+++ b/protocols/Quotes/Utility/Yahoo.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Provider>
+ <name>Yahoo</name>
+ <ref>http://finance.yahoo.com/</ref>
+ <url>http://finance.yahoo.com/d/</url>
+</Provider> \ No newline at end of file
diff --git a/protocols/Quotes/Utility/google.xml b/protocols/Quotes/Utility/google.xml
new file mode 100644
index 0000000000..9363addced
--- /dev/null
+++ b/protocols/Quotes/Utility/google.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Provider>
+ <name>Google</name>
+ <ref>http://www.google.com</ref>
+ <url>http://www.google.com/finance/converter</url>
+
+<section>
+ <name>Currencies</name>
+ <quote>
+ <id>AED</id>
+ <symbol>AED</symbol>
+ <description>United Arab Emirates Dirham (AED)</description>
+ </quote>
+ <quote>
+ <id>ANG</id><symbol>ANG</symbol><description>Netherlands Antillean Gulden (ANG)</description>
+ </quote>
+ <quote>
+ <id>ARS</id><symbol>ARS</symbol><description>Argentine Peso (ARS)</description>
+ </quote>
+ <quote>
+ <id>AUD</id><symbol>AUD</symbol><description>Australian Dollar (AUD)</description>
+ </quote>
+ <quote>
+ <id>BGN</id><symbol>BGN</symbol><description>Bulgarian Lev (BGN)</description>
+ </quote>
+ <quote>
+ <id>BHD</id><symbol>BHD</symbol><description>Bahraini Dinar (BHD)</description>
+ </quote>
+ <quote>
+ <id>BND</id><symbol>BND</symbol><description>Brunei Dollar (BND)</description>
+ </quote>
+ <quote>
+ <id>BOB</id><symbol>BOB</symbol><description>Bolivian Boliviano (BOB)</description>
+ </quote>
+ <quote>
+ <id>BRL</id><symbol>BRL</symbol><description>Brazilian Real (BRL)</description>
+ </quote>
+ <quote>
+ <id>BWP</id><symbol>BWP</symbol><description>Botswana Pula (BWP)</description>
+ </quote>
+ <quote>
+ <id>CAD</id><symbol>CAD</symbol><description>Canadian Dollar (CAD)</description>
+ </quote>
+ <quote>
+ <id>CHF</id><symbol>CHF</symbol><description>Swiss Franc (CHF)</description>
+ </quote>
+ <quote>
+ <id>CLP</id><symbol>CLP</symbol><description>Chilean Peso (CLP)</description>
+ </quote>
+ <quote>
+ <id>CNY</id><symbol>CNY</symbol><description>Chinese Yuan (renminbi) (CNY)</description>
+ </quote>
+ <quote>
+ <id>COP</id><symbol>COP</symbol><description>Colombian Peso (COP)</description>
+ </quote>
+ <quote>
+ <id>CSD</id><symbol>CSD</symbol><description>Serbian Dinar (CSD)</description>
+ </quote>
+ <quote>
+ <id>CZK</id><symbol>CZK</symbol><description>Czech Koruna (CZK)</description>
+ </quote>
+ <quote>
+ <id>DKK</id><symbol>DKK</symbol><description>Danish Krone (DKK)</description>
+ </quote>
+ <quote>
+ <id>EEK</id><symbol>EEK</symbol><description>Estonian Kroon (EEK)</description>
+ </quote>
+ <quote>
+ <id>EGP</id><symbol>EGP</symbol><description>Egyptian Pound (EGP)</description>
+ </quote>
+ <quote>
+ <id>EUR</id><symbol>EUR</symbol><description>Euro (EUR)</description>
+ </quote>
+ <quote>
+ <id>FJD</id><symbol>FJD</symbol><description>Fijian Dollar (FJD)</description>
+ </quote>
+ <quote><id>GBP</id><symbol>GBP</symbol><description>British Pound (GBP)</description></quote><quote><id>HKD</id><symbol>HKD</symbol><description>Hong Kong Dollar (HKD)</description></quote><quote><id>HNL</id><symbol>HNL</symbol><description>Honduran Lempira (HNL)</description></quote><quote><id>HRK</id><symbol>HRK</symbol><description>Croatian Kuna (HRK)</description></quote><quote><id>HUF</id><symbol>HUF</symbol><description>Hungarian Forint (HUF)</description></quote><quote><id>IDR</id><symbol>IDR</symbol><description>Indonesian Rupiah (IDR)</description></quote><quote><id>ILS</id><symbol>ILS</symbol><description>New Israeli Sheqel (ILS)</description></quote><quote><id>INR</id><symbol>INR</symbol><description>Indian Rupee (INR)</description></quote><quote><id>ISK</id><symbol>ISK</symbol><description>Icelandic Króna (ISK)</description></quote><quote><id>JPY</id><symbol>JPY</symbol><description>Japanese Yen (JPY)</description></quote><quote><id>KRW</id><symbol>KRW</symbol><description>South Korean Won (KRW)</description></quote><quote><id>KWD</id><symbol>KWD</symbol><description>Kuwaiti Dinar (KWD)</description></quote><quote><id>KZT</id><symbol>KZT</symbol><description>Kazakhstani Tenge (KZT)</description></quote><quote><id>LKR</id><symbol>LKR</symbol><description>Sri Lankan Rupee (LKR)</description></quote><quote><id>LTL</id><symbol>LTL</symbol><description>Lithuanian Litas (LTL)</description></quote><quote><id>MAD</id><symbol>MAD</symbol><description>Moroccan Dirham (MAD)</description></quote><quote><id>MUR</id><symbol>MUR</symbol><description>Mauritian Rupee (MUR)</description></quote><quote><id>MXN</id><symbol>MXN</symbol><description>Mexican Peso (MXN)</description></quote><quote><id>MYR</id><symbol>MYR</symbol><description>Malaysian Ringgit (MYR)</description></quote><quote><id>NOK</id><symbol>NOK</symbol><description>Norwegian Krone (NOK)</description></quote><quote><id>NPR</id><symbol>NPR</symbol><description>Nepalese Rupee (NPR)</description></quote><quote><id>NZD</id><symbol>NZD</symbol><description>New Zealand Dollar (NZD)</description></quote><quote><id>OMR</id><symbol>OMR</symbol><description>Omani Rial (OMR)</description></quote><quote><id>PEN</id><symbol>PEN</symbol><description>Peruvian Nuevo Sol (PEN)</description></quote><quote><id>PHP</id><symbol>PHP</symbol><description>Philippine Peso (PHP)</description></quote><quote><id>PKR</id><symbol>PKR</symbol><description>Pakistani Rupee (PKR)</description></quote><quote><id>PLN</id><symbol>PLN</symbol><description>Polish Złoty (PLN)</description></quote><quote><id>QAR</id><symbol>QAR</symbol><description>Qatari Riyal (QAR)</description></quote><quote><id>RON</id><symbol>RON</symbol><description>New Romanian Leu (RON)</description></quote>
+
+ <quote>
+ <id>RUB</id><symbol>RUB</symbol><description>Russian Ruble (RUB)</description>
+ </quote>
+ <quote>
+ <id>SAR</id><symbol>SAR</symbol><description>Saudi Riyal (SAR)</description>
+ </quote>
+ <quote><id>SEK</id><symbol>SEK</symbol><description>Swedish Krona (SEK)</description></quote><quote><id>SGD</id><symbol>SGD</symbol><description>Singapore Dollar (SGD)</description></quote><quote><id>SIT</id><symbol>SIT</symbol><description>Slovenian Tolar (SIT)</description></quote><quote><id>SKK</id><symbol>SKK</symbol><description>Slovak Koruna (SKK)</description></quote><quote><id>THB</id><symbol>THB</symbol><description>Thai Baht (THB)</description></quote><quote><id>TRY</id><symbol>TRY</symbol><description>New Turkish Lira (TRY)</description></quote><quote><id>TTD</id><symbol>TTD</symbol><description>Trinidad and Tobago Dollar (TTD)</description></quote><quote><id>TWD</id><symbol>TWD</symbol><description>New Taiwan Dollar (TWD)</description></quote><quote><id>UAH</id><symbol>UAH</symbol><description>Ukrainian Hryvnia (UAH)</description></quote><quote><id>USD</id><symbol>USD</symbol><description>United States Dollar (USD)</description></quote><quote><id>VEB</id><symbol>VEB</symbol><description>Venezuelan Bolívar (VEB)</description></quote><quote><id>ZAR</id><symbol>ZAR</symbol><description>South African Rand (ZAR)</description></quote>
+ <quote>
+ <id>VND</id><symbol>VND</symbol><description>Vietnamese Dong (VND)</description>
+ </quote>
+</section>
+</Provider> \ No newline at end of file
diff --git a/protocols/Quotes/Version.rc b/protocols/Quotes/Version.rc
new file mode 100644
index 0000000000..a5fcb30231
--- /dev/null
+++ b/protocols/Quotes/Version.rc
@@ -0,0 +1,41 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "afxres.h"
+#include "version.h"
+
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#endif //_WIN32
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "FileDescription", __DESCRIPTION
+ VALUE "FileVersion", __FILEVERSION_DOTS
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ VALUE "ProductName", __PLUGIN_NAME
+ VALUE "ProductVersion", __FILEVERSION_DOTS
+ VALUE "SpecialBuild", SPECIAL_BUILD_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/protocols/Quotes/WinCtrlHelper.cpp b/protocols/Quotes/WinCtrlHelper.cpp
new file mode 100644
index 0000000000..dba445958e
--- /dev/null
+++ b/protocols/Quotes/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(CModuleInfo::GetModuleHandle(),
+ MAKEINTRESOURCE(IDD_DIALOG_VARIABLE_LIST),
+ hwndParent,
+ VariableListDlgProc,
+ reinterpret_cast<LPARAM>(pProvider));
+}
diff --git a/protocols/Quotes/WinCtrlHelper.h b/protocols/Quotes/WinCtrlHelper.h
new file mode 100644
index 0000000000..d7f8957a86
--- /dev/null
+++ b/protocols/Quotes/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/WorkingThread.cpp b/protocols/Quotes/WorkingThread.cpp
new file mode 100644
index 0000000000..bc4d80b734
--- /dev/null
+++ b/protocols/Quotes/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/WorkingThread.h b/protocols/Quotes/WorkingThread.h
new file mode 100644
index 0000000000..a77734bb85
--- /dev/null
+++ b/protocols/Quotes/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/XMLEngineMI.cpp b/protocols/Quotes/XMLEngineMI.cpp
new file mode 100644
index 0000000000..7e2adfb7d9
--- /dev/null
+++ b/protocols/Quotes/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/XMLEngineMI.h b/protocols/Quotes/XMLEngineMI.h
new file mode 100644
index 0000000000..5e5a51232f
--- /dev/null
+++ b/protocols/Quotes/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/dllmain.cpp b/protocols/Quotes/dllmain.cpp
new file mode 100644
index 0000000000..9a1be15de5
--- /dev/null
+++ b/protocols/Quotes/dllmain.cpp
@@ -0,0 +1,23 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+#include "ModuleInfo.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ CModuleInfo::SetModuleHandle(hModule);
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
diff --git a/protocols/Quotes/proto_Quotes/proto_Quotes.rc b/protocols/Quotes/proto_Quotes/proto_Quotes.rc
new file mode 100644
index 0000000000..b9ce00b0cd
--- /dev/null
+++ b/protocols/Quotes/proto_Quotes/proto_Quotes.rc
@@ -0,0 +1,122 @@
+//Microsoft Developer Studio generated resource script.
+//
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+104 ICON DISCARDABLE "../res/proto_online.ico"
+105 ICON DISCARDABLE "../res/proto_offline.ico"
+131 ICON DISCARDABLE "../res/proto_na.ico"
+159 ICON DISCARDABLE "../res/proto_occupied.ico"
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,0,0,1
+ PRODUCTVERSION 0,0,0,15
+ FILEFLAGSMASK 0x37L
+#ifdef _DEBUG
+ FILEFLAGS 0x21L
+#else
+ FILEFLAGS 0x20L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "Dioksin"
+ VALUE "FileDescription", "Quotes protocol icons"
+ VALUE "FileVersion", "0, 0, 0, 1"
+ VALUE "InternalName", "proto_Quotes"
+ VALUE "LegalCopyright", "Do not worry!"
+ VALUE "OriginalFilename", "proto_Quotes.dll"
+ VALUE "ProductName", "Miranda IM"
+ VALUE "ProductVersion", "0, 0, 0, 15"
+ VALUE "SpecialBuild", "3"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj b/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj
new file mode 100644
index 0000000000..13a3acc0bc
--- /dev/null
+++ b/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>Proto_Quotes</ProjectName>
+ <ProjectGuid>{5A0A9761-78E1-4E0F-AD8C-8931A667A5F2}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <None Include="..\res\proto_na.ico" />
+ <None Include="..\res\proto_occupied.ico" />
+ <None Include="..\res\proto_offline.ico" />
+ <None Include="..\res\proto_online.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="proto_Quotes.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj.filters b/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj.filters
new file mode 100644
index 0000000000..6da0285fe9
--- /dev/null
+++ b/protocols/Quotes/proto_Quotes/proto_Quotes_10.vcxproj.filters
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\res\proto_na.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\res\proto_occupied.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\res\proto_offline.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\res\proto_online.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="proto_Quotes.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/Quotes/res/CurrencyConverter.ico b/protocols/Quotes/res/CurrencyConverter.ico
new file mode 100644
index 0000000000..67ac2095f5
--- /dev/null
+++ b/protocols/Quotes/res/CurrencyConverter.ico
Binary files differ
diff --git a/protocols/Quotes/res/Export quotes.ico b/protocols/Quotes/res/Export quotes.ico
new file mode 100644
index 0000000000..31c7aa2ba1
--- /dev/null
+++ b/protocols/Quotes/res/Export quotes.ico
Binary files differ
diff --git a/protocols/Quotes/res/Import quotes.ico b/protocols/Quotes/res/Import quotes.ico
new file mode 100644
index 0000000000..506aa62af3
--- /dev/null
+++ b/protocols/Quotes/res/Import quotes.ico
Binary files differ
diff --git a/protocols/Quotes/res/Refresh.ico b/protocols/Quotes/res/Refresh.ico
new file mode 100644
index 0000000000..2dbcfd3878
--- /dev/null
+++ b/protocols/Quotes/res/Refresh.ico
Binary files differ
diff --git a/protocols/Quotes/res/Section.ico b/protocols/Quotes/res/Section.ico
new file mode 100644
index 0000000000..f59105b665
--- /dev/null
+++ b/protocols/Quotes/res/Section.ico
Binary files differ
diff --git a/protocols/Quotes/res/down.ico b/protocols/Quotes/res/down.ico
new file mode 100644
index 0000000000..9dfe185cbe
--- /dev/null
+++ b/protocols/Quotes/res/down.ico
Binary files differ
diff --git a/protocols/Quotes/res/main.ico b/protocols/Quotes/res/main.ico
new file mode 100644
index 0000000000..4d32e57495
--- /dev/null
+++ b/protocols/Quotes/res/main.ico
Binary files differ
diff --git a/protocols/Quotes/res/notchanged.ico b/protocols/Quotes/res/notchanged.ico
new file mode 100644
index 0000000000..e1d9ee3a09
--- /dev/null
+++ b/protocols/Quotes/res/notchanged.ico
Binary files differ
diff --git a/protocols/Quotes/res/proto_na.ico b/protocols/Quotes/res/proto_na.ico
new file mode 100644
index 0000000000..c8888adb80
--- /dev/null
+++ b/protocols/Quotes/res/proto_na.ico
Binary files differ
diff --git a/protocols/Quotes/res/proto_occupied.ico b/protocols/Quotes/res/proto_occupied.ico
new file mode 100644
index 0000000000..3f54c740d1
--- /dev/null
+++ b/protocols/Quotes/res/proto_occupied.ico
Binary files differ
diff --git a/protocols/Quotes/res/proto_offline.ico b/protocols/Quotes/res/proto_offline.ico
new file mode 100644
index 0000000000..cd99c072bf
--- /dev/null
+++ b/protocols/Quotes/res/proto_offline.ico
Binary files differ
diff --git a/protocols/Quotes/res/proto_online.ico b/protocols/Quotes/res/proto_online.ico
new file mode 100644
index 0000000000..29e500e2bb
--- /dev/null
+++ b/protocols/Quotes/res/proto_online.ico
Binary files differ
diff --git a/protocols/Quotes/res/quote.ico b/protocols/Quotes/res/quote.ico
new file mode 100644
index 0000000000..832ed12f52
--- /dev/null
+++ b/protocols/Quotes/res/quote.ico
Binary files differ
diff --git a/protocols/Quotes/res/swap.ico b/protocols/Quotes/res/swap.ico
new file mode 100644
index 0000000000..1bff71b764
--- /dev/null
+++ b/protocols/Quotes/res/swap.ico
Binary files differ
diff --git a/protocols/Quotes/res/up.ico b/protocols/Quotes/res/up.ico
new file mode 100644
index 0000000000..a75899cd3d
--- /dev/null
+++ b/protocols/Quotes/res/up.ico
Binary files differ
diff --git a/protocols/Quotes/resource.h b/protocols/Quotes/resource.h
new file mode 100644
index 0000000000..50ee0a637b
--- /dev/null
+++ b/protocols/Quotes/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/stdafx.cpp b/protocols/Quotes/stdafx.cpp
new file mode 100644
index 0000000000..e4738d8f60
--- /dev/null
+++ b/protocols/Quotes/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/stdafx.h b/protocols/Quotes/stdafx.h
new file mode 100644
index 0000000000..19c85a3303
--- /dev/null
+++ b/protocols/Quotes/stdafx.h
@@ -0,0 +1,165 @@
+// 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 0x0800
+#define MIRANDA_CUSTOM_LP
+// #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>
+
+#ifdef _UNICODE
+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;
+#else
+typedef std::string tstring;
+typedef std::ostringstream tostringstream;
+typedef std::istringstream tistringstream;
+typedef std::ofstream tofstream;
+typedef std::ifstream tifstream;
+typedef std::ostream tostream;
+typedef std::istream tistream;
+typedef boost::posix_time::time_input_facet ttime_input_facet;
+typedef boost::posix_time::time_facet ttime_facet;
+#endif
+
+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){}
+};
+
+
+// #ifdef MIRANDA_VER
+// #undef MIRANDA_VER
+// #endif
+
+// TODO: reference additional headers your program requires here
diff --git a/protocols/Quotes/targetver.h b/protocols/Quotes/targetver.h
new file mode 100644
index 0000000000..f583181dfd
--- /dev/null
+++ b/protocols/Quotes/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/version.h b/protocols/Quotes/version.h
new file mode 100644
index 0000000000..956486d4d5
--- /dev/null
+++ b/protocols/Quotes/version.h
@@ -0,0 +1,25 @@
+#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)
+
+#if defined (_UNICODE)
+#define __PLUGIN_NAME "Quotes (Unicode)"
+#else
+#define __PLUGIN_NAME "Quotes"
+#endif
+#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://www.miranda-im.org"
+#define __COPYRIGHT "Don't worry!"
+#define SPECIAL_BUILD_STRING "5388"