From 11db91e81fa495935c75ee3812ec3806e15ca510 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 18 May 2012 12:47:39 +0000 Subject: Weather moved to C++ git-svn-id: http://svn.miranda-ng.org/main/trunk@41 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/weather/weather.c | 307 ------------ protocols/weather/weather.cpp | 307 ++++++++++++ protocols/weather/weather_10.vcxproj | 30 +- protocols/weather/weather_addstn.c | 438 ----------------- protocols/weather/weather_addstn.cpp | 438 +++++++++++++++++ protocols/weather/weather_contacts.c | 515 -------------------- protocols/weather/weather_contacts.cpp | 515 ++++++++++++++++++++ protocols/weather/weather_conv.c | 838 --------------------------------- protocols/weather/weather_conv.cpp | 838 +++++++++++++++++++++++++++++++++ protocols/weather/weather_data.c | 500 -------------------- protocols/weather/weather_data.cpp | 500 ++++++++++++++++++++ protocols/weather/weather_http.c | 226 --------- protocols/weather/weather_http.cpp | 226 +++++++++ protocols/weather/weather_icons.c | 90 ---- protocols/weather/weather_icons.cpp | 90 ++++ protocols/weather/weather_info.c | 253 ---------- protocols/weather/weather_info.cpp | 253 ++++++++++ protocols/weather/weather_ini.c | 628 ------------------------ protocols/weather/weather_ini.cpp | 628 ++++++++++++++++++++++++ protocols/weather/weather_mwin.c | 449 ------------------ protocols/weather/weather_mwin.cpp | 449 ++++++++++++++++++ protocols/weather/weather_opt.c | 660 -------------------------- protocols/weather/weather_opt.cpp | 660 ++++++++++++++++++++++++++ protocols/weather/weather_popup.c | 454 ------------------ protocols/weather/weather_popup.cpp | 454 ++++++++++++++++++ protocols/weather/weather_svcs.c | 452 ------------------ protocols/weather/weather_svcs.cpp | 452 ++++++++++++++++++ protocols/weather/weather_update.c | 678 -------------------------- protocols/weather/weather_update.cpp | 678 ++++++++++++++++++++++++++ protocols/weather/weather_userinfo.c | 418 ---------------- protocols/weather/weather_userinfo.cpp | 418 ++++++++++++++++ 31 files changed, 6921 insertions(+), 6921 deletions(-) delete mode 100644 protocols/weather/weather.c create mode 100644 protocols/weather/weather.cpp delete mode 100644 protocols/weather/weather_addstn.c create mode 100644 protocols/weather/weather_addstn.cpp delete mode 100644 protocols/weather/weather_contacts.c create mode 100644 protocols/weather/weather_contacts.cpp delete mode 100644 protocols/weather/weather_conv.c create mode 100644 protocols/weather/weather_conv.cpp delete mode 100644 protocols/weather/weather_data.c create mode 100644 protocols/weather/weather_data.cpp delete mode 100644 protocols/weather/weather_http.c create mode 100644 protocols/weather/weather_http.cpp delete mode 100644 protocols/weather/weather_icons.c create mode 100644 protocols/weather/weather_icons.cpp delete mode 100644 protocols/weather/weather_info.c create mode 100644 protocols/weather/weather_info.cpp delete mode 100644 protocols/weather/weather_ini.c create mode 100644 protocols/weather/weather_ini.cpp delete mode 100644 protocols/weather/weather_mwin.c create mode 100644 protocols/weather/weather_mwin.cpp delete mode 100644 protocols/weather/weather_opt.c create mode 100644 protocols/weather/weather_opt.cpp delete mode 100644 protocols/weather/weather_popup.c create mode 100644 protocols/weather/weather_popup.cpp delete mode 100644 protocols/weather/weather_svcs.c create mode 100644 protocols/weather/weather_svcs.cpp delete mode 100644 protocols/weather/weather_update.c create mode 100644 protocols/weather/weather_update.cpp delete mode 100644 protocols/weather/weather_userinfo.c create mode 100644 protocols/weather/weather_userinfo.cpp (limited to 'protocols/weather') diff --git a/protocols/weather/weather.c b/protocols/weather/weather.c deleted file mode 100644 index f2ac4a8e7d..0000000000 --- a/protocols/weather/weather.c +++ /dev/null @@ -1,307 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -Main file for the Weather Protocol, includes loading, unloading, -upgrading, support for plugin uninsaller, and anything that doesn't -belong to any other file. -*/ - -#include "weather.h" - -//============ GLOBAL VARIABLES ============ - -WIDATALIST *WIHead; -WIDATALIST *WITail; - -HINSTANCE hInst; -HWND hPopupWindow; - -HANDLE hHookWeatherUpdated; -HANDLE hHookWeatherError; - -static HANDLE hHooks[9]; - -HANDLE hDataWindowList; -HANDLE hWindowList; - -HANDLE hUpdateMutex; - -unsigned status; -unsigned old_status; - -UINT_PTR timerId; -int hLangpack; - -MYOPTIONS opt; - -// check if weather is currently updating -BOOL ThreadRunning; - -// variable to determine if module loaded -BOOL ModuleLoaded; - -struct MM_INTERFACE mmi; -struct UTF8_INTERFACE utfi; - - -PLUGINLINK *pluginLink; - -// plugin info -// VER = version, AUTH = author, defined in weather.h -static const PLUGININFOEX pluginInfoEx = -{ - sizeof(PLUGININFOEX), -#ifdef _WIN64 - "Weather Protocol x64 Mataes Release", -#else - "Weather Protocol Mataes Release", -#endif - __VERSION_DWORD, - "Retrieve weather information and display them in your contact list. Mod for Mataes Pack.", - AUTH, - "borkra@miranda-im.org", - "(c) 2002-2005 NoName, 2005-2010 Boris Krasnovskiy", - "http://addons.miranda-im.org/details.php?action=viewfile&id=2322", - UNICODE_AWARE, - 0, - MIID_WEATHER -}; - -__declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) -{ - if (mirandaVersion < PLUGIN_MAKE_VERSION(0,8,0,0)) { - MessageBox(NULL, "Weather Protocol requires Miranda 0.8.0.0 or later to run.", "Weather Protocol", MB_OK|MB_ICONERROR|MB_APPLMODAL); - return NULL; - } - // if Miranda version is higher than 0.7.0 - else - return &pluginInfoEx; -} - -// MirandaPluginInterfaces - returns the protocol interface to the core -static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST}; -__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) -{ - return interfaces; -} - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch(fdwReason) - { - case DLL_PROCESS_ATTACH: - hInst = hinstDLL; - DisableThreadLibraryCalls(hinstDLL); - break; - } - - return TRUE; -} - - -int WeatherShutdown(WPARAM wParam,LPARAM lParam) -{ - KillTimer(NULL, timerId); // kill update timer - - SaveOptions(); // save options once more - status = ID_STATUS_OFFLINE; // set status to offline - - CallService(MS_NETLIB_SHUTDOWN, (WPARAM)hNetlibHttp, 0); - - WindowList_Broadcast(hWindowList, WM_CLOSE, 0, 0); - WindowList_Broadcast(hDataWindowList, WM_CLOSE, 0, 0); - SendMessage(hWndSetup, WM_CLOSE, 0, 0); - - return 0; -} - -// update some settings/db values for new version -// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION -void Upgrade(DWORD lastver) -{ - // for version below v0.3.2.3, remove the "TriggerText" setting - if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3)) - DBDeleteContactSetting(NULL, WEATHERPROTONAME, "TriggerText"); - if (lastver < PLUGIN_MAKE_VERSION(0,3,3,13)) - DBDeleteContactSetting(NULL, "KnownModules", "Weather"); - - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "Version", __VERSION_DWORD); -} - -// weather protocol initialization function -// run after the event ME_SYSTEM_MODULESLOADED occurs -int WeatherInit(WPARAM wParam,LPARAM lParam) -{ - // initialize netlib - NetlibInit(); - - InitIcons(); - InitMwin(); - - // load weather menu items - AddMenuItems(); - - // timer for the first update - timerId = SetTimer(NULL, 0, 5000, (TIMERPROC)timerProc2); // first update is 5 sec after load - - // weather user detail - hHooks[0] = HookEvent(ME_USERINFO_INITIALISE, UserInfoInit); - - hDataWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); - hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); - - return 0; -} - -// update some settings/db values for new version, this one is for contact -// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION -// hContact = current contact -void UpgradeContact(DWORD lastver, HANDLE hContact) -{ - // for version below v0.3.2.3, suppress online notifications for all weather contacts - if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3)) - { - DBWriteContactSettingDword(hContact, "Ignore", "Mask", 8); - DBWriteContactSettingDword(hContact, "Ignore", "Mask1", 8); - } -} - -//============ MISC FUNCTIONS ============ - -// initialize the global variables at startup -void InitVar() -{ - // setup the linklist for weather update list - UpdateListTail = NULL; - UpdateListHead = NULL; - - // other settings - timerId=0; - opt.DefStn = NULL; - ModuleLoaded = FALSE; -} - -// unload function -int __declspec(dllexport) Unload(void) -{ - unsigned i; - - DestroyMwin(); - DestroyWindow(hPopupWindow); - - for (i = sizeof(hHooks)/sizeof(HANDLE); i--; ) - UnhookEvent(hHooks[i]); - - DestroyHookableEvent(hHookWeatherUpdated); - DestroyHookableEvent(hHookWeatherError); - - DestroyServices(); - - NetlibHttpDisconnect(); - Netlib_CloseHandle(hNetlibUser); - - DestroyUpdateList(); - DestroyOptions(); - DestroyWIList(); // unload all ini data from memory - - CloseHandle(hUpdateMutex); - - return 0; -} - -int __declspec(dllexport) Load(PLUGINLINK *link) -{ - PROTOCOLDESCRIPTOR pd = {0}; - char SvcFunc[100]; - DWORD lastver; - - pluginLink = link; - - mir_getMMI(&mmi); - mir_getUTFI(&utfi); - mir_getLP(&pluginInfoEx); - - // initialize global variables - InitVar(); - InitUniConv(); - - // load options and set defaults - LoadOptions(); - - // upgrade check - // I only support version check and upgrade for my own version, so check if the author is my name - if (strstr(AUTH, "NoName") != NULL) - { - lastver = DBGetContactSettingDword(NULL, WEATHERPROTONAME, "Version", PLUGIN_MAKE_VERSION(0,3,1,8)); - if (lastver < __VERSION_DWORD) Upgrade(lastver); - } - else // if it is not my build, ignore upgrade procedure - lastver = PLUGIN_MAKE_VERSION(255,255,255,255); - - // reset the weather data at startup for individual contacts - EraseAllInfo(lastver); - - // load weather update data - LoadWIData(TRUE); - - // set status to online if "Do not display weather condition as protocol status" is enabled - old_status = status = ID_STATUS_OFFLINE; - - // add an event on weather update and error - hHookWeatherUpdated = CreateHookableEvent(ME_WEATHER_UPDATED); - hHookWeatherError = CreateHookableEvent(ME_WEATHER_ERROR); - - // initialize options and network - hHooks[1] = HookEvent(ME_OPT_INITIALISE, OptInit); - hHooks[2] = HookEvent(ME_SYSTEM_MODULESLOADED, WeatherInit); - hHooks[3] = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); - hHooks[4] = HookEvent(ME_CLIST_DOUBLECLICKED, BriefInfo); - hHooks[5] = HookEvent(ME_WEATHER_UPDATED, WeatherPopup); - hHooks[6] = HookEvent(ME_WEATHER_ERROR, WeatherError); - hHooks[7] = HookEvent(ME_SYSTEM_PRESHUTDOWN, WeatherShutdown); - hHooks[8] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, BuildContactMenu); - - hUpdateMutex = CreateMutex(NULL, FALSE, NULL); - - // register weather protocol - pd.cbSize = PROTOCOLDESCRIPTOR_V3_SIZE; - pd.szName = WEATHERPROTONAME; - pd.type = PROTOTYPE_PROTOCOL; - CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); - - // initialize weather protocol services - InitServices(); - - // add our modules to the KnownModules list - DBWriteContactSettingString(NULL, "KnownModules", "Weather Protocol", "Weather,WeatherCondition,Current"); - - // add sound event - SkinAddNewSound("weatherupdated", Translate("Weather Condition Changed"), ""); - SkinAddNewSound("weatheralert", Translate("Weather Alert Issued"), ""); - - // window needed for popup commands - strcpy(SvcFunc, WEATHERPROTONAME); - strcat(SvcFunc, "_PopupWindow"); - hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW,"static",SvcFunc,0,CW_USEDEFAULT,CW_USEDEFAULT, - CW_USEDEFAULT,CW_USEDEFAULT,HWND_DESKTOP,NULL,hInst,NULL); - SetWindowLongPtr(hPopupWindow, GWLP_WNDPROC, (LONG_PTR)PopupWndProc); - - return 0; -} diff --git a/protocols/weather/weather.cpp b/protocols/weather/weather.cpp new file mode 100644 index 0000000000..e4e5ee88d6 --- /dev/null +++ b/protocols/weather/weather.cpp @@ -0,0 +1,307 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +Main file for the Weather Protocol, includes loading, unloading, +upgrading, support for plugin uninsaller, and anything that doesn't +belong to any other file. +*/ + +#include "weather.h" + +//============ GLOBAL VARIABLES ============ + +WIDATALIST *WIHead; +WIDATALIST *WITail; + +HINSTANCE hInst; +HWND hPopupWindow; + +HANDLE hHookWeatherUpdated; +HANDLE hHookWeatherError; + +static HANDLE hHooks[9]; + +HANDLE hDataWindowList; +HANDLE hWindowList; + +HANDLE hUpdateMutex; + +unsigned status; +unsigned old_status; + +UINT_PTR timerId; +int hLangpack; + +MYOPTIONS opt; + +// check if weather is currently updating +BOOL ThreadRunning; + +// variable to determine if module loaded +BOOL ModuleLoaded; + +struct MM_INTERFACE mmi; +struct UTF8_INTERFACE utfi; + + +PLUGINLINK *pluginLink; + +// plugin info +// VER = version, AUTH = author, defined in weather.h +static const PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), +#ifdef _WIN64 + "Weather Protocol x64 Mataes Release", +#else + "Weather Protocol Mataes Release", +#endif + __VERSION_DWORD, + "Retrieve weather information and display them in your contact list. Mod for Mataes Pack.", + AUTH, + "borkra@miranda-im.org", + "(c) 2002-2005 NoName, 2005-2010 Boris Krasnovskiy", + "http://addons.miranda-im.org/details.php?action=viewfile&id=2322", + UNICODE_AWARE, + 0, + MIID_WEATHER +}; + +extern "C" __declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if (mirandaVersion < PLUGIN_MAKE_VERSION(0,8,0,0)) { + MessageBox(NULL, "Weather Protocol requires Miranda 0.8.0.0 or later to run.", "Weather Protocol", MB_OK|MB_ICONERROR|MB_APPLMODAL); + return NULL; + } + // if Miranda version is higher than 0.7.0 + else + return &pluginInfoEx; +} + +// MirandaPluginInterfaces - returns the protocol interface to the core +static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch(fdwReason) + { + case DLL_PROCESS_ATTACH: + hInst = hinstDLL; + DisableThreadLibraryCalls(hinstDLL); + break; + } + + return TRUE; +} + + +int WeatherShutdown(WPARAM wParam,LPARAM lParam) +{ + KillTimer(NULL, timerId); // kill update timer + + SaveOptions(); // save options once more + status = ID_STATUS_OFFLINE; // set status to offline + + CallService(MS_NETLIB_SHUTDOWN, (WPARAM)hNetlibHttp, 0); + + WindowList_Broadcast(hWindowList, WM_CLOSE, 0, 0); + WindowList_Broadcast(hDataWindowList, WM_CLOSE, 0, 0); + SendMessage(hWndSetup, WM_CLOSE, 0, 0); + + return 0; +} + +// update some settings/db values for new version +// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION +void Upgrade(DWORD lastver) +{ + // for version below v0.3.2.3, remove the "TriggerText" setting + if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3)) + DBDeleteContactSetting(NULL, WEATHERPROTONAME, "TriggerText"); + if (lastver < PLUGIN_MAKE_VERSION(0,3,3,13)) + DBDeleteContactSetting(NULL, "KnownModules", "Weather"); + + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "Version", __VERSION_DWORD); +} + +// weather protocol initialization function +// run after the event ME_SYSTEM_MODULESLOADED occurs +int WeatherInit(WPARAM wParam,LPARAM lParam) +{ + // initialize netlib + NetlibInit(); + + InitIcons(); + InitMwin(); + + // load weather menu items + AddMenuItems(); + + // timer for the first update + timerId = SetTimer(NULL, 0, 5000, (TIMERPROC)timerProc2); // first update is 5 sec after load + + // weather user detail + hHooks[0] = HookEvent(ME_USERINFO_INITIALISE, UserInfoInit); + + hDataWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); + hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); + + return 0; +} + +// update some settings/db values for new version, this one is for contact +// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION +// hContact = current contact +void UpgradeContact(DWORD lastver, HANDLE hContact) +{ + // for version below v0.3.2.3, suppress online notifications for all weather contacts + if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3)) + { + DBWriteContactSettingDword(hContact, "Ignore", "Mask", 8); + DBWriteContactSettingDword(hContact, "Ignore", "Mask1", 8); + } +} + +//============ MISC FUNCTIONS ============ + +// initialize the global variables at startup +void InitVar() +{ + // setup the linklist for weather update list + UpdateListTail = NULL; + UpdateListHead = NULL; + + // other settings + timerId=0; + opt.DefStn = NULL; + ModuleLoaded = FALSE; +} + +// unload function +extern "C" int __declspec(dllexport) Unload(void) +{ + unsigned i; + + DestroyMwin(); + DestroyWindow(hPopupWindow); + + for (i = sizeof(hHooks)/sizeof(HANDLE); i--; ) + UnhookEvent(hHooks[i]); + + DestroyHookableEvent(hHookWeatherUpdated); + DestroyHookableEvent(hHookWeatherError); + + DestroyServices(); + + NetlibHttpDisconnect(); + Netlib_CloseHandle(hNetlibUser); + + DestroyUpdateList(); + DestroyOptions(); + DestroyWIList(); // unload all ini data from memory + + CloseHandle(hUpdateMutex); + + return 0; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + PROTOCOLDESCRIPTOR pd = {0}; + char SvcFunc[100]; + DWORD lastver; + + pluginLink = link; + + mir_getMMI(&mmi); + mir_getUTFI(&utfi); + mir_getLP(&pluginInfoEx); + + // initialize global variables + InitVar(); + InitUniConv(); + + // load options and set defaults + LoadOptions(); + + // upgrade check + // I only support version check and upgrade for my own version, so check if the author is my name + if (strstr(AUTH, "NoName") != NULL) + { + lastver = DBGetContactSettingDword(NULL, WEATHERPROTONAME, "Version", PLUGIN_MAKE_VERSION(0,3,1,8)); + if (lastver < __VERSION_DWORD) Upgrade(lastver); + } + else // if it is not my build, ignore upgrade procedure + lastver = PLUGIN_MAKE_VERSION(255,255,255,255); + + // reset the weather data at startup for individual contacts + EraseAllInfo(lastver); + + // load weather update data + LoadWIData(TRUE); + + // set status to online if "Do not display weather condition as protocol status" is enabled + old_status = status = ID_STATUS_OFFLINE; + + // add an event on weather update and error + hHookWeatherUpdated = CreateHookableEvent(ME_WEATHER_UPDATED); + hHookWeatherError = CreateHookableEvent(ME_WEATHER_ERROR); + + // initialize options and network + hHooks[1] = HookEvent(ME_OPT_INITIALISE, OptInit); + hHooks[2] = HookEvent(ME_SYSTEM_MODULESLOADED, WeatherInit); + hHooks[3] = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); + hHooks[4] = HookEvent(ME_CLIST_DOUBLECLICKED, BriefInfo); + hHooks[5] = HookEvent(ME_WEATHER_UPDATED, WeatherPopup); + hHooks[6] = HookEvent(ME_WEATHER_ERROR, WeatherError); + hHooks[7] = HookEvent(ME_SYSTEM_PRESHUTDOWN, WeatherShutdown); + hHooks[8] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, BuildContactMenu); + + hUpdateMutex = CreateMutex(NULL, FALSE, NULL); + + // register weather protocol + pd.cbSize = PROTOCOLDESCRIPTOR_V3_SIZE; + pd.szName = WEATHERPROTONAME; + pd.type = PROTOTYPE_PROTOCOL; + CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); + + // initialize weather protocol services + InitServices(); + + // add our modules to the KnownModules list + DBWriteContactSettingString(NULL, "KnownModules", "Weather Protocol", "Weather,WeatherCondition,Current"); + + // add sound event + SkinAddNewSound("weatherupdated", Translate("Weather Condition Changed"), ""); + SkinAddNewSound("weatheralert", Translate("Weather Alert Issued"), ""); + + // window needed for popup commands + strcpy(SvcFunc, WEATHERPROTONAME); + strcat(SvcFunc, "_PopupWindow"); + hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW,"static",SvcFunc,0,CW_USEDEFAULT,CW_USEDEFAULT, + CW_USEDEFAULT,CW_USEDEFAULT,HWND_DESKTOP,NULL,hInst,NULL); + SetWindowLongPtr(hPopupWindow, GWLP_WNDPROC, (LONG_PTR)PopupWndProc); + + return 0; +} diff --git a/protocols/weather/weather_10.vcxproj b/protocols/weather/weather_10.vcxproj index 64ea807e1a..7f2bd633b3 100644 --- a/protocols/weather/weather_10.vcxproj +++ b/protocols/weather/weather_10.vcxproj @@ -200,21 +200,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/protocols/weather/weather_addstn.c b/protocols/weather/weather_addstn.c deleted file mode 100644 index 24b965ce19..0000000000 --- a/protocols/weather/weather_addstn.c +++ /dev/null @@ -1,438 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* This file contain the source related to search and add a weather station -to the contact list. Contain code for both name and ID search. -*/ - -#include "weather.h" - -// variables used for weather_addstn.c -static int searchId=-1; -static char sID[32]; -static char name1[256]; - -//============ ADDING NEW STATION ============ - -// protocol service function for adding a new contact onto contact list -// lParam = PROTOSEARCHRESULT -INT_PTR WeatherAddToList(WPARAM wParam,LPARAM lParam) -{ - PROTOSEARCHRESULT *psr=(PROTOSEARCHRESULT*)lParam; - char str[256], svc[256]; - WIDATA *sData; - - // search for existing contact - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); - while(hContact != NULL) - { - // check if it is a weather contact - if(IsMyContact(hContact)) - { - DBVARIANT dbv; - // check ID to see if the contact already exist in the database - if(!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) - { - if(!_stricmp(psr->email,dbv.pszVal)) - { - // remove the flag for not on list and hidden, thus make the contact visible - // and add them on the list - if (DBGetContactSettingByte(hContact,"CList","NotOnList",1)) - { - DBDeleteContactSetting(hContact,"CList","NotOnList"); - DBDeleteContactSetting(hContact,"CList","Hidden"); - } - DBFreeVariant(&dbv); - // contact is added, function quitting - return (INT_PTR)hContact; - } - DBFreeVariant(&dbv); - } - } - hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0); - } - - // if contact with the same ID was not found, add it - if (psr->cbSize < sizeof(PROTOSEARCHRESULT)) return 0; - hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0); - CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)WEATHERPROTONAME); - // suppress online notification for the new contact - CallService(MS_IGNORE_IGNORE,(WPARAM)hContact, IGNOREEVENT_USERONLINE); - // set contact info and settings - strncpy(svc, psr->email, sizeof(svc)); svc[sizeof(svc)-1] = 0; - GetSvc(svc); - // set settings by obtaining the default for the service - if (psr->lastName[0] != 0) - { - sData = GetWIData(svc); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", sData->DefaultMap); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", sData->DefaultURL); - } - else // if no valid service is found, create empty strings for MapURL and InfoURL - { - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", ""); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", ""); - } - // write the other info and settings to the database - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "ID", psr->email); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", psr->nick); - wsprintf(str, Translate("Current weather information for %s."), psr->nick); - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE); - AvatarDownloaded(hContact); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "About", str); - // make the last update tags to something invalid - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", "never"); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", "None"); - - // ignore status change - DBWriteContactSettingDword(hContact, "Ignore", "Mask", 8); - - // if no default station is found, set the new contact as default station - if (opt.Default[0] == 0) - { - DBVARIANT dbv; - GetStationID(hContact, opt.Default, sizeof(opt.Default)); - - opt.DefStn = hContact; - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Nick",&dbv)) - { - // notification message box - wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); - DBFreeVariant(&dbv); - MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); - } - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); - } - // display the Edit Settings dialog box - EditSettings((WPARAM)hContact, 0); - return (INT_PTR)hContact; -} - -//============ WARNING DIALOG ============ - -// show a message box and cancel search if update is in process -BOOL CheckSearch() { - if (UpdateListHead != NULL) { - MessageBox(NULL, Translate("Please try again after weather update is completed."), Translate("Weather Protocol"), MB_OK|MB_ICONERROR); - return FALSE; - } - return TRUE; -} - -//============ BASIC ID SEARCH ============ - -// A timer process for the ID search (threaded) -static void __cdecl BasicSearchTimerProc(LPVOID hWnd) -{ - int result; - // search only when it's not current updating weather. - if (CheckSearch()) result = IDSearch(sID, searchId); - // broadcast the search result - ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_SUCCESS,(HANDLE)searchId,0); - - // exit the search - searchId=-1; -} - -// the service function for ID search -// lParam = ID search string -INT_PTR WeatherBasicSearch(WPARAM wParam,LPARAM lParam) -{ - if(searchId != -1) return 0; //only one search at a time - strncpy(sID, (char*)lParam, sizeof(sID)); - sID[sizeof(sID)-1] = 0; - searchId=1; - // create a thread for the ID search - mir_forkthread(BasicSearchTimerProc, NULL); - return searchId; -} - -//============ NAME SEARCH ============ - -// name search timer process (threaded) -static void __cdecl NameSearchTimerProc(LPVOID hWnd) -{ - // search only when it's not current updating weather. - if (CheckSearch()) - { - if (name1[0] != 0) NameSearch(name1, searchId); // search nickname field - } - // broadcast the result - ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)searchId, 0); - - // exit the search - searchId = -1; -} - -static INT_PTR CALLBACK WeatherSearchAdvancedDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - SetFocus(GetDlgItem(hwndDlg, IDC_SEARCHCITY)); - return TRUE; - - case WM_COMMAND: - if (HIWORD(wParam) == EN_SETFOCUS) - PostMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndDlg); - } - return FALSE; -} - -INT_PTR WeatherCreateAdvancedSearchUI(WPARAM wParam, LPARAM lParam) -{ - HWND parent = (HWND)lParam; - - if (parent) - return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHCITY), parent, WeatherSearchAdvancedDlgProc, 0); - - return 0; -} - -// service function for name search -INT_PTR WeatherAdvancedSearch(WPARAM wParam, LPARAM lParam) -{ - if (searchId != -1) return 0; //only one search at a time - searchId = 1; - - GetDlgItemText((HWND)lParam, IDC_SEARCHCITY, name1, 256); - - // search for the weather station using a thread - mir_forkthread(NameSearchTimerProc, NULL); - return searchId; -} - -//============ SEARCH FOR A WEATHER STATION USING ID ============ - -// Seaching station ID from a single weather service (Threaded) -// sID = search string for the station ID -// searchId = -1 -// sData = the ID search data for that particular weather service -// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather) -int IDSearchProc(char *sID, const int searchId, WIIDSEARCH *sData, char *svc, char *svcname) -{ - PROTOSEARCHRESULT psr = {0}; - char str[MAX_DATA_LEN] = "", newID[MAX_DATA_LEN]; - - if (sData->Available) - { - char loc[255], *szData = NULL; - - // load the page - mir_snprintf(loc, sizeof(loc), sData->SearchURL , sID); - if (InternetDownloadFile(loc, NULL, &szData) == 0) - { - char* szInfo = szData; - - // not found - if (strstr(szInfo, sData->NotFoundStr) == NULL) - GetDataValue(&sData->Name, str, &szInfo); - } - mir_free(szData); - // Station not found exit - if (str[0] == 0) return 1; - } - - // give no station name but only ID if the search is unavailable - else strcpy(str, Translate("")); - mir_snprintf(newID, sizeof(newID), "%s/%s", svc, sID); - - // set the search result and broadcast it - psr.cbSize=sizeof(psr); - psr.nick=str; - psr.firstName=" "; - psr.lastName=svcname; - psr.email=newID; - ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); - - return 0; -} - -// ID search (Threaded) -// sID: the ID to search for -// searchId: don't change -// return 0 if no error -int IDSearch(char *sID, const int searchId) -{ - // for a normal ID search (ID != #) - if (strcmp(sID, "#")) - { - WIDATALIST *Item = WIHead; - - // search every weather service using the search station ID - while (Item != NULL) - { - IDSearchProc(sID, searchId, &Item->Data.IDSearch, Item->Data.InternalName, Item->Data.DisplayName); - Item = Item->next; - } - NetlibHttpDisconnect(); - } - // if the station ID is #, return a dummy result and quit the funciton - else - { - PROTOSEARCHRESULT psr = {0}; - // return an empty contact on "#" - psr.cbSize=sizeof(psr); - psr.nick=Translate(""); // to be entered - psr.firstName=" "; - psr.lastName=""; - psr.email=Translate(""); // to be entered - ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA,(HANDLE)searchId,(LPARAM)&psr); - } - - return 0; -} - -//============ SEARCH FOR A WEATHER STATION BY NAME ============ - -// Seaching station name from a single weather service (Threaded) -// name = the name of the weather station to be searched -// searchId = -1 -// sData = the name search data for that particular weather service -// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather) -int NameSearchProc(char *name, const int searchId, WINAMESEARCH *sData, char *svc, char *svcname) -{ - PROTOSEARCHRESULT psr; - char *search, str[MAX_DATA_LEN], loc[256], sID[MAX_DATA_LEN], Name[MAX_DATA_LEN], *szData = NULL; - - // replace spaces with %20 - char *pstr = (char*)CallService(MS_NETLIB_URLENCODE, 0, (LPARAM) name); - wsprintf(loc, sData->SearchURL, pstr); - HeapFree(GetProcessHeap(), 0, pstr); - - if (InternetDownloadFile(loc, NULL, &szData) == 0) - { - char* szInfo = szData; - search = strstr(szInfo, sData->NotFoundStr); // determine if data is available - if (search == NULL) // if data is found - { - // test if it is single result - if (sData->Single.Available && sData->Multiple.Available) - search = strstr(szInfo, sData->SingleStr); - // for single result - if (sData->Single.Available && (search != NULL || !sData->Multiple.Available)) // single result - { - // if station ID appears first in the downloaded data - if (!_stricmp(sData->Single.First, "ID")) - { - GetDataValue(&sData->Single.ID, str, &szInfo); - wsprintf(sID, "%s/%s", svc, str); - GetDataValue(&sData->Single.Name, Name, &szInfo); - } - // if station name appears first in the downloaded data - else if (!_stricmp(sData->Single.First, "NAME")) - { - GetDataValue(&sData->Single.Name, Name, &szInfo); - GetDataValue(&sData->Single.ID, str, &szInfo); - wsprintf(sID, "%s/%s", svc, str); - } - // if no station ID is obtained, quit the search - if (str[0] == 0) - { - mir_free(szData); - return 1; - } - // if can't get the name, use the search string as name - if (Name[0] == 0) strcpy(Name, name); - - // set the data and broadcast it - memset(&psr,0,sizeof(psr)); - psr.cbSize=sizeof(psr); - psr.nick=Name; - psr.firstName=" "; - psr.lastName=svcname; - psr.email=sID; - psr.id=sID; - ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA,(HANDLE)searchId,(LPARAM)&psr); - mir_free(szData); - return 0; - } - // for multiple result - else if (sData->Multiple.Available) // multiple results - { - // search for the next occurrence of the string - for (;;) - { - // if station ID appears first in the downloaded data - if (!_stricmp(sData->Multiple.First, "ID")) { - GetDataValue(&sData->Multiple.ID, str, &szInfo); - wsprintf(sID, "%s/%s", svc, str); - GetDataValue(&sData->Multiple.Name, Name, &szInfo); - } - // if station name appears first in the downloaded data - else if (!_stricmp(sData->Multiple.First, "NAME")) { - GetDataValue(&sData->Multiple.Name, Name, &szInfo); - GetDataValue(&sData->Multiple.ID, str, &szInfo); - wsprintf(sID, "%s/%s", svc, str); - } - // if no station ID is obtained, search completed and quit the search - if (str[0] == 0) break; - // if can't get the name, use the search string as name - if (Name[0] == 0) strcpy(Name, name); - - memset(&psr,0,sizeof(psr)); - psr.cbSize=sizeof(psr); - psr.nick=Name; - psr.firstName=""; - psr.lastName=svcname; - psr.email=sID; - psr.id=sID; - ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA, - (HANDLE)searchId,(LPARAM)&psr); - } - } - } - mir_free(szData); - return 0; - } - mir_free(szData); - return 1; -} - -// name search (Threaded) -// name: the station name to search for -// searchId: don't change -// return 0 if no error -int NameSearch(char *name, const int searchId) -{ - WIDATALIST *Item = WIHead; - - // search every weather service using the search station name - while (Item != NULL) - { - if (Item->Data.NameSearch.Single.Available || Item->Data.NameSearch.Multiple.Available) - NameSearchProc(name, searchId, &Item->Data.NameSearch, Item->Data.InternalName, Item->Data.DisplayName); - Item = Item->next; - } - NetlibHttpDisconnect(); - - return 0; -} - -//====================== MENU ITEM FUNCTION ============ - -// add a new weather station via find/add dialog -int WeatherAdd(WPARAM wParam, LPARAM lParam) -{ - DBWriteContactSettingString(NULL, "FindAdd", "LastSearched", "Weather"); - CallService(MS_FINDADD_FINDADD, 0, 0); - return 0; -} diff --git a/protocols/weather/weather_addstn.cpp b/protocols/weather/weather_addstn.cpp new file mode 100644 index 0000000000..24b965ce19 --- /dev/null +++ b/protocols/weather/weather_addstn.cpp @@ -0,0 +1,438 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* This file contain the source related to search and add a weather station +to the contact list. Contain code for both name and ID search. +*/ + +#include "weather.h" + +// variables used for weather_addstn.c +static int searchId=-1; +static char sID[32]; +static char name1[256]; + +//============ ADDING NEW STATION ============ + +// protocol service function for adding a new contact onto contact list +// lParam = PROTOSEARCHRESULT +INT_PTR WeatherAddToList(WPARAM wParam,LPARAM lParam) +{ + PROTOSEARCHRESULT *psr=(PROTOSEARCHRESULT*)lParam; + char str[256], svc[256]; + WIDATA *sData; + + // search for existing contact + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while(hContact != NULL) + { + // check if it is a weather contact + if(IsMyContact(hContact)) + { + DBVARIANT dbv; + // check ID to see if the contact already exist in the database + if(!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) + { + if(!_stricmp(psr->email,dbv.pszVal)) + { + // remove the flag for not on list and hidden, thus make the contact visible + // and add them on the list + if (DBGetContactSettingByte(hContact,"CList","NotOnList",1)) + { + DBDeleteContactSetting(hContact,"CList","NotOnList"); + DBDeleteContactSetting(hContact,"CList","Hidden"); + } + DBFreeVariant(&dbv); + // contact is added, function quitting + return (INT_PTR)hContact; + } + DBFreeVariant(&dbv); + } + } + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0); + } + + // if contact with the same ID was not found, add it + if (psr->cbSize < sizeof(PROTOSEARCHRESULT)) return 0; + hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)WEATHERPROTONAME); + // suppress online notification for the new contact + CallService(MS_IGNORE_IGNORE,(WPARAM)hContact, IGNOREEVENT_USERONLINE); + // set contact info and settings + strncpy(svc, psr->email, sizeof(svc)); svc[sizeof(svc)-1] = 0; + GetSvc(svc); + // set settings by obtaining the default for the service + if (psr->lastName[0] != 0) + { + sData = GetWIData(svc); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", sData->DefaultMap); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", sData->DefaultURL); + } + else // if no valid service is found, create empty strings for MapURL and InfoURL + { + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", ""); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", ""); + } + // write the other info and settings to the database + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "ID", psr->email); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", psr->nick); + wsprintf(str, Translate("Current weather information for %s."), psr->nick); + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE); + AvatarDownloaded(hContact); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "About", str); + // make the last update tags to something invalid + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", "never"); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", "None"); + + // ignore status change + DBWriteContactSettingDword(hContact, "Ignore", "Mask", 8); + + // if no default station is found, set the new contact as default station + if (opt.Default[0] == 0) + { + DBVARIANT dbv; + GetStationID(hContact, opt.Default, sizeof(opt.Default)); + + opt.DefStn = hContact; + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Nick",&dbv)) + { + // notification message box + wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); + DBFreeVariant(&dbv); + MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); + } + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); + } + // display the Edit Settings dialog box + EditSettings((WPARAM)hContact, 0); + return (INT_PTR)hContact; +} + +//============ WARNING DIALOG ============ + +// show a message box and cancel search if update is in process +BOOL CheckSearch() { + if (UpdateListHead != NULL) { + MessageBox(NULL, Translate("Please try again after weather update is completed."), Translate("Weather Protocol"), MB_OK|MB_ICONERROR); + return FALSE; + } + return TRUE; +} + +//============ BASIC ID SEARCH ============ + +// A timer process for the ID search (threaded) +static void __cdecl BasicSearchTimerProc(LPVOID hWnd) +{ + int result; + // search only when it's not current updating weather. + if (CheckSearch()) result = IDSearch(sID, searchId); + // broadcast the search result + ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_SUCCESS,(HANDLE)searchId,0); + + // exit the search + searchId=-1; +} + +// the service function for ID search +// lParam = ID search string +INT_PTR WeatherBasicSearch(WPARAM wParam,LPARAM lParam) +{ + if(searchId != -1) return 0; //only one search at a time + strncpy(sID, (char*)lParam, sizeof(sID)); + sID[sizeof(sID)-1] = 0; + searchId=1; + // create a thread for the ID search + mir_forkthread(BasicSearchTimerProc, NULL); + return searchId; +} + +//============ NAME SEARCH ============ + +// name search timer process (threaded) +static void __cdecl NameSearchTimerProc(LPVOID hWnd) +{ + // search only when it's not current updating weather. + if (CheckSearch()) + { + if (name1[0] != 0) NameSearch(name1, searchId); // search nickname field + } + // broadcast the result + ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)searchId, 0); + + // exit the search + searchId = -1; +} + +static INT_PTR CALLBACK WeatherSearchAdvancedDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetFocus(GetDlgItem(hwndDlg, IDC_SEARCHCITY)); + return TRUE; + + case WM_COMMAND: + if (HIWORD(wParam) == EN_SETFOCUS) + PostMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndDlg); + } + return FALSE; +} + +INT_PTR WeatherCreateAdvancedSearchUI(WPARAM wParam, LPARAM lParam) +{ + HWND parent = (HWND)lParam; + + if (parent) + return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHCITY), parent, WeatherSearchAdvancedDlgProc, 0); + + return 0; +} + +// service function for name search +INT_PTR WeatherAdvancedSearch(WPARAM wParam, LPARAM lParam) +{ + if (searchId != -1) return 0; //only one search at a time + searchId = 1; + + GetDlgItemText((HWND)lParam, IDC_SEARCHCITY, name1, 256); + + // search for the weather station using a thread + mir_forkthread(NameSearchTimerProc, NULL); + return searchId; +} + +//============ SEARCH FOR A WEATHER STATION USING ID ============ + +// Seaching station ID from a single weather service (Threaded) +// sID = search string for the station ID +// searchId = -1 +// sData = the ID search data for that particular weather service +// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather) +int IDSearchProc(char *sID, const int searchId, WIIDSEARCH *sData, char *svc, char *svcname) +{ + PROTOSEARCHRESULT psr = {0}; + char str[MAX_DATA_LEN] = "", newID[MAX_DATA_LEN]; + + if (sData->Available) + { + char loc[255], *szData = NULL; + + // load the page + mir_snprintf(loc, sizeof(loc), sData->SearchURL , sID); + if (InternetDownloadFile(loc, NULL, &szData) == 0) + { + char* szInfo = szData; + + // not found + if (strstr(szInfo, sData->NotFoundStr) == NULL) + GetDataValue(&sData->Name, str, &szInfo); + } + mir_free(szData); + // Station not found exit + if (str[0] == 0) return 1; + } + + // give no station name but only ID if the search is unavailable + else strcpy(str, Translate("")); + mir_snprintf(newID, sizeof(newID), "%s/%s", svc, sID); + + // set the search result and broadcast it + psr.cbSize=sizeof(psr); + psr.nick=str; + psr.firstName=" "; + psr.lastName=svcname; + psr.email=newID; + ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); + + return 0; +} + +// ID search (Threaded) +// sID: the ID to search for +// searchId: don't change +// return 0 if no error +int IDSearch(char *sID, const int searchId) +{ + // for a normal ID search (ID != #) + if (strcmp(sID, "#")) + { + WIDATALIST *Item = WIHead; + + // search every weather service using the search station ID + while (Item != NULL) + { + IDSearchProc(sID, searchId, &Item->Data.IDSearch, Item->Data.InternalName, Item->Data.DisplayName); + Item = Item->next; + } + NetlibHttpDisconnect(); + } + // if the station ID is #, return a dummy result and quit the funciton + else + { + PROTOSEARCHRESULT psr = {0}; + // return an empty contact on "#" + psr.cbSize=sizeof(psr); + psr.nick=Translate(""); // to be entered + psr.firstName=" "; + psr.lastName=""; + psr.email=Translate(""); // to be entered + ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA,(HANDLE)searchId,(LPARAM)&psr); + } + + return 0; +} + +//============ SEARCH FOR A WEATHER STATION BY NAME ============ + +// Seaching station name from a single weather service (Threaded) +// name = the name of the weather station to be searched +// searchId = -1 +// sData = the name search data for that particular weather service +// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather) +int NameSearchProc(char *name, const int searchId, WINAMESEARCH *sData, char *svc, char *svcname) +{ + PROTOSEARCHRESULT psr; + char *search, str[MAX_DATA_LEN], loc[256], sID[MAX_DATA_LEN], Name[MAX_DATA_LEN], *szData = NULL; + + // replace spaces with %20 + char *pstr = (char*)CallService(MS_NETLIB_URLENCODE, 0, (LPARAM) name); + wsprintf(loc, sData->SearchURL, pstr); + HeapFree(GetProcessHeap(), 0, pstr); + + if (InternetDownloadFile(loc, NULL, &szData) == 0) + { + char* szInfo = szData; + search = strstr(szInfo, sData->NotFoundStr); // determine if data is available + if (search == NULL) // if data is found + { + // test if it is single result + if (sData->Single.Available && sData->Multiple.Available) + search = strstr(szInfo, sData->SingleStr); + // for single result + if (sData->Single.Available && (search != NULL || !sData->Multiple.Available)) // single result + { + // if station ID appears first in the downloaded data + if (!_stricmp(sData->Single.First, "ID")) + { + GetDataValue(&sData->Single.ID, str, &szInfo); + wsprintf(sID, "%s/%s", svc, str); + GetDataValue(&sData->Single.Name, Name, &szInfo); + } + // if station name appears first in the downloaded data + else if (!_stricmp(sData->Single.First, "NAME")) + { + GetDataValue(&sData->Single.Name, Name, &szInfo); + GetDataValue(&sData->Single.ID, str, &szInfo); + wsprintf(sID, "%s/%s", svc, str); + } + // if no station ID is obtained, quit the search + if (str[0] == 0) + { + mir_free(szData); + return 1; + } + // if can't get the name, use the search string as name + if (Name[0] == 0) strcpy(Name, name); + + // set the data and broadcast it + memset(&psr,0,sizeof(psr)); + psr.cbSize=sizeof(psr); + psr.nick=Name; + psr.firstName=" "; + psr.lastName=svcname; + psr.email=sID; + psr.id=sID; + ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA,(HANDLE)searchId,(LPARAM)&psr); + mir_free(szData); + return 0; + } + // for multiple result + else if (sData->Multiple.Available) // multiple results + { + // search for the next occurrence of the string + for (;;) + { + // if station ID appears first in the downloaded data + if (!_stricmp(sData->Multiple.First, "ID")) { + GetDataValue(&sData->Multiple.ID, str, &szInfo); + wsprintf(sID, "%s/%s", svc, str); + GetDataValue(&sData->Multiple.Name, Name, &szInfo); + } + // if station name appears first in the downloaded data + else if (!_stricmp(sData->Multiple.First, "NAME")) { + GetDataValue(&sData->Multiple.Name, Name, &szInfo); + GetDataValue(&sData->Multiple.ID, str, &szInfo); + wsprintf(sID, "%s/%s", svc, str); + } + // if no station ID is obtained, search completed and quit the search + if (str[0] == 0) break; + // if can't get the name, use the search string as name + if (Name[0] == 0) strcpy(Name, name); + + memset(&psr,0,sizeof(psr)); + psr.cbSize=sizeof(psr); + psr.nick=Name; + psr.firstName=""; + psr.lastName=svcname; + psr.email=sID; + psr.id=sID; + ProtoBroadcastAck(WEATHERPROTONAME,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA, + (HANDLE)searchId,(LPARAM)&psr); + } + } + } + mir_free(szData); + return 0; + } + mir_free(szData); + return 1; +} + +// name search (Threaded) +// name: the station name to search for +// searchId: don't change +// return 0 if no error +int NameSearch(char *name, const int searchId) +{ + WIDATALIST *Item = WIHead; + + // search every weather service using the search station name + while (Item != NULL) + { + if (Item->Data.NameSearch.Single.Available || Item->Data.NameSearch.Multiple.Available) + NameSearchProc(name, searchId, &Item->Data.NameSearch, Item->Data.InternalName, Item->Data.DisplayName); + Item = Item->next; + } + NetlibHttpDisconnect(); + + return 0; +} + +//====================== MENU ITEM FUNCTION ============ + +// add a new weather station via find/add dialog +int WeatherAdd(WPARAM wParam, LPARAM lParam) +{ + DBWriteContactSettingString(NULL, "FindAdd", "LastSearched", "Weather"); + CallService(MS_FINDADD_FINDADD, 0, 0); + return 0; +} diff --git a/protocols/weather/weather_contacts.c b/protocols/weather/weather_contacts.c deleted file mode 100644 index da876963b0..0000000000 --- a/protocols/weather/weather_contacts.c +++ /dev/null @@ -1,515 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* This file contain the source that is related to weather contacts, -include the links, edit settings, and loading weather information for -the contact. -*/ - -#include "weather.h" - -//============ BASIC CONTACTS FUNCTIONS AND LINKS ============ - -// view weather log for the contact -// wParam = current contact -INT_PTR ViewLog(WPARAM wParam,LPARAM lParam) -{ - DBVARIANT dbv; - // see if the log path is set - if (!DBGetContactSettingTString((HANDLE)wParam,WEATHERPROTONAME,"Log",&dbv)) - { - if (dbv.pszVal[0] != 0) - ShellExecute((HWND)lParam, _T("open"), dbv.ptszVal, _T(""), _T(""), SW_SHOW); - DBFreeVariant(&dbv); - } - else // display warning dialog if no path is specified - MessageBox(NULL, TranslateT("Weather condition was not logged."), - TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); - return 0; -} - -// read complete forecast -// wParam = current contact -INT_PTR LoadForecast(WPARAM wParam,LPARAM lParam) -{ - char id[256], loc[256], loc2[256]; - - // get station ID - GetStationID((HANDLE)wParam, id, sizeof(id)); - - if (id[0] != 0) - { - GetID(id); - - // check if the complte forecast URL is set. If it is not, display warning and quit - if (DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "InfoURL", loc2, sizeof(loc2)) || loc2[0] == 0) - { - MessageBox(NULL, TranslateT("The URL for complete forcast have not been set. You can set it from the Edit Settings dialog."), - TranslateT("Weather Protocol"), MB_ICONINFORMATION); - return 1; - } - // set the url and open the webpage - mir_snprintf(loc, sizeof(loc), loc2, id); - CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); - } - return 0; -} - -// load weather map -// wParam = current contact -INT_PTR WeatherMap(WPARAM wParam,LPARAM lParam) -{ - char id[256], loc[256], loc2[256]; - - GetStationID((HANDLE)wParam, id, sizeof(id)); - - if (id[0] != 0) - { - GetID(id); - - // check if the weather map URL is set. If it is not, display warning and quit - if (DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "MapURL", loc2, sizeof(loc2)) || loc2[0] == 0) - { - MessageBox(NULL, TranslateT("The URL for weather map have not been set. You can set it from the Edit Settings dialog."), TranslateT("Weather Protocol"), MB_ICONINFORMATION); - return 1; - } - // set the url and open the webpage - mir_snprintf(loc, sizeof(loc), loc2, id); - CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); - } - - return 0; -} - -//============ EDIT SETTINGS ============ - -// show edit settings dialog -// wParam = current contact -INT_PTR EditSettings(WPARAM wParam,LPARAM lParam) -{ - HWND hEditDlg = WindowList_Find(hWindowList, (HANDLE)wParam); - - // search the dialog list to prevent multiple instance of dialog for the same contact - if (hEditDlg != NULL) - { - // if the dialog box already opened, bring it to the front - SetForegroundWindow(hEditDlg); - SetFocus(hEditDlg); - } - else - { - if(IsMyContact((HANDLE)wParam)) - { - // if the dialog box is not opened, open a new one - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_EDIT), NULL, DlgProcChange, (LPARAM)wParam); - } - } - - return 0; -} - -typedef struct -{ - HANDLE hContact; - HICON hRename; - HICON hUserDetail; - HICON hFile; - HICON hSrchAll; -} CntSetWndDataType; - -// edit weather settings -// lParam = current contact -INT_PTR CALLBACK DlgProcChange(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - DBVARIANT dbv; - char str[256], str2[256], city[256], filter[256], *pfilter, loc[512], *chop; - OPENFILENAME ofn; // common dialog box structure - HANDLE hContact; - WIDATA *sData; - CntSetWndDataType *wndData = NULL; - - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - - wndData = mir_alloc(sizeof(CntSetWndDataType)); - wndData->hContact = hContact = (HANDLE)lParam; - wndData->hRename = LoadSkinnedIcon(SKINICON_OTHER_RENAME); - wndData->hUserDetail = LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS); - wndData->hFile = LoadSkinnedIcon(SKINICON_EVENT_FILE); - wndData->hSrchAll = LoadSkinnedIcon(SKINICON_OTHER_SEARCHALL); - - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)wndData); - - // set button images - SendDlgItemMessage(hwndDlg, IDC_GETNAME, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); - SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hUserDetail); - SendDlgItemMessage(hwndDlg, IDC_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hFile); - SendDlgItemMessage(hwndDlg, IDC_VIEW1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll); - SendDlgItemMessage(hwndDlg, IDC_RESET1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); - SendDlgItemMessage(hwndDlg, IDC_VIEW2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll); - SendDlgItemMessage(hwndDlg, IDC_RESET2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); - - // make all buttons flat - SendDlgItemMessage(hwndDlg,IDC_GETNAME, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_SVCINFO, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_BROWSE, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_VIEW1, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_RESET1, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_VIEW2, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg,IDC_RESET2, BUTTONSETASFLATBTN, 0, 0); - - // set tooltip for the buttons - SendDlgItemMessage(hwndDlg,IDC_GETNAME, BUTTONADDTOOLTIP, (WPARAM)"Get city name from ID", 0); - SendDlgItemMessage(hwndDlg,IDC_SVCINFO, BUTTONADDTOOLTIP, (WPARAM)"Weather INI information", 0); - SendDlgItemMessage(hwndDlg,IDC_BROWSE, BUTTONADDTOOLTIP, (WPARAM)"Browse", 0); - SendDlgItemMessage(hwndDlg,IDC_VIEW1, BUTTONADDTOOLTIP, (WPARAM)"View webpage", 0); - SendDlgItemMessage(hwndDlg,IDC_RESET1, BUTTONADDTOOLTIP, (WPARAM)"Reset to default", 0); - SendDlgItemMessage(hwndDlg,IDC_VIEW2, BUTTONADDTOOLTIP, (WPARAM)"View webpage", 0); - SendDlgItemMessage(hwndDlg, IDC_RESET2, BUTTONADDTOOLTIP, (WPARAM)"Reset to default", 0); - - // save the handle for the contact - WindowList_Add(hWindowList, hwndDlg, hContact); - - // start to get the settings - // if the setting not exist, leave the dialog box blank - if(!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) - { - SetDlgItemTextA(hwndDlg,IDC_ID,dbv.pszVal); - // check if the station is a default station - if (!strcmp(dbv.pszVal, opt.Default)) - CheckDlgButton(hwndDlg, IDC_DEFA, TRUE); - else CheckDlgButton(hwndDlg, IDC_DEFA, FALSE); - DBFreeVariant(&dbv); - } - if(!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Nick",&dbv)) - { - SetDlgItemText(hwndDlg,IDC_NAME,dbv.ptszVal); - DBFreeVariant(&dbv); - } - if(!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Log",&dbv)) - { - SetDlgItemText(hwndDlg, IDC_LOG, dbv.ptszVal); - // if the log path is not empty, check the checkbox for external log - if (dbv.ptszVal[0]) CheckDlgButton(hwndDlg, IDC_External, TRUE); - DBFreeVariant(&dbv); - } - // enable/disable the browse button depending on the value of external log checkbox - EnableWindow(GetDlgItem(hwndDlg,IDC_BROWSE),(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); - - // other checkbox options - CheckDlgButton(hwndDlg, IDC_DPop, DBGetContactSettingByte(hContact,WEATHERPROTONAME,"DPopUp",FALSE)); - CheckDlgButton(hwndDlg, IDC_DAutoUpdate, DBGetContactSettingByte(hContact,WEATHERPROTONAME, - "DAutoUpdate",FALSE)); - CheckDlgButton(hwndDlg, IDC_Internal, DBGetContactSettingByte(hContact,WEATHERPROTONAME,"History",0)); - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"InfoURL",&dbv)) - { - SetDlgItemText(hwndDlg,IDC_IURL,dbv.pszVal); - DBFreeVariant(&dbv); - } - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"MapURL",&dbv)) - { - SetDlgItemText(hwndDlg,IDC_MURL,dbv.pszVal); - DBFreeVariant(&dbv); - } - - // display the dialog box and free memory - Utils_RestoreWindowPositionNoMove(hwndDlg,NULL,WEATHERPROTONAME,"EditSetting_"); - ShowWindow(hwndDlg,SW_SHOW); - break; - - case WM_COMMAND: - wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - hContact = wndData ? wndData->hContact : NULL; - - switch(LOWORD(wParam)) - { - case IDC_ID: - // check if there are 2 parts in the ID (svc/id) seperated by "/" - // if not, don't let user change the setting - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - chop = strstr(str, "/"); - if (chop == NULL) - EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),FALSE); - else - EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),TRUE); - break; - case IDC_NAME: - // check if station name is entered - // if not, don't let user change the setting - GetDlgItemText(hwndDlg,IDC_NAME,str,sizeof(str)); - EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),str[0] != 0); - break; - case IDC_GETNAME: - { - // the button for getting station name from the internet - // this function uses the ID search for add/find weather station - WIDATA *sData; - - if (!CheckSearch()) return TRUE; // don't download if update is in progress - // get the weather update data using the string in the ID field - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - GetSvc(str); - sData = GetWIData(str); - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - GetID(str); - // if ID search is available, do it - if (sData->IDSearch.Available) - { - char *szData = NULL; - - // load the page - wsprintf(loc, sData->IDSearch.SearchURL, str); - str[0] = 0; - if (InternetDownloadFile(loc, NULL, &szData) == 0) - { - char *szInfo = szData; - char* search = strstr(szInfo, sData->IDSearch.NotFoundStr); - - // if the page is found (ie. valid ID), get the name of the city - if (search == NULL) - GetDataValue(&sData->IDSearch.Name, str, &szInfo); - - // free memory - mir_free(szData); - } - NetlibHttpDisconnect(); - } - // give no station name but only ID if the search is unavailable - if (str[0] != 0) SetDlgItemText(hwndDlg,IDC_NAME,str); - break; - } - case IDC_External: - // enable/disable the borwse button depending if the external log is enabled - EnableWindow(GetDlgItem(hwndDlg,IDC_BROWSE),(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); - if (!(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)) return TRUE; - - case IDC_BROWSE: // fall through - // browse for the external log file - GetDlgItemText(hwndDlg,IDC_LOG,str,sizeof(str)); - // Initialize OPENFILENAME - ZeroMemory(&ofn, sizeof(OPENFILENAME)); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hwndDlg; - ofn.lpstrFile = str; - ofn.nMaxFile = sizeof(str); - // set filters - strcpy(filter,Translate("Text Files")); - strcat(filter," (*.txt)"); - pfilter=filter+strlen(filter)+1; - strcpy(pfilter,"*.txt"); - pfilter=pfilter+strlen(pfilter)+1; - strcpy(pfilter,Translate("All Files")); - strcat(pfilter," (*.*)"); - pfilter=pfilter+strlen(pfilter)+1; - strcpy(pfilter,"*.*"); - pfilter=pfilter+strlen(pfilter)+1; - *pfilter='\0'; - ofn.lpstrFilter = filter; - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST; - - // Display a Open dialog box and put the file name on the dialog - if(GetOpenFileName(&ofn)) - SetDlgItemText(hwndDlg,IDC_LOG,ofn.lpstrFile); - // if there is no log file specified, disable external logging - EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),ofn.lpstrFile[0] != 0); - break; - - case IDC_VIEW1: - // view the page for more info - GetDlgItemText(hwndDlg,IDC_IURL,str,sizeof(str)); - if (str[0] == 0) return TRUE; - GetDlgItemText(hwndDlg,IDC_ID,str2,sizeof(str2)); - GetID(str2); - wsprintf(loc, str, str2); - CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); - break; - - case IDC_VIEW2: - // view the page for weather map - GetDlgItemText(hwndDlg,IDC_MURL,str,sizeof(str)); - if (str[0] == 0) return TRUE; - GetDlgItemText(hwndDlg,IDC_ID,str2,sizeof(str2)); - GetID(str2); - wsprintf(loc, str, str2); - CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); - break; - - case IDC_RESET1: - // reset the more info url to service default - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - GetSvc(str); - sData = GetWIData(str); - SetDlgItemText(hwndDlg,IDC_IURL,sData->DefaultURL); - break; - - case IDC_RESET2: - // reset the weathe map url to service default - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - GetSvc(str); - sData = GetWIData(str); - SetDlgItemText(hwndDlg,IDC_MURL,sData->DefaultMap); - break; - - case IDC_SVCINFO: - // display the information of the ini file used by the weather station - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - GetSvc(str); - GetINIInfo(str); - break; - - case IDC_CHANGE: - // temporary disable the protocol while applying the change - // start writing the new settings to database - GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "ID", str); - if ((BYTE)IsDlgButtonChecked(hwndDlg,IDC_DEFA)) { // if default station is set - strcpy(opt.Default, str); - opt.DefStn = hContact; - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); - } - GetDlgItemText(hwndDlg,IDC_NAME,city,sizeof(city)); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", city); - wsprintf(str2, Translate("Current weather information for %s."), city); - if ((BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)) - { - GetDlgItemText(hwndDlg,IDC_LOG,str,sizeof(str)); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Log", str); - } - else - DBDeleteContactSetting(hContact, WEATHERPROTONAME, "Log"); - GetDlgItemTextA(hwndDlg,IDC_IURL,str,sizeof(str)); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", str); - GetDlgItemTextA(hwndDlg,IDC_MURL,str,sizeof(str)); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", str); - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE); - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE); - AvatarDownloaded(hContact); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "About", str2); - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"History",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_Internal)); - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"Overwrite",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_Overwrite)); - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"DPopUp",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DPop)); - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"DAutoUpdate",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DAutoUpdate)); - - // re-enable the protocol and update the data for the station - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); - UpdateSingleStation((WPARAM)hContact, 0); - - case IDCANCEL: // fall through - // remove the dialog from window list and close it - DestroyWindow(hwndDlg); - break; - } - break; - - case WM_CLOSE: - // remove the dialog from window list and close it - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hFile, 0); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hRename, 0); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hSrchAll, 0); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hUserDetail, 0); - mir_free(wndData); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - - WindowList_Remove(hWindowList, hwndDlg); - Utils_SaveWindowPosition(hwndDlg,NULL,WEATHERPROTONAME,"EditSetting_"); - break; - } - return FALSE; -} - -//============ CONTACT DELETION ============ - -// when a contact is deleted, make sure some other contact take over the default station -// wParam = deleted contact -int ContactDeleted(WPARAM wParam,LPARAM lParam) -{ - DBVARIANT dbv; - - if(!IsMyContact((HANDLE)wParam)) return 0; - - removeWindow((HANDLE)wParam); - - // exit this function if it is not default station - if (!DBGetContactSettingString((HANDLE)wParam, WEATHERPROTONAME, "ID", &dbv)) - { - if (strcmp(dbv.pszVal, opt.Default)) - { - DBFreeVariant(&dbv); - return 0; - } - DBFreeVariant(&dbv); - } - - // now the default station is deleted, try to get a new one - { - // start looking for other weather stations - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while(hContact) - { - if(IsMyContact(hContact)) - { - if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "ID", &dbv)) - { - // if the station is not a default station, set it as the new default station - // this is the first weather station encountered from the search - if (strcmp(opt.Default, dbv.pszVal)) - { - strcpy(opt.Default, dbv.pszVal); - opt.DefStn = hContact; - DBFreeVariant(&dbv); - if (!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Nick",&dbv)) - { - TCHAR str[255]; - mir_sntprintf(str, SIZEOF(str), TranslateT("%s is now the default weather station"), dbv.ptszVal); - DBFreeVariant(&dbv); - MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); - } - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); - return 0; // exit this function quickly - } - DBFreeVariant(&dbv); - } - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - // got here if no more weather station left - opt.Default[0] = 0; // no default station - opt.DefStn = NULL; - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); - } - return 0; -} - -BOOL IsMyContact(HANDLE hContact) -{ - const char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - return szProto != NULL && strcmp(WEATHERPROTONAME, szProto) == 0; -} diff --git a/protocols/weather/weather_contacts.cpp b/protocols/weather/weather_contacts.cpp new file mode 100644 index 0000000000..94aae312fd --- /dev/null +++ b/protocols/weather/weather_contacts.cpp @@ -0,0 +1,515 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* This file contain the source that is related to weather contacts, +include the links, edit settings, and loading weather information for +the contact. +*/ + +#include "weather.h" + +//============ BASIC CONTACTS FUNCTIONS AND LINKS ============ + +// view weather log for the contact +// wParam = current contact +INT_PTR ViewLog(WPARAM wParam,LPARAM lParam) +{ + DBVARIANT dbv; + // see if the log path is set + if (!DBGetContactSettingTString((HANDLE)wParam,WEATHERPROTONAME,"Log",&dbv)) + { + if (dbv.pszVal[0] != 0) + ShellExecute((HWND)lParam, _T("open"), dbv.ptszVal, _T(""), _T(""), SW_SHOW); + DBFreeVariant(&dbv); + } + else // display warning dialog if no path is specified + MessageBox(NULL, TranslateT("Weather condition was not logged."), + TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); + return 0; +} + +// read complete forecast +// wParam = current contact +INT_PTR LoadForecast(WPARAM wParam,LPARAM lParam) +{ + char id[256], loc[256], loc2[256]; + + // get station ID + GetStationID((HANDLE)wParam, id, sizeof(id)); + + if (id[0] != 0) + { + GetID(id); + + // check if the complte forecast URL is set. If it is not, display warning and quit + if (DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "InfoURL", loc2, sizeof(loc2)) || loc2[0] == 0) + { + MessageBox(NULL, TranslateT("The URL for complete forcast have not been set. You can set it from the Edit Settings dialog."), + TranslateT("Weather Protocol"), MB_ICONINFORMATION); + return 1; + } + // set the url and open the webpage + mir_snprintf(loc, sizeof(loc), loc2, id); + CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); + } + return 0; +} + +// load weather map +// wParam = current contact +INT_PTR WeatherMap(WPARAM wParam,LPARAM lParam) +{ + char id[256], loc[256], loc2[256]; + + GetStationID((HANDLE)wParam, id, sizeof(id)); + + if (id[0] != 0) + { + GetID(id); + + // check if the weather map URL is set. If it is not, display warning and quit + if (DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "MapURL", loc2, sizeof(loc2)) || loc2[0] == 0) + { + MessageBox(NULL, TranslateT("The URL for weather map have not been set. You can set it from the Edit Settings dialog."), TranslateT("Weather Protocol"), MB_ICONINFORMATION); + return 1; + } + // set the url and open the webpage + mir_snprintf(loc, sizeof(loc), loc2, id); + CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); + } + + return 0; +} + +//============ EDIT SETTINGS ============ + +// show edit settings dialog +// wParam = current contact +INT_PTR EditSettings(WPARAM wParam,LPARAM lParam) +{ + HWND hEditDlg = WindowList_Find(hWindowList, (HANDLE)wParam); + + // search the dialog list to prevent multiple instance of dialog for the same contact + if (hEditDlg != NULL) + { + // if the dialog box already opened, bring it to the front + SetForegroundWindow(hEditDlg); + SetFocus(hEditDlg); + } + else + { + if(IsMyContact((HANDLE)wParam)) + { + // if the dialog box is not opened, open a new one + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_EDIT), NULL, DlgProcChange, (LPARAM)wParam); + } + } + + return 0; +} + +typedef struct +{ + HANDLE hContact; + HICON hRename; + HICON hUserDetail; + HICON hFile; + HICON hSrchAll; +} CntSetWndDataType; + +// edit weather settings +// lParam = current contact +INT_PTR CALLBACK DlgProcChange(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char str[256], str2[256], city[256], filter[256], *pfilter, loc[512], *chop; + OPENFILENAME ofn; // common dialog box structure + HANDLE hContact; + WIDATA *sData; + CntSetWndDataType *wndData = NULL; + + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + wndData = ( CntSetWndDataType* )mir_alloc(sizeof(CntSetWndDataType)); + wndData->hContact = hContact = (HANDLE)lParam; + wndData->hRename = LoadSkinnedIcon(SKINICON_OTHER_RENAME); + wndData->hUserDetail = LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS); + wndData->hFile = LoadSkinnedIcon(SKINICON_EVENT_FILE); + wndData->hSrchAll = LoadSkinnedIcon(SKINICON_OTHER_SEARCHALL); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)wndData); + + // set button images + SendDlgItemMessage(hwndDlg, IDC_GETNAME, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); + SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hUserDetail); + SendDlgItemMessage(hwndDlg, IDC_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hFile); + SendDlgItemMessage(hwndDlg, IDC_VIEW1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll); + SendDlgItemMessage(hwndDlg, IDC_RESET1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); + SendDlgItemMessage(hwndDlg, IDC_VIEW2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll); + SendDlgItemMessage(hwndDlg, IDC_RESET2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename); + + // make all buttons flat + SendDlgItemMessage(hwndDlg,IDC_GETNAME, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_SVCINFO, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_BROWSE, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_VIEW1, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_RESET1, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_VIEW2, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg,IDC_RESET2, BUTTONSETASFLATBTN, 0, 0); + + // set tooltip for the buttons + SendDlgItemMessage(hwndDlg,IDC_GETNAME, BUTTONADDTOOLTIP, (WPARAM)"Get city name from ID", 0); + SendDlgItemMessage(hwndDlg,IDC_SVCINFO, BUTTONADDTOOLTIP, (WPARAM)"Weather INI information", 0); + SendDlgItemMessage(hwndDlg,IDC_BROWSE, BUTTONADDTOOLTIP, (WPARAM)"Browse", 0); + SendDlgItemMessage(hwndDlg,IDC_VIEW1, BUTTONADDTOOLTIP, (WPARAM)"View webpage", 0); + SendDlgItemMessage(hwndDlg,IDC_RESET1, BUTTONADDTOOLTIP, (WPARAM)"Reset to default", 0); + SendDlgItemMessage(hwndDlg,IDC_VIEW2, BUTTONADDTOOLTIP, (WPARAM)"View webpage", 0); + SendDlgItemMessage(hwndDlg, IDC_RESET2, BUTTONADDTOOLTIP, (WPARAM)"Reset to default", 0); + + // save the handle for the contact + WindowList_Add(hWindowList, hwndDlg, hContact); + + // start to get the settings + // if the setting not exist, leave the dialog box blank + if(!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) + { + SetDlgItemTextA(hwndDlg,IDC_ID,dbv.pszVal); + // check if the station is a default station + if (!strcmp(dbv.pszVal, opt.Default)) + CheckDlgButton(hwndDlg, IDC_DEFA, TRUE); + else CheckDlgButton(hwndDlg, IDC_DEFA, FALSE); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Nick",&dbv)) + { + SetDlgItemText(hwndDlg,IDC_NAME,dbv.ptszVal); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Log",&dbv)) + { + SetDlgItemText(hwndDlg, IDC_LOG, dbv.ptszVal); + // if the log path is not empty, check the checkbox for external log + if (dbv.ptszVal[0]) CheckDlgButton(hwndDlg, IDC_External, TRUE); + DBFreeVariant(&dbv); + } + // enable/disable the browse button depending on the value of external log checkbox + EnableWindow(GetDlgItem(hwndDlg,IDC_BROWSE),(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); + + // other checkbox options + CheckDlgButton(hwndDlg, IDC_DPop, DBGetContactSettingByte(hContact,WEATHERPROTONAME,"DPopUp",FALSE)); + CheckDlgButton(hwndDlg, IDC_DAutoUpdate, DBGetContactSettingByte(hContact,WEATHERPROTONAME, + "DAutoUpdate",FALSE)); + CheckDlgButton(hwndDlg, IDC_Internal, DBGetContactSettingByte(hContact,WEATHERPROTONAME,"History",0)); + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"InfoURL",&dbv)) + { + SetDlgItemText(hwndDlg,IDC_IURL,dbv.pszVal); + DBFreeVariant(&dbv); + } + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"MapURL",&dbv)) + { + SetDlgItemText(hwndDlg,IDC_MURL,dbv.pszVal); + DBFreeVariant(&dbv); + } + + // display the dialog box and free memory + Utils_RestoreWindowPositionNoMove(hwndDlg,NULL,WEATHERPROTONAME,"EditSetting_"); + ShowWindow(hwndDlg,SW_SHOW); + break; + + case WM_COMMAND: + wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + hContact = wndData ? wndData->hContact : NULL; + + switch(LOWORD(wParam)) + { + case IDC_ID: + // check if there are 2 parts in the ID (svc/id) seperated by "/" + // if not, don't let user change the setting + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + chop = strstr(str, "/"); + if (chop == NULL) + EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),FALSE); + else + EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),TRUE); + break; + case IDC_NAME: + // check if station name is entered + // if not, don't let user change the setting + GetDlgItemText(hwndDlg,IDC_NAME,str,sizeof(str)); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),str[0] != 0); + break; + case IDC_GETNAME: + { + // the button for getting station name from the internet + // this function uses the ID search for add/find weather station + WIDATA *sData; + + if (!CheckSearch()) return TRUE; // don't download if update is in progress + // get the weather update data using the string in the ID field + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + GetSvc(str); + sData = GetWIData(str); + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + GetID(str); + // if ID search is available, do it + if (sData->IDSearch.Available) + { + char *szData = NULL; + + // load the page + wsprintf(loc, sData->IDSearch.SearchURL, str); + str[0] = 0; + if (InternetDownloadFile(loc, NULL, &szData) == 0) + { + char *szInfo = szData; + char* search = strstr(szInfo, sData->IDSearch.NotFoundStr); + + // if the page is found (ie. valid ID), get the name of the city + if (search == NULL) + GetDataValue(&sData->IDSearch.Name, str, &szInfo); + + // free memory + mir_free(szData); + } + NetlibHttpDisconnect(); + } + // give no station name but only ID if the search is unavailable + if (str[0] != 0) SetDlgItemText(hwndDlg,IDC_NAME,str); + break; + } + case IDC_External: + // enable/disable the borwse button depending if the external log is enabled + EnableWindow(GetDlgItem(hwndDlg,IDC_BROWSE),(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); + if (!(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)) return TRUE; + + case IDC_BROWSE: // fall through + // browse for the external log file + GetDlgItemText(hwndDlg,IDC_LOG,str,sizeof(str)); + // Initialize OPENFILENAME + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hwndDlg; + ofn.lpstrFile = str; + ofn.nMaxFile = sizeof(str); + // set filters + strcpy(filter,Translate("Text Files")); + strcat(filter," (*.txt)"); + pfilter=filter+strlen(filter)+1; + strcpy(pfilter,"*.txt"); + pfilter=pfilter+strlen(pfilter)+1; + strcpy(pfilter,Translate("All Files")); + strcat(pfilter," (*.*)"); + pfilter=pfilter+strlen(pfilter)+1; + strcpy(pfilter,"*.*"); + pfilter=pfilter+strlen(pfilter)+1; + *pfilter='\0'; + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST; + + // Display a Open dialog box and put the file name on the dialog + if(GetOpenFileName(&ofn)) + SetDlgItemText(hwndDlg,IDC_LOG,ofn.lpstrFile); + // if there is no log file specified, disable external logging + EnableWindow(GetDlgItem(hwndDlg,IDC_CHANGE),ofn.lpstrFile[0] != 0); + break; + + case IDC_VIEW1: + // view the page for more info + GetDlgItemText(hwndDlg,IDC_IURL,str,sizeof(str)); + if (str[0] == 0) return TRUE; + GetDlgItemText(hwndDlg,IDC_ID,str2,sizeof(str2)); + GetID(str2); + wsprintf(loc, str, str2); + CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); + break; + + case IDC_VIEW2: + // view the page for weather map + GetDlgItemText(hwndDlg,IDC_MURL,str,sizeof(str)); + if (str[0] == 0) return TRUE; + GetDlgItemText(hwndDlg,IDC_ID,str2,sizeof(str2)); + GetID(str2); + wsprintf(loc, str, str2); + CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, (WPARAM)loc); + break; + + case IDC_RESET1: + // reset the more info url to service default + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + GetSvc(str); + sData = GetWIData(str); + SetDlgItemText(hwndDlg,IDC_IURL,sData->DefaultURL); + break; + + case IDC_RESET2: + // reset the weathe map url to service default + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + GetSvc(str); + sData = GetWIData(str); + SetDlgItemText(hwndDlg,IDC_MURL,sData->DefaultMap); + break; + + case IDC_SVCINFO: + // display the information of the ini file used by the weather station + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + GetSvc(str); + GetINIInfo(str); + break; + + case IDC_CHANGE: + // temporary disable the protocol while applying the change + // start writing the new settings to database + GetDlgItemText(hwndDlg,IDC_ID,str,sizeof(str)); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "ID", str); + if ((BYTE)IsDlgButtonChecked(hwndDlg,IDC_DEFA)) { // if default station is set + strcpy(opt.Default, str); + opt.DefStn = hContact; + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); + } + GetDlgItemText(hwndDlg,IDC_NAME,city,sizeof(city)); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", city); + wsprintf(str2, Translate("Current weather information for %s."), city); + if ((BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)) + { + GetDlgItemText(hwndDlg,IDC_LOG,str,sizeof(str)); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Log", str); + } + else + DBDeleteContactSetting(hContact, WEATHERPROTONAME, "Log"); + GetDlgItemTextA(hwndDlg,IDC_IURL,str,sizeof(str)); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "InfoURL", str); + GetDlgItemTextA(hwndDlg,IDC_MURL,str,sizeof(str)); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MapURL", str); + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE); + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE); + AvatarDownloaded(hContact); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "About", str2); + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"History",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_Internal)); + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"Overwrite",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_Overwrite)); + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_External)); + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"DPopUp",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DPop)); + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"DAutoUpdate",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DAutoUpdate)); + + // re-enable the protocol and update the data for the station + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); + UpdateSingleStation((WPARAM)hContact, 0); + + case IDCANCEL: // fall through + // remove the dialog from window list and close it + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + // remove the dialog from window list and close it + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hFile, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hRename, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hSrchAll, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)wndData->hUserDetail, 0); + mir_free(wndData); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + + WindowList_Remove(hWindowList, hwndDlg); + Utils_SaveWindowPosition(hwndDlg,NULL,WEATHERPROTONAME,"EditSetting_"); + break; + } + return FALSE; +} + +//============ CONTACT DELETION ============ + +// when a contact is deleted, make sure some other contact take over the default station +// wParam = deleted contact +int ContactDeleted(WPARAM wParam,LPARAM lParam) +{ + DBVARIANT dbv; + + if(!IsMyContact((HANDLE)wParam)) return 0; + + removeWindow((HANDLE)wParam); + + // exit this function if it is not default station + if (!DBGetContactSettingString((HANDLE)wParam, WEATHERPROTONAME, "ID", &dbv)) + { + if (strcmp(dbv.pszVal, opt.Default)) + { + DBFreeVariant(&dbv); + return 0; + } + DBFreeVariant(&dbv); + } + + // now the default station is deleted, try to get a new one + { + // start looking for other weather stations + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + if(IsMyContact(hContact)) + { + if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "ID", &dbv)) + { + // if the station is not a default station, set it as the new default station + // this is the first weather station encountered from the search + if (strcmp(opt.Default, dbv.pszVal)) + { + strcpy(opt.Default, dbv.pszVal); + opt.DefStn = hContact; + DBFreeVariant(&dbv); + if (!DBGetContactSettingTString(hContact,WEATHERPROTONAME,"Nick",&dbv)) + { + TCHAR str[255]; + mir_sntprintf(str, SIZEOF(str), TranslateT("%s is now the default weather station"), dbv.ptszVal); + DBFreeVariant(&dbv); + MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); + } + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); + return 0; // exit this function quickly + } + DBFreeVariant(&dbv); + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + // got here if no more weather station left + opt.Default[0] = 0; // no default station + opt.DefStn = NULL; + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); + } + return 0; +} + +BOOL IsMyContact(HANDLE hContact) +{ + const char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + return szProto != NULL && strcmp(WEATHERPROTONAME, szProto) == 0; +} diff --git a/protocols/weather/weather_conv.c b/protocols/weather/weather_conv.c deleted file mode 100644 index 23554d4d5f..0000000000 --- a/protocols/weather/weather_conv.c +++ /dev/null @@ -1,838 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -This file contain the source related unit conversion, icon assignment, -string conversions, display text parsing, etc -*/ - -#include "weather.h" - -//============ SOME HELPER FUNCTIONS ============ - -// see if a string is a number -// s = the string to be determined -// return value = true if the string is a number, false if it isn't -BOOL is_number(char *s) -{ - BOOL tag = FALSE; - // looking character by character - // for a number: numerous spaces in front, then optional +/-, then the number - // don't care anything that comes after it - while(*s != '\0') - { - if (*s >= '0' && *s <='9') return TRUE; - else if (*s == ' '); - else if (*s != '+' && *s != '-') return FALSE; - else if ((*s == '+' || *s == '-') && !tag) tag = TRUE; - else return FALSE; - s++; - } - return FALSE; -} - -static void numToStr(double num, char* str) -{ - int i = (int)(num * (opt.NoFrac ? 10 : 100)); - int u = abs(i); - - int r = u % 10; - int w = u / 10 + (r >= 5); - - if (opt.NoFrac) - { - r = 0; - } - else - { - r = w % 10; - w /= 10; - } - - if (i < 0 && (w || r)) *(str++) = '-'; - if (r) - sprintf(str, "%i.%i", w, r); - else - sprintf(str, "%i", w); -} - -//============ UNIT CONVERSIONS ============ - -// temperature conversion -// tempchar = the string containing the temperature value -// unit = the unit for temperature -// return value = the converted temperature with degree sign and unit; if fails, return N/A -void GetTemp(char *tempchar, char *unit, char* str) -{ - // unit can be C, F - double temp; - char tstr[20]; - - TrimString(tempchar); - if (tempchar[0] == '-' && tempchar[1] == ' ') - memmove(&tempchar[1], &tempchar[2], strlen(&tempchar[2])+1); - - // quit if the value obtained is N/A or not a number - if (!strcmp(tempchar, NODATA) || !strcmp(tempchar, "N/A")) - { - strcpy(str, tempchar); - return; - } - if (!is_number(tempchar)) - { - strcpy(str, NODATA); - return; - } - - // convert the string to an integer - temp = atof(tempchar); - - // convert all to F first - if (!_stricmp(unit, "C")) temp = (temp*9/5)+32; - else if (!_stricmp(unit, "K")) temp = ((temp-273.15)*9/5)+32; - - // convert to apporiate unit - switch (opt.tUnit) - { - case 1: - // rounding - numToStr((temp-32)/9*5, tstr); - if (opt.DoNotAppendUnit) - sprintf(str, "%s", tstr); - else - sprintf(str, "%s%sC", tstr, opt.DegreeSign); - break; - - case 2: - numToStr(temp, tstr); - if (opt.DoNotAppendUnit) - sprintf(str, "%s", tstr); - else - sprintf(str, "%s%sF", tstr, opt.DegreeSign); - break; - } -} - -// temperature conversion -// tempchar = the string containing the pressure value -// unit = the unit for pressure -// return value = the converted pressure with unit; if fail, return the original string -void GetPressure(char *tempchar, char *unit, char* str) -{ - // unit can be kPa, hPa, mb, in, mm, torr - double tempunit = 0, output; - int intunit; - - // convert the string to a floating point number (always positive) - // if it end up with 0, then it's not a number, return the original string and quit - output = atof(tempchar); - if (output == 0) - { - strcpy(str, tempchar); - return; - } - - // convert all to mb first - if (!_stricmp(unit, "KPA")) - tempunit = (double)output * 10; - else if (!_stricmp(unit, "HPA")) - tempunit = (double)output; - else if (!_stricmp(unit, "MB")) - tempunit = (double)output; - else if (!_stricmp(unit, "IN")) - tempunit = (double)output * 33.86388; - else if (!_stricmp(unit, "MM")) - tempunit = (double)output * 1.33322; - else if (!_stricmp(unit, "TORR")) - tempunit = (double)output * 1.33322; - - // convert to apporiate unit - switch (opt.pUnit) - { - case 1: - intunit = (int)(tempunit + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("kPa")); - break; - case 2: - intunit = (int)(tempunit + 0.5); - wsprintf(str, "%i %s", intunit, opt.DoNotAppendUnit ? "" : Translate("mb")); - break; - case 3: - intunit = (int)((tempunit*10 / 33.86388) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("in")); - break; - case 4: - intunit = (int)((tempunit*10 / 1.33322) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("mm")); - break; - default: - strcpy(str, tempchar); - break; - - } -} - -// speed conversion -// tempchar = the string containing the speed value -// unit = the unit for speed -// return value = the converted speed with unit; if fail, return "" -void GetSpeed(char *tempchar, char *unit, char *str) -{ - // unit can be km/h, mph, m/s, knots - double tempunit; - char tstr[20]; - - str[0] = 0; - - // convert the string into an integer (always positive) - // if the result is 0, then the string is not a number, return "" - tempunit = atof(tempchar); - if (tempunit == 0 && tempchar[0] != '0') return; - - // convert all to m/s first - if (!_stricmp(unit, "KM/H")) - tempunit /= 3.6; -// else if (!_stricmp(unit, "M/S")) -// tempunit = tempunit; - else if (!_stricmp(unit, "MPH")) - tempunit *= 0.44704; - else if (!_stricmp(unit, "KNOTS")) - tempunit *= 0.514444; - - // convert to apporiate unit - switch (opt.wUnit) - { - case 1: - numToStr(tempunit * 3.6, tstr); - sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("km/h")); - break; - case 2: - numToStr(tempunit, tstr); - sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("m/s")); - break; - case 3: - numToStr(tempunit / 0.44704, tstr); - sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("mph")); - break; - case 4: - numToStr(tempunit / 0.514444, tstr); - sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("knots")); - break; - } -} - -// distance conversion -// tempchar = the string containing the distance value -// unit = the unit for distance -// return value = the converted distance with unit; if fail, return original string -void GetDist(char *tempchar, char *unit, char *str) -{ - // unit can be km, miles - double tempunit = 0, output; - int intunit; - - // convert the string to a floating point number (always positive) - // if it end up with 0, then it's not a number, return the original string and quit - output = atof(tempchar); - if (output == 0) - { - strcpy(str, tempchar); - return; - } - - // convert all to km first - if (!_stricmp(unit, "KM")) - tempunit = (double)output; - else if (!_stricmp(unit, "MILES")) - tempunit = (double)output * 1.609; - - // convert to apporiate unit - switch (opt.vUnit) - { - case 1: - intunit = (int)((tempunit*10) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("km")); - break; - case 2: - intunit = (int)((tempunit*10 / 1.609) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("miles")); - break; - default: - strcpy(str, tempchar); - break; - } -} - -// elevation conversion -// tempchar = the string containing the elevation value -// unit = the unit for elevation -// return value = the converted elevation with unit; if fail, return original string -void GetElev(char *tempchar, char *unit, char *str) -{ - // unit can be ft, m - double tempunit = 0, output; - int intunit; - - // convert the string to a floating point number (always positive) - // if it end up with 0, then it's not a number, return the original string and quit - output = atof(tempchar); - if (output == 0) - { - strcpy(str, tempchar); - return; - } - - // convert all to m first - if (!_stricmp(unit, "M")) - tempunit = (double)output; - else if (!_stricmp(unit, "FT")) - tempunit = (double)output / 3.28; - - // convert to apporiate unit - switch (opt.eUnit) { - case 1: - intunit = (int)((tempunit*10 * 3.28) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("ft")); - break; - case 2: - intunit = (int)((tempunit*10) + 0.5); - wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("m")); - break; - default: - strcpy(str, tempchar); - break; - } -} - -//============ CONDITION ICON ASSIGNMENT ============ - -// assign the contact icon (status) from the condition string -// the description may be different between different sources -// cond = the string for weather condition -// return value = status for the icon (ONLINE, OFFLINE, etc) -WORD GetIcon(const char* cond, WIDATA *Data) -{ - int i; - - static const - char *statusStr[10] = - { - "Lightning", - "Fog", - "Snow Shower", - "Snow", - "Rain Shower", - "Rain", - "Partly Cloudy", - "Cloudy", - "Sunny", - "N/A" - }; - - static const - WORD statusValue[10] = - { - LIGHT, - FOG, - SSHOWER, - SNOW, - RSHOWER, - RAIN, - PCLOUDY, - CLOUDY, - SUNNY, - NA - }; - - // set the icon using ini - for (i=0; i<10; i++) { - if (IsContainedInCondList(cond, &Data->CondList[i])) - return statusValue[i]; - } - - // internal detection - if ( - strstr(cond, "mainy sunny") != NULL || - strstr(cond, "mainy clear") != NULL || - strstr(cond, "partly cloudy") != NULL || - strstr(cond, "mostly") != NULL || - strstr(cond, "clouds") != NULL) { - return PCLOUDY; - } - else if ( - strstr(cond, "sunny") != NULL || - strstr(cond, "clear") != NULL || - strstr(cond, "fair") != NULL) { - return SUNNY; - } - else if ( - strstr(cond, "thunder") != NULL || - strstr(cond, "t-storm") != NULL) { - return LIGHT; - } - else if ( - strstr(cond, "cloud") != NULL || - strstr(cond, "overcast") != NULL) { - return CLOUDY; - } - else if ( - strstr(cond, "fog") != NULL || - strstr(cond, "mist") != NULL || - strstr(cond, "smoke") != NULL || - strstr(cond, "sand") != NULL || - strstr(cond, "dust") != NULL || - strstr(cond, "haze") != NULL) { - return FOG; - } - else if ( - (strstr(cond, "shower") != NULL && strstr(cond, "snow") != NULL) || - strstr(cond, "flurries") != NULL) { - return SSHOWER; - } - else if ( - strstr(cond, "rain shower") != NULL || - strstr(cond, "shower") != NULL) - { - return RSHOWER; - } - else if ( - strstr(cond, "snow") != NULL || - strstr(cond, "ice") != NULL || - strstr(cond, "freezing") != NULL || - strstr(cond, "wintry") != NULL) { - return SNOW; - } - else if ( - strstr(cond, "drizzle") != NULL || - strstr(cond, "rain") != NULL) - { - return RAIN; - } - - // set the icon using langpack - for (i=0; i<9; i++) - { - char LangPackStr[64]; - char LangPackStr1[128]; - int j = 0; - do - { - j++; - // using the format "# Weather #" - mir_snprintf(LangPackStr, sizeof(LangPackStr), "# Weather %s %i #", statusStr[i], j); - mir_snprintf(LangPackStr1, sizeof(LangPackStr1), "%s", Translate(LangPackStr)); - CharLowerBuff(LangPackStr1, (DWORD)strlen(LangPackStr1)); - if (strstr(cond, LangPackStr1) != NULL) - return statusValue[i]; - // loop until the translation string exists (ie, the translated string is differ from original) - } - while (strcmp(Translate(LangPackStr), LangPackStr)); - } - - return NA; -} - -//============ STRING CONVERSIONS ============ - -// this function convert the string to the format with 1 upper case followed by lower case char -void CaseConv(char *str) -{ - char *pstr; - BOOL nextUp = TRUE; - - CharLowerBuff(str, (DWORD)strlen(str)); - for(pstr=str; *pstr; pstr++) - { - if (*pstr==' ' || *pstr=='-') - nextUp = TRUE; - else - { - unsigned ch = *(unsigned char*)pstr; - if (nextUp) *pstr = (char)(unsigned)CharUpper((LPSTR)ch); - nextUp = FALSE; - } - } -} - -// the next 2 functions are copied from miranda source -// str = the string to modify -void TrimString(char *str) -{ - size_t len, start; - - len = strlen(str); - while(len && (unsigned char)str[len-1] <= ' ') str[--len] = 0; - for(start=0; (unsigned char)str[start]<=' ' && str[start]; start++); - memmove(str, str+start, len-start+1); -} - -// convert \t to tab and \n to linefeed -void ConvertBackslashes(char *str) -{ - char *pstr; - for(pstr=str;*pstr;pstr=CharNext(pstr)) - { - if(*pstr=='\\') - { - switch(pstr[1]) - { - case 'n': *pstr='\n'; break; - case 't': *pstr='\t'; break; - default: *pstr=pstr[1]; break; - } - memmove(pstr+1,pstr+2,strlen(pstr+2)+1); - } - } -} - -// replace spaces with "%20" -// dis = original string -// return value = the modified string with space -> "%20" -char *GetSearchStr(char *dis) -{ - char *pstr = dis; - size_t len = strlen(dis); - while (*pstr != 0) - { - if (*pstr == ' ') - { - memmove(pstr+3, pstr+1, len); - memcpy(pstr, "%20", 3); - pstr += 2; - } - pstr++; - len--; - } - return dis; -} - -//============ ICON ASSIGNMENT ============ - -// make display and history strings -// w = WEATHERINFO data to be parsed -// dis = the string to parse -// return value = the parsed string -char* GetDisplay(WEATHERINFO *w, const char *dis, char* str) -{ - char lpzDate[32], chr, name[256], temp[2]; - DBVARIANT dbv; - size_t i; - - // Clear the string - str[0] = 0; - - // looking character by character - for (i=0; icond); break; - case 'd': // get the current date - GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, lpzDate, sizeof(lpzDate)); - strcat(str, lpzDate); break; - case 'e': strcat(str, w->dewpoint); break; - case 'f': strcat(str, w->feel); break; - case 'h': strcat(str, w->high); break; - case 'i': strcat(str, w->winddir); break; - case 'l': strcat(str, w->low); break; - case 'm': strcat(str, w->humid); break; - case 'n': strcat(str, w->city); break; - case 'p': strcat(str, w->pressure); break; - case 'r': strcat(str, w->sunrise); break; - case 's': strcat(str, w->id); break; - case 't': strcat(str, w->temp); break; - case 'u': - if (strcmp(w->update, NODATA)) strcat(str, w->update); - else strcat(str, Translate("")); - break; - case 'v': strcat(str, w->vis); break; - case 'w': strcat(str, w->wind); break; - case 'y': strcat(str, w->sunset); break; - case '%': strcat(str, "%"); break; - case '[': // custom variables - i++; - name[0] = 0; - // read the entire variable name - while (dis[i] != ']' && i < strlen(dis)) { - wsprintf(temp, "%c", dis[i++]); - strcat(name, temp); - } - // access the database to get its value - if (!DBGetContactSettingString(w->hContact, WEATHERCONDITION, name, &dbv)) - { - if (dbv.pszVal != Translate(NODATA) && dbv.pszVal != Translate("")) - strcat(str, dbv.pszVal); - DBFreeVariant(&dbv); - } - break; - } - } - // if the character is not a variable, write the original character to the new string - else - { - wsprintf(temp, "%c", dis[i]); - strcat(str, temp); - } - } - return str; -} - -char svcReturnText[MAX_TEXT_SIZE]; -INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam) -{ - WEATHERINFO winfo = LoadWeatherInfo((HANDLE)wParam); - return (INT_PTR)GetDisplay(&winfo, (char *)lParam, svcReturnText); -} - -//============ ID MANAGEMENT ============ - -// get service data module internal name -// mod/id <- the mod part -// pszID = original 2-part id, return the service internal name -void GetSvc(char *pszID) -{ - char *chop; - - chop = strstr(pszID, "/"); - if (chop != NULL) *chop = '\0'; - else pszID[0] = 0; -} - -// get the id use for update without the service internal name -// mod/id <- the id part -// pszID = original 2-part id, return the single part id -void GetID(char *pszID) -{ - char *chop; - - chop = strstr(pszID, "/"); - if (chop != NULL) strcpy(pszID, chop+1); - else pszID[0] = 0; -} - -//============ WEATHER ERROR CODE ============ - -// Get the text when an error code is specified -// code = the error code obtained when updating weather -// str = the string for the error - -char *GetError(int code) -{ - char *str, str2[100]; - switch (code) - { - case 10: str = E10; break; - case 11: str = E11; break; - case 12: str = E12; break; - case 20: str = E20; break; - case 30: str = E30; break; - case 40: str = E40; break; - case 42: str = E42; break; - case 43: str = E43; break; - case 99: str = E99; break; - case 204: str = E204; break; - case 301: str = E301; break; - case 305: str = E305; break; - case 307: str = E307; break; - case 400: str = E400; break; - case 401: str = E401; break; - case 402: str = E402; break; - case 403: str = E403; break; - case 404: str = E404; break; - case 405: str = E405; break; - case 407: str = E407; break; - case 410: str = E410; break; - case 500: str = E500; break; - case 502: str = E502; break; - case 503: str = E503; break; - case 504: str = E504; break; - default: - mir_snprintf(str2, sizeof(str2), Translate("HTTP Error %i"), code); - str = str2; - break; - } - return str; -} - -LPWSTR ConvToUnicode(LPCSTR str2) -{ - const size_t nLength = MultiByteToWideChar(lpcp, 0, str2, -1, NULL, 0); - LPWSTR res = mir_alloc(sizeof(WCHAR)*nLength); - MultiByteToWideChar(lpcp, 0, str2, -1, res, (int)nLength); - return res; -} - -typedef BOOL (WINAPI *ft_SetDlgItemTextW) ( - HWND hDlg, - int nIDDlgItem, - LPCWSTR lpString - ); - -typedef BOOL (WINAPI *ft_SetWindowTextW) ( - HWND hWnd, - LPCWSTR lpString - ); - -typedef UINT (WINAPI *ft_GetDlgItemTextW) ( - HWND hDlg, - int nIDDlgItem, - LPWSTR lpString, - int nMaxCount - ); - -static ft_GetDlgItemTextW f_GetDlgItemTextW = NULL; -static ft_SetDlgItemTextW f_SetDlgItemTextW = NULL; -static ft_SetWindowTextW f_SetWindowTextW = NULL; - -unsigned lpcp; - -void InitUniConv(void) -{ - HMODULE hUser = GetModuleHandle("user32.dll"); - f_GetDlgItemTextW = (ft_GetDlgItemTextW)GetProcAddress(hUser, "GetDlgItemTextW"); - f_SetDlgItemTextW = (ft_SetDlgItemTextW)GetProcAddress(hUser, "SetDlgItemTextW"); - f_SetWindowTextW = (ft_SetWindowTextW) GetProcAddress(hUser, "SetWindowTextW"); - - lpcp = (unsigned)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); - if (lpcp == CALLSERVICE_NOTFOUND || lpcp == GetUserDefaultLangID()) - lpcp = CP_ACP; -} - -UINT GetDlgItemTextWth(HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount) -{ - UINT res; - - if (lpcp != CP_ACP && f_GetDlgItemTextW != NULL) - { - LPWSTR m_psz = mir_alloc(sizeof(WCHAR) * nMaxCount); - res = f_GetDlgItemTextW(hDlg, nIDDlgItem, m_psz, nMaxCount); - WideCharToMultiByte( lpcp, 0, m_psz, -1, lpString, nMaxCount, NULL, NULL ); - mir_free(m_psz); - } - else - res = GetDlgItemText(hDlg, nIDDlgItem, lpString, nMaxCount); - - return res; -} - -BOOL SetDlgItemTextWth(HWND hDlg, int nIDDlgItem, LPCSTR lpString) -{ - BOOL res; - - if (lpcp != CP_ACP && f_SetDlgItemTextW != NULL) - { - LPWSTR m_psz = ConvToUnicode(lpString); - res = f_SetDlgItemTextW(hDlg, nIDDlgItem, m_psz); - mir_free(m_psz); - } - else - res = SetDlgItemText(hDlg, nIDDlgItem, lpString); - - return res; -} - -BOOL SetWindowTextWth(HWND hWnd, LPCSTR lpString) -{ - BOOL res; - - if (lpcp != CP_ACP && f_SetWindowTextW != NULL) - { - LPWSTR m_psz = ConvToUnicode(lpString); - res = f_SetWindowTextW(hWnd, m_psz); - mir_free(m_psz); - } - else - res = SetWindowText(hWnd, lpString); - - return res; -} - -void ListView_SetItemTextWth(HWND hwndLV, int i, int iSubItem_, LPSTR pszText_) -{ - LV_ITEM _ms_lvi; - _ms_lvi.iSubItem = iSubItem_; - - if (lpcp != CP_ACP) - { - LPWSTR m_psz = ConvToUnicode(pszText_); - _ms_lvi.pszText = (LPSTR)m_psz; - SendMessage(hwndLV, LVM_SETITEMTEXTW, (WPARAM)(i), (LPARAM)&_ms_lvi); - mir_free(m_psz); - } - else - { - _ms_lvi.pszText = pszText_; - SendMessage(hwndLV, LVM_SETITEMTEXTA, (WPARAM)(i), (LPARAM)&_ms_lvi); - } -} - -int ListView_InsertItemWth(HWND hwnd, LV_ITEM *pitem) -{ - int res; - if (lpcp != CP_ACP) - { - LPSTR otxt = pitem->pszText; - LPWSTR m_psz = ConvToUnicode(otxt); - pitem->pszText = (LPSTR)m_psz; - res = SendMessage(hwnd, LVM_INSERTITEMW, 0, (LPARAM)pitem); - mir_free(m_psz); - pitem->pszText = otxt; - } - else - res = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)pitem); - - return res; -} - -int ListView_InsertColumnWth(HWND hwnd, int iCol, LV_COLUMN *pitem) -{ - int res; - if (lpcp != CP_ACP) - { - LPSTR otxt = pitem->pszText; - LPWSTR m_psz = ConvToUnicode(otxt); - pitem->pszText = (LPSTR)m_psz; - res = SendMessage(hwnd, LVM_INSERTCOLUMNW, iCol, (LPARAM)pitem); - mir_free(m_psz); - pitem->pszText = otxt; - } - else - res = SendMessage(hwnd, LVM_INSERTCOLUMNA, iCol, (LPARAM)pitem); - - return res; -} diff --git a/protocols/weather/weather_conv.cpp b/protocols/weather/weather_conv.cpp new file mode 100644 index 0000000000..7679a6c440 --- /dev/null +++ b/protocols/weather/weather_conv.cpp @@ -0,0 +1,838 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +This file contain the source related unit conversion, icon assignment, +string conversions, display text parsing, etc +*/ + +#include "weather.h" + +//============ SOME HELPER FUNCTIONS ============ + +// see if a string is a number +// s = the string to be determined +// return value = true if the string is a number, false if it isn't +BOOL is_number(char *s) +{ + BOOL tag = FALSE; + // looking character by character + // for a number: numerous spaces in front, then optional +/-, then the number + // don't care anything that comes after it + while(*s != '\0') + { + if (*s >= '0' && *s <='9') return TRUE; + else if (*s == ' '); + else if (*s != '+' && *s != '-') return FALSE; + else if ((*s == '+' || *s == '-') && !tag) tag = TRUE; + else return FALSE; + s++; + } + return FALSE; +} + +static void numToStr(double num, char* str) +{ + int i = (int)(num * (opt.NoFrac ? 10 : 100)); + int u = abs(i); + + int r = u % 10; + int w = u / 10 + (r >= 5); + + if (opt.NoFrac) + { + r = 0; + } + else + { + r = w % 10; + w /= 10; + } + + if (i < 0 && (w || r)) *(str++) = '-'; + if (r) + sprintf(str, "%i.%i", w, r); + else + sprintf(str, "%i", w); +} + +//============ UNIT CONVERSIONS ============ + +// temperature conversion +// tempchar = the string containing the temperature value +// unit = the unit for temperature +// return value = the converted temperature with degree sign and unit; if fails, return N/A +void GetTemp(char *tempchar, char *unit, char* str) +{ + // unit can be C, F + double temp; + char tstr[20]; + + TrimString(tempchar); + if (tempchar[0] == '-' && tempchar[1] == ' ') + memmove(&tempchar[1], &tempchar[2], strlen(&tempchar[2])+1); + + // quit if the value obtained is N/A or not a number + if (!strcmp(tempchar, NODATA) || !strcmp(tempchar, "N/A")) + { + strcpy(str, tempchar); + return; + } + if (!is_number(tempchar)) + { + strcpy(str, NODATA); + return; + } + + // convert the string to an integer + temp = atof(tempchar); + + // convert all to F first + if (!_stricmp(unit, "C")) temp = (temp*9/5)+32; + else if (!_stricmp(unit, "K")) temp = ((temp-273.15)*9/5)+32; + + // convert to apporiate unit + switch (opt.tUnit) + { + case 1: + // rounding + numToStr((temp-32)/9*5, tstr); + if (opt.DoNotAppendUnit) + sprintf(str, "%s", tstr); + else + sprintf(str, "%s%sC", tstr, opt.DegreeSign); + break; + + case 2: + numToStr(temp, tstr); + if (opt.DoNotAppendUnit) + sprintf(str, "%s", tstr); + else + sprintf(str, "%s%sF", tstr, opt.DegreeSign); + break; + } +} + +// temperature conversion +// tempchar = the string containing the pressure value +// unit = the unit for pressure +// return value = the converted pressure with unit; if fail, return the original string +void GetPressure(char *tempchar, char *unit, char* str) +{ + // unit can be kPa, hPa, mb, in, mm, torr + double tempunit = 0, output; + int intunit; + + // convert the string to a floating point number (always positive) + // if it end up with 0, then it's not a number, return the original string and quit + output = atof(tempchar); + if (output == 0) + { + strcpy(str, tempchar); + return; + } + + // convert all to mb first + if (!_stricmp(unit, "KPA")) + tempunit = (double)output * 10; + else if (!_stricmp(unit, "HPA")) + tempunit = (double)output; + else if (!_stricmp(unit, "MB")) + tempunit = (double)output; + else if (!_stricmp(unit, "IN")) + tempunit = (double)output * 33.86388; + else if (!_stricmp(unit, "MM")) + tempunit = (double)output * 1.33322; + else if (!_stricmp(unit, "TORR")) + tempunit = (double)output * 1.33322; + + // convert to apporiate unit + switch (opt.pUnit) + { + case 1: + intunit = (int)(tempunit + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("kPa")); + break; + case 2: + intunit = (int)(tempunit + 0.5); + wsprintf(str, "%i %s", intunit, opt.DoNotAppendUnit ? "" : Translate("mb")); + break; + case 3: + intunit = (int)((tempunit*10 / 33.86388) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("in")); + break; + case 4: + intunit = (int)((tempunit*10 / 1.33322) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("mm")); + break; + default: + strcpy(str, tempchar); + break; + + } +} + +// speed conversion +// tempchar = the string containing the speed value +// unit = the unit for speed +// return value = the converted speed with unit; if fail, return "" +void GetSpeed(char *tempchar, char *unit, char *str) +{ + // unit can be km/h, mph, m/s, knots + double tempunit; + char tstr[20]; + + str[0] = 0; + + // convert the string into an integer (always positive) + // if the result is 0, then the string is not a number, return "" + tempunit = atof(tempchar); + if (tempunit == 0 && tempchar[0] != '0') return; + + // convert all to m/s first + if (!_stricmp(unit, "KM/H")) + tempunit /= 3.6; +// else if (!_stricmp(unit, "M/S")) +// tempunit = tempunit; + else if (!_stricmp(unit, "MPH")) + tempunit *= 0.44704; + else if (!_stricmp(unit, "KNOTS")) + tempunit *= 0.514444; + + // convert to apporiate unit + switch (opt.wUnit) + { + case 1: + numToStr(tempunit * 3.6, tstr); + sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("km/h")); + break; + case 2: + numToStr(tempunit, tstr); + sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("m/s")); + break; + case 3: + numToStr(tempunit / 0.44704, tstr); + sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("mph")); + break; + case 4: + numToStr(tempunit / 0.514444, tstr); + sprintf(str, "%s %s", tstr, opt.DoNotAppendUnit ? "" : Translate("knots")); + break; + } +} + +// distance conversion +// tempchar = the string containing the distance value +// unit = the unit for distance +// return value = the converted distance with unit; if fail, return original string +void GetDist(char *tempchar, char *unit, char *str) +{ + // unit can be km, miles + double tempunit = 0, output; + int intunit; + + // convert the string to a floating point number (always positive) + // if it end up with 0, then it's not a number, return the original string and quit + output = atof(tempchar); + if (output == 0) + { + strcpy(str, tempchar); + return; + } + + // convert all to km first + if (!_stricmp(unit, "KM")) + tempunit = (double)output; + else if (!_stricmp(unit, "MILES")) + tempunit = (double)output * 1.609; + + // convert to apporiate unit + switch (opt.vUnit) + { + case 1: + intunit = (int)((tempunit*10) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("km")); + break; + case 2: + intunit = (int)((tempunit*10 / 1.609) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("miles")); + break; + default: + strcpy(str, tempchar); + break; + } +} + +// elevation conversion +// tempchar = the string containing the elevation value +// unit = the unit for elevation +// return value = the converted elevation with unit; if fail, return original string +void GetElev(char *tempchar, char *unit, char *str) +{ + // unit can be ft, m + double tempunit = 0, output; + int intunit; + + // convert the string to a floating point number (always positive) + // if it end up with 0, then it's not a number, return the original string and quit + output = atof(tempchar); + if (output == 0) + { + strcpy(str, tempchar); + return; + } + + // convert all to m first + if (!_stricmp(unit, "M")) + tempunit = (double)output; + else if (!_stricmp(unit, "FT")) + tempunit = (double)output / 3.28; + + // convert to apporiate unit + switch (opt.eUnit) { + case 1: + intunit = (int)((tempunit*10 * 3.28) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("ft")); + break; + case 2: + intunit = (int)((tempunit*10) + 0.5); + wsprintf(str, "%i.%i %s", intunit/10, intunit%10, opt.DoNotAppendUnit ? "" : Translate("m")); + break; + default: + strcpy(str, tempchar); + break; + } +} + +//============ CONDITION ICON ASSIGNMENT ============ + +// assign the contact icon (status) from the condition string +// the description may be different between different sources +// cond = the string for weather condition +// return value = status for the icon (ONLINE, OFFLINE, etc) +WORD GetIcon(const char* cond, WIDATA *Data) +{ + int i; + + static const + char *statusStr[10] = + { + "Lightning", + "Fog", + "Snow Shower", + "Snow", + "Rain Shower", + "Rain", + "Partly Cloudy", + "Cloudy", + "Sunny", + "N/A" + }; + + static const + WORD statusValue[10] = + { + LIGHT, + FOG, + SSHOWER, + SNOW, + RSHOWER, + RAIN, + PCLOUDY, + CLOUDY, + SUNNY, + NA + }; + + // set the icon using ini + for (i=0; i<10; i++) { + if (IsContainedInCondList(cond, &Data->CondList[i])) + return statusValue[i]; + } + + // internal detection + if ( + strstr(cond, "mainy sunny") != NULL || + strstr(cond, "mainy clear") != NULL || + strstr(cond, "partly cloudy") != NULL || + strstr(cond, "mostly") != NULL || + strstr(cond, "clouds") != NULL) { + return PCLOUDY; + } + else if ( + strstr(cond, "sunny") != NULL || + strstr(cond, "clear") != NULL || + strstr(cond, "fair") != NULL) { + return SUNNY; + } + else if ( + strstr(cond, "thunder") != NULL || + strstr(cond, "t-storm") != NULL) { + return LIGHT; + } + else if ( + strstr(cond, "cloud") != NULL || + strstr(cond, "overcast") != NULL) { + return CLOUDY; + } + else if ( + strstr(cond, "fog") != NULL || + strstr(cond, "mist") != NULL || + strstr(cond, "smoke") != NULL || + strstr(cond, "sand") != NULL || + strstr(cond, "dust") != NULL || + strstr(cond, "haze") != NULL) { + return FOG; + } + else if ( + (strstr(cond, "shower") != NULL && strstr(cond, "snow") != NULL) || + strstr(cond, "flurries") != NULL) { + return SSHOWER; + } + else if ( + strstr(cond, "rain shower") != NULL || + strstr(cond, "shower") != NULL) + { + return RSHOWER; + } + else if ( + strstr(cond, "snow") != NULL || + strstr(cond, "ice") != NULL || + strstr(cond, "freezing") != NULL || + strstr(cond, "wintry") != NULL) { + return SNOW; + } + else if ( + strstr(cond, "drizzle") != NULL || + strstr(cond, "rain") != NULL) + { + return RAIN; + } + + // set the icon using langpack + for (i=0; i<9; i++) + { + char LangPackStr[64]; + char LangPackStr1[128]; + int j = 0; + do + { + j++; + // using the format "# Weather #" + mir_snprintf(LangPackStr, sizeof(LangPackStr), "# Weather %s %i #", statusStr[i], j); + mir_snprintf(LangPackStr1, sizeof(LangPackStr1), "%s", Translate(LangPackStr)); + CharLowerBuff(LangPackStr1, (DWORD)strlen(LangPackStr1)); + if (strstr(cond, LangPackStr1) != NULL) + return statusValue[i]; + // loop until the translation string exists (ie, the translated string is differ from original) + } + while (strcmp(Translate(LangPackStr), LangPackStr)); + } + + return NA; +} + +//============ STRING CONVERSIONS ============ + +// this function convert the string to the format with 1 upper case followed by lower case char +void CaseConv(char *str) +{ + char *pstr; + BOOL nextUp = TRUE; + + CharLowerBuff(str, (DWORD)strlen(str)); + for(pstr=str; *pstr; pstr++) + { + if (*pstr==' ' || *pstr=='-') + nextUp = TRUE; + else + { + unsigned ch = *(unsigned char*)pstr; + if (nextUp) *pstr = (char)(unsigned)CharUpper((LPSTR)ch); + nextUp = FALSE; + } + } +} + +// the next 2 functions are copied from miranda source +// str = the string to modify +void TrimString(char *str) +{ + size_t len, start; + + len = strlen(str); + while(len && (unsigned char)str[len-1] <= ' ') str[--len] = 0; + for(start=0; (unsigned char)str[start]<=' ' && str[start]; start++); + memmove(str, str+start, len-start+1); +} + +// convert \t to tab and \n to linefeed +void ConvertBackslashes(char *str) +{ + char *pstr; + for(pstr=str;*pstr;pstr=CharNext(pstr)) + { + if(*pstr=='\\') + { + switch(pstr[1]) + { + case 'n': *pstr='\n'; break; + case 't': *pstr='\t'; break; + default: *pstr=pstr[1]; break; + } + memmove(pstr+1,pstr+2,strlen(pstr+2)+1); + } + } +} + +// replace spaces with "%20" +// dis = original string +// return value = the modified string with space -> "%20" +char *GetSearchStr(char *dis) +{ + char *pstr = dis; + size_t len = strlen(dis); + while (*pstr != 0) + { + if (*pstr == ' ') + { + memmove(pstr+3, pstr+1, len); + memcpy(pstr, "%20", 3); + pstr += 2; + } + pstr++; + len--; + } + return dis; +} + +//============ ICON ASSIGNMENT ============ + +// make display and history strings +// w = WEATHERINFO data to be parsed +// dis = the string to parse +// return value = the parsed string +char* GetDisplay(WEATHERINFO *w, const char *dis, char* str) +{ + char lpzDate[32], chr, name[256], temp[2]; + DBVARIANT dbv; + size_t i; + + // Clear the string + str[0] = 0; + + // looking character by character + for (i=0; icond); break; + case 'd': // get the current date + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, lpzDate, sizeof(lpzDate)); + strcat(str, lpzDate); break; + case 'e': strcat(str, w->dewpoint); break; + case 'f': strcat(str, w->feel); break; + case 'h': strcat(str, w->high); break; + case 'i': strcat(str, w->winddir); break; + case 'l': strcat(str, w->low); break; + case 'm': strcat(str, w->humid); break; + case 'n': strcat(str, w->city); break; + case 'p': strcat(str, w->pressure); break; + case 'r': strcat(str, w->sunrise); break; + case 's': strcat(str, w->id); break; + case 't': strcat(str, w->temp); break; + case 'u': + if (strcmp(w->update, NODATA)) strcat(str, w->update); + else strcat(str, Translate("")); + break; + case 'v': strcat(str, w->vis); break; + case 'w': strcat(str, w->wind); break; + case 'y': strcat(str, w->sunset); break; + case '%': strcat(str, "%"); break; + case '[': // custom variables + i++; + name[0] = 0; + // read the entire variable name + while (dis[i] != ']' && i < strlen(dis)) { + wsprintf(temp, "%c", dis[i++]); + strcat(name, temp); + } + // access the database to get its value + if (!DBGetContactSettingString(w->hContact, WEATHERCONDITION, name, &dbv)) + { + if (dbv.pszVal != Translate(NODATA) && dbv.pszVal != Translate("")) + strcat(str, dbv.pszVal); + DBFreeVariant(&dbv); + } + break; + } + } + // if the character is not a variable, write the original character to the new string + else + { + wsprintf(temp, "%c", dis[i]); + strcat(str, temp); + } + } + return str; +} + +char svcReturnText[MAX_TEXT_SIZE]; +INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam) +{ + WEATHERINFO winfo = LoadWeatherInfo((HANDLE)wParam); + return (INT_PTR)GetDisplay(&winfo, (char *)lParam, svcReturnText); +} + +//============ ID MANAGEMENT ============ + +// get service data module internal name +// mod/id <- the mod part +// pszID = original 2-part id, return the service internal name +void GetSvc(char *pszID) +{ + char *chop; + + chop = strstr(pszID, "/"); + if (chop != NULL) *chop = '\0'; + else pszID[0] = 0; +} + +// get the id use for update without the service internal name +// mod/id <- the id part +// pszID = original 2-part id, return the single part id +void GetID(char *pszID) +{ + char *chop; + + chop = strstr(pszID, "/"); + if (chop != NULL) strcpy(pszID, chop+1); + else pszID[0] = 0; +} + +//============ WEATHER ERROR CODE ============ + +// Get the text when an error code is specified +// code = the error code obtained when updating weather +// str = the string for the error + +char *GetError(int code) +{ + char *str, str2[100]; + switch (code) + { + case 10: str = E10; break; + case 11: str = E11; break; + case 12: str = E12; break; + case 20: str = E20; break; + case 30: str = E30; break; + case 40: str = E40; break; + case 42: str = E42; break; + case 43: str = E43; break; + case 99: str = E99; break; + case 204: str = E204; break; + case 301: str = E301; break; + case 305: str = E305; break; + case 307: str = E307; break; + case 400: str = E400; break; + case 401: str = E401; break; + case 402: str = E402; break; + case 403: str = E403; break; + case 404: str = E404; break; + case 405: str = E405; break; + case 407: str = E407; break; + case 410: str = E410; break; + case 500: str = E500; break; + case 502: str = E502; break; + case 503: str = E503; break; + case 504: str = E504; break; + default: + mir_snprintf(str2, sizeof(str2), Translate("HTTP Error %i"), code); + str = str2; + break; + } + return str; +} + +LPWSTR ConvToUnicode(LPCSTR str2) +{ + const size_t nLength = MultiByteToWideChar(lpcp, 0, str2, -1, NULL, 0); + LPWSTR res = ( LPWSTR )mir_alloc(sizeof(WCHAR)*nLength); + MultiByteToWideChar(lpcp, 0, str2, -1, res, (int)nLength); + return res; +} + +typedef BOOL (WINAPI *ft_SetDlgItemTextW) ( + HWND hDlg, + int nIDDlgItem, + LPCWSTR lpString + ); + +typedef BOOL (WINAPI *ft_SetWindowTextW) ( + HWND hWnd, + LPCWSTR lpString + ); + +typedef UINT (WINAPI *ft_GetDlgItemTextW) ( + HWND hDlg, + int nIDDlgItem, + LPWSTR lpString, + int nMaxCount + ); + +static ft_GetDlgItemTextW f_GetDlgItemTextW = NULL; +static ft_SetDlgItemTextW f_SetDlgItemTextW = NULL; +static ft_SetWindowTextW f_SetWindowTextW = NULL; + +unsigned lpcp; + +void InitUniConv(void) +{ + HMODULE hUser = GetModuleHandle("user32.dll"); + f_GetDlgItemTextW = (ft_GetDlgItemTextW)GetProcAddress(hUser, "GetDlgItemTextW"); + f_SetDlgItemTextW = (ft_SetDlgItemTextW)GetProcAddress(hUser, "SetDlgItemTextW"); + f_SetWindowTextW = (ft_SetWindowTextW) GetProcAddress(hUser, "SetWindowTextW"); + + lpcp = (unsigned)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); + if (lpcp == CALLSERVICE_NOTFOUND || lpcp == GetUserDefaultLangID()) + lpcp = CP_ACP; +} + +UINT GetDlgItemTextWth(HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount) +{ + UINT res; + + if (lpcp != CP_ACP && f_GetDlgItemTextW != NULL) + { + LPWSTR m_psz = ( LPWSTR )mir_alloc(sizeof(WCHAR) * nMaxCount); + res = f_GetDlgItemTextW(hDlg, nIDDlgItem, m_psz, nMaxCount); + WideCharToMultiByte( lpcp, 0, m_psz, -1, lpString, nMaxCount, NULL, NULL ); + mir_free(m_psz); + } + else + res = GetDlgItemText(hDlg, nIDDlgItem, lpString, nMaxCount); + + return res; +} + +BOOL SetDlgItemTextWth(HWND hDlg, int nIDDlgItem, LPCSTR lpString) +{ + BOOL res; + + if (lpcp != CP_ACP && f_SetDlgItemTextW != NULL) + { + LPWSTR m_psz = ConvToUnicode(lpString); + res = f_SetDlgItemTextW(hDlg, nIDDlgItem, m_psz); + mir_free(m_psz); + } + else + res = SetDlgItemText(hDlg, nIDDlgItem, lpString); + + return res; +} + +BOOL SetWindowTextWth(HWND hWnd, LPCSTR lpString) +{ + BOOL res; + + if (lpcp != CP_ACP && f_SetWindowTextW != NULL) + { + LPWSTR m_psz = ConvToUnicode(lpString); + res = f_SetWindowTextW(hWnd, m_psz); + mir_free(m_psz); + } + else + res = SetWindowText(hWnd, lpString); + + return res; +} + +void ListView_SetItemTextWth(HWND hwndLV, int i, int iSubItem_, LPSTR pszText_) +{ + LV_ITEM _ms_lvi; + _ms_lvi.iSubItem = iSubItem_; + + if (lpcp != CP_ACP) + { + LPWSTR m_psz = ConvToUnicode(pszText_); + _ms_lvi.pszText = (LPSTR)m_psz; + SendMessage(hwndLV, LVM_SETITEMTEXTW, (WPARAM)(i), (LPARAM)&_ms_lvi); + mir_free(m_psz); + } + else + { + _ms_lvi.pszText = pszText_; + SendMessage(hwndLV, LVM_SETITEMTEXTA, (WPARAM)(i), (LPARAM)&_ms_lvi); + } +} + +int ListView_InsertItemWth(HWND hwnd, LV_ITEM *pitem) +{ + int res; + if (lpcp != CP_ACP) + { + LPSTR otxt = pitem->pszText; + LPWSTR m_psz = ConvToUnicode(otxt); + pitem->pszText = (LPSTR)m_psz; + res = SendMessage(hwnd, LVM_INSERTITEMW, 0, (LPARAM)pitem); + mir_free(m_psz); + pitem->pszText = otxt; + } + else + res = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)pitem); + + return res; +} + +int ListView_InsertColumnWth(HWND hwnd, int iCol, LV_COLUMN *pitem) +{ + int res; + if (lpcp != CP_ACP) + { + LPSTR otxt = pitem->pszText; + LPWSTR m_psz = ConvToUnicode(otxt); + pitem->pszText = (LPSTR)m_psz; + res = SendMessage(hwnd, LVM_INSERTCOLUMNW, iCol, (LPARAM)pitem); + mir_free(m_psz); + pitem->pszText = otxt; + } + else + res = SendMessage(hwnd, LVM_INSERTCOLUMNA, iCol, (LPARAM)pitem); + + return res; +} diff --git a/protocols/weather/weather_data.c b/protocols/weather/weather_data.c deleted file mode 100644 index 86f051199f..0000000000 --- a/protocols/weather/weather_data.c +++ /dev/null @@ -1,500 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -This file contain the source related loading, obtaining, and -saving individual weather data for a weather contact. -*/ - -#include "weather.h" - -// temporary counter and storage for removing weather data -typedef struct -{ - char *value[1024]; - int current; -} WCOUNTER; - -//============ LOAD WEATHER INFO FROM A CONTACT ============ - -// get station ID from DB -// hContact = the current contact handle -// return value = the string for station ID -void GetStationID(HANDLE hContact, char* id, size_t idlen) -{ - // accessing the database - if (DBGetStaticString(hContact, WEATHERPROTONAME, "ID", id, idlen)) - id[0] = 0; -} - -// initialize weather info by loading values from database -// Change = current contact handle -// return value = the current weather information in WEATHERINFO struct -WEATHERINFO LoadWeatherInfo(HANDLE Change) -{ - WEATHERINFO winfo; - - winfo.hContact = Change; - // obtaining values from the DB - // assuming station ID must exist at all time, but others does not have to - // if the string is not found in database, a value of "N/A" is stored in the field - GetStationID(Change, winfo.id, sizeof(winfo.id)); - - if (DBGetStaticString(Change, WEATHERPROTONAME, "Nick", winfo.city, sizeof(winfo.city))) - strcpy(winfo.city, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Update", winfo.update, sizeof(winfo.update))) - strcpy(winfo.update, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Condition", winfo.cond, sizeof(winfo.cond))) - strcpy(winfo.cond, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Temperature", winfo.temp, sizeof(winfo.temp))) - strcpy(winfo.temp, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "High", winfo.high, sizeof(winfo.high))) - strcpy(winfo.high, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Low", winfo.low, sizeof(winfo.low))) - strcpy(winfo.low, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Sunset", winfo.sunset, sizeof(winfo.sunset))) - strcpy(winfo.sunset, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Sunrise", winfo.sunrise, sizeof(winfo.sunrise))) - strcpy(winfo.sunrise, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Wind Speed", winfo.wind, sizeof(winfo.wind))) - strcpy(winfo.wind, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Wind Direction", winfo.winddir, sizeof(winfo.winddir))) - strcpy(winfo.winddir, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Dewpoint", winfo.dewpoint, sizeof(winfo.dewpoint))) - strcpy(winfo.dewpoint, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Pressure", winfo.pressure, sizeof(winfo.pressure))) - strcpy(winfo.pressure, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Visibility", winfo.vis, sizeof(winfo.vis))) - strcpy(winfo.vis, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Humidity", winfo.humid, sizeof(winfo.humid))) - strcpy(winfo.humid, NODATA); - if (DBGetStaticString(Change, WEATHERCONDITION, "Feel", winfo.feel, sizeof(winfo.feel))) - strcpy(winfo.feel, NODATA); - - winfo.status = (WORD)DBGetContactSettingWord(Change, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE); - return winfo; -} - -// getting weather setting from database -// return 0 on success -int DBGetData(HANDLE hContact, char *setting, DBVARIANT *dbv) -{ - if (DBGetContactSettingString(hContact, WEATHERCONDITION, setting, dbv)) - { - size_t len = strlen(setting) + 1; - char *set = (char*)alloca(len + 1); - *set = '#'; - memcpy(set + 1, setting, len); - - if (DBGetContactSettingString(hContact, WEATHERCONDITION, set, dbv)) - return 1; - } - return 0; -} - -int DBGetStaticString(HANDLE hContact, const char *szModule, const char *valueName, char *dest, size_t dest_len) -{ - DBVARIANT dbv; - DBCONTACTGETSETTING sVal; - - dbv.pszVal = dest; - dbv.cchVal = (WORD)dest_len; - dbv.type = DBVT_ASCIIZ; - - sVal.pValue = &dbv; - sVal.szModule = szModule; - sVal.szSetting = valueName; - - if ( CallService( MS_DB_CONTACT_GETSETTINGSTATIC, ( WPARAM )hContact, ( LPARAM )&sVal ) != 0 ) - return 1; - - return ( dbv.type != DBVT_ASCIIZ ); -} - - -//============ ERASE OLD SETTINGS ============ - -// erase all current weather information from database -// lastver = the last used version number in dword (using PLUGIN_MAKE_VERSION) -void EraseAllInfo(DWORD lastver) -{ - char str[255]; - int ContactCount = 0; - HANDLE hContact, LastContact = NULL; - DBVARIANT dbv; - // loop through all contacts - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while(hContact) - { - // see if the contact is a weather contact - if(IsMyContact(hContact)) - { - // check for upgrade - if (lastver < __VERSION_DWORD) UpgradeContact(lastver, hContact); - DBWriteContactSettingWord(hContact,WEATHERPROTONAME,"Status",ID_STATUS_OFFLINE); - DBWriteContactSettingWord(hContact,WEATHERPROTONAME,"StatusIcon",ID_STATUS_OFFLINE); - DBDeleteContactSetting(hContact,"CList","MyHandle"); - // clear all data - if (DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv)) { - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", Translate("")); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", "never"); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", "None"); - } - else - DBFreeVariant(&dbv); -/* - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Update", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Condition", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Temperature", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"High", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Low", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Humidity", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Wind Speed", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Wind Direction", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Pressure", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Visibility", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Dewpoint", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Feel", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Heat Index", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Sunrise", NODATA); - DBWriteContactSettingString(hContact,WEATHERCONDITION,"Sunset", NODATA); -*/ - DBDataManage(hContact, WDBM_REMOVE, 0, 0); - DBWriteContactSettingString(hContact, "UserInfo", "MyNotes", ""); - // reset update tag - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"IsUpdated",FALSE); - // reset logging settings - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Log",&dbv)) - { - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",(BYTE)(dbv.pszVal[0] != 0)); - DBFreeVariant(&dbv); - } - else - DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",FALSE); - // if no default station find, assign a new one - if (opt.Default[0] == 0) - { - GetStationID(hContact, opt.Default, sizeof(opt.Default)); - - opt.DefStn = hContact; - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Nick",&dbv)) - { - wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); - DBFreeVariant(&dbv); - MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); - } - } - // get the handle of the default station - if (opt.DefStn == NULL) { - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) - { - if (!strcmp(dbv.pszVal, opt.Default)) opt.DefStn = hContact; - DBFreeVariant(&dbv); - } - } - ContactCount++; // increment counter - LastContact = hContact; - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - // if weather contact exists, set the status to online so it is ready for update - // if (ContactCount != 0) status = ONLINE; - // in case where the default station is missing - if (opt.DefStn == NULL && ContactCount != 0) - { - if (!DBGetContactSettingString(LastContact,WEATHERPROTONAME,"ID",&dbv)) - { - strcpy(opt.Default, dbv.pszVal); - DBFreeVariant(&dbv); - } - opt.DefStn = LastContact; - if (!DBGetContactSettingString(LastContact,WEATHERPROTONAME,"Nick",&dbv)) - { - wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); - DBFreeVariant(&dbv); - MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); - } - } - // save option in case of default station changed - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); -} - -void ConvertDataValue(WIDATAITEM *UpdateData, char *Data) -{ - char str[MAX_DATA_LEN]; - - // convert the unit - if (strcmp(Data, Translate("")) && strcmp(Data, NODATA) && strcmp(Data, Translate(NODATA))) - { - // temperature - if (!strcmp(UpdateData->Name, "Temperature") || !strcmp(UpdateData->Name, "High") || - !strcmp(UpdateData->Name, "Low") || !strcmp(UpdateData->Name, "Feel") || - !strcmp(UpdateData->Name, "Dewpoint") || - !_stricmp(UpdateData->Unit, "C") || !_stricmp(UpdateData->Unit, "F") || - !_stricmp(UpdateData->Unit, "K")) - { - GetTemp(Data, UpdateData->Unit, str); - strcpy(Data, str); - } - // pressure - else if (!strcmp(UpdateData->Name, "Pressure") || !_stricmp(UpdateData->Unit, "HPA") || - !_stricmp(UpdateData->Unit, "KPA") || !_stricmp(UpdateData->Unit, "MB") || - !_stricmp(UpdateData->Unit, "TORR") || !_stricmp(UpdateData->Unit, "IN") || - !_stricmp(UpdateData->Unit, "MM")) - { - GetPressure(Data, UpdateData->Unit, str); - strcpy(Data, str); - } - // speed - else if (!strcmp(UpdateData->Name, "Wind Speed") || !_stricmp(UpdateData->Unit, "KM/H") || - !_stricmp(UpdateData->Unit, "M/S") || !_stricmp(UpdateData->Unit, "MPH") || - !_stricmp(UpdateData->Unit, "KNOTS")) - { - GetSpeed(Data, UpdateData->Unit, str); - strcpy(Data, str); - } - // visibility - else if (!strcmp(UpdateData->Name, "Visibility") || !_stricmp(UpdateData->Unit, "KM") || - !_stricmp(UpdateData->Unit, "MILES")) - { - GetDist(Data, UpdateData->Unit, str); - strcpy(Data, str); - } - // elevation - else if (!strcmp(UpdateData->Name, "Elevation") || !_stricmp(UpdateData->Unit, "FT") || - !_stricmp(UpdateData->Unit, "M")) - { - GetElev(Data, UpdateData->Unit, str); - strcpy(Data, str); - } - // converting case for condition to the upper+lower format - else if (!_stricmp(UpdateData->Unit, "COND")) - CaseConv(Data); - // degree sign - else if (!_stricmp(UpdateData->Unit, "DEG")) - { - if (!opt.DoNotAppendUnit) strcat(Data, opt.DegreeSign); - } - // percent sign - else if (!_stricmp(UpdateData->Unit, "%")) - { - if (!opt.DoNotAppendUnit) strcat(Data, "%"); - } - // truncating strings for day/month to 2 or 3 characters - else if (!_stricmp(UpdateData->Unit, "DAY") || !_stricmp(UpdateData->Unit, "MONTH")) - if (opt.dUnit > 1 && strlen(Data) > opt.dUnit) Data[opt.dUnit] = '\0'; - } -} - -//============ GET THE VALUE OF A DATAITEM ============ - -// get the value of the data using the start, end strings -// UpdateData = the WIDATAITEM struct containing start, end, unit -// Data = the string containing weather data obtained from UpdateData -// global var. used: szInfo = the downloaded string -void GetDataValue(WIDATAITEM *UpdateData, char *Data, char** szData) -{ - char last = 0, current, *start, *end; - unsigned startloc = 0, endloc = 0, respos = 0; - BOOL tag = FALSE, symb = FALSE; - char *szInfo = *szData; - - Data[0] = 0; - // parse the data if available - if (UpdateData->Start[0] == 0 && UpdateData->End[0] == 0) return; - start = szInfo; - // the start string must be found - if (UpdateData->Start[0] != 0) { - start = strstr(szInfo, UpdateData->Start); - if (start != NULL) { - // set the starting location for getting data - start += strlen(UpdateData->Start); - szInfo = start; - } - } - // the end string must be found too - if (UpdateData->End[0] != 0) - end = strstr(szInfo, UpdateData->End); - else end = strstr(szInfo, " "); - if (end != NULL) { - // set the ending location - startloc = 0; - endloc = end - szInfo; - end += strlen(UpdateData->End); - last = '\n'; - } - // ignore if not both of the string found - this prevent crashes - if (start != NULL && end != NULL) - { - // begin reading the data from start location to end location - // remove all HTML tag in between, as well as leading space, ending space, - // multiple spaces, tabs, and return key - while (startloc < endloc) - { - if (szInfo[startloc] == '<') tag = TRUE; - else if (szInfo[startloc] == '&' && - (szInfo[startloc+1] == ';' || szInfo[startloc+2] == ';' || szInfo[startloc+3] == ';' || - szInfo[startloc+4] == ';' || szInfo[startloc+5] == ';' || szInfo[startloc+6] == ';')) - symb = TRUE; - else if (szInfo[startloc] == '>') tag = FALSE; - else if (szInfo[startloc] == ';') symb = FALSE; - else { - if (!tag && !symb) { - current = szInfo[startloc]; - if (current == '\n' || current == '\t' || current == ' ' || current == '\r') - current = ' '; - if (current != ' ' || last != ' ') { - if (last != '\n' && (respos != 0 || (respos == 0 && last != ' '))) - Data[respos++] = last; - last = current; - } - } - } - ++startloc; - // prevent crashes if the string go over maximun length -> generate an error - if (respos >= MAX_DATA_LEN) { - if (opt.ShowWarnings && UpdateData->Name[0] != 0 && strcmp(UpdateData->Name, "Ignore")) { - mir_snprintf(Data, MAX_DATA_LEN, Translate("Error when obtaining data: %s"), UpdateData->Name); - WPShowMessage(Data, SM_WARNING); - } - strncpy(Data, Translate(""), MAX_DATA_LEN); - last = ' '; - respos = MAX_DATA_LEN - 1; - break; - } - } - - // get the last character - if (last != ' ') - Data[respos++] = last; - - // null terminate the string - Data[respos] = 0; - - // write raw data for debug - Netlib_Logf(hNetlibUser, "%s: %s", UpdateData->Name, Data); - - // convert the unit - ConvertDataValue(UpdateData, Data); - - // remove the string before the data from szInfo - szInfo = end; - } - *szData = szInfo; -} - -//============ ALLOCATE SPACE AND COPY STRING ============ - -// copy a string into a new memory location -// Data = the field the data is copied to -// Value = the original string, the string where data is copied from -void wSetData(char **Data, const char *Value) -{ - if (Value[0] != 0) - { - char *newData = (char*)mir_alloc(strlen(Value)+3); - strcpy(newData, Value); - *Data = newData; - } - else - *Data = ""; -} - -// A safer free function that free memory for a string -// Data = the string occuping the data to be freed -void wfree(char **Data) -{ - if (*Data && strlen(*Data) > 0) mir_free(*Data); - *Data = NULL; -} - -//============ MANAGE THE ITEMS STORED IN DB ============ - -// remove or display the weatehr information for a contact -// hContact - the contact in which the info is going to be removed -void DBDataManage(HANDLE hContact, WORD Mode, WPARAM wParam, LPARAM lParam) -{ - DBCONTACTENUMSETTINGS dbces; - DBVARIANT dbv; - WCOUNTER wc; - wc.current = 0; - - dbces.lParam=(LPARAM)&wc; - dbces.pfnEnumProc=GetWeatherDataFromDB; - dbces.szModule=WEATHERCONDITION; - - // get all the settings and stored them in a temporary list - if(CallService(MS_DB_CONTACT_ENUMSETTINGS,(WPARAM)hContact,(LPARAM)&dbces)==-1) - wc.current--; - - // begin deleting settings - for (; --wc.current>-1;) - { - if (!DBGetContactSettingString(hContact, WEATHERCONDITION, wc.value[wc.current], &dbv)) - { - switch (Mode) - { - case WDBM_REMOVE: - DBDeleteContactSetting(hContact, WEATHERCONDITION, wc.value[wc.current]); - break; - - case WDBM_DETAILDISPLAY: - { - HWND hList = GetDlgItem((HWND)wParam, IDC_DATALIST); - LV_ITEM lvi = { 0 }; - - // skip the "WeatherInfo" variable - if (strcmp(wc.value[wc.current], "WeatherInfo") == 0 || - strcmp(wc.value[wc.current], "Ignore") == 0 || - wc.value[wc.current][0] == '#') - { - wfree(&wc.value[wc.current]); - DBFreeVariant(&dbv); - continue; - } - - lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.iItem = 0; - lvi.iSubItem = 0; - lvi.lParam = (LPARAM)wc.current; - lvi.pszText = (LPSTR)Translate(wc.value[wc.current]); - lvi.iItem = ListView_InsertItemWth(hList, &lvi); - lvi.pszText = dbv.pszVal; - ListView_SetItemTextWth(hList, lvi.iItem, 1, lvi.pszText); - break; - } - } - DBFreeVariant(&dbv); - } - wfree(&wc.value[wc.current]); - } -} - -// get single setting that is found -// szSetting = the setting name -// lparam = the counter -int GetWeatherDataFromDB(const char *szSetting, LPARAM lparam) -{ - WCOUNTER *wc = (WCOUNTER*)lparam; - wc->value[wc->current] = (char *)mir_alloc(strlen(szSetting) + 1); - strcpy(wc->value[wc->current], szSetting); - wc->current++; - return 0; -} diff --git a/protocols/weather/weather_data.cpp b/protocols/weather/weather_data.cpp new file mode 100644 index 0000000000..86f051199f --- /dev/null +++ b/protocols/weather/weather_data.cpp @@ -0,0 +1,500 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +This file contain the source related loading, obtaining, and +saving individual weather data for a weather contact. +*/ + +#include "weather.h" + +// temporary counter and storage for removing weather data +typedef struct +{ + char *value[1024]; + int current; +} WCOUNTER; + +//============ LOAD WEATHER INFO FROM A CONTACT ============ + +// get station ID from DB +// hContact = the current contact handle +// return value = the string for station ID +void GetStationID(HANDLE hContact, char* id, size_t idlen) +{ + // accessing the database + if (DBGetStaticString(hContact, WEATHERPROTONAME, "ID", id, idlen)) + id[0] = 0; +} + +// initialize weather info by loading values from database +// Change = current contact handle +// return value = the current weather information in WEATHERINFO struct +WEATHERINFO LoadWeatherInfo(HANDLE Change) +{ + WEATHERINFO winfo; + + winfo.hContact = Change; + // obtaining values from the DB + // assuming station ID must exist at all time, but others does not have to + // if the string is not found in database, a value of "N/A" is stored in the field + GetStationID(Change, winfo.id, sizeof(winfo.id)); + + if (DBGetStaticString(Change, WEATHERPROTONAME, "Nick", winfo.city, sizeof(winfo.city))) + strcpy(winfo.city, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Update", winfo.update, sizeof(winfo.update))) + strcpy(winfo.update, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Condition", winfo.cond, sizeof(winfo.cond))) + strcpy(winfo.cond, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Temperature", winfo.temp, sizeof(winfo.temp))) + strcpy(winfo.temp, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "High", winfo.high, sizeof(winfo.high))) + strcpy(winfo.high, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Low", winfo.low, sizeof(winfo.low))) + strcpy(winfo.low, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Sunset", winfo.sunset, sizeof(winfo.sunset))) + strcpy(winfo.sunset, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Sunrise", winfo.sunrise, sizeof(winfo.sunrise))) + strcpy(winfo.sunrise, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Wind Speed", winfo.wind, sizeof(winfo.wind))) + strcpy(winfo.wind, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Wind Direction", winfo.winddir, sizeof(winfo.winddir))) + strcpy(winfo.winddir, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Dewpoint", winfo.dewpoint, sizeof(winfo.dewpoint))) + strcpy(winfo.dewpoint, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Pressure", winfo.pressure, sizeof(winfo.pressure))) + strcpy(winfo.pressure, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Visibility", winfo.vis, sizeof(winfo.vis))) + strcpy(winfo.vis, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Humidity", winfo.humid, sizeof(winfo.humid))) + strcpy(winfo.humid, NODATA); + if (DBGetStaticString(Change, WEATHERCONDITION, "Feel", winfo.feel, sizeof(winfo.feel))) + strcpy(winfo.feel, NODATA); + + winfo.status = (WORD)DBGetContactSettingWord(Change, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE); + return winfo; +} + +// getting weather setting from database +// return 0 on success +int DBGetData(HANDLE hContact, char *setting, DBVARIANT *dbv) +{ + if (DBGetContactSettingString(hContact, WEATHERCONDITION, setting, dbv)) + { + size_t len = strlen(setting) + 1; + char *set = (char*)alloca(len + 1); + *set = '#'; + memcpy(set + 1, setting, len); + + if (DBGetContactSettingString(hContact, WEATHERCONDITION, set, dbv)) + return 1; + } + return 0; +} + +int DBGetStaticString(HANDLE hContact, const char *szModule, const char *valueName, char *dest, size_t dest_len) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING sVal; + + dbv.pszVal = dest; + dbv.cchVal = (WORD)dest_len; + dbv.type = DBVT_ASCIIZ; + + sVal.pValue = &dbv; + sVal.szModule = szModule; + sVal.szSetting = valueName; + + if ( CallService( MS_DB_CONTACT_GETSETTINGSTATIC, ( WPARAM )hContact, ( LPARAM )&sVal ) != 0 ) + return 1; + + return ( dbv.type != DBVT_ASCIIZ ); +} + + +//============ ERASE OLD SETTINGS ============ + +// erase all current weather information from database +// lastver = the last used version number in dword (using PLUGIN_MAKE_VERSION) +void EraseAllInfo(DWORD lastver) +{ + char str[255]; + int ContactCount = 0; + HANDLE hContact, LastContact = NULL; + DBVARIANT dbv; + // loop through all contacts + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + // see if the contact is a weather contact + if(IsMyContact(hContact)) + { + // check for upgrade + if (lastver < __VERSION_DWORD) UpgradeContact(lastver, hContact); + DBWriteContactSettingWord(hContact,WEATHERPROTONAME,"Status",ID_STATUS_OFFLINE); + DBWriteContactSettingWord(hContact,WEATHERPROTONAME,"StatusIcon",ID_STATUS_OFFLINE); + DBDeleteContactSetting(hContact,"CList","MyHandle"); + // clear all data + if (DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv)) { + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "Nick", Translate("")); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", "never"); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", "None"); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", "None"); + } + else + DBFreeVariant(&dbv); +/* + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Update", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Condition", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Temperature", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"High", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Low", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Humidity", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Wind Speed", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Wind Direction", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Pressure", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Visibility", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Dewpoint", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Feel", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Heat Index", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Sunrise", NODATA); + DBWriteContactSettingString(hContact,WEATHERCONDITION,"Sunset", NODATA); +*/ + DBDataManage(hContact, WDBM_REMOVE, 0, 0); + DBWriteContactSettingString(hContact, "UserInfo", "MyNotes", ""); + // reset update tag + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"IsUpdated",FALSE); + // reset logging settings + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Log",&dbv)) + { + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",(BYTE)(dbv.pszVal[0] != 0)); + DBFreeVariant(&dbv); + } + else + DBWriteContactSettingByte(hContact,WEATHERPROTONAME,"File",FALSE); + // if no default station find, assign a new one + if (opt.Default[0] == 0) + { + GetStationID(hContact, opt.Default, sizeof(opt.Default)); + + opt.DefStn = hContact; + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Nick",&dbv)) + { + wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); + DBFreeVariant(&dbv); + MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); + } + } + // get the handle of the default station + if (opt.DefStn == NULL) { + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"ID",&dbv)) + { + if (!strcmp(dbv.pszVal, opt.Default)) opt.DefStn = hContact; + DBFreeVariant(&dbv); + } + } + ContactCount++; // increment counter + LastContact = hContact; + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + // if weather contact exists, set the status to online so it is ready for update + // if (ContactCount != 0) status = ONLINE; + // in case where the default station is missing + if (opt.DefStn == NULL && ContactCount != 0) + { + if (!DBGetContactSettingString(LastContact,WEATHERPROTONAME,"ID",&dbv)) + { + strcpy(opt.Default, dbv.pszVal); + DBFreeVariant(&dbv); + } + opt.DefStn = LastContact; + if (!DBGetContactSettingString(LastContact,WEATHERPROTONAME,"Nick",&dbv)) + { + wsprintf(str, Translate("%s is now the default weather station"), dbv.pszVal); + DBFreeVariant(&dbv); + MessageBox(NULL, str, Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); + } + } + // save option in case of default station changed + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); +} + +void ConvertDataValue(WIDATAITEM *UpdateData, char *Data) +{ + char str[MAX_DATA_LEN]; + + // convert the unit + if (strcmp(Data, Translate("")) && strcmp(Data, NODATA) && strcmp(Data, Translate(NODATA))) + { + // temperature + if (!strcmp(UpdateData->Name, "Temperature") || !strcmp(UpdateData->Name, "High") || + !strcmp(UpdateData->Name, "Low") || !strcmp(UpdateData->Name, "Feel") || + !strcmp(UpdateData->Name, "Dewpoint") || + !_stricmp(UpdateData->Unit, "C") || !_stricmp(UpdateData->Unit, "F") || + !_stricmp(UpdateData->Unit, "K")) + { + GetTemp(Data, UpdateData->Unit, str); + strcpy(Data, str); + } + // pressure + else if (!strcmp(UpdateData->Name, "Pressure") || !_stricmp(UpdateData->Unit, "HPA") || + !_stricmp(UpdateData->Unit, "KPA") || !_stricmp(UpdateData->Unit, "MB") || + !_stricmp(UpdateData->Unit, "TORR") || !_stricmp(UpdateData->Unit, "IN") || + !_stricmp(UpdateData->Unit, "MM")) + { + GetPressure(Data, UpdateData->Unit, str); + strcpy(Data, str); + } + // speed + else if (!strcmp(UpdateData->Name, "Wind Speed") || !_stricmp(UpdateData->Unit, "KM/H") || + !_stricmp(UpdateData->Unit, "M/S") || !_stricmp(UpdateData->Unit, "MPH") || + !_stricmp(UpdateData->Unit, "KNOTS")) + { + GetSpeed(Data, UpdateData->Unit, str); + strcpy(Data, str); + } + // visibility + else if (!strcmp(UpdateData->Name, "Visibility") || !_stricmp(UpdateData->Unit, "KM") || + !_stricmp(UpdateData->Unit, "MILES")) + { + GetDist(Data, UpdateData->Unit, str); + strcpy(Data, str); + } + // elevation + else if (!strcmp(UpdateData->Name, "Elevation") || !_stricmp(UpdateData->Unit, "FT") || + !_stricmp(UpdateData->Unit, "M")) + { + GetElev(Data, UpdateData->Unit, str); + strcpy(Data, str); + } + // converting case for condition to the upper+lower format + else if (!_stricmp(UpdateData->Unit, "COND")) + CaseConv(Data); + // degree sign + else if (!_stricmp(UpdateData->Unit, "DEG")) + { + if (!opt.DoNotAppendUnit) strcat(Data, opt.DegreeSign); + } + // percent sign + else if (!_stricmp(UpdateData->Unit, "%")) + { + if (!opt.DoNotAppendUnit) strcat(Data, "%"); + } + // truncating strings for day/month to 2 or 3 characters + else if (!_stricmp(UpdateData->Unit, "DAY") || !_stricmp(UpdateData->Unit, "MONTH")) + if (opt.dUnit > 1 && strlen(Data) > opt.dUnit) Data[opt.dUnit] = '\0'; + } +} + +//============ GET THE VALUE OF A DATAITEM ============ + +// get the value of the data using the start, end strings +// UpdateData = the WIDATAITEM struct containing start, end, unit +// Data = the string containing weather data obtained from UpdateData +// global var. used: szInfo = the downloaded string +void GetDataValue(WIDATAITEM *UpdateData, char *Data, char** szData) +{ + char last = 0, current, *start, *end; + unsigned startloc = 0, endloc = 0, respos = 0; + BOOL tag = FALSE, symb = FALSE; + char *szInfo = *szData; + + Data[0] = 0; + // parse the data if available + if (UpdateData->Start[0] == 0 && UpdateData->End[0] == 0) return; + start = szInfo; + // the start string must be found + if (UpdateData->Start[0] != 0) { + start = strstr(szInfo, UpdateData->Start); + if (start != NULL) { + // set the starting location for getting data + start += strlen(UpdateData->Start); + szInfo = start; + } + } + // the end string must be found too + if (UpdateData->End[0] != 0) + end = strstr(szInfo, UpdateData->End); + else end = strstr(szInfo, " "); + if (end != NULL) { + // set the ending location + startloc = 0; + endloc = end - szInfo; + end += strlen(UpdateData->End); + last = '\n'; + } + // ignore if not both of the string found - this prevent crashes + if (start != NULL && end != NULL) + { + // begin reading the data from start location to end location + // remove all HTML tag in between, as well as leading space, ending space, + // multiple spaces, tabs, and return key + while (startloc < endloc) + { + if (szInfo[startloc] == '<') tag = TRUE; + else if (szInfo[startloc] == '&' && + (szInfo[startloc+1] == ';' || szInfo[startloc+2] == ';' || szInfo[startloc+3] == ';' || + szInfo[startloc+4] == ';' || szInfo[startloc+5] == ';' || szInfo[startloc+6] == ';')) + symb = TRUE; + else if (szInfo[startloc] == '>') tag = FALSE; + else if (szInfo[startloc] == ';') symb = FALSE; + else { + if (!tag && !symb) { + current = szInfo[startloc]; + if (current == '\n' || current == '\t' || current == ' ' || current == '\r') + current = ' '; + if (current != ' ' || last != ' ') { + if (last != '\n' && (respos != 0 || (respos == 0 && last != ' '))) + Data[respos++] = last; + last = current; + } + } + } + ++startloc; + // prevent crashes if the string go over maximun length -> generate an error + if (respos >= MAX_DATA_LEN) { + if (opt.ShowWarnings && UpdateData->Name[0] != 0 && strcmp(UpdateData->Name, "Ignore")) { + mir_snprintf(Data, MAX_DATA_LEN, Translate("Error when obtaining data: %s"), UpdateData->Name); + WPShowMessage(Data, SM_WARNING); + } + strncpy(Data, Translate(""), MAX_DATA_LEN); + last = ' '; + respos = MAX_DATA_LEN - 1; + break; + } + } + + // get the last character + if (last != ' ') + Data[respos++] = last; + + // null terminate the string + Data[respos] = 0; + + // write raw data for debug + Netlib_Logf(hNetlibUser, "%s: %s", UpdateData->Name, Data); + + // convert the unit + ConvertDataValue(UpdateData, Data); + + // remove the string before the data from szInfo + szInfo = end; + } + *szData = szInfo; +} + +//============ ALLOCATE SPACE AND COPY STRING ============ + +// copy a string into a new memory location +// Data = the field the data is copied to +// Value = the original string, the string where data is copied from +void wSetData(char **Data, const char *Value) +{ + if (Value[0] != 0) + { + char *newData = (char*)mir_alloc(strlen(Value)+3); + strcpy(newData, Value); + *Data = newData; + } + else + *Data = ""; +} + +// A safer free function that free memory for a string +// Data = the string occuping the data to be freed +void wfree(char **Data) +{ + if (*Data && strlen(*Data) > 0) mir_free(*Data); + *Data = NULL; +} + +//============ MANAGE THE ITEMS STORED IN DB ============ + +// remove or display the weatehr information for a contact +// hContact - the contact in which the info is going to be removed +void DBDataManage(HANDLE hContact, WORD Mode, WPARAM wParam, LPARAM lParam) +{ + DBCONTACTENUMSETTINGS dbces; + DBVARIANT dbv; + WCOUNTER wc; + wc.current = 0; + + dbces.lParam=(LPARAM)&wc; + dbces.pfnEnumProc=GetWeatherDataFromDB; + dbces.szModule=WEATHERCONDITION; + + // get all the settings and stored them in a temporary list + if(CallService(MS_DB_CONTACT_ENUMSETTINGS,(WPARAM)hContact,(LPARAM)&dbces)==-1) + wc.current--; + + // begin deleting settings + for (; --wc.current>-1;) + { + if (!DBGetContactSettingString(hContact, WEATHERCONDITION, wc.value[wc.current], &dbv)) + { + switch (Mode) + { + case WDBM_REMOVE: + DBDeleteContactSetting(hContact, WEATHERCONDITION, wc.value[wc.current]); + break; + + case WDBM_DETAILDISPLAY: + { + HWND hList = GetDlgItem((HWND)wParam, IDC_DATALIST); + LV_ITEM lvi = { 0 }; + + // skip the "WeatherInfo" variable + if (strcmp(wc.value[wc.current], "WeatherInfo") == 0 || + strcmp(wc.value[wc.current], "Ignore") == 0 || + wc.value[wc.current][0] == '#') + { + wfree(&wc.value[wc.current]); + DBFreeVariant(&dbv); + continue; + } + + lvi.mask = LVIF_TEXT | LVIF_PARAM; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.lParam = (LPARAM)wc.current; + lvi.pszText = (LPSTR)Translate(wc.value[wc.current]); + lvi.iItem = ListView_InsertItemWth(hList, &lvi); + lvi.pszText = dbv.pszVal; + ListView_SetItemTextWth(hList, lvi.iItem, 1, lvi.pszText); + break; + } + } + DBFreeVariant(&dbv); + } + wfree(&wc.value[wc.current]); + } +} + +// get single setting that is found +// szSetting = the setting name +// lparam = the counter +int GetWeatherDataFromDB(const char *szSetting, LPARAM lparam) +{ + WCOUNTER *wc = (WCOUNTER*)lparam; + wc->value[wc->current] = (char *)mir_alloc(strlen(szSetting) + 1); + strcpy(wc->value[wc->current], szSetting); + wc->current++; + return 0; +} diff --git a/protocols/weather/weather_http.c b/protocols/weather/weather_http.c deleted file mode 100644 index eb69dd4ca7..0000000000 --- a/protocols/weather/weather_http.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -This file contain the source related to downloading weather info -from the web using netlib -*/ - -#include "weather.h" - -HANDLE hNetlibUser, hNetlibHttp; - -int findHeader(NETLIBHTTPREQUEST *nlhrReply, char *hdr) -{ - int res = -1, i; - for (i=0; iheadersCount; i++) - { - if (_stricmp(nlhrReply->headers[i].szName, hdr) == 0) - { - res = i; - break; - } - } - return res; -} - -//============ DOWNLOAD NEW WEATHER ============ - -// function to download webpage from the internet -// szUrl = URL of the webpage to be retrieved -// return value = 0 for success, 1 or HTTP error code for failure -// global var used: szData, szInfo = containing the retrieved data -int InternetDownloadFile (char *szUrl, char* cookie, char** szData) -{ - int result = 0xBADBAD; - char* szRedirUrl = NULL; - NETLIBHTTPREQUEST nlhr = {0}, *nlhrReply; - NETLIBHTTPHEADER headers[6]; - - // initialize the netlib request - nlhr.cbSize = sizeof(nlhr); - nlhr.requestType = REQUEST_GET; - nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; - nlhr.szUrl = szUrl; - nlhr.nlc = hNetlibHttp; - - if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5)) - nlhr.flags |= NLHRF_PERSISTENT | NLHRF_REDIRECT; - - // change the header so the plugin is pretended to be IE 6 + WinXP - nlhr.headersCount = 5; - nlhr.headers = headers; - 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 = "Cache-Control"; - nlhr.headers[1].szValue = "no-cache"; - nlhr.headers[2].szName = "Pragma"; - nlhr.headers[2].szValue = "no-cache"; - nlhr.headers[3].szName = "Connection"; - nlhr.headers[3].szValue = "close"; - nlhr.headers[4].szName = "Cookie"; - nlhr.headers[4].szValue = cookie; -// nlhr.headers[5].szName = "If-Modified-Since"; -// nlhr.headers[5].szValue = "Tue, 24 Feb 2009 03:44:23 GMT"; - - if (cookie == NULL || cookie[0] == 0) --nlhr.headersCount; - - while (result == 0xBADBAD) - { - // download the page - nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, - (WPARAM)hNetlibUser,(LPARAM)&nlhr); - - if (nlhrReply) - { - // if the recieved code is 200 OK - if(nlhrReply->resultCode == 200) - { - if (nlhrReply->dataLength) - { - char* end; - int i; - - result = 0; - -// i = findHeader(nlhrReply, "Date-Modified"); - - // allocate memory and save the retrieved data - *szData = (char *)mir_alloc(nlhrReply->dataLength + 2); - - memcpy(*szData, nlhrReply->pData, nlhrReply->dataLength); - (*szData)[nlhrReply->dataLength] = 0; - - i = findHeader(nlhrReply, "Content-Type"); - if (i != -1) - { - if (strstr(_strlwr((char*)nlhrReply->headers[i].szValue), "utf-8")) - mir_utf8decode(*szData, NULL); - } - - end = *szData; - for (;;) - { - char* beg = strstr(end, "'); - tmp = *end; *end = 0; - - method = strstr(beg, "http-equiv=\""); - if (method && _strnicmp(method+12, "Content-Type", 12) == 0 && strstr(method, "utf-8")) - { - *end = tmp; - mir_utf8decode(*szData, NULL); - break; - } - else - *end = tmp; - } - } - } - else - result = DATA_EMPTY; - } - // if the recieved code is 302 Moved, Found, etc - // workaround for url forwarding - else if(nlhrReply->resultCode == 302 || nlhrReply->resultCode == 301 || nlhrReply->resultCode == 303 ) // page moved - { - // get the url for the new location and save it to szInfo - // look for the reply header "Location" - int i = findHeader(nlhrReply, "Location"); - - if (i != -1) - { - size_t rlen = 0; - if (nlhrReply->headers[i].szValue[0] == '/') - { - char* szPath; - char* szPref = strstr(szUrl, "://"); - szPref = szPref ? szPref + 3 : szUrl; - szPath = strchr(szPref, '/'); - rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl); - } - - szRedirUrl = (char*)mir_realloc(szRedirUrl, - rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1); - - strncpy(szRedirUrl, szUrl, rlen); - strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue); - - GetSearchStr(szRedirUrl); - - nlhr.szUrl = szRedirUrl; - } - } - // return error code if the recieved code is neither 200 OK nor 302 Moved - else - { - *szData = (char *)mir_alloc(512); - // store the error code in szData - wsprintf(*szData, "Error occured! HTTP Error: %i\n", nlhrReply->resultCode); - result = (int)nlhrReply->resultCode; - } - - hNetlibHttp = nlhrReply->nlc; - // make a copy of the retrieved data, then free the memory of the http reply - CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply); - } - // if the data does not downloaded successfully (ie. disconnected), then return 1000 as error code - else - { - *szData = (char *)mir_alloc(512); - // store the error code in szData - strcpy(*szData, "NetLib error occurred!!"); - result = NETLIB_ERROR; - hNetlibHttp = NULL; - } - - } - - mir_free(szRedirUrl); - - return result; -} - -//============ NETLIB INITIALIZATION ============ - -// initialize netlib support for weather protocol -void NetlibInit(void) -{ - NETLIBUSER nlu = {0}; - nlu.cbSize = sizeof(nlu); - nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION; - nlu.szSettingsModule = WEATHERPROTONAME; - nlu.szDescriptiveName = Translate("Weather HTTP connections"); - hNetlibUser=(HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); -} - -void NetlibHttpDisconnect(void) -{ - if (hNetlibHttp) - { - HANDLE hConn = hNetlibHttp; - hNetlibHttp = NULL; - Netlib_CloseHandle(hConn); - } -} - diff --git a/protocols/weather/weather_http.cpp b/protocols/weather/weather_http.cpp new file mode 100644 index 0000000000..eb69dd4ca7 --- /dev/null +++ b/protocols/weather/weather_http.cpp @@ -0,0 +1,226 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +This file contain the source related to downloading weather info +from the web using netlib +*/ + +#include "weather.h" + +HANDLE hNetlibUser, hNetlibHttp; + +int findHeader(NETLIBHTTPREQUEST *nlhrReply, char *hdr) +{ + int res = -1, i; + for (i=0; iheadersCount; i++) + { + if (_stricmp(nlhrReply->headers[i].szName, hdr) == 0) + { + res = i; + break; + } + } + return res; +} + +//============ DOWNLOAD NEW WEATHER ============ + +// function to download webpage from the internet +// szUrl = URL of the webpage to be retrieved +// return value = 0 for success, 1 or HTTP error code for failure +// global var used: szData, szInfo = containing the retrieved data +int InternetDownloadFile (char *szUrl, char* cookie, char** szData) +{ + int result = 0xBADBAD; + char* szRedirUrl = NULL; + NETLIBHTTPREQUEST nlhr = {0}, *nlhrReply; + NETLIBHTTPHEADER headers[6]; + + // initialize the netlib request + nlhr.cbSize = sizeof(nlhr); + nlhr.requestType = REQUEST_GET; + nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; + nlhr.szUrl = szUrl; + nlhr.nlc = hNetlibHttp; + + if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5)) + nlhr.flags |= NLHRF_PERSISTENT | NLHRF_REDIRECT; + + // change the header so the plugin is pretended to be IE 6 + WinXP + nlhr.headersCount = 5; + nlhr.headers = headers; + 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 = "Cache-Control"; + nlhr.headers[1].szValue = "no-cache"; + nlhr.headers[2].szName = "Pragma"; + nlhr.headers[2].szValue = "no-cache"; + nlhr.headers[3].szName = "Connection"; + nlhr.headers[3].szValue = "close"; + nlhr.headers[4].szName = "Cookie"; + nlhr.headers[4].szValue = cookie; +// nlhr.headers[5].szName = "If-Modified-Since"; +// nlhr.headers[5].szValue = "Tue, 24 Feb 2009 03:44:23 GMT"; + + if (cookie == NULL || cookie[0] == 0) --nlhr.headersCount; + + while (result == 0xBADBAD) + { + // download the page + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, + (WPARAM)hNetlibUser,(LPARAM)&nlhr); + + if (nlhrReply) + { + // if the recieved code is 200 OK + if(nlhrReply->resultCode == 200) + { + if (nlhrReply->dataLength) + { + char* end; + int i; + + result = 0; + +// i = findHeader(nlhrReply, "Date-Modified"); + + // allocate memory and save the retrieved data + *szData = (char *)mir_alloc(nlhrReply->dataLength + 2); + + memcpy(*szData, nlhrReply->pData, nlhrReply->dataLength); + (*szData)[nlhrReply->dataLength] = 0; + + i = findHeader(nlhrReply, "Content-Type"); + if (i != -1) + { + if (strstr(_strlwr((char*)nlhrReply->headers[i].szValue), "utf-8")) + mir_utf8decode(*szData, NULL); + } + + end = *szData; + for (;;) + { + char* beg = strstr(end, "'); + tmp = *end; *end = 0; + + method = strstr(beg, "http-equiv=\""); + if (method && _strnicmp(method+12, "Content-Type", 12) == 0 && strstr(method, "utf-8")) + { + *end = tmp; + mir_utf8decode(*szData, NULL); + break; + } + else + *end = tmp; + } + } + } + else + result = DATA_EMPTY; + } + // if the recieved code is 302 Moved, Found, etc + // workaround for url forwarding + else if(nlhrReply->resultCode == 302 || nlhrReply->resultCode == 301 || nlhrReply->resultCode == 303 ) // page moved + { + // get the url for the new location and save it to szInfo + // look for the reply header "Location" + int i = findHeader(nlhrReply, "Location"); + + if (i != -1) + { + size_t rlen = 0; + if (nlhrReply->headers[i].szValue[0] == '/') + { + char* szPath; + char* szPref = strstr(szUrl, "://"); + szPref = szPref ? szPref + 3 : szUrl; + szPath = strchr(szPref, '/'); + rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl); + } + + szRedirUrl = (char*)mir_realloc(szRedirUrl, + rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1); + + strncpy(szRedirUrl, szUrl, rlen); + strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue); + + GetSearchStr(szRedirUrl); + + nlhr.szUrl = szRedirUrl; + } + } + // return error code if the recieved code is neither 200 OK nor 302 Moved + else + { + *szData = (char *)mir_alloc(512); + // store the error code in szData + wsprintf(*szData, "Error occured! HTTP Error: %i\n", nlhrReply->resultCode); + result = (int)nlhrReply->resultCode; + } + + hNetlibHttp = nlhrReply->nlc; + // make a copy of the retrieved data, then free the memory of the http reply + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply); + } + // if the data does not downloaded successfully (ie. disconnected), then return 1000 as error code + else + { + *szData = (char *)mir_alloc(512); + // store the error code in szData + strcpy(*szData, "NetLib error occurred!!"); + result = NETLIB_ERROR; + hNetlibHttp = NULL; + } + + } + + mir_free(szRedirUrl); + + return result; +} + +//============ NETLIB INITIALIZATION ============ + +// initialize netlib support for weather protocol +void NetlibInit(void) +{ + NETLIBUSER nlu = {0}; + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION; + nlu.szSettingsModule = WEATHERPROTONAME; + nlu.szDescriptiveName = Translate("Weather HTTP connections"); + hNetlibUser=(HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); +} + +void NetlibHttpDisconnect(void) +{ + if (hNetlibHttp) + { + HANDLE hConn = hNetlibHttp; + hNetlibHttp = NULL; + Netlib_CloseHandle(hConn); + } +} + diff --git a/protocols/weather/weather_icons.c b/protocols/weather/weather_icons.c deleted file mode 100644 index e1b95c4405..0000000000 --- a/protocols/weather/weather_icons.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - - -#include "weather.h" - -HANDLE hIcoLibIconsChanged = NULL; - -struct _tag_iconList -{ - char* szDescr; - char* szName; - int defIconID; - HANDLE hIconLibItem; -} -static iconList[] = -{ - { "Protocol icon", "main", IDI_ICON }, - { "Update Disabled", "disabled", IDI_DISABLED }, - { "View Log", "log", IDI_LOG }, - { "Update with Clear", "update2", IDI_UPDATE2 }, - { "View Brief", "brief", IDI_S }, - { "View Complete", "read", IDI_READ }, - { "Weather Update", "update", IDI_UPDATE }, - { "Weather Map", "map", IDI_MAP }, - { "Popup", "popup", IDI_POPUP }, - { "No Popup", "nopopup", IDI_NOPOPUP }, - { "Edit Settings", "edit", IDI_EDIT }, -}; - -void InitIcons(void) -{ - char szFile[MAX_PATH]; - char szSettingName[100]; - SKINICONDESC sid = {0}; - unsigned i; - - GetModuleFileName(hInst, szFile, MAX_PATH); - - sid.cbSize = sizeof(SKINICONDESC); - sid.pszDefaultFile = szFile; - sid.pszName = szSettingName; - sid.pszSection = WEATHERPROTONAME; - - for (i = 0; i < SIZEOF(iconList); i++) - { - mir_snprintf(szSettingName, sizeof( szSettingName ), "%s_%s", WEATHERPROTONAME, iconList[i].szName); - - sid.pszDescription = iconList[i].szDescr; - sid.iDefaultIndex = -iconList[i].defIconID; - iconList[i].hIconLibItem = ( HANDLE )CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); - } -} - - -HICON LoadIconEx(const char* name, BOOL big) -{ - char szSettingName[100]; - mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", WEATHERPROTONAME, name); - return (HICON)CallService(MS_SKIN2_GETICON, big, (LPARAM)szSettingName); -} - -HANDLE GetIconHandle(const char* name) -{ - unsigned i; - for (i=0; i < SIZEOF(iconList); i++) - if (strcmp(iconList[i].szName, name) == 0) - return iconList[i].hIconLibItem; - return NULL; -} - -void ReleaseIconEx(HICON hIcon) -{ - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); -} diff --git a/protocols/weather/weather_icons.cpp b/protocols/weather/weather_icons.cpp new file mode 100644 index 0000000000..e1b95c4405 --- /dev/null +++ b/protocols/weather/weather_icons.cpp @@ -0,0 +1,90 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + + +#include "weather.h" + +HANDLE hIcoLibIconsChanged = NULL; + +struct _tag_iconList +{ + char* szDescr; + char* szName; + int defIconID; + HANDLE hIconLibItem; +} +static iconList[] = +{ + { "Protocol icon", "main", IDI_ICON }, + { "Update Disabled", "disabled", IDI_DISABLED }, + { "View Log", "log", IDI_LOG }, + { "Update with Clear", "update2", IDI_UPDATE2 }, + { "View Brief", "brief", IDI_S }, + { "View Complete", "read", IDI_READ }, + { "Weather Update", "update", IDI_UPDATE }, + { "Weather Map", "map", IDI_MAP }, + { "Popup", "popup", IDI_POPUP }, + { "No Popup", "nopopup", IDI_NOPOPUP }, + { "Edit Settings", "edit", IDI_EDIT }, +}; + +void InitIcons(void) +{ + char szFile[MAX_PATH]; + char szSettingName[100]; + SKINICONDESC sid = {0}; + unsigned i; + + GetModuleFileName(hInst, szFile, MAX_PATH); + + sid.cbSize = sizeof(SKINICONDESC); + sid.pszDefaultFile = szFile; + sid.pszName = szSettingName; + sid.pszSection = WEATHERPROTONAME; + + for (i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, sizeof( szSettingName ), "%s_%s", WEATHERPROTONAME, iconList[i].szName); + + sid.pszDescription = iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + iconList[i].hIconLibItem = ( HANDLE )CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + } +} + + +HICON LoadIconEx(const char* name, BOOL big) +{ + char szSettingName[100]; + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", WEATHERPROTONAME, name); + return (HICON)CallService(MS_SKIN2_GETICON, big, (LPARAM)szSettingName); +} + +HANDLE GetIconHandle(const char* name) +{ + unsigned i; + for (i=0; i < SIZEOF(iconList); i++) + if (strcmp(iconList[i].szName, name) == 0) + return iconList[i].hIconLibItem; + return NULL; +} + +void ReleaseIconEx(HICON hIcon) +{ + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); +} diff --git a/protocols/weather/weather_info.c b/protocols/weather/weather_info.c deleted file mode 100644 index b5997feb6c..0000000000 --- a/protocols/weather/weather_info.c +++ /dev/null @@ -1,253 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - - -/* -This file contain the source for displaying information for the -ini files, as well as function that are used for debug purpose -regrading the loading of ini contents -*/ - -#include "weather.h" - -//============ INI INFORMATION ============ - -// List INI Information for all loaded INI files -void INIInfo(HWND hwndDlg) -{ - char str[16]; - size_t memused = 0; - LVITEM lvi = {0}; - WIDATALIST *Item = WIHead; - - HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST); - - ListView_DeleteAllItems(hIniList); - - lvi.mask = LVIF_TEXT; - lvi.iItem = 0; - while (Item != NULL) - { - // get the data for the ini file - lvi.iSubItem = 0; - lvi.pszText = Item->Data.InternalName; - ListView_InsertItem(hIniList, &lvi); - lvi.iSubItem = 1; - lvi.pszText = Item->Data.Author; - ListView_SetItem(hIniList, &lvi); - lvi.iSubItem = 2; - lvi.pszText = Item->Data.Version; - ListView_SetItem(hIniList, &lvi); - lvi.iSubItem = 3; - switch (Item->Data.InternalVer) - { - case 1: lvi.pszText = "1.0"; break; - case 2: lvi.pszText = "1.1"; break; - case 3: lvi.pszText = "1.1a"; break; - case 4: lvi.pszText = "1.2"; break; - case 5: lvi.pszText = "1.3"; break; - case 6: lvi.pszText = "1.4"; break; - default: lvi.pszText = ""; break; - } - ListView_SetItem(hIniList, &lvi); - lvi.iSubItem = 4; - lvi.pszText = _ltoa(Item->Data.UpdateDataCount, str, 10); - ListView_SetItem(hIniList, &lvi); - lvi.iSubItem = 5; - lvi.pszText = Item->Data.DisplayName; - ListView_SetItem(hIniList, &lvi); - lvi.iSubItem = 6; - lvi.pszText = Item->Data.ShortFileName; - ListView_SetItem(hIniList, &lvi); - - memused += Item->Data.MemUsed; - - Item = Item->next; - ++lvi.iItem; - } - SetDlgItemText(hwndDlg, IDC_INICOUNT, _itoa(lvi.iItem, str, 10)); - SetDlgItemText(hwndDlg, IDC_MEMUSED, _ltoa((long)memused, str, 10)); -} - -static const struct tag_Columns -{ - const char *name; - unsigned size; -} -columns[] = -{ - { "Name" , 70 }, - { "Author" , 100 }, - { "File Version" , 70 }, - { "INI Version" , 70 }, - { "Items" , 40 }, - { "Display Name" , 200 }, - { "File Name" , 150 }, -}; - - -INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - unsigned i; - - HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST); - LVCOLUMN lvc = {0}; - - lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; - lvc.fmt = LVCFMT_LEFT; - for (i=0; i<7; ++i) - { - lvc.iSubItem = i; - lvc.pszText = Translate(columns[i].name); - lvc.cx = columns[i].size; - ListView_InsertColumnWth(hIniList, i, &lvc); - } - INIInfo(hwndDlg); - } - - break; - - case WM_DESTROY: - break; - - case WM_COMMAND: - if ( HIWORD(wParam) == BN_CLICKED && - LOWORD(wParam) == IDC_RELOADINI ) - { - DestroyWIList(); - LoadWIData(TRUE); - INIInfo(hwndDlg); - } - break; - } - return 0; -} - - -// get the info of individual ini file -// pszSvc = the internal name of the service to get the data -void GetINIInfo(char *pszSvc) { - char str2[2048]; - WIDATA *sData = GetWIData(pszSvc); - // if the service does not exist among the loaded INI's - if (sData == NULL) - { - wsprintf(str2, Translate("The corresponding INI file for \"%s\" is not found."), pszSvc); - MessageBox(NULL, str2, Translate("Weather INI information"), MB_OK|MB_ICONINFORMATION); - } - // if exist, get the information - else - { - wsprintf(str2, Translate("Weather INI information for \"%s\":"), pszSvc); - strcat(str2, "\n\n"); - strcat(str2, Translate("Name:")); - strcat(str2, "\t\t"); - strcat(str2, sData->DisplayName); - strcat(str2, "\n"); - strcat(str2, Translate("Internal Name:")); - strcat(str2, "\t"); - strcat(str2, sData->InternalName); - strcat(str2, "\n"); - strcat(str2, Translate("Author:")); - strcat(str2, "\t\t"); - strcat(str2, sData->Author); - strcat(str2, "\n"); - strcat(str2, Translate("Version:")); - strcat(str2, "\t\t"); - strcat(str2, sData->Version); - strcat(str2, "\n"); - strcat(str2, Translate("INI Version:")); - strcat(str2, "\t"); - switch (sData->InternalVer) - { - case 1: strcat(str2, "1.0"); break; - case 2: strcat(str2, "1.1"); break; - case 3: strcat(str2, "1.1a"); break; - case 4: strcat(str2, "1.2"); break; - case 5: strcat(str2, "1.3"); break; - case 6: strcat(str2, "1.4"); break; - } - strcat(str2, "\n"); - strcat(str2, Translate("File Name:")); - strcat(str2, "\t"); - strcat(str2, sData->ShortFileName); - strcat(str2, "\n"); - strcat(str2, Translate("Item Count:")); - wsprintf(str2, "%s\t%i\n", str2, sData->UpdateDataCount); - strcat(str2, Translate("Memory Used:")); - wsprintf(str2, "%s\t%i ", str2, sData->MemUsed); - strcat(str2, Translate("bytes")); - strcat(str2, "\n\n"); - strcat(str2, Translate("Description:")); - strcat(str2, "\n"); - strcat(str2, sData->Description); - - // display the message box and quit - MessageBox(NULL, str2, Translate("Weather INI information"), MB_OK|MB_ICONINFORMATION); - } -} - -//============ DISPLAY A LIST FOR CUSTOM VARIABLES ============ - -// a message box for displaying the list of custom variables -// can be found when click on "More" in text option dialog -void MoreVarList(void) -{ - char str[10240], tempstr[1024], *find; - - WIDATALIST *Item = WIHead; - // heading - strcpy(str, Translate("Here is a list of custom variables that are currently available")); - strcat(str, "\n\n"); - // loop through all weather services to find custom variables - while (Item != NULL) - { - WIDATAITEMLIST* WItem; - WItem = Item->Data.UpdateData; - // loop through all update items in a service - while (WItem != NULL) - { - // the custom variable is defined as "%[]" - // ignore the "hi" item and hidden items - if (strcmp(WItem->Item.Name, "Ignore") && WItem->Item.Name[0] != '#') { - wsprintf(tempstr, "%c[%s]", '%', WItem->Item.Name); - find = strstr(str, tempstr); - // if the custom variable does not exist in the list, add it to the list - if (find == NULL) { - strcat(str, tempstr); - strcat(str, ", "); - } - } - WItem = WItem->Next; - } - Item = Item->next; - } - // remove the last comma in the list - find = strrchr(str, ','); - if (find != NULL) *find = '\0'; - - // display the list in a message box - MessageBox(NULL, str, Translate("More Variables"), MB_OK|MB_ICONINFORMATION|MB_TOPMOST); -} - diff --git a/protocols/weather/weather_info.cpp b/protocols/weather/weather_info.cpp new file mode 100644 index 0000000000..b5997feb6c --- /dev/null +++ b/protocols/weather/weather_info.cpp @@ -0,0 +1,253 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + + +/* +This file contain the source for displaying information for the +ini files, as well as function that are used for debug purpose +regrading the loading of ini contents +*/ + +#include "weather.h" + +//============ INI INFORMATION ============ + +// List INI Information for all loaded INI files +void INIInfo(HWND hwndDlg) +{ + char str[16]; + size_t memused = 0; + LVITEM lvi = {0}; + WIDATALIST *Item = WIHead; + + HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST); + + ListView_DeleteAllItems(hIniList); + + lvi.mask = LVIF_TEXT; + lvi.iItem = 0; + while (Item != NULL) + { + // get the data for the ini file + lvi.iSubItem = 0; + lvi.pszText = Item->Data.InternalName; + ListView_InsertItem(hIniList, &lvi); + lvi.iSubItem = 1; + lvi.pszText = Item->Data.Author; + ListView_SetItem(hIniList, &lvi); + lvi.iSubItem = 2; + lvi.pszText = Item->Data.Version; + ListView_SetItem(hIniList, &lvi); + lvi.iSubItem = 3; + switch (Item->Data.InternalVer) + { + case 1: lvi.pszText = "1.0"; break; + case 2: lvi.pszText = "1.1"; break; + case 3: lvi.pszText = "1.1a"; break; + case 4: lvi.pszText = "1.2"; break; + case 5: lvi.pszText = "1.3"; break; + case 6: lvi.pszText = "1.4"; break; + default: lvi.pszText = ""; break; + } + ListView_SetItem(hIniList, &lvi); + lvi.iSubItem = 4; + lvi.pszText = _ltoa(Item->Data.UpdateDataCount, str, 10); + ListView_SetItem(hIniList, &lvi); + lvi.iSubItem = 5; + lvi.pszText = Item->Data.DisplayName; + ListView_SetItem(hIniList, &lvi); + lvi.iSubItem = 6; + lvi.pszText = Item->Data.ShortFileName; + ListView_SetItem(hIniList, &lvi); + + memused += Item->Data.MemUsed; + + Item = Item->next; + ++lvi.iItem; + } + SetDlgItemText(hwndDlg, IDC_INICOUNT, _itoa(lvi.iItem, str, 10)); + SetDlgItemText(hwndDlg, IDC_MEMUSED, _ltoa((long)memused, str, 10)); +} + +static const struct tag_Columns +{ + const char *name; + unsigned size; +} +columns[] = +{ + { "Name" , 70 }, + { "Author" , 100 }, + { "File Version" , 70 }, + { "INI Version" , 70 }, + { "Items" , 40 }, + { "Display Name" , 200 }, + { "File Name" , 150 }, +}; + + +INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + unsigned i; + + HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST); + LVCOLUMN lvc = {0}; + + lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; + lvc.fmt = LVCFMT_LEFT; + for (i=0; i<7; ++i) + { + lvc.iSubItem = i; + lvc.pszText = Translate(columns[i].name); + lvc.cx = columns[i].size; + ListView_InsertColumnWth(hIniList, i, &lvc); + } + INIInfo(hwndDlg); + } + + break; + + case WM_DESTROY: + break; + + case WM_COMMAND: + if ( HIWORD(wParam) == BN_CLICKED && + LOWORD(wParam) == IDC_RELOADINI ) + { + DestroyWIList(); + LoadWIData(TRUE); + INIInfo(hwndDlg); + } + break; + } + return 0; +} + + +// get the info of individual ini file +// pszSvc = the internal name of the service to get the data +void GetINIInfo(char *pszSvc) { + char str2[2048]; + WIDATA *sData = GetWIData(pszSvc); + // if the service does not exist among the loaded INI's + if (sData == NULL) + { + wsprintf(str2, Translate("The corresponding INI file for \"%s\" is not found."), pszSvc); + MessageBox(NULL, str2, Translate("Weather INI information"), MB_OK|MB_ICONINFORMATION); + } + // if exist, get the information + else + { + wsprintf(str2, Translate("Weather INI information for \"%s\":"), pszSvc); + strcat(str2, "\n\n"); + strcat(str2, Translate("Name:")); + strcat(str2, "\t\t"); + strcat(str2, sData->DisplayName); + strcat(str2, "\n"); + strcat(str2, Translate("Internal Name:")); + strcat(str2, "\t"); + strcat(str2, sData->InternalName); + strcat(str2, "\n"); + strcat(str2, Translate("Author:")); + strcat(str2, "\t\t"); + strcat(str2, sData->Author); + strcat(str2, "\n"); + strcat(str2, Translate("Version:")); + strcat(str2, "\t\t"); + strcat(str2, sData->Version); + strcat(str2, "\n"); + strcat(str2, Translate("INI Version:")); + strcat(str2, "\t"); + switch (sData->InternalVer) + { + case 1: strcat(str2, "1.0"); break; + case 2: strcat(str2, "1.1"); break; + case 3: strcat(str2, "1.1a"); break; + case 4: strcat(str2, "1.2"); break; + case 5: strcat(str2, "1.3"); break; + case 6: strcat(str2, "1.4"); break; + } + strcat(str2, "\n"); + strcat(str2, Translate("File Name:")); + strcat(str2, "\t"); + strcat(str2, sData->ShortFileName); + strcat(str2, "\n"); + strcat(str2, Translate("Item Count:")); + wsprintf(str2, "%s\t%i\n", str2, sData->UpdateDataCount); + strcat(str2, Translate("Memory Used:")); + wsprintf(str2, "%s\t%i ", str2, sData->MemUsed); + strcat(str2, Translate("bytes")); + strcat(str2, "\n\n"); + strcat(str2, Translate("Description:")); + strcat(str2, "\n"); + strcat(str2, sData->Description); + + // display the message box and quit + MessageBox(NULL, str2, Translate("Weather INI information"), MB_OK|MB_ICONINFORMATION); + } +} + +//============ DISPLAY A LIST FOR CUSTOM VARIABLES ============ + +// a message box for displaying the list of custom variables +// can be found when click on "More" in text option dialog +void MoreVarList(void) +{ + char str[10240], tempstr[1024], *find; + + WIDATALIST *Item = WIHead; + // heading + strcpy(str, Translate("Here is a list of custom variables that are currently available")); + strcat(str, "\n\n"); + // loop through all weather services to find custom variables + while (Item != NULL) + { + WIDATAITEMLIST* WItem; + WItem = Item->Data.UpdateData; + // loop through all update items in a service + while (WItem != NULL) + { + // the custom variable is defined as "%[]" + // ignore the "hi" item and hidden items + if (strcmp(WItem->Item.Name, "Ignore") && WItem->Item.Name[0] != '#') { + wsprintf(tempstr, "%c[%s]", '%', WItem->Item.Name); + find = strstr(str, tempstr); + // if the custom variable does not exist in the list, add it to the list + if (find == NULL) { + strcat(str, tempstr); + strcat(str, ", "); + } + } + WItem = WItem->Next; + } + Item = Item->next; + } + // remove the last comma in the list + find = strrchr(str, ','); + if (find != NULL) *find = '\0'; + + // display the list in a message box + MessageBox(NULL, str, Translate("More Variables"), MB_OK|MB_ICONINFORMATION|MB_TOPMOST); +} + diff --git a/protocols/weather/weather_ini.c b/protocols/weather/weather_ini.c deleted file mode 100644 index eba127bdaf..0000000000 --- a/protocols/weather/weather_ini.c +++ /dev/null @@ -1,628 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - - -/* -This file contain the source related to loading the reading the -weather ini files and store them into memory. Also containing -code for unloading and getting weather data from the ini settings. -*/ - -#include "weather.h" - -HWND hWndSetup; - -//============ DATA LIST (LINKED LIST) ============ - -// add an item into weather service data list -// Data = the service data to be added to the list -void WIListAdd(WIDATA Data) -{ - WIDATALIST *newItem; - - // create a new datalist item and point to the data - newItem = (WIDATALIST*)mir_alloc(sizeof(WIDATALIST)); - newItem->Data = Data; - // add to the linked list - newItem->next = NULL; - if (WITail == NULL) WIHead = newItem; - else WITail->next = newItem; - WITail = newItem; -} - -// get the service data (from loaded ini file) by internal name -// pszServ = internal name for the service -// return value = the matching WIDATA struct for pszServ, NULL if no match found -WIDATA* GetWIData(char *pszServ) -{ - WIDATALIST *Item = WIHead; - - // loop through the list to find matching internal name - while (Item != NULL) - { - // if internal name found, return the data - if (strcmp(Item->Data.InternalName, pszServ) == 0) return &Item->Data; - Item = Item->next; - } - // return NULL when no match found - return NULL; -} - -// remove all service data from memory -void DestroyWIList(void) -{ - // free the list one by one - while (WIHead != NULL) - { - WIDATALIST *wi = WIHead; - WIHead = wi->next; - FreeWIData(&wi->Data); // free the data struct - mir_free(wi); - } - - // make sure the entire list is clear - WITail = NULL; -} - -//============ DATA ITEM LIST (LINKED LIST) ============ - -// add a new update item into the current list -void WIItemListAdd(WIDATAITEM *DataItem, WIDATA *Data) -{ - WIDATAITEMLIST *newItem; - - newItem = (WIDATAITEMLIST*)mir_alloc(sizeof(WIDATAITEMLIST)); - newItem->Item = *DataItem; - newItem->Next = NULL; - if (Data->UpdateData == NULL) Data->UpdateData = newItem; - else Data->UpdateDataTail->Next = newItem; - Data->UpdateDataTail = newItem; -} - -// reset the data item by using empty string -// Item = the item to set -// name = the string to store in the "name" field -void ResetDataItem(WIDATAITEM *Item, const char *name) -{ - char str[] = "ID Search - Station Name"; - Item->Name = mir_alloc(sizeof(str)); - strcpy(Item->Name, str); - Item->Start = ""; - Item->End = ""; - Item->Unit = ""; - Item->Url = ""; - Item->Break = ""; - Item->Type = 0; -} - -// free the data item by using empty string -// Item = the item to free -void FreeDataItem(WIDATAITEM *Item) -{ - wfree(&Item->Name); - wfree(&Item->Start); - wfree(&Item->End); - wfree(&Item->Unit); - wfree(&Item->Url); - wfree(&Item->Break); -} - -//============ Condition Icon List ============ - -// initiate icon assignmet list -void WICondListInit(WICONDLIST *List) -{ - List->Tail = NULL; - List->Head = NULL; -} - -// add a new update item into the current list -void WICondListAdd(char *str, WICONDLIST *List) -{ - WICONDITEM *newItem; - - newItem = (WICONDITEM*)mir_alloc(sizeof(WICONDITEM)); - CharLowerBuff(str, (DWORD)strlen(str)); - wSetData(&newItem->Item, str); - newItem->Next = NULL; - if (List->Tail == NULL) List->Head = newItem; - else List->Tail->Next = newItem; - List->Tail = newItem; -} - -// check if the condition string matched for the assignment -BOOL IsContainedInCondList(const char *pszStr, WICONDLIST *List) -{ - WICONDITEM *Item = List->Head; - - // loop through the list to find matching internal name - while (Item != NULL) - { - // if internal name found, return true indicating that the data is found - if (strstr(pszStr, Item->Item)) return TRUE; - Item = Item->Next; - } - // return false when no match found - return FALSE; -} - -// free the memory for icon assignment list -void DestroyCondList(WICONDLIST *List) -{ - WICONDITEM *temp; - - temp = List->Head; - - // free the list one by one - while (temp != NULL) - { - List->Head = temp->Next; - wfree(&temp->Item); // free the data struct - mir_free(temp); - temp = List->Head; - } - // make sure the entire list is clear - List->Tail = NULL; -} - - -//============ LOADING INI FILES ============ - -// load the weather update data form INI files -BOOL LoadWIData(BOOL dial) -{ - HANDLE hFind; - char szSearchPath[MAX_PATH], FileName[MAX_PATH], *chop; - WIN32_FIND_DATA fd; - WIDATA Data; - - // make sure that the current service data list is empty - WITail = NULL; - WIHead = WITail; - - // find all *.ini file in the plugin\weather directory - GetModuleFileName(GetModuleHandle(NULL), szSearchPath, sizeof(szSearchPath)); - chop = strrchr(szSearchPath, '\\'); - *chop = '\0'; - strcat(szSearchPath,"\\Plugins\\Weather\\*.ini"); - strcpy(FileName, szSearchPath); - - hFind = FindFirstFile(szSearchPath, &fd); - - // load the content of the ini file into memory - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - chop = strrchr(FileName, '\\'); - chop[1] = '\0'; - strcat(FileName, fd.cFileName); - if (_stricmp(fd.cFileName, "SAMPLE_INI.INI")) - { - LoadStationData(FileName, fd.cFileName, &Data); - if (Data.Enabled) WIListAdd(Data); - } - // look through the entire "plugins\weather" directory - } - while(FindNextFile(hFind, &fd)); - FindClose(hFind); - } - if (WIHead == NULL) - { - // no ini found, display an error message box. - if (dial) - hWndSetup = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SETUP), NULL, DlgProcSetup); - else - MessageBox(NULL, - Translate("No update data file is found. Please check your Plugins\\Weather directory."), - Translate("Weather Protocol"), MB_OK | MB_ICONERROR); - return FALSE; - } - return TRUE; -} - -// load the station data from a file -// pszFile = the file name + path for the ini file to be loaded -// pszShortFile = the file name of the ini file, but not including the path -// Data = the struct to load the ini content to, and return to previous function -void LoadStationData(char *pszFile, char *pszShortFile, WIDATA *Data) -{ - WIDATAITEM DataItem; - FILE *pfile; - int i; - char Line[4096], *Group, *Temp; - char *ValName, *Value; - - static const char *statusStr[10] = - { - "LIGHTNING", - "FOG", - "SNOW SHOWER", - "SNOW", - "RAIN SHOWER", - "RAIN", - "PARTLY CLOUDY", - "CLOUDY", - "SUNNY", - "N/A" - }; - - // clean up old stuff - ZeroMemory(Data, sizeof(Data)); - Data->Enabled = FALSE; - - // open the ini file - pfile = _fsopen(pszFile, "rt", _SH_DENYWR); - if (pfile != NULL) - { - fgets(Line, sizeof(Line), pfile); - TrimString(Line); - // make sure it is a valid weather protocol ini file - if (!strcmp(Line, "[Weather 0.3.x Update Data]")) - Data->InternalVer = 1; - else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.1]")) - Data->InternalVer = 2; - else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.1a]")) - Data->InternalVer = 3; - else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.2]")) - Data->InternalVer = 4; - else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.3]")) - Data->InternalVer = 5; - else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.4]")) - Data->InternalVer = 6; - else - { - wsprintf(Line, Translate("Invalid ini format for: %s"), pszFile); - MessageBox(NULL, Line, Translate("Weather Protocol"), MB_OK|MB_ICONERROR); - fclose(pfile); - return; - } - - // initialize all data fields - Group = ""; - Data->DisplayName = ""; - Data->InternalName = ""; - Data->Description = ""; - Data->Author = ""; - Data->Version = ""; - Data->DefaultURL = ""; - Data->DefaultMap = ""; - Data->UpdateURL = ""; - Data->UpdateURL2 = ""; - Data->UpdateURL3 = ""; - Data->UpdateURL4 = ""; - Data->Cookie = ""; - Data->IDSearch.SearchURL = ""; - Data->IDSearch.NotFoundStr = ""; - Data->NameSearch.SearchURL = ""; - Data->NameSearch.NotFoundStr = ""; - Data->NameSearch.SingleStr = ""; - Data->NameSearch.Single.First = ""; - Data->NameSearch.Multiple.First = ""; - Data->IDSearch.Available = FALSE; - Data->NameSearch.Single.Available = FALSE; - Data->NameSearch.Multiple.Available = FALSE; - wSetData(&Data->FileName, pszFile); - wSetData(&Data->ShortFileName, pszShortFile); - - ResetDataItem(&Data->IDSearch.Name, "ID Search - Station Name"); - ResetDataItem(&Data->NameSearch.Single.Name, "Name Search Single Result - Station Name"); - ResetDataItem(&Data->NameSearch.Single.ID, "Name Search Single Result - Station ID"); - ResetDataItem(&Data->NameSearch.Multiple.Name, "Name Search Multiple Result - Station Name"); - ResetDataItem(&Data->NameSearch.Multiple.ID, "Name Search Multiple Result - Station ID"); - - DataItem.Name = ""; - DataItem.Start = ""; - DataItem.End = ""; - DataItem.Unit = ""; - DataItem.Url = ""; - DataItem.Break = ""; - DataItem.Type = 0; - - Temp = ""; - - // initialize the linked list for update items - Data->UpdateDataCount = 0; - Data->MemUsed = sizeof(WIDATA) + sizeof(WIDATALIST) + strlen(pszShortFile) + strlen(pszFile) + 20; - Data->UpdateData = NULL; - Data->UpdateDataTail = NULL; - - // initialize the icon assignment list - for (i=0; i<10; i++) WICondListInit(&Data->CondList[i]); - - while (!feof(pfile)) - { - // determine current tag - - if (fgets(Line, sizeof(Line), pfile) == NULL) break; - TrimString(Line); - - // if the line is a group header/footer - if (Line[0] == '[') - { - char *chop = strchr(Line+1,']'); - if (chop == NULL) continue; - if (Line[1] != '/') // if it is not a footer (for old ini) - { - // save the group name - Temp = (char *)mir_alloc(strlen(Line)+10); - strncpy(Temp, Line+1, chop-Line-1); - Temp[chop-Line-1] = 0; - wfree(&Group); - wSetData(&Group, Temp); - // see if it is a update item, if it is, add a new item to the linked list - // if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && - // strcmpi(Group, "NAME SEARCH")) - // wSetData(&DataItem.Name, Group); - if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && - _stricmp(Group, "NAME SEARCH") && _stricmp(Group, "ICONS")) - { - wSetData(&DataItem.Name, Temp); - DataItem.Type = WID_NORMAL; - WIItemListAdd(&DataItem, Data); - Data->UpdateDataCount++; - } - mir_free(Temp); - } - else - { - wfree(&Group); - wSetData(&Group, ""); - } - } - // ignore comments and all lines without an '=' - Value = strstr(Line, "="); - if (Value == NULL) continue; - - // get the string before '=' (ValName) and after '=' (Value) - ValName = (char *)mir_alloc(strlen(Line)+1); - strncpy(ValName, Line, Value-Line); - ValName[Value-Line] = 0; - Value++; - ConvertBackslashes(Value); - // store the value for each string - if (!_stricmp(Group, "HEADER")) - { - if (!_stricmp(ValName, "NAME")) wSetData(&Data->DisplayName, Value); - else if (!_stricmp(ValName, "INTERNAL NAME")) wSetData(&Data->InternalName, Value); - else if (!_stricmp(ValName, "DESCRIPTION")) wSetData(&Data->Description, Value); - else if (!_stricmp(ValName, "AUTHOR")) wSetData(&Data->Author, Value); - else if (!_stricmp(ValName, "VERSION")) wSetData(&Data->Version, Value); - } - else if (!_stricmp(Group, "DEFAULT")) { - if (!_stricmp(ValName, "DEFAULT URL")) wSetData(&Data->DefaultURL, Value); - else if (!_stricmp(ValName, "DEFAULT MAP")) wSetData(&Data->DefaultMap, Value); - else if (!_stricmp(ValName, "UPDATE URL")) wSetData(&Data->UpdateURL, Value); - else if (!_stricmp(ValName, "UPDATE URL2")) wSetData(&Data->UpdateURL2, Value); - else if (!_stricmp(ValName, "UPDATE URL3")) wSetData(&Data->UpdateURL3, Value); - else if (!_stricmp(ValName, "UPDATE URL4")) wSetData(&Data->UpdateURL4, Value); - else if (!_stricmp(ValName, "COOKIE")) wSetData(&Data->Cookie, Value); - } - else if (!_stricmp(Group, "ID SEARCH")) - { - if (!_stricmp(ValName, "AVAILABLE")) - { - if (!_stricmp(Value, "TRUE")) Data->IDSearch.Available = TRUE; - else Data->IDSearch.Available = FALSE; - } - else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->IDSearch.SearchURL, Value); - else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->IDSearch.NotFoundStr, Value); - else if (!_stricmp(ValName, "NAME START")) wSetData(&Data->IDSearch.Name.Start, Value); - else if (!_stricmp(ValName, "NAME END")) wSetData(&Data->IDSearch.Name.End, Value); - } - else if (!_stricmp(Group, "NAME SEARCH")) - { - if (!_stricmp(ValName, "SINGLE RESULT")) - { - if (!_stricmp(Value, "TRUE")) Data->NameSearch.Single.Available = TRUE; - else Data->NameSearch.Single.Available = FALSE; - } - else if (!_stricmp(ValName, "MULTIPLE RESULT")) - { - if (!_stricmp(Value, "TRUE")) Data->NameSearch.Multiple.Available = TRUE; - else Data->NameSearch.Multiple.Available = FALSE; - } - else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->NameSearch.SearchURL, Value); - else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->NameSearch.NotFoundStr, Value); - else if (!_stricmp(ValName, "SINGLE RESULT STR")) wSetData(&Data->NameSearch.SingleStr, Value); - else if (!_stricmp(ValName, "SINGLE FIRST")) wSetData(&Data->NameSearch.Single.First, Value); - else if (!_stricmp(ValName, "SINGLE NAME START"))wSetData(&Data->NameSearch.Single.Name.Start, Value); - else if (!_stricmp(ValName, "SINGLE NAME END")) wSetData(&Data->NameSearch.Single.Name.End, Value); - else if (!_stricmp(ValName, "SINGLE ID START")) wSetData(&Data->NameSearch.Single.ID.Start, Value); - else if (!_stricmp(ValName, "SINGLE ID END")) wSetData(&Data->NameSearch.Single.ID.End, Value); - else if (!_stricmp(ValName, "MULT FIRST")) wSetData(&Data->NameSearch.Multiple.First, Value); - else if (!_stricmp(ValName, "MULT NAME START")) wSetData(&Data->NameSearch.Multiple.Name.Start, Value); - else if (!_stricmp(ValName, "MULT NAME END")) wSetData(&Data->NameSearch.Multiple.Name.End, Value); - else if (!_stricmp(ValName, "MULT ID START")) wSetData(&Data->NameSearch.Multiple.ID.Start, Value); - else if (!_stricmp(ValName, "MULT ID END")) wSetData(&Data->NameSearch.Multiple.ID.End, Value); - } - else if (!_stricmp(Group, "ICONS")) - { - for (i=0; i<10; i++) - { - if (!_stricmp(ValName, statusStr[i])) - { - WICondListAdd(Value, &Data->CondList[i]); - break; - } - } - } - else if (Data->UpdateDataCount != 0) - { - if (!_stricmp(ValName, "START")) wSetData(&Data->UpdateDataTail->Item.Start, Value); - else if (!_stricmp(ValName, "SOURCE")) wSetData(&Data->UpdateDataTail->Item.Start, Value); - else if (!_stricmp(ValName, "END")) wSetData(&Data->UpdateDataTail->Item.End, Value); - else if (!_stricmp(ValName, "UNIT")) wSetData(&Data->UpdateDataTail->Item.Unit, Value); - else if (!_stricmp(ValName, "URL")) wSetData(&Data->UpdateDataTail->Item.Url, Value); - else if (!_stricmp(ValName, "HIDDEN")) - { - if (!_stricmp(Value, "TRUE")) - { - char *nm = Data->UpdateDataTail->Item.Name; - size_t len = strlen(nm) + 1; - - Data->UpdateDataTail->Item.Name = nm = mir_realloc(nm, len + 3); - memmove(nm + 1, nm, len); - *nm = '#'; - } - } - else if (!_stricmp(ValName, "SET DATA")) - { - Data->UpdateDataTail->Item.Type = WID_SET; - wSetData(&Data->UpdateDataTail->Item.End, Value); - } - else if (!_stricmp(ValName, "BREAK DATA")) - { - Data->UpdateDataTail->Item.Type = WID_BREAK; - wSetData(&Data->UpdateDataTail->Item.Break, Value); - } - } - // recalculate memory used - Data->MemUsed += (strlen(Value) + 10); - wfree(&ValName); - } - // calcualate memory used for the ini and close the file - Data->MemUsed += sizeof(WIDATAITEMLIST)*Data->UpdateDataCount; - Data->Enabled = TRUE; // enable the service - fclose(pfile); - wfree(&Group); - } -} - -//============ FREE WIDATA ITEM FROM MEMORY ============ - -// free the WIDATA struct from memory -// Data = the struct to be freed -void FreeWIData(WIDATA *Data) -{ - WIDATAITEMLIST* WItem; - int i; - - // free update items linked list first - WItem = Data->UpdateData; - while (WItem != NULL) - { - Data->UpdateData = WItem->Next; - FreeDataItem(&WItem->Item); - mir_free(WItem); - WItem = Data->UpdateData; - } - - // free the strings in the rest of the struct - wfree(&Data->DisplayName); - wfree(&Data->InternalName); - wfree(&Data->Description); - wfree(&Data->Author); - wfree(&Data->Version); - wfree(&Data->DefaultURL); - wfree(&Data->DefaultMap); - wfree(&Data->UpdateURL); - wfree(&Data->UpdateURL2); - wfree(&Data->UpdateURL3); - wfree(&Data->UpdateURL4); - wfree(&Data->Cookie); - wfree(&Data->IDSearch.SearchURL); - wfree(&Data->IDSearch.NotFoundStr); - FreeDataItem(&Data->IDSearch.Name); - wfree(&Data->NameSearch.SearchURL); - wfree(&Data->NameSearch.NotFoundStr); - wfree(&Data->NameSearch.SingleStr); - wfree(&Data->NameSearch.Single.First); - FreeDataItem(&Data->NameSearch.Single.Name); - FreeDataItem(&Data->NameSearch.Single.ID); - wfree(&Data->NameSearch.Multiple.First); - FreeDataItem(&Data->NameSearch.Multiple.Name); - FreeDataItem(&Data->NameSearch.Multiple.ID); - wfree(&Data->ShortFileName); - wfree(&Data->FileName); - for (i=0; i<10; i++) DestroyCondList(&Data->CondList[i]); -} - -//============ WEATHER INI SETUP DIALOG ============ - -INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - - // make the buttons flat - SendMessage(GetDlgItem(hwndDlg,IDC_STEP1), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hwndDlg,IDC_STEP2), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hwndDlg,IDC_STEP3), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hwndDlg,IDC_STEP4), BUTTONSETASFLATBTN, 0, 0); - - // set icons - SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx("main", TRUE)); - SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx("main", FALSE)); - - WindowList_Add(hWindowList, hwndDlg, NULL); - ShowWindow(hwndDlg, SW_SHOW); - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_STEP1: - // update current data - CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, - (WPARAM)"http://addons.miranda-im.org/index.php?action=display&id=78"); - break; - - case IDC_STEP2: - { - char szPath[1024], *chop; - GetModuleFileName(GetModuleHandle(NULL), szPath, sizeof(szPath)); - chop = strrchr(szPath, '\\'); - *chop = '\0'; - strcat(szPath,"\\Plugins\\weather\\"); - _mkdir(szPath); - ShellExecute((HWND)lParam, "open", szPath, "", "", SW_SHOW); - break; - } - - case IDC_STEP3: - if (LoadWIData(FALSE)) - MessageBox(NULL, Translate("All update data has been reloaded."), - Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); - break; - - case IDC_STEP4: - WeatherAdd(0, 0); - - case IDCANCEL: - // close the info window - DestroyWindow(hwndDlg); - break; - } - break; - - case WM_CLOSE: - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); - break; - } - return FALSE; -} - diff --git a/protocols/weather/weather_ini.cpp b/protocols/weather/weather_ini.cpp new file mode 100644 index 0000000000..363f2d364f --- /dev/null +++ b/protocols/weather/weather_ini.cpp @@ -0,0 +1,628 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + + +/* +This file contain the source related to loading the reading the +weather ini files and store them into memory. Also containing +code for unloading and getting weather data from the ini settings. +*/ + +#include "weather.h" + +HWND hWndSetup; + +//============ DATA LIST (LINKED LIST) ============ + +// add an item into weather service data list +// Data = the service data to be added to the list +void WIListAdd(WIDATA Data) +{ + WIDATALIST *newItem; + + // create a new datalist item and point to the data + newItem = (WIDATALIST*)mir_alloc(sizeof(WIDATALIST)); + newItem->Data = Data; + // add to the linked list + newItem->next = NULL; + if (WITail == NULL) WIHead = newItem; + else WITail->next = newItem; + WITail = newItem; +} + +// get the service data (from loaded ini file) by internal name +// pszServ = internal name for the service +// return value = the matching WIDATA struct for pszServ, NULL if no match found +WIDATA* GetWIData(char *pszServ) +{ + WIDATALIST *Item = WIHead; + + // loop through the list to find matching internal name + while (Item != NULL) + { + // if internal name found, return the data + if (strcmp(Item->Data.InternalName, pszServ) == 0) return &Item->Data; + Item = Item->next; + } + // return NULL when no match found + return NULL; +} + +// remove all service data from memory +void DestroyWIList(void) +{ + // free the list one by one + while (WIHead != NULL) + { + WIDATALIST *wi = WIHead; + WIHead = wi->next; + FreeWIData(&wi->Data); // free the data struct + mir_free(wi); + } + + // make sure the entire list is clear + WITail = NULL; +} + +//============ DATA ITEM LIST (LINKED LIST) ============ + +// add a new update item into the current list +void WIItemListAdd(WIDATAITEM *DataItem, WIDATA *Data) +{ + WIDATAITEMLIST *newItem; + + newItem = (WIDATAITEMLIST*)mir_alloc(sizeof(WIDATAITEMLIST)); + newItem->Item = *DataItem; + newItem->Next = NULL; + if (Data->UpdateData == NULL) Data->UpdateData = newItem; + else Data->UpdateDataTail->Next = newItem; + Data->UpdateDataTail = newItem; +} + +// reset the data item by using empty string +// Item = the item to set +// name = the string to store in the "name" field +void ResetDataItem(WIDATAITEM *Item, const char *name) +{ + char str[] = "ID Search - Station Name"; + Item->Name = ( char* )mir_alloc(sizeof(str)); + strcpy(Item->Name, str); + Item->Start = ""; + Item->End = ""; + Item->Unit = ""; + Item->Url = ""; + Item->Break = ""; + Item->Type = 0; +} + +// free the data item by using empty string +// Item = the item to free +void FreeDataItem(WIDATAITEM *Item) +{ + wfree(&Item->Name); + wfree(&Item->Start); + wfree(&Item->End); + wfree(&Item->Unit); + wfree(&Item->Url); + wfree(&Item->Break); +} + +//============ Condition Icon List ============ + +// initiate icon assignmet list +void WICondListInit(WICONDLIST *List) +{ + List->Tail = NULL; + List->Head = NULL; +} + +// add a new update item into the current list +void WICondListAdd(char *str, WICONDLIST *List) +{ + WICONDITEM *newItem; + + newItem = (WICONDITEM*)mir_alloc(sizeof(WICONDITEM)); + CharLowerBuff(str, (DWORD)strlen(str)); + wSetData(&newItem->Item, str); + newItem->Next = NULL; + if (List->Tail == NULL) List->Head = newItem; + else List->Tail->Next = newItem; + List->Tail = newItem; +} + +// check if the condition string matched for the assignment +BOOL IsContainedInCondList(const char *pszStr, WICONDLIST *List) +{ + WICONDITEM *Item = List->Head; + + // loop through the list to find matching internal name + while (Item != NULL) + { + // if internal name found, return true indicating that the data is found + if (strstr(pszStr, Item->Item)) return TRUE; + Item = Item->Next; + } + // return false when no match found + return FALSE; +} + +// free the memory for icon assignment list +void DestroyCondList(WICONDLIST *List) +{ + WICONDITEM *temp; + + temp = List->Head; + + // free the list one by one + while (temp != NULL) + { + List->Head = temp->Next; + wfree(&temp->Item); // free the data struct + mir_free(temp); + temp = List->Head; + } + // make sure the entire list is clear + List->Tail = NULL; +} + + +//============ LOADING INI FILES ============ + +// load the weather update data form INI files +BOOL LoadWIData(BOOL dial) +{ + HANDLE hFind; + char szSearchPath[MAX_PATH], FileName[MAX_PATH], *chop; + WIN32_FIND_DATA fd; + WIDATA Data; + + // make sure that the current service data list is empty + WITail = NULL; + WIHead = WITail; + + // find all *.ini file in the plugin\weather directory + GetModuleFileName(GetModuleHandle(NULL), szSearchPath, sizeof(szSearchPath)); + chop = strrchr(szSearchPath, '\\'); + *chop = '\0'; + strcat(szSearchPath,"\\Plugins\\Weather\\*.ini"); + strcpy(FileName, szSearchPath); + + hFind = FindFirstFile(szSearchPath, &fd); + + // load the content of the ini file into memory + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + chop = strrchr(FileName, '\\'); + chop[1] = '\0'; + strcat(FileName, fd.cFileName); + if (_stricmp(fd.cFileName, "SAMPLE_INI.INI")) + { + LoadStationData(FileName, fd.cFileName, &Data); + if (Data.Enabled) WIListAdd(Data); + } + // look through the entire "plugins\weather" directory + } + while(FindNextFile(hFind, &fd)); + FindClose(hFind); + } + if (WIHead == NULL) + { + // no ini found, display an error message box. + if (dial) + hWndSetup = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SETUP), NULL, DlgProcSetup); + else + MessageBox(NULL, + Translate("No update data file is found. Please check your Plugins\\Weather directory."), + Translate("Weather Protocol"), MB_OK | MB_ICONERROR); + return FALSE; + } + return TRUE; +} + +// load the station data from a file +// pszFile = the file name + path for the ini file to be loaded +// pszShortFile = the file name of the ini file, but not including the path +// Data = the struct to load the ini content to, and return to previous function +void LoadStationData(char *pszFile, char *pszShortFile, WIDATA *Data) +{ + WIDATAITEM DataItem; + FILE *pfile; + int i; + char Line[4096], *Group, *Temp; + char *ValName, *Value; + + static const char *statusStr[10] = + { + "LIGHTNING", + "FOG", + "SNOW SHOWER", + "SNOW", + "RAIN SHOWER", + "RAIN", + "PARTLY CLOUDY", + "CLOUDY", + "SUNNY", + "N/A" + }; + + // clean up old stuff + ZeroMemory(Data, sizeof(Data)); + Data->Enabled = FALSE; + + // open the ini file + pfile = _fsopen(pszFile, "rt", _SH_DENYWR); + if (pfile != NULL) + { + fgets(Line, sizeof(Line), pfile); + TrimString(Line); + // make sure it is a valid weather protocol ini file + if (!strcmp(Line, "[Weather 0.3.x Update Data]")) + Data->InternalVer = 1; + else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.1]")) + Data->InternalVer = 2; + else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.1a]")) + Data->InternalVer = 3; + else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.2]")) + Data->InternalVer = 4; + else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.3]")) + Data->InternalVer = 5; + else if (!strcmp(Line, "[Weather 0.3.x Update Data 1.4]")) + Data->InternalVer = 6; + else + { + wsprintf(Line, Translate("Invalid ini format for: %s"), pszFile); + MessageBox(NULL, Line, Translate("Weather Protocol"), MB_OK|MB_ICONERROR); + fclose(pfile); + return; + } + + // initialize all data fields + Group = ""; + Data->DisplayName = ""; + Data->InternalName = ""; + Data->Description = ""; + Data->Author = ""; + Data->Version = ""; + Data->DefaultURL = ""; + Data->DefaultMap = ""; + Data->UpdateURL = ""; + Data->UpdateURL2 = ""; + Data->UpdateURL3 = ""; + Data->UpdateURL4 = ""; + Data->Cookie = ""; + Data->IDSearch.SearchURL = ""; + Data->IDSearch.NotFoundStr = ""; + Data->NameSearch.SearchURL = ""; + Data->NameSearch.NotFoundStr = ""; + Data->NameSearch.SingleStr = ""; + Data->NameSearch.Single.First = ""; + Data->NameSearch.Multiple.First = ""; + Data->IDSearch.Available = FALSE; + Data->NameSearch.Single.Available = FALSE; + Data->NameSearch.Multiple.Available = FALSE; + wSetData(&Data->FileName, pszFile); + wSetData(&Data->ShortFileName, pszShortFile); + + ResetDataItem(&Data->IDSearch.Name, "ID Search - Station Name"); + ResetDataItem(&Data->NameSearch.Single.Name, "Name Search Single Result - Station Name"); + ResetDataItem(&Data->NameSearch.Single.ID, "Name Search Single Result - Station ID"); + ResetDataItem(&Data->NameSearch.Multiple.Name, "Name Search Multiple Result - Station Name"); + ResetDataItem(&Data->NameSearch.Multiple.ID, "Name Search Multiple Result - Station ID"); + + DataItem.Name = ""; + DataItem.Start = ""; + DataItem.End = ""; + DataItem.Unit = ""; + DataItem.Url = ""; + DataItem.Break = ""; + DataItem.Type = 0; + + Temp = ""; + + // initialize the linked list for update items + Data->UpdateDataCount = 0; + Data->MemUsed = sizeof(WIDATA) + sizeof(WIDATALIST) + strlen(pszShortFile) + strlen(pszFile) + 20; + Data->UpdateData = NULL; + Data->UpdateDataTail = NULL; + + // initialize the icon assignment list + for (i=0; i<10; i++) WICondListInit(&Data->CondList[i]); + + while (!feof(pfile)) + { + // determine current tag + + if (fgets(Line, sizeof(Line), pfile) == NULL) break; + TrimString(Line); + + // if the line is a group header/footer + if (Line[0] == '[') + { + char *chop = strchr(Line+1,']'); + if (chop == NULL) continue; + if (Line[1] != '/') // if it is not a footer (for old ini) + { + // save the group name + Temp = (char *)mir_alloc(strlen(Line)+10); + strncpy(Temp, Line+1, chop-Line-1); + Temp[chop-Line-1] = 0; + wfree(&Group); + wSetData(&Group, Temp); + // see if it is a update item, if it is, add a new item to the linked list + // if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && + // strcmpi(Group, "NAME SEARCH")) + // wSetData(&DataItem.Name, Group); + if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") && + _stricmp(Group, "NAME SEARCH") && _stricmp(Group, "ICONS")) + { + wSetData(&DataItem.Name, Temp); + DataItem.Type = WID_NORMAL; + WIItemListAdd(&DataItem, Data); + Data->UpdateDataCount++; + } + mir_free(Temp); + } + else + { + wfree(&Group); + wSetData(&Group, ""); + } + } + // ignore comments and all lines without an '=' + Value = strstr(Line, "="); + if (Value == NULL) continue; + + // get the string before '=' (ValName) and after '=' (Value) + ValName = (char *)mir_alloc(strlen(Line)+1); + strncpy(ValName, Line, Value-Line); + ValName[Value-Line] = 0; + Value++; + ConvertBackslashes(Value); + // store the value for each string + if (!_stricmp(Group, "HEADER")) + { + if (!_stricmp(ValName, "NAME")) wSetData(&Data->DisplayName, Value); + else if (!_stricmp(ValName, "INTERNAL NAME")) wSetData(&Data->InternalName, Value); + else if (!_stricmp(ValName, "DESCRIPTION")) wSetData(&Data->Description, Value); + else if (!_stricmp(ValName, "AUTHOR")) wSetData(&Data->Author, Value); + else if (!_stricmp(ValName, "VERSION")) wSetData(&Data->Version, Value); + } + else if (!_stricmp(Group, "DEFAULT")) { + if (!_stricmp(ValName, "DEFAULT URL")) wSetData(&Data->DefaultURL, Value); + else if (!_stricmp(ValName, "DEFAULT MAP")) wSetData(&Data->DefaultMap, Value); + else if (!_stricmp(ValName, "UPDATE URL")) wSetData(&Data->UpdateURL, Value); + else if (!_stricmp(ValName, "UPDATE URL2")) wSetData(&Data->UpdateURL2, Value); + else if (!_stricmp(ValName, "UPDATE URL3")) wSetData(&Data->UpdateURL3, Value); + else if (!_stricmp(ValName, "UPDATE URL4")) wSetData(&Data->UpdateURL4, Value); + else if (!_stricmp(ValName, "COOKIE")) wSetData(&Data->Cookie, Value); + } + else if (!_stricmp(Group, "ID SEARCH")) + { + if (!_stricmp(ValName, "AVAILABLE")) + { + if (!_stricmp(Value, "TRUE")) Data->IDSearch.Available = TRUE; + else Data->IDSearch.Available = FALSE; + } + else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->IDSearch.SearchURL, Value); + else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->IDSearch.NotFoundStr, Value); + else if (!_stricmp(ValName, "NAME START")) wSetData(&Data->IDSearch.Name.Start, Value); + else if (!_stricmp(ValName, "NAME END")) wSetData(&Data->IDSearch.Name.End, Value); + } + else if (!_stricmp(Group, "NAME SEARCH")) + { + if (!_stricmp(ValName, "SINGLE RESULT")) + { + if (!_stricmp(Value, "TRUE")) Data->NameSearch.Single.Available = TRUE; + else Data->NameSearch.Single.Available = FALSE; + } + else if (!_stricmp(ValName, "MULTIPLE RESULT")) + { + if (!_stricmp(Value, "TRUE")) Data->NameSearch.Multiple.Available = TRUE; + else Data->NameSearch.Multiple.Available = FALSE; + } + else if (!_stricmp(ValName, "SEARCH URL")) wSetData(&Data->NameSearch.SearchURL, Value); + else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->NameSearch.NotFoundStr, Value); + else if (!_stricmp(ValName, "SINGLE RESULT STR")) wSetData(&Data->NameSearch.SingleStr, Value); + else if (!_stricmp(ValName, "SINGLE FIRST")) wSetData(&Data->NameSearch.Single.First, Value); + else if (!_stricmp(ValName, "SINGLE NAME START"))wSetData(&Data->NameSearch.Single.Name.Start, Value); + else if (!_stricmp(ValName, "SINGLE NAME END")) wSetData(&Data->NameSearch.Single.Name.End, Value); + else if (!_stricmp(ValName, "SINGLE ID START")) wSetData(&Data->NameSearch.Single.ID.Start, Value); + else if (!_stricmp(ValName, "SINGLE ID END")) wSetData(&Data->NameSearch.Single.ID.End, Value); + else if (!_stricmp(ValName, "MULT FIRST")) wSetData(&Data->NameSearch.Multiple.First, Value); + else if (!_stricmp(ValName, "MULT NAME START")) wSetData(&Data->NameSearch.Multiple.Name.Start, Value); + else if (!_stricmp(ValName, "MULT NAME END")) wSetData(&Data->NameSearch.Multiple.Name.End, Value); + else if (!_stricmp(ValName, "MULT ID START")) wSetData(&Data->NameSearch.Multiple.ID.Start, Value); + else if (!_stricmp(ValName, "MULT ID END")) wSetData(&Data->NameSearch.Multiple.ID.End, Value); + } + else if (!_stricmp(Group, "ICONS")) + { + for (i=0; i<10; i++) + { + if (!_stricmp(ValName, statusStr[i])) + { + WICondListAdd(Value, &Data->CondList[i]); + break; + } + } + } + else if (Data->UpdateDataCount != 0) + { + if (!_stricmp(ValName, "START")) wSetData(&Data->UpdateDataTail->Item.Start, Value); + else if (!_stricmp(ValName, "SOURCE")) wSetData(&Data->UpdateDataTail->Item.Start, Value); + else if (!_stricmp(ValName, "END")) wSetData(&Data->UpdateDataTail->Item.End, Value); + else if (!_stricmp(ValName, "UNIT")) wSetData(&Data->UpdateDataTail->Item.Unit, Value); + else if (!_stricmp(ValName, "URL")) wSetData(&Data->UpdateDataTail->Item.Url, Value); + else if (!_stricmp(ValName, "HIDDEN")) + { + if (!_stricmp(Value, "TRUE")) + { + char *nm = Data->UpdateDataTail->Item.Name; + size_t len = strlen(nm) + 1; + + Data->UpdateDataTail->Item.Name = nm = ( char* )mir_realloc(nm, len + 3); + memmove(nm + 1, nm, len); + *nm = '#'; + } + } + else if (!_stricmp(ValName, "SET DATA")) + { + Data->UpdateDataTail->Item.Type = WID_SET; + wSetData(&Data->UpdateDataTail->Item.End, Value); + } + else if (!_stricmp(ValName, "BREAK DATA")) + { + Data->UpdateDataTail->Item.Type = WID_BREAK; + wSetData(&Data->UpdateDataTail->Item.Break, Value); + } + } + // recalculate memory used + Data->MemUsed += (strlen(Value) + 10); + wfree(&ValName); + } + // calcualate memory used for the ini and close the file + Data->MemUsed += sizeof(WIDATAITEMLIST)*Data->UpdateDataCount; + Data->Enabled = TRUE; // enable the service + fclose(pfile); + wfree(&Group); + } +} + +//============ FREE WIDATA ITEM FROM MEMORY ============ + +// free the WIDATA struct from memory +// Data = the struct to be freed +void FreeWIData(WIDATA *Data) +{ + WIDATAITEMLIST* WItem; + int i; + + // free update items linked list first + WItem = Data->UpdateData; + while (WItem != NULL) + { + Data->UpdateData = WItem->Next; + FreeDataItem(&WItem->Item); + mir_free(WItem); + WItem = Data->UpdateData; + } + + // free the strings in the rest of the struct + wfree(&Data->DisplayName); + wfree(&Data->InternalName); + wfree(&Data->Description); + wfree(&Data->Author); + wfree(&Data->Version); + wfree(&Data->DefaultURL); + wfree(&Data->DefaultMap); + wfree(&Data->UpdateURL); + wfree(&Data->UpdateURL2); + wfree(&Data->UpdateURL3); + wfree(&Data->UpdateURL4); + wfree(&Data->Cookie); + wfree(&Data->IDSearch.SearchURL); + wfree(&Data->IDSearch.NotFoundStr); + FreeDataItem(&Data->IDSearch.Name); + wfree(&Data->NameSearch.SearchURL); + wfree(&Data->NameSearch.NotFoundStr); + wfree(&Data->NameSearch.SingleStr); + wfree(&Data->NameSearch.Single.First); + FreeDataItem(&Data->NameSearch.Single.Name); + FreeDataItem(&Data->NameSearch.Single.ID); + wfree(&Data->NameSearch.Multiple.First); + FreeDataItem(&Data->NameSearch.Multiple.Name); + FreeDataItem(&Data->NameSearch.Multiple.ID); + wfree(&Data->ShortFileName); + wfree(&Data->FileName); + for (i=0; i<10; i++) DestroyCondList(&Data->CondList[i]); +} + +//============ WEATHER INI SETUP DIALOG ============ + +INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + // make the buttons flat + SendMessage(GetDlgItem(hwndDlg,IDC_STEP1), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg,IDC_STEP2), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg,IDC_STEP3), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hwndDlg,IDC_STEP4), BUTTONSETASFLATBTN, 0, 0); + + // set icons + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx("main", TRUE)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx("main", FALSE)); + + WindowList_Add(hWindowList, hwndDlg, NULL); + ShowWindow(hwndDlg, SW_SHOW); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_STEP1: + // update current data + CallService(MS_UTILS_OPENURL, opt.NewBrowserWin, + (WPARAM)"http://addons.miranda-im.org/index.php?action=display&id=78"); + break; + + case IDC_STEP2: + { + char szPath[1024], *chop; + GetModuleFileName(GetModuleHandle(NULL), szPath, sizeof(szPath)); + chop = strrchr(szPath, '\\'); + *chop = '\0'; + strcat(szPath,"\\Plugins\\weather\\"); + _mkdir(szPath); + ShellExecute((HWND)lParam, "open", szPath, "", "", SW_SHOW); + break; + } + + case IDC_STEP3: + if (LoadWIData(FALSE)) + MessageBox(NULL, Translate("All update data has been reloaded."), + Translate("Weather Protocol"), MB_OK|MB_ICONINFORMATION); + break; + + case IDC_STEP4: + WeatherAdd(0, 0); + + case IDCANCEL: + // close the info window + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); + break; + } + return FALSE; +} + diff --git a/protocols/weather/weather_mwin.c b/protocols/weather/weather_mwin.c deleted file mode 100644 index 0f534fdf19..0000000000 --- a/protocols/weather/weather_mwin.c +++ /dev/null @@ -1,449 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2006-2009 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2006 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "weather.h" -#include "m_acc.h" - -/* DRAWGLYPH Request structure */ -typedef struct s_SKINDRAWREQUEST -{ - char szObjectID[255]; // Unic Object ID (path) to paint - RECT rcDestRect; // Rectangle to fit - RECT rcClipRect; // Rectangle to paint in. - HDC hDC; // Handler to device context to paint in. -} SKINDRAWREQUEST,*LPSKINDRAWREQUEST; - - -// Request painting glyph object -// wParam = pointer to SKINDRAWREQUEST structure -// lParam = 0 -#define MS_SKIN_DRAWGLYPH "ModernList/DrawGlyph" - - -#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip" -#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip" - -typedef BOOL (WINAPI *ft_TrackMouseEvent) (LPTRACKMOUSEEVENT lpEventTrack); - -static ft_TrackMouseEvent f_TrackMouseEvent = NULL; -static HANDLE hMwinWindowList; -static HANDLE hFontHook; - -HANDLE hMwinMenu; - -typedef struct -{ - HANDLE hContact; - HWND hAvt; - BOOL haveAvatar; -} MWinDataType; - -#define WM_REDRAWWIN (WM_USER + 17369) - -static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - MWinDataType *data = (MWinDataType*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - switch(msg) - { - case WM_CREATE: - data = (MWinDataType*)mir_calloc(sizeof(MWinDataType)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); - - data->hContact = (HANDLE)((LPCREATESTRUCT)lParam)->lpCreateParams; - data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD, - 0, 0, opt.AvatarSize, opt.AvatarSize, hwnd, NULL, hInst, 0); - if (data->hAvt) SendMessage(data->hAvt, AVATAR_SETCONTACT, 0, (LPARAM)data->hContact); - break; - - case WM_DESTROY: - mir_free(data); - break; - - case WM_CONTEXTMENU: - { - POINT pt; - HMENU hMenu; - - hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)data->hContact, 0); - GetCursorPos(&pt); - TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL); - DestroyMenu(hMenu); - } - break; - - case WM_MOUSEMOVE: - if (f_TrackMouseEvent) - { - TRACKMOUSEEVENT tme = {0}; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.hwndTrack = hwnd; - tme.dwFlags = TME_QUERY; - f_TrackMouseEvent(&tme); - - if (tme.dwFlags == 0) - { - tme.dwFlags = TME_HOVER | TME_LEAVE; - tme.hwndTrack = hwnd; - tme.dwHoverTime = CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0); - f_TrackMouseEvent(&tme); - } - } - break; - - case WM_MOUSEHOVER: - { - POINT pt; - CLCINFOTIP ti = {0}; - - GetCursorPos(&pt); - GetWindowRect(hwnd, &ti.rcItem); - - ti.cbSize = sizeof(ti); - ti.hItem = data->hContact; - ti.ptCursor = pt; - ti.isTreeFocused = 1; - CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti); - } - break; - - case WM_LBUTTONDBLCLK: - BriefInfo((WPARAM)data->hContact, 0); - break; - - case WM_COMMAND: //Needed by the contact's context menu - if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)data->hContact)) - break; - return FALSE; - - case WM_MEASUREITEM: //Needed by the contact's context menu - return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); - - case WM_DRAWITEM: //Needed by the contact's context menu - return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->code == NM_AVATAR_CHANGED) - { - BOOL newava = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)data->hContact, 0) != 0; - if (newava != data->haveAvatar) - { - LONG_PTR style = GetWindowLongPtr(data->hAvt, GWL_STYLE); - data->haveAvatar = newava; - SetWindowLongPtr(data->hAvt, GWL_STYLE, newava ? (style | WS_VISIBLE) : (style & ~WS_VISIBLE)); - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); - } - } - break; - - case WM_REDRAWWIN: - if (data->hAvt != NULL) MoveWindow(data->hAvt, 0, 0, opt.AvatarSize, opt.AvatarSize, TRUE); - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - break; - - case WM_PAINT: - { - RECT r, rc; - - if(GetUpdateRect(hwnd, &r, FALSE)) - { - DBVARIANT dbv = {0}; - PAINTSTRUCT ps; - HDC hdc; - LOGFONT lfnt, lfnt1; - COLORREF fntc, fntc1; - COLORREF clr; - int picSize = opt.AvatarSize; - HICON hIcon = NULL; - - if (!data->haveAvatar) - { - int statusIcon = DBGetContactSettingWord(data->hContact, WEATHERPROTONAME, "Status", 0); - - picSize = GetSystemMetrics(SM_CXICON); - hIcon = LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon); - if ((INT_PTR)hIcon == CALLSERVICE_NOTFOUND) - { - picSize = GetSystemMetrics(SM_CXSMICON); - hIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon); - } - } - - clr = DBGetContactSettingDword(NULL, WEATHERPROTONAME, "ColorMwinFrame", GetSysColor(COLOR_3DFACE)); - - { - FontID fntid = {0}; - strcpy(fntid.group, WEATHERPROTONAME); - strcpy(fntid.name, "Frame Font"); - fntc = CallService(MS_FONT_GET, (WPARAM)&fntid, (LPARAM)&lfnt); - - strcpy(fntid.name, "Frame Title Font"); - fntc1 = CallService(MS_FONT_GET, (WPARAM)&fntid, (LPARAM)&lfnt1); - } - - DBGetContactSettingString(data->hContact, WEATHERCONDITION, "WeatherInfo", &dbv); - - GetClientRect(hwnd, &rc); - - hdc = BeginPaint(hwnd, &ps); - - if (ServiceExists(MS_SKIN_DRAWGLYPH)) - { - SKINDRAWREQUEST rq; - memset(&rq, 0, sizeof(rq)); - rq.hDC = hdc; - rq.rcDestRect = rc; - rq.rcClipRect = rc; - - strcpy(rq.szObjectID, "Main,ID=WeatherFrame"); - CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0); - } - - if (clr != 0xFFFFFFFF) - { - HBRUSH hBkgBrush = CreateSolidBrush(clr); - FillRect(hdc, &rc, hBkgBrush); - DeleteObject(hBkgBrush); - } - - if (!data->haveAvatar) - DrawIconEx(hdc, 1, 1, hIcon, 0, 0, 0, NULL, DI_NORMAL); - - SetBkMode(hdc, TRANSPARENT); - - { - HFONT hfnt = CreateFontIndirect(&lfnt1); - HFONT hfntold = SelectObject(hdc, hfnt); - SIZE fontSize; - - char *nick = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)data->hContact, 0); - - GetTextExtentPoint32(hdc, _T("|"), 1, &fontSize); - - rc.top += 1; - rc.left += picSize + fontSize.cx; - - SetTextColor(hdc, fntc1); - DrawText(hdc, nick, -1, &rc, DT_LEFT | DT_EXPANDTABS); - - rc.top += fontSize.cy; - - SelectObject(hdc, hfntold); - DeleteObject(hfnt); - } - - if (dbv.pszVal) - { - HFONT hfnt = CreateFontIndirect(&lfnt); - HFONT hfntold = SelectObject(hdc, hfnt); - - SetTextColor(hdc, fntc); - DrawText(hdc, dbv.pszVal, -1, &rc, DT_LEFT | DT_EXPANDTABS); - - SelectObject(hdc, hfntold); - DeleteObject(hfnt); - } - EndPaint(hwnd, &ps); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); - DBFreeVariant(&dbv); - } - break; - } - - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - return(TRUE); -} - -static void addWindow(HANDLE hContact) -{ - CLISTFrame Frame = {0}; - HWND hWnd; - DBVARIANT dbv; - char winname[512]; - DWORD frameID; - - DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv); - mir_snprintf(winname, sizeof(winname), "Weather: %s", dbv.pszVal); - DBFreeVariant(&dbv); - - hWnd = CreateWindow("WeatherFrame", "", WS_CHILD | WS_VISIBLE, - 0, 0, 10, 10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, hContact); - - Frame.name = winname; - Frame.cbSize = sizeof(Frame); - Frame.hWnd = hWnd; - Frame.align = alBottom; - Frame.Flags = F_VISIBLE|F_NOBORDER; - Frame.height = 32; - - WindowList_Add(hMwinWindowList, hWnd, hContact); - - frameID = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0); - DBWriteContactSettingDword(hContact, WEATHERPROTONAME, "mwin", frameID); - DBWriteContactSettingByte(hContact, "CList", "Hidden", TRUE); -} - -void removeWindow(HANDLE hContact) -{ - DWORD frameId = DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); - - WindowList_Remove(hMwinWindowList, WindowList_Find(hMwinWindowList, hContact)); - CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0); - - DBWriteContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); - DBDeleteContactSetting(hContact, "CList", "Hidden"); -} - -void UpdateMwinData(HANDLE hContact) -{ - HWND hwnd = WindowList_Find(hMwinWindowList, hContact); - if (hwnd != NULL) - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); -} - - -INT_PTR Mwin_MenuClicked(WPARAM wParam,LPARAM lParam) -{ - BOOL addwnd = WindowList_Find(hMwinWindowList, (HANDLE)wParam) == NULL; - if (addwnd) - addWindow((HANDLE)wParam); - else - removeWindow((HANDLE)wParam); - return 0; -} - - -int BuildContactMenu(WPARAM wparam,LPARAM lparam) -{ - CLISTMENUITEM mi = {0}; - - mi.cbSize = sizeof(mi); - mi.flags = CMIM_FLAGS | - (DBGetContactSettingDword((HANDLE)wparam, WEATHERPROTONAME, "mwin", 0) ? CMIF_CHECKED : 0); - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMwinMenu, (LPARAM)&mi); - return 0; -} - - -int RedrawFrame(WPARAM wParam, LPARAM lParam) -{ - WindowList_Broadcast(hMwinWindowList, WM_REDRAWWIN, 0, 0); - return 0; -} - - -void InitMwin(void) -{ - HANDLE hContact; - HMODULE hUser = GetModuleHandle("user32.dll"); - - if (!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) return; - - f_TrackMouseEvent = (ft_TrackMouseEvent)GetProcAddress(hUser, "TrackMouseEvent"); - - - hMwinWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); - - { - WNDCLASS wndclass; - wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wndclass.lpfnWndProc = wndProc; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = 0; - wndclass.hInstance = hInst; - wndclass.hIcon = NULL; - wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); - wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); - wndclass.lpszMenuName = NULL; - wndclass.lpszClassName = "WeatherFrame"; - RegisterClass(&wndclass); - } - - { - FontID fontid = {0}; - ColourID colourid = {0}; - HDC hdc; - - colourid.cbSize = sizeof(ColourID); - strcpy(colourid.dbSettingsGroup, WEATHERPROTONAME); - strcpy(colourid.setting, "ColorMwinFrame"); - strcpy(colourid.name, "Frame Background"); - strcpy(colourid.group, WEATHERPROTONAME); - colourid.defcolour = GetSysColor(COLOR_3DFACE); - - CallService(MS_COLOUR_REGISTER, (WPARAM)&colourid, 0); - - fontid.cbSize = sizeof(FontID); - fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID; - strcpy(fontid.dbSettingsGroup, WEATHERPROTONAME); - strcpy(fontid.group, WEATHERPROTONAME); - strcpy(fontid.name, "Frame Font"); - strcpy(fontid.prefix, "fnt0"); - - hdc = GetDC(NULL); - fontid.deffontsettings.size = -13; - ReleaseDC(0, hdc); - - fontid.deffontsettings.charset = DEFAULT_CHARSET; - strcpy(fontid.deffontsettings.szFace, "Verdana"); - strcpy(fontid.backgroundGroup, WEATHERPROTONAME); - strcpy(fontid.backgroundName, "Frame Background"); - - CallService(MS_FONT_REGISTER, (WPARAM)&fontid, 0); - - fontid.deffontsettings.style = DBFONTF_BOLD; - strcpy(fontid.name, "Frame Title Font"); - strcpy(fontid.prefix, "fnt1"); - - CallService(MS_FONT_REGISTER, (WPARAM)&fontid, 0); - } - - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while(hContact) - { - // see if the contact is a weather contact - if(IsMyContact(hContact)) - { - if (DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0)) - addWindow(hContact); - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame); -} - -void DestroyMwin(void) -{ - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while(hContact) - { - // see if the contact is a weather contact - if(IsMyContact(hContact)) - { - DWORD frameId = DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); - if (frameId) - CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0); - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - UnregisterClass("WeatherFrame", hInst); - UnhookEvent(hFontHook); -} diff --git a/protocols/weather/weather_mwin.cpp b/protocols/weather/weather_mwin.cpp new file mode 100644 index 0000000000..8f40fde594 --- /dev/null +++ b/protocols/weather/weather_mwin.cpp @@ -0,0 +1,449 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2006-2009 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2006 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "weather.h" +#include "m_acc.h" + +/* DRAWGLYPH Request structure */ +typedef struct s_SKINDRAWREQUEST +{ + char szObjectID[255]; // Unic Object ID (path) to paint + RECT rcDestRect; // Rectangle to fit + RECT rcClipRect; // Rectangle to paint in. + HDC hDC; // Handler to device context to paint in. +} SKINDRAWREQUEST,*LPSKINDRAWREQUEST; + + +// Request painting glyph object +// wParam = pointer to SKINDRAWREQUEST structure +// lParam = 0 +#define MS_SKIN_DRAWGLYPH "ModernList/DrawGlyph" + + +#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip" +#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip" + +typedef BOOL (WINAPI *ft_TrackMouseEvent) (LPTRACKMOUSEEVENT lpEventTrack); + +static ft_TrackMouseEvent f_TrackMouseEvent = NULL; +static HANDLE hMwinWindowList; +static HANDLE hFontHook; + +HANDLE hMwinMenu; + +typedef struct +{ + HANDLE hContact; + HWND hAvt; + BOOL haveAvatar; +} MWinDataType; + +#define WM_REDRAWWIN (WM_USER + 17369) + +static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + MWinDataType *data = (MWinDataType*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch(msg) + { + case WM_CREATE: + data = (MWinDataType*)mir_calloc(sizeof(MWinDataType)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); + + data->hContact = (HANDLE)((LPCREATESTRUCT)lParam)->lpCreateParams; + data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD, + 0, 0, opt.AvatarSize, opt.AvatarSize, hwnd, NULL, hInst, 0); + if (data->hAvt) SendMessage(data->hAvt, AVATAR_SETCONTACT, 0, (LPARAM)data->hContact); + break; + + case WM_DESTROY: + mir_free(data); + break; + + case WM_CONTEXTMENU: + { + POINT pt; + HMENU hMenu; + + hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)data->hContact, 0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL); + DestroyMenu(hMenu); + } + break; + + case WM_MOUSEMOVE: + if (f_TrackMouseEvent) + { + TRACKMOUSEEVENT tme = {0}; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.hwndTrack = hwnd; + tme.dwFlags = TME_QUERY; + f_TrackMouseEvent(&tme); + + if (tme.dwFlags == 0) + { + tme.dwFlags = TME_HOVER | TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0); + f_TrackMouseEvent(&tme); + } + } + break; + + case WM_MOUSEHOVER: + { + POINT pt; + CLCINFOTIP ti = {0}; + + GetCursorPos(&pt); + GetWindowRect(hwnd, &ti.rcItem); + + ti.cbSize = sizeof(ti); + ti.hItem = data->hContact; + ti.ptCursor = pt; + ti.isTreeFocused = 1; + CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti); + } + break; + + case WM_LBUTTONDBLCLK: + BriefInfo((WPARAM)data->hContact, 0); + break; + + case WM_COMMAND: //Needed by the contact's context menu + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)data->hContact)) + break; + return FALSE; + + case WM_MEASUREITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + case WM_DRAWITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == NM_AVATAR_CHANGED) + { + BOOL newava = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)data->hContact, 0) != 0; + if (newava != data->haveAvatar) + { + LONG_PTR style = GetWindowLongPtr(data->hAvt, GWL_STYLE); + data->haveAvatar = newava; + SetWindowLongPtr(data->hAvt, GWL_STYLE, newava ? (style | WS_VISIBLE) : (style & ~WS_VISIBLE)); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + } + } + break; + + case WM_REDRAWWIN: + if (data->hAvt != NULL) MoveWindow(data->hAvt, 0, 0, opt.AvatarSize, opt.AvatarSize, TRUE); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + + case WM_PAINT: + { + RECT r, rc; + + if(GetUpdateRect(hwnd, &r, FALSE)) + { + DBVARIANT dbv = {0}; + PAINTSTRUCT ps; + HDC hdc; + LOGFONT lfnt, lfnt1; + COLORREF fntc, fntc1; + COLORREF clr; + int picSize = opt.AvatarSize; + HICON hIcon = NULL; + + if (!data->haveAvatar) + { + int statusIcon = DBGetContactSettingWord(data->hContact, WEATHERPROTONAME, "Status", 0); + + picSize = GetSystemMetrics(SM_CXICON); + hIcon = LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon); + if ((INT_PTR)hIcon == CALLSERVICE_NOTFOUND) + { + picSize = GetSystemMetrics(SM_CXSMICON); + hIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon); + } + } + + clr = DBGetContactSettingDword(NULL, WEATHERPROTONAME, "ColorMwinFrame", GetSysColor(COLOR_3DFACE)); + + { + FontID fntid = {0}; + strcpy(fntid.group, WEATHERPROTONAME); + strcpy(fntid.name, "Frame Font"); + fntc = CallService(MS_FONT_GET, (WPARAM)&fntid, (LPARAM)&lfnt); + + strcpy(fntid.name, "Frame Title Font"); + fntc1 = CallService(MS_FONT_GET, (WPARAM)&fntid, (LPARAM)&lfnt1); + } + + DBGetContactSettingString(data->hContact, WEATHERCONDITION, "WeatherInfo", &dbv); + + GetClientRect(hwnd, &rc); + + hdc = BeginPaint(hwnd, &ps); + + if (ServiceExists(MS_SKIN_DRAWGLYPH)) + { + SKINDRAWREQUEST rq; + memset(&rq, 0, sizeof(rq)); + rq.hDC = hdc; + rq.rcDestRect = rc; + rq.rcClipRect = rc; + + strcpy(rq.szObjectID, "Main,ID=WeatherFrame"); + CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0); + } + + if (clr != 0xFFFFFFFF) + { + HBRUSH hBkgBrush = CreateSolidBrush(clr); + FillRect(hdc, &rc, hBkgBrush); + DeleteObject(hBkgBrush); + } + + if (!data->haveAvatar) + DrawIconEx(hdc, 1, 1, hIcon, 0, 0, 0, NULL, DI_NORMAL); + + SetBkMode(hdc, TRANSPARENT); + + { + HFONT hfnt = CreateFontIndirect(&lfnt1); + HFONT hfntold = ( HFONT )SelectObject(hdc, hfnt); + SIZE fontSize; + + char *nick = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)data->hContact, 0); + + GetTextExtentPoint32(hdc, _T("|"), 1, &fontSize); + + rc.top += 1; + rc.left += picSize + fontSize.cx; + + SetTextColor(hdc, fntc1); + DrawText(hdc, nick, -1, &rc, DT_LEFT | DT_EXPANDTABS); + + rc.top += fontSize.cy; + + SelectObject(hdc, hfntold); + DeleteObject(hfnt); + } + + if (dbv.pszVal) + { + HFONT hfnt = CreateFontIndirect(&lfnt); + HFONT hfntold = ( HFONT )SelectObject(hdc, hfnt); + + SetTextColor(hdc, fntc); + DrawText(hdc, dbv.pszVal, -1, &rc, DT_LEFT | DT_EXPANDTABS); + + SelectObject(hdc, hfntold); + DeleteObject(hfnt); + } + EndPaint(hwnd, &ps); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + DBFreeVariant(&dbv); + } + break; + } + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return(TRUE); +} + +static void addWindow(HANDLE hContact) +{ + CLISTFrame Frame = {0}; + HWND hWnd; + DBVARIANT dbv; + char winname[512]; + DWORD frameID; + + DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv); + mir_snprintf(winname, sizeof(winname), "Weather: %s", dbv.pszVal); + DBFreeVariant(&dbv); + + hWnd = CreateWindow("WeatherFrame", "", WS_CHILD | WS_VISIBLE, + 0, 0, 10, 10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, hContact); + + Frame.name = winname; + Frame.cbSize = sizeof(Frame); + Frame.hWnd = hWnd; + Frame.align = alBottom; + Frame.Flags = F_VISIBLE|F_NOBORDER; + Frame.height = 32; + + WindowList_Add(hMwinWindowList, hWnd, hContact); + + frameID = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0); + DBWriteContactSettingDword(hContact, WEATHERPROTONAME, "mwin", frameID); + DBWriteContactSettingByte(hContact, "CList", "Hidden", TRUE); +} + +void removeWindow(HANDLE hContact) +{ + DWORD frameId = DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); + + WindowList_Remove(hMwinWindowList, WindowList_Find(hMwinWindowList, hContact)); + CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0); + + DBWriteContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); + DBDeleteContactSetting(hContact, "CList", "Hidden"); +} + +void UpdateMwinData(HANDLE hContact) +{ + HWND hwnd = WindowList_Find(hMwinWindowList, hContact); + if (hwnd != NULL) + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + + +INT_PTR Mwin_MenuClicked(WPARAM wParam,LPARAM lParam) +{ + BOOL addwnd = WindowList_Find(hMwinWindowList, (HANDLE)wParam) == NULL; + if (addwnd) + addWindow((HANDLE)wParam); + else + removeWindow((HANDLE)wParam); + return 0; +} + + +int BuildContactMenu(WPARAM wparam,LPARAM lparam) +{ + CLISTMENUITEM mi = {0}; + + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | + (DBGetContactSettingDword((HANDLE)wparam, WEATHERPROTONAME, "mwin", 0) ? CMIF_CHECKED : 0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMwinMenu, (LPARAM)&mi); + return 0; +} + + +int RedrawFrame(WPARAM wParam, LPARAM lParam) +{ + WindowList_Broadcast(hMwinWindowList, WM_REDRAWWIN, 0, 0); + return 0; +} + + +void InitMwin(void) +{ + HANDLE hContact; + HMODULE hUser = GetModuleHandle("user32.dll"); + + if (!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) return; + + f_TrackMouseEvent = (ft_TrackMouseEvent)GetProcAddress(hUser, "TrackMouseEvent"); + + + hMwinWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0); + + { + WNDCLASS wndclass; + wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = wndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = "WeatherFrame"; + RegisterClass(&wndclass); + } + + { + FontID fontid = {0}; + ColourID colourid = {0}; + HDC hdc; + + colourid.cbSize = sizeof(ColourID); + strcpy(colourid.dbSettingsGroup, WEATHERPROTONAME); + strcpy(colourid.setting, "ColorMwinFrame"); + strcpy(colourid.name, "Frame Background"); + strcpy(colourid.group, WEATHERPROTONAME); + colourid.defcolour = GetSysColor(COLOR_3DFACE); + + CallService(MS_COLOUR_REGISTER, (WPARAM)&colourid, 0); + + fontid.cbSize = sizeof(FontID); + fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID; + strcpy(fontid.dbSettingsGroup, WEATHERPROTONAME); + strcpy(fontid.group, WEATHERPROTONAME); + strcpy(fontid.name, "Frame Font"); + strcpy(fontid.prefix, "fnt0"); + + hdc = GetDC(NULL); + fontid.deffontsettings.size = -13; + ReleaseDC(0, hdc); + + fontid.deffontsettings.charset = DEFAULT_CHARSET; + strcpy(fontid.deffontsettings.szFace, "Verdana"); + strcpy(fontid.backgroundGroup, WEATHERPROTONAME); + strcpy(fontid.backgroundName, "Frame Background"); + + CallService(MS_FONT_REGISTER, (WPARAM)&fontid, 0); + + fontid.deffontsettings.style = DBFONTF_BOLD; + strcpy(fontid.name, "Frame Title Font"); + strcpy(fontid.prefix, "fnt1"); + + CallService(MS_FONT_REGISTER, (WPARAM)&fontid, 0); + } + + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + // see if the contact is a weather contact + if(IsMyContact(hContact)) + { + if (DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0)) + addWindow(hContact); + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame); +} + +void DestroyMwin(void) +{ + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + // see if the contact is a weather contact + if(IsMyContact(hContact)) + { + DWORD frameId = DBGetContactSettingDword(hContact, WEATHERPROTONAME, "mwin", 0); + if (frameId) + CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0); + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + UnregisterClass("WeatherFrame", hInst); + UnhookEvent(hFontHook); +} diff --git a/protocols/weather/weather_opt.c b/protocols/weather/weather_opt.c deleted file mode 100644 index 59419edf1b..0000000000 --- a/protocols/weather/weather_opt.c +++ /dev/null @@ -1,660 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* This file contain the source related to weather option pages. It also -contain code for saving/loading options from the database. -*/ - -#include "weather.h" - -static BOOL opt_startup; -int RedrawFrame(WPARAM wParam, LPARAM lParam); - -//============ LOADING AND SAVING OPTIONS =========== - -// set a string to default -// in = string to determine which field to set default "CBNEHXPp" -void SetTextDefault(const char* in) -{ - char str[MAX_TEXT_SIZE]; - - if (strchr(in, 'C') != NULL) - { - strcpy(str, C_DEFAULT); - wSetData(&opt.cText, Translate(str)); - } - if (strchr(in, 'b') != NULL) - { - strcpy(str, b_DEFAULT); - wSetData(&opt.bTitle, Translate(str)); - } - if (strchr(in, 'B') != NULL) - { - strcpy(str, B_DEFAULT); - wSetData(&opt.bText, Translate(str)); - } - if (strchr(in, 'N') != NULL) - { - strcpy(str, N_DEFAULT); - wSetData(&opt.nText, Translate(str)); - } - if (strchr(in, 'E') != NULL) - { - strcpy(str, E_DEFAULT); - wSetData(&opt.eText, Translate(str)); - } - if (strchr(in, 'H') != NULL) - { - strcpy(str, H_DEFAULT); - wSetData(&opt.hText, Translate(str)); - } - if (strchr(in, 'X') != NULL) - { - strcpy(str, X_DEFAULT); - wSetData(&opt.xText, Translate(str)); - } - if (strchr(in, 'P') != NULL) - { - strcpy(str, P_DEFAULT); - wSetData(&opt.pTitle, Translate(str)); - } - if (strchr(in, 'p') != NULL) - { - strcpy(str, p_DEFAULT); - wSetData(&opt.pText, Translate(str)); - } - if (strchr(in, 'S') != NULL) - { - strcpy(str, s_DEFAULT); - wSetData(&opt.sText, Translate(str)); - } -} - -void DestroyOptions(void) -{ - wfree(&opt.cText); - wfree(&opt.bTitle); - wfree(&opt.bText); - wfree(&opt.nText); - wfree(&opt.eText); - wfree(&opt.hText); - wfree(&opt.xText); - wfree(&opt.pTitle); - wfree(&opt.pText); - wfree(&opt.sText); -} - -// load options from database + set default if the setting does not exist -void LoadOptions(void) -{ - DBVARIANT dbv; - ZeroMemory(&opt, sizeof(opt)); - - // main options - opt.StartupUpdate = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"StartupUpdate",TRUE); - opt.AutoUpdate = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AutoUpdate",TRUE); - opt.UpdateTime = (WORD)DBGetContactSettingWord(NULL,WEATHERPROTONAME,"UpdateTime",30); - opt.NewBrowserWin = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"NewWindow",TRUE); - opt.NoProtoCondition = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"NoStatus",0); - opt.UpdateOnlyConditionChanged = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"CondChangeAsUpdate",TRUE); - opt.RemoveOldData = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"RemoveOld",FALSE); - opt.MakeItalic = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"MakeItalic",TRUE); - opt.AvatarSize = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AvatarSize", 128); - // units - opt.tUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "tUnit", 1); - opt.wUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "wUnit", 2); - opt.vUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "vUnit", 1); - opt.pUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "pUnit", 4); - opt.dUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "dUnit", 1); - opt.eUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "eUnit", 2); - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"DegreeSign",&dbv)) - strcpy(opt.DegreeSign, ""); - else - { - strcpy(opt.DegreeSign, dbv.pszVal); - DBFreeVariant(&dbv); - } - opt.DoNotAppendUnit = DBGetContactSettingByte(NULL, WEATHERPROTONAME, "DoNotAppendUnit", 0); - opt.NoFrac = DBGetContactSettingByte(NULL, WEATHERPROTONAME, "NoFractions", 0); - // texts - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"DisplayText",&dbv)) - SetTextDefault("C"); - else - { - wSetData(&opt.cText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"BriefTextTitle",&dbv)) - SetTextDefault("b"); - else - { - wSetData(&opt.bTitle, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"BriefText",&dbv)) - SetTextDefault("B"); - else - { - wSetData(&opt.bText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"NoteText",&dbv)) - SetTextDefault("N"); - else - { - wSetData(&opt.nText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"ExtText",&dbv)) - SetTextDefault("E"); - else - { - wSetData(&opt.eText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"HistoryText",&dbv)) - SetTextDefault("H"); - else - { - wSetData(&opt.hText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"ExtraText",&dbv)) - SetTextDefault("X"); - else - { - wSetData(&opt.xText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"StatusText",&dbv)) - SetTextDefault("S"); - else - { - wSetData(&opt.sText, Translate(dbv.pszVal)); - DBFreeVariant(&dbv); - } - - // advanced - opt.DisCondIcon = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"DisableConditionIcon",FALSE); - // popup options - opt.UsePopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"UsePopUp",TRUE); - opt.UpdatePopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"UpdatePopup",TRUE); - opt.AlertPopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AlertPopup",TRUE); - opt.PopupOnChange = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"PopUpOnChange",TRUE); - opt.ShowWarnings = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"ShowWarnings",TRUE); - // popup colors - opt.BGColour = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"BackgroundColour",GetSysColor(COLOR_BTNFACE)); - opt.TextColour = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"TextColour",GetSysColor(COLOR_WINDOWTEXT)); - opt.UseWinColors = (BOOL)DBGetContactSettingByte(NULL,WEATHERPROTONAME, "UseWinColors", FALSE); - // popup actions - opt.LeftClickAction = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"LeftClickAction",IDM_M2); - opt.RightClickAction = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"RightClickAction",IDM_M1); - // popup delay - opt.pDelay = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"PopupDelay",0); - // popup texts - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"PopupTitle",&dbv)) - SetTextDefault("P"); - else - { - wSetData(&opt.pTitle, dbv.pszVal); - DBFreeVariant(&dbv); - } - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"PopupText",&dbv)) - SetTextDefault("p"); - else - { - wSetData(&opt.pText, dbv.pszVal); - DBFreeVariant(&dbv); - } - // misc - if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"Default",&dbv)) - opt.Default[0] = 0; - else - { - strcpy(opt.Default, dbv.pszVal); - DBFreeVariant(&dbv); - } -} - -// save the options to database -void SaveOptions(void) -{ - // main options - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "StartupUpdate", (BYTE)opt.StartupUpdate); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "UpdateTime", opt.UpdateTime); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NewWindow", (BYTE)opt.NewBrowserWin); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NoStatus", (BYTE)opt.NoProtoCondition); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "CondChangeAsUpdate", (BYTE)opt.UpdateOnlyConditionChanged); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "RemoveOld", (BYTE)opt.RemoveOldData); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "MakeItalic", (BYTE)opt.MakeItalic); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AvatarSize", (BYTE)opt.AvatarSize); - // units - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "tUnit", opt.tUnit); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "wUnit", opt.wUnit); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "vUnit", opt.vUnit); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "pUnit", opt.pUnit); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "dUnit", opt.dUnit); - DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "eUnit", opt.eUnit); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "DegreeSign", opt.DegreeSign); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "DoNotAppendUnit", (BYTE)opt.DoNotAppendUnit); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NoFractions", (BYTE)opt.NoFrac); - // texts - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "DisplayText", opt.cText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "BriefTextTitle", opt.bTitle); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "BriefText", opt.bText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "NoteText", opt.nText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "ExtText", opt.eText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "HistoryText", opt.hText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "ExtraText", opt.xText); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "StatusText", opt.sText); - // advanced - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "DisableConditionIcon", (BYTE)opt.DisCondIcon); - // popup options - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UpdatePopup", (BYTE)opt.UpdatePopup); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AlertPopup", (BYTE)opt.AlertPopup); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "PopUpOnChange", (BYTE)opt.PopupOnChange); - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "ShowWarnings", (BYTE)opt.ShowWarnings); - // popup colors - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "BackgroundColour", opt.BGColour); - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "TextColour", opt.TextColour); - DBWriteContactSettingByte(NULL,WEATHERPROTONAME, "UseWinColors", (BYTE)opt.UseWinColors); - // popup actions - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "LeftClickAction", opt.LeftClickAction); - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "RightClickAction", opt.RightClickAction); - // popup delay - DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "PopupDelay", opt.pDelay); - // popup texts - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "PopupTitle", opt.pTitle); - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "PopupText", opt.pText); - // misc stuff - DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); -} - -//============ OPTION INITIALIZATION ============ - -// register the weather option pages -int OptInit(WPARAM wParam,LPARAM lParam) { - OPTIONSDIALOGPAGE odp = {0}; - - odp.cbSize = sizeof(odp); - odp.hInstance = hInst; - - // plugin options - odp.position = 95600; - odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS); - odp.pfnDlgProc = OptionsProc; - odp.pszGroup = LPGEN("Network"); - odp.pszTitle = WEATHERPROTOTEXT; - odp.pszTab = LPGEN("General"); - odp.flags = ODPF_BOLDGROUPS; - CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); - - // text options - odp.pszTemplate = MAKEINTRESOURCE(IDD_TEXTOPT); - odp.pfnDlgProc = DlgProcText; - odp.pszTab = LPGEN("Display"); - CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); - - // if popup service exists, load the weather popup options - if ((ServiceExists(MS_POPUP_ADDPOPUP))) - { - odp.position = 100000000; - odp.pszTemplate = MAKEINTRESOURCE(IDD_POPUP); - odp.pszGroup = LPGEN("PopUps"); - odp.groupPosition = 910000000; - odp.pszTab = NULL; - odp.pfnDlgProc = DlgPopUpOpts; - CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); - } - - return 0; -} - -//============ MAIN OPTIONS ============ - -// weather options -INT_PTR CALLBACK OptionsProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) -{ - char str[512]; - - switch(msg) - { - case WM_INITDIALOG: - opt_startup = TRUE; - TranslateDialogDefault(hdlg); - // load settings - _ltoa(opt.UpdateTime, str, 10); - SetDlgItemTextWth(hdlg, IDC_UPDATETIME, str); - SetDlgItemTextWth(hdlg, IDC_DEGREE, opt.DegreeSign); - - SendDlgItemMessage(hdlg, IDC_AVATARSPIN, UDM_SETRANGE32, 0, 999); - SendDlgItemMessage(hdlg, IDC_AVATARSPIN, UDM_SETPOS, 0, opt.AvatarSize); - SendDlgItemMessage(hdlg, IDC_AVATARSIZE, EM_LIMITTEXT, 3, 0); - - CheckDlgButton(hdlg, IDC_STARTUPUPD, opt.StartupUpdate); - CheckDlgButton(hdlg, IDC_UPDATE, opt.AutoUpdate); - CheckDlgButton(hdlg, IDC_PROTOCOND, !opt.NoProtoCondition); - CheckDlgButton(hdlg, IDC_UPDCONDCHG, opt.UpdateOnlyConditionChanged); - CheckDlgButton(hdlg, IDC_NEWWIN, opt.NewBrowserWin); - CheckDlgButton(hdlg, IDC_REMOVEOLD, opt.RemoveOldData); - CheckDlgButton(hdlg, IDC_MAKEI, opt.MakeItalic); - CheckDlgButton(hdlg, IDC_DISCONDICON, opt.DisCondIcon); - CheckDlgButton(hdlg, IDC_DONOTAPPUNITS, opt.DoNotAppendUnit); - CheckDlgButton(hdlg, IDC_NOFRAC, opt.NoFrac); - - // load units - switch (opt.tUnit) { // temperature - case 1: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T1); break; - case 2: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T2); break; - } - switch (opt.wUnit) { // wind - case 1: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W1); break; - case 2: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W2); break; - case 3: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W3); break; - case 4: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W4); break; - } - switch (opt.vUnit) { // visibility - case 1: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V1); break; - case 2: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V2); break; - } - switch (opt.pUnit) { // pressure - case 1: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P1); break; - case 2: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P2); break; - case 3: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P3); break; - case 4: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P4); break; - } - switch (opt.dUnit) { // pressure - case 1: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D1); break; - case 2: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D2); break; - case 3: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D3); break; - } - - switch (opt.eUnit) { // elev - case 1: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E1); break; - case 2: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E2); break; - } - - opt_startup = FALSE; - return 0; - - case WM_COMMAND: - if (HIWORD(wparam)==BN_CLICKED && GetFocus()==(HWND)lparam) - if (!opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); - if (!((LOWORD(wparam) == IDC_UPDATE || LOWORD(wparam) == IDC_DEGREE) && - (HIWORD(wparam) != EN_CHANGE || (HWND)lparam != GetFocus()))) - if (!opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); - return 0; - - case WM_NOTIFY: - switch(((LPNMHDR)lparam)->code) - { - case PSN_APPLY: - // change the status for weather protocol - if (IsDlgButtonChecked(hdlg, IDC_PROTOCOND) && opt.DefStn != NULL) - { - old_status = status; - status = DBGetContactSettingWord(opt.DefStn, WEATHERPROTONAME, "StatusIcon", NOSTATUSDATA); - ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); - } - - // get update time and remove the old timer - GetDlgItemText(hdlg, IDC_UPDATETIME, str, sizeof(str)); - opt.UpdateTime = (WORD)atoi(str); - if (opt.UpdateTime < 1) opt.UpdateTime = 1; - KillTimer(NULL, timerId); - timerId = SetTimer(NULL, 0, opt.UpdateTime*60000, (TIMERPROC)timerProc); - - // other general options - GetDlgItemText(hdlg, IDC_DEGREE, opt.DegreeSign, sizeof(opt.DegreeSign)); - opt.StartupUpdate = IsDlgButtonChecked(hdlg, IDC_STARTUPUPD); - opt.AutoUpdate = IsDlgButtonChecked(hdlg, IDC_UPDATE); - opt.NewBrowserWin = IsDlgButtonChecked(hdlg, IDC_NEWWIN); - opt.NoProtoCondition = !IsDlgButtonChecked(hdlg, IDC_PROTOCOND); - opt.DisCondIcon = IsDlgButtonChecked(hdlg, IDC_DISCONDICON); - opt.UpdateOnlyConditionChanged = (BYTE)IsDlgButtonChecked(hdlg, IDC_UPDCONDCHG); - opt.RemoveOldData = IsDlgButtonChecked(hdlg, IDC_REMOVEOLD); - opt.MakeItalic = IsDlgButtonChecked(hdlg, IDC_MAKEI); - opt.AvatarSize = GetDlgItemInt(hdlg, IDC_AVATARSIZE, NULL, FALSE);; - opt.DoNotAppendUnit = IsDlgButtonChecked(hdlg, IDC_DONOTAPPUNITS); - opt.NoFrac = IsDlgButtonChecked(hdlg, IDC_NOFRAC); - UpdateMenu(opt.AutoUpdate); - - // save the units - if (IsDlgButtonChecked(hdlg, IDC_T1)) opt.tUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_T2)) opt.tUnit = 2; - if (IsDlgButtonChecked(hdlg, IDC_W1)) opt.wUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_W2)) opt.wUnit = 2; - if (IsDlgButtonChecked(hdlg, IDC_W3)) opt.wUnit = 3; - if (IsDlgButtonChecked(hdlg, IDC_W4)) opt.wUnit = 4; - if (IsDlgButtonChecked(hdlg, IDC_V1)) opt.vUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_V2)) opt.vUnit = 2; - if (IsDlgButtonChecked(hdlg, IDC_P1)) opt.pUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_P2)) opt.pUnit = 2; - if (IsDlgButtonChecked(hdlg, IDC_P3)) opt.pUnit = 3; - if (IsDlgButtonChecked(hdlg, IDC_P4)) opt.pUnit = 4; - if (IsDlgButtonChecked(hdlg, IDC_D1)) opt.dUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_D2)) opt.dUnit = 2; - if (IsDlgButtonChecked(hdlg, IDC_D3)) opt.dUnit = 3; - if (IsDlgButtonChecked(hdlg, IDC_E1)) opt.eUnit = 1; - if (IsDlgButtonChecked(hdlg, IDC_E2)) opt.eUnit = 2; - - // save the new weather options - SaveOptions(); - - RedrawFrame(0, 0); - - return 1; - } - break; - } - return 0; -} - -//============ TEXT OPTION DIALOG ============ - -void LoadTextSettings(HWND hdlg) -{ - // load text option settings from memory - SetDlgItemTextWth(hdlg, IDC_CTEXT, opt.cText); - SetDlgItemTextWth(hdlg, IDC_BTITLE, opt.bTitle); - SetDlgItemTextWth(hdlg, IDC_BTEXT, opt.bText); - SetDlgItemTextWth(hdlg, IDC_ETEXT, opt.eText); - SetDlgItemTextWth(hdlg, IDC_NTEXT, opt.nText); - SetDlgItemTextWth(hdlg, IDC_HTEXT, opt.hText); - SetDlgItemTextWth(hdlg, IDC_XTEXT, opt.xText); - SetDlgItemTextWth(hdlg, IDC_BTITLE2, opt.sText); -} - -// free the display text settings from memory -void FreeTextVar(void) -{ - wfree(&opt.cText); - wfree(&opt.bText); - wfree(&opt.bTitle); - wfree(&opt.eText); - wfree(&opt.nText); - wfree(&opt.hText); - wfree(&opt.xText); - wfree(&opt.sText); -} - -// text option dialog -INT_PTR CALLBACK DlgProcText(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - RECT rc, pos; - HWND button; - HMENU hMenu, hMenu1; - char str[4096]; - switch (msg) - { - case WM_INITDIALOG: - opt_startup = TRUE; - // set windows position, make it top-most - GetWindowRect(hdlg, &rc); - SetWindowPos(hdlg, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); - TranslateDialogDefault(hdlg); - // generate the display text for variable list - strcpy(str, Translate("%c\tcurrent condition\n%d\tcurrent date\n%e\tdewpoint\n%f\tfeel-like temp\n%h\ttoday's high\n%i\twind direction\n%l\ttoday's low\n%m\thumidity\n%n\tstation name\n%p\tpressure\n%r\tsunrise time\n%s\tstation ID\n%t\ttemperature\n%u\tupdate time\n%v\tvisibility\n%w\twind speed\n%y\tsun set")); - SetDlgItemTextWth(hdlg, IDC_VARLIST, str); - - // make the more variable and other buttons flat - SendMessage(GetDlgItem(hdlg,IDC_MORE), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM1), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM2), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM3), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM4), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM5), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM6), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM7), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_TM8), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_RESET), BUTTONSETASFLATBTN, 0, 0); - // load the settings - LoadTextSettings(hdlg); - opt_startup = FALSE; - return TRUE; - - case WM_COMMAND: - if (opt_startup) return TRUE; - switch(LOWORD(wParam)) { - case IDC_CTEXT: - case IDC_BTITLE: - case IDC_BTEXT: - case IDC_NTEXT: - case IDC_XTEXT: - case IDC_ETEXT: - case IDC_HTEXT: - case IDC_BTITLE2: - if (HIWORD(wParam) == EN_CHANGE) - SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); - break; - - case IDC_MORE: - // display custom variables list - MoreVarList(); - break; - - case IDC_TM1: - case IDC_TM2: - case IDC_TM3: - case IDC_TM4: - case IDC_TM5: - case IDC_TM6: - case IDC_TM7: - case IDC_TM8: - { - static const char *varname[8] = {"C", "b", "B", "N", "X", "E", "H", "S"}; - static const int cname[8] = {IDC_CTEXT, IDC_BTITLE, IDC_BTEXT, IDC_NTEXT, IDC_XTEXT, - IDC_ETEXT, IDC_HTEXT, IDC_BTITLE2 }; - static char* const *var[8] = {&opt.cText, &opt.bTitle, &opt.bText, &opt.nText, - &opt.xText, &opt.eText, &opt.hText, &opt.sText }; - WEATHERINFO winfo; - - // display the menu - button = GetDlgItem(hdlg, LOWORD(wParam)); - GetWindowRect(button, &pos); - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); - switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL)) - { - case ID_MPREVIEW: - // show the preview in a message box, using the weather data from the default station - winfo = LoadWeatherInfo(opt.DefStn); - GetDisplay(&winfo, *var[LOWORD(wParam)-IDC_TM1], str); - MessageBox(NULL, str, Translate("Weather Protocol Text Preview"), MB_OK|MB_TOPMOST); - break; - - case ID_MRESET: - { - unsigned varo = LOWORD(wParam) - IDC_TM1; - // remove the old setting from db and free memory - char* vartmp = *var[varo]; - wfree(&vartmp); - SetTextDefault(varname[varo]); - SetDlgItemTextWth(hdlg, cname[varo], *var[varo]); - } - break; - } - DestroyMenu(hMenu); - break; - } - - case IDC_RESET: - // left click action selection menu - button = GetDlgItem(hdlg, IDC_RESET); - GetWindowRect(button, &pos); - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); - switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL)) - { - case ID_T1: - // reset to the strings in memory, discard all changes - LoadTextSettings(hdlg); - break; - - case ID_T2: - // reset to the default setting - FreeTextVar(); - SetTextDefault("CbBENHX"); - LoadTextSettings(hdlg); - break; - } - DestroyMenu(hMenu); - break; - } - return TRUE; - case WM_NOTIFY: - switch(((LPNMHDR)lParam)->code) - { - case PSN_APPLY: - { - // save the option - char textstr[MAX_TEXT_SIZE]; - // free memory for old settings - FreeTextVar(); - // save new settings to memory - GetDlgItemTextWth(hdlg, IDC_CTEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.cText, textstr); - GetDlgItemTextWth(hdlg, IDC_BTEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.bText, textstr); - GetDlgItemTextWth(hdlg, IDC_BTITLE, textstr, MAX_TEXT_SIZE); - wSetData(&opt.bTitle, textstr); - GetDlgItemTextWth(hdlg, IDC_ETEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.eText, textstr); - GetDlgItemTextWth(hdlg, IDC_NTEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.nText, textstr); - GetDlgItemTextWth(hdlg, IDC_HTEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.hText, textstr); - GetDlgItemTextWth(hdlg, IDC_XTEXT, textstr, MAX_TEXT_SIZE); - wSetData(&opt.xText, textstr); - GetDlgItemTextWth(hdlg, IDC_BTITLE2, textstr, MAX_TEXT_SIZE); - wSetData(&opt.sText, textstr); - SaveOptions(); - UpdateAllInfo(0, 0); - break; - } - } - break; - } - return FALSE; -} - diff --git a/protocols/weather/weather_opt.cpp b/protocols/weather/weather_opt.cpp new file mode 100644 index 0000000000..59419edf1b --- /dev/null +++ b/protocols/weather/weather_opt.cpp @@ -0,0 +1,660 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* This file contain the source related to weather option pages. It also +contain code for saving/loading options from the database. +*/ + +#include "weather.h" + +static BOOL opt_startup; +int RedrawFrame(WPARAM wParam, LPARAM lParam); + +//============ LOADING AND SAVING OPTIONS =========== + +// set a string to default +// in = string to determine which field to set default "CBNEHXPp" +void SetTextDefault(const char* in) +{ + char str[MAX_TEXT_SIZE]; + + if (strchr(in, 'C') != NULL) + { + strcpy(str, C_DEFAULT); + wSetData(&opt.cText, Translate(str)); + } + if (strchr(in, 'b') != NULL) + { + strcpy(str, b_DEFAULT); + wSetData(&opt.bTitle, Translate(str)); + } + if (strchr(in, 'B') != NULL) + { + strcpy(str, B_DEFAULT); + wSetData(&opt.bText, Translate(str)); + } + if (strchr(in, 'N') != NULL) + { + strcpy(str, N_DEFAULT); + wSetData(&opt.nText, Translate(str)); + } + if (strchr(in, 'E') != NULL) + { + strcpy(str, E_DEFAULT); + wSetData(&opt.eText, Translate(str)); + } + if (strchr(in, 'H') != NULL) + { + strcpy(str, H_DEFAULT); + wSetData(&opt.hText, Translate(str)); + } + if (strchr(in, 'X') != NULL) + { + strcpy(str, X_DEFAULT); + wSetData(&opt.xText, Translate(str)); + } + if (strchr(in, 'P') != NULL) + { + strcpy(str, P_DEFAULT); + wSetData(&opt.pTitle, Translate(str)); + } + if (strchr(in, 'p') != NULL) + { + strcpy(str, p_DEFAULT); + wSetData(&opt.pText, Translate(str)); + } + if (strchr(in, 'S') != NULL) + { + strcpy(str, s_DEFAULT); + wSetData(&opt.sText, Translate(str)); + } +} + +void DestroyOptions(void) +{ + wfree(&opt.cText); + wfree(&opt.bTitle); + wfree(&opt.bText); + wfree(&opt.nText); + wfree(&opt.eText); + wfree(&opt.hText); + wfree(&opt.xText); + wfree(&opt.pTitle); + wfree(&opt.pText); + wfree(&opt.sText); +} + +// load options from database + set default if the setting does not exist +void LoadOptions(void) +{ + DBVARIANT dbv; + ZeroMemory(&opt, sizeof(opt)); + + // main options + opt.StartupUpdate = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"StartupUpdate",TRUE); + opt.AutoUpdate = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AutoUpdate",TRUE); + opt.UpdateTime = (WORD)DBGetContactSettingWord(NULL,WEATHERPROTONAME,"UpdateTime",30); + opt.NewBrowserWin = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"NewWindow",TRUE); + opt.NoProtoCondition = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"NoStatus",0); + opt.UpdateOnlyConditionChanged = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"CondChangeAsUpdate",TRUE); + opt.RemoveOldData = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"RemoveOld",FALSE); + opt.MakeItalic = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"MakeItalic",TRUE); + opt.AvatarSize = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AvatarSize", 128); + // units + opt.tUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "tUnit", 1); + opt.wUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "wUnit", 2); + opt.vUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "vUnit", 1); + opt.pUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "pUnit", 4); + opt.dUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "dUnit", 1); + opt.eUnit = (WORD)DBGetContactSettingWord(NULL, WEATHERPROTONAME, "eUnit", 2); + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"DegreeSign",&dbv)) + strcpy(opt.DegreeSign, ""); + else + { + strcpy(opt.DegreeSign, dbv.pszVal); + DBFreeVariant(&dbv); + } + opt.DoNotAppendUnit = DBGetContactSettingByte(NULL, WEATHERPROTONAME, "DoNotAppendUnit", 0); + opt.NoFrac = DBGetContactSettingByte(NULL, WEATHERPROTONAME, "NoFractions", 0); + // texts + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"DisplayText",&dbv)) + SetTextDefault("C"); + else + { + wSetData(&opt.cText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"BriefTextTitle",&dbv)) + SetTextDefault("b"); + else + { + wSetData(&opt.bTitle, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"BriefText",&dbv)) + SetTextDefault("B"); + else + { + wSetData(&opt.bText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"NoteText",&dbv)) + SetTextDefault("N"); + else + { + wSetData(&opt.nText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"ExtText",&dbv)) + SetTextDefault("E"); + else + { + wSetData(&opt.eText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"HistoryText",&dbv)) + SetTextDefault("H"); + else + { + wSetData(&opt.hText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"ExtraText",&dbv)) + SetTextDefault("X"); + else + { + wSetData(&opt.xText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"StatusText",&dbv)) + SetTextDefault("S"); + else + { + wSetData(&opt.sText, Translate(dbv.pszVal)); + DBFreeVariant(&dbv); + } + + // advanced + opt.DisCondIcon = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"DisableConditionIcon",FALSE); + // popup options + opt.UsePopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"UsePopUp",TRUE); + opt.UpdatePopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"UpdatePopup",TRUE); + opt.AlertPopup = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"AlertPopup",TRUE); + opt.PopupOnChange = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"PopUpOnChange",TRUE); + opt.ShowWarnings = DBGetContactSettingByte(NULL,WEATHERPROTONAME,"ShowWarnings",TRUE); + // popup colors + opt.BGColour = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"BackgroundColour",GetSysColor(COLOR_BTNFACE)); + opt.TextColour = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"TextColour",GetSysColor(COLOR_WINDOWTEXT)); + opt.UseWinColors = (BOOL)DBGetContactSettingByte(NULL,WEATHERPROTONAME, "UseWinColors", FALSE); + // popup actions + opt.LeftClickAction = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"LeftClickAction",IDM_M2); + opt.RightClickAction = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"RightClickAction",IDM_M1); + // popup delay + opt.pDelay = DBGetContactSettingDword(NULL,WEATHERPROTONAME,"PopupDelay",0); + // popup texts + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"PopupTitle",&dbv)) + SetTextDefault("P"); + else + { + wSetData(&opt.pTitle, dbv.pszVal); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"PopupText",&dbv)) + SetTextDefault("p"); + else + { + wSetData(&opt.pText, dbv.pszVal); + DBFreeVariant(&dbv); + } + // misc + if (DBGetContactSettingString(NULL,WEATHERPROTONAME,"Default",&dbv)) + opt.Default[0] = 0; + else + { + strcpy(opt.Default, dbv.pszVal); + DBFreeVariant(&dbv); + } +} + +// save the options to database +void SaveOptions(void) +{ + // main options + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "StartupUpdate", (BYTE)opt.StartupUpdate); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "UpdateTime", opt.UpdateTime); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NewWindow", (BYTE)opt.NewBrowserWin); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NoStatus", (BYTE)opt.NoProtoCondition); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "CondChangeAsUpdate", (BYTE)opt.UpdateOnlyConditionChanged); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "RemoveOld", (BYTE)opt.RemoveOldData); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "MakeItalic", (BYTE)opt.MakeItalic); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AvatarSize", (BYTE)opt.AvatarSize); + // units + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "tUnit", opt.tUnit); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "wUnit", opt.wUnit); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "vUnit", opt.vUnit); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "pUnit", opt.pUnit); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "dUnit", opt.dUnit); + DBWriteContactSettingWord(NULL, WEATHERPROTONAME, "eUnit", opt.eUnit); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "DegreeSign", opt.DegreeSign); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "DoNotAppendUnit", (BYTE)opt.DoNotAppendUnit); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "NoFractions", (BYTE)opt.NoFrac); + // texts + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "DisplayText", opt.cText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "BriefTextTitle", opt.bTitle); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "BriefText", opt.bText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "NoteText", opt.nText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "ExtText", opt.eText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "HistoryText", opt.hText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "ExtraText", opt.xText); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "StatusText", opt.sText); + // advanced + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "DisableConditionIcon", (BYTE)opt.DisCondIcon); + // popup options + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UpdatePopup", (BYTE)opt.UpdatePopup); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AlertPopup", (BYTE)opt.AlertPopup); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "PopUpOnChange", (BYTE)opt.PopupOnChange); + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "ShowWarnings", (BYTE)opt.ShowWarnings); + // popup colors + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "BackgroundColour", opt.BGColour); + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "TextColour", opt.TextColour); + DBWriteContactSettingByte(NULL,WEATHERPROTONAME, "UseWinColors", (BYTE)opt.UseWinColors); + // popup actions + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "LeftClickAction", opt.LeftClickAction); + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "RightClickAction", opt.RightClickAction); + // popup delay + DBWriteContactSettingDword(NULL, WEATHERPROTONAME, "PopupDelay", opt.pDelay); + // popup texts + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "PopupTitle", opt.pTitle); + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "PopupText", opt.pText); + // misc stuff + DBWriteContactSettingString(NULL, WEATHERPROTONAME, "Default", opt.Default); +} + +//============ OPTION INITIALIZATION ============ + +// register the weather option pages +int OptInit(WPARAM wParam,LPARAM lParam) { + OPTIONSDIALOGPAGE odp = {0}; + + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + + // plugin options + odp.position = 95600; + odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS); + odp.pfnDlgProc = OptionsProc; + odp.pszGroup = LPGEN("Network"); + odp.pszTitle = WEATHERPROTOTEXT; + odp.pszTab = LPGEN("General"); + odp.flags = ODPF_BOLDGROUPS; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + // text options + odp.pszTemplate = MAKEINTRESOURCE(IDD_TEXTOPT); + odp.pfnDlgProc = DlgProcText; + odp.pszTab = LPGEN("Display"); + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + // if popup service exists, load the weather popup options + if ((ServiceExists(MS_POPUP_ADDPOPUP))) + { + odp.position = 100000000; + odp.pszTemplate = MAKEINTRESOURCE(IDD_POPUP); + odp.pszGroup = LPGEN("PopUps"); + odp.groupPosition = 910000000; + odp.pszTab = NULL; + odp.pfnDlgProc = DlgPopUpOpts; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + } + + return 0; +} + +//============ MAIN OPTIONS ============ + +// weather options +INT_PTR CALLBACK OptionsProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) +{ + char str[512]; + + switch(msg) + { + case WM_INITDIALOG: + opt_startup = TRUE; + TranslateDialogDefault(hdlg); + // load settings + _ltoa(opt.UpdateTime, str, 10); + SetDlgItemTextWth(hdlg, IDC_UPDATETIME, str); + SetDlgItemTextWth(hdlg, IDC_DEGREE, opt.DegreeSign); + + SendDlgItemMessage(hdlg, IDC_AVATARSPIN, UDM_SETRANGE32, 0, 999); + SendDlgItemMessage(hdlg, IDC_AVATARSPIN, UDM_SETPOS, 0, opt.AvatarSize); + SendDlgItemMessage(hdlg, IDC_AVATARSIZE, EM_LIMITTEXT, 3, 0); + + CheckDlgButton(hdlg, IDC_STARTUPUPD, opt.StartupUpdate); + CheckDlgButton(hdlg, IDC_UPDATE, opt.AutoUpdate); + CheckDlgButton(hdlg, IDC_PROTOCOND, !opt.NoProtoCondition); + CheckDlgButton(hdlg, IDC_UPDCONDCHG, opt.UpdateOnlyConditionChanged); + CheckDlgButton(hdlg, IDC_NEWWIN, opt.NewBrowserWin); + CheckDlgButton(hdlg, IDC_REMOVEOLD, opt.RemoveOldData); + CheckDlgButton(hdlg, IDC_MAKEI, opt.MakeItalic); + CheckDlgButton(hdlg, IDC_DISCONDICON, opt.DisCondIcon); + CheckDlgButton(hdlg, IDC_DONOTAPPUNITS, opt.DoNotAppendUnit); + CheckDlgButton(hdlg, IDC_NOFRAC, opt.NoFrac); + + // load units + switch (opt.tUnit) { // temperature + case 1: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T1); break; + case 2: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T2); break; + } + switch (opt.wUnit) { // wind + case 1: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W1); break; + case 2: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W2); break; + case 3: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W3); break; + case 4: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W4); break; + } + switch (opt.vUnit) { // visibility + case 1: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V1); break; + case 2: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V2); break; + } + switch (opt.pUnit) { // pressure + case 1: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P1); break; + case 2: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P2); break; + case 3: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P3); break; + case 4: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P4); break; + } + switch (opt.dUnit) { // pressure + case 1: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D1); break; + case 2: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D2); break; + case 3: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D3); break; + } + + switch (opt.eUnit) { // elev + case 1: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E1); break; + case 2: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E2); break; + } + + opt_startup = FALSE; + return 0; + + case WM_COMMAND: + if (HIWORD(wparam)==BN_CLICKED && GetFocus()==(HWND)lparam) + if (!opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); + if (!((LOWORD(wparam) == IDC_UPDATE || LOWORD(wparam) == IDC_DEGREE) && + (HIWORD(wparam) != EN_CHANGE || (HWND)lparam != GetFocus()))) + if (!opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); + return 0; + + case WM_NOTIFY: + switch(((LPNMHDR)lparam)->code) + { + case PSN_APPLY: + // change the status for weather protocol + if (IsDlgButtonChecked(hdlg, IDC_PROTOCOND) && opt.DefStn != NULL) + { + old_status = status; + status = DBGetContactSettingWord(opt.DefStn, WEATHERPROTONAME, "StatusIcon", NOSTATUSDATA); + ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); + } + + // get update time and remove the old timer + GetDlgItemText(hdlg, IDC_UPDATETIME, str, sizeof(str)); + opt.UpdateTime = (WORD)atoi(str); + if (opt.UpdateTime < 1) opt.UpdateTime = 1; + KillTimer(NULL, timerId); + timerId = SetTimer(NULL, 0, opt.UpdateTime*60000, (TIMERPROC)timerProc); + + // other general options + GetDlgItemText(hdlg, IDC_DEGREE, opt.DegreeSign, sizeof(opt.DegreeSign)); + opt.StartupUpdate = IsDlgButtonChecked(hdlg, IDC_STARTUPUPD); + opt.AutoUpdate = IsDlgButtonChecked(hdlg, IDC_UPDATE); + opt.NewBrowserWin = IsDlgButtonChecked(hdlg, IDC_NEWWIN); + opt.NoProtoCondition = !IsDlgButtonChecked(hdlg, IDC_PROTOCOND); + opt.DisCondIcon = IsDlgButtonChecked(hdlg, IDC_DISCONDICON); + opt.UpdateOnlyConditionChanged = (BYTE)IsDlgButtonChecked(hdlg, IDC_UPDCONDCHG); + opt.RemoveOldData = IsDlgButtonChecked(hdlg, IDC_REMOVEOLD); + opt.MakeItalic = IsDlgButtonChecked(hdlg, IDC_MAKEI); + opt.AvatarSize = GetDlgItemInt(hdlg, IDC_AVATARSIZE, NULL, FALSE);; + opt.DoNotAppendUnit = IsDlgButtonChecked(hdlg, IDC_DONOTAPPUNITS); + opt.NoFrac = IsDlgButtonChecked(hdlg, IDC_NOFRAC); + UpdateMenu(opt.AutoUpdate); + + // save the units + if (IsDlgButtonChecked(hdlg, IDC_T1)) opt.tUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_T2)) opt.tUnit = 2; + if (IsDlgButtonChecked(hdlg, IDC_W1)) opt.wUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_W2)) opt.wUnit = 2; + if (IsDlgButtonChecked(hdlg, IDC_W3)) opt.wUnit = 3; + if (IsDlgButtonChecked(hdlg, IDC_W4)) opt.wUnit = 4; + if (IsDlgButtonChecked(hdlg, IDC_V1)) opt.vUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_V2)) opt.vUnit = 2; + if (IsDlgButtonChecked(hdlg, IDC_P1)) opt.pUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_P2)) opt.pUnit = 2; + if (IsDlgButtonChecked(hdlg, IDC_P3)) opt.pUnit = 3; + if (IsDlgButtonChecked(hdlg, IDC_P4)) opt.pUnit = 4; + if (IsDlgButtonChecked(hdlg, IDC_D1)) opt.dUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_D2)) opt.dUnit = 2; + if (IsDlgButtonChecked(hdlg, IDC_D3)) opt.dUnit = 3; + if (IsDlgButtonChecked(hdlg, IDC_E1)) opt.eUnit = 1; + if (IsDlgButtonChecked(hdlg, IDC_E2)) opt.eUnit = 2; + + // save the new weather options + SaveOptions(); + + RedrawFrame(0, 0); + + return 1; + } + break; + } + return 0; +} + +//============ TEXT OPTION DIALOG ============ + +void LoadTextSettings(HWND hdlg) +{ + // load text option settings from memory + SetDlgItemTextWth(hdlg, IDC_CTEXT, opt.cText); + SetDlgItemTextWth(hdlg, IDC_BTITLE, opt.bTitle); + SetDlgItemTextWth(hdlg, IDC_BTEXT, opt.bText); + SetDlgItemTextWth(hdlg, IDC_ETEXT, opt.eText); + SetDlgItemTextWth(hdlg, IDC_NTEXT, opt.nText); + SetDlgItemTextWth(hdlg, IDC_HTEXT, opt.hText); + SetDlgItemTextWth(hdlg, IDC_XTEXT, opt.xText); + SetDlgItemTextWth(hdlg, IDC_BTITLE2, opt.sText); +} + +// free the display text settings from memory +void FreeTextVar(void) +{ + wfree(&opt.cText); + wfree(&opt.bText); + wfree(&opt.bTitle); + wfree(&opt.eText); + wfree(&opt.nText); + wfree(&opt.hText); + wfree(&opt.xText); + wfree(&opt.sText); +} + +// text option dialog +INT_PTR CALLBACK DlgProcText(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + RECT rc, pos; + HWND button; + HMENU hMenu, hMenu1; + char str[4096]; + switch (msg) + { + case WM_INITDIALOG: + opt_startup = TRUE; + // set windows position, make it top-most + GetWindowRect(hdlg, &rc); + SetWindowPos(hdlg, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); + TranslateDialogDefault(hdlg); + // generate the display text for variable list + strcpy(str, Translate("%c\tcurrent condition\n%d\tcurrent date\n%e\tdewpoint\n%f\tfeel-like temp\n%h\ttoday's high\n%i\twind direction\n%l\ttoday's low\n%m\thumidity\n%n\tstation name\n%p\tpressure\n%r\tsunrise time\n%s\tstation ID\n%t\ttemperature\n%u\tupdate time\n%v\tvisibility\n%w\twind speed\n%y\tsun set")); + SetDlgItemTextWth(hdlg, IDC_VARLIST, str); + + // make the more variable and other buttons flat + SendMessage(GetDlgItem(hdlg,IDC_MORE), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM1), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM2), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM3), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM4), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM5), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM6), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM7), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_TM8), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_RESET), BUTTONSETASFLATBTN, 0, 0); + // load the settings + LoadTextSettings(hdlg); + opt_startup = FALSE; + return TRUE; + + case WM_COMMAND: + if (opt_startup) return TRUE; + switch(LOWORD(wParam)) { + case IDC_CTEXT: + case IDC_BTITLE: + case IDC_BTEXT: + case IDC_NTEXT: + case IDC_XTEXT: + case IDC_ETEXT: + case IDC_HTEXT: + case IDC_BTITLE2: + if (HIWORD(wParam) == EN_CHANGE) + SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); + break; + + case IDC_MORE: + // display custom variables list + MoreVarList(); + break; + + case IDC_TM1: + case IDC_TM2: + case IDC_TM3: + case IDC_TM4: + case IDC_TM5: + case IDC_TM6: + case IDC_TM7: + case IDC_TM8: + { + static const char *varname[8] = {"C", "b", "B", "N", "X", "E", "H", "S"}; + static const int cname[8] = {IDC_CTEXT, IDC_BTITLE, IDC_BTEXT, IDC_NTEXT, IDC_XTEXT, + IDC_ETEXT, IDC_HTEXT, IDC_BTITLE2 }; + static char* const *var[8] = {&opt.cText, &opt.bTitle, &opt.bText, &opt.nText, + &opt.xText, &opt.eText, &opt.hText, &opt.sText }; + WEATHERINFO winfo; + + // display the menu + button = GetDlgItem(hdlg, LOWORD(wParam)); + GetWindowRect(button, &pos); + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); + switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL)) + { + case ID_MPREVIEW: + // show the preview in a message box, using the weather data from the default station + winfo = LoadWeatherInfo(opt.DefStn); + GetDisplay(&winfo, *var[LOWORD(wParam)-IDC_TM1], str); + MessageBox(NULL, str, Translate("Weather Protocol Text Preview"), MB_OK|MB_TOPMOST); + break; + + case ID_MRESET: + { + unsigned varo = LOWORD(wParam) - IDC_TM1; + // remove the old setting from db and free memory + char* vartmp = *var[varo]; + wfree(&vartmp); + SetTextDefault(varname[varo]); + SetDlgItemTextWth(hdlg, cname[varo], *var[varo]); + } + break; + } + DestroyMenu(hMenu); + break; + } + + case IDC_RESET: + // left click action selection menu + button = GetDlgItem(hdlg, IDC_RESET); + GetWindowRect(button, &pos); + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); + switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL)) + { + case ID_T1: + // reset to the strings in memory, discard all changes + LoadTextSettings(hdlg); + break; + + case ID_T2: + // reset to the default setting + FreeTextVar(); + SetTextDefault("CbBENHX"); + LoadTextSettings(hdlg); + break; + } + DestroyMenu(hMenu); + break; + } + return TRUE; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + // save the option + char textstr[MAX_TEXT_SIZE]; + // free memory for old settings + FreeTextVar(); + // save new settings to memory + GetDlgItemTextWth(hdlg, IDC_CTEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.cText, textstr); + GetDlgItemTextWth(hdlg, IDC_BTEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.bText, textstr); + GetDlgItemTextWth(hdlg, IDC_BTITLE, textstr, MAX_TEXT_SIZE); + wSetData(&opt.bTitle, textstr); + GetDlgItemTextWth(hdlg, IDC_ETEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.eText, textstr); + GetDlgItemTextWth(hdlg, IDC_NTEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.nText, textstr); + GetDlgItemTextWth(hdlg, IDC_HTEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.hText, textstr); + GetDlgItemTextWth(hdlg, IDC_XTEXT, textstr, MAX_TEXT_SIZE); + wSetData(&opt.xText, textstr); + GetDlgItemTextWth(hdlg, IDC_BTITLE2, textstr, MAX_TEXT_SIZE); + wSetData(&opt.sText, textstr); + SaveOptions(); + UpdateAllInfo(0, 0); + break; + } + } + break; + } + return FALSE; +} + diff --git a/protocols/weather/weather_popup.c b/protocols/weather/weather_popup.c deleted file mode 100644 index 270f989c73..0000000000 --- a/protocols/weather/weather_popup.c +++ /dev/null @@ -1,454 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2009 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* This file contain the source related to weather popups, including popup - options, popup display, and the code for popup process. -*/ - -#include "weather.h" - -// variables for weather_popup.c -static HANDLE hPopupContact; - -//============ SHOW WEATHER POPUPS ============ - -// display weather popups -// wParam = the contact to display popup -// lParam = whether the weather data is changed or not -int WeatherPopup(WPARAM wParam, LPARAM lParam) -{ - // determine if the popup should display or not - if (opt.UsePopup && opt.UpdatePopup && (!opt.PopupOnChange || (BOOL)lParam) && - !DBGetContactSettingByte((HANDLE)wParam, WEATHERPROTONAME, "DPopUp", 0)) - { - POPUPDATAEX ppd = {0}; - WEATHERINFO winfo; - - // setup the popup - ppd.lchContact = (HANDLE)wParam; -// if ((HANDLE)wParam != NULL) { // for actual contact - winfo = LoadWeatherInfo((HANDLE)wParam); - ppd.PluginData = ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, winfo.status); - GetDisplay(&winfo, opt.pTitle, ppd.lpzContactName); - GetDisplay(&winfo, opt.pText, ppd.lpzText); - ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; -// } -// else { // for preview -// ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, ONLINE); -// strcpy(ppd.lpzContactName, Translate("This is the name of the city")); -// strcpy(ppd.lpzText, Translate("Here is a short weather description")); -// ppd.PluginWindowProc = NULL; -// } - ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour; - ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour; - ppd.iSeconds = opt.pDelay; - // display popups - if (!ServiceExists(MS_POPUP_ADDPOPUPEX)) // old version - CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0); - else { // new version with delay - ppd.iSeconds = opt.pDelay; - CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); - } - } - return 0; -} - -//============ WEATHER ERROR POPUPS ============ - -// display weather error or notices (not threaded) -// wParam = error text -// lParam = display type -// Type can either be SM_WARNING, SM_NOTIFY, or SM_WEATHERALERT -int WeatherError(WPARAM wParam, LPARAM lParam) -{ - if (!opt.UsePopup) return 0; - - if ((DWORD)lParam == SM_WARNING) - PUShowMessage((char*)wParam, SM_WARNING); - else if ((DWORD)lParam == SM_NOTIFY) - PUShowMessage((char*)wParam, SM_NOTIFY); - else if ((DWORD)lParam == SM_WEATHERALERT) - { - POPUPDATAEX ppd = {0}; - char *chop; - char str1[512], str2[512]; - - // get the 2 strings - strcpy(str1, (char*)wParam); - strcpy(str2, (char*)wParam); - chop = strchr(str1, 255); - if (chop != NULL) *chop = '\0'; - else str1[0] = 0; - chop = strchr(str2, 255); - if (chop != NULL) strcpy(str2, chop+1); - else str2[0] = 0; - - // setup the popup - ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_BANG), IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); - strcpy(ppd.lpzContactName, str1); - strcpy(ppd.lpzText, str2); - ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour; - ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour; - ppd.iSeconds = opt.pDelay; - - // display popups - if (!ServiceExists(MS_POPUP_ADDPOPUPEX)) // old version - CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0); - else { // new version with delay - ppd.iSeconds = opt.pDelay; - CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); - } - } - return 0; -} - -// wrapper function for displaying weather warning popup by triggering an event -// (threaded) -// lpzText = error text -// kind = display type (see m_popup.h) -int WPShowMessage(char* lpzText, WORD kind) { - NotifyEventHooks(hHookWeatherError, (WPARAM)lpzText, (LPARAM)kind); - return 0; -} - -//============ WEATHER POPUP PROCESSES ============ - -// popup dialog pocess -// for selecting actions when click on the popup window -// use for displaying contact menu -LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - DWORD ID = 0; - HANDLE hContact; - hContact = PUGetContact(hWnd); - - switch(message) - { - case WM_COMMAND: - ID = opt.LeftClickAction; - if (ID != IDM_M7) PUDeletePopUp(hWnd); - SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0); - return TRUE; - - case WM_CONTEXTMENU: - ID = opt.RightClickAction; - if (ID != IDM_M7) PUDeletePopUp(hWnd); - SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0); - return TRUE; - - case UM_FREEPLUGINDATA: - CallService(MS_SKIN2_RELEASEICON, (WPARAM)PUGetPluginData(hWnd), 0); - return FALSE; - } - - return DefWindowProc(hWnd, message, wParam, lParam); -} - -// process for the popup window -// containing the code for popup actions -LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pt; - HMENU hMenu; - switch (uMsg) - { - case IDM_M2: // brief info - BriefInfo(wParam, 0); - break; - - case IDM_M3: // read complete forecast - LoadForecast(wParam, 0); - break; - - case IDM_M4: // display weather map - WeatherMap(wParam, 0); - break; - - case IDM_M5: // open history window - CallService(MS_HISTORY_SHOWCONTACTHISTORY, wParam, 0); - break; - - case IDM_M6: // open external log - ViewLog(wParam, 0); - break; - - case IDM_M7: // display contact menu - hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,wParam,0); - GetCursorPos(&pt); - hPopupContact = (HANDLE)wParam; - TrackPopupMenu(hMenu,TPM_LEFTALIGN,pt.x,pt.y,0,hWnd,NULL); - DestroyMenu(hMenu); - break; - - case IDM_M8: // display contact detail - CallService(MS_USERINFO_SHOWDIALOG, wParam, 0); - - case WM_COMMAND: //Needed by the contact's context menu - if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),(LPARAM)hPopupContact)) - break; - return FALSE; - - case WM_MEASUREITEM: //Needed by the contact's context menu - return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); - - case WM_DRAWITEM: //Needed by the contact's context menu - return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE; -} - -//============ POPUP OPTIONS ============ - -// temporary read the current option to memory -// but does not write to the database -void ReadPopupOpt(HWND hdlg) -{ - char text[MAX_TEXT_SIZE]; - int num; - char str[512]; - - // popup colour - opt.TextColour = SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_GETCOLOUR,0,0); - opt.BGColour = SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_GETCOLOUR,0,0); - - // get delay time - GetDlgItemText(hdlg, IDC_DELAY, str, sizeof(str)); - num = atoi(str); - opt.pDelay = num; - - // other options - opt.UseWinColors = (BYTE)IsDlgButtonChecked(hdlg, IDC_USEWINCOLORS); - opt.UsePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_E); - opt.UpdatePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP1); - opt.AlertPopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP2); - opt.PopupOnChange = (BYTE)IsDlgButtonChecked(hdlg, IDC_CH); - opt.ShowWarnings = (BYTE)IsDlgButtonChecked(hdlg, IDC_W); - - // popup texts - wfree(&opt.pText); - wfree(&opt.pTitle); - GetDlgItemTextWth(hdlg, IDC_PText, text, MAX_TEXT_SIZE); - wSetData(&opt.pText, text); - GetDlgItemTextWth(hdlg, IDC_PTitle, text, MAX_TEXT_SIZE); - wSetData(&opt.pTitle, text); -} - -// copied and modified from NewStatusNotify -INT_PTR CALLBACK DlgPopUpOpts(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - int ID; - char str[512]; - HMENU hMenu, hMenu1; - RECT pos; - HWND button; - HANDLE hContact; - - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - SaveOptions(); - - // click actions - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND); - SetDlgItemTextWth(hdlg, IDC_LeftClick, Translate(str)); - GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND); - SetDlgItemTextWth(hdlg, IDC_RightClick, Translate(str)); - DestroyMenu(hMenu); - - // other options - CheckDlgButton(hdlg, IDC_E, opt.UsePopup); - CheckDlgButton(hdlg, IDC_POP2, opt.AlertPopup); - CheckDlgButton(hdlg, IDC_POP1, opt.UpdatePopup); - CheckDlgButton(hdlg, IDC_CH, opt.PopupOnChange); - CheckDlgButton(hdlg, IDC_W, opt.ShowWarnings); - SetDlgItemTextWth(hdlg,IDC_PText, opt.pText); - SetDlgItemTextWth(hdlg,IDC_PTitle, opt.pTitle); - // setting popup delay option - _ltoa(opt.pDelay, str, 10); - SetDlgItemTextWth(hdlg,IDC_DELAY, str); - if (opt.pDelay == -1) - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); - else if (opt.pDelay == 0) - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); - else - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); - //Colours. First step is configuring the colours. - SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_SETCOLOUR,0,opt.BGColour); - SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_SETCOLOUR,0,opt.TextColour); - //Second step is disabling them if we want to use default Windows ones. - CheckDlgButton(hdlg, IDC_USEWINCOLORS,opt.UseWinColors?BST_CHECKED:BST_UNCHECKED); - EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !opt.UseWinColors); - EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !opt.UseWinColors); - - // buttons - SendMessage(GetDlgItem(hdlg,IDC_PREVIEW), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_PDEF), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_LeftClick), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_RightClick), BUTTONSETASFLATBTN, 0, 0); - SendMessage(GetDlgItem(hdlg,IDC_VAR3), BUTTONSETASFLATBTN, 0, 0); - - return TRUE; - - case WM_COMMAND: - // enable the "apply" button - if (HIWORD(wParam)==BN_CLICKED && GetFocus()==(HWND)lParam) - SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); - if (!((LOWORD(wParam) == IDC_UPDATE || LOWORD(wParam) == IDC_DEGREE) && - (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))) - SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); - //These are simple clicks: we don't save, but we tell the Options Page to enable the "Apply" button. - switch(LOWORD(wParam)) - { - case IDC_BGCOLOUR: //Fall through - case IDC_TEXTCOLOUR: - // select new colors - if (HIWORD(wParam) == CPN_COLOURCHANGED) - SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); - break; - - case IDC_USEWINCOLORS: - // use window color - enable/disable color selection controls - EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !(opt.UseWinColors)); - EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !(opt.UseWinColors)); - SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); - break; - - case IDC_E: - case IDC_CH: - SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); - break; - - case IDC_RightClick: - // right click action selection menu - button = GetDlgItem(hdlg, IDC_RightClick); - GetWindowRect(button, &pos); - - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); - SelectMenuItem(hMenu1, opt.RightClickAction); - ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL); - if (ID) opt.RightClickAction = ID; - DestroyMenu(hMenu); - - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND); - SetDlgItemTextWth(hdlg, IDC_RightClick, Translate(str)); - DestroyMenu(hMenu); - break; - - case IDC_LeftClick: - // left click action selection menu - button = GetDlgItem(hdlg, IDC_LeftClick); - GetWindowRect(button, &pos); - - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); - SelectMenuItem(hMenu1, opt.LeftClickAction); - ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL); - if (ID) opt.LeftClickAction = ID; - DestroyMenu(hMenu); - - hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND); - SetDlgItemTextWth(hdlg, IDC_LeftClick, Translate(str)); - DestroyMenu(hMenu); - break; - - case IDC_PD1: - // Popup delay setting from PopUp plugin - SetDlgItemText(hdlg, IDC_DELAY, "0"); - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); - break; - - case IDC_PD2: - // Popup delay = permanent - SetDlgItemText(hdlg, IDC_DELAY, "-1"); - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); - break; - - case IDC_DELAY: - // if text is edited - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); - break; - - case IDC_PDEF: - // set the default value for popup texts - SetTextDefault("Pp"); - SetDlgItemTextWth(hdlg,IDC_PText, opt.pText); - SetDlgItemTextWth(hdlg,IDC_PTitle, opt.pTitle); - wfree(&opt.pText); - wfree(&opt.pTitle); - break; - - case IDC_VAR3: - // display variable list - strcpy(str, " \n"); // to make the message box wider - strcat(str, Translate("%c\tcurrent condition\n%d\tcurrent date\n%e\tdewpoint\n%f\tfeel-like temperature\n%h\ttoday's high\n%i\twind direction\n%l\ttoday's low\n%m\thumidity\n%n\tstation name\n%p\tpressure\n%r\tsunrise time\n%s\tstation ID\n%t\ttemperature\n%u\tupdate time\n%v\tvisibility\n%w\twind speed\n%y\tsun set")); - strcat(str, "\n"); - strcat(str, Translate("%[..]\tcustom variables")); - MessageBox(NULL, str, Translate("Variable List"), MB_OK|MB_ICONASTERISK|MB_TOPMOST); - break; - - case IDC_PREVIEW: - // popup preview - hContact = opt.DefStn; - ReadPopupOpt(hdlg); // read new options to memory - WeatherPopup((WPARAM)opt.DefStn, (BOOL)TRUE); // display popup using new opt - DestroyOptions(); - LoadOptions(); // restore old option in memory - opt.DefStn = hContact; - break; - } - break; - //End WM_COMMAND - case WM_NOTIFY: //Here we have pressed either the OK or the APPLY button. - switch (((LPNMHDR)lParam)->code) - { - case PSN_APPLY: - { - ReadPopupOpt(hdlg); - - // save the options, and update main menu - SaveOptions(); - UpdatePopupMenu(opt.UsePopup); - return TRUE; - } - } - break; - } - return FALSE; -} - -// used to select the menu item for popup action menu -void SelectMenuItem(HMENU hMenu, int Check) -{ - int i; - for (i=0; i<=GetMenuItemCount(hMenu)-1; i++) - CheckMenuItem(hMenu, i, MF_BYPOSITION|((int)GetMenuItemID(hMenu, i) == Check)*8); -} - diff --git a/protocols/weather/weather_popup.cpp b/protocols/weather/weather_popup.cpp new file mode 100644 index 0000000000..270f989c73 --- /dev/null +++ b/protocols/weather/weather_popup.cpp @@ -0,0 +1,454 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2009 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* This file contain the source related to weather popups, including popup + options, popup display, and the code for popup process. +*/ + +#include "weather.h" + +// variables for weather_popup.c +static HANDLE hPopupContact; + +//============ SHOW WEATHER POPUPS ============ + +// display weather popups +// wParam = the contact to display popup +// lParam = whether the weather data is changed or not +int WeatherPopup(WPARAM wParam, LPARAM lParam) +{ + // determine if the popup should display or not + if (opt.UsePopup && opt.UpdatePopup && (!opt.PopupOnChange || (BOOL)lParam) && + !DBGetContactSettingByte((HANDLE)wParam, WEATHERPROTONAME, "DPopUp", 0)) + { + POPUPDATAEX ppd = {0}; + WEATHERINFO winfo; + + // setup the popup + ppd.lchContact = (HANDLE)wParam; +// if ((HANDLE)wParam != NULL) { // for actual contact + winfo = LoadWeatherInfo((HANDLE)wParam); + ppd.PluginData = ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, winfo.status); + GetDisplay(&winfo, opt.pTitle, ppd.lpzContactName); + GetDisplay(&winfo, opt.pText, ppd.lpzText); + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; +// } +// else { // for preview +// ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, ONLINE); +// strcpy(ppd.lpzContactName, Translate("This is the name of the city")); +// strcpy(ppd.lpzText, Translate("Here is a short weather description")); +// ppd.PluginWindowProc = NULL; +// } + ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour; + ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour; + ppd.iSeconds = opt.pDelay; + // display popups + if (!ServiceExists(MS_POPUP_ADDPOPUPEX)) // old version + CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0); + else { // new version with delay + ppd.iSeconds = opt.pDelay; + CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); + } + } + return 0; +} + +//============ WEATHER ERROR POPUPS ============ + +// display weather error or notices (not threaded) +// wParam = error text +// lParam = display type +// Type can either be SM_WARNING, SM_NOTIFY, or SM_WEATHERALERT +int WeatherError(WPARAM wParam, LPARAM lParam) +{ + if (!opt.UsePopup) return 0; + + if ((DWORD)lParam == SM_WARNING) + PUShowMessage((char*)wParam, SM_WARNING); + else if ((DWORD)lParam == SM_NOTIFY) + PUShowMessage((char*)wParam, SM_NOTIFY); + else if ((DWORD)lParam == SM_WEATHERALERT) + { + POPUPDATAEX ppd = {0}; + char *chop; + char str1[512], str2[512]; + + // get the 2 strings + strcpy(str1, (char*)wParam); + strcpy(str2, (char*)wParam); + chop = strchr(str1, 255); + if (chop != NULL) *chop = '\0'; + else str1[0] = 0; + chop = strchr(str2, 255); + if (chop != NULL) strcpy(str2, chop+1); + else str2[0] = 0; + + // setup the popup + ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_BANG), IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); + strcpy(ppd.lpzContactName, str1); + strcpy(ppd.lpzText, str2); + ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour; + ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour; + ppd.iSeconds = opt.pDelay; + + // display popups + if (!ServiceExists(MS_POPUP_ADDPOPUPEX)) // old version + CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0); + else { // new version with delay + ppd.iSeconds = opt.pDelay; + CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); + } + } + return 0; +} + +// wrapper function for displaying weather warning popup by triggering an event +// (threaded) +// lpzText = error text +// kind = display type (see m_popup.h) +int WPShowMessage(char* lpzText, WORD kind) { + NotifyEventHooks(hHookWeatherError, (WPARAM)lpzText, (LPARAM)kind); + return 0; +} + +//============ WEATHER POPUP PROCESSES ============ + +// popup dialog pocess +// for selecting actions when click on the popup window +// use for displaying contact menu +LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + DWORD ID = 0; + HANDLE hContact; + hContact = PUGetContact(hWnd); + + switch(message) + { + case WM_COMMAND: + ID = opt.LeftClickAction; + if (ID != IDM_M7) PUDeletePopUp(hWnd); + SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0); + return TRUE; + + case WM_CONTEXTMENU: + ID = opt.RightClickAction; + if (ID != IDM_M7) PUDeletePopUp(hWnd); + SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0); + return TRUE; + + case UM_FREEPLUGINDATA: + CallService(MS_SKIN2_RELEASEICON, (WPARAM)PUGetPluginData(hWnd), 0); + return FALSE; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +// process for the popup window +// containing the code for popup actions +LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pt; + HMENU hMenu; + switch (uMsg) + { + case IDM_M2: // brief info + BriefInfo(wParam, 0); + break; + + case IDM_M3: // read complete forecast + LoadForecast(wParam, 0); + break; + + case IDM_M4: // display weather map + WeatherMap(wParam, 0); + break; + + case IDM_M5: // open history window + CallService(MS_HISTORY_SHOWCONTACTHISTORY, wParam, 0); + break; + + case IDM_M6: // open external log + ViewLog(wParam, 0); + break; + + case IDM_M7: // display contact menu + hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,wParam,0); + GetCursorPos(&pt); + hPopupContact = (HANDLE)wParam; + TrackPopupMenu(hMenu,TPM_LEFTALIGN,pt.x,pt.y,0,hWnd,NULL); + DestroyMenu(hMenu); + break; + + case IDM_M8: // display contact detail + CallService(MS_USERINFO_SHOWDIALOG, wParam, 0); + + case WM_COMMAND: //Needed by the contact's context menu + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),(LPARAM)hPopupContact)) + break; + return FALSE; + + case WM_MEASUREITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + + case WM_DRAWITEM: //Needed by the contact's context menu + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE; +} + +//============ POPUP OPTIONS ============ + +// temporary read the current option to memory +// but does not write to the database +void ReadPopupOpt(HWND hdlg) +{ + char text[MAX_TEXT_SIZE]; + int num; + char str[512]; + + // popup colour + opt.TextColour = SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_GETCOLOUR,0,0); + opt.BGColour = SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_GETCOLOUR,0,0); + + // get delay time + GetDlgItemText(hdlg, IDC_DELAY, str, sizeof(str)); + num = atoi(str); + opt.pDelay = num; + + // other options + opt.UseWinColors = (BYTE)IsDlgButtonChecked(hdlg, IDC_USEWINCOLORS); + opt.UsePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_E); + opt.UpdatePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP1); + opt.AlertPopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP2); + opt.PopupOnChange = (BYTE)IsDlgButtonChecked(hdlg, IDC_CH); + opt.ShowWarnings = (BYTE)IsDlgButtonChecked(hdlg, IDC_W); + + // popup texts + wfree(&opt.pText); + wfree(&opt.pTitle); + GetDlgItemTextWth(hdlg, IDC_PText, text, MAX_TEXT_SIZE); + wSetData(&opt.pText, text); + GetDlgItemTextWth(hdlg, IDC_PTitle, text, MAX_TEXT_SIZE); + wSetData(&opt.pTitle, text); +} + +// copied and modified from NewStatusNotify +INT_PTR CALLBACK DlgPopUpOpts(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int ID; + char str[512]; + HMENU hMenu, hMenu1; + RECT pos; + HWND button; + HANDLE hContact; + + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hdlg); + SaveOptions(); + + // click actions + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND); + SetDlgItemTextWth(hdlg, IDC_LeftClick, Translate(str)); + GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND); + SetDlgItemTextWth(hdlg, IDC_RightClick, Translate(str)); + DestroyMenu(hMenu); + + // other options + CheckDlgButton(hdlg, IDC_E, opt.UsePopup); + CheckDlgButton(hdlg, IDC_POP2, opt.AlertPopup); + CheckDlgButton(hdlg, IDC_POP1, opt.UpdatePopup); + CheckDlgButton(hdlg, IDC_CH, opt.PopupOnChange); + CheckDlgButton(hdlg, IDC_W, opt.ShowWarnings); + SetDlgItemTextWth(hdlg,IDC_PText, opt.pText); + SetDlgItemTextWth(hdlg,IDC_PTitle, opt.pTitle); + // setting popup delay option + _ltoa(opt.pDelay, str, 10); + SetDlgItemTextWth(hdlg,IDC_DELAY, str); + if (opt.pDelay == -1) + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); + else if (opt.pDelay == 0) + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); + else + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); + //Colours. First step is configuring the colours. + SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_SETCOLOUR,0,opt.BGColour); + SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_SETCOLOUR,0,opt.TextColour); + //Second step is disabling them if we want to use default Windows ones. + CheckDlgButton(hdlg, IDC_USEWINCOLORS,opt.UseWinColors?BST_CHECKED:BST_UNCHECKED); + EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !opt.UseWinColors); + EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !opt.UseWinColors); + + // buttons + SendMessage(GetDlgItem(hdlg,IDC_PREVIEW), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_PDEF), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_LeftClick), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_RightClick), BUTTONSETASFLATBTN, 0, 0); + SendMessage(GetDlgItem(hdlg,IDC_VAR3), BUTTONSETASFLATBTN, 0, 0); + + return TRUE; + + case WM_COMMAND: + // enable the "apply" button + if (HIWORD(wParam)==BN_CLICKED && GetFocus()==(HWND)lParam) + SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); + if (!((LOWORD(wParam) == IDC_UPDATE || LOWORD(wParam) == IDC_DEGREE) && + (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))) + SendMessage(GetParent(hdlg),PSM_CHANGED,0,0); + //These are simple clicks: we don't save, but we tell the Options Page to enable the "Apply" button. + switch(LOWORD(wParam)) + { + case IDC_BGCOLOUR: //Fall through + case IDC_TEXTCOLOUR: + // select new colors + if (HIWORD(wParam) == CPN_COLOURCHANGED) + SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); + break; + + case IDC_USEWINCOLORS: + // use window color - enable/disable color selection controls + EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !(opt.UseWinColors)); + EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !(opt.UseWinColors)); + SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); + break; + + case IDC_E: + case IDC_CH: + SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); + break; + + case IDC_RightClick: + // right click action selection menu + button = GetDlgItem(hdlg, IDC_RightClick); + GetWindowRect(button, &pos); + + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); + SelectMenuItem(hMenu1, opt.RightClickAction); + ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL); + if (ID) opt.RightClickAction = ID; + DestroyMenu(hMenu); + + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND); + SetDlgItemTextWth(hdlg, IDC_RightClick, Translate(str)); + DestroyMenu(hMenu); + break; + + case IDC_LeftClick: + // left click action selection menu + button = GetDlgItem(hdlg, IDC_LeftClick); + GetWindowRect(button, &pos); + + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)hMenu1, 0); + SelectMenuItem(hMenu1, opt.LeftClickAction); + ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL); + if (ID) opt.LeftClickAction = ID; + DestroyMenu(hMenu); + + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); + GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND); + SetDlgItemTextWth(hdlg, IDC_LeftClick, Translate(str)); + DestroyMenu(hMenu); + break; + + case IDC_PD1: + // Popup delay setting from PopUp plugin + SetDlgItemText(hdlg, IDC_DELAY, "0"); + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); + break; + + case IDC_PD2: + // Popup delay = permanent + SetDlgItemText(hdlg, IDC_DELAY, "-1"); + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); + break; + + case IDC_DELAY: + // if text is edited + CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); + break; + + case IDC_PDEF: + // set the default value for popup texts + SetTextDefault("Pp"); + SetDlgItemTextWth(hdlg,IDC_PText, opt.pText); + SetDlgItemTextWth(hdlg,IDC_PTitle, opt.pTitle); + wfree(&opt.pText); + wfree(&opt.pTitle); + break; + + case IDC_VAR3: + // display variable list + strcpy(str, " \n"); // to make the message box wider + strcat(str, Translate("%c\tcurrent condition\n%d\tcurrent date\n%e\tdewpoint\n%f\tfeel-like temperature\n%h\ttoday's high\n%i\twind direction\n%l\ttoday's low\n%m\thumidity\n%n\tstation name\n%p\tpressure\n%r\tsunrise time\n%s\tstation ID\n%t\ttemperature\n%u\tupdate time\n%v\tvisibility\n%w\twind speed\n%y\tsun set")); + strcat(str, "\n"); + strcat(str, Translate("%[..]\tcustom variables")); + MessageBox(NULL, str, Translate("Variable List"), MB_OK|MB_ICONASTERISK|MB_TOPMOST); + break; + + case IDC_PREVIEW: + // popup preview + hContact = opt.DefStn; + ReadPopupOpt(hdlg); // read new options to memory + WeatherPopup((WPARAM)opt.DefStn, (BOOL)TRUE); // display popup using new opt + DestroyOptions(); + LoadOptions(); // restore old option in memory + opt.DefStn = hContact; + break; + } + break; + //End WM_COMMAND + case WM_NOTIFY: //Here we have pressed either the OK or the APPLY button. + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + ReadPopupOpt(hdlg); + + // save the options, and update main menu + SaveOptions(); + UpdatePopupMenu(opt.UsePopup); + return TRUE; + } + } + break; + } + return FALSE; +} + +// used to select the menu item for popup action menu +void SelectMenuItem(HMENU hMenu, int Check) +{ + int i; + for (i=0; i<=GetMenuItemCount(hMenu)-1; i++) + CheckMenuItem(hMenu, i, MF_BYPOSITION|((int)GetMenuItemID(hMenu, i) == Check)*8); +} + diff --git a/protocols/weather/weather_svcs.c b/protocols/weather/weather_svcs.c deleted file mode 100644 index 89c58c2d6e..0000000000 --- a/protocols/weather/weather_svcs.c +++ /dev/null @@ -1,452 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -This file contain the source related to weather protocol services -as required for a Miranda protocol. Also, it contains functions for -building/changing the weather menu items. -*/ - -#include "weather.h" - -static int hEnableDisablePopupMenu; -static int hEnableDisableMenu; - -static HANDLE hService[27]; - -//============ MIRANDA PROTOCOL SERVICES ============ - -// protocol service function for setting weather protocol status -INT_PTR WeatherSetStatus(WPARAM new_status, LPARAM lParam) -{ - new_status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; - - // if we don't want to show status for default station - if (opt.NoProtoCondition && status != new_status) - { - old_status = status; - status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; - ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); - - UpdateMenu(new_status != ID_STATUS_OFFLINE); - if (new_status != ID_STATUS_OFFLINE) UpdateAll(FALSE, FALSE); - } - - return 0; -} - -// get capabilities protocol service function -INT_PTR WeatherGetCaps(WPARAM wParam, LPARAM lParam) -{ - INT_PTR ret = 0; - - switch(wParam) - { - case PFLAGNUM_1: - // support search and visible list - ret = PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_EXTSEARCH | PF1_VISLIST | PF1_MODEMSGRECV; - break; - - case PFLAGNUM_2: - ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | - PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; - break; - - case PFLAGNUM_4: - ret = PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_FORCEADDED | - PF4_FORCEAUTH; - break; - - case PFLAGNUM_5: /* this is PFLAGNUM_5 change when alpha SDK is released */ - ret = PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | - PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; - // if (!opt.NoProtoCondition) ret |= PF2_ONLINE; - break; - - case PFLAG_UNIQUEIDTEXT: - ret = (INT_PTR)Translate("Station ID"); - break; - - case PFLAG_UNIQUEIDSETTING: - ret = (INT_PTR)"ID"; - break; - } - return ret; -} - -// protocol service function to get weather protocol name -INT_PTR WeatherGetName(WPARAM wParam,LPARAM lParam) -{ - strncpy((char*)lParam,WEATHERPROTOTEXT,wParam-1); - *((char*)lParam + wParam-1) = 0; - return 0; -} - -// protocol service function to get the current status of the protocol -INT_PTR WeatherGetStatus(WPARAM wParam,LPARAM lParam) -{ - return status; -} - -// protocol service function to get the icon of the protocol -INT_PTR WeatherLoadIcon(WPARAM wParam,LPARAM lParam) -{ - return (LOWORD(wParam) == PLI_PROTOCOL) ? (INT_PTR)CopyIcon(LoadIconEx("main", FALSE)) : 0; -} - -static void __cdecl AckThreadProc(HANDLE param) -{ - Sleep(100); - ProtoBroadcastAck(WEATHERPROTONAME, param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0); -} - -// nothing to do here because weather proto do not need to retrieve contact info form network -// so just return a 0 -INT_PTR WeatherGetInfo(WPARAM wParam,LPARAM lParam) -{ - CCSDATA *ccs = (CCSDATA *) lParam; - mir_forkthread(AckThreadProc, ccs->hContact); - return 0; -} - - -INT_PTR WeatherGetAvatarInfo(WPARAM wParam, LPARAM lParam) -{ - static const char *statusStr[] = { - "Light", - "Fog", - "SShower", - "Snow", - "RShower", - "Rain", - "PCloudy", - "Cloudy", - "Sunny", - "NA" - }; - - static const WORD statusValue[] = { - LIGHT, - FOG, - SSHOWER, - SNOW, - RSHOWER, - RAIN, - PCLOUDY, - CLOUDY, - SUNNY, - NA - }; - char szSearchPath[MAX_PATH], *chop; - WORD status; - unsigned i; - PROTO_AVATAR_INFORMATION* ai = ( PROTO_AVATAR_INFORMATION* )lParam; - - GetModuleFileName(GetModuleHandle(NULL), szSearchPath, sizeof(szSearchPath)); - chop = strrchr(szSearchPath, '\\'); - - if (chop) *chop = '\0'; - else szSearchPath[0] = 0; - - status = (WORD)DBGetContactSettingWord(ai->hContact, WEATHERPROTONAME, "StatusIcon",0); - for (i=0; i<10; i++) - { - if (statusValue[i] == status) - break; - } - if (i >= 10) return GAIR_NOAVATAR; - - ai->format = PA_FORMAT_PNG; - wsprintf(ai->filename, "%s\\Plugins\\Weather\\%s.png", szSearchPath, statusStr[i]); - if (_access(ai->filename, 4) == 0) return GAIR_SUCCESS; - - ai->format = PA_FORMAT_GIF; - wsprintf(ai->filename, "%s\\Plugins\\Weather\\%s.gif", szSearchPath, statusStr[i]); - if (_access(ai->filename, 4) == 0) return GAIR_SUCCESS; - - ai->format = PA_FORMAT_UNKNOWN; - ai->filename[0] = 0; - return GAIR_NOAVATAR; -} - - -void AvatarDownloaded(HANDLE hContact) -{ - int haveAvatar; - PROTO_AVATAR_INFORMATION AI = {0}; - AI.cbSize = sizeof(AI); - AI.hContact = hContact; - -// ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0); - - haveAvatar = WeatherGetAvatarInfo(GAIF_FORCE, (LPARAM)&AI) == GAIR_SUCCESS; - - if (haveAvatar) - ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &AI, 0); - else - ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0); -} - - -static void __cdecl WeatherGetAwayMsgThread(HANDLE hContact) -{ - DBVARIANT dbv; - Sleep(100); - if (!DBGetContactSettingString(hContact, "CList", "StatusMsg", &dbv)) - { - ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, - (HANDLE)1, (LPARAM)dbv.pszVal); - DBFreeVariant( &dbv ); - } - else - ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0); -} - -static INT_PTR WeatherGetAwayMsg(WPARAM wParam, LPARAM lParam) -{ - CCSDATA* ccs = (CCSDATA*)lParam; - if (ccs == NULL) - return 0; - - mir_forkthread(WeatherGetAwayMsgThread, ccs->hContact); - return 1; -} - -//============ PROTOCOL INITIALIZATION ============ -// protocol services -void InitServices(void) -{ - hService[0] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETCAPS, WeatherGetCaps); - hService[1] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETNAME, WeatherGetName); - hService[3] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_LOADICON, WeatherLoadIcon); - hService[4] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SETSTATUS, WeatherSetStatus); - hService[5] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETSTATUS, WeatherGetStatus); - hService[6] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_BASICSEARCH, WeatherBasicSearch); - hService[7] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYEMAIL, WeatherBasicSearch); - hService[8] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_ADDTOLIST, WeatherAddToList); - hService[9] = CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETINFO, WeatherGetInfo); - hService[10] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETAVATARINFO, WeatherGetAvatarInfo); - hService[11] = CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETAWAYMSG, WeatherGetAwayMsg); - hService[12] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_CREATEADVSEARCHUI, WeatherCreateAdvancedSearchUI); - hService[13] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYADVANCED, WeatherAdvancedSearch); - - hService[14] = CreateProtoServiceFunction(WEATHERPROTONAME, MS_WEATHER_GETDISPLAY, GetDisplaySvcFunc); -} - -void DestroyServices(void) -{ - unsigned i; - - for (i = sizeof(hService)/sizeof(HANDLE); i--; ) - { - if (hService[i] != NULL) - DestroyServiceFunction(hService[i]); - } -} - -//============ MENU INITIALIZATION ============ - -void UpdateMenu(BOOL State) -{ - // We're here to change something, so let's read the actual value. - // TempDisable == FALSE means that right now the popups are enabled - // and if we're here, we want to disable them. - // The icon works this way: - // if the notifications are disabled, the icon hasn't the red circle; - // if the notifications are enabled, the icon has the red circle. - - CLISTMENUITEM mi = {0}; - - mi.cbSize = sizeof(mi); - - if (State) - { // to enable auto-update - mi.pszName = "Auto Update Enabled"; - mi.icolibItem = GetIconHandle("main"); - } - else - { // to disable auto-update - mi.pszName = "Auto Update Disabled"; - mi.icolibItem = GetIconHandle("disabled"); - } - // update option setting - opt.CAutoUpdate = State; - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate); - mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB; - - // update menu item - CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableDisableMenu,(LPARAM)&mi); -} - -void UpdatePopupMenu(BOOL State) -{ - // We're here to change something, so let's read the actual value. - // TempDisable == FALSE means that right now the popups are enabled - // and if we're here, we want to disable them. - // The icon works this way: - // if the notifications are disabled, the icon hasn't the red circle; - // if the notifications are enabled, the icon has the red circle. - - CLISTMENUITEM mi = {0}; - - mi.cbSize = sizeof(mi); - - if (State) - { // to enable popup - mi.pszName = "Disable &weather notification"; - mi.icolibItem = GetIconHandle("popup"); - } - else - { // to disable popup - mi.pszName = "Enable &weather notification"; - mi.icolibItem = GetIconHandle("nopopup"); - } - // update option setting - opt.UsePopup = State; - DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup); - mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB; - - // update menu item - CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableDisablePopupMenu,(LPARAM)&mi); -} - -// update the weather auto-update menu item when click on it -INT_PTR EnableDisableCmd(WPARAM wParam,LPARAM lParam) -{ - UpdateMenu(wParam == TRUE ? (BOOL)lParam : !opt.CAutoUpdate); - return 0; -} - -// update the weather popup menu item when click on it -INT_PTR MenuitemNotifyCmd(WPARAM wParam,LPARAM lParam) -{ - UpdatePopupMenu(!opt.UsePopup); - return 0; -} - -// adding weather contact menus -// copied and modified form "modified MSN Protocol" -void AddMenuItems(void) -{ - CLISTMENUITEM mi = {0}; - - mi.cbSize = sizeof(mi); - mi.pszContactOwner = WEATHERPROTONAME; - mi.flags = CMIF_ICONFROMICOLIB; - - // contact menu - hService[15] = CreateServiceFunction(MS_WEATHER_UPDATE, UpdateSingleStation); - mi.position=-0x7FFFFFFA; - mi.icolibItem = GetIconHandle("update"); - mi.pszName="Update Weather"; - mi.pszService = MS_WEATHER_UPDATE; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[16] = CreateServiceFunction(MS_WEATHER_REFRESH, UpdateSingleRemove); - mi.position=-0x7FFFFFF9; - mi.icolibItem = GetIconHandle("update2"); - mi.pszName="Remove Old Data then Update"; - mi.pszService = MS_WEATHER_REFRESH; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[17] = CreateServiceFunction(MS_WEATHER_BRIEF, BriefInfoSvc); - mi.position=-0x7FFFFFF8; - mi.icolibItem = GetIconHandle("brief"); - mi.pszName="Brief Information"; - mi.pszService = MS_WEATHER_BRIEF; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[18] = CreateServiceFunction(MS_WEATHER_COMPLETE, LoadForecast); - mi.position=-0x7FFFFFF7; - mi.icolibItem = GetIconHandle("read"); - mi.pszName="Read Complete Forecast"; - mi.pszService = MS_WEATHER_COMPLETE; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[19] = CreateServiceFunction(MS_WEATHER_MAP, WeatherMap); - mi.position=-0x7FFFFFF6; - mi.icolibItem = GetIconHandle("map"); - mi.pszName="Weather Map"; - mi.pszService = MS_WEATHER_MAP; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[20] = CreateServiceFunction(MS_WEATHER_LOG, ViewLog); - mi.position=-0x7FFFFFF5; - mi.icolibItem = GetIconHandle("log"); - mi.pszName="View Log"; - mi.pszService = MS_WEATHER_LOG; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - hService[21] = CreateServiceFunction(MS_WEATHER_EDIT, EditSettings); - mi.position=-0x7FFFFFF4; - mi.icolibItem = GetIconHandle("edit"); - mi.pszName="Edit Settings"; - mi.pszService = MS_WEATHER_EDIT; - CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - - // adding main menu items - mi.pszPopupName = "Weather"; - mi.popupPosition = 500099000; - - hService[22] = CreateServiceFunction(MS_WEATHER_ENABLED, EnableDisableCmd); - mi.pszName = "Enable/Disable Weather Update"; - mi.icolibItem = GetIconHandle("main"); - mi.position=10100001; - mi.pszService = MS_WEATHER_ENABLED; - hEnableDisableMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); - UpdateMenu(opt.AutoUpdate); - - hService[23] = CreateServiceFunction(MS_WEATHER_UPDATEALL, UpdateAllInfo); - mi.position=20100001; - mi.icolibItem = GetIconHandle("update"); - mi.pszName="Update All Weather"; - mi.pszService = MS_WEATHER_UPDATEALL; - CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); - - hService[24] = CreateServiceFunction(MS_WEATHER_REFRESHALL, UpdateAllRemove); - mi.position=20100002; - mi.icolibItem = GetIconHandle("update2"); - mi.pszName="Remove Old Data then Update All"; - mi.pszService = MS_WEATHER_REFRESHALL; - CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); - - // only run if popup service exists - if (ServiceExists(MS_POPUP_ADDPOPUP)) - { - hService[25] = CreateServiceFunction(WEATHERPROTONAME "/PopupMenu", MenuitemNotifyCmd); - mi.pszName = "Weather Notification"; - mi.icolibItem = GetIconHandle("popup"); - mi.position = 0; - mi.pszPopupName = "PopUps"; - mi.pszService = WEATHERPROTONAME "/PopupMenu"; - hEnableDisablePopupMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); - UpdatePopupMenu(opt.UsePopup); - } - - if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) - { - hService[26] = CreateServiceFunction("Weather/mwin_menu", Mwin_MenuClicked); - mi.position = -0x7FFFFFF0; - mi.hIcon = NULL; - mi.flags = 0; - mi.pszName = "Display in a frame"; - mi.pszService = "Weather/mwin_menu"; - hMwinMenu = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); - } -} diff --git a/protocols/weather/weather_svcs.cpp b/protocols/weather/weather_svcs.cpp new file mode 100644 index 0000000000..89c58c2d6e --- /dev/null +++ b/protocols/weather/weather_svcs.cpp @@ -0,0 +1,452 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +This file contain the source related to weather protocol services +as required for a Miranda protocol. Also, it contains functions for +building/changing the weather menu items. +*/ + +#include "weather.h" + +static int hEnableDisablePopupMenu; +static int hEnableDisableMenu; + +static HANDLE hService[27]; + +//============ MIRANDA PROTOCOL SERVICES ============ + +// protocol service function for setting weather protocol status +INT_PTR WeatherSetStatus(WPARAM new_status, LPARAM lParam) +{ + new_status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; + + // if we don't want to show status for default station + if (opt.NoProtoCondition && status != new_status) + { + old_status = status; + status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; + ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); + + UpdateMenu(new_status != ID_STATUS_OFFLINE); + if (new_status != ID_STATUS_OFFLINE) UpdateAll(FALSE, FALSE); + } + + return 0; +} + +// get capabilities protocol service function +INT_PTR WeatherGetCaps(WPARAM wParam, LPARAM lParam) +{ + INT_PTR ret = 0; + + switch(wParam) + { + case PFLAGNUM_1: + // support search and visible list + ret = PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_EXTSEARCH | PF1_VISLIST | PF1_MODEMSGRECV; + break; + + case PFLAGNUM_2: + ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | + PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; + break; + + case PFLAGNUM_4: + ret = PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_FORCEADDED | + PF4_FORCEAUTH; + break; + + case PFLAGNUM_5: /* this is PFLAGNUM_5 change when alpha SDK is released */ + ret = PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | + PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; + // if (!opt.NoProtoCondition) ret |= PF2_ONLINE; + break; + + case PFLAG_UNIQUEIDTEXT: + ret = (INT_PTR)Translate("Station ID"); + break; + + case PFLAG_UNIQUEIDSETTING: + ret = (INT_PTR)"ID"; + break; + } + return ret; +} + +// protocol service function to get weather protocol name +INT_PTR WeatherGetName(WPARAM wParam,LPARAM lParam) +{ + strncpy((char*)lParam,WEATHERPROTOTEXT,wParam-1); + *((char*)lParam + wParam-1) = 0; + return 0; +} + +// protocol service function to get the current status of the protocol +INT_PTR WeatherGetStatus(WPARAM wParam,LPARAM lParam) +{ + return status; +} + +// protocol service function to get the icon of the protocol +INT_PTR WeatherLoadIcon(WPARAM wParam,LPARAM lParam) +{ + return (LOWORD(wParam) == PLI_PROTOCOL) ? (INT_PTR)CopyIcon(LoadIconEx("main", FALSE)) : 0; +} + +static void __cdecl AckThreadProc(HANDLE param) +{ + Sleep(100); + ProtoBroadcastAck(WEATHERPROTONAME, param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0); +} + +// nothing to do here because weather proto do not need to retrieve contact info form network +// so just return a 0 +INT_PTR WeatherGetInfo(WPARAM wParam,LPARAM lParam) +{ + CCSDATA *ccs = (CCSDATA *) lParam; + mir_forkthread(AckThreadProc, ccs->hContact); + return 0; +} + + +INT_PTR WeatherGetAvatarInfo(WPARAM wParam, LPARAM lParam) +{ + static const char *statusStr[] = { + "Light", + "Fog", + "SShower", + "Snow", + "RShower", + "Rain", + "PCloudy", + "Cloudy", + "Sunny", + "NA" + }; + + static const WORD statusValue[] = { + LIGHT, + FOG, + SSHOWER, + SNOW, + RSHOWER, + RAIN, + PCLOUDY, + CLOUDY, + SUNNY, + NA + }; + char szSearchPath[MAX_PATH], *chop; + WORD status; + unsigned i; + PROTO_AVATAR_INFORMATION* ai = ( PROTO_AVATAR_INFORMATION* )lParam; + + GetModuleFileName(GetModuleHandle(NULL), szSearchPath, sizeof(szSearchPath)); + chop = strrchr(szSearchPath, '\\'); + + if (chop) *chop = '\0'; + else szSearchPath[0] = 0; + + status = (WORD)DBGetContactSettingWord(ai->hContact, WEATHERPROTONAME, "StatusIcon",0); + for (i=0; i<10; i++) + { + if (statusValue[i] == status) + break; + } + if (i >= 10) return GAIR_NOAVATAR; + + ai->format = PA_FORMAT_PNG; + wsprintf(ai->filename, "%s\\Plugins\\Weather\\%s.png", szSearchPath, statusStr[i]); + if (_access(ai->filename, 4) == 0) return GAIR_SUCCESS; + + ai->format = PA_FORMAT_GIF; + wsprintf(ai->filename, "%s\\Plugins\\Weather\\%s.gif", szSearchPath, statusStr[i]); + if (_access(ai->filename, 4) == 0) return GAIR_SUCCESS; + + ai->format = PA_FORMAT_UNKNOWN; + ai->filename[0] = 0; + return GAIR_NOAVATAR; +} + + +void AvatarDownloaded(HANDLE hContact) +{ + int haveAvatar; + PROTO_AVATAR_INFORMATION AI = {0}; + AI.cbSize = sizeof(AI); + AI.hContact = hContact; + +// ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0); + + haveAvatar = WeatherGetAvatarInfo(GAIF_FORCE, (LPARAM)&AI) == GAIR_SUCCESS; + + if (haveAvatar) + ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &AI, 0); + else + ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0); +} + + +static void __cdecl WeatherGetAwayMsgThread(HANDLE hContact) +{ + DBVARIANT dbv; + Sleep(100); + if (!DBGetContactSettingString(hContact, "CList", "StatusMsg", &dbv)) + { + ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, + (HANDLE)1, (LPARAM)dbv.pszVal); + DBFreeVariant( &dbv ); + } + else + ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0); +} + +static INT_PTR WeatherGetAwayMsg(WPARAM wParam, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*)lParam; + if (ccs == NULL) + return 0; + + mir_forkthread(WeatherGetAwayMsgThread, ccs->hContact); + return 1; +} + +//============ PROTOCOL INITIALIZATION ============ +// protocol services +void InitServices(void) +{ + hService[0] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETCAPS, WeatherGetCaps); + hService[1] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETNAME, WeatherGetName); + hService[3] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_LOADICON, WeatherLoadIcon); + hService[4] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SETSTATUS, WeatherSetStatus); + hService[5] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETSTATUS, WeatherGetStatus); + hService[6] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_BASICSEARCH, WeatherBasicSearch); + hService[7] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYEMAIL, WeatherBasicSearch); + hService[8] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_ADDTOLIST, WeatherAddToList); + hService[9] = CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETINFO, WeatherGetInfo); + hService[10] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETAVATARINFO, WeatherGetAvatarInfo); + hService[11] = CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETAWAYMSG, WeatherGetAwayMsg); + hService[12] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_CREATEADVSEARCHUI, WeatherCreateAdvancedSearchUI); + hService[13] = CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYADVANCED, WeatherAdvancedSearch); + + hService[14] = CreateProtoServiceFunction(WEATHERPROTONAME, MS_WEATHER_GETDISPLAY, GetDisplaySvcFunc); +} + +void DestroyServices(void) +{ + unsigned i; + + for (i = sizeof(hService)/sizeof(HANDLE); i--; ) + { + if (hService[i] != NULL) + DestroyServiceFunction(hService[i]); + } +} + +//============ MENU INITIALIZATION ============ + +void UpdateMenu(BOOL State) +{ + // We're here to change something, so let's read the actual value. + // TempDisable == FALSE means that right now the popups are enabled + // and if we're here, we want to disable them. + // The icon works this way: + // if the notifications are disabled, the icon hasn't the red circle; + // if the notifications are enabled, the icon has the red circle. + + CLISTMENUITEM mi = {0}; + + mi.cbSize = sizeof(mi); + + if (State) + { // to enable auto-update + mi.pszName = "Auto Update Enabled"; + mi.icolibItem = GetIconHandle("main"); + } + else + { // to disable auto-update + mi.pszName = "Auto Update Disabled"; + mi.icolibItem = GetIconHandle("disabled"); + } + // update option setting + opt.CAutoUpdate = State; + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate); + mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB; + + // update menu item + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableDisableMenu,(LPARAM)&mi); +} + +void UpdatePopupMenu(BOOL State) +{ + // We're here to change something, so let's read the actual value. + // TempDisable == FALSE means that right now the popups are enabled + // and if we're here, we want to disable them. + // The icon works this way: + // if the notifications are disabled, the icon hasn't the red circle; + // if the notifications are enabled, the icon has the red circle. + + CLISTMENUITEM mi = {0}; + + mi.cbSize = sizeof(mi); + + if (State) + { // to enable popup + mi.pszName = "Disable &weather notification"; + mi.icolibItem = GetIconHandle("popup"); + } + else + { // to disable popup + mi.pszName = "Enable &weather notification"; + mi.icolibItem = GetIconHandle("nopopup"); + } + // update option setting + opt.UsePopup = State; + DBWriteContactSettingByte(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup); + mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB; + + // update menu item + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hEnableDisablePopupMenu,(LPARAM)&mi); +} + +// update the weather auto-update menu item when click on it +INT_PTR EnableDisableCmd(WPARAM wParam,LPARAM lParam) +{ + UpdateMenu(wParam == TRUE ? (BOOL)lParam : !opt.CAutoUpdate); + return 0; +} + +// update the weather popup menu item when click on it +INT_PTR MenuitemNotifyCmd(WPARAM wParam,LPARAM lParam) +{ + UpdatePopupMenu(!opt.UsePopup); + return 0; +} + +// adding weather contact menus +// copied and modified form "modified MSN Protocol" +void AddMenuItems(void) +{ + CLISTMENUITEM mi = {0}; + + mi.cbSize = sizeof(mi); + mi.pszContactOwner = WEATHERPROTONAME; + mi.flags = CMIF_ICONFROMICOLIB; + + // contact menu + hService[15] = CreateServiceFunction(MS_WEATHER_UPDATE, UpdateSingleStation); + mi.position=-0x7FFFFFFA; + mi.icolibItem = GetIconHandle("update"); + mi.pszName="Update Weather"; + mi.pszService = MS_WEATHER_UPDATE; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[16] = CreateServiceFunction(MS_WEATHER_REFRESH, UpdateSingleRemove); + mi.position=-0x7FFFFFF9; + mi.icolibItem = GetIconHandle("update2"); + mi.pszName="Remove Old Data then Update"; + mi.pszService = MS_WEATHER_REFRESH; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[17] = CreateServiceFunction(MS_WEATHER_BRIEF, BriefInfoSvc); + mi.position=-0x7FFFFFF8; + mi.icolibItem = GetIconHandle("brief"); + mi.pszName="Brief Information"; + mi.pszService = MS_WEATHER_BRIEF; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[18] = CreateServiceFunction(MS_WEATHER_COMPLETE, LoadForecast); + mi.position=-0x7FFFFFF7; + mi.icolibItem = GetIconHandle("read"); + mi.pszName="Read Complete Forecast"; + mi.pszService = MS_WEATHER_COMPLETE; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[19] = CreateServiceFunction(MS_WEATHER_MAP, WeatherMap); + mi.position=-0x7FFFFFF6; + mi.icolibItem = GetIconHandle("map"); + mi.pszName="Weather Map"; + mi.pszService = MS_WEATHER_MAP; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[20] = CreateServiceFunction(MS_WEATHER_LOG, ViewLog); + mi.position=-0x7FFFFFF5; + mi.icolibItem = GetIconHandle("log"); + mi.pszName="View Log"; + mi.pszService = MS_WEATHER_LOG; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + hService[21] = CreateServiceFunction(MS_WEATHER_EDIT, EditSettings); + mi.position=-0x7FFFFFF4; + mi.icolibItem = GetIconHandle("edit"); + mi.pszName="Edit Settings"; + mi.pszService = MS_WEATHER_EDIT; + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + // adding main menu items + mi.pszPopupName = "Weather"; + mi.popupPosition = 500099000; + + hService[22] = CreateServiceFunction(MS_WEATHER_ENABLED, EnableDisableCmd); + mi.pszName = "Enable/Disable Weather Update"; + mi.icolibItem = GetIconHandle("main"); + mi.position=10100001; + mi.pszService = MS_WEATHER_ENABLED; + hEnableDisableMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + UpdateMenu(opt.AutoUpdate); + + hService[23] = CreateServiceFunction(MS_WEATHER_UPDATEALL, UpdateAllInfo); + mi.position=20100001; + mi.icolibItem = GetIconHandle("update"); + mi.pszName="Update All Weather"; + mi.pszService = MS_WEATHER_UPDATEALL; + CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + + hService[24] = CreateServiceFunction(MS_WEATHER_REFRESHALL, UpdateAllRemove); + mi.position=20100002; + mi.icolibItem = GetIconHandle("update2"); + mi.pszName="Remove Old Data then Update All"; + mi.pszService = MS_WEATHER_REFRESHALL; + CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + + // only run if popup service exists + if (ServiceExists(MS_POPUP_ADDPOPUP)) + { + hService[25] = CreateServiceFunction(WEATHERPROTONAME "/PopupMenu", MenuitemNotifyCmd); + mi.pszName = "Weather Notification"; + mi.icolibItem = GetIconHandle("popup"); + mi.position = 0; + mi.pszPopupName = "PopUps"; + mi.pszService = WEATHERPROTONAME "/PopupMenu"; + hEnableDisablePopupMenu = CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + UpdatePopupMenu(opt.UsePopup); + } + + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + hService[26] = CreateServiceFunction("Weather/mwin_menu", Mwin_MenuClicked); + mi.position = -0x7FFFFFF0; + mi.hIcon = NULL; + mi.flags = 0; + mi.pszName = "Display in a frame"; + mi.pszService = "Weather/mwin_menu"; + hMwinMenu = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + } +} diff --git a/protocols/weather/weather_update.c b/protocols/weather/weather_update.c deleted file mode 100644 index 9b81b023f5..0000000000 --- a/protocols/weather/weather_update.c +++ /dev/null @@ -1,678 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -This file contain the source related to updating new weather -information, both automatic (by timer) and manually (by selecting -menu items). -*/ - -#include "weather.h" - -UPDATELIST *UpdateListHead; -UPDATELIST *UpdateListTail; - -extern HANDLE hUpdateMutex; - -//============ RETRIEVE NEW WEATHER ============ - -// retrieve weather info and display / log them -// hContact = current contact -int UpdateWeather(HANDLE hContact) -{ - char str[256], str2[MAX_TEXT_SIZE], logstr[256]; - int code; - FILE *file; - DBVARIANT dbv; - BOOL Ch = FALSE; - WEATHERINFO winfo; - HWND hMoreDataDlg; - int dbres; - - if (hContact == NULL) return 1; // some error prevention - - dbv.pszVal = ""; - - // log to netlib log for debug purpose - Netlib_Logf(hNetlibUser, "************************************************************************"); - dbres = DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv); - - Netlib_Logf(hNetlibUser, "<-- Start update for station: %s -->", dbv.pszVal); - mir_snprintf(logstr, sizeof(logstr), "<-- Update successful for station: %s -->", dbv.pszVal); - - // download the info and parse it - // result are stored in database - code = GetWeatherData(hContact); - if (code != 0) - { - // error occurs if the return value is not equals to 0 - if (opt.ShowWarnings) - { // show warnings by popup - mir_snprintf(str, sizeof(str)-105, - Translate("Unable to retrieve weather information for %s"), dbv.pszVal); - strcat(str, "\n"); - strcat(str, GetError(code)); - WPShowMessage(str, SM_WARNING); - } - // log to netlib - Netlib_Logf(hNetlibUser, "Error! Update cannot continue... Start to free memory"); - Netlib_Logf(hNetlibUser, "<-- Error occurs while updating station: %s -->", dbv.pszVal); - if (!dbres) DBFreeVariant(&dbv); - return 1; - } - if (!dbres) DBFreeVariant(&dbv); - - // initialize, load new weather Data - winfo = LoadWeatherInfo(hContact); - - // translate weather condition - strcpy(winfo.cond, Translate(winfo.cond)); - - // compare the old condition and determine if the weather had changed - if (opt.UpdateOnlyConditionChanged) // consider condition change - { - if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", &dbv)) - { - if (_stricmp(winfo.cond, dbv.pszVal)) Ch = TRUE; // the weather condition is changed - DBFreeVariant(&dbv); - } - else Ch = TRUE; - if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", &dbv)) - { - if (_stricmp(winfo.temp, dbv.pszVal)) Ch = TRUE; // the temperature is changed - DBFreeVariant(&dbv); - } - else Ch = TRUE; - } - else // consider update time change - { - if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastUpdate", &dbv)) - { - if (_stricmp(winfo.update, dbv.pszVal)) Ch = TRUE; // the update time is changed - DBFreeVariant(&dbv); - } - else Ch = TRUE; - } - - // have weather alert issued? - dbres = DBGetContactSettingString(hContact, WEATHERCONDITION, "Alert", &dbv); - if (!dbres && dbv.pszVal[0] != 0) - { - if (opt.AlertPopup && !DBGetContactSettingByte(hContact, WEATHERPROTONAME, "DPopUp", 0) && Ch) - { - // display alert popup - wsprintf(str, "Alert for %s%c%s", winfo.city, 255, dbv.pszVal); - WPShowMessage(str, SM_WEATHERALERT); - } - // alert issued, set display to italic - if (opt.MakeItalic) - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "ApparentMode", ID_STATUS_OFFLINE); - SkinPlaySound("weatheralert"); - } - // alert dropped, set the display back to normal - else DBDeleteContactSetting(hContact, WEATHERPROTONAME, "ApparentMode"); - if (!dbres) DBFreeVariant(&dbv); - - // backup current condition for checking if the weather is changed or not - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", winfo.update); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", winfo.cond); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", winfo.temp); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastUpdate", winfo.update); - - // display condition on contact list - if (opt.DisCondIcon && winfo.status != ID_STATUS_OFFLINE) - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_ONLINE); - else - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", winfo.status); - AvatarDownloaded(hContact); - - GetDisplay(&winfo, opt.cText, str2); - if (lpcp != CP_ACP) - { - LPWSTR m_psz = ConvToUnicode(str2); - DBWriteContactSettingWString(hContact, "CList", "MyHandle", m_psz); - mir_free(m_psz); - } - else - DBWriteContactSettingString(hContact, "CList", "MyHandle", str2); - - GetDisplay(&winfo, opt.sText, str2); - if (str2[0]) - { - if (lpcp != CP_ACP) - { - wchar_t* m_psz = ConvToUnicode(str2); - DBWriteContactSettingWString(hContact, "CList", "StatusMsg", m_psz); - mir_free(m_psz); - } - else - DBWriteContactSettingString(hContact, "CList", "StatusMsg", str2); - } - else - DBDeleteContactSetting(hContact, "CList", "StatusMsg"); - - ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, NULL, (LPARAM)(str2[0] ? str2 : 0)); - - // save descriptions in MyNotes - GetDisplay(&winfo, opt.nText, str2); - DBWriteContactSettingString(hContact, "UserInfo", "MyNotes", str2); - GetDisplay(&winfo, opt.xText, str2); - DBWriteContactSettingString(hContact, WEATHERCONDITION, "WeatherInfo", str2); - - // set the update tag - DBWriteContactSettingByte(hContact, WEATHERPROTONAME, "IsUpdated", TRUE); - - // save info for default weather condition - if (!strcmp(winfo.id, opt.Default) && !opt.NoProtoCondition) { - // save current condition for default station to be displayed after the update - old_status = status; - status = winfo.status; - // a workaround for a default station that currently have an n/a icon assigned - if (status == ID_STATUS_OFFLINE) status = NOSTATUSDATA; - ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); - } - - // logging - if (Ch) - { - // play the sound event - SkinPlaySound("weatherupdated"); - - if (DBGetContactSettingByte(hContact, WEATHERPROTONAME, "File", 0)) - { - // external log - if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Log",&dbv)) - { - // for the option for overwriting the file, delete old file first - if (DBGetContactSettingByte(hContact,WEATHERPROTONAME,"Overwrite",0)) - DeleteFile(dbv.pszVal); - // open the file and set point to the end of file - file = fopen( dbv.pszVal, "a"); - DBFreeVariant(&dbv); - if (file != NULL) - { - // write data to the file and close - GetDisplay(&winfo, opt.eText, str2); - fputs(str2, file); - fclose(file); - } - } - } - - if (DBGetContactSettingByte(hContact, WEATHERPROTONAME, "History", 0)) - { - DBEVENTINFO dbei = {0}; - // internal log using history - GetDisplay(&winfo, opt.hText, str2); - dbei.cbSize = sizeof(dbei); - dbei.szModule = WEATHERPROTONAME; - dbei.timestamp = (DWORD)time(NULL); - dbei.flags = DBEF_READ; - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = (DWORD)strlen(str2)+1; - dbei.pBlob = (PBYTE)str2; - - // add the history event - CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); - } - - // show the popup - NotifyEventHooks(hHookWeatherUpdated, (WPARAM)hContact, (LPARAM)Ch); - } - - Netlib_Logf(hNetlibUser, "Update Completed - Start to free memory"); - - // free memory - Netlib_Logf(hNetlibUser, logstr); - - // Update frame data - UpdateMwinData(hContact); - - // update brief info if its opened - hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); - if (hMoreDataDlg != NULL) PostMessage(hMoreDataDlg, WM_UPDATEDATA, 0, 0); - return 0; -} - -//============ UPDATE LIST ============ - -// a linked list queue for updating weather station -// this function add a weather contact to the end of queue for update -// hContact = current contact -void UpdateListAdd(HANDLE hContact) -{ - UPDATELIST *newItem; - - newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST)); - newItem->hContact = hContact; - newItem->next = NULL; - - WaitForSingleObject(hUpdateMutex, INFINITE); - - if (UpdateListTail == NULL) UpdateListHead = newItem; - else UpdateListTail->next = newItem; - UpdateListTail = newItem; - - ReleaseMutex(hUpdateMutex); -} - -// get the first item from the update queue and remove it from the queue -// return value = the contact for next update -HANDLE UpdateGetFirst() -{ - HANDLE hContact = NULL; - - WaitForSingleObject(hUpdateMutex, INFINITE); - - if (UpdateListHead != NULL) - { - UPDATELIST* Item = UpdateListHead; - - hContact = Item->hContact; - UpdateListHead = Item->next; - mir_free(Item); - - if (UpdateListHead == NULL) UpdateListTail = NULL; - } - - ReleaseMutex(hUpdateMutex); - - return hContact; -} - -void DestroyUpdateList(void) -{ - UPDATELIST *temp; - - WaitForSingleObject(hUpdateMutex, INFINITE); - - temp = UpdateListHead; - - // free the list one by one - while (temp != NULL) - { - UpdateListHead = temp->next; - mir_free(temp); - temp = UpdateListHead; - } - // make sure the entire list is clear - UpdateListTail = NULL; - - ReleaseMutex(hUpdateMutex); -} - - -//============ UPDATE WEATHER ============ - -// update all weather station -// AutoUpdate = true if it is from automatic update using timer -// false if it is from update by clicking the main menu -void UpdateAll(BOOL AutoUpdate, BOOL RemoveData) -{ - // add all weather contact to the update queue list - HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact != NULL) - { - if(IsMyContact(hContact)) - { - if (!DBGetContactSettingByte(hContact,WEATHERPROTONAME,"AutoUpdate",FALSE) || !AutoUpdate) - { - if (RemoveData) DBDataManage((HANDLE)hContact, WDBM_REMOVE, 0, 0); - UpdateListAdd(hContact); - } - } - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - - // if it is not updating, then start the update thread process - // if it is updating, the stations just added to the queue will get updated by the already-running process - if (!ThreadRunning) - mir_forkthread(UpdateThreadProc, NULL); -} - -// update a single station -// wParam = handle for the weather station that is going to be updated -INT_PTR UpdateSingleStation(WPARAM wParam, LPARAM lParam) -{ - if(IsMyContact((HANDLE)wParam)) - { - // add the station to the end of the update queue - UpdateListAdd((HANDLE)wParam); - - // if it is not updating, then start the update thread process - // if it is updating, the stations just added to the queue will get - // updated by the already-running process - if (!ThreadRunning) - mir_forkthread(UpdateThreadProc, NULL); - } - - return 0; -} - -// update a single station with removing the old data -// wParam = handle for the weather station that is going to be updated -INT_PTR UpdateSingleRemove(WPARAM wParam, LPARAM lParam) -{ - if(IsMyContact((HANDLE)wParam)) - { - // add the station to the end of the update queue, and also remove old data - DBDataManage((HANDLE)wParam, WDBM_REMOVE, 0, 0); - UpdateListAdd((HANDLE)wParam); - - // if it is not updating, then start the update thread process - // if it is updating, the stations just added to the queue will get updated by the already-running process - if (!ThreadRunning) - mir_forkthread(UpdateThreadProc, NULL); - } - - return 0; -} - -// update all weather thread -// this thread update each weather station from the queue -void UpdateThreadProc(LPVOID hWnd) -{ - WaitForSingleObject(hUpdateMutex, INFINITE); - if (ThreadRunning) - { - ReleaseMutex(hUpdateMutex); - return; - } - ThreadRunning = TRUE; // prevent 2 instance of this thread running - ReleaseMutex(hUpdateMutex); - - // update weather by getting the first station from the queue until the queue is empty - while (UpdateListHead != NULL && !Miranda_Terminated()) - UpdateWeather(UpdateGetFirst()); - - NetlibHttpDisconnect(); - - // exit the update thread - ThreadRunning = FALSE; -} - -// the "Update All" menu item in main menu -INT_PTR UpdateAllInfo(WPARAM wParam,LPARAM lParam) -{ - if (!ThreadRunning) UpdateAll(FALSE, FALSE); - return 0; -} - -// the "Update All" menu item in main menu and remove the old data -INT_PTR UpdateAllRemove(WPARAM wParam,LPARAM lParam) { - if (!ThreadRunning) UpdateAll(FALSE, TRUE); - return 0; -} - -//============ GETTING WEATHER DATA ============ - -// getting weather data and save them into the database -// hContact = the contact to get the data -int GetWeatherData(HANDLE hContact) -{ - char *loc, id[256], Svc[256], DataValue[MAX_DATA_LEN], *szData = NULL, *szInfo; - int retval, i; - WIDATAITEMLIST* Item; - WIDATA *Data; - WORD cond = NA; - - // get eacnh part of the id's - GetStationID(hContact, id, sizeof(id)); - - // test ID format - loc = strchr(id, '/'); - if (loc == NULL) return INVALID_ID_FORMAT; - - GetID(id); - GetStationID(hContact, Svc, sizeof(Svc)); - GetSvc(Svc); - - // check for invalid station - if (id[0] == 0) return INVALID_ID; - if (Svc[0] == 0) return INVALID_SVC; - - // get the update strings (loaded to memory from ini files) - Data = GetWIData(Svc); - if (Data == NULL) return SVC_NOT_FOUND; // the ini for the station cannot be found - - for (i=0; i<4; ++i) - { - // generate update URL - switch(i) - { - case 0: - loc = (char*)mir_alloc(strlen(Data->UpdateURL)+128); - wsprintf(loc, Data->UpdateURL, id); - break; - - case 1: - loc = (char*)mir_alloc(strlen(Data->UpdateURL2)+128); - wsprintf(loc, Data->UpdateURL2, id); - break; - - case 2: - loc = (char*)mir_alloc(strlen(Data->UpdateURL3)+128); - wsprintf(loc, Data->UpdateURL3, id); - break; - - case 3: - loc = (char*)mir_alloc(strlen(Data->UpdateURL4)+128); - wsprintf(loc, Data->UpdateURL4, id); - break; - } - - if (loc[0] == 0) - { - mir_free(loc); - continue; - } - - // download the html file from the internet - retval = InternetDownloadFile(loc, Data->Cookie, &szData); - mir_free(loc); - - if (retval != 0) - { - mir_free(szData); - return retval; - } - else if (strstr(szData, "Document Not Found") != NULL) { - mir_free(szData); - return DOC_NOT_FOUND; - } - - szInfo = szData; - - Item = Data->UpdateData; - - // begin parsing item by item - while (Item != NULL) - { - if (Item->Item.Url[0] != 0 && Item->Item.Url[0] != (i + '1')) - { - Item = Item->Next; - continue; - } - - switch (Item->Item.Type) - { - case WID_NORMAL: - // if it is a normal item with start= and end=, then parse through the downloaded string - // to get a data value. - GetDataValue(&Item->Item, DataValue, &szInfo); - if (strcmp(Item->Item.Name, "Condition") && _stricmp(Item->Item.Unit, "Cond")) - strcpy(DataValue, Translate(DataValue)); - break; - - case WID_SET: - { - // for the "Set Data=" operation - DBVARIANT dbv; - char *chop, *str, str2[MAX_DATA_LEN]; - BOOL hasvar = FALSE; - size_t stl; - - // get the set data operation string - str = Item->Item.End; - DataValue[0] = 0; - // go through each part of the operation string seperated by the & operator - do { - chop = strstr(str, " & "); - // the end of the string, last item - if (chop == NULL) chop = strchr(str, '\0'); - - stl = min(sizeof(str2)-1, (unsigned)(chop-str-2)); - strncpy(str2, str+1, stl); - str2[stl] = 0; - - switch(str[0]) - { - case '[': // variable, add the value to the result string - hasvar = TRUE; - if (!DBGetData(hContact, str2, &dbv)) - { - strncat(DataValue, dbv.pszVal, sizeof(DataValue)-strlen(DataValue)); - DataValue[sizeof(DataValue)-1]=0; - DBFreeVariant(&dbv); - } - break; - - case'\"': // constant, add it to the result string - strncat(DataValue, Translate(str2), sizeof(DataValue)-strlen(DataValue)); - DataValue[sizeof(DataValue)-1]=0; - break; - } - - // remove the front part of the string that is done and continue parsing - str = chop + 3; - } while (chop[0] && str[0]); - - if (!hasvar) ConvertDataValue(&Item->Item, DataValue); - break; - } - case WID_BREAK: - { - // for the "Break Data=" operation - char *end; - DBVARIANT dbv; - if (!DBGetData(hContact, Item->Item.Start, &dbv)) - { - strncpy(DataValue, dbv.pszVal, sizeof(DataValue)); - DataValue[sizeof(DataValue)-1] = 0; - DBFreeVariant(&dbv); - } - else - { - DataValue[0] = 0; - break; // do not continue if the source is invalid - } - - // generate the strings - end = strstr(DataValue, Item->Item.Break); - if (end == NULL) - { - DataValue[0] = 0; - break; // exit if break string is not found - } - *end = '\0'; - end+=strlen(Item->Item.Break); - while (end[0] == ' ') end++; // remove extra space - - ConvertDataValue(&Item->Item, DataValue); - - // write the 2 strings created from the break operation -// DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, DataValue); - if (Item->Item.End[0]) - DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.End, end); - break; - } - } - - // don't store data if it is not available - if ((DataValue[0] != 0 && strcmp(DataValue, NODATA) && - strcmp(DataValue, Translate(NODATA)) && strcmp(Item->Item.Name, "Ignore")) || - (!strcmp(Item->Item.Name, "Alert") && i == 0)) - { - // temporary workaround for mToolTip to show feel-like temperature - if (!strcmp(Item->Item.Name, "Feel")) - DBWriteContactSettingString(hContact, WEATHERCONDITION, "Heat Index", DataValue); - GetStationID(hContact, Svc, sizeof(Svc)); - if (strcmp(Svc, opt.Default) == 0) - DBWriteContactSettingString(NULL, DEFCURRENTWEATHER, Item->Item.Name, DataValue); - if (strcmp(Item->Item.Name, "Condition") == 0) - { - char buf[128], *cbuf; - mir_snprintf(buf, sizeof(buf), "#%s Weather", DataValue); - cbuf = Translate(buf); - if (cbuf[0] == '#') - cbuf = Translate(DataValue); - DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, cbuf); - CharLowerBuff(DataValue, (int)strlen(DataValue)); - cond = GetIcon(DataValue, Data); - } - else if (_stricmp(Item->Item.Unit, "Cond") == 0) - { - char buf[128], *cbuf; - mir_snprintf(buf, sizeof(buf), "#%s Weather", DataValue); - cbuf = Translate(buf); - if (cbuf[0] == '#') - cbuf = Translate(DataValue); - DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, cbuf); - } - else - DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, DataValue); - } - Item = Item->Next; - } - mir_free(szData); - } - - // assign condition icon - DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", cond); - DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MirVer", Data->DisplayName); - - return 0; -} - -//============ UPDATE TIMERS ============ - -// main auto-update timer -void CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) -{ - // only run if it is not current updating and the auto update option is enabled - if (!ThreadRunning && opt.CAutoUpdate && !Miranda_Terminated() && - (!opt.NoProtoCondition || status == ID_STATUS_ONLINE)) - UpdateAll(TRUE, FALSE); -} - -// temporary timer for first run -// when this is run, it kill the old startup timer and create the permenant one above -void CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) -{ - KillTimer(NULL, timerId); - ThreadRunning = FALSE; - - if (!Miranda_Terminated()) - { - if (opt.StartupUpdate && !opt.NoProtoCondition) - UpdateAll(FALSE, FALSE); - timerId = SetTimer(NULL, 0, ((int)opt.UpdateTime)*60000, (TIMERPROC)timerProc); - } -} - diff --git a/protocols/weather/weather_update.cpp b/protocols/weather/weather_update.cpp new file mode 100644 index 0000000000..9b81b023f5 --- /dev/null +++ b/protocols/weather/weather_update.cpp @@ -0,0 +1,678 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +This file contain the source related to updating new weather +information, both automatic (by timer) and manually (by selecting +menu items). +*/ + +#include "weather.h" + +UPDATELIST *UpdateListHead; +UPDATELIST *UpdateListTail; + +extern HANDLE hUpdateMutex; + +//============ RETRIEVE NEW WEATHER ============ + +// retrieve weather info and display / log them +// hContact = current contact +int UpdateWeather(HANDLE hContact) +{ + char str[256], str2[MAX_TEXT_SIZE], logstr[256]; + int code; + FILE *file; + DBVARIANT dbv; + BOOL Ch = FALSE; + WEATHERINFO winfo; + HWND hMoreDataDlg; + int dbres; + + if (hContact == NULL) return 1; // some error prevention + + dbv.pszVal = ""; + + // log to netlib log for debug purpose + Netlib_Logf(hNetlibUser, "************************************************************************"); + dbres = DBGetContactSettingString(hContact, WEATHERPROTONAME, "Nick", &dbv); + + Netlib_Logf(hNetlibUser, "<-- Start update for station: %s -->", dbv.pszVal); + mir_snprintf(logstr, sizeof(logstr), "<-- Update successful for station: %s -->", dbv.pszVal); + + // download the info and parse it + // result are stored in database + code = GetWeatherData(hContact); + if (code != 0) + { + // error occurs if the return value is not equals to 0 + if (opt.ShowWarnings) + { // show warnings by popup + mir_snprintf(str, sizeof(str)-105, + Translate("Unable to retrieve weather information for %s"), dbv.pszVal); + strcat(str, "\n"); + strcat(str, GetError(code)); + WPShowMessage(str, SM_WARNING); + } + // log to netlib + Netlib_Logf(hNetlibUser, "Error! Update cannot continue... Start to free memory"); + Netlib_Logf(hNetlibUser, "<-- Error occurs while updating station: %s -->", dbv.pszVal); + if (!dbres) DBFreeVariant(&dbv); + return 1; + } + if (!dbres) DBFreeVariant(&dbv); + + // initialize, load new weather Data + winfo = LoadWeatherInfo(hContact); + + // translate weather condition + strcpy(winfo.cond, Translate(winfo.cond)); + + // compare the old condition and determine if the weather had changed + if (opt.UpdateOnlyConditionChanged) // consider condition change + { + if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", &dbv)) + { + if (_stricmp(winfo.cond, dbv.pszVal)) Ch = TRUE; // the weather condition is changed + DBFreeVariant(&dbv); + } + else Ch = TRUE; + if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", &dbv)) + { + if (_stricmp(winfo.temp, dbv.pszVal)) Ch = TRUE; // the temperature is changed + DBFreeVariant(&dbv); + } + else Ch = TRUE; + } + else // consider update time change + { + if (!DBGetContactSettingString(hContact, WEATHERPROTONAME, "LastUpdate", &dbv)) + { + if (_stricmp(winfo.update, dbv.pszVal)) Ch = TRUE; // the update time is changed + DBFreeVariant(&dbv); + } + else Ch = TRUE; + } + + // have weather alert issued? + dbres = DBGetContactSettingString(hContact, WEATHERCONDITION, "Alert", &dbv); + if (!dbres && dbv.pszVal[0] != 0) + { + if (opt.AlertPopup && !DBGetContactSettingByte(hContact, WEATHERPROTONAME, "DPopUp", 0) && Ch) + { + // display alert popup + wsprintf(str, "Alert for %s%c%s", winfo.city, 255, dbv.pszVal); + WPShowMessage(str, SM_WEATHERALERT); + } + // alert issued, set display to italic + if (opt.MakeItalic) + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "ApparentMode", ID_STATUS_OFFLINE); + SkinPlaySound("weatheralert"); + } + // alert dropped, set the display back to normal + else DBDeleteContactSetting(hContact, WEATHERPROTONAME, "ApparentMode"); + if (!dbres) DBFreeVariant(&dbv); + + // backup current condition for checking if the weather is changed or not + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastLog", winfo.update); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastCondition", winfo.cond); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastTemperature", winfo.temp); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "LastUpdate", winfo.update); + + // display condition on contact list + if (opt.DisCondIcon && winfo.status != ID_STATUS_OFFLINE) + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", ID_STATUS_ONLINE); + else + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "Status", winfo.status); + AvatarDownloaded(hContact); + + GetDisplay(&winfo, opt.cText, str2); + if (lpcp != CP_ACP) + { + LPWSTR m_psz = ConvToUnicode(str2); + DBWriteContactSettingWString(hContact, "CList", "MyHandle", m_psz); + mir_free(m_psz); + } + else + DBWriteContactSettingString(hContact, "CList", "MyHandle", str2); + + GetDisplay(&winfo, opt.sText, str2); + if (str2[0]) + { + if (lpcp != CP_ACP) + { + wchar_t* m_psz = ConvToUnicode(str2); + DBWriteContactSettingWString(hContact, "CList", "StatusMsg", m_psz); + mir_free(m_psz); + } + else + DBWriteContactSettingString(hContact, "CList", "StatusMsg", str2); + } + else + DBDeleteContactSetting(hContact, "CList", "StatusMsg"); + + ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, NULL, (LPARAM)(str2[0] ? str2 : 0)); + + // save descriptions in MyNotes + GetDisplay(&winfo, opt.nText, str2); + DBWriteContactSettingString(hContact, "UserInfo", "MyNotes", str2); + GetDisplay(&winfo, opt.xText, str2); + DBWriteContactSettingString(hContact, WEATHERCONDITION, "WeatherInfo", str2); + + // set the update tag + DBWriteContactSettingByte(hContact, WEATHERPROTONAME, "IsUpdated", TRUE); + + // save info for default weather condition + if (!strcmp(winfo.id, opt.Default) && !opt.NoProtoCondition) { + // save current condition for default station to be displayed after the update + old_status = status; + status = winfo.status; + // a workaround for a default station that currently have an n/a icon assigned + if (status == ID_STATUS_OFFLINE) status = NOSTATUSDATA; + ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); + } + + // logging + if (Ch) + { + // play the sound event + SkinPlaySound("weatherupdated"); + + if (DBGetContactSettingByte(hContact, WEATHERPROTONAME, "File", 0)) + { + // external log + if (!DBGetContactSettingString(hContact,WEATHERPROTONAME,"Log",&dbv)) + { + // for the option for overwriting the file, delete old file first + if (DBGetContactSettingByte(hContact,WEATHERPROTONAME,"Overwrite",0)) + DeleteFile(dbv.pszVal); + // open the file and set point to the end of file + file = fopen( dbv.pszVal, "a"); + DBFreeVariant(&dbv); + if (file != NULL) + { + // write data to the file and close + GetDisplay(&winfo, opt.eText, str2); + fputs(str2, file); + fclose(file); + } + } + } + + if (DBGetContactSettingByte(hContact, WEATHERPROTONAME, "History", 0)) + { + DBEVENTINFO dbei = {0}; + // internal log using history + GetDisplay(&winfo, opt.hText, str2); + dbei.cbSize = sizeof(dbei); + dbei.szModule = WEATHERPROTONAME; + dbei.timestamp = (DWORD)time(NULL); + dbei.flags = DBEF_READ; + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = (DWORD)strlen(str2)+1; + dbei.pBlob = (PBYTE)str2; + + // add the history event + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); + } + + // show the popup + NotifyEventHooks(hHookWeatherUpdated, (WPARAM)hContact, (LPARAM)Ch); + } + + Netlib_Logf(hNetlibUser, "Update Completed - Start to free memory"); + + // free memory + Netlib_Logf(hNetlibUser, logstr); + + // Update frame data + UpdateMwinData(hContact); + + // update brief info if its opened + hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); + if (hMoreDataDlg != NULL) PostMessage(hMoreDataDlg, WM_UPDATEDATA, 0, 0); + return 0; +} + +//============ UPDATE LIST ============ + +// a linked list queue for updating weather station +// this function add a weather contact to the end of queue for update +// hContact = current contact +void UpdateListAdd(HANDLE hContact) +{ + UPDATELIST *newItem; + + newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST)); + newItem->hContact = hContact; + newItem->next = NULL; + + WaitForSingleObject(hUpdateMutex, INFINITE); + + if (UpdateListTail == NULL) UpdateListHead = newItem; + else UpdateListTail->next = newItem; + UpdateListTail = newItem; + + ReleaseMutex(hUpdateMutex); +} + +// get the first item from the update queue and remove it from the queue +// return value = the contact for next update +HANDLE UpdateGetFirst() +{ + HANDLE hContact = NULL; + + WaitForSingleObject(hUpdateMutex, INFINITE); + + if (UpdateListHead != NULL) + { + UPDATELIST* Item = UpdateListHead; + + hContact = Item->hContact; + UpdateListHead = Item->next; + mir_free(Item); + + if (UpdateListHead == NULL) UpdateListTail = NULL; + } + + ReleaseMutex(hUpdateMutex); + + return hContact; +} + +void DestroyUpdateList(void) +{ + UPDATELIST *temp; + + WaitForSingleObject(hUpdateMutex, INFINITE); + + temp = UpdateListHead; + + // free the list one by one + while (temp != NULL) + { + UpdateListHead = temp->next; + mir_free(temp); + temp = UpdateListHead; + } + // make sure the entire list is clear + UpdateListTail = NULL; + + ReleaseMutex(hUpdateMutex); +} + + +//============ UPDATE WEATHER ============ + +// update all weather station +// AutoUpdate = true if it is from automatic update using timer +// false if it is from update by clicking the main menu +void UpdateAll(BOOL AutoUpdate, BOOL RemoveData) +{ + // add all weather contact to the update queue list + HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL) + { + if(IsMyContact(hContact)) + { + if (!DBGetContactSettingByte(hContact,WEATHERPROTONAME,"AutoUpdate",FALSE) || !AutoUpdate) + { + if (RemoveData) DBDataManage((HANDLE)hContact, WDBM_REMOVE, 0, 0); + UpdateListAdd(hContact); + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + + // if it is not updating, then start the update thread process + // if it is updating, the stations just added to the queue will get updated by the already-running process + if (!ThreadRunning) + mir_forkthread(UpdateThreadProc, NULL); +} + +// update a single station +// wParam = handle for the weather station that is going to be updated +INT_PTR UpdateSingleStation(WPARAM wParam, LPARAM lParam) +{ + if(IsMyContact((HANDLE)wParam)) + { + // add the station to the end of the update queue + UpdateListAdd((HANDLE)wParam); + + // if it is not updating, then start the update thread process + // if it is updating, the stations just added to the queue will get + // updated by the already-running process + if (!ThreadRunning) + mir_forkthread(UpdateThreadProc, NULL); + } + + return 0; +} + +// update a single station with removing the old data +// wParam = handle for the weather station that is going to be updated +INT_PTR UpdateSingleRemove(WPARAM wParam, LPARAM lParam) +{ + if(IsMyContact((HANDLE)wParam)) + { + // add the station to the end of the update queue, and also remove old data + DBDataManage((HANDLE)wParam, WDBM_REMOVE, 0, 0); + UpdateListAdd((HANDLE)wParam); + + // if it is not updating, then start the update thread process + // if it is updating, the stations just added to the queue will get updated by the already-running process + if (!ThreadRunning) + mir_forkthread(UpdateThreadProc, NULL); + } + + return 0; +} + +// update all weather thread +// this thread update each weather station from the queue +void UpdateThreadProc(LPVOID hWnd) +{ + WaitForSingleObject(hUpdateMutex, INFINITE); + if (ThreadRunning) + { + ReleaseMutex(hUpdateMutex); + return; + } + ThreadRunning = TRUE; // prevent 2 instance of this thread running + ReleaseMutex(hUpdateMutex); + + // update weather by getting the first station from the queue until the queue is empty + while (UpdateListHead != NULL && !Miranda_Terminated()) + UpdateWeather(UpdateGetFirst()); + + NetlibHttpDisconnect(); + + // exit the update thread + ThreadRunning = FALSE; +} + +// the "Update All" menu item in main menu +INT_PTR UpdateAllInfo(WPARAM wParam,LPARAM lParam) +{ + if (!ThreadRunning) UpdateAll(FALSE, FALSE); + return 0; +} + +// the "Update All" menu item in main menu and remove the old data +INT_PTR UpdateAllRemove(WPARAM wParam,LPARAM lParam) { + if (!ThreadRunning) UpdateAll(FALSE, TRUE); + return 0; +} + +//============ GETTING WEATHER DATA ============ + +// getting weather data and save them into the database +// hContact = the contact to get the data +int GetWeatherData(HANDLE hContact) +{ + char *loc, id[256], Svc[256], DataValue[MAX_DATA_LEN], *szData = NULL, *szInfo; + int retval, i; + WIDATAITEMLIST* Item; + WIDATA *Data; + WORD cond = NA; + + // get eacnh part of the id's + GetStationID(hContact, id, sizeof(id)); + + // test ID format + loc = strchr(id, '/'); + if (loc == NULL) return INVALID_ID_FORMAT; + + GetID(id); + GetStationID(hContact, Svc, sizeof(Svc)); + GetSvc(Svc); + + // check for invalid station + if (id[0] == 0) return INVALID_ID; + if (Svc[0] == 0) return INVALID_SVC; + + // get the update strings (loaded to memory from ini files) + Data = GetWIData(Svc); + if (Data == NULL) return SVC_NOT_FOUND; // the ini for the station cannot be found + + for (i=0; i<4; ++i) + { + // generate update URL + switch(i) + { + case 0: + loc = (char*)mir_alloc(strlen(Data->UpdateURL)+128); + wsprintf(loc, Data->UpdateURL, id); + break; + + case 1: + loc = (char*)mir_alloc(strlen(Data->UpdateURL2)+128); + wsprintf(loc, Data->UpdateURL2, id); + break; + + case 2: + loc = (char*)mir_alloc(strlen(Data->UpdateURL3)+128); + wsprintf(loc, Data->UpdateURL3, id); + break; + + case 3: + loc = (char*)mir_alloc(strlen(Data->UpdateURL4)+128); + wsprintf(loc, Data->UpdateURL4, id); + break; + } + + if (loc[0] == 0) + { + mir_free(loc); + continue; + } + + // download the html file from the internet + retval = InternetDownloadFile(loc, Data->Cookie, &szData); + mir_free(loc); + + if (retval != 0) + { + mir_free(szData); + return retval; + } + else if (strstr(szData, "Document Not Found") != NULL) { + mir_free(szData); + return DOC_NOT_FOUND; + } + + szInfo = szData; + + Item = Data->UpdateData; + + // begin parsing item by item + while (Item != NULL) + { + if (Item->Item.Url[0] != 0 && Item->Item.Url[0] != (i + '1')) + { + Item = Item->Next; + continue; + } + + switch (Item->Item.Type) + { + case WID_NORMAL: + // if it is a normal item with start= and end=, then parse through the downloaded string + // to get a data value. + GetDataValue(&Item->Item, DataValue, &szInfo); + if (strcmp(Item->Item.Name, "Condition") && _stricmp(Item->Item.Unit, "Cond")) + strcpy(DataValue, Translate(DataValue)); + break; + + case WID_SET: + { + // for the "Set Data=" operation + DBVARIANT dbv; + char *chop, *str, str2[MAX_DATA_LEN]; + BOOL hasvar = FALSE; + size_t stl; + + // get the set data operation string + str = Item->Item.End; + DataValue[0] = 0; + // go through each part of the operation string seperated by the & operator + do { + chop = strstr(str, " & "); + // the end of the string, last item + if (chop == NULL) chop = strchr(str, '\0'); + + stl = min(sizeof(str2)-1, (unsigned)(chop-str-2)); + strncpy(str2, str+1, stl); + str2[stl] = 0; + + switch(str[0]) + { + case '[': // variable, add the value to the result string + hasvar = TRUE; + if (!DBGetData(hContact, str2, &dbv)) + { + strncat(DataValue, dbv.pszVal, sizeof(DataValue)-strlen(DataValue)); + DataValue[sizeof(DataValue)-1]=0; + DBFreeVariant(&dbv); + } + break; + + case'\"': // constant, add it to the result string + strncat(DataValue, Translate(str2), sizeof(DataValue)-strlen(DataValue)); + DataValue[sizeof(DataValue)-1]=0; + break; + } + + // remove the front part of the string that is done and continue parsing + str = chop + 3; + } while (chop[0] && str[0]); + + if (!hasvar) ConvertDataValue(&Item->Item, DataValue); + break; + } + case WID_BREAK: + { + // for the "Break Data=" operation + char *end; + DBVARIANT dbv; + if (!DBGetData(hContact, Item->Item.Start, &dbv)) + { + strncpy(DataValue, dbv.pszVal, sizeof(DataValue)); + DataValue[sizeof(DataValue)-1] = 0; + DBFreeVariant(&dbv); + } + else + { + DataValue[0] = 0; + break; // do not continue if the source is invalid + } + + // generate the strings + end = strstr(DataValue, Item->Item.Break); + if (end == NULL) + { + DataValue[0] = 0; + break; // exit if break string is not found + } + *end = '\0'; + end+=strlen(Item->Item.Break); + while (end[0] == ' ') end++; // remove extra space + + ConvertDataValue(&Item->Item, DataValue); + + // write the 2 strings created from the break operation +// DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, DataValue); + if (Item->Item.End[0]) + DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.End, end); + break; + } + } + + // don't store data if it is not available + if ((DataValue[0] != 0 && strcmp(DataValue, NODATA) && + strcmp(DataValue, Translate(NODATA)) && strcmp(Item->Item.Name, "Ignore")) || + (!strcmp(Item->Item.Name, "Alert") && i == 0)) + { + // temporary workaround for mToolTip to show feel-like temperature + if (!strcmp(Item->Item.Name, "Feel")) + DBWriteContactSettingString(hContact, WEATHERCONDITION, "Heat Index", DataValue); + GetStationID(hContact, Svc, sizeof(Svc)); + if (strcmp(Svc, opt.Default) == 0) + DBWriteContactSettingString(NULL, DEFCURRENTWEATHER, Item->Item.Name, DataValue); + if (strcmp(Item->Item.Name, "Condition") == 0) + { + char buf[128], *cbuf; + mir_snprintf(buf, sizeof(buf), "#%s Weather", DataValue); + cbuf = Translate(buf); + if (cbuf[0] == '#') + cbuf = Translate(DataValue); + DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, cbuf); + CharLowerBuff(DataValue, (int)strlen(DataValue)); + cond = GetIcon(DataValue, Data); + } + else if (_stricmp(Item->Item.Unit, "Cond") == 0) + { + char buf[128], *cbuf; + mir_snprintf(buf, sizeof(buf), "#%s Weather", DataValue); + cbuf = Translate(buf); + if (cbuf[0] == '#') + cbuf = Translate(DataValue); + DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, cbuf); + } + else + DBWriteContactSettingString(hContact, WEATHERCONDITION, Item->Item.Name, DataValue); + } + Item = Item->Next; + } + mir_free(szData); + } + + // assign condition icon + DBWriteContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", cond); + DBWriteContactSettingString(hContact, WEATHERPROTONAME, "MirVer", Data->DisplayName); + + return 0; +} + +//============ UPDATE TIMERS ============ + +// main auto-update timer +void CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + // only run if it is not current updating and the auto update option is enabled + if (!ThreadRunning && opt.CAutoUpdate && !Miranda_Terminated() && + (!opt.NoProtoCondition || status == ID_STATUS_ONLINE)) + UpdateAll(TRUE, FALSE); +} + +// temporary timer for first run +// when this is run, it kill the old startup timer and create the permenant one above +void CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + KillTimer(NULL, timerId); + ThreadRunning = FALSE; + + if (!Miranda_Terminated()) + { + if (opt.StartupUpdate && !opt.NoProtoCondition) + UpdateAll(FALSE, FALSE); + timerId = SetTimer(NULL, 0, ((int)opt.UpdateTime)*60000, (TIMERPROC)timerProc); + } +} + diff --git a/protocols/weather/weather_userinfo.c b/protocols/weather/weather_userinfo.c deleted file mode 100644 index 2addea14da..0000000000 --- a/protocols/weather/weather_userinfo.c +++ /dev/null @@ -1,418 +0,0 @@ -/* -Weather Protocol plugin for Miranda IM -Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved -Copyright (C) 2002-2005 Calvin Che - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - - -/* -This file contain the source that is related to display contact -information, including the one shows in user detail and the brief -information -*/ - -#include "weather.h" - -extern INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -//============ CONTACT INFORMATION ============ - -// initialize user info -// lParam = current contact -int UserInfoInit(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = {0}; - - odp.cbSize = sizeof(odp); - odp.hInstance = hInst; - odp.position = 100000000; - odp.pszTitle = LPGEN(WEATHERPROTONAME); - - if (lParam == 0) - { - odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO); - odp.pfnDlgProc = DlgProcINIPage; - CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); - } - else - { - // check if it is a weather contact - if(IsMyContact((HANDLE)lParam)) - { - // register the contact info page - odp.pszTemplate = MAKEINTRESOURCE(IDD_USERINFO); - odp.pfnDlgProc = DlgProcUIPage; - odp.flags = ODPF_BOLDGROUPS; - CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); - } - } - - return 0; -} - -// dialog process for the weather tab under user info -// lParam = current contact -INT_PTR CALLBACK DlgProcUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WEATHERINFO w; - char str[MAX_TEXT_SIZE]; - HANDLE hContact; - - hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - switch (msg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - SendMessage(GetDlgItem(hwndDlg,IDC_MOREDETAIL), BUTTONSETASFLATBTN, 0, 0); - // save the contact handle for later use - hContact = (HANDLE)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact); - // load weather info for the contact - w = LoadWeatherInfo((HANDLE)lParam); - SetDlgItemTextWth(hwndDlg, IDC_INFO1, GetDisplay(&w, Translate("Current condition for %n"), str)); - - SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON, - (WPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME, - DBGetContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon",0)), 0); - - { // bold and enlarge the current condition - LOGFONT lf; - HFONT hNormalFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_INFO2,WM_GETFONT,0,0); - GetObject(hNormalFont,sizeof(lf),&lf); - lf.lfWeight=FW_BOLD; - lf.lfWidth=7; - lf.lfHeight=15; - SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0); - } - // set the text for displaying other current weather conditions data - GetDisplay(&w, "%c %t", str); - SetDlgItemTextWth(hwndDlg, IDC_INFO2, str); - SetDlgItemTextWth(hwndDlg, IDC_INFO3, w.feel); - SetDlgItemTextWth(hwndDlg, IDC_INFO4, w.pressure); - GetDisplay(&w, "%i %w", str); - SetDlgItemTextWth(hwndDlg, IDC_INFO5, str); - SetDlgItemTextWth(hwndDlg, IDC_INFO6, w.dewpoint); - SetDlgItemTextWth(hwndDlg, IDC_INFO7, w.sunrise); - SetDlgItemTextWth(hwndDlg, IDC_INFO8, w.sunset); - SetDlgItemTextWth(hwndDlg, IDC_INFO9, w.high); - SetDlgItemTextWth(hwndDlg, IDC_INFO10, w.low); - GetDisplay(&w, Translate("Last update on: %u"), str); - SetDlgItemTextWth(hwndDlg, IDC_INFO11, str); - SetDlgItemTextWth(hwndDlg, IDC_INFO12, w.humid); - SetDlgItemTextWth(hwndDlg, IDC_INFO13, w.vis); - break; - - case WM_DESTROY: - CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON, 0, 0), 0); - DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_GETFONT, 0, 0)); - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_MOREDETAIL: - { - HWND hMoreDataDlg; - - hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); - if (hMoreDataDlg == NULL) - hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL, - DlgProcMoreData, (LPARAM)hContact); - else - { - SetForegroundWindow(hMoreDataDlg); - SetFocus(hMoreDataDlg); - } - ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 0); - ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 1); - break; - } - } - break; - } - return 0; -} - -//============ BRIEF INFORMATION ============ - -static int BriefDlgResizer(HWND hwnd, LPARAM lParam, UTILRESIZECONTROL *urc) -{ - switch(urc->wId) - { - case IDC_HEADERBAR: - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH; - - case IDC_MTEXT: - case IDC_DATALIST: - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - - case IDC_MUPDATE: - return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; - - case IDC_MTOGGLE: - case IDC_MWEBPAGE: - case IDCANCEL: - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - } - return RD_ANCHORX_LEFT|RD_ANCHORY_TOP; -} - - - -// dialog process for more data in the user info window -// lParam = contact handle -INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static const unsigned tabstops = 48; - HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - switch (msg) - { - case WM_INITDIALOG: - // save the contact handle for later use - hContact = (HANDLE)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact); - - SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETEVENTMASK, 0, ENM_LINK); - SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETMARGINS, EC_LEFTMARGIN, 5); - SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETTABSTOPS, 1, (LPARAM)&tabstops); - - // get the list to display - { - LV_COLUMN lvc = { 0 }; - HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); - RECT aRect = { 0 }; - GetClientRect(hList, &aRect); - - // managing styles - lvc.mask = LVCF_WIDTH | LVCF_TEXT; - ListView_SetExtendedListViewStyleEx(hList, - LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, - LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); - - // inserting columns - lvc.cx = LIST_COLUMN; - lvc.pszText = Translate("Variable"); - ListView_InsertColumnWth(hList, 0, &lvc); - - lvc.cx = aRect.right - LIST_COLUMN - GetSystemMetrics(SM_CXVSCROLL) - 3; - lvc.pszText = Translate("Information"); - ListView_InsertColumnWth(hList, 1, &lvc); - - // inserting data - SendMessage(hwndDlg, WM_UPDATEDATA, 0, 0); - } - TranslateDialogDefault(hwndDlg); - - // prevent dups of the window - WindowList_Add(hDataWindowList, hwndDlg, hContact); - - // restore window position - Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_"); - return TRUE; - - case WM_UPDATEDATA: - ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_DATALIST)); - LoadBriefInfoText(hwndDlg, hContact); - DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)hwndDlg, 0); - - // set icons - { - WORD statusIcon = DBGetContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", 0); - - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon))); - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon))); - } - RedrawWindow(GetDlgItem(hwndDlg, IDC_HEADERBAR), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - break; - - case WM_SIZE: - { - RECT rc; - HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); - GetWindowRect(hList, &rc); - ListView_SetColumnWidth(hList, 1, ListView_GetColumnWidth(hList, 1) + - (int)LOWORD(lParam) - (rc.right - rc.left)); - } - { - UTILRESIZEDIALOG urd = {0}; - urd.cbSize = sizeof(urd); - urd.hwndDlg = hwndDlg; - urd.hInstance = hInst; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_BRIEF); - urd.pfnResizer = BriefDlgResizer; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); - } - break; - - case WM_GETMINMAXINFO: - { - LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - - // The minimum width in points - mmi->ptMinTrackSize.x = 350; - // The minimum height in points - mmi->ptMinTrackSize.y = 300; - } - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDCANCEL: - // close the info window - DestroyWindow(hwndDlg); - break; - - case IDC_MUPDATE: - { - LV_ITEM lvi = {0}; - HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); - - // update current data - // set the text to "updating" - SetDlgItemTextWth(hwndDlg, IDC_MTEXT, Translate("Retrieving new data, please wait...")); - ListView_DeleteAllItems(hList); - lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.lParam = 1; - lvi.pszText = (LPSTR)""; - lvi.iItem = ListView_InsertItemWth(hList, &lvi); - lvi.pszText = Translate("Retrieving new data, please wait..."); - ListView_SetItemTextWth(hList, lvi.iItem, 1, lvi.pszText); - UpdateSingleStation((WPARAM)hContact, 0); - break; - } - - case IDC_MWEBPAGE: - LoadForecast((WPARAM)hContact, 0); // read complete forecast - break; - - case IDC_MTOGGLE: - if (IsWindowVisible(GetDlgItem(hwndDlg,IDC_DATALIST))) - SetDlgItemTextWth(hwndDlg, IDC_MTOGGLE, Translate("More Info")); - else - SetDlgItemTextWth(hwndDlg, IDC_MTOGGLE, Translate("Brief Info")); - ShowWindow(GetDlgItem(hwndDlg,IDC_DATALIST), (int)!IsWindowVisible( - GetDlgItem(hwndDlg,IDC_DATALIST))); - ShowWindow(GetDlgItem(hwndDlg,IDC_MTEXT), (int)!IsWindowVisible(GetDlgItem(hwndDlg,IDC_MTEXT))); - break; - } - break; - - case WM_NOTIFY: - { - LPNMHDR pNmhdr = (LPNMHDR)lParam; - if (pNmhdr->idFrom == IDC_MTEXT && pNmhdr->code == EN_LINK) - { - ENLINK *enlink = (ENLINK *) lParam; - TEXTRANGE tr; - switch (enlink->msg) - { - case WM_LBUTTONUP: - tr.chrg = enlink->chrg; - tr.lpstrText = mir_alloc(tr.chrg.cpMax - tr.chrg.cpMin + 8); - SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText); - mir_free(tr.lpstrText); - break; - } - } - break; - } - - case WM_CLOSE: - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); - ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); - - Utils_SaveWindowPosition(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_"); - WindowList_Remove(hDataWindowList, hwndDlg); - break; - } - - return FALSE; -} - -// set the title of the dialog and on the which rectangle -// also load brief info into message box -void LoadBriefInfoText(HWND hwndDlg, HANDLE hContact) -{ - WEATHERINFO winfo; - char str[4096], str2[4096]; - - // load weather information from the contact into the WEATHERINFO struct - winfo = LoadWeatherInfo(hContact); - // check if data exist. If not, display error message box - if (!(BOOL)DBGetContactSettingByte(hContact, WEATHERPROTONAME, "IsUpdated", FALSE)) - { - strcpy(str, Translate("No information available.\r\nPlease update weather condition first.")); - } - else - // set the display text and show the message box - GetDisplay(&winfo, opt.bText, str); - - if (lpcp != CP_ACP) - { - SETTEXTEX textex; - textex.flags = ST_DEFAULT; - textex.codepage = lpcp; - - SendMessage(GetDlgItem(hwndDlg, IDC_MTEXT), EM_SETTEXTEX, (WPARAM)&textex, (LPARAM)str); - } - else - SetDlgItemText(hwndDlg, IDC_MTEXT, str); - - GetDisplay(&winfo, opt.bTitle, str); - SetWindowTextWth(hwndDlg, str); - GetDisplay(&winfo, "%c, %t", str); - mir_snprintf(str2, SIZEOF(str2), "%s\n%s", winfo.city, str); - SetDlgItemTextWth(hwndDlg, IDC_HEADERBAR, str2); -} - -// show brief information dialog -// wParam = current contact -int BriefInfo(WPARAM wParam, LPARAM lParam) -{ - // make sure that the contact is actually a weather one - if(IsMyContact((HANDLE)wParam)) - { - HWND hMoreDataDlg = WindowList_Find(hDataWindowList,(HANDLE)wParam); - if (hMoreDataDlg != NULL) - { - SetForegroundWindow(hMoreDataDlg); - SetFocus(hMoreDataDlg); - } - else - { - hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL, DlgProcMoreData, - (LPARAM)wParam); - } - ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 0); - ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 1); - SetDlgItemTextWth(hMoreDataDlg, IDC_MTOGGLE, Translate("More Info")); - return 1; - } - return 0; -} - -INT_PTR BriefInfoSvc(WPARAM wParam, LPARAM lParam) -{ - return BriefInfo(wParam, lParam); -} diff --git a/protocols/weather/weather_userinfo.cpp b/protocols/weather/weather_userinfo.cpp new file mode 100644 index 0000000000..f608978c12 --- /dev/null +++ b/protocols/weather/weather_userinfo.cpp @@ -0,0 +1,418 @@ +/* +Weather Protocol plugin for Miranda IM +Copyright (C) 2005-2011 Boris Krasnovskiy All Rights Reserved +Copyright (C) 2002-2005 Calvin Che + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + + +/* +This file contain the source that is related to display contact +information, including the one shows in user detail and the brief +information +*/ + +#include "weather.h" + +extern INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//============ CONTACT INFORMATION ============ + +// initialize user info +// lParam = current contact +int UserInfoInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = {0}; + + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.position = 100000000; + odp.pszTitle = LPGEN(WEATHERPROTONAME); + + if (lParam == 0) + { + odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO); + odp.pfnDlgProc = DlgProcINIPage; + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + else + { + // check if it is a weather contact + if(IsMyContact((HANDLE)lParam)) + { + // register the contact info page + odp.pszTemplate = MAKEINTRESOURCE(IDD_USERINFO); + odp.pfnDlgProc = DlgProcUIPage; + odp.flags = ODPF_BOLDGROUPS; + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + } + + return 0; +} + +// dialog process for the weather tab under user info +// lParam = current contact +INT_PTR CALLBACK DlgProcUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WEATHERINFO w; + char str[MAX_TEXT_SIZE]; + HANDLE hContact; + + hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SendMessage(GetDlgItem(hwndDlg,IDC_MOREDETAIL), BUTTONSETASFLATBTN, 0, 0); + // save the contact handle for later use + hContact = (HANDLE)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact); + // load weather info for the contact + w = LoadWeatherInfo((HANDLE)lParam); + SetDlgItemTextWth(hwndDlg, IDC_INFO1, GetDisplay(&w, Translate("Current condition for %n"), str)); + + SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON, + (WPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME, + DBGetContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon",0)), 0); + + { // bold and enlarge the current condition + LOGFONT lf; + HFONT hNormalFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_INFO2,WM_GETFONT,0,0); + GetObject(hNormalFont,sizeof(lf),&lf); + lf.lfWeight=FW_BOLD; + lf.lfWidth=7; + lf.lfHeight=15; + SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0); + } + // set the text for displaying other current weather conditions data + GetDisplay(&w, "%c %t", str); + SetDlgItemTextWth(hwndDlg, IDC_INFO2, str); + SetDlgItemTextWth(hwndDlg, IDC_INFO3, w.feel); + SetDlgItemTextWth(hwndDlg, IDC_INFO4, w.pressure); + GetDisplay(&w, "%i %w", str); + SetDlgItemTextWth(hwndDlg, IDC_INFO5, str); + SetDlgItemTextWth(hwndDlg, IDC_INFO6, w.dewpoint); + SetDlgItemTextWth(hwndDlg, IDC_INFO7, w.sunrise); + SetDlgItemTextWth(hwndDlg, IDC_INFO8, w.sunset); + SetDlgItemTextWth(hwndDlg, IDC_INFO9, w.high); + SetDlgItemTextWth(hwndDlg, IDC_INFO10, w.low); + GetDisplay(&w, Translate("Last update on: %u"), str); + SetDlgItemTextWth(hwndDlg, IDC_INFO11, str); + SetDlgItemTextWth(hwndDlg, IDC_INFO12, w.humid); + SetDlgItemTextWth(hwndDlg, IDC_INFO13, w.vis); + break; + + case WM_DESTROY: + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON, 0, 0), 0); + DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_GETFONT, 0, 0)); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_MOREDETAIL: + { + HWND hMoreDataDlg; + + hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); + if (hMoreDataDlg == NULL) + hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL, + DlgProcMoreData, (LPARAM)hContact); + else + { + SetForegroundWindow(hMoreDataDlg); + SetFocus(hMoreDataDlg); + } + ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 0); + ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 1); + break; + } + } + break; + } + return 0; +} + +//============ BRIEF INFORMATION ============ + +static int BriefDlgResizer(HWND hwnd, LPARAM lParam, UTILRESIZECONTROL *urc) +{ + switch(urc->wId) + { + case IDC_HEADERBAR: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH; + + case IDC_MTEXT: + case IDC_DATALIST: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + + case IDC_MUPDATE: + return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; + + case IDC_MTOGGLE: + case IDC_MWEBPAGE: + case IDCANCEL: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT|RD_ANCHORY_TOP; +} + + + +// dialog process for more data in the user info window +// lParam = contact handle +INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static const unsigned tabstops = 48; + HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (msg) + { + case WM_INITDIALOG: + // save the contact handle for later use + hContact = (HANDLE)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact); + + SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETEVENTMASK, 0, ENM_LINK); + SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETMARGINS, EC_LEFTMARGIN, 5); + SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETTABSTOPS, 1, (LPARAM)&tabstops); + + // get the list to display + { + LV_COLUMN lvc = { 0 }; + HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); + RECT aRect = { 0 }; + GetClientRect(hList, &aRect); + + // managing styles + lvc.mask = LVCF_WIDTH | LVCF_TEXT; + ListView_SetExtendedListViewStyleEx(hList, + LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, + LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); + + // inserting columns + lvc.cx = LIST_COLUMN; + lvc.pszText = Translate("Variable"); + ListView_InsertColumnWth(hList, 0, &lvc); + + lvc.cx = aRect.right - LIST_COLUMN - GetSystemMetrics(SM_CXVSCROLL) - 3; + lvc.pszText = Translate("Information"); + ListView_InsertColumnWth(hList, 1, &lvc); + + // inserting data + SendMessage(hwndDlg, WM_UPDATEDATA, 0, 0); + } + TranslateDialogDefault(hwndDlg); + + // prevent dups of the window + WindowList_Add(hDataWindowList, hwndDlg, hContact); + + // restore window position + Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_"); + return TRUE; + + case WM_UPDATEDATA: + ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_DATALIST)); + LoadBriefInfoText(hwndDlg, hContact); + DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)hwndDlg, 0); + + // set icons + { + WORD statusIcon = DBGetContactSettingWord(hContact, WEATHERPROTONAME, "StatusIcon", 0); + + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon))); + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon))); + } + RedrawWindow(GetDlgItem(hwndDlg, IDC_HEADERBAR), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + + case WM_SIZE: + { + RECT rc; + HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); + GetWindowRect(hList, &rc); + ListView_SetColumnWidth(hList, 1, ListView_GetColumnWidth(hList, 1) + + (int)LOWORD(lParam) - (rc.right - rc.left)); + } + { + UTILRESIZEDIALOG urd = {0}; + urd.cbSize = sizeof(urd); + urd.hwndDlg = hwndDlg; + urd.hInstance = hInst; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_BRIEF); + urd.pfnResizer = BriefDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); + } + break; + + case WM_GETMINMAXINFO: + { + LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; + + // The minimum width in points + mmi->ptMinTrackSize.x = 350; + // The minimum height in points + mmi->ptMinTrackSize.y = 300; + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDCANCEL: + // close the info window + DestroyWindow(hwndDlg); + break; + + case IDC_MUPDATE: + { + LV_ITEM lvi = {0}; + HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); + + // update current data + // set the text to "updating" + SetDlgItemTextWth(hwndDlg, IDC_MTEXT, Translate("Retrieving new data, please wait...")); + ListView_DeleteAllItems(hList); + lvi.mask = LVIF_TEXT | LVIF_PARAM; + lvi.lParam = 1; + lvi.pszText = (LPSTR)""; + lvi.iItem = ListView_InsertItemWth(hList, &lvi); + lvi.pszText = Translate("Retrieving new data, please wait..."); + ListView_SetItemTextWth(hList, lvi.iItem, 1, lvi.pszText); + UpdateSingleStation((WPARAM)hContact, 0); + break; + } + + case IDC_MWEBPAGE: + LoadForecast((WPARAM)hContact, 0); // read complete forecast + break; + + case IDC_MTOGGLE: + if (IsWindowVisible(GetDlgItem(hwndDlg,IDC_DATALIST))) + SetDlgItemTextWth(hwndDlg, IDC_MTOGGLE, Translate("More Info")); + else + SetDlgItemTextWth(hwndDlg, IDC_MTOGGLE, Translate("Brief Info")); + ShowWindow(GetDlgItem(hwndDlg,IDC_DATALIST), (int)!IsWindowVisible( + GetDlgItem(hwndDlg,IDC_DATALIST))); + ShowWindow(GetDlgItem(hwndDlg,IDC_MTEXT), (int)!IsWindowVisible(GetDlgItem(hwndDlg,IDC_MTEXT))); + break; + } + break; + + case WM_NOTIFY: + { + LPNMHDR pNmhdr = (LPNMHDR)lParam; + if (pNmhdr->idFrom == IDC_MTEXT && pNmhdr->code == EN_LINK) + { + ENLINK *enlink = (ENLINK *) lParam; + TEXTRANGE tr; + switch (enlink->msg) + { + case WM_LBUTTONUP: + tr.chrg = enlink->chrg; + tr.lpstrText = ( LPSTR )mir_alloc(tr.chrg.cpMax - tr.chrg.cpMin + 8); + SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText); + mir_free(tr.lpstrText); + break; + } + } + break; + } + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); + + Utils_SaveWindowPosition(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_"); + WindowList_Remove(hDataWindowList, hwndDlg); + break; + } + + return FALSE; +} + +// set the title of the dialog and on the which rectangle +// also load brief info into message box +void LoadBriefInfoText(HWND hwndDlg, HANDLE hContact) +{ + WEATHERINFO winfo; + char str[4096], str2[4096]; + + // load weather information from the contact into the WEATHERINFO struct + winfo = LoadWeatherInfo(hContact); + // check if data exist. If not, display error message box + if (!(BOOL)DBGetContactSettingByte(hContact, WEATHERPROTONAME, "IsUpdated", FALSE)) + { + strcpy(str, Translate("No information available.\r\nPlease update weather condition first.")); + } + else + // set the display text and show the message box + GetDisplay(&winfo, opt.bText, str); + + if (lpcp != CP_ACP) + { + SETTEXTEX textex; + textex.flags = ST_DEFAULT; + textex.codepage = lpcp; + + SendMessage(GetDlgItem(hwndDlg, IDC_MTEXT), EM_SETTEXTEX, (WPARAM)&textex, (LPARAM)str); + } + else + SetDlgItemText(hwndDlg, IDC_MTEXT, str); + + GetDisplay(&winfo, opt.bTitle, str); + SetWindowTextWth(hwndDlg, str); + GetDisplay(&winfo, "%c, %t", str); + mir_snprintf(str2, SIZEOF(str2), "%s\n%s", winfo.city, str); + SetDlgItemTextWth(hwndDlg, IDC_HEADERBAR, str2); +} + +// show brief information dialog +// wParam = current contact +int BriefInfo(WPARAM wParam, LPARAM lParam) +{ + // make sure that the contact is actually a weather one + if(IsMyContact((HANDLE)wParam)) + { + HWND hMoreDataDlg = WindowList_Find(hDataWindowList,(HANDLE)wParam); + if (hMoreDataDlg != NULL) + { + SetForegroundWindow(hMoreDataDlg); + SetFocus(hMoreDataDlg); + } + else + { + hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL, DlgProcMoreData, + (LPARAM)wParam); + } + ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 0); + ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 1); + SetDlgItemTextWth(hMoreDataDlg, IDC_MTOGGLE, Translate("More Info")); + return 1; + } + return 0; +} + +INT_PTR BriefInfoSvc(WPARAM wParam, LPARAM lParam) +{ + return BriefInfo(wParam, lParam); +} -- cgit v1.2.3