From 162e60d66c78bd51aa44c691fe4f4e2f1deb990f Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sat, 19 May 2012 14:24:27 +0000 Subject: added Quotes git-svn-id: http://svn.miranda-ng.org/main/trunk@76 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Quotes/Forex.cpp | 523 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 plugins/Quotes/Forex.cpp (limited to 'plugins/Quotes/Forex.cpp') diff --git a/plugins/Quotes/Forex.cpp b/plugins/Quotes/Forex.cpp new file mode 100644 index 0000000000..a661958302 --- /dev/null +++ b/plugins/Quotes/Forex.cpp @@ -0,0 +1,523 @@ +// 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 +#include "QuoteInfoDlg.h" +#include "ModuleInfo.h" +#include "QuotesProviders.h" +#include "IQuotesProvider.h" +#include "EconomicRateInfo.h" +#include "DBUtils.h" +#include "ExtraImages.h" +#include "HTTPSession.h" +#include "CurrencyConverter.h" +#ifdef CHART_IMPLEMENT +#include "QuoteChart.h" +#endif +#include "WinCtrlHelper.h" +#include "ImportExport.h" +#include "m_Quotes.h" +#include "version.h" + +PLUGINLINK* pluginLink = NULL; +struct MM_INTERFACE mmi; +struct UTF8_INTERFACE utfi; +int hLangpack; + +HANDLE g_hEventWorkThreadStop; +int g_nStatus = ID_STATUS_OFFLINE; +HGENMENU g_hMenuEditSettings = NULL; +HGENMENU g_hMenuOpenLogFile = NULL; +#ifdef CHART_IMPLEMENT +HGENMENU g_hMenuChart = NULL; +#endif +HGENMENU g_hMenuRefresh = NULL; + +namespace +{ + typedef std::vector 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, + 0 +#ifdef _UNICODE + // {E882056D-0D1D-4131-9A98-404CBAEA6A9C} + ,{0xe882056d, 0xd1d, 0x4131, { 0x9a, 0x98, 0x40, 0x4c, 0xba, 0xea, 0x6a, 0x9c } } +#else + // {8CE16273-89EA-4e12-8CF1-2D38AB6BF431} + ,{0x8ce16273, 0x89ea, 0x4e12, { 0x8c, 0xf1, 0x2d, 0x38, 0xab, 0x6b, 0xf4, 0x31 } } +#endif + }; + + INT_PTR QuotesMenu_RefreshAll(WPARAM wp,LPARAM lp) + { + const CQuotesProviders::TQuotesProviders& apProviders = CModuleInfo::GetQuoteProvidersPtr()->GetProviders(); + std::for_each(apProviders.begin(),apProviders.end(),boost::bind(&IQuotesProvider::RefreshAll,_1)); + return 0; + } + + void InitMenu() + { +// USES_CONVERSION; + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(CLISTMENUITEM); + //mi.ptszPopupName = _T("Quotes"); + mi.ptszName = _T("Quotes"); + mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTPOPUP; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + HGENMENU hMenuRoot = reinterpret_cast(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast(&mi))); + g_ahMenus.push_back(hMenuRoot); + + mi.ptszName = _T("Refresh All Quotes\\Rates"); + mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + //mi.position = 0x0FFFFFFF; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + mi.pszService = "Quotes/RefreshAll"; + mi.hParentMenu = hMenuRoot; + HGENMENU hMenu = reinterpret_cast(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast(&mi))); + g_ahMenus.push_back(hMenu); + HANDLE h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshAll); + g_ahServices.push_back(h); + + mi.ptszName = _T("Currency Converter..."); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + //mi.position = 0x0FFFFFFF; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_CURRENCY_CONVERTER); + mi.pszService = "Quotes/CurrencyConverter"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast(&mi))); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_CurrencyConverter); + g_ahServices.push_back(h); + +#ifdef TEST_IMPORT_EXPORT + mi.ptszName = _T("Export All Quotes"); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_EXPORT); + mi.pszService = "Quotes/ExportAll"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast(&mi))); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_ExportAll); + g_ahServices.push_back(h); + + mi.ptszName =_T("Import All Quotes"); + //mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_IMPORT); + mi.pszService = "Quotes/ImportAll"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDMAINMENUITEM,0,reinterpret_cast(&mi))); + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_ImportAll); + g_ahServices.push_back(h); +#endif + + bool bSubGroups = 1 == ServiceExists(MS_CLIST_ADDSUBGROUPMENUITEM); + + h = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,Quotes_PrebuildContactMenu); + g_ahEvents.push_back(h); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.pszContactOwner = QUOTES_PROTOCOL_NAME; + hMenuRoot = NULL; + if(bSubGroups) + { + mi.pszPopupName=(char *)-1; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_MAIN); + mi.flags = CMIF_ICONFROMICOLIB|CMIF_TCHAR|CMIF_ROOTPOPUP; + tstring sProtocolName = quotes_a2t(QUOTES_PROTOCOL_NAME); + mi.ptszName = const_cast(sProtocolName.c_str());//A2T(QUOTES_PROTOCOL_NAME); + mi.position = 0; + + hMenuRoot = reinterpret_cast(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast(&mi))); + } + + mi.flags = CMIF_TCHAR; + if(bSubGroups) + { + mi.flags |= CMIF_CHILDPOPUP; + mi.pszPopupName = (char*)hMenuRoot; + } + + mi.ptszName = _T("Refresh"); + mi.popupPosition = 0; + mi.flags |= CMIF_ICONFROMICOLIB; + mi.icolibItem = Quotes_GetIconHandle(IDI_ICON_REFRESH); + mi.pszService = "Quotes/RefreshContact"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast(&mi))); + g_hMenuRefresh = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_RefreshContact); + g_ahServices.push_back(h); + + mi.ptszName = _T("Open Log File..."); + mi.popupPosition = 1; + mi.icolibItem = NULL; + mi.pszService = "Quotes/OpenLogFile"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast(&mi))); + g_hMenuOpenLogFile = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_OpenLogFile); + g_ahServices.push_back(h); + +#ifdef CHART_IMPLEMENT + mi.ptszName = _T("Chart..."); + mi.popupPosition = 2; + mi.icolibItem = NULL; + mi.pszService = "Quotes/Chart"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast(&mi))); + g_hMenuChart = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_Chart); + g_ahServices.push_back(h); +#endif + + mi.ptszName = _T("Edit Settings..."); +#ifdef CHART_IMPLEMENT + mi.popupPosition = 3; +#else + mi.popupPosition = 2; +#endif + mi.icolibItem = NULL; + mi.pszService = "Quotes/EditSettings"; + hMenu = reinterpret_cast(CallService(MS_CLIST_ADDCONTACTMENUITEM,0,reinterpret_cast(&mi))); + g_hMenuEditSettings = hMenu; + g_ahMenus.push_back(hMenu); + h = CreateServiceFunction(mi.pszService, QuotesMenu_EditSettings); + g_ahServices.push_back(h); + } + + + int QuotesEventFunc_OnModulesLoaded(WPARAM, LPARAM) + { + CHTTPSession::Init(); + + if(ServiceExists(MS_UPDATE_REGISTER)) + { + Update update = {0}; + char szVersion[16]; + + update.szComponentName = Global_pluginInfo.shortName; + update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=4021"; + update.pbVersionPrefix = (BYTE *)"Quotes "; + update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix); + update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=4021"; + + update.szBetaVersionURL = NULL; + update.pbBetaVersionPrefix = NULL; + update.cpbBetaVersionPrefix = 0; + update.szBetaUpdateURL = NULL; + + update.pbVersion = (BYTE*)CreateVersionString(Global_pluginInfo.version,szVersion); + update.cpbVersion = (int)strlen((char *)update.pbVersion); + + update.szBetaChangelogURL = NULL; + + CallService(MS_UPDATE_REGISTER,0,(WPARAM)&update); + } + + HANDLE h = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD,QuotesEventFunc_onExtraImageListRebuild); + g_ahEvents.push_back(h); +// QuotesEventFunc_onExtraImageListRebuild(0,0); + + h = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY,QuotesEventFunc_onExtraImageApply); + g_ahEvents.push_back(h); + + g_hEventWorkThreadStop = ::CreateEvent(NULL,TRUE,FALSE,NULL); + h = (ME_USERINFO_INITIALISE,QuotesEventFunc_OnUserInfoInit); + g_ahEvents.push_back(h); + + + h = HookEvent(ME_CLIST_DOUBLECLICKED,Quotes_OnContactDoubleClick); + g_ahEvents.push_back(h); + + InitMenu(); + + return 0; + } + + int QuotesEventFunc_OnContactDeleted(WPARAM wParam, LPARAM) + { + HANDLE hContact = reinterpret_cast(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*/) + { +// USES_CONVERSION; + + const CModuleInfo::TQuotesProvidersPtr& pProviders = CModuleInfo::GetQuoteProvidersPtr(); + const CQuotesProviders::TQuotesProviders& rapProviders = pProviders->GetProviders(); + + OPTIONSDIALOGPAGE odp; + ZeroMemory(&odp,sizeof(odp)); + + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = CModuleInfo::GetModuleHandle(); + tstring sProtocolName = quotes_a2t(QUOTES_PROTOCOL_NAME); + odp.ptszTitle = const_cast(sProtocolName.c_str());//A2T(QUOTES_PROTOCOL_NAME); + odp.ptszGroup = _T("Network"); + odp.hIcon = Quotes_LoadIconEx(ICON_STR_MAIN); + odp.flags = ODPF_TCHAR|ODPF_USERINFOTAB; + + std::for_each(rapProviders.begin(),rapProviders.end(),boost::bind(&IQuotesProvider::ShowPropertyPage,_1,wp,boost::ref(odp))); + return 0; + } + + inline int Quotes_DestroyServiceFunction(HANDLE h) + { + return DestroyServiceFunction(h); + } + + inline int Quotes_UnhookEvent(HANDLE h) + { + return UnhookEvent(h); + } + + inline int Quotes_RemoveMenuItem(HGENMENU h) + { + return CallService(MS_CLIST_REMOVECONTACTMENUITEM,reinterpret_cast(h),0); + } + +// PROTO_INTERFACE* protoInit(const char* pszProtoName, const TCHAR* tszUserName) +// { +// CAimProto *ppro = new CAimProto(pszProtoName, tszUserName); +// g_Instances.insert(ppro); +// return ppro; +// } +// +// int protoUninit(PROTO_INTERFACE* ppro) +// { +// g_Instances.remove((CAimProto*)ppro); +// return 0; +// } + +} + +extern "C" +{ + __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) + { + if ( mirandaVersion < PLUGIN_MAKE_VERSION(0,8,0,0) ) + { + MessageBox(NULL, TranslateT("Quotes plugin requires Miranda IM 0.8.0.0 or later"), TranslateT("Fatal error"), MB_OK); + return NULL; + } + + return &Global_pluginInfo; + } + + +#define MIID_QUOTES {0x723243c2, 0x8d4b, 0x4c29, { 0x8a, 0x37, 0xc0, 0x11, 0x48, 0x65, 0xb0, 0x80}} + + __declspec(dllexport) const MUUID* MirandaPluginInterfaces() + { + static const MUUID interfaces[] = {MIID_PROTOCOL,MIID_QUOTES,MIID_LAST}; + return interfaces; + } + + int __declspec(dllexport) Load(PLUGINLINK *link) + { + pluginLink = link; + mir_getMMI(&mmi); + mir_getUTFI(&utfi); + mir_getLP(&Global_pluginInfo); +// if((mirandaVersion >= 0x0800) && (1 == mir_getXI(&xi))) +// { +// CModuleInfo::SetXMLEnginePtr(CModuleInfo::TXMLEnginePtr(new CXMLEngineMI)); +// } + + if(false == CModuleInfo::Verify()) + { + return 1; + } + + Quotes_IconsInit(); + + PROTOCOLDESCRIPTOR pd = {0}; + pd.cbSize = /*sizeof(pd)*/PROTOCOLDESCRIPTOR_V3_SIZE; + pd.szName = QUOTES_PROTOCOL_NAME; + pd.type = PROTOTYPE_PROTOCOL; +// pd.fnInit = protoInit; +// pd.fnUninit = protoUninit; + + CallService( MS_PROTO_REGISTERMODULE, 0, ( LPARAM )&pd ); + + HANDLE h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETNAME, QuoteProtoFunc_GetName); + g_ahServices.push_back(h); + h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETCAPS, QuoteProtoFunc_GetCaps); + g_ahServices.push_back(h); + h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_SETSTATUS, QuoteProtoFunc_SetStatus); + g_ahServices.push_back(h); + h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_GETSTATUS, QuoteProtoFunc_GetStatus); + g_ahServices.push_back(h); + h = CreateProtoServiceFunction(QUOTES_PROTOCOL_NAME, PS_LOADICON, QuoteProtoFunc_LoadIcon); + g_ahServices.push_back(h); + + h = HookEvent(ME_SYSTEM_MODULESLOADED,QuotesEventFunc_OnModulesLoaded); + g_ahEvents.push_back(h); + h = HookEvent(ME_DB_CONTACT_DELETED,QuotesEventFunc_OnContactDeleted); + g_ahEvents.push_back(h); + h = HookEvent(ME_SYSTEM_PRESHUTDOWN,QuotesEventFunc_PreShutdown); + g_ahEvents.push_back(h); + h = HookEvent(ME_OPT_INITIALISE,QuotesEventFunc_OptInitialise); + g_ahEvents.push_back(h); + + h = CreateServiceFunction(MS_QUOTES_EXPORT, Quotes_Export); + g_ahServices.push_back(h); + h = CreateServiceFunction(MS_QUOTES_IMPORT, Quotes_Import); + g_ahServices.push_back(h); + + return 0; + } + + __declspec(dllexport) int Unload(void) + { + std::for_each(g_ahServices.begin(),g_ahServices.end(),boost::bind(Quotes_DestroyServiceFunction,_1)); + std::for_each(g_ahEvents.begin(),g_ahEvents.end(),boost::bind(Quotes_UnhookEvent,_1)); + std::for_each(g_ahMenus.begin(),g_ahMenus.end(),boost::bind(Quotes_RemoveMenuItem,_1)); + + WaitForWorkingThreads(); + + ::CloseHandle(g_hEventWorkThreadStop); + + return 0; + } +} -- cgit v1.2.3