From a70382b0e8bed265a1d314d9f6aae8f2dd48d20b Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 28 Nov 2012 18:45:54 +0000 Subject: ex-protos moved to the Plugins folder git-svn-id: http://svn.miranda-ng.org/main/trunk@2545 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Quotes/src/Base64.cpp | 43 + plugins/Quotes/src/Base64.h | 12 + plugins/Quotes/src/Chart.h | 280 +++++ plugins/Quotes/src/ComHelper.cpp | 39 + plugins/Quotes/src/ComHelper.h | 9 + plugins/Quotes/src/CommonOptionDlg.cpp | 272 +++++ plugins/Quotes/src/CommonOptionDlg.h | 17 + plugins/Quotes/src/CreateFilePath.cpp | 45 + plugins/Quotes/src/CreateFilePath.h | 8 + plugins/Quotes/src/CurrencyConverter.cpp | 309 ++++++ plugins/Quotes/src/CurrencyConverter.h | 6 + plugins/Quotes/src/DBUtils.cpp | 70 ++ plugins/Quotes/src/DBUtils.h | 13 + plugins/Quotes/src/EconomicRateInfo.h | 59 + plugins/Quotes/src/ExtraImages.cpp | 67 ++ plugins/Quotes/src/ExtraImages.h | 37 + plugins/Quotes/src/Forex.cpp | 469 ++++++++ plugins/Quotes/src/HTMLParserMS.cpp | 313 ++++++ plugins/Quotes/src/HTMLParserMS.h | 36 + plugins/Quotes/src/HTTPSession.cpp | 262 +++++ plugins/Quotes/src/HTTPSession.h | 27 + plugins/Quotes/src/IHTMLEngine.h | 18 + plugins/Quotes/src/IHTMLParser.h | 41 + plugins/Quotes/src/IQuotesProvider.h | 41 + plugins/Quotes/src/IXMLEngine.h | 43 + plugins/Quotes/src/IconLib.cpp | 94 ++ plugins/Quotes/src/IconLib.h | 21 + plugins/Quotes/src/ImportExport.cpp | 850 +++++++++++++++ plugins/Quotes/src/ImportExport.h | 11 + plugins/Quotes/src/IsWithinAccuracy.h | 15 + plugins/Quotes/src/LightMutex.cpp | 22 + plugins/Quotes/src/LightMutex.h | 34 + plugins/Quotes/src/Locale.cpp | 75 ++ plugins/Quotes/src/Locale.h | 9 + plugins/Quotes/src/Log.cpp | 56 + plugins/Quotes/src/Log.h | 13 + plugins/Quotes/src/ModuleInfo.cpp | 135 +++ plugins/Quotes/src/ModuleInfo.h | 43 + plugins/Quotes/src/OptionDukasCopy.cpp | 414 +++++++ plugins/Quotes/src/OptionDukasCopy.h | 8 + plugins/Quotes/src/QuoteChart.cpp | 408 +++++++ plugins/Quotes/src/QuoteChart.h | 12 + plugins/Quotes/src/QuoteInfoDlg.cpp | 350 ++++++ plugins/Quotes/src/QuoteInfoDlg.h | 11 + plugins/Quotes/src/QuotesProviderBase.cpp | Bin 0 -> 58860 bytes plugins/Quotes/src/QuotesProviderBase.h | 112 ++ plugins/Quotes/src/QuotesProviderDukasCopy.cpp | Bin 0 -> 15324 bytes plugins/Quotes/src/QuotesProviderDukasCopy.h | 38 + plugins/Quotes/src/QuotesProviderFinance.cpp | 318 ++++++ plugins/Quotes/src/QuotesProviderFinance.h | 21 + plugins/Quotes/src/QuotesProviderGoogle.cpp | 543 +++++++++ plugins/Quotes/src/QuotesProviderGoogle.h | 42 + plugins/Quotes/src/QuotesProviderGoogleFinance.cpp | 366 +++++++ plugins/Quotes/src/QuotesProviderGoogleFinance.h | 25 + plugins/Quotes/src/QuotesProviderVisitor.h | 25 + .../Quotes/src/QuotesProviderVisitorDbSettings.cpp | 157 +++ .../Quotes/src/QuotesProviderVisitorDbSettings.h | 49 + .../QuotesProviderVisitorFormatSpecificator.cpp | 63 ++ .../src/QuotesProviderVisitorFormatSpecificator.h | 36 + .../Quotes/src/QuotesProviderVisitorFormater.cpp | 216 ++++ plugins/Quotes/src/QuotesProviderVisitorFormater.h | 32 + .../Quotes/src/QuotesProviderVisitorTendency.cpp | 70 ++ plugins/Quotes/src/QuotesProviderVisitorTendency.h | 29 + plugins/Quotes/src/QuotesProviderYahoo.cpp | 193 ++++ plugins/Quotes/src/QuotesProviderYahoo.h | 20 + plugins/Quotes/src/QuotesProviders.cpp | 119 ++ plugins/Quotes/src/QuotesProviders.h | 32 + plugins/Quotes/src/SettingsDlg.cpp | 1148 ++++++++++++++++++++ plugins/Quotes/src/SettingsDlg.h | 118 ++ plugins/Quotes/src/WinCtrlHelper.cpp | 49 + plugins/Quotes/src/WinCtrlHelper.h | 37 + plugins/Quotes/src/WorkingThread.cpp | 15 + plugins/Quotes/src/WorkingThread.h | 6 + plugins/Quotes/src/XMLEngineMI.cpp | 230 ++++ plugins/Quotes/src/XMLEngineMI.h | 17 + plugins/Quotes/src/resource.h | 109 ++ plugins/Quotes/src/stdafx.cpp | 8 + plugins/Quotes/src/stdafx.h | 154 +++ plugins/Quotes/src/targetver.h | 24 + plugins/Quotes/src/version.h | 21 + 80 files changed, 9559 insertions(+) create mode 100644 plugins/Quotes/src/Base64.cpp create mode 100644 plugins/Quotes/src/Base64.h create mode 100644 plugins/Quotes/src/Chart.h create mode 100644 plugins/Quotes/src/ComHelper.cpp create mode 100644 plugins/Quotes/src/ComHelper.h create mode 100644 plugins/Quotes/src/CommonOptionDlg.cpp create mode 100644 plugins/Quotes/src/CommonOptionDlg.h create mode 100644 plugins/Quotes/src/CreateFilePath.cpp create mode 100644 plugins/Quotes/src/CreateFilePath.h create mode 100644 plugins/Quotes/src/CurrencyConverter.cpp create mode 100644 plugins/Quotes/src/CurrencyConverter.h create mode 100644 plugins/Quotes/src/DBUtils.cpp create mode 100644 plugins/Quotes/src/DBUtils.h create mode 100644 plugins/Quotes/src/EconomicRateInfo.h create mode 100644 plugins/Quotes/src/ExtraImages.cpp create mode 100644 plugins/Quotes/src/ExtraImages.h create mode 100644 plugins/Quotes/src/Forex.cpp create mode 100644 plugins/Quotes/src/HTMLParserMS.cpp create mode 100644 plugins/Quotes/src/HTMLParserMS.h create mode 100644 plugins/Quotes/src/HTTPSession.cpp create mode 100644 plugins/Quotes/src/HTTPSession.h create mode 100644 plugins/Quotes/src/IHTMLEngine.h create mode 100644 plugins/Quotes/src/IHTMLParser.h create mode 100644 plugins/Quotes/src/IQuotesProvider.h create mode 100644 plugins/Quotes/src/IXMLEngine.h create mode 100644 plugins/Quotes/src/IconLib.cpp create mode 100644 plugins/Quotes/src/IconLib.h create mode 100644 plugins/Quotes/src/ImportExport.cpp create mode 100644 plugins/Quotes/src/ImportExport.h create mode 100644 plugins/Quotes/src/IsWithinAccuracy.h create mode 100644 plugins/Quotes/src/LightMutex.cpp create mode 100644 plugins/Quotes/src/LightMutex.h create mode 100644 plugins/Quotes/src/Locale.cpp create mode 100644 plugins/Quotes/src/Locale.h create mode 100644 plugins/Quotes/src/Log.cpp create mode 100644 plugins/Quotes/src/Log.h create mode 100644 plugins/Quotes/src/ModuleInfo.cpp create mode 100644 plugins/Quotes/src/ModuleInfo.h create mode 100644 plugins/Quotes/src/OptionDukasCopy.cpp create mode 100644 plugins/Quotes/src/OptionDukasCopy.h create mode 100644 plugins/Quotes/src/QuoteChart.cpp create mode 100644 plugins/Quotes/src/QuoteChart.h create mode 100644 plugins/Quotes/src/QuoteInfoDlg.cpp create mode 100644 plugins/Quotes/src/QuoteInfoDlg.h create mode 100644 plugins/Quotes/src/QuotesProviderBase.cpp create mode 100644 plugins/Quotes/src/QuotesProviderBase.h create mode 100644 plugins/Quotes/src/QuotesProviderDukasCopy.cpp create mode 100644 plugins/Quotes/src/QuotesProviderDukasCopy.h create mode 100644 plugins/Quotes/src/QuotesProviderFinance.cpp create mode 100644 plugins/Quotes/src/QuotesProviderFinance.h create mode 100644 plugins/Quotes/src/QuotesProviderGoogle.cpp create mode 100644 plugins/Quotes/src/QuotesProviderGoogle.h create mode 100644 plugins/Quotes/src/QuotesProviderGoogleFinance.cpp create mode 100644 plugins/Quotes/src/QuotesProviderGoogleFinance.h create mode 100644 plugins/Quotes/src/QuotesProviderVisitor.h create mode 100644 plugins/Quotes/src/QuotesProviderVisitorDbSettings.cpp create mode 100644 plugins/Quotes/src/QuotesProviderVisitorDbSettings.h create mode 100644 plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp create mode 100644 plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.h create mode 100644 plugins/Quotes/src/QuotesProviderVisitorFormater.cpp create mode 100644 plugins/Quotes/src/QuotesProviderVisitorFormater.h create mode 100644 plugins/Quotes/src/QuotesProviderVisitorTendency.cpp create mode 100644 plugins/Quotes/src/QuotesProviderVisitorTendency.h create mode 100644 plugins/Quotes/src/QuotesProviderYahoo.cpp create mode 100644 plugins/Quotes/src/QuotesProviderYahoo.h create mode 100644 plugins/Quotes/src/QuotesProviders.cpp create mode 100644 plugins/Quotes/src/QuotesProviders.h create mode 100644 plugins/Quotes/src/SettingsDlg.cpp create mode 100644 plugins/Quotes/src/SettingsDlg.h create mode 100644 plugins/Quotes/src/WinCtrlHelper.cpp create mode 100644 plugins/Quotes/src/WinCtrlHelper.h create mode 100644 plugins/Quotes/src/WorkingThread.cpp create mode 100644 plugins/Quotes/src/WorkingThread.h create mode 100644 plugins/Quotes/src/XMLEngineMI.cpp create mode 100644 plugins/Quotes/src/XMLEngineMI.h create mode 100644 plugins/Quotes/src/resource.h create mode 100644 plugins/Quotes/src/stdafx.cpp create mode 100644 plugins/Quotes/src/stdafx.h create mode 100644 plugins/Quotes/src/targetver.h create mode 100644 plugins/Quotes/src/version.h (limited to 'plugins/Quotes/src') diff --git a/plugins/Quotes/src/Base64.cpp b/plugins/Quotes/src/Base64.cpp new file mode 100644 index 0000000000..1854fb42fd --- /dev/null +++ b/plugins/Quotes/src/Base64.cpp @@ -0,0 +1,43 @@ +#include "StdAfx.h" +#include "Base64.h" + +bool base64::encode(const BYTE* in, size_t inlen,std::vector& 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& 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/plugins/Quotes/src/Base64.h b/plugins/Quotes/src/Base64.h new file mode 100644 index 0000000000..3f911bfeb8 --- /dev/null +++ b/plugins/Quotes/src/Base64.h @@ -0,0 +1,12 @@ +#ifndef __FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__ +#define __FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__ + +#pragma once + +namespace base64 +{ + bool encode(const BYTE* in, size_t inlen,std::vector& out); + bool decode(const char* in, size_t inlen,std::vector& out); +} + +#endif //__FBB8ABCA_315E_4ace_B2EB_51E03AD6F8D1_Base64_h__ diff --git a/plugins/Quotes/src/Chart.h b/plugins/Quotes/src/Chart.h new file mode 100644 index 0000000000..62a658d818 --- /dev/null +++ b/plugins/Quotes/src/Chart.h @@ -0,0 +1,280 @@ +#ifndef __FAE7F26E_61ED_4951_BE87_5E022CDF21DF_Chart_h__ +#define __FAE7F26E_61ED_4951_BE87_5E022CDF21DF_Chart_h__ + +#pragma once + +namespace detail +{ + template struct CConverter + { + static double Convert(const T& v) + { + return boost::numeric_cast(v); + } + + static tstring ToString(const T& v) + { + return boost::lexical_cast(v); + } + }; + + template<> struct CConverter + { + 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 TYConverter = detail::CConverter > +class CChart +{ +private: + typedef std::pair TValue; + typedef std::vector 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(::GetStockObject(DEFAULT_GUI_FONT)); + HFONT hOldFont = static_cast(::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(::SelectObject(hdc,hPen)); + HFONT hFont = static_cast(::GetStockObject(DEFAULT_GUI_FONT)); + HFONT hOldFont = static_cast(::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(::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((rc.right-rc.left)*(k/dx)); + k = TYConverter::Convert(v.second-m_MinY); + int y = rc.bottom-boost::numeric_cast((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/plugins/Quotes/src/ComHelper.cpp b/plugins/Quotes/src/ComHelper.cpp new file mode 100644 index 0000000000..e15d05d739 --- /dev/null +++ b/plugins/Quotes/src/ComHelper.cpp @@ -0,0 +1,39 @@ +#include "StdAfx.h" +#include "ComHelper.h" +#include "Log.h" +#include "WinCtrlHelper.h" + +tstring ComException2Msg(_com_error& e,const tstring& rsAdditionalInfo) +{ + HRESULT hError = e.Error(); + tostringstream o; + if(false == rsAdditionalInfo.empty()) + { + o << rsAdditionalInfo << "\n"; + } + + o << e.ErrorMessage() << _T(" (") << std::hex << hError << _T(")"); + + IErrorInfo* p = e.ErrorInfo(); + CComPtr 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/plugins/Quotes/src/ComHelper.h b/plugins/Quotes/src/ComHelper.h new file mode 100644 index 0000000000..0b4140d80d --- /dev/null +++ b/plugins/Quotes/src/ComHelper.h @@ -0,0 +1,9 @@ +#ifndef __37ae28ab_c414_4aba_bbef_d23dd68643a5_ComHelper_h__ +#define __37ae28ab_c414_4aba_bbef_d23dd68643a5_ComHelper_h__ + +#include + +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/plugins/Quotes/src/CommonOptionDlg.cpp b/plugins/Quotes/src/CommonOptionDlg.cpp new file mode 100644 index 0000000000..0b460665c5 --- /dev/null +++ b/plugins/Quotes/src/CommonOptionDlg.cpp @@ -0,0 +1,272 @@ +#include "StdAfx.h" +#include "CommonOptionDlg.h" +#include "QuotesProviderBase.h" +#include "resource.h" +#include "EconomicRateInfo.h" +#include "DBUtils.h" +#include "QuotesProviderVisitorDbSettings.h" +#include "WinCtrlHelper.h" +#include "SettingsDlg.h" + +namespace +{ + typedef boost::shared_ptr TAdvSettingsPtr; + typedef std::map 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(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(::SendMessage(reinterpret_cast(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(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(lp); + switch(pNMHDR->code) + { + case PSN_KILLACTIVE: + { + BOOL bOk = FALSE; + UINT nRefreshRate = ::GetDlgItemInt(hWnd,IDC_EDIT_REFRESH_RATE,&bOk,FALSE); + ERefreshRateType nType = static_cast(::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(::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/plugins/Quotes/src/CommonOptionDlg.h b/plugins/Quotes/src/CommonOptionDlg.h new file mode 100644 index 0000000000..b9f696362a --- /dev/null +++ b/plugins/Quotes/src/CommonOptionDlg.h @@ -0,0 +1,17 @@ +#ifndef __c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__ +#define __c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__ + +class CQuotesProviderBase; + +struct CCommonDlgProcData +{ + CCommonDlgProcData(const CQuotesProviderBase* pQuotesProvider) + : m_pQuotesProvider(pQuotesProvider),m_bFireSetingsChangedEvent(false){} + + const CQuotesProviderBase* m_pQuotesProvider; + bool m_bFireSetingsChangedEvent; +}; + +void CommonOptionDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp,CCommonDlgProcData& rData); + +#endif//__c85fe710_f71b_4a58_9d44_3e39f6209c5f_CommonOptionDlg_h__ diff --git a/plugins/Quotes/src/CreateFilePath.cpp b/plugins/Quotes/src/CreateFilePath.cpp new file mode 100644 index 0000000000..23c0c345b0 --- /dev/null +++ b/plugins/Quotes/src/CreateFilePath.cpp @@ -0,0 +1,45 @@ +#include "StdAfx.h" +#include "CreateFilePath.h" + +#include +#include "ModuleInfo.h" + +namespace +{ + TCHAR replace_invalid_symbol(TCHAR chr) + { + TCHAR InvaliSymbols[] = {_T('\\'),_T('/'),_T(':'),_T('*'),_T('?'),_T('"'),_T('<'),_T('>'),_T('|')}; + for(int i = 0; i < sizeof(InvaliSymbols)/sizeof(InvaliSymbols[0]);++i) + { + if(chr == InvaliSymbols[i]) + { + return _T('_'); + } + } + + return chr; + } + + void prepare_name(tstring& rsName) + { + std::transform(rsName.begin(),rsName.end(),rsName.begin(),boost::bind(replace_invalid_symbol,_1)); + } +} + +tstring CreateFilePath(const tstring& rsName) +{ + TCHAR szPath[_MAX_PATH]; + ::GetModuleFileName(g_hInstance,szPath,_MAX_PATH); + + TCHAR* p = _tcsrchr(szPath,_T('\\')); + if(p) + { + *p = 0; + } + + tstring s(rsName); + prepare_name(s); + tostringstream o; + o << szPath << _T("\\Quotes\\") << s; + return o.str(); +} \ No newline at end of file diff --git a/plugins/Quotes/src/CreateFilePath.h b/plugins/Quotes/src/CreateFilePath.h new file mode 100644 index 0000000000..f097e59a52 --- /dev/null +++ b/plugins/Quotes/src/CreateFilePath.h @@ -0,0 +1,8 @@ +#ifndef _aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__ +#define _aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__ + +#include + +tstring CreateFilePath(const tstring& rsName); + +#endif //_aaf3bee6_cee7_4023_8848_5911ad7a9660_CreateFilePath_h__ diff --git a/plugins/Quotes/src/CurrencyConverter.cpp b/plugins/Quotes/src/CurrencyConverter.cpp new file mode 100644 index 0000000000..7124677567 --- /dev/null +++ b/plugins/Quotes/src/CurrencyConverter.cpp @@ -0,0 +1,309 @@ +#include "StdAfx.h" +#include "CurrencyConverter.h" +#include "ModuleInfo.h" +#include "resource.h" + +#include "QuotesProviderGoogle.h" +#include "QuotesProviders.h" +#include "WinCtrlHelper.h" +#include "EconomicRateInfo.h" +#include "Locale.h" +#include "DBUtils.h" +#include "IconLib.h" + +#define WINDOW_PREFIX "CurrenyConverter_" + +#define DB_STR_CC_QUOTE_FROM_ID "CurrencyConverter_FromID" +#define DB_STR_CC_QUOTE_TO_ID "CurrencyConverter_ToID" +#define DB_STR_CC_AMOUNT "CurrencyConverter_Amount" + +namespace +{ + CQuotesProviderGoogle* get_google_provider() + { + CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr(); + const CQuotesProviders::TQuotesProviders& rapQuotesProviders = pProviders->GetProviders(); + for(CQuotesProviders::TQuotesProviders::const_iterator i = rapQuotesProviders.begin();i != rapQuotesProviders.end();++i) + { + const CQuotesProviders::TQuotesProviderPtr& pProvider = *i; + CQuotesProviderGoogle* pGoogle = dynamic_cast(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(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0)); + int nTo = static_cast(::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(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0)); + int nTo = static_cast(::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(Quotes_LoadIconEx(ICON_STR_CURRENCY_CONVERTER))); + ::SendMessage(hDlg,WM_SETICON,TRUE,reinterpret_cast(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(pszName)); + LRESULT nTo = ::SendMessage(hcbxTo,CB_ADDSTRING,0,reinterpret_cast(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(" ") << pi.m_sName << _T(""); + + ::SetDlgItemText(hDlg,IDC_SYSLINK_PROVIDER,o.str().c_str()); + + ::SendMessage(::GetDlgItem(hDlg,IDC_BUTTON_SWAP),BM_SETIMAGE,IMAGE_ICON, + reinterpret_cast(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(::SendMessage(::GetDlgItem(hDlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0)); + size_t nTo = static_cast(::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(lp); + switch(pNMHDR->code) + { + case NM_CLICK: + if(IDC_SYSLINK_PROVIDER == wp) + { + PNMLINK pNMLink = reinterpret_cast(pNMHDR); + ::ShellExecute(hDlg,_T("open"),pNMLink->item.szUrl,NULL,NULL,SW_SHOWNORMAL); + } + break; + } + } + break; + } + return (FALSE); + } +} + +INT_PTR QuotesMenu_CurrencyConverter(WPARAM wp,LPARAM lp) +{ + HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX,true); + HWND hWnd = WindowList_Find(hWL,NULL); + if(NULL != hWnd) + { + SetForegroundWindow(hWnd); + SetFocus(hWnd); + } + else + { + CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_CURRENCY_CONVERTER), NULL, CurrencyConverterDlgProc, 0); + } + + return 0; +} diff --git a/plugins/Quotes/src/CurrencyConverter.h b/plugins/Quotes/src/CurrencyConverter.h new file mode 100644 index 0000000000..9af7c6bca1 --- /dev/null +++ b/plugins/Quotes/src/CurrencyConverter.h @@ -0,0 +1,6 @@ +#ifndef __4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__ +#define __4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__ + +INT_PTR QuotesMenu_CurrencyConverter(WPARAM wp,LPARAM lp); + +#endif //__4FB6320B_2D02_408b_BAF5_426C185AAA11_CurrencyConverter_h__ diff --git a/plugins/Quotes/src/DBUtils.cpp b/plugins/Quotes/src/DBUtils.cpp new file mode 100644 index 0000000000..11c0fb3d0d --- /dev/null +++ b/plugins/Quotes/src/DBUtils.cpp @@ -0,0 +1,70 @@ +#include "StdAfx.h" +#include "DBUtils.h" + +std::string Quotes_DBGetStringA(HANDLE hContact,const char* szModule,const char* szSetting,const char* pszDefValue /*= NULL*/) +{ + std::string sResult; + char* pszSymbol = DBGetString(hContact,szModule,szSetting); + if(NULL != pszSymbol) + { + sResult = pszSymbol; + mir_free(pszSymbol); + } + else if(NULL != pszDefValue) + { + sResult = pszDefValue; + } + + return sResult; +} + +std::wstring Quotes_DBGetStringW(HANDLE hContact,const char* szModule,const char* szSetting,const wchar_t* pszDefValue/* = NULL*/) +{ + std::wstring sResult; + wchar_t* pszSymbol = DBGetStringW(hContact,szModule,szSetting); + if(NULL != pszSymbol) + { + sResult = pszSymbol; + mir_free(pszSymbol); + } + else if(NULL != pszDefValue) + { + sResult = pszDefValue; + } + + return sResult; +} + +bool Quotes_DBWriteDouble(HANDLE hContact,const char* szModule,const char* szSetting,double dValue) +{ + DBCONTACTWRITESETTING cws = {0}; + + cws.szModule = szModule; + cws.szSetting = szSetting; + cws.value.type = DBVT_BLOB; + cws.value.cpbVal = sizeof(dValue); + cws.value.pbVal = reinterpret_cast(&dValue); + return 0 == CallService(MS_DB_CONTACT_WRITESETTING,reinterpret_cast(hContact),reinterpret_cast(&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(dbv.pbVal); + } + + DBFreeVariant(&dbv); + return bResult; +} + diff --git a/plugins/Quotes/src/DBUtils.h b/plugins/Quotes/src/DBUtils.h new file mode 100644 index 0000000000..27e3de5038 --- /dev/null +++ b/plugins/Quotes/src/DBUtils.h @@ -0,0 +1,13 @@ +#ifndef __54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__ +#define __54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__ + +std::string Quotes_DBGetStringA(HANDLE hContact,const char* szModule,const char* szSetting,const char* pszDefValue = NULL); +std::wstring Quotes_DBGetStringW(HANDLE hContact,const char* szModule,const char* szSetting,const wchar_t* pszDefValue = NULL); + + +#define Quotes_DBGetStringT Quotes_DBGetStringW + +bool Quotes_DBWriteDouble(HANDLE hContact,const char* szModule,const char* szSetting,double dValue); +bool Quotes_DBReadDouble(HANDLE hContact,const char* szModule,const char* szSetting,double& rdValue); + +#endif //__54294385_3fdd_4f0c_98c3_c583a96e7fb4_DBUtils_h__ diff --git a/plugins/Quotes/src/EconomicRateInfo.h b/plugins/Quotes/src/EconomicRateInfo.h new file mode 100644 index 0000000000..73e269619c --- /dev/null +++ b/plugins/Quotes/src/EconomicRateInfo.h @@ -0,0 +1,59 @@ +#ifndef __87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__ +#define __87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__ + +#define QUOTES_PROTOCOL_NAME "Quotes"// protocol name + +#define QUOTES_MODULE_NAME QUOTES_PROTOCOL_NAME // db settings module path + +enum ERefreshRateType +{ + RRT_SECONDS = 0, + RRT_MINUTES = 1, + RRT_HOURS = 2 +}; + +#define DB_STR_ENABLE_LOG "EnableLog" +#define DB_STR_QUOTE_PROVIDER "QuoteProvider" +#define DB_STR_QUOTE_ID "QuoteID" +#define DB_STR_QUOTE_SYMBOL "QuoteSymbol" +#define DB_STR_QUOTE_DESCRIPTION "QuoteDescription" +#define DB_STR_QUOTE_PREV_VALUE "PreviousQuoteValue" +#define DB_STR_QUOTE_CURR_VALUE "CurrentQuoteValue" +#define DB_STR_QUOTE_FETCH_TIME "FetchTime" + + +enum ELogMode +{ + lmDisabled = 0x0000, + lmInternalHistory = 0x0001, + lmExternalFile = 0x0002, + lmPopup = 0x0004, +}; + +#define DB_STR_CONTACT_SPEC_SETTINGS "ContactSpecSettings" +#define DB_STR_QUOTE_LOG "Log" +#define DB_STR_QUOTE_LOG_FILE "LogFile" +#define DB_STR_QUOTE_FORMAT_LOG_FILE "LogFileFormat" +#define DB_STR_QUOTE_FORMAT_HISTORY "HistoryFormat" +#define DB_STR_QUOTE_LOG_FILE_CONDITION "AddToLogOnlyIfValueIsChanged" +#define DB_STR_QUOTE_HISTORY_CONDITION "AddToHistoryOnlyIfValueIsChanged" +#define DB_STR_QUOTE_EXTRA_IMAGE_SLOT "ExtraImageSlot" +#define DB_STR_QUOTE_FORMAT_POPUP "PopupFormat" +#define DB_STR_QUOTE_POPUP_CONDITION "ShowPopupOnlyIfValueIsChanged" + +#define DB_STR_QUOTE_POPUP_COLOUR_MODE "PopupColourMode" +#define DB_STR_QUOTE_POPUP_COLOUR_BK "PopupColourBk" +#define DB_STR_QUOTE_POPUP_COLOUR_TEXT "PopupColourText" +#define DB_STR_QUOTE_POPUP_DELAY_MODE "PopupDelayMode" +#define DB_STR_QUOTE_POPUP_DELAY_TIMEOUT "PopupDelayTimeout" +#define DB_STR_QUOTE_POPUP_HISTORY_FLAG "PopupHistoryFlag" + + +// #define DB_STR_NICK "Nick" +#define DB_STR_STATUS "Status" + +#define LIST_MODULE_NAME "CList" +#define CONTACT_LIST_NAME "MyHandle" +#define STATUS_MSG_NAME "StatusMsg" + +#endif //__87d726e0_26c6_485d_8016_1fba819b037d_EconomicRateInfo__ diff --git a/plugins/Quotes/src/ExtraImages.cpp b/plugins/Quotes/src/ExtraImages.cpp new file mode 100644 index 0000000000..a89032e53c --- /dev/null +++ b/plugins/Quotes/src/ExtraImages.cpp @@ -0,0 +1,67 @@ +#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" +#include "resource.h" + +CExtraImages::CExtraImages() : + m_hExtraIcons(ExtraIcon_Register(ICON_STR_QUOTE,QUOTES_PROTOCOL_NAME,Quotes_MakeIconName(ICON_STR_MAIN).c_str())), + m_bExtraImagesInit(false) +{ + m_ahExtraImages[eiUp] = INVALID_HANDLE_VALUE; + m_ahExtraImages[eiDown] = INVALID_HANDLE_VALUE; + m_ahExtraImages[eiNotChanged] = INVALID_HANDLE_VALUE; +} + +CExtraImages::~CExtraImages() +{ +} + +CExtraImages& CExtraImages::GetInstance() +{ + static CExtraImages s_ei; + return s_ei; +} + +void CExtraImages::RebuildExtraImages() +{ +} + +bool CExtraImages::SetContactExtraImage(HANDLE hContact,EImageIndex nIndex)const +{ + if (!m_hExtraIcons) + return false; + + HANDLE hIcolib; + switch(nIndex) { + case eiUp: + hIcolib = Quotes_GetIconHandle(IDI_ICON_UP); + break; + case eiDown: + hIcolib = Quotes_GetIconHandle(IDI_ICON_DOWN); + break; + case eiNotChanged: + hIcolib = Quotes_GetIconHandle(IDI_ICON_NOTCHANGED); + break; + default: + hIcolib = NULL; + } + return ExtraIcon_SetIcon(m_hExtraIcons, hContact, hIcolib) == 0; +} + +int QuotesEventFunc_onExtraImageApply(WPARAM wp,LPARAM lp) +{ + HANDLE hContact = reinterpret_cast(wp); + + const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr(); + CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact); + if(pProvider) + pProvider->SetContactExtraIcon(hContact); + + return 0; +} diff --git a/plugins/Quotes/src/ExtraImages.h b/plugins/Quotes/src/ExtraImages.h new file mode 100644 index 0000000000..cd09600217 --- /dev/null +++ b/plugins/Quotes/src/ExtraImages.h @@ -0,0 +1,37 @@ +#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 QuotesEventFunc_onExtraImageApply(WPARAM wp,LPARAM lp); + +#endif //__9d0dac0c_12e4_46ce_809a_db6dc7d6f269_ExtraImages_h__ diff --git a/plugins/Quotes/src/Forex.cpp b/plugins/Quotes/src/Forex.cpp new file mode 100644 index 0000000000..6aa7d90dcf --- /dev/null +++ b/plugins/Quotes/src/Forex.cpp @@ -0,0 +1,469 @@ +// Forex.cpp : Defines the exported functions for the DLL application. +// + +#include "stdafx.h" + +#pragma warning(disable:4996) +#include +#include +#pragma warning(default:4996) +#include "WorkingThread.h" +#include +#include "resource.h" +#include "IconLib.h" +#include +#include +#include "QuoteInfoDlg.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "IQuotesProvider.h" +#include "EconomicRateInfo.h" +#include "DBUtils.h" +#include "ExtraImages.h" +#include "HTTPSession.h" +#include "CurrencyConverter.h" +#ifdef CHART_IMPLEMENT +#include "QuoteChart.h" +#endif +#include "WinCtrlHelper.h" +#include "ImportExport.h" +#include "m_Quotes.h" +#include "version.h" + +int hLangpack; +HINSTANCE g_hInstance = NULL; +HANDLE g_hEventWorkThreadStop; +int g_nStatus = ID_STATUS_OFFLINE; +HGENMENU g_hMenuEditSettings = NULL; +HGENMENU g_hMenuOpenLogFile = NULL; +#ifdef CHART_IMPLEMENT +HGENMENU g_hMenuChart = NULL; +#endif +HGENMENU g_hMenuRefresh = NULL; + +namespace +{ + typedef std::vector THandles; + THandles g_ahEvents; + THandles g_ahServices; + THandles g_ahThreads; + std::vector g_ahMenus; + + PLUGININFOEX Global_pluginInfo = + { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {E882056D-0D1D-4131-9A98-404CBAEA6A9C} + {0xe882056d, 0xd1d, 0x4131, { 0x9a, 0x98, 0x40, 0x4c, 0xba, 0xea, 0x6a, 0x9c } } + }; + + INT_PTR QuotesMenu_RefreshAll(WPARAM wp,LPARAM lp) + { + const CQuotesProviders::TQuotesProviders& apProviders = CModuleInfo::GetQuoteProvidersPtr()->GetProviders(); + std::for_each(apProviders.begin(),apProviders.end(),boost::bind(&IQuotesProvider::RefreshAll,_1)); + return 0; + } + + void InitMenu() + { +// USES_CONVERSION; + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(CLISTMENUITEM); + //mi.ptszPopupName = _T("Quotes"); + mi.ptszName = _T("Quotes"); + mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTPOPUP; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + HGENMENU hMenuRoot = Menu_AddMainMenuItem(&mi); + g_ahMenus.push_back(hMenuRoot); + + mi.ptszName = _T("Refresh All Quotes\\Rates"); + mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + //mi.position = 0x0FFFFFFF; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + mi.pszService = "Quotes/RefreshAll"; + mi.hParentMenu = hMenuRoot; + HGENMENU hMenu = Menu_AddMainMenuItem(&mi); + g_ahMenus.push_back(hMenu); + HANDLE h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshAll); + g_ahServices.push_back(h); + + mi.ptszName = _T("Currency Converter..."); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + //mi.position = 0x0FFFFFFF; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_CURRENCY_CONVERTER); + mi.pszService = "Quotes/CurrencyConverter"; + hMenu = Menu_AddMainMenuItem(&mi); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_CurrencyConverter); + g_ahServices.push_back(h); + +#ifdef TEST_IMPORT_EXPORT + mi.ptszName = _T("Export All Quotes"); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_EXPORT); + mi.pszService = "Quotes/ExportAll"; + hMenu = Menu_AddMainMenuItem(&mi); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_ExportAll); + g_ahServices.push_back(h); + + mi.ptszName =_T("Import All Quotes"); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_IMPORT); + mi.pszService = "Quotes/ImportAll"; + hMenu = Menu_AddMainMenuItem(&mi); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_ImportAll); + g_ahServices.push_back(h); +#endif + + bool bSubGroups = 1 == ServiceExists(MS_CLIST_MENUBUILDSUBGROUP); + + h = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,Quotes_PrebuildContactMenu); + g_ahEvents.push_back(h); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.pszContactOwner = QUOTES_PROTOCOL_NAME; + hMenuRoot = NULL; + if(bSubGroups) + { + mi.pszPopupName=(char *)-1; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + mi.flags = CMIF_ICONFROMICOLIB|CMIF_TCHAR|CMIF_ROOTPOPUP; + tstring sProtocolName = quotes_a2t(QUOTES_PROTOCOL_NAME); + mi.ptszName = const_cast(sProtocolName.c_str());//A2T(QUOTES_PROTOCOL_NAME); + mi.position = 0; + + hMenuRoot = Menu_AddContactMenuItem(&mi); + } + + mi.flags = CMIF_TCHAR; + if(bSubGroups) + { + mi.flags |= CMIF_CHILDPOPUP; + mi.pszPopupName = (char*)hMenuRoot; + } + + mi.ptszName = _T("Refresh"); + mi.popupPosition = 0; + mi.flags |= CMIF_ICONFROMICOLIB; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_REFRESH); + mi.pszService = "Quotes/RefreshContact"; + hMenu = Menu_AddContactMenuItem(&mi); + g_hMenuRefresh = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshContact); + g_ahServices.push_back(h); + + mi.ptszName = _T("Open Log File..."); + mi.popupPosition = 1; + mi.icolibItem = NULL; + mi.pszService = "Quotes/OpenLogFile"; + hMenu = Menu_AddContactMenuItem(&mi); + g_hMenuOpenLogFile = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_OpenLogFile); + g_ahServices.push_back(h); + +#ifdef CHART_IMPLEMENT + mi.ptszName = _T("Chart..."); + mi.popupPosition = 2; + mi.icolibItem = NULL; + mi.pszService = "Quotes/Chart"; + hMenu = Menu_AddContactMenuItem(&mi); + g_hMenuChart = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_Chart); + g_ahServices.push_back(h); +#endif + + mi.ptszName = _T("Edit Settings..."); +#ifdef CHART_IMPLEMENT + mi.popupPosition = 3; +#else + mi.popupPosition = 2; +#endif + mi.icolibItem = NULL; + mi.pszService = "Quotes/EditSettings"; + hMenu = Menu_AddContactMenuItem(&mi); + g_hMenuEditSettings = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_EditSettings); + g_ahServices.push_back(h); + } + + + int QuotesEventFunc_OnModulesLoaded(WPARAM, LPARAM) + { + CHTTPSession::Init(); + + HANDLE h = HookEvent(ME_CLIST_EXTRA_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(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(mir_forkthread(WorkingThread,pProvider.get())); + g_ahThreads.push_back(hThread); + } + } + + ProtoBroadcastAck(QUOTES_PROTOCOL_NAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,reinterpret_cast(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(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(::CopyIcon(Quotes_LoadIconEx(ICON_STR_MAIN))); + } + + return 0; + } + + int QuotesEventFunc_OptInitialise(WPARAM wp,LPARAM/* lp*/) + { + const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr(); + const CQuotesProviders::TQuotesProviders& rapProviders = pProviders->GetProviders(); + + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = g_hInstance; + odp.ptszTitle = _T(QUOTES_PROTOCOL_NAME); + odp.ptszGroup = LPGENT("Network"); + odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN); + odp.flags = ODPF_USERINFOTAB | ODPF_TCHAR; + + std::for_each(rapProviders.begin(),rapProviders.end(),boost::bind(&IQuotesProvider::ShowPropertyPage,_1,wp,boost::ref(odp))); + return 0; + } + + inline int Quotes_DestroyServiceFunction(HANDLE h) + { + return DestroyServiceFunction(h); + } + + inline int Quotes_UnhookEvent(HANDLE h) + { + return UnhookEvent(h); + } + + inline int Quotes_RemoveMenuItem(HGENMENU h) + { + return CallService(MS_CLIST_REMOVECONTACTMENUITEM,reinterpret_cast(h),0); + } + +// PROTO_INTERFACE* protoInit(const char* pszProtoName, const TCHAR* tszUserName) +// { +// CAimProto *ppro = new CAimProto(pszProtoName, tszUserName); +// g_Instances.insert(ppro); +// return ppro; +// } +// +// int protoUninit(PROTO_INTERFACE* ppro) +// { +// g_Instances.remove((CAimProto*)ppro); +// return 0; +// } + +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + g_hInstance = hinstDLL; + return TRUE; +} + +extern "C" +{ + __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) + { + return &Global_pluginInfo; + } + + + #define MIID_QUOTES {0x723243c2, 0x8d4b, 0x4c29, { 0x8a, 0x37, 0xc0, 0x11, 0x48, 0x65, 0xb0, 0x80}} + + __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL,MIID_QUOTES,MIID_LAST}; + + int __declspec(dllexport) Load(void) + { + + mir_getLP(&Global_pluginInfo); +// if ((mirandaVersion >= 0x0800) && (1 == mir_getXI(&xi))) +// { +// CModuleInfo::SetXMLEnginePtr(CModuleInfo::TXMLEnginePtr(new CXMLEngineMI)); +// } + + if(false == CModuleInfo::Verify()) + { + return 1; + } + + Quotes_IconsInit(); + + PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE }; + pd.szName = QUOTES_PROTOCOL_NAME; + pd.type = PROTOTYPE_VIRTUAL; + 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/plugins/Quotes/src/HTMLParserMS.cpp b/plugins/Quotes/src/HTMLParserMS.cpp new file mode 100644 index 0000000000..bfe58b43b1 --- /dev/null +++ b/plugins/Quotes/src/HTMLParserMS.cpp @@ -0,0 +1,313 @@ +#include "StdAfx.h" +#include "HTMLParserMS.h" + +using _com_util::CheckError; + +namespace +{ + class CHTMLNode : public IHTMLNode + { + public: + typedef CComPtr TComPtr; + typedef CComPtr TDocumentPtr; + + protected: + typedef CComPtr 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 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 pTable; + return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTable,reinterpret_cast(&pTable))) && (pTable)); + } + case TableRow: + { + CComPtr pRow; + return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTableRow,reinterpret_cast(&pRow))) && (pRow)); + } + case TableColumn: + { + CComPtr pCol; + return (SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLTableCol,reinterpret_cast(&pCol))) && (pCol)); + } + } + + return false; + } + + virtual tstring GetAttribute(const tstring& rsAttrName)const + { + USES_CONVERSION; + + tstring sAttr; + CComPtr pElement; + if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast(&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 pElement; + if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast(&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(&pColl)); + if(FAILED(hr)) + { + CComPtr pElement; + if(SUCCEEDED(m_pElement->QueryInterface(IID_IHTMLElement,reinterpret_cast(&pElement))) && pElement) + { + CComPtr pDisp; + if(SUCCEEDED(pElement->get_children(&pDisp)) && pDisp) + { + hr = pDisp->QueryInterface(IID_IHTMLElementCollection,reinterpret_cast(&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 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 cs(m_cs); + + OLECHAR* p = T2OLE(const_cast(rsHTML.c_str())); + CComPtr pMC; + _com_util::CheckError(m_pMS->ParseString(p,0,&pMC,m_pMkStart,m_pMkFinish)); + + if(pMC) + { + CComPtr pNewDoc; + + _com_util::CheckError(pMC->QueryInterface(IID_IHTMLDocument, + (LPVOID*)&pNewDoc)); + + if(pNewDoc) + { + CComPtr 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 pDoc; + _com_util::CheckError( + ::CoCreateInstance(CLSID_HTMLDocument, + NULL, + CLSCTX_INPROC_SERVER, + IID_IHTMLDocument2, + reinterpret_cast(&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/plugins/Quotes/src/HTMLParserMS.h b/plugins/Quotes/src/HTMLParserMS.h new file mode 100644 index 0000000000..0773efa42a --- /dev/null +++ b/plugins/Quotes/src/HTMLParserMS.h @@ -0,0 +1,36 @@ +#ifndef __3c99e3f7_ecd9_4d9b_8f86_fe293c5fc8e6_HTMLParserMS_h__ +#define __3c99e3f7_ecd9_4d9b_8f86_fe293c5fc8e6_HTMLParserMS_h__ + +#include "ihtmlparser.h" +#include "LightMutex.h" +#include "IHTMLEngine.h" + +class CHTMLParserMS : public IHTMLParser +{ +public: + CHTMLParserMS(); + ~CHTMLParserMS(); + + virtual THTMLNodePtr ParseString(const tstring& rsHTML); + + static bool IsInstalled(); + +private: + bool m_bCallUninit; + CComPtr m_pDoc; + CComPtr m_pMS; + CComPtr m_pMkStart; + CComPtr 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/plugins/Quotes/src/HTTPSession.cpp b/plugins/Quotes/src/HTTPSession.cpp new file mode 100644 index 0000000000..aa66948ae9 --- /dev/null +++ b/plugins/Quotes/src/HTTPSession.cpp @@ -0,0 +1,262 @@ +#include "StdAfx.h" +#include "HTTPSession.h" +#include "EconomicRateInfo.h" +#include "LightMutex.h" + +class CHTTPSession::CImpl +{ +public: + CImpl() {} + virtual ~CImpl() {} + + virtual bool OpenURL(const tstring& rsURL) = 0; + virtual bool ReadResponce(tstring& rsResponce)const = 0; +}; + +namespace +{ +// class CImplMS : public CHTTPSession::CImpl +// { +// public: +// CImplMS() +// : m_hSession(::InternetOpen(_T("Dioksin"),PRE_CONFIG_INTERNET_ACCESS,NULL,INTERNET_INVALID_PORT_NUMBER,0)), +// m_hRequest(NULL) +// { +// +// } +// +// ~CImplMS() +// { +// if(m_hRequest) +// { +// ::InternetCloseHandle(m_hRequest); +// } +// +// if(m_hSession) +// { +// ::InternetCloseHandle(m_hSession); +// } +// } +// +// virtual bool OpenURL(const tstring& rsURL) +// { +// if(NULL == m_hSession) +// { +// return false; +// } +// +// if(NULL != m_hRequest) +// { +// ::InternetCloseHandle(m_hRequest); +// m_hRequest = NULL; +// } +// +// m_hRequest = ::InternetOpenUrl(m_hSession,rsURL.c_str(),NULL,0,INTERNET_FLAG_RELOAD,0); +// return NULL != m_hRequest; +// } +// +// virtual bool ReadResponce(tstring& rsResponce)const +// { +// if(NULL == m_hRequest) +// { +// return false; +// } +// +// std::string sBuffer; +// bool bResult = true; +// DWORD cbRead = 0; +// char szBuffer[1024]; +// do{ +// if(FALSE == ::InternetReadFile(m_hRequest,szBuffer,1024,&cbRead)) +// { +// bResult = false; +// break; +// } +// if (0 == cbRead) +// { +// break; // Stop. +// } +// else +// { +// sBuffer.insert(sBuffer.size(),szBuffer,cbRead); +// } +// }while(true); +// +// if(true == bResult) +// { +// USES_CONVERSION; +// rsResponce = A2CT(sBuffer.c_str()); +// } +// +// return bResult; +// } +// private: +// HINTERNET m_hSession; +// HINTERNET m_hRequest; +// }; +// + int find_header(const NETLIBHTTPREQUEST* pRequest,const char* hdr) + { + for(int i = 0;i < pRequest->headersCount; ++i) + { + if (0 == _stricmp(pRequest->headers[i].szName,hdr)) + { + return i; + } + } + + return -1; + } + + + class CImplMI : public CHTTPSession::CImpl + { + public: + CImplMI() {} + + static bool Init() + { + assert(NULL == g_hNetLib); + + NETLIBUSER nlu = {0}; + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION|NUF_TCHAR; + nlu.szSettingsModule = QUOTES_PROTOCOL_NAME; + nlu.ptszDescriptiveName = TranslateT("Quotes HTTP connections"); + g_hNetLib = reinterpret_cast(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 guard(m_mx); + pReply = reinterpret_cast(CallService(MS_NETLIB_HTTPTRANSACTION, + reinterpret_cast(g_hNetLib),reinterpret_cast(&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(pReply)); + } + + mir_free(nlhr.headers); + + return bResult; + } + + private: + static HANDLE g_hNetLib; + typedef std::vector 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/plugins/Quotes/src/HTTPSession.h b/plugins/Quotes/src/HTTPSession.h new file mode 100644 index 0000000000..fe93a2dce5 --- /dev/null +++ b/plugins/Quotes/src/HTTPSession.h @@ -0,0 +1,27 @@ +#ifndef __8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__ +#define __8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__ + +#include + +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 TImpl; + +private: + TImpl m_pImpl; +}; + +#endif //__8C9706FF_6B05_4d0d_85B8_5724E5DC0BA4_HTTPSession_h__ diff --git a/plugins/Quotes/src/IHTMLEngine.h b/plugins/Quotes/src/IHTMLEngine.h new file mode 100644 index 0000000000..7df3074d3e --- /dev/null +++ b/plugins/Quotes/src/IHTMLEngine.h @@ -0,0 +1,18 @@ +#ifndef __85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__ +#define __85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__ + +class IHTMLParser; + +class IHTMLEngine +{ +public: + typedef boost::shared_ptr THTMLParserPtr; + +public: + IHTMLEngine(void){} + virtual ~IHTMLEngine() {} + + virtual THTMLParserPtr GetParserPtr()const = 0; +}; + +#endif //__85dbfa97_919b_4776_919c_7410a1c3d787_HTMLEngine_h__ diff --git a/plugins/Quotes/src/IHTMLParser.h b/plugins/Quotes/src/IHTMLParser.h new file mode 100644 index 0000000000..defc6f61cb --- /dev/null +++ b/plugins/Quotes/src/IHTMLParser.h @@ -0,0 +1,41 @@ +#ifndef __98ad6d6d_2a27_43fd_bf3e_c18416a45e54_IHTMLParser_h__ +#define __98ad6d6d_2a27_43fd_bf3e_c18416a45e54_IHTMLParser_h__ + +class IHTMLNode +{ +public: + typedef boost::shared_ptr 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/plugins/Quotes/src/IQuotesProvider.h b/plugins/Quotes/src/IQuotesProvider.h new file mode 100644 index 0000000000..a03a2a9bcd --- /dev/null +++ b/plugins/Quotes/src/IQuotesProvider.h @@ -0,0 +1,41 @@ +#pragma once + +#ifndef __ac71e133_786c_41a7_ab07_625b76ff2a8c_QuotesProvider_h__ +#define __ac71e133_786c_41a7_ab07_625b76ff2a8c_QuotesProvider_h__ + +#include +#include + +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/plugins/Quotes/src/IXMLEngine.h b/plugins/Quotes/src/IXMLEngine.h new file mode 100644 index 0000000000..910c3efea0 --- /dev/null +++ b/plugins/Quotes/src/IXMLEngine.h @@ -0,0 +1,43 @@ +#ifndef __f88e20d7_5e65_40fb_a7b5_7c7af1ee1c78_IXMLEngine_h__ +#define __f88e20d7_5e65_40fb_a7b5_7c7af1ee1c78_IXMLEngine_h__ + +class IXMLNode +{ +public: + typedef boost::shared_ptr 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/plugins/Quotes/src/IconLib.cpp b/plugins/Quotes/src/IconLib.cpp new file mode 100644 index 0000000000..9ac96599a5 --- /dev/null +++ b/plugins/Quotes/src/IconLib.cpp @@ -0,0 +1,94 @@ +#include "StdAfx.h" +#include "IconLib.h" +#include +#include "resource.h" +#include "EconomicRateInfo.h" +// #include +#include +#include +#pragma warning (disable:4996) +#include +#pragma warning (default:4996) +#include "ModuleInfo.h" + +// extern HMODULE g_hInstance; + +namespace +{ + struct CIconList + { + TCHAR* szDescr; + char* szName; + int defIconID; + HANDLE hIconLibItem; + }; + + CIconList iconList[] = + { + { _T("Protocol icon"), ICON_STR_MAIN, IDI_ICON_MAIN }, + { _T("Quote/Rate up"), ICON_STR_QUOTE_UP, IDI_ICON_UP }, + { _T("Quote/Rate down"), ICON_STR_QUOTE_DOWN, IDI_ICON_DOWN }, + { _T("Quote/Rate not changed"), ICON_STR_QUOTE_NOT_CHANGED, IDI_ICON_NOTCHANGED }, + { _T("Quote Section"), ICON_STR_SECTION, IDI_ICON_SECTION }, + { _T("Quote"), ICON_STR_QUOTE, IDI_ICON_QUOTE }, + { _T("Currency Converter"), ICON_STR_CURRENCY_CONVERTER, IDI_ICON_CURRENCY_CONVERTER }, + { _T("Refresh"), ICON_STR_REFRESH, IDI_ICON_REFRESH }, + { _T("Export"), ICON_STR_EXPORT, IDI_ICON_EXPORT }, + { _T("Swap button"), ICON_STR_SWAP, IDI_ICON_SWAP }, + { _T("Import"), ICON_STR_IMPORT, IDI_ICON_IMPORT } + }; +} + +void Quotes_IconsInit() +{ + USES_CONVERSION; + + SKINICONDESC sid = {0}; + TCHAR szFile[MAX_PATH]; + ::GetModuleFileName(g_hInstance, szFile, MAX_PATH); + + sid.cbSize = sizeof(SKINICONDESC); + sid.ptszDefaultFile = szFile; + sid.cx = sid.cy = 16; + sid.flags = SIDF_ALL_TCHAR; + sid.ptszSection = A2T(QUOTES_PROTOCOL_NAME); + + for (int i = 0; i < SIZEOF(iconList); i++) { + std::string sName = Quotes_MakeIconName( iconList[i].szName); + sid.pszName = const_cast(sName.c_str()); + sid.ptszDescription = iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + iconList[i].hIconLibItem = Skin_AddIcon(&sid); + } +} + +std::string Quotes_MakeIconName(const char* name) +{ + assert(name); + //char szSettingName[100]; + //mir_snprintf(szSettingName,SIZEOF(szSettingName),"%s_%s",QUOTES_PROTOCOL_NAME,name); + std::string sName(QUOTES_PROTOCOL_NAME); + sName += "_"; + sName += name; + return sName; +} + +HICON Quotes_LoadIconEx(const char* name,bool bBig /*= false*/) +{ + std::string sIconName = Quotes_MakeIconName(name); + return Skin_GetIcon(sIconName.c_str(), bBig); +} + +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/plugins/Quotes/src/IconLib.h b/plugins/Quotes/src/IconLib.h new file mode 100644 index 0000000000..29b0326622 --- /dev/null +++ b/plugins/Quotes/src/IconLib.h @@ -0,0 +1,21 @@ +#ifndef __8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__ +#define __8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__ + +#define ICON_STR_MAIN "main" +#define ICON_STR_QUOTE_UP "quote_up" +#define ICON_STR_QUOTE_DOWN "quote_down" +#define ICON_STR_QUOTE_NOT_CHANGED "quote_not_changed" +#define ICON_STR_SECTION "quote_section" +#define ICON_STR_QUOTE "quote" +#define ICON_STR_CURRENCY_CONVERTER "currency_converter" +#define ICON_STR_REFRESH "refresh" +#define ICON_STR_IMPORT "import" +#define ICON_STR_EXPORT "export" +#define ICON_STR_SWAP "swap" + +void Quotes_IconsInit(); +HICON Quotes_LoadIconEx(const char* name,bool bBig = false); +HANDLE Quotes_GetIconHandle(int iconId); +std::string Quotes_MakeIconName(const char* name); + +#endif //__8821d334_afac_439e_9a81_76318e1ac4ef_IconLib_h__ diff --git a/plugins/Quotes/src/ImportExport.cpp b/plugins/Quotes/src/ImportExport.cpp new file mode 100644 index 0000000000..80ab41d309 --- /dev/null +++ b/plugins/Quotes/src/ImportExport.cpp @@ -0,0 +1,850 @@ +#include "StdAfx.h" +#include "ImportExport.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#ifdef TEST_IMPORT_EXPORT +#include "m_Quotes.h" +#endif +#include "IXMLEngine.h" +#include "Base64.h" +#include "EconomicRateInfo.h" +#include "IQuotesProvider.h" +#include "QuotesProviderVisitor.h" +#include "QuotesProviderDukasCopy.h" +#include "QuotesProviderGoogle.h" +#include "QuotesProviderGoogleFinance.h" +#include "Locale.h" + +namespace +{ + LPCTSTR g_pszXmlValue = _T("Value"); + LPCTSTR g_pszXmlName = _T("Name"); + LPCTSTR g_pszXmlSetting = _T("Setting"); + LPCTSTR g_pszXmlModule = _T("Module"); + LPCTSTR g_pszXmlContact = _T("Contact"); + LPCTSTR g_pszXmlContacts = _T("Contacts"); + LPCTSTR g_pszXmlType = _T("type"); + LPCTSTR g_pszXmlTypeByte = _T("byte"); + LPCTSTR g_pszXmlTypeWord = _T("word"); + LPCTSTR g_pszXmlTypeDword = _T("dword"); + LPCTSTR g_pszXmlTypeAsciiz = _T("asciiz"); + LPCTSTR g_pszXmlTypeWchar = _T("wchar"); + LPCTSTR g_pszXmlTypeUtf8 = _T("utf8"); + LPCTSTR g_pszXmlTypeBlob = _T("blob"); + + struct CEnumContext + { + CModuleInfo::TXMLEnginePtr m_pXmlEngine; + IXMLNode::TXMLNodePtr m_pNode; + HANDLE m_hContact; + LPCSTR m_pszModule; + }; + + struct mir_safety_dbvar + { + mir_safety_dbvar(DBVARIANT* p) : m_p(p){} + ~mir_safety_dbvar(){DBFreeVariant(m_p);} + DBVARIANT* m_p; + }; + + static int enum_contact_settings(const char* szSetting,LPARAM lp) + { +// USES_CONVERSION; + CEnumContext* ctx = reinterpret_cast(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(ctx->m_hContact), + reinterpret_cast(&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 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 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 buf; + if(true == base64::encode(dbv.pbVal,dbv.cpbVal,buf)) + { + buf.push_back('\0'); + sValue << &*buf.begin(); + } + } + break; + } + +// mir_safe_string 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(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(ctx); + + CallService(MS_DB_CONTACT_ENUMSETTINGS,reinterpret_cast(ctx->m_hContact),reinterpret_cast(&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(&ctx),reinterpret_cast(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(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(wp); + if(hContact) + { + CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact); + if(pProvider) + { + IXMLNode::TXMLNodePtr pNode = export_contact(hContact,pXmlEngine); + if(pNode) + { + pRoot->AddChild(pNode); + } + } + } + else + { + for(hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) + { + CQuotesProviders::TQuotesProviderPtr pProvider = pProviders->GetContactProviderPtr(hContact); + if(pProvider) + { + IXMLNode::TXMLNodePtr pNode = export_contact(hContact,pXmlEngine); + if(pNode) + { + pRoot->AddChild(pNode); + } + } + } + } + + return ((true == pXmlEngine->SaveFile(sFileName,pRoot)) ? 0 : 1); +} + +namespace +{ + bool set_contact_settings(HANDLE hContact,DBCONTACTWRITESETTING& dbs) + { + assert(DBVT_DELETED != dbs.value.type); + return (0 == CallService(MS_DB_CONTACT_WRITESETTING,reinterpret_cast(hContact), + reinterpret_cast(&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 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(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 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(CallService(MS_DB_CONTACT_ADD,0,0)); + cst.m_bNewContact = true; + } + else if(impctx.m_nFlags"ES_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(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/plugins/Quotes/src/ImportExport.h b/plugins/Quotes/src/ImportExport.h new file mode 100644 index 0000000000..da2053e9a3 --- /dev/null +++ b/plugins/Quotes/src/ImportExport.h @@ -0,0 +1,11 @@ +#ifndef __F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__ +#define __F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__ + +INT_PTR Quotes_Export(WPARAM wp,LPARAM lp); +INT_PTR Quotes_Import(WPARAM wp,LPARAM lp); + +#ifdef TEST_IMPORT_EXPORT +INT_PTR QuotesMenu_ImportAll(WPARAM wp,LPARAM lp); +INT_PTR QuotesMenu_ExportAll(WPARAM wp,LPARAM lp); +#endif +#endif //__F86374E6_713C_4600_85FB_903A5CDF7251_IMPORT_EXPORT_H__ diff --git a/plugins/Quotes/src/IsWithinAccuracy.h b/plugins/Quotes/src/IsWithinAccuracy.h new file mode 100644 index 0000000000..5e39281719 --- /dev/null +++ b/plugins/Quotes/src/IsWithinAccuracy.h @@ -0,0 +1,15 @@ +#ifndef __C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__ +#define __C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__ + +inline bool IsWithinAccuracy(double dValue1, double dValue2, double dAccuracy = 1e-4) +{ + double dDifference = dValue1 - dValue2 ; + + if ((-dAccuracy <= dDifference) && (dDifference <= dAccuracy)) + return true ; + else + return false ; +} + + +#endif //__C8C6FB80_D66B_4382_8FAB_E92C83F77BB8_IsWithinAcuracy_h__ diff --git a/plugins/Quotes/src/LightMutex.cpp b/plugins/Quotes/src/LightMutex.cpp new file mode 100644 index 0000000000..8d14e8e7bb --- /dev/null +++ b/plugins/Quotes/src/LightMutex.cpp @@ -0,0 +1,22 @@ +#include "StdAfx.h" +#include "LightMutex.h" + +CLightMutex::CLightMutex() +{ + InitializeCriticalSection(&m_cs); +} + +CLightMutex::~CLightMutex() +{ + ::DeleteCriticalSection(&m_cs); +} + +void CLightMutex::Lock() +{ + ::EnterCriticalSection(&m_cs); +} + +void CLightMutex::Unlock() +{ + ::LeaveCriticalSection(&m_cs); +} diff --git a/plugins/Quotes/src/LightMutex.h b/plugins/Quotes/src/LightMutex.h new file mode 100644 index 0000000000..e8c7363ba1 --- /dev/null +++ b/plugins/Quotes/src/LightMutex.h @@ -0,0 +1,34 @@ +#ifndef __a33da2bb_d4fe4aa7_aaf5_f9f8c3156ce6_LightMutex_h__ +#define __a33da2bb_d4fe4aa7_aaf5_f9f8c3156ce6_LightMutex_h__ + +class CLightMutex +{ +public: + CLightMutex(); + ~CLightMutex(); + + void Lock(); + void Unlock(); + +private: + CRITICAL_SECTION m_cs; +}; + +template class 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/plugins/Quotes/src/Locale.cpp b/plugins/Quotes/src/Locale.cpp new file mode 100644 index 0000000000..c01f67148a --- /dev/null +++ b/plugins/Quotes/src/Locale.cpp @@ -0,0 +1,75 @@ +#include "StdAfx.h" +#include "Locale.h" + +const std::locale GetSystemLocale() +{ + return std::locale(""); +} + +namespace +{ + tstring get_int_registry_value(LPCTSTR pszValueName) + { + tstring sResult; + HKEY hKey = NULL; + LONG lResult = ::RegOpenKeyEx(HKEY_CURRENT_USER, + _T("Control Panel\\International"),0,KEY_QUERY_VALUE,&hKey); + if ((ERROR_SUCCESS == lResult) && (NULL != hKey)) + { + DWORD dwType = 0; + DWORD dwSize = 0; + lResult = ::RegQueryValueEx(hKey,pszValueName,nullptr,&dwType,nullptr,&dwSize); + if ((ERROR_SUCCESS == lResult) && ((REG_SZ == dwType) || (REG_EXPAND_SZ == dwType))) + { + std::vector aBuffer(dwSize); + lResult = ::RegQueryValueEx(hKey,pszValueName,nullptr,nullptr,reinterpret_cast(&*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/plugins/Quotes/src/Locale.h b/plugins/Quotes/src/Locale.h new file mode 100644 index 0000000000..92d3a56ed4 --- /dev/null +++ b/plugins/Quotes/src/Locale.h @@ -0,0 +1,9 @@ +#ifndef __11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_ +#define __11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_ + +// std::string GetLocaleInfoString(LCTYPE LCType,LCID Locale = LOCALE_USER_DEFAULT); +const std::locale GetSystemLocale(); +tstring Quotes_GetDateFormat(bool bShort); +tstring Quotes_GetTimeFormat(bool bShort); + +#endif //__11f7afd0_5a66_4029_8bf3_e3c66346b349_Locale_h_ diff --git a/plugins/Quotes/src/Log.cpp b/plugins/Quotes/src/Log.cpp new file mode 100644 index 0000000000..d692763bad --- /dev/null +++ b/plugins/Quotes/src/Log.cpp @@ -0,0 +1,56 @@ +#include "StdAfx.h" +#include "Log.h" +#include "LightMutex.h" +#include "EconomicRateInfo.h" +#include "CreateFilePath.h" + +namespace +{ + CLightMutex g_Mutex; + + tstring get_log_file_name() + { + return CreateFilePath(_T("Quotes.log")); + } + + bool is_log_enabled() + { +#ifdef _DEBUG + return true; +#else + return (1 == DBGetContactSettingByte(NULL,QUOTES_PROTOCOL_NAME,DB_STR_ENABLE_LOG,false)); +#endif + } + + void do_log(const tstring& rsFileName,ESeverity nSeverity,const tstring& rsMsg) + { + CGuard 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/plugins/Quotes/src/Log.h b/plugins/Quotes/src/Log.h new file mode 100644 index 0000000000..274fcfec06 --- /dev/null +++ b/plugins/Quotes/src/Log.h @@ -0,0 +1,13 @@ +#ifndef __653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__ +#define __653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__ + +enum ESeverity +{ + Info, + Warning, + Error +}; + +void LogIt(ESeverity nSeverity,const tstring& rsMsg); + +#endif //__653719be_16d6_4058_8555_8aa7d5404214_OutputDlg_h__ diff --git a/plugins/Quotes/src/ModuleInfo.cpp b/plugins/Quotes/src/ModuleInfo.cpp new file mode 100644 index 0000000000..4caec96368 --- /dev/null +++ b/plugins/Quotes/src/ModuleInfo.cpp @@ -0,0 +1,135 @@ +#include "StdAfx.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "HTMLParserMS.h" +#include "LightMutex.h" +#include "WinCtrlHelper.h" +#include "EconomicRateInfo.h" +#include "XMLEngineMI.h" + +namespace +{ + CModuleInfo::TXMLEnginePtr g_pXMLEngine; + CModuleInfo::THTMLEnginePtr g_pHTMLEngine; + CLightMutex g_lmParsers; +} + +CModuleInfo::CModuleInfo() + : m_bExtendedStatusInfo(1 == DBGetContactSettingByte(NULL,QUOTES_MODULE_NAME,"ExtendedStatus",false)) +{ +} + +CModuleInfo::~CModuleInfo() +{ +} + +CModuleInfo& CModuleInfo::GetInstance() +{ + static CModuleInfo mi; + return mi; +} + +HANDLE CModuleInfo::GetWindowList(const std::string& rsKey,bool bAllocateIfNonExist /*= true*/) +{ + HANDLE hResult = NULL; + THandles::const_iterator i = m_ahWindowLists.find(rsKey); + if(i != m_ahWindowLists.end()) + { + hResult = i->second; + } + else if(bAllocateIfNonExist) + { + hResult = reinterpret_cast(CallService(MS_UTILS_ALLOCWINDOWLIST,0,0)); + if(hResult) + { + m_ahWindowLists.insert(std::make_pair(rsKey,hResult)); + } + } + + return hResult; +} + +void CModuleInfo::OnMirandaShutdown() +{ + BOOST_FOREACH(THandles::value_type p,m_ahWindowLists) + { + WindowList_Broadcast(p.second,WM_CLOSE,0,0); + } +} + +CModuleInfo::TQuotesProvidersPtr CModuleInfo::GetQuoteProvidersPtr() +{ + static TQuotesProvidersPtr pProviders(new CQuotesProviders); + return pProviders; +} + +CModuleInfo::TXMLEnginePtr CModuleInfo::GetXMLEnginePtr() +{ + if (!g_pXMLEngine) + { + CGuard 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 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/plugins/Quotes/src/ModuleInfo.h b/plugins/Quotes/src/ModuleInfo.h new file mode 100644 index 0000000000..2882dfae6d --- /dev/null +++ b/plugins/Quotes/src/ModuleInfo.h @@ -0,0 +1,43 @@ +#ifndef __d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__ +#define __d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__ + +class CQuotesProviders; +class IXMLEngine; +class IHTMLEngine; +// class IHTMLParser; + +class CModuleInfo +{ +public: + typedef boost::shared_ptr TQuotesProvidersPtr; + typedef boost::shared_ptr TXMLEnginePtr; + typedef boost::shared_ptr THTMLEnginePtr; + +private: + CModuleInfo(); + ~CModuleInfo(void); + +public: + static CModuleInfo& GetInstance(); + + void OnMirandaShutdown(); + HANDLE GetWindowList(const std::string& rsKey,bool bAllocateIfNonExist = true); + bool GetExtendedStatusFlag()const; + + static bool Verify(); + + static TQuotesProvidersPtr GetQuoteProvidersPtr(); + + static TXMLEnginePtr GetXMLEnginePtr(); +// static void SetXMLEnginePtr(TXMLEnginePtr pEngine); + + static THTMLEnginePtr GetHTMLEngine(); + static void SetHTMLEngine(THTMLEnginePtr pEngine); + +private: + typedef std::map THandles; + THandles m_ahWindowLists; + bool m_bExtendedStatusInfo; +}; + +#endif //__d0f22b66_3135_4bbe_bee5_a31ea631ce58_ModuleInfo__ diff --git a/plugins/Quotes/src/OptionDukasCopy.cpp b/plugins/Quotes/src/OptionDukasCopy.cpp new file mode 100644 index 0000000000..6fcc542b09 --- /dev/null +++ b/plugins/Quotes/src/OptionDukasCopy.cpp @@ -0,0 +1,414 @@ +#include "StdAfx.h" +#include "OptionDukasCopy.h" +#include "IconLib.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "QuotesProviderDukasCopy.h" +#include "resource.h" +#include "EconomicRateInfo.h" +#include "CommonOptionDlg.h" + +// extern HANDLE g_hEventSettingsCnanged; + +namespace +{ + enum ETreeCheckBoxState + { + // tree check box state + TCBS_NOSTATEBOX = 0, + TCBS_UNCHECKED = 1, + TCBS_CHECKED = 2, + }; + + enum + { + TREE_VIEW_CHECK_STATE_CHANGE = WM_USER + 100, + IMAGE_INDEX_SECTION = 0, + IMAGE_INDEX_QUOTE = 1 + }; + + // typedef CQuotesProviders::TQuotesProviders TQuotesProviders; + // typedef CQuotesProviders::TQuotesProviderPtr TQuotesProviderPtr; + + HTREEITEM tree_insert_item(HWND hwndTree, + const tstring& rsName, + HTREEITEM htiParent, + int nImage, + LPARAM lp = 0) + { +// USES_CONVERSION; + TVINSERTSTRUCT tvi; + ZeroMemory(&tvi,sizeof(tvi)); + + tvi.hParent = htiParent; + tvi.hInsertAfter = TVI_LAST; + tvi.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + +// CA2T name(rsName.c_str()); + + tvi.item.pszText = const_cast(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(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(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(::SendMessage(hwndTree, TVM_GETNEXTITEM, TVGN_CHILD,reinterpret_cast(hti))); + } + + inline HTREEITEM tree_get_next_sibling_item(HWND hwndTree,HTREEITEM hti) + { + return reinterpret_cast(::SendMessage(hwndTree, TVM_GETNEXTITEM, TVGN_NEXT,reinterpret_cast(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(&tvi))) + { + UINT nState = (tvi.state >> 12); + return static_cast(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(&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(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(lParam); + switch(pNMHDR->code) + { + case TVN_KEYDOWN: + if(IDC_TREE_ECONOMIC_RATES == wParam) + { + LPNMTVKEYDOWN pKeyDown = reinterpret_cast(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(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(::SendMessage(hwndTree,TVM_HITTEST,0,reinterpret_cast(&tvhti))); + if(hti && (tvhti.flags&TVHT_ONITEMSTATEICON)) + { + ::PostMessage(hdlg,TREE_VIEW_CHECK_STATE_CHANGE,MAKEWPARAM(1,0),reinterpret_cast(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(lParam); + + ETreeCheckBoxState nState; + + bool bRecursively = 1 == LOWORD(wParam); + if(bRecursively) + { + nState = tree_get_state_image(hwndTree,hti); + } + else + { + nState = static_cast(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(pi.m_sName.c_str())); + odp.ptszTab = const_cast(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(sTitle.c_str())); +// #endif + + Options_AddPage(wp, &odp); +} diff --git a/plugins/Quotes/src/OptionDukasCopy.h b/plugins/Quotes/src/OptionDukasCopy.h new file mode 100644 index 0000000000..0674119e83 --- /dev/null +++ b/plugins/Quotes/src/OptionDukasCopy.h @@ -0,0 +1,8 @@ +#ifndef __60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__ +#define __60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__ + +class CQuotesProviderDukasCopy; + +void ShowDukasCopyPropPage(CQuotesProviderDukasCopy* pProvider,WPARAM wp,OPTIONSDIALOGPAGE& odp); + +#endif //__60a5d152_872c_4bc4_b9ae_cd561d110b2dOptionDukasCopy_h__ diff --git a/plugins/Quotes/src/QuoteChart.cpp b/plugins/Quotes/src/QuoteChart.cpp new file mode 100644 index 0000000000..3746540d23 --- /dev/null +++ b/plugins/Quotes/src/QuoteChart.cpp @@ -0,0 +1,408 @@ +#include "StdAfx.h" +#include "QuoteChart.h" + +#ifdef CHART_IMPLEMENT + +// #include "QuotesProviderDukasCopy.h" +// #include "QuotesProviders.h" +#include "ModuleInfo.h" +#include "EconomicRateInfo.h" +// #include "WinCtrlHelper.h" +#include "resource.h" +#include "DBUtils.h" +#include "Locale.h" +#include "SettingsDlg.h" +#include "Chart.h" +#include "WinCtrlHelper.h" + +#define WINDOW_PREFIX "Quotes Chart_" +#define CHART_CTRL_CLASS _T("DioksinChart") + +namespace +{ + struct CTimeConvert + { + static double Convert(const boost::posix_time::time_duration& v) + { + return boost::numeric_cast(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 TChart; + + inline TChart* get_chart_ptr(HWND hWnd) + { + TChart* pChart = reinterpret_cast(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(lp); + HANDLE hContact = reinterpret_cast(pCS->lpCreateParams); + + TChart* pChart = new TChart; + read_log_file(hContact,*pChart); + + ::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast(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(::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(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(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(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(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(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(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(lp); + switch(pNMHDR->code) + { + case NM_CLICK: + if(IDC_SYSLINK_PROVIDER == wp) + { + PNMLINK pNMLink = reinterpret_cast(pNMHDR); + ::ShellExecute(hDlg,_T("open"),pNMLink->item.szUrl,NULL,NULL,SW_SHOWNORMAL); + } + break; + } + } + break; +// case WM_ERASEBKGND: +// { +// HDC hdc = reinterpret_cast(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(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(hContact)); + } + + return 0; +} + +#endif //CHART_IMPLEMENT diff --git a/plugins/Quotes/src/QuoteChart.h b/plugins/Quotes/src/QuoteChart.h new file mode 100644 index 0000000000..1b40f428b5 --- /dev/null +++ b/plugins/Quotes/src/QuoteChart.h @@ -0,0 +1,12 @@ +#ifndef __39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__ +#define __39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__ + +#ifdef CHART_IMPLEMENT + +#pragma once + +INT_PTR QuotesMenu_Chart(WPARAM wp,LPARAM lp); + +#endif + +#endif //__39BE8775_A837_494f_925C_0ABF7910F238_QuoteChart_h__ diff --git a/plugins/Quotes/src/QuoteInfoDlg.cpp b/plugins/Quotes/src/QuoteInfoDlg.cpp new file mode 100644 index 0000000000..61b6fb5f11 --- /dev/null +++ b/plugins/Quotes/src/QuoteInfoDlg.cpp @@ -0,0 +1,350 @@ +#include "StdAfx.h" +#include "QuoteInfoDlg.h" +#include "EconomicRateInfo.h" +#include "resource.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "IconLib.h" +#include "DBUtils.h" +#include "IQuotesProvider.h" +#include "Locale.h" +#include "SettingsDlg.h" + +// extern HANDLE g_hWindowListEditSettings; +extern HGENMENU g_hMenuEditSettings; +extern HGENMENU g_hMenuOpenLogFile; +#ifdef CHART_IMPLEMENT +extern HGENMENU g_hMenuChart; +#endif +extern HGENMENU g_hMenuRefresh; + + +#define WINDOW_PREFIX_INFO "Quote Info" + + +namespace +{ + HANDLE g_hContact; + + inline bool IsMyContact(HANDLE hContact) + { + CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact); + return (NULL != pProvider); + } + + inline HANDLE get_contact(HWND hWnd) + { + return reinterpret_cast(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(hContact),reinterpret_cast(&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(" ") << pi.m_sName << _T(""); + + ::SetDlgItemText(hdlg,IDC_SYSLINK_PROVIDER,o.str().c_str()); + } + return TRUE; + case WM_NOTIFY: + { + LPNMHDR pNMHDR = reinterpret_cast(lParam); + switch(pNMHDR->code) + { + case NM_CLICK: + if(IDC_SYSLINK_PROVIDER == wParam) + { + PNMLINK pNMLink = reinterpret_cast(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(lp); + if(NULL == hContact) + { + return 0; + } + + + if(false == IsMyContact(hContact)) + { + return 0; + } + + g_hContact = hContact; + + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof( odp ); + odp.hInstance = g_hInstance; + + odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN); + odp.pfnDlgProc = QuoteInfoDlgProc; + odp.position = -2000000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_DIALOG_QUOTE_INFO); + odp.pszTitle = LPGEN("Quote"); + UserInfo_AddPage(wp, &odp); + return 0; +} + + +INT_PTR QuotesMenu_EditSettings(WPARAM wp,LPARAM lp) +{ + HANDLE hContact = reinterpret_cast(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(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(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(lParam); + HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_INFO,false); + assert(hWL); + WindowList_Add(hWL,hdlg,hContact); + + ::SetWindowLongPtr(hdlg,GWLP_USERDATA,reinterpret_cast(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(wp); + if(CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(hContact)) + { + HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_INFO,true); + assert(hWL); + HWND hWnd = WindowList_Find(hWL,hContact); + if(NULL != hWnd) + { + SetForegroundWindow(hWnd); + SetFocus(hWnd); + } + else if(true == IsMyContact(hContact)) + { + CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_DIALOG_QUOTE_INFO_1),NULL,QuoteInfoDlgProc1,reinterpret_cast(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(hMenu),reinterpret_cast(&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(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/plugins/Quotes/src/QuoteInfoDlg.h b/plugins/Quotes/src/QuoteInfoDlg.h new file mode 100644 index 0000000000..c4a1999a4c --- /dev/null +++ b/plugins/Quotes/src/QuoteInfoDlg.h @@ -0,0 +1,11 @@ +#ifndef __aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__ +#define __aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__ + +int QuotesEventFunc_OnUserInfoInit(WPARAM wp,LPARAM lp); +INT_PTR QuotesMenu_EditSettings(WPARAM wp,LPARAM lp); +INT_PTR QuotesMenu_OpenLogFile(WPARAM wp,LPARAM lp); +INT_PTR QuotesMenu_RefreshContact(WPARAM wp,LPARAM lp); +int Quotes_PrebuildContactMenu(WPARAM wp,LPARAM lp); +int Quotes_OnContactDoubleClick(WPARAM wp,LPARAM lp); + +#endif //__aa849fa0_ff3f_49e9_b47a_e7dd34783dc2_QuoteInfoDlg_h__ diff --git a/plugins/Quotes/src/QuotesProviderBase.cpp b/plugins/Quotes/src/QuotesProviderBase.cpp new file mode 100644 index 0000000000..681afb0d38 Binary files /dev/null and b/plugins/Quotes/src/QuotesProviderBase.cpp differ diff --git a/plugins/Quotes/src/QuotesProviderBase.h b/plugins/Quotes/src/QuotesProviderBase.h new file mode 100644 index 0000000000..76db155f4c --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderBase.h @@ -0,0 +1,112 @@ +#ifndef __3e6cb4ec_fc47_468f_a2c8_a77941176bc9_QuotesProviderBase_h__ +#define __3e6cb4ec_fc47_468f_a2c8_a77941176bc9_QuotesProviderBase_h__ + +#include "iquotesprovider.h" +#include +#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 TSections; + typedef std::vector 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 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 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/plugins/Quotes/src/QuotesProviderDukasCopy.cpp b/plugins/Quotes/src/QuotesProviderDukasCopy.cpp new file mode 100644 index 0000000000..a7ffc5331a Binary files /dev/null and b/plugins/Quotes/src/QuotesProviderDukasCopy.cpp differ diff --git a/plugins/Quotes/src/QuotesProviderDukasCopy.h b/plugins/Quotes/src/QuotesProviderDukasCopy.h new file mode 100644 index 0000000000..d6ec498bcf --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderDukasCopy.h @@ -0,0 +1,38 @@ +#ifndef __93121758_68c7_4836_b571_da84dfe82b84_QuotesProviderDukasCopy_h__ +#define __93121758_68c7_4836_b571_da84dfe82b84_QuotesProviderDukasCopy_h__ + +#include "quotesproviderbase.h" +#include + +#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/plugins/Quotes/src/QuotesProviderFinance.cpp b/plugins/Quotes/src/QuotesProviderFinance.cpp new file mode 100644 index 0000000000..e8b335035d --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderFinance.cpp @@ -0,0 +1,318 @@ +#include "stdafx.h" +#include "QuotesProviderFinance.h" +#include "EconomicRateInfo.h" +#include "DBUtils.h" +#include "QuotesProviderVisitor.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "CommonOptionDlg.h" +#include "resource.h" +#include "WinCtrlHelper.h" + +void CQuotesProviderFinance::GetWatchedQuotes(TQuotes& raQuotes)const +{ + raQuotes.clear(); + BOOST_FOREACH(HANDLE hContact,m_aContacts) + { + tstring sID = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID); + tstring sSymbol = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_SYMBOL,sID.c_str()); + tstring sDescr = Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION); + CQuotesProviderBase::CQuote quote(sID,sSymbol,sDescr); + + raQuotes.push_back(quote); + } +} + +namespace +{ + inline tstring get_quote_id(HANDLE hContact) + { + return Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID); + } + + inline bool is_quote_id_equal(HANDLE hContact,const tstring& sID) + { + return sID == get_quote_id(hContact); + } +} + +bool CQuotesProviderFinance::WatchForQuote(const CQuote& rQuote,bool bWatch) +{ + const tstring& sQuoteID = rQuote.GetID(); + TContracts::iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(), + boost::bind(is_quote_id_equal,_1,sQuoteID)); + + if ((false == bWatch) && (i != m_aContacts.end())) + { + HANDLE hContact = *i; + {// for CCritSection + CGuard cs(m_cs); + m_aContacts.erase(i); + } + + CallService(MS_DB_CONTACT_DELETE,reinterpret_cast(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 cs(m_cs); + + TContracts::const_iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(), + boost::bind(std::equal_to(),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(sName.c_str())); + if(nIndex >= 0) + { + CQuotesProviderBase::CQuote* pQuote = new CQuotesProviderBase::CQuote(rQuote); + if(LB_ERR == ::SendMessage(hwnd,LB_SETITEMDATA,nIndex,reinterpret_cast(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(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(lParam); + SetWindowLongPtr(hDlg,GWLP_USERDATA,lParam); + } + else + { + pProvider = reinterpret_cast(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(lParam); + switch(pNMHDR->code) + { + case PSN_APPLY: + if(pProvider) + { + CQuotesProviderFinance::TQuotes aTemp; + pProvider->GetWatchedQuotes(aTemp); + + typedef std::vector 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(), + ["e](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(static_cast(this)); + odp.ptszTab = const_cast(GetInfo().m_sName.c_str()); + Options_AddPage(wp, &odp); +} diff --git a/plugins/Quotes/src/QuotesProviderFinance.h b/plugins/Quotes/src/QuotesProviderFinance.h new file mode 100644 index 0000000000..f63077071d --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderFinance.h @@ -0,0 +1,21 @@ +#ifndef __95A13A68_0DF0_43FA_B6C1_81D83AED59AA_QuotesProviderFinance_h__ +#define __95A13A68_0DF0_43FA_B6C1_81D83AED59AA_QuotesProviderFinance_h__ + +#include "QuotesProviderBase.h" + +class CQuotesProviderFinance : public CQuotesProviderBase +{ +public: + typedef std::vector 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/plugins/Quotes/src/QuotesProviderGoogle.cpp b/plugins/Quotes/src/QuotesProviderGoogle.cpp new file mode 100644 index 0000000000..c2b30a9a6a --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderGoogle.cpp @@ -0,0 +1,543 @@ +#include "StdAfx.h" +#include "QuotesProviderGoogle.h" +#include "resource.h" +#include "HTTPSession.h" +#include "Log.h" +#include "DBUtils.h" +#include "EconomicRateInfo.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "IHTMLParser.h" +#include "IHTMLEngine.h" +#include "CommonOptionDlg.h" +#include "QuotesProviderVisitor.h" + +CQuotesProviderGoogle::CQuotesProviderGoogle() +{ +} + +CQuotesProviderGoogle::~CQuotesProviderGoogle() +{ +} + +namespace +{ + inline tstring make_contact_name(const tstring& rsSymbolFrom,const tstring& rsSymbolTo) + { + tostringstream o; + o << rsSymbolFrom << _T("/") << rsSymbolTo; + return o.str(); + } + + inline bool is_rate_watched(HANDLE hContact, + const CQuotesProviderBase::CQuote& from, + const CQuotesProviderBase::CQuote& to) + { + tstring sFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID); + tstring sTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID); + return ((0 == quotes_stricmp(from.GetID().c_str(),sFrom.c_str())) + && (0 == quotes_stricmp(to.GetID().c_str(),sTo.c_str()))); + } +} + +bool CQuotesProviderGoogle::WatchForRate(const CRateInfo& ri, + bool bWatch) +{ + TContracts::const_iterator i = std::find_if(m_aContacts.begin(),m_aContacts.end(), + boost::bind(is_rate_watched,_1,ri.m_from,ri.m_to)); + if ((true == bWatch) && (i == m_aContacts.end())) + { + tstring sName = make_contact_name(ri.m_from.GetSymbol(),ri.m_to.GetSymbol()); + HANDLE hContact = CreateNewContact(sName); + if(hContact) + { + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID,ri.m_from.GetID().c_str()); + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID,ri.m_to.GetID().c_str()); + if(false == ri.m_from.GetName().empty()) + { + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_DESCRIPTION,ri.m_from.GetName().c_str()); + } + if(false == ri.m_to.GetName().empty()) + { + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_DESCRIPTION,ri.m_to.GetName().c_str()); + } + + return true; + } + } + else if ((false == bWatch) && (i != m_aContacts.end())) + { + HANDLE hContact = *i; + {// for CCritSection + CGuard cs(m_cs); + m_aContacts.erase(i); + } + + CallService(MS_DB_CONTACT_DELETE,reinterpret_cast(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(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 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(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(pszName)); + ::SendMessage(hcbxTo,CB_ADDSTRING,0,reinterpret_cast(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(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(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0)); + int nTo = static_cast(::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(::SendMessage(::GetDlgItem(hdlg,IDC_COMBO_CONVERT_FROM),CB_GETCURSEL,0,0)); + size_t nTo = static_cast(::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(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(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(GetInfo().m_sName.c_str())); + odp.ptszTab = const_cast(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(sTitle.c_str())); +// #endif + Options_AddPage(wp, &odp); +} + +void CQuotesProviderGoogle::Accept(CQuotesProviderVisitor& visitor)const +{ + CQuotesProviderBase::Accept(visitor); + visitor.Visit(*this); +} + +double CQuotesProviderGoogle::Convert(double dAmount,const CQuote& from,const CQuote& to)const +{ + tstring sFullURL = build_url(GetURL(),from.GetID(),to.GetID(),dAmount); +// LogIt(Info,sFullURL); + + CHTTPSession http; + if ((true == http.OpenURL(sFullURL))) + { + tstring sHTML; + if ((true == http.ReadResponce(sHTML))) + { +// LogIt(Info,sHTML); + + double dResult = 0.0; + if ((true == parse_responce(sHTML,dResult))) + { + return dResult; + } + else + { + throw std::runtime_error(Translate("Error occurred during html parsing.")); + } + } + else + { + throw std::runtime_error(Translate("Error occurred during site access.")); + } + } + else + { + throw std::runtime_error(Translate("Error occurred during site access.")); + } + + return 0.0; +} + +namespace +{ + bool is_equal_ids(HANDLE hContact,const tstring& rsFromID,const tstring& rsToID) + { + tstring sFrom = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_FROM_ID); + tstring sTo = Quotes_DBGetStringT(hContact,QUOTES_PROTOCOL_NAME,DB_STR_TO_ID); + return ((0 == quotes_stricmp(rsFromID.c_str(),sFrom.c_str())) + && (0 == quotes_stricmp(rsToID.c_str(),sTo.c_str()))); + } +} + +HANDLE CQuotesProviderGoogle::GetContactByID(const tstring& rsFromID,const tstring& rsToID)const +{ + CGuard 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/plugins/Quotes/src/QuotesProviderGoogle.h b/plugins/Quotes/src/QuotesProviderGoogle.h new file mode 100644 index 0000000000..4289861178 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderGoogle.h @@ -0,0 +1,42 @@ +#ifndef __c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__ +#define __c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__ + +#include "quotesproviderBase.h" + +#define DB_STR_FROM_ID "FromID" +#define DB_STR_TO_ID "ToID" +#define DB_STR_FROM_DESCRIPTION "FromDesc" +#define DB_STR_TO_DESCRIPTION "ToDesc" +#define DB_STR_GOOGLE_REFRESH_RATE_TYPE "Google_RefreshRateType" +#define DB_STR_GOOGLE_REFRESH_RATE_VALUE "Google_RefreshRateValue" +#define DB_STR_GOOGLE_DISPLAY_NAME_FORMAT "Google_DspNameFrmt" +// #define DB_STR_GOOGLE_LOG_FILE_FORMAT "Google_LogFileFormat" +// #define DB_STR_GOOGLE_HISTORY_FORMAT "Google_HistoryFormat" + +class CQuotesProviderGoogle : public CQuotesProviderBase +{ +public: + struct CRateInfo + { + CQuotesProviderBase::CQuote m_from; + CQuotesProviderBase::CQuote m_to; + }; +public: + CQuotesProviderGoogle(); + ~CQuotesProviderGoogle(); + + bool WatchForRate(const CRateInfo& ri,bool bWatch); + size_t GetWatchedRateCount()const; + bool GetWatchedRateInfo(size_t nIndex,CRateInfo& rRateInfo); + + HANDLE GetContactByID(const tstring& rsFromID,const tstring& rsToID)const; + + double Convert(double dAmount,const CQuote& from,const CQuote& to)const; + +private: + virtual void RefreshQuotes(TContracts& anContacts); + virtual void ShowPropertyPage(WPARAM wp,OPTIONSDIALOGPAGE& odp); + virtual void Accept(CQuotesProviderVisitor& visitor)const; +}; + +#endif //__c0e48a95_b3f0_4227_8adc_455e265f3c14_QuotesProviderGoogle_h__ diff --git a/plugins/Quotes/src/QuotesProviderGoogleFinance.cpp b/plugins/Quotes/src/QuotesProviderGoogleFinance.cpp new file mode 100644 index 0000000000..8a129b6b8b --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderGoogleFinance.cpp @@ -0,0 +1,366 @@ +#include "StdAfx.h" +#include "QuotesProviderGoogleFinance.h" +#include "QuotesProviderVisitor.h" +#include "EconomicRateInfo.h" +#include "DBUtils.h" +#include "resource.h" +#include "ModuleInfo.h" +// #include "QuotesProviders.h" +// #include "CommonOptionDlg.h" +// #include "WinCtrlHelper.h" +#include "IHTMLParser.h" +#include "IHTMLEngine.h" +#include "HTTPSession.h" +#include "Log.h" +#include "Locale.h" + +CQuotesProviderGoogleFinance::CQuotesProviderGoogleFinance() +{ +} + +CQuotesProviderGoogleFinance::~CQuotesProviderGoogleFinance() +{ +} + +namespace +{ + tstring build_url(HANDLE hContact,const tstring& rsURL) + { + tostringstream o; + o << rsURL << _T("?q=") << Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID); + return o.str(); + } + + struct CGoogleInfo + { + enum + { + giRate = 0x0001, + giOpen = 0x0002, + giPercentChangeAfterHours = 0x0004, + giPercentChangeToYesterdayClose = 0x0008 + }; + CGoogleInfo() + : m_dRate(0.0),m_dOpenValue(0.0),m_dPercentChangeAfterHours(0.0),m_dPercentChangeToYersterdayClose(0.0),m_nFlags(0){} +// tstring m_sCmpID; + tstring m_sCmpName; + double m_dRate; + double m_dOpenValue; + double m_dPercentChangeAfterHours; + double m_dPercentChangeToYersterdayClose; + +// tstring m_sRateID; +// tstring m_sDiffID; + byte m_nFlags; + }; + + tstring make_rate_id_value(const tstring& rsCmpID,int nFlags) + { + tostringstream o; + o << _T("ref_") << rsCmpID; + switch(nFlags) + { + default: + assert(!"Unknown type of value"); + case CGoogleInfo::giRate: + o << _T("_l"); + break; + case CGoogleInfo::giPercentChangeAfterHours: + o << _T("_ecp"); + break; + case CGoogleInfo::giPercentChangeToYesterdayClose: + o << _T("_cp"); + break; + } + + return o.str(); + } + + tstring get_var_value(const tstring& rsHTML,LPCTSTR pszVarName,size_t cVarNameLength) + { + tstring sResult; + tstring::size_type n = rsHTML.find(pszVarName); + if(tstring::npos != n) + { + size_t cLengthHTML = rsHTML.size(); + for(size_t i = n + cVarNameLength;i < cLengthHTML;++i) + { + TCHAR c = rsHTML[i]; + if(_T(';') == c) + { + break; + } + else + { + sResult.push_back(c); + } + } + } + + return sResult; + } + + tstring get_company_id(const tstring& rsHTML) + { + static LPCTSTR pszVarName = _T("setCompanyId("); + static size_t cVarNameLength = _tcslen(pszVarName); + + tstring sResult; + tstring::size_type n = rsHTML.find(pszVarName); + if(tstring::npos != n) + { + size_t cLengthHTML = rsHTML.size(); + for(size_t i = n + cVarNameLength;i < cLengthHTML;++i) + { + TCHAR c = rsHTML[i]; + if(_T(')') == c) + { + break; + } + else + { + sResult.push_back(c); + } + } + } + return sResult; +// return get_var_value(rsHTML,pszVarName,cVarNameLength); + } + + tstring get_company_name(const tstring& rsHTML) + { + static LPCTSTR pszVarName = _T("var _companyName = "); + static size_t cVarNameLength = _tcslen(pszVarName); + + tstring s = get_var_value(rsHTML,pszVarName,cVarNameLength); + if(s.size() > 0 && _T('\'') == s[0]) + { + s.erase(s.begin()); + } + + if(s.size() > 0 && _T('\'') == s[s.size()-1]) + { + s.erase(s.rbegin().base()-1); + } + + return s; + } + + bool get_double_value(const tstring& rsText,double& rdValue) + { + tistringstream input(rsText); + input.imbue(std::locale("English_United States.1252")); + input >> rdValue; + + if ((true == input.bad()) || (true == input.fail())) + { + tistringstream inputSys(rsText); + input.imbue(GetSystemLocale()); + input >> rdValue; + return (false == inputSys.bad()) && (false == inputSys.fail()); + } + else + { + return true; + } + } + + bool get_rate(const IHTMLNode::THTMLNodePtr& pRate,CGoogleInfo& rInfo) + { + tstring sRate = pRate->GetText(); + + if(true == get_double_value(sRate,rInfo.m_dRate)) + { + rInfo.m_nFlags |= CGoogleInfo::giRate; + return true; + } + else + { + return false; + } + } + + bool get_inline_data(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo) + { + size_t cChild = pNode->GetChildCount(); + for(size_t i = 0;i < cChild;++i) + { + IHTMLNode::THTMLNodePtr pChild = pNode->GetChildPtr(i); + size_t c = pChild->GetChildCount(); + assert(2 == c); + if(c >= 2) + { + IHTMLNode::THTMLNodePtr pName = pChild->GetChildPtr(0); + + tstring sName = pName->GetText(); + if(0 == quotes_stricmp(sName.c_str(),_T("Open"))) + { + IHTMLNode::THTMLNodePtr pValue = pChild->GetChildPtr(1); + tstring sValue = pValue->GetText(); + if(true == get_double_value(sValue,rInfo.m_dOpenValue)) + { + rInfo.m_nFlags |= CGoogleInfo::giOpen; + } + return true; + } + } + } + + return false; + } + + bool get_dif_value(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo,int nItem) + { + tstring sDiff = pNode->GetText(); + // this value is in brackets and it has percentage sign. + // Remove these symbols. + for(tstring::iterator i = sDiff.begin();i != sDiff.end();) + { + TCHAR s = *i; + if(_T('(') == s || _T(')') == s || _T('%') == s) + { + i = sDiff.erase(i); + } + else + { + ++i; + } + } + + double* pValue = NULL; + switch(nItem) + { + case CGoogleInfo::giPercentChangeAfterHours: + pValue = &rInfo.m_dPercentChangeAfterHours; + break; + case CGoogleInfo::giPercentChangeToYesterdayClose: + pValue = &rInfo.m_dPercentChangeToYersterdayClose; + break; + } + + assert(pValue); + + if ((pValue) && (true == get_double_value(sDiff,*pValue))) + { + rInfo.m_nFlags |= nItem; + return true; + } + else + { + return false; + } + + } + + bool parse_responce(const tstring& rsHTML,CGoogleInfo& rInfo) + { + IHTMLEngine::THTMLParserPtr pHTMLParser = CModuleInfo::GetHTMLEngine()->GetParserPtr(); + IHTMLNode::THTMLNodePtr pRoot = pHTMLParser->ParseString(rsHTML); + if(pRoot) + { + tstring sCmpID = get_company_id(rsHTML); + if(false == sCmpID.empty()) + { + tstring sRateID = make_rate_id_value(sCmpID,CGoogleInfo::giRate); + IHTMLNode::THTMLNodePtr pRate = pRoot->GetElementByID(sRateID); + if(pRate && get_rate(pRate,rInfo)) + { + rInfo.m_sCmpName = get_company_name(rsHTML); + + IHTMLNode::THTMLNodePtr pInline = pRoot->GetElementByID(_T("snap-data")); + if(pInline) + { + get_inline_data(pInline,rInfo); + } + + tstring sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeAfterHours); + IHTMLNode::THTMLNodePtr pDiff = pRoot->GetElementByID(sDiffID); + if(pDiff) + { + get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeAfterHours); + } + + sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeToYesterdayClose); + pDiff = pRoot->GetElementByID(sDiffID); + if(pDiff) + { + get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeToYesterdayClose); + } + + return true; + } + + //return (true == parse_html_node(pRoot,rInfo)); + } + } + + return false; + } +} + +void CQuotesProviderGoogleFinance::RefreshQuotes(TContracts& anContacts) +{ + CHTTPSession http; + tstring sURL = GetURL(); + bool bUseExtendedStatus = CModuleInfo::GetInstance().GetExtendedStatusFlag(); + + for(TContracts::const_iterator i = anContacts.begin();i != anContacts.end() && IsOnline();++i) + { + HANDLE hContact = *i; + + if(bUseExtendedStatus) + { + SetContactStatus(hContact,ID_STATUS_OCCUPIED); + } + + tstring sFullURL = build_url(hContact,sURL); +// LogIt(Info,sFullURL); + if ((true == http.OpenURL(sFullURL)) && (true == IsOnline())) + { + tstring sHTML; + if ((true == http.ReadResponce(sHTML)) && (true == IsOnline())) + { +// LogIt(Info,sHTML); + + CGoogleInfo Info; + parse_responce(sHTML,Info); + if(true == IsOnline()) + { + if(Info.m_nFlags&CGoogleInfo::giRate) + { + if(Info.m_nFlags&CGoogleInfo::giOpen) + { + Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_OPEN_VALUE,Info.m_dOpenValue); + } + if(Info.m_nFlags&CGoogleInfo::giPercentChangeAfterHours) + { + Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_DIFF,Info.m_dPercentChangeAfterHours); + } + if(Info.m_nFlags&CGoogleInfo::giPercentChangeToYesterdayClose) + { + Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE,Info.m_dPercentChangeToYersterdayClose); + } + if(false == Info.m_sCmpName.empty()) + { + DBWriteContactSettingTString(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION,Info.m_sCmpName.c_str()); + } + + WriteContactRate(hContact,Info.m_dRate); + continue; + } + } + } + } + + SetContactStatus(hContact,ID_STATUS_NA); + } + +} + + +void CQuotesProviderGoogleFinance::Accept(CQuotesProviderVisitor& visitor)const +{ + CQuotesProviderFinance::Accept(visitor); + visitor.Visit(*this); +} + diff --git a/plugins/Quotes/src/QuotesProviderGoogleFinance.h b/plugins/Quotes/src/QuotesProviderGoogleFinance.h new file mode 100644 index 0000000000..075498a4dd --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderGoogleFinance.h @@ -0,0 +1,25 @@ +#ifndef __89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__ +#define __89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__ + +#include "QuotesProviderFinance.h" + +#define DB_STR_GOOGLE_FINANCE_OPEN_VALUE "OpenQuotePrice" +#define DB_STR_GOOGLE_FINANCE_DIFF "DifferentFromStartOfDay" +#define DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE "PercentChangeToYersterdayClose" + +// #define DB_STR_GOOGLE_FINANCE_COMP_NAME "CompanyName" + + +class CQuotesProviderGoogleFinance : public CQuotesProviderFinance +{ + +public: + CQuotesProviderGoogleFinance(); + ~CQuotesProviderGoogleFinance(); + +private: + virtual void RefreshQuotes(TContracts& anContacts); + virtual void Accept(CQuotesProviderVisitor& visitor)const; +}; + +#endif //__89D3CC58_7DED_484f_AA25_62BDBB57E18B_QuotesProvider_Google_Finance_h__ diff --git a/plugins/Quotes/src/QuotesProviderVisitor.h b/plugins/Quotes/src/QuotesProviderVisitor.h new file mode 100644 index 0000000000..9ae601f2a1 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitor.h @@ -0,0 +1,25 @@ +#ifndef __7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__ +#define __7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__ + +class CQuotesProviderBase; +class CQuotesProviderFinance; +class CQuotesProviderDukasCopy; +class CQuotesProviderGoogle; +class CQuotesProviderGoogleFinance; +class CQuotesProviderYahoo; + +class CQuotesProviderVisitor +{ +public: + CQuotesProviderVisitor() {} + virtual ~CQuotesProviderVisitor() {} + + virtual void Visit(const CQuotesProviderBase& rProvider){} + virtual void Visit(const CQuotesProviderFinance& rProvider){} + virtual void Visit(const CQuotesProviderDukasCopy& rProvider){} + virtual void Visit(const CQuotesProviderGoogle& rProvider){} + virtual void Visit(const CQuotesProviderGoogleFinance& rProvider){} + virtual void Visit(const CQuotesProviderYahoo& rProvider){} +}; + +#endif //__7fca59e7_17b2_4849_bd7a_02c7675f2d76_QuotesProviderVisitor_h__ diff --git a/plugins/Quotes/src/QuotesProviderVisitorDbSettings.cpp b/plugins/Quotes/src/QuotesProviderVisitorDbSettings.cpp new file mode 100644 index 0000000000..5caea48685 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorDbSettings.cpp @@ -0,0 +1,157 @@ +#include "StdAfx.h" +#include "QuotesProviderVisitorDbSettings.h" + +#include "QuotesProviderGoogle.h" +#include "QuotesProviderDukasCopy.h" + +CQuotesProviderVisitorDbSettings::CQuotesProviderVisitorDbSettings() + : m_pszDbRefreshRateType(NULL), + m_pszDbRefreshRateValue(NULL), + m_pszDbDisplayNameFormat(NULL), + m_pszDefDisplayFormat(NULL), + m_pszDefLogFileFormat(NULL), + m_pszDefHistoryFormat(NULL), + m_pszXMLIniFileName(NULL), + m_pszDbStatusMsgFormat(NULL), + m_pszDefStatusMsgFormat(NULL), + m_pszDbLogMode(NULL), + m_pszDbHistoryFormat(NULL), + m_pszDbHistoryCondition(NULL), + m_pszDbLogFile(NULL), + m_pszDbLogFormat(NULL), + m_pszDbLogCondition(NULL), + m_pszDbPopupFormat(NULL), + m_pszDefPopupFormat(NULL), + m_pszDbPopupCondition(NULL), + m_pszDbPopupColourMode(NULL), + m_pszDbPopupBkColour(NULL), + m_pszDbPopupTextColour(NULL), + m_pszDbPopupDelayMode(NULL), + m_pszDbPopupDelayTimeout(NULL), + m_pszDbPopupHistoryFlag(NULL), + m_pszDbTendencyFormat(nullptr), + m_pszDefTendencyFormat(_T("%r>%p")) +{ +} + +CQuotesProviderVisitorDbSettings::~CQuotesProviderVisitorDbSettings() +{ +} + +void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderBase&/* rProvider*/) +{ + m_pszDefLogFileFormat = _T("%s\\t%t\\t%r\\n"); + m_pszDefHistoryFormat = _T("%s %r"); + m_pszDefPopupFormat = _T("\\nCurrent = %r\\nPrevious = %p"); +} + +void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderDukasCopy&/* rProvider*/) +{ + m_pszDbRefreshRateType = DB_STR_REFRESH_RATE_TYPE; + m_pszDbRefreshRateValue = DB_STR_REFRESH_RATE_VALUE; + m_pszDbDisplayNameFormat = DB_STR_DC_DISPLAY_NAME_FORMAT; + m_pszDefDisplayFormat = _T("%s %r"); + m_pszXMLIniFileName = _T("Dukascopy.xml"); + m_pszDbStatusMsgFormat = "DC_StatusMessageFormat"; + + m_pszDbLogMode = "DC_LogMode"; + m_pszDbHistoryFormat = "DC_HistoryFormat"; + m_pszDbHistoryCondition = "DC_AddToHistoryOnlyIfValueIsChanged"; + m_pszDbLogFile = "DC_LogFile"; + m_pszDbLogFormat = "DC_LogFileFormat"; + m_pszDbLogCondition = "DC_AddToLogOnlyIfValueIsChanged"; + m_pszDbPopupFormat ="DC_PopupFormat"; + m_pszDbPopupCondition = "DC_ShowPopupOnlyIfValueChanged"; + + m_pszDbPopupColourMode = "DC_PopupColourMode"; + m_pszDbPopupBkColour = "DC_PopupColourBk"; + m_pszDbPopupTextColour = "DC_PopupColourText"; + m_pszDbPopupDelayMode = "DC_PopupDelayMode"; + m_pszDbPopupDelayTimeout = "DC_PopupDelayTimeout"; + m_pszDbPopupHistoryFlag = "DC_PopupHistoryFlag"; + m_pszDbTendencyFormat = "DC_TendencyFormat"; +} + +void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderGoogle&/* rProvider*/) +{ + m_pszDbRefreshRateType = DB_STR_GOOGLE_REFRESH_RATE_TYPE; + m_pszDbRefreshRateValue = DB_STR_GOOGLE_REFRESH_RATE_VALUE; + m_pszDbDisplayNameFormat = DB_STR_GOOGLE_DISPLAY_NAME_FORMAT; + m_pszDefDisplayFormat = _T("1 %f = %r %i"); + m_pszXMLIniFileName = _T("Google.xml"); + m_pszDbStatusMsgFormat = "Google_StatusMessageFormat"; + + m_pszDbLogMode = "Google_LogMode"; + m_pszDbHistoryFormat = "Google_HistoryFormat"; + m_pszDbHistoryCondition = "Google_AddToHistoryOnlyIfValueIsChanged"; + m_pszDbLogFile = "Google_LogFile"; + m_pszDbLogFormat = "Google_LogFileFormat"; + m_pszDbLogCondition = "Google_AddToLogOnlyIfValueIsChanged"; + m_pszDbPopupFormat ="Google_PopupFormat"; + m_pszDbPopupCondition = "Google_ShowPopupOnlyIfValueChanged"; + + m_pszDbPopupColourMode = "Google_PopupColourMode"; + m_pszDbPopupBkColour = "Google_PopupColourBk"; + m_pszDbPopupTextColour = "Google_PopupColourText"; + m_pszDbPopupDelayMode = "Google_PopupDelayMode"; + m_pszDbPopupDelayTimeout = "Google_PopupDelayTimeout"; + m_pszDbPopupHistoryFlag = "Google_PopupHistoryFlag"; + + m_pszDbTendencyFormat = "Google_TendencyFormat"; +} + +void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderGoogleFinance&/* rProvider*/) +{ + m_pszDbRefreshRateType = "GoogleFinance_RefreshRateType"; + m_pszDbRefreshRateValue = "GoogleFinance_RefreshRateValue"; + m_pszDbDisplayNameFormat = "GoogleFinance_DspNameFrmt"; + m_pszDefDisplayFormat = _T("%s %r"); + m_pszXMLIniFileName = _T("GoogleFinance.xml"); + m_pszDbStatusMsgFormat = "GoogleFinance_StatusMessageFormat"; + + m_pszDbLogMode = "GoogleFinance_LogMode"; + m_pszDbHistoryFormat = "GoogleFinance_HistoryFormat"; + m_pszDbHistoryCondition = "GoogleFinance_AddToHistoryOnlyIfValueIsChanged"; + m_pszDbLogFile = "GoogleFinance_LogFile"; + m_pszDbLogFormat = "GoogleFinance_LogFileFormat"; + m_pszDbLogCondition = "GoogleFinance_AddToLogOnlyIfValueIsChanged"; + m_pszDbPopupFormat ="GoogleFinance_PopupFormat"; + m_pszDbPopupCondition = "GoogleFinance_ShowPopupOnlyIfValueChanged"; + + m_pszDbPopupColourMode = "GoogleFinance_PopupColourMode"; + m_pszDbPopupBkColour = "GoogleFinance_PopupColourBk"; + m_pszDbPopupTextColour = "GoogleFinance_PopupColourText"; + m_pszDbPopupDelayMode = "GoogleFinance_PopupDelayMode"; + m_pszDbPopupDelayTimeout = "GoogleFinance_PopupDelayTimeout"; + m_pszDbPopupHistoryFlag = "GoogleFinance_PopupHistoryFlag"; + + m_pszDbTendencyFormat = "GoogleFinance_TendencyFormat"; +} + +void CQuotesProviderVisitorDbSettings::Visit(const CQuotesProviderYahoo& rProvider) +{ + m_pszDbRefreshRateType = "Yahoo_RefreshRateType"; + m_pszDbRefreshRateValue = "Yahoo_RefreshRateValue"; + m_pszDbDisplayNameFormat = "Yahoo_DspNameFrmt"; + m_pszDefDisplayFormat = _T("%s %r"); + m_pszXMLIniFileName = _T("Yahoo.xml"); + m_pszDbStatusMsgFormat = "Yahoo_StatusMessageFormat"; + + m_pszDbLogMode = "Yahoo_LogMode"; + m_pszDbHistoryFormat = "Yahoo_HistoryFormat"; + m_pszDbHistoryCondition = "Yahoo_AddToHistoryOnlyIfValueIsChanged"; + m_pszDbLogFile = "Yahoo_LogFile"; + m_pszDbLogFormat = "Yahoo_LogFileFormat"; + m_pszDbLogCondition = "Yahoo_AddToLogOnlyIfValueIsChanged"; + m_pszDbPopupFormat ="Yahoo_PopupFormat"; + m_pszDbPopupCondition = "Yahoo_ShowPopupOnlyIfValueChanged"; + + m_pszDbPopupColourMode = "Yahoo_PopupColourMode"; + m_pszDbPopupBkColour = "Yahoo_PopupColourBk"; + m_pszDbPopupTextColour = "Yahoo_PopupColourText"; + m_pszDbPopupDelayMode = "Yahoo_PopupDelayMode"; + m_pszDbPopupDelayTimeout = "Yahoo_PopupDelayTimeout"; + m_pszDbPopupHistoryFlag = "Yahoo_PopupHistoryFlag"; + + m_pszDbTendencyFormat = "Yahoo_TendencyFormat"; +} diff --git a/plugins/Quotes/src/QuotesProviderVisitorDbSettings.h b/plugins/Quotes/src/QuotesProviderVisitorDbSettings.h new file mode 100644 index 0000000000..728a436dfa --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorDbSettings.h @@ -0,0 +1,49 @@ +#ifndef __97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__ +#define __97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__ + +#include "quotesprovidervisitor.h" + +class CQuotesProviderVisitorDbSettings : public CQuotesProviderVisitor +{ +public: + CQuotesProviderVisitorDbSettings(); + ~CQuotesProviderVisitorDbSettings(); + +private: + virtual void Visit(const CQuotesProviderBase& rProvider); + virtual void Visit(const CQuotesProviderDukasCopy& rProvider); + virtual void Visit(const CQuotesProviderGoogle& rProvider); + virtual void Visit(const CQuotesProviderGoogleFinance& rProvider); + virtual void Visit(const CQuotesProviderYahoo& rProvider); +public: + LPCSTR m_pszDbRefreshRateType; + LPCSTR m_pszDbRefreshRateValue; + LPCSTR m_pszDbDisplayNameFormat; + LPCTSTR m_pszDefDisplayFormat; + LPCTSTR m_pszDefLogFileFormat; + LPCTSTR m_pszDefHistoryFormat; + LPCTSTR m_pszXMLIniFileName; + LPCSTR m_pszDbStatusMsgFormat; + LPCTSTR m_pszDefStatusMsgFormat; + LPCTSTR m_pszDefPopupFormat; + LPCSTR m_pszDbTendencyFormat; + LPCTSTR m_pszDefTendencyFormat; + + //global settings + LPCSTR m_pszDbLogMode; + LPCSTR m_pszDbHistoryFormat; + LPCSTR m_pszDbHistoryCondition; + LPCSTR m_pszDbLogFile; + LPCSTR m_pszDbLogFormat; + LPCSTR m_pszDbLogCondition; + LPCSTR m_pszDbPopupFormat; + LPCSTR m_pszDbPopupCondition; + LPCSTR m_pszDbPopupColourMode; + LPCSTR m_pszDbPopupBkColour; + LPCSTR m_pszDbPopupTextColour; + LPCSTR m_pszDbPopupDelayMode; + LPCSTR m_pszDbPopupDelayTimeout; + LPCSTR m_pszDbPopupHistoryFlag; +}; + +#endif //__97cd432a_1119_4803_a96f_0abc1cc2653f_QuotesProviderVisitorDbSettings_h__ diff --git a/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp b/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp new file mode 100644 index 0000000000..9e643fe1b6 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.cpp @@ -0,0 +1,63 @@ +#include "StdAfx.h" +#include "QuotesProviderVisitorFormatSpecificator.h" + +CQuotesProviderVisitorFormatSpecificator::CQuotesProviderVisitorFormatSpecificator() +{ +} + +CQuotesProviderVisitorFormatSpecificator::~CQuotesProviderVisitorFormatSpecificator() +{ +} + +void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderDukasCopy&/* rProvider*/) +{ + m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%d"),TranslateT("Quote Name"))); +} + +void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderGoogle&/* rProvider*/) +{ + m_aSpecificators.push_back(CFormatSpecificator(_T("%F"),TranslateT("From Currency Full Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%f"),TranslateT("From Currency Short Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%I"),TranslateT("Into Currency Full Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%i"),TranslateT("Into Currency Short Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Short notation for \"%f/%i\""))); +} + +void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderBase&/* rProvider*/) +{ + m_aSpecificators.push_back(CFormatSpecificator(_T("%S"),TranslateT("Source of Information"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%r"),TranslateT("Rate Value"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%p"),TranslateT("Previous Rate Value"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%X"),TranslateT("Fetch Time"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%x"),TranslateT("Fetch Date"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%t"),TranslateT("Fetch Time and Date"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("\\%"),TranslateT("Percentage Character (%)"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("\\t"),TranslateT("Tabulation"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("\\\\"),TranslateT("Left slash (\\)"))); +} + +void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderGoogleFinance&/* rProvider*/) +{ + m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%n"),TranslateT("Quote Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%o"),TranslateT("Open Price"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%d"),TranslateT("Percent Change to After Hours"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%y"),TranslateT("Percent Change to Yesterday Close"))); +} + +const CQuotesProviderVisitorFormatSpecificator::TFormatSpecificators& CQuotesProviderVisitorFormatSpecificator::GetSpecificators()const +{ + return m_aSpecificators; +} + +void CQuotesProviderVisitorFormatSpecificator::Visit(const CQuotesProviderYahoo& rProvider) +{ + m_aSpecificators.push_back(CFormatSpecificator(_T("%s"),TranslateT("Quote Symbol"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%n"),TranslateT("Quote Name"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%o"),TranslateT("Open Price"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%h"),TranslateT("Day's High"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%g"),TranslateT("Day's Low"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%P"),TranslateT("Previous Close"))); + m_aSpecificators.push_back(CFormatSpecificator(_T("%c"),TranslateT("Change"))); +} diff --git a/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.h b/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.h new file mode 100644 index 0000000000..870ab00634 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorFormatSpecificator.h @@ -0,0 +1,36 @@ +#ifndef __00c159f3_525a_41e9_8fc5_00464b6fafa3_QuotesProviderVisitorFormatSpecificator_h__ +#define __00c159f3_525a_41e9_8fc5_00464b6fafa3_QuotesProviderVisitorFormatSpecificator_h__ + +#include "quotesprovidervisitor.h" + +class CQuotesProviderVisitorFormatSpecificator : public CQuotesProviderVisitor +{ +public: + struct CFormatSpecificator + { + CFormatSpecificator(const tstring& rsSymbol = _T(""),const tstring& rsDec = _T("")) + : m_sSymbol(rsSymbol),m_sDesc(rsDec){} + + tstring m_sSymbol; + tstring m_sDesc; + }; + typedef std::vector 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/plugins/Quotes/src/QuotesProviderVisitorFormater.cpp b/plugins/Quotes/src/QuotesProviderVisitorFormater.cpp new file mode 100644 index 0000000000..4b1d73bb05 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorFormater.cpp @@ -0,0 +1,216 @@ +#include "StdAfx.h" +#include "QuotesProviderVisitorFormater.h" +#include "DBUtils.h" +#include "EconomicRateInfo.h" +#include "QuotesProviderGoogle.h" +#include "Locale.h" +#include "IsWithinAccuracy.h" +#include "QuotesProviderGoogleFinance.h" +#include "QuotesProviderYahoo.h" + +CQuotesProviderVisitorFormater::CQuotesProviderVisitorFormater(HANDLE hContact,TCHAR chr,int nWidth) + : m_hContact(hContact), + m_chr(chr), + m_nWidth(nWidth) +{ +} + +CQuotesProviderVisitorFormater::~CQuotesProviderVisitorFormater() +{ +} + +const tstring& CQuotesProviderVisitorFormater::GetResult()const +{ + return m_sResult; +} + +void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderDukasCopy& rProvider) +{ + if(_T('d') == m_chr || _T('D') == m_chr) + { + m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION); + } +} + +void CQuotesProviderVisitorFormater::Visit(const CQuotesProviderGoogle& rProvider) +{ + switch(m_chr) + { + case _T('F'): + m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_FROM_DESCRIPTION); + break; + case _T('f'): + m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_FROM_ID); + break; + case _T('I'): + m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_TO_DESCRIPTION); + break; + case _T('i'): + m_sResult = Quotes_DBGetStringT(m_hContact,QUOTES_MODULE_NAME,DB_STR_TO_ID); + break; + } +} + +namespace +{ + bool get_fetch_time(HANDLE hContact,time_t& rTime) + { + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=QUOTES_MODULE_NAME; + cgs.szSetting=DB_STR_QUOTE_FETCH_TIME; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,reinterpret_cast(hContact),reinterpret_cast(&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::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/plugins/Quotes/src/QuotesProviderVisitorFormater.h b/plugins/Quotes/src/QuotesProviderVisitorFormater.h new file mode 100644 index 0000000000..7c9c222269 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorFormater.h @@ -0,0 +1,32 @@ +#ifndef __2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__ +#define __2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__ + +#include "quotesprovidervisitor.h" + +class CQuotesProviderVisitorFormater : public CQuotesProviderVisitor +{ +public: + CQuotesProviderVisitorFormater(HANDLE hContact,TCHAR chr,int nWidth); + ~CQuotesProviderVisitorFormater(); + + const tstring& GetResult()const; + +private: + virtual void Visit(const CQuotesProviderDukasCopy& rProvider); + virtual void Visit(const CQuotesProviderGoogle& rProvider); + virtual void Visit(const CQuotesProviderBase& rProvider); + virtual void Visit(const CQuotesProviderGoogleFinance& rProvider); + virtual void Visit(const CQuotesProviderYahoo& rProvider); + +private: + void FormatDoubleHelper(LPCSTR pszDbSet,const tstring sInvalid = _T("-")); +// void FormatChangeValueHelper(bool bPercentage); + +private: + HANDLE m_hContact; + TCHAR m_chr; + tstring m_sResult; + int m_nWidth; +}; + +#endif //__2b5ddd05_9255_4be0_9408_e59768b70568_QuotesProviderVisitorFormater_h__ diff --git a/plugins/Quotes/src/QuotesProviderVisitorTendency.cpp b/plugins/Quotes/src/QuotesProviderVisitorTendency.cpp new file mode 100644 index 0000000000..00703521b3 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorTendency.cpp @@ -0,0 +1,70 @@ +#include "stdafx.h" +#include "QuotesProviderVisitorTendency.h" +#include "DBUtils.h" +#include "QuotesProviderGoogleFinance.h" +#include "EconomicRateInfo.h" +#include "QuotesProviderYahoo.h" + +CQuotesProviderVisitorTendency::CQuotesProviderVisitorTendency(HANDLE hContact,TCHAR chr) + : m_hContact(hContact),m_chr(chr),m_bValid(false),m_dResult(0.0) +{ +} + +void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderBase& rProvider) +{ + switch(m_chr) + { + case _T('r'): + case _T('R'): + GetValue(DB_STR_QUOTE_CURR_VALUE); + break; + case _T('p'): + GetValue(DB_STR_QUOTE_PREV_VALUE); + break; + } +} + +void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderGoogleFinance& rProvider) +{ + switch(m_chr) + { + case _T('o'): + GetValue(DB_STR_GOOGLE_FINANCE_OPEN_VALUE); + break; + case _T('d'): + GetValue(DB_STR_GOOGLE_FINANCE_DIFF); + break; + case _T('y'): + GetValue(DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE); + break; + } +} + +void CQuotesProviderVisitorTendency::Visit(const CQuotesProviderYahoo& rProvider) +{ + switch(m_chr) + { + case _T('o'): + GetValue(DB_STR_YAHOO_OPEN_VALUE); + break; + case _T('h'): + GetValue(DB_STR_YAHOO_DAY_HIGH); + break; + case _T('P'): + GetValue(DB_STR_YAHOO_PREVIOUS_CLOSE); + break; + case _T('c'): + GetValue(DB_STR_YAHOO_CHANGE); + break; + case _T('g'): + GetValue(DB_STR_YAHOO_DAY_LOW); + break; + } + +} + + +void CQuotesProviderVisitorTendency::GetValue(LPCSTR pszDbKeyName) +{ + m_bValid = Quotes_DBReadDouble(m_hContact,QUOTES_MODULE_NAME,pszDbKeyName,m_dResult); +} diff --git a/plugins/Quotes/src/QuotesProviderVisitorTendency.h b/plugins/Quotes/src/QuotesProviderVisitorTendency.h new file mode 100644 index 0000000000..fa0f04c5f0 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderVisitorTendency.h @@ -0,0 +1,29 @@ +#ifndef __AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__ +#define __AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__ + +#include "quotesprovidervisitor.h" + +class CQuotesProviderVisitorTendency : public CQuotesProviderVisitor +{ +public: + CQuotesProviderVisitorTendency(HANDLE hContact,TCHAR chr); + + bool IsValid()const{return m_bValid;} + double GetResult()const{return m_dResult;} + +private: + virtual void Visit(const CQuotesProviderBase& rProvider); + virtual void Visit(const CQuotesProviderGoogleFinance& rProvider); + virtual void Visit(const CQuotesProviderYahoo& rProvider); + +private: + void GetValue(LPCSTR pszDbKeyName); + +private: + HANDLE m_hContact; + TCHAR m_chr; + bool m_bValid; + double m_dResult; +}; + +#endif //__AD721194_E9944366_9CF1_0307460EF32F_QuotesProviderVisitorTendency_h__ diff --git a/plugins/Quotes/src/QuotesProviderYahoo.cpp b/plugins/Quotes/src/QuotesProviderYahoo.cpp new file mode 100644 index 0000000000..35edb3207c --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderYahoo.cpp @@ -0,0 +1,193 @@ +#include "stdafx.h" +#include "QuotesProviderYahoo.h" +#include "QuotesProviderVisitor.h" +#include "ModuleInfo.h" +#include "DBUtils.h" +#include "EconomicRateInfo.h" +#include "HTTPSession.h" + +namespace +{ + void remove_quotes(tstring& s) + { + if (*s.begin() == _T('"')) + { + s.erase(s.begin()); + } + if (*s.rbegin() == _T('"')) + { + tstring::iterator i(s.begin()); + std::advance(i,s.size()-1); + s.erase(i); + } + } + + void remove_end_of_line(tstring& s) + { + if (*s.rbegin() == _T('\n')) + { + tstring::iterator i(s.begin()); + std::advance(i,s.size()-1); + s.erase(i); + } + if (*s.rbegin() == _T('\r')) + { + tstring::iterator i(s.begin()); + std::advance(i,s.size()-1); + s.erase(i); + } + } + + bool t2d(const tstring& s,double& d) + { + tistringstream stream(s); + stream >> d; + return ((false == stream.fail()) && (false == stream.bad())); +// try +// { +// d = boost::lexical_cast(s); +// return true; +// } +// catch(boost::bad_lexical_cast& e) +// { +// } +// return false; + } + + typedef std::vector 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 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/plugins/Quotes/src/QuotesProviderYahoo.h b/plugins/Quotes/src/QuotesProviderYahoo.h new file mode 100644 index 0000000000..feadefbca4 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviderYahoo.h @@ -0,0 +1,20 @@ +#ifndef __E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__ +#define __E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__ + +#include "QuotesProviderFinance.h" + + +#define DB_STR_YAHOO_OPEN_VALUE "OpenQuotePrice" +#define DB_STR_YAHOO_DAY_HIGH "DayHigh" +#define DB_STR_YAHOO_DAY_LOW "DayLow" +#define DB_STR_YAHOO_PREVIOUS_CLOSE "PreviousClose" +#define DB_STR_YAHOO_CHANGE "Change" + +class CQuotesProviderYahoo : public CQuotesProviderFinance +{ +private: + virtual void RefreshQuotes(TContracts& anContacts); + virtual void Accept(CQuotesProviderVisitor& visitor)const; +}; + +#endif //__E927F394_5452_458E_AF48_71E44F9EE793_QuotesProviderYahoo_h__ diff --git a/plugins/Quotes/src/QuotesProviders.cpp b/plugins/Quotes/src/QuotesProviders.cpp new file mode 100644 index 0000000000..26cbb067ea --- /dev/null +++ b/plugins/Quotes/src/QuotesProviders.cpp @@ -0,0 +1,119 @@ +#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 +{ + templatevoid create_provider(CQuotesProviders::TQuotesProviders& apProviders) + { + CQuotesProviders::TQuotesProviderPtr pProvider(new T); + if(pProvider->Init()) + { + apProviders.push_back(pProvider); + } + } +} + +void CQuotesProviders::CreateProviders() +{ + create_provider(m_apProviders); + create_provider(m_apProviders); + create_provider(m_apProviders); + create_provider(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(lmDisabled)); + if ((dwLogMode&lmInternalHistory) || (dwLogMode&lmExternalFile)) + { + DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,1); + } + } +} +void CQuotesProviders::InitProviders() +{ + CreateProviders(); + + const WORD nCurrentVersion = 17; + WORD nVersion = DBGetContactSettingWord(NULL,QUOTES_MODULE_NAME,LAST_RUN_VERSION,1); + + for(HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) + { + TQuotesProviderPtr pProvider = GetContactProviderPtr(hContact); + if(pProvider) + { + pProvider->AddContact(hContact); + if(nVersion < nCurrentVersion) + { + convert_contact_settings(hContact); + } + } + } + + DBWriteContactSettingWord(NULL,QUOTES_MODULE_NAME,LAST_RUN_VERSION,nCurrentVersion); +} + +CQuotesProviders::TQuotesProviderPtr CQuotesProviders::GetContactProviderPtr(HANDLE hContact)const +{ + char* szProto = GetContactProto(hContact); + 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/plugins/Quotes/src/QuotesProviders.h b/plugins/Quotes/src/QuotesProviders.h new file mode 100644 index 0000000000..02aa5184c9 --- /dev/null +++ b/plugins/Quotes/src/QuotesProviders.h @@ -0,0 +1,32 @@ +#ifndef __148306d1_da2a_43df_b1ad_0cdc8ef8a79e_QuotesProviders_h__ +#define __148306d1_da2a_43df_b1ad_0cdc8ef8a79e_QuotesProviders_h__ + +#include +#include + +class IQuotesProvider; + +class CQuotesProviders +{ +public: + typedef boost::shared_ptr TQuotesProviderPtr; + typedef std::vector 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/plugins/Quotes/src/SettingsDlg.cpp b/plugins/Quotes/src/SettingsDlg.cpp new file mode 100644 index 0000000000..0011d2e917 --- /dev/null +++ b/plugins/Quotes/src/SettingsDlg.cpp @@ -0,0 +1,1148 @@ +#include "StdAfx.h" +#include "SettingsDlg.h" +#include "EconomicRateInfo.h" +#include "ModuleInfo.h" +#include "WinCtrlHelper.h" +#include "CreateFilePath.h" +#include "QuotesProviderVisitorDbSettings.h" +#include "DBUtils.h" +#include "resource.h" +#include "QuotesProviders.h" +#include "IQuotesProvider.h" + +#define WINDOW_PREFIX_SETTINGS "Edit Settings_" + +namespace +{ + LPCTSTR g_pszVariableQuoteName = _T("%quotename%"); + LPCTSTR g_pszVariableUserProfile = _T("%miranda_userdata%"); + + void update_file_controls(HWND hDlg) + { + bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_EXTERNAL_FILE)); + + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_FILE_NAME),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_SELECT_FILE),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_BROWSE),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_LOG_FILE_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_LOG_FILE_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_LOG_FILE_DESCRIPTION),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_LOG_FILE_CONDITION),bEnable); + } + + void update_history_controls(HWND hDlg) + { + bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_INTERNAL_HISTORY)); + + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_HISTORY_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_HISTORY_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_HISTORY_DESCRIPTION),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_HISTORY_CONDITION),bEnable); + } + + void update_popup_controls(HWND hDlg) + { + bool bEnable = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_SHOW_POPUP)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),bEnable); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),bEnable); + } + + bool enable_popup_controls(HWND hDlg) + { + bool bIsPopupServiceEnabled = 1 == ServiceExists(MS_POPUP_ADDPOPUPT); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP),bIsPopupServiceEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),bIsPopupServiceEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),bIsPopupServiceEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),bIsPopupServiceEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),bIsPopupServiceEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),bIsPopupServiceEnabled); + + return bIsPopupServiceEnabled; + } + + void update_all_controls(HWND hDlg) + { + bool bIsCheckedContactSpec = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_CONTACT_SPECIFIC)); + bool bIsCheckedExternal = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_EXTERNAL_FILE)); + + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_EXTERNAL_FILE),bIsCheckedContactSpec); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_FILE_NAME),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_SELECT_FILE),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_BROWSE),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_LOG_FILE_FORMAT),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_LOG_FILE_FORMAT),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_LOG_FILE_DESCRIPTION),(bIsCheckedContactSpec&&bIsCheckedExternal)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_LOG_FILE_CONDITION),(bIsCheckedContactSpec&&bIsCheckedExternal)); + + bool bIsCheckedHistory = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_INTERNAL_HISTORY)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_INTERNAL_HISTORY),bIsCheckedContactSpec); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_HISTORY_FORMAT),(bIsCheckedContactSpec&&bIsCheckedHistory)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_HISTORY_FORMAT),(bIsCheckedContactSpec&&bIsCheckedHistory)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_HISTORY_DESCRIPTION),(bIsCheckedContactSpec&&bIsCheckedHistory)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_HISTORY_CONDITION),(bIsCheckedContactSpec&&bIsCheckedHistory)); + + bool bIsPopupServiceEnabled = 1 == ServiceExists(MS_POPUP_ADDPOPUPT); + bool bIsCheckedShowPopup = (1 == ::IsDlgButtonChecked(hDlg,IDC_CHECK_SHOW_POPUP)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP),(bIsCheckedContactSpec&&bIsPopupServiceEnabled)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_EDIT_POPUP_FORMAT),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_STATIC_POPUP_FORMAT),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_FORMAT_DESCRIPTION),(bIsCheckedContactSpec&&bIsPopupServiceEnabled&&bIsCheckedShowPopup)); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BUTTON_POPUP_SETTINGS),(bIsCheckedContactSpec&&bIsPopupServiceEnabled)); + } + + std::vector get_filter() + { + std::vector 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 aFileBuffer(_MAX_PATH*2,_T('\0')); +// std::copy(sFileName.begin(),sFileName.end(),aFileBuffer.begin()); + LPTSTR pszFile = &*aFileBuffer.begin(); + + std::vector aFilterBuffer = get_filter(); + LPCTSTR pszFilter = &*aFilterBuffer.begin(); + + OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFile = pszFile; + ofn.nMaxFile = (DWORD)aFileBuffer.size(); + ofn.lpstrFilter = pszFilter; + ofn.nFilterIndex = 1; + ofn.hInstance = g_hInstance; + ofn.lpstrDefExt = _T("log"); +// ofn.lpstrFileTitle = NULL; +// ofn.nMaxFileTitle = 0; +// ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_EXPLORER; + + BOOL b = GetOpenFileName(&ofn); + if(TRUE == b) + { + SetDlgItemText(hDlg,IDC_EDIT_FILE_NAME,ofn.lpstrFile); + } + } + + struct CSettingWindowParam + { + CSettingWindowParam(HANDLE hContact) : m_hContact(hContact),m_pPopupSettings(NULL){} + ~CSettingWindowParam(){delete m_pPopupSettings;} + + HANDLE m_hContact; + CPopupSettings* m_pPopupSettings; + }; + + inline CSettingWindowParam* get_param(HWND hWnd) + { + return reinterpret_cast(GetWindowLongPtr(hWnd,GWLP_USERDATA)); + } + + +// inline HANDLE get_contact(HWND hWnd) +// { +// return reinterpret_cast(GetWindowLongPtr(hWnd,GWLP_USERDATA)); +// } + + void update_popup_controls_settings(HWND hDlg) + { + bool bIsColoursEnabled = 1 == IsDlgButtonChecked(hDlg,IDC_RADIO_USER_DEFINED_COLOURS); + ::EnableWindow(::GetDlgItem(hDlg,IDC_BGCOLOR),bIsColoursEnabled); + ::EnableWindow(::GetDlgItem(hDlg,IDC_TEXTCOLOR),bIsColoursEnabled); + + bool bIsDelayEnabled = 1 == IsDlgButtonChecked(hDlg,IDC_DELAYCUSTOM); + ::EnableWindow(::GetDlgItem(hDlg,IDC_DELAY),bIsDelayEnabled); + + } + + INT_PTR CALLBACK EditPopupSettingsDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) + { + switch(msg) + { + case WM_INITDIALOG: + { + CPopupSettings* pSettings = reinterpret_cast(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(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(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(::SendDlgItemMessage(hWnd,IDC_BGCOLOR,CPM_GETCOLOUR,0,0))); + pSettings->SetColourText(static_cast(::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(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(pParam)); + Utils_RestoreWindowPositionNoSize(hWnd,hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_SETTINGS); + ::ShowWindow(hWnd,SW_SHOW); + } + break; + case WM_COMMAND: + switch(LOWORD(wp)) + { + case IDC_BUTTON_HISTORY_DESCRIPTION: + case IDC_BUTTON_LOG_FILE_DESCRIPTION: + case IDC_BUTTON_POPUP_FORMAT_DESCRIPTION: + if(BN_CLICKED == HIWORD(wp)) + { + CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(get_param(hWnd)->m_hContact); + show_variable_list(hWnd,pProvider.get()); + } + break; + + case IDC_CHECK_CONTACT_SPECIFIC: + if(BN_CLICKED == HIWORD(wp)) + { + update_all_controls(hWnd); + } + break; + case IDC_CHECK_EXTERNAL_FILE: + if(BN_CLICKED == HIWORD(wp)) + { + update_file_controls(hWnd); + } + break; + case IDC_CHECK_INTERNAL_HISTORY: + if(BN_CLICKED == HIWORD(wp)) + { + update_history_controls(hWnd); + } + break; + case IDC_CHECK_SHOW_POPUP: + if(BN_CLICKED == HIWORD(wp)) + { + update_popup_controls(hWnd); + } + break; + case IDC_BUTTON_BROWSE: + if(BN_CLICKED == HIWORD(wp)) + { + select_log_file(hWnd); + } + break; + case IDC_BUTTON_POPUP_SETTINGS: + if(BN_CLICKED == HIWORD(wp)) + { + CSettingWindowParam* pParam = get_param(hWnd); + if (!pParam->m_pPopupSettings) + { + CQuotesProviders::TQuotesProviderPtr pProvider = CModuleInfo::GetQuoteProvidersPtr()->GetContactProviderPtr(pParam->m_hContact); + + pParam->m_pPopupSettings = new CPopupSettings(pProvider.get()); + pParam->m_pPopupSettings->InitForContact(pParam->m_hContact); + } + + DialogBoxParam(g_hInstance, + MAKEINTRESOURCE(IDD_DIALOG_POPUP), + hWnd, + EditPopupSettingsDlgProc,reinterpret_cast(pParam->m_pPopupSettings)); + } + break; + + case IDOK: + { + CSettingWindowParam* pParam = get_param(hWnd); + HANDLE hContact = pParam->m_hContact; + + bool bUseContactSpec = 1 == ::IsDlgButtonChecked(hWnd,IDC_CHECK_CONTACT_SPECIFIC); + + WORD nLogMode = lmDisabled; + UINT nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_EXTERNAL_FILE); + if(1 == nCheck) + { + nLogMode |= lmExternalFile; + } + + nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_INTERNAL_HISTORY); + if(1 == nCheck) + { + nLogMode |= lmInternalHistory; + } + + nCheck = ::IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP); + if(1 == nCheck) + { + nLogMode |= lmPopup; + } + + bool bOk = true; + HWND hwndLogFile = ::GetDlgItem(hWnd,IDC_EDIT_FILE_NAME); + HWND hwndLogFileFrmt = ::GetDlgItem(hWnd,IDC_EDIT_LOG_FILE_FORMAT); + HWND hwndHistoryFrmt = ::GetDlgItem(hWnd,IDC_EDIT_HISTORY_FORMAT); + tstring sLogFile = get_window_text(hwndLogFile); + tstring sLogFileFormat = get_window_text(hwndLogFileFrmt); + tstring sHistoryFormat = get_window_text(hwndHistoryFrmt); + if ((nLogMode&lmExternalFile)) + { + if(true == sLogFile.empty()) + { + prepare_edit_ctrl_for_error(hwndLogFile); + Quotes_MessageBox(hWnd,TranslateT("Enter log file name."),MB_OK|MB_ICONERROR); + bOk = false; + } + else if(true == sLogFileFormat.empty()) + { + prepare_edit_ctrl_for_error(hwndLogFileFrmt); + Quotes_MessageBox(hWnd,TranslateT("Enter log file format."),MB_OK|MB_ICONERROR); + bOk = false; + } + } + + if ((true == bOk) && (nLogMode&lmInternalHistory) && (true == sHistoryFormat.empty())) + { + prepare_edit_ctrl_for_error(hwndHistoryFrmt); + Quotes_MessageBox(hWnd,TranslateT("Enter history format."),MB_OK|MB_ICONERROR); + bOk = false; + } + + HWND hwndPopupFrmt = ::GetDlgItem(hWnd,IDC_EDIT_POPUP_FORMAT); + tstring sPopupFormat = get_window_text(hwndPopupFrmt); + if ((true == bOk) && (nLogMode&lmPopup) && (true == sPopupFormat.empty())) + { + prepare_edit_ctrl_for_error(hwndPopupFrmt); + Quotes_MessageBox(hWnd,TranslateT("Enter popup window format."),MB_OK|MB_ICONERROR); + bOk = false; + } + + if(true == bOk) + { + UINT nIfChangedHistory = IsDlgButtonChecked(hWnd,IDC_CHECK_HISTORY_CONDITION); + UINT nIfChangedFile = IsDlgButtonChecked(hWnd,IDC_CHECK_LOG_FILE_CONDITION); + bool bIfChangedPopup = (1 == IsDlgButtonChecked(hWnd,IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED)); + + DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_CONTACT_SPEC_SETTINGS,bUseContactSpec); + DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG,nLogMode); + DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE_CONDITION,nIfChangedFile); + DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_HISTORY_CONDITION,nIfChangedHistory); + DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_CONDITION,bIfChangedPopup); + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_LOG_FILE,sLogFile.c_str()); + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_LOG_FILE,sLogFileFormat.c_str()); + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_HISTORY,sHistoryFormat.c_str()); + DBWriteContactSettingTString(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_FORMAT_POPUP,sPopupFormat.c_str()); + + if(pParam->m_pPopupSettings) + { + pParam->m_pPopupSettings->SaveForContact(hContact); + } + + ::DestroyWindow(hWnd); + } + } + break; + case IDCANCEL: + DestroyWindow(hWnd); + break; + } + break; + case WM_CLOSE: + DestroyWindow(hWnd); + break; + case WM_DESTROY: + { + CSettingWindowParam* pParam = get_param(hWnd); + SetWindowLongPtr(hWnd,GWLP_USERDATA,0); + + HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_SETTINGS,false); + assert(hWL); + WindowList_Remove(hWL,hWnd); + Utils_SaveWindowPosition(hWnd,pParam->m_hContact,QUOTES_MODULE_NAME,WINDOW_PREFIX_SETTINGS); + delete pParam; + } + break; + } + + return FALSE; + } +} + + +void ShowSettingsDlg(HANDLE hContact) +{ + HANDLE hWL = CModuleInfo::GetInstance().GetWindowList(WINDOW_PREFIX_SETTINGS,true); + assert(hWL); + HWND hWnd = WindowList_Find(hWL,hContact); + if(NULL != hWnd) + { + SetForegroundWindow(hWnd); + SetFocus(hWnd); + } + else + { + CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_CONTACT_SETTINGS),NULL,EditSettingsPerContactDlgProc,reinterpret_cast(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(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(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(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(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(GetWindowLongPtr(hWnd,GWLP_USERDATA)); + DialogBoxParam(g_hInstance, + MAKEINTRESOURCE(IDD_DIALOG_POPUP), + hWnd, + EditPopupSettingsDlgProc,reinterpret_cast(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(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(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(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(m_modeColour)); + if(m >= colourDefault && m <= colourUserDefined) + { + m_modeColour = static_cast(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(m_modeDelay)); + if(m >= delayFromPopup && m <= delayPermanent) + { + m_modeDelay = static_cast(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(m_modeColour)); + if(m >= CPopupSettings::colourDefault && m <= CPopupSettings::colourUserDefined) + { + m_modeColour = static_cast(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(m_modeDelay)); + if(m >= CPopupSettings::delayFromPopup && m <= CPopupSettings::delayPermanent) + { + m_modeDelay = static_cast(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(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(m_modeDelay)); + DBWriteContactSettingWord(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_DELAY_TIMEOUT,m_wDelay); + DBWriteContactSettingByte(hContact,QUOTES_PROTOCOL_NAME,DB_STR_QUOTE_POPUP_HISTORY_FLAG,m_bUseHistory); +} + +CPopupSettings::EColourMode CPopupSettings::GetColourMode()const +{ + return m_modeColour; +} + +void CPopupSettings::SetColourMode(EColourMode nMode) +{ + m_modeColour = nMode; +} + +COLORREF CPopupSettings::GetColourBk()const +{ + return m_rgbBkg; +} + +void CPopupSettings::SetColourBk(COLORREF rgb) +{ + m_rgbBkg = rgb; +} + +COLORREF CPopupSettings::GetColourText()const +{ + return m_rgbText; +} + +void CPopupSettings::SetColourText(COLORREF rgb) +{ + m_rgbText = rgb; +} + +CPopupSettings::EDelayMode CPopupSettings::GetDelayMode()const +{ + return m_modeDelay; +} + +void CPopupSettings::SetDelayMode(EDelayMode nMode) +{ + m_modeDelay = nMode; +} + +WORD CPopupSettings::GetDelayTimeout()const +{ + return m_wDelay; +} + +void CPopupSettings::SetDelayTimeout(WORD delay) +{ + m_wDelay = delay; +} + +bool CPopupSettings::GetHistoryFlag()const +{ + return m_bUseHistory; +} + +void CPopupSettings::SetHistoryFlag(bool flag) +{ + m_bUseHistory = flag; +} + +bool ShowSettingsDlg(HWND hWndParent,CAdvProviderSettings* pAdvSettings) +{ + assert(pAdvSettings); + + return (IDOK == DialogBoxParam(g_hInstance, + MAKEINTRESOURCE(IDD_PROVIDER_ADV_SETTINGS), + hWndParent, + EditSettingsPerProviderDlgProc, + reinterpret_cast(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(CallService(MS_UTILS_REPLACEVARS, + reinterpret_cast(sPath.c_str()),reinterpret_cast(&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/plugins/Quotes/src/SettingsDlg.h b/plugins/Quotes/src/SettingsDlg.h new file mode 100644 index 0000000000..569d0b7d2c --- /dev/null +++ b/plugins/Quotes/src/SettingsDlg.h @@ -0,0 +1,118 @@ +#ifndef __E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__ +#define __E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__ + +class IQuotesProvider; + +class CPopupSettings +{ +public: + enum EColourMode + { + colourDefault, + colourUserDefined, + }; + + enum EDelayMode + { + delayFromPopup, + delayCustom, + delayPermanent + }; + +public: + CPopupSettings(const IQuotesProvider* pQuotesProvider); + + static COLORREF GetDefColourBk(); + static COLORREF GetDefColourText(); + + void InitForContact(HANDLE hContact); + void SaveForContact(HANDLE hContact)const; + + EColourMode GetColourMode()const; + void SetColourMode(EColourMode nMode); + + COLORREF GetColourBk()const; + void SetColourBk(COLORREF rgb); + + COLORREF GetColourText()const; + void SetColourText(COLORREF rgb); + + EDelayMode GetDelayMode()const; + void SetDelayMode(EDelayMode nMode); + + WORD GetDelayTimeout()const; + void SetDelayTimeout(WORD delay); + + bool GetHistoryFlag()const; + void SetHistoryFlag(bool flag); + +private: + EColourMode m_modeColour; + EDelayMode m_modeDelay; + COLORREF m_rgbBkg; + COLORREF m_rgbText; + WORD m_wDelay; + bool m_bUseHistory; +}; + + +class CAdvProviderSettings +{ +public: + CAdvProviderSettings(const IQuotesProvider* pQuotesProvider); + ~CAdvProviderSettings(); + + void SaveToDb()const; + + const IQuotesProvider* GetProviderPtr()const; + + WORD GetLogMode()const; + void SetLogMode(WORD wMode); + tstring GetHistoryFormat()const; + void SetHistoryFormat(const tstring& rsFormat); + bool GetHistoryOnlyChangedFlag()const; + void SetHistoryOnlyChangedFlag(bool bMode); + + tstring GetLogFileName()const; + void SetLogFileName(const tstring& rsFile); + tstring GetLogFormat()const; + void SetLogFormat(const tstring& rsFormat); + bool GetLogOnlyChangedFlag()const; + void SetLogOnlyChangedFlag(bool bMode); + + const tstring& GetPopupFormat() const; + void SetPopupFormat(const tstring& val); + + bool GetShowPopupIfValueChangedFlag() const; + void SetShowPopupIfValueChangedFlag(bool val); + + CPopupSettings* GetPopupSettingsPtr()const; + +private: + const IQuotesProvider* m_pQuotesProvider; + WORD m_wLogMode; + tstring m_sFormatHistory; + bool m_bIsOnlyChangedHistory; + tstring m_sLogFileName; + tstring m_sFormatLogFile; + bool m_bIsOnlyChangedLogFile; + tstring m_sPopupFormat; + bool m_bShowPopupIfValueChanged; + mutable CPopupSettings* m_pPopupSettings; +}; + +void ShowSettingsDlg(HANDLE hContact); +bool ShowSettingsDlg(HWND hWndParent,CAdvProviderSettings* pAdvSettings); + +enum +{ + glfnResolveQuoteName = 0x0001, + glfnResolveUserProfile = 0x0002, + glfnResolveAll = glfnResolveQuoteName|glfnResolveUserProfile, +}; +tstring GenerateLogFileName(const tstring& rsLogFilePattern,const tstring& rsQuoteSymbol,int nFlags = glfnResolveAll); +tstring GetContactLogFileName(HANDLE hContact); +tstring GetContactName(HANDLE hContact); + +#endif //__E211E4D9_383C_43BE_A787_7EF1D585B90D_SettingsDlg_h__ + diff --git a/plugins/Quotes/src/WinCtrlHelper.cpp b/plugins/Quotes/src/WinCtrlHelper.cpp new file mode 100644 index 0000000000..619fe3d41b --- /dev/null +++ b/plugins/Quotes/src/WinCtrlHelper.cpp @@ -0,0 +1,49 @@ +#include "stdafx.h" +#include "QuotesProviderVisitorFormatSpecificator.h" +#include "IQuotesProvider.h" +#include "resource.h" +#include "ModuleInfo.h" + +namespace +{ + INT_PTR CALLBACK VariableListDlgProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) + { + switch(msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hWnd); + const IQuotesProvider* pProvider = reinterpret_cast(lp); + CQuotesProviderVisitorFormatSpecificator visitor; + pProvider->Accept(visitor); + + tostringstream o; + const CQuotesProviderVisitorFormatSpecificator::TFormatSpecificators& raSpec = visitor.GetSpecificators(); + std::for_each(raSpec.begin(),raSpec.end(), + [&o](const CQuotesProviderVisitorFormatSpecificator::CFormatSpecificator& spec) + { + o << spec.m_sSymbol << _T('\t') << spec.m_sDesc << _T("\r\n"); + }); + ::SetDlgItemText(hWnd,IDC_EDIT_VARIABLE,o.str().c_str()); + } + break; + case WM_COMMAND: + if(BN_CLICKED == HIWORD(wp) && (IDOK == LOWORD(wp) || IDCANCEL == LOWORD(wp))) + { + ::EndDialog(hWnd,IDOK); + } + break; + } + + return FALSE; + } +} + +void show_variable_list(HWND hwndParent,const IQuotesProvider* pProvider) +{ + ::DialogBoxParam(g_hInstance, + MAKEINTRESOURCE(IDD_DIALOG_VARIABLE_LIST), + hwndParent, + VariableListDlgProc, + reinterpret_cast(pProvider)); +} diff --git a/plugins/Quotes/src/WinCtrlHelper.h b/plugins/Quotes/src/WinCtrlHelper.h new file mode 100644 index 0000000000..d7f8957a86 --- /dev/null +++ b/plugins/Quotes/src/WinCtrlHelper.h @@ -0,0 +1,37 @@ +#ifndef __a05d6852_4497_4f28_85e1_48a15a170738_WinCtrlHelper_h__ +#define __a05d6852_4497_4f28_85e1_48a15a170738_WinCtrlHelper_h__ + +class IQuotesProvider; + +inline tstring get_window_text(HWND hWnd) +{ + int cBytes = ::GetWindowTextLength(hWnd); + + std::vector 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/plugins/Quotes/src/WorkingThread.cpp b/plugins/Quotes/src/WorkingThread.cpp new file mode 100644 index 0000000000..bc4d80b734 --- /dev/null +++ b/plugins/Quotes/src/WorkingThread.cpp @@ -0,0 +1,15 @@ +#include "StdAfx.h" +#include "WorkingThread.h" + +#include "IQuotesProvider.h" + +void WorkingThread(void* pParam) +{ + IQuotesProvider* pProvider = reinterpret_cast(pParam); + assert(pProvider); + + if(pProvider) + { + pProvider->Run(); + } +} diff --git a/plugins/Quotes/src/WorkingThread.h b/plugins/Quotes/src/WorkingThread.h new file mode 100644 index 0000000000..a77734bb85 --- /dev/null +++ b/plugins/Quotes/src/WorkingThread.h @@ -0,0 +1,6 @@ +#ifndef __cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__ +#define __cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__ + +void WorkingThread(void* pParam); + +#endif //__cd52f1a3_63b2_44f0_a0a9_48c203958fa4_WorkingThread_h__ diff --git a/plugins/Quotes/src/XMLEngineMI.cpp b/plugins/Quotes/src/XMLEngineMI.cpp new file mode 100644 index 0000000000..7e2adfb7d9 --- /dev/null +++ b/plugins/Quotes/src/XMLEngineMI.cpp @@ -0,0 +1,230 @@ +#include "StdAfx.h" +#include "XMLEngineMI.h" + +XML_API xi; + +namespace +{ + class CXMLNodeMI : public IXMLNode, + private boost::noncopyable + { + public: + typedef boost::shared_ptr 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(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 ss(xi.toString(m_hXML,NULL)); + if(ss.m_p) + { + mir_safe_string 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 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(st.st_size)) + { + pBuffer[cBytes] = '\0'; + + int nLen = (int)cBytes; + mir_safe_string 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(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/plugins/Quotes/src/XMLEngineMI.h b/plugins/Quotes/src/XMLEngineMI.h new file mode 100644 index 0000000000..5e5a51232f --- /dev/null +++ b/plugins/Quotes/src/XMLEngineMI.h @@ -0,0 +1,17 @@ +#ifndef __0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__ +#define __0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__ + +#include "ixmlengine.h" + +class CXMLEngineMI : public IXMLEngine +{ +public: + CXMLEngineMI(); + ~CXMLEngineMI(); + + virtual IXMLNode::TXMLNodePtr LoadFile(const tstring& rsFileName)const; + virtual bool SaveFile(const tstring& rsFileName,const IXMLNode::TXMLNodePtr& pNode)const; + virtual IXMLNode::TXMLNodePtr CreateNode(const tstring& rsName,const tstring& rsText)const; +}; + +#endif //__0c3d1da4_92b7_431c_83e5_f998cd513f0d_XMLEngineMI_h__ diff --git a/plugins/Quotes/src/resource.h b/plugins/Quotes/src/resource.h new file mode 100644 index 0000000000..50ee0a637b --- /dev/null +++ b/plugins/Quotes/src/resource.h @@ -0,0 +1,109 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Forex.rc +// +#define IDD_DIALOG_ECONOMIC_RATES 101 +#define IDI_ICON_MAIN 102 +#define IDD_DIALOG_QUOTE_INFO 102 +#define IDD_DIALOG_OPT_GOOGLE 103 +#define IDI_ICON_SECTION 110 +#define IDI_ICON_QUOTE 111 +#define IDI_ICON_UP 113 +#define IDI_ICON_DOWN 114 +#define IDD_CONTACT_SETTINGS 115 +#define IDI_ICON_NOTCHANGED 116 +#define IDD_CURRENCY_CONVERTER 116 +#define IDI_ICON_CURRENCY_CONVERTER 117 +#define IDD_DUKASCOPY_CHART 117 +#define IDD_CHART 117 +#define IDD_DIALOG_QUOTE_INFO_1 118 +#define IDI_ICON_REFRESH 118 +#define IDD_DIALOG_OPT_FINANCE 119 +#define IDI_ICON_IMPORT 119 +#define IDI_ICON_EXPORT 120 +#define IDD_PROVIDER_ADV_SETTINGS 120 +#define IDI_ICON_SWAP 121 +#define IDD_DIALOG_POPUP 121 +#define IDD_DIALOG_VARIABLE_LIST 123 +#define IDC_TREE_ECONOMIC_RATES 1001 +#define IDC_EDIT_REFRESH_RATE 1002 +#define IDC_SPIN_REFRESH_RATE 1003 +#define IDC_COMBO_REFRESH_RATE 1004 +#define IDC_STATIC_QUOTE_NAME 1008 +#define IDC_SYSLINK_PROVIDER 1009 +#define IDC_STATIC_CHART 1010 +#define IDC_STATIC_QUOTE_CHART 1010 +#define IDC_COMBO_CONVERT_FROM 1011 +#define IDC_COMBO_CONVERT_INTO 1012 +#define IDC_BUTTON_ADD 1013 +#define IDC_LIST_RATES 1014 +#define IDC_BUTTON_REMOVE 1015 +#define IDC_EDIT_RATE 1016 +#define IDC_EDIT_RATE_FETCH_TIME 1017 +#define IDC_EDIT_CONTACT_LIST_FORMAT 1018 +#define IDC_EDIT_PREVIOUS_RATE 1018 +#define IDC_BUTTON_DESCRIPTION 1019 +#define IDC_CHECK_INTERNAL_HISTORY 1020 +#define IDC_EDIT_STATUS_MESSAGE_FORMAT 1020 +#define IDC_CHECK_EXTERNAL_FILE 1021 +#define IDC_EDIT_FILE_NAME 1022 +#define IDC_EDIT_TENDENCY_FORMAT 1022 +#define IDC_BUTTON_BROWSE 1023 +#define IDC_STATIC_SELECT_FILE 1024 +#define IDC_EDIT_NAME 1025 +#define IDC_EDIT_HISTORY_FORMAT 1026 +#define IDC_EDIT_LOG_FILE_FORMAT 1027 +#define IDC_BUTTON_DESCRIPTION2 1028 +#define IDC_BUTTON_LOG_FILE_DESCRIPTION 1028 +#define IDC_STATIC_HISTORY_FORMAT 1029 +#define IDC_BUTTON_HISTORY_DESCRIPTION 1030 +#define IDC_STATIC_LOG_FILE_FORMAT 1031 +#define IDC_CHECK_HISTORY_CONDITION 1032 +#define IDC_CHECK_LOG_CONDITION2 1033 +#define IDC_CHECK_LOG_FILE_CONDITION 1033 +#define IDC_EDIT_VALUE 1033 +#define IDC_BUTTON_CONVERT 1034 +#define IDC_CHECK_SHOW_POPUP_ONLY_VALUE_CHANGED 1034 +#define IDC_STATIC_POPUP_FORMAT 1035 +#define IDC_EDIT_POPUP_FORMAT 1036 +#define IDC_BUTTON_LOG_FILE_DESCRIPTION2 1037 +#define IDC_BUTTON_POPUP_FORMAT_DESCRIPTION 1037 +#define IDC_EDIT_RESULT 1039 +#define IDC_STATIC_IMAGE 1056 +#define IDC_EDIT_QUOTE 1059 +#define IDC_BUTTON_SWAP 1060 +#define IDC_BUTTON_ADVANCED_SETTINGS 1061 +#define IDC_BUTTON_POPUP_SETTINGS 1061 +#define IDC_CHECK_CONTACT_SPECIFIC 1062 +#define IDC_RADIO_DEFAULT_COLOURS 1063 +#define IDC_CHECK_SHOW_POPUP 1064 +#define IDC_RADIO_USER_DEFINED_COLOURS 1064 +#define IDC_MFCCOLORBUTTON1 1066 +#define IDC_CHECK1 1067 +#define IDC_CHECK_DONT_USE_POPUPHISTORY 1067 +#define IDC_COMBO_DATA_SOURCE 1068 +#define IDC_COMBO_FILTER 1069 +#define IDC_EDIT_FROM 1070 +#define IDC_EDIT_FROM2 1071 +#define IDC_EDIT_TO 1071 +#define IDC_STATIC_PROVIDER_NAME 1071 +#define IDC_DELAY 1072 +#define IDC_EDIT1 1072 +#define IDC_EDIT_VARIABLE 1072 +#define IDC_BGCOLOR 1074 +#define IDC_TEXTCOLOR 1075 +#define IDC_PREV 1076 +#define IDC_DELAYFROMPU 1093 +#define IDC_DELAYCUSTOM 1094 +#define IDC_DELAYPERMANENT 1095 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 124 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1073 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/Quotes/src/stdafx.cpp b/plugins/Quotes/src/stdafx.cpp new file mode 100644 index 0000000000..e4738d8f60 --- /dev/null +++ b/plugins/Quotes/src/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Forex.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/plugins/Quotes/src/stdafx.h b/plugins/Quotes/src/stdafx.h new file mode 100644 index 0000000000..5e72bc0e0b --- /dev/null +++ b/plugins/Quotes/src/stdafx.h @@ -0,0 +1,154 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" +#define MIRANDA_VER 0x0A00 +// #define CHART_IMPLEMENT +#define TEST_IMPORT_EXPORT + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Miranda headers +#pragma warning(disable: 4996) +#include +#include +#include +#include +#pragma warning(default: 4996) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// boost headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boost/date_time/c_local_time_adjustor.hpp" + +// stl headers +#include +#include +#include +#include +#include +#include + + +typedef std::wstring tstring; +typedef std::wostringstream tostringstream; +typedef std::wistringstream tistringstream; +typedef std::wofstream tofstream; +typedef std::wifstream tifstream; +typedef std::wostream tostream; +typedef std::wistream tistream; +typedef boost::posix_time::wtime_input_facet ttime_input_facet; +typedef boost::posix_time::wtime_facet ttime_facet; + +inline int quotes_stricmp(LPCTSTR p1,LPCTSTR p2) +{ + return _tcsicmp(p1,p2); +} + +inline std::string quotes_t2a(const TCHAR* t) +{ + std::string s; + char* p = mir_t2a(t); + if(p) + { + s = p; + mir_free(p); + } + return s; +} + +inline tstring quotes_a2t(const char* s) +{ + tstring t; + TCHAR* p = mir_a2t(s); + if(p) + { + t = p; + mir_free(p); + } + return t; +} +namespace detail +{ + template 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 struct MirandaFree + { + static void dealloc(T* p){mir_free(p);} + }; + + template struct OwnerFree + { + static void dealloc(T* p){::free(p);} + }; +} + +template struct mir_safe_string : public detail::safe_string_impl> +{ + mir_safe_string(PTR p) : detail::safe_string_impl>(p){} +}; + +template struct safe_string : public detail::safe_string_impl> +{ + safe_string(PTR p) : detail::safe_string_impl>(p){} +}; + +extern HINSTANCE g_hInstance; + +// #ifdef MIRANDA_VER +// #undef MIRANDA_VER +// #endif + +// TODO: reference additional headers your program requires here diff --git a/plugins/Quotes/src/targetver.h b/plugins/Quotes/src/targetver.h new file mode 100644 index 0000000000..f583181dfd --- /dev/null +++ b/plugins/Quotes/src/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/plugins/Quotes/src/version.h b/plugins/Quotes/src/version.h new file mode 100644 index 0000000000..a80f032948 --- /dev/null +++ b/plugins/Quotes/src/version.h @@ -0,0 +1,21 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 0 +#define __RELEASE_NUM 24 +#define __BUILD_NUM 0 + +#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM + +#define __STRINGIFY_IMPL(x) #x +#define __STRINGIFY(x) __STRINGIFY_IMPL(x) +#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) + +#define __PLUGIN_NAME "Quotes" +#define __INTERNAL_NAME "Quotes" +#define __FILENAME "Quotes.dll" +#define __DESCRIPTION "Shows currency rates and economic quotes." +#define __AUTHOR "Dioksin" +#define __AUTHOREMAIL "dioksin@ua.fm" +#define __AUTHORWEB "http://miranda-ng.org/" +#define __COPYRIGHT "Don't worry!" +#define SPECIAL_BUILD_STRING "5388" -- cgit v1.2.3