diff options
21 files changed, 1588 insertions, 1644 deletions
diff --git a/plugins/ExternalAPI/m_weather.h b/plugins/ExternalAPI/m_weather.h index eb9e89f84d..83793cc651 100644 --- a/plugins/ExternalAPI/m_weather.h +++ b/plugins/ExternalAPI/m_weather.h @@ -59,74 +59,9 @@ struct WEATHERINFO // WPARAM = LPARAM = NULL
#define MS_WEATHER_REFRESHALL "Weather/RefreshAll"
-// Below are the service functions for weather contacts
-// The plugin does NOT verify that they are used in weather contact,
-// so bad call on these function may cause crashes.
-
-// Update a single station
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_UPDATE "Weather/Update"
-
-// Update a single station + delete old settings
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_REFRESH "Weather/Refresh"
-
-// View the brief info of a contact
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_BRIEF "Weather/Brief"
-
-// Use default browser to open the complete forecast on web
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_COMPLETE "Weather/CompleteForecast"
-
-// Use default browser to open the weather map defined for the contact
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_MAP "Weather/Map"
-
-// Open the external log of the weather contact
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_LOG "Weather/Log"
-
-// Edit weather contact setting
-// WPARAM = (HANDLE)hContact
-// LPARAM = NULL
-#define MS_WEATHER_EDIT "Weather/Edit"
-
// parse the string to turn it to weather display
// WPARAM = (WEATHERINFO*)hContact
// LPARAM = (char*)display_str
#define MS_WEATHER_GETDISPLAY "Weather/GetDisplay"
-// =============== WEATHER EVENTS ================
-
-/*
-HANDLE hContact = (HANDLE)wParam;
-BOOL Condition_Changed = (BOOL)lParam;
-
-hContact is the handle of updated contact
-If the weather condition is differ from the last update (either temperature/condition,
-or the last update time, depend what the user choose in the options), then
-Condition_Changed is true; otherwise is false.
-*/
-#define ME_WEATHER_UPDATED "Miranda/Weather/Updated"
-
-/*
-Shows a warning message for Weather Popup.
-wParam = (char*) lpzMessage
-lParam = Type
-Type can either be SM_WARNING, SM_NOTIFY, or SM_WEATHERALERT
-
-This event is used to avoid the error popup to occurs within a thread, so the "Use
-multiply thread" fuction don't have to be enabled for weather popups to work.
-*/
-#define SM_WEATHERALERT 16
-#define ME_WEATHER_ERROR "Miranda/Weather/Error"
-
-
#endif //M_WEATHER_H__
diff --git a/protocols/Weather/res/resource.rc b/protocols/Weather/res/resource.rc index 34e5f32c83..36e656b8f7 100644 --- a/protocols/Weather/res/resource.rc +++ b/protocols/Weather/res/resource.rc @@ -54,10 +54,8 @@ BEGIN CONTROL "Remove old data when updating",IDC_REMOVEOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,45,286,8 CONTROL "Make the contact italic when weather alert is issued",IDC_MAKEI, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,56,286,8 - GROUPBOX "Modes",IDC_STATIC,3,70,300,37 - CONTROL "Use weather condition as protocol status",IDC_PROTOCOND, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,81,278,8 - CONTROL "Avatar only mode",IDC_DISCONDICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,91,278,8 + GROUPBOX "Modes",IDC_STATIC,3,70,300,27 + CONTROL "Avatar only mode",IDC_DISCONDICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,81,278,8 GROUPBOX "Units",IDC_STATIC,3,107,299,80,WS_GROUP LTEXT "Temperature",IDC_STATIC,8,116,53,8 CONTROL "Celsius",IDC_T1,"Button",BS_AUTORADIOBUTTON,65,116,40,8 diff --git a/protocols/Weather/src/proto.h b/protocols/Weather/src/proto.h new file mode 100644 index 0000000000..6e1747b8c2 --- /dev/null +++ b/protocols/Weather/src/proto.h @@ -0,0 +1,218 @@ +#pragma once + +struct MYOPTIONS +{ + // main options + uint8_t AutoUpdate; + uint8_t CAutoUpdate; + uint8_t StartupUpdate; + uint8_t UpdateOnlyConditionChanged; + uint8_t RemoveOldData; + uint8_t MakeItalic; + + uint16_t UpdateTime; + uint16_t AvatarSize; + + // units + uint16_t tUnit; + uint16_t wUnit; + uint16_t vUnit; + uint16_t pUnit; + uint16_t dUnit; + uint16_t eUnit; + wchar_t DegreeSign[4]; + uint8_t DoNotAppendUnit; + uint8_t NoFrac; + + // advanced + uint8_t DisCondIcon; + + // popup options + uint8_t UpdatePopup; + uint8_t AlertPopup; + uint8_t PopupOnChange; + uint8_t ShowWarnings; + + // popup colors + uint8_t UseWinColors; + COLORREF BGColour; + COLORREF TextColour; + + // popup actions + uint32_t LeftClickAction; + uint32_t RightClickAction; + + // popup delay + uint32_t pDelay; + + // other misc stuff + wchar_t Default[64]; + MCONTACT DefStn; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// Protocol class + +class CWeatherProto : public PROTO<CWeatherProto> +{ + friend class CEditDlg; + friend class COptionsDlg; + friend class CPopupOptsDlg; + friend class CBriefInfoDlg; + friend class COptionsTextDlg; + + class CProtoImpl + { + friend class CWeatherProto; + CWeatherProto &m_proto; + + CTimer m_start, m_update; + + void OnStart(CTimer *pTimer) + { + pTimer->Stop(); + m_proto.StartUpdate(); + } + + void OnUpdate(CTimer *) + { + m_proto.DoUpdate(); + } + + CProtoImpl(CWeatherProto &pro) : + m_proto(pro), + m_start(Miranda_GetSystemWindow(), UINT_PTR(this) + 1), + m_update(Miranda_GetSystemWindow(), UINT_PTR(this) + 2) + { + m_start.OnEvent = Callback(this, &CProtoImpl::OnStart); + m_update.OnEvent = Callback(this, &CProtoImpl::OnUpdate); + } + } + m_impl; + + void DoUpdate(); + void StartUpdate(); + + // contacts + INT_PTR __cdecl ViewLog(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl LoadForecast(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl WeatherMap(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl EditSettings(WPARAM wParam, LPARAM lParam); + + int __cdecl BriefInfoEvt(WPARAM wParam, LPARAM lParam); + + bool IsMyContact(MCONTACT hContact); + + // conversions + void numToStr(double num, wchar_t *str, size_t strSize); + + void GetTemp(wchar_t *tempchar, wchar_t *unit, wchar_t *str); + void GetSpeed(wchar_t *tempchar, wchar_t *unit, wchar_t *str); + void GetPressure(wchar_t *tempchar, wchar_t *unit, wchar_t *str); + void GetDist(wchar_t *tempchar, wchar_t *unit, wchar_t *str); + void GetElev(wchar_t *tempchar, wchar_t *unit, wchar_t *str); + + // data + void ConvertDataValue(struct WIDATAITEM *UpdateData, wchar_t *Data); + void EraseAllInfo(void); + void GetDataValue(WIDATAITEM *UpdateData, wchar_t *Data, wchar_t **szData); + + // http + int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **szData); + + // menu items + void InitMenuItems(); + void UpdateMenu(BOOL State); + + INT_PTR __cdecl EnableDisableCmd(WPARAM wParam, LPARAM lParam); + + // mwin + void InitMwin(void); + void DestroyMwin(void); + + int __cdecl BuildContactMenu(WPARAM wparam, LPARAM lparam); + + // options + void LoadOptions(); + void SaveOptions(); + void RestartTimer(); + void InitPopupOptions(WPARAM); + + int __cdecl OptInit(WPARAM wParam, LPARAM lParam); + + CMStringW GetTextValue(int c); + + // popups + int WPShowMessage(const wchar_t *lpzText, int kind); + int WeatherPopup(MCONTACT hContact, bool bNew); + + // search + int IDSearch(wchar_t *id, const int searchId); + int IDSearchProc(wchar_t *sID, const int searchId, struct WIIDSEARCH *sData, wchar_t *svc, wchar_t *svcname); + + int NameSearch(wchar_t *name, const int searchId); + int NameSearchProc(wchar_t *name, const int searchId, struct WINAMESEARCH *sData, wchar_t *svc, wchar_t *svcname); + + void __cdecl NameSearchThread(void *); + void __cdecl BasicSearchThread(void *); + + // update weather + HANDLE hUpdateMutex; + + int GetWeatherData(MCONTACT hContact); + int UpdateWeather(MCONTACT hContact); + void UpdateListAdd(MCONTACT hContact); + MCONTACT UpdateGetFirst(); + void DestroyUpdateList(void); + + void __cdecl UpdateThread(void *); + void UpdateAll(BOOL AutoUpdate, BOOL RemoveOld); + + INT_PTR __cdecl UpdateSingleStation(WPARAM, LPARAM); + INT_PTR __cdecl UpdateSingleRemove(WPARAM, LPARAM); + + INT_PTR __cdecl UpdateAllInfo(WPARAM wParam, LPARAM lParam); + INT_PTR __cdecl UpdateAllRemove(WPARAM wParam, LPARAM lParam); + + // user info + int __cdecl UserInfoInit(WPARAM, LPARAM); + +public: + CWeatherProto(const char *protoName, const wchar_t *userName); + ~CWeatherProto(); + + MYOPTIONS opt; + + INT_PTR __cdecl BriefInfo(WPARAM, LPARAM); + + static LRESULT CALLBACK CWeatherProto::PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + // PROTO_INTERFACE + MCONTACT AddToList(int flags, PROTOSEARCHRESULT *psr) override; + HANDLE SearchBasic(const wchar_t *id) override; + HANDLE SearchAdvanced(MWindow owner) override; + MWindow CreateExtendedSearchUI(MWindow owner) override; + + INT_PTR GetCaps(int type, MCONTACT hContact) override; + int SetStatus(int iNewStatus) override; + + bool OnContactDeleted(MCONTACT, uint32_t flags) override; + void OnModulesLoaded() override; + void OnShutdown() override; +}; + +typedef CProtoDlgBase<CWeatherProto> CWeatherDlgBase; + +///////////////////////////////////////////////////////////////////////////////////////// +// Plugin class + +struct CMPlugin : public ACCPROTOPLUGIN<CWeatherProto> +{ + CMPlugin(); + + HINSTANCE hIconsDll = nullptr; + CMOption<bool> bPopups; + + int Load() override; + int Unload() override; +}; diff --git a/protocols/Weather/src/resource.h b/protocols/Weather/src/resource.h index 67e9006fb3..28b2aa9163 100644 --- a/protocols/Weather/src/resource.h +++ b/protocols/Weather/src/resource.h @@ -58,7 +58,6 @@ #define IDC_DAutoUpdate 2030 #define IDC_IURL 2032 #define IDC_MURL 2033 -#define IDC_PROTOCOND 2034 #define IDC_Overwrite 2035 #define IDC_UPDCONDCHG 2036 #define IDC_REMOVEOLD 2037 diff --git a/protocols/Weather/src/stdafx.h b/protocols/Weather/src/stdafx.h index e3df248c79..59f2e4fa38 100644 --- a/protocols/Weather/src/stdafx.h +++ b/protocols/Weather/src/stdafx.h @@ -62,6 +62,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "resource.h"
#include "version.h"
+#include "proto.h"
//============ CONSTANTS ============
@@ -86,9 +87,6 @@ enum EWeatherCondition MAX_COND
};
-// status
-#define NOSTATUSDATA 1
-
// limits
#define MAX_TEXT_SIZE 4096
#define MAX_DATA_LEN 1024
@@ -105,73 +103,22 @@ enum EWeatherCondition #define UM_SETCONTACT 40000
// weather update error codes
-#define INVALID_ID_FORMAT 10
-#define INVALID_SVC 11
-#define INVALID_ID 12
-#define SVC_NOT_FOUND 20
-#define NETLIB_ERROR 30
-#define DATA_EMPTY 40
-#define DOC_NOT_FOUND 42
-#define DOC_TOO_SHORT 43
-#define UNKNOWN_ERROR 99
+#define INVALID_ID_FORMAT 10
+#define INVALID_SVC 11
+#define INVALID_ID 12
+#define SVC_NOT_FOUND 20
+#define NETLIB_ERROR 30
+#define DATA_EMPTY 40
+#define DOC_NOT_FOUND 42
+#define DOC_TOO_SHORT 43
+#define UNKNOWN_ERROR 99
+
+#define SM_WEATHERALERT 16
+#define WM_UPDATEDATA (WM_USER + 2687)
// defaults constants
#define VAR_LIST_OPT TranslateT("%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\n----------\n\\n\tnew line")
-//============ OPTION STRUCT ============
-
-// option struct
-struct MYOPTIONS
-{
- // main options
- uint8_t AutoUpdate;
- uint8_t CAutoUpdate;
- uint8_t StartupUpdate;
- uint8_t NoProtoCondition;
- uint8_t UpdateOnlyConditionChanged;
- uint8_t RemoveOldData;
- uint8_t MakeItalic;
-
- uint16_t UpdateTime;
- uint16_t AvatarSize;
-
- // units
- uint16_t tUnit;
- uint16_t wUnit;
- uint16_t vUnit;
- uint16_t pUnit;
- uint16_t dUnit;
- uint16_t eUnit;
- wchar_t DegreeSign[4];
- uint8_t DoNotAppendUnit;
- uint8_t NoFrac;
-
- // advanced
- uint8_t DisCondIcon;
-
- // popup options
- uint8_t UpdatePopup;
- uint8_t AlertPopup;
- uint8_t PopupOnChange;
- uint8_t ShowWarnings;
-
- // popup colors
- uint8_t UseWinColors;
- COLORREF BGColour;
- COLORREF TextColour;
-
- // popup actions
- uint32_t LeftClickAction;
- uint32_t RightClickAction;
-
- // popup delay
- uint32_t pDelay;
-
- // other misc stuff
- wchar_t Default[64];
- MCONTACT DefStn;
-};
-
//============ STRUCT USED TO MAKE AN UPDATE LIST ============
struct WCONTACTLIST {
MCONTACT hContact;
@@ -182,8 +129,6 @@ typedef struct WCONTACTLIST UPDATELIST; extern UPDATELIST *UpdateListHead, *UpdateListTail;
-void DestroyUpdateList(void);
-
//============ DATA FORMAT STRUCT ============
#define WID_NORMAL 0
@@ -298,15 +243,9 @@ extern WIDATALIST *WIHead, *WITail; extern HWND hPopupWindow, hWndSetup;
-extern MYOPTIONS opt;
-
-extern unsigned status, old_status;
-
extern MWindowList hDataWindowList, hWindowList;
-extern HNETLIBUSER hNetlibUser;
-extern HANDLE hHookWeatherUpdated, hHookWeatherError, hTBButton, hUpdateMutex;
-extern UINT_PTR timerId;
+extern HANDLE hTBButton;
extern HGENMENU hMwinMenu;
@@ -317,35 +256,9 @@ extern bool g_bIsUtf; //============ FUNCTION PRIMITIVES ============
// functions in weather_addstn.c
-INT_PTR WeatherAddToList(WPARAM wParam,LPARAM lParam);
BOOL CheckSearch();
-int IDSearch(wchar_t *id, const int searchId);
-int NameSearch(wchar_t *name, const int searchId);
-
-INT_PTR WeatherBasicSearch(WPARAM wParam,LPARAM lParam);
-INT_PTR WeatherCreateAdvancedSearchUI(WPARAM wParam, LPARAM lParam);
-INT_PTR WeatherAdvancedSearch(WPARAM wParam, LPARAM lParam);
-
-int WeatherAdd(WPARAM wParam, LPARAM lParam);
-
-// functions used in weather_contacts.c
-INT_PTR ViewLog(WPARAM wParam,LPARAM lParam);
-INT_PTR LoadForecast(WPARAM wParam,LPARAM lParam);
-INT_PTR WeatherMap(WPARAM wParam,LPARAM lParam);
-INT_PTR EditSettings(WPARAM wParam,LPARAM lParam);
-
-int ContactDeleted(WPARAM wParam,LPARAM lParam);
-
-BOOL IsMyContact(MCONTACT hContact);
-
// functions in weather_conv.c
-void GetTemp(wchar_t *tempchar, wchar_t *unit, wchar_t *str);
-void GetSpeed(wchar_t *tempchar, wchar_t *unit, wchar_t *str);
-void GetPressure(wchar_t *tempchar, wchar_t *unit, wchar_t *str);
-void GetDist(wchar_t *tempchar, wchar_t *unit, wchar_t *str);
-void GetElev(wchar_t *tempchar, wchar_t *unit, wchar_t *str);
-
void ClearStatusIcons();
int MapCondToStatus(MCONTACT hContact);
HICON GetStatusIcon(MCONTACT hContact);
@@ -371,10 +284,6 @@ void GetStationID(MCONTACT hContact, wchar_t* id, int idlen); WEATHERINFO LoadWeatherInfo(MCONTACT Change);
int DBGetData(MCONTACT hContact, char *setting, DBVARIANT *dbv);
-void EraseAllInfo(void);
-
-void GetDataValue(WIDATAITEM *UpdateData, wchar_t *Data, wchar_t** szInfo);
-void ConvertDataValue(WIDATAITEM *UpdateData, wchar_t *Data);
void wSetData(char *&Data, const char *Value);
void wSetData(wchar_t *&Data, const char *Value);
void wSetData(wchar_t *&Data, const wchar_t *Value);
@@ -383,10 +292,6 @@ void wfree(wchar_t *&Data); void DBDataManage(MCONTACT hContact, uint16_t Mode, WPARAM wParam, LPARAM lParam);
-// functions in weather_http.c
-int InternetDownloadFile (char *szUrl, char *cookie, char *userAgent, wchar_t** szData);
-void NetlibInit();
-
// functions in weather_ini.c
WIDATA* GetWIData(wchar_t *pszServ);
@@ -395,74 +300,26 @@ bool IsContainedInCondList(const wchar_t *pszStr, WICONDLIST *List); void DestroyWIList();
bool LoadWIData(bool dial);
-INT_PTR CALLBACK DlgPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
// functions in weather_info.c
void GetINIInfo(wchar_t *pszSvc);
wchar_t* GetINIVersionNum(int iVersion);
+const wchar_t *GetDefaultText(int c);
void MoreVarList();
-// functions in weather_opt.c
-void LoadOptions();
-void SaveOptions();
-
-int OptInit(WPARAM wParam,LPARAM lParam);
-
-CMStringW GetTextValue(int c);
-const wchar_t* GetDefaultText(int c);
-
-// functions in weather_popup.c
-int WeatherPopup(WPARAM wParam, LPARAM lParam);
-int WeatherError(WPARAM wParam, LPARAM lParam);
-int WPShowMessage(const wchar_t* lpzText, uint16_t kind);
-
-LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
// functions in weather_svcs.c
void InitServices(void);
-INT_PTR WeatherSetStatus(WPARAM new_status, LPARAM lParam);
-INT_PTR WeatherGetCaps(WPARAM wParam, LPARAM lParam);
-INT_PTR WeatherGetName(WPARAM wParam, LPARAM lParam);
-INT_PTR WeatherGetStatus(WPARAM wParam, LPARAM lParam);
INT_PTR WeatherLoadIcon(WPARAM wParam, LPARAM lParam);
-void UpdateMenu(BOOL State);
-void UpdatePopupMenu(BOOL State);
-void AddMenuItems();
void AvatarDownloaded(MCONTACT hContact);
-// functions in weather_update.c
-int UpdateWeather(MCONTACT hContact);
-
-void UpdateAll(BOOL AutoUpdate, BOOL RemoveOld);
-INT_PTR UpdateSingleStation(WPARAM wParam,LPARAM lParam);
-INT_PTR UpdateAllInfo(WPARAM wParam,LPARAM lParam);
-INT_PTR UpdateSingleRemove(WPARAM wParam,LPARAM lParam);
-INT_PTR UpdateAllRemove(WPARAM wParam,LPARAM lParam);
-
-int GetWeatherData(MCONTACT hContact);
-
-void CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
-void CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
-
// function from multiwin module
-void InitMwin(void);
-void DestroyMwin(void);
INT_PTR Mwin_MenuClicked(WPARAM wParam, LPARAM lParam);
-int BuildContactMenu(WPARAM wparam, LPARAM lparam);
void UpdateMwinData(MCONTACT hContact);
void removeWindow(MCONTACT hContact);
-// functions in weather_userinfo.c
-int UserInfoInit(WPARAM wParam, LPARAM lParam);
-
-#define WM_UPDATEDATA WM_USER + 2687
-
-int BriefInfo(WPARAM wParam, LPARAM lParam);
-
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
// UI Classes
class WeatherMyDetailsDlg : public CUserInfoPageDlg
@@ -476,17 +333,3 @@ public: void onClick_Reload(CCtrlButton *);
};
-
-//============ Plugin Class ============
-
-struct CMPlugin : public PLUGIN<CMPlugin>
-{
- CMPlugin();
-
- HINSTANCE hIconsDll = nullptr;
- CMOption<bool> bPopups;
-
- int Load() override;
- int Unload() override;
-};
-
diff --git a/protocols/Weather/src/weather.cpp b/protocols/Weather/src/weather.cpp index f5e6bb2e7b..f84a009ff8 100644 --- a/protocols/Weather/src/weather.cpp +++ b/protocols/Weather/src/weather.cpp @@ -33,18 +33,8 @@ WIDATALIST *WITail; HWND hPopupWindow; -HANDLE hHookWeatherUpdated; -HANDLE hHookWeatherError; - MWindowList hDataWindowList, hWindowList; -HANDLE hUpdateMutex; - -unsigned status; -unsigned old_status; - -UINT_PTR timerId = 0; - CMPlugin g_plugin; MYOPTIONS opt; @@ -77,11 +67,9 @@ static const PLUGININFOEX pluginInfoEx = }; CMPlugin::CMPlugin() : - PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx), + ACCPROTOPLUGIN<CWeatherProto>(MODULENAME, pluginInfoEx), bPopups(MODULENAME, "UsePopup", true) { - opt.NoProtoCondition = g_plugin.getByte("NoStatus", true); - RegisterProtocol((opt.NoProtoCondition) ? PROTOTYPE_VIRTUAL : PROTOTYPE_PROTOCOL); SetUniqueId("ID"); } @@ -91,21 +79,7 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOC ///////////////////////////////////////////////////////////////////////////////////////// -int WeatherShutdown(WPARAM, LPARAM) -{ - KillTimer(nullptr, timerId); // kill update timer - - SaveOptions(); // save options once more - status = ID_STATUS_OFFLINE; // set status to offline - - WindowList_Broadcast(hWindowList, WM_CLOSE, 0, 0); - WindowList_Broadcast(hDataWindowList, WM_CLOSE, 0, 0); - SendMessage(hWndSetup, WM_CLOSE, 0, 0); - - return 0; -} - -int OnToolbarLoaded(WPARAM, LPARAM) +static int OnToolbarLoaded(WPARAM, LPARAM) { TTBButton ttb = {}; ttb.name = LPGEN("Enable/disable auto update"); @@ -119,23 +93,8 @@ int OnToolbarLoaded(WPARAM, LPARAM) return 0; } -// weather protocol initialization function -// run after the event ME_SYSTEM_MODULESLOADED occurs -int WeatherInit(WPARAM, LPARAM) +static int OnModulesLoaded(WPARAM, LPARAM) { - // initialize netlib - NetlibInit(); - - InitMwin(); - - // load weather menu items - AddMenuItems(); - - // timer for the first update - timerId = SetTimer(nullptr, 0, 5000, timerProc2); // first update is 5 sec after load - - // weather user detail - HookEvent(ME_USERINFO_INITIALISE, UserInfoInit); HookEvent(ME_TTB_MODULELOADED, OnToolbarLoaded); return 0; } @@ -162,37 +121,15 @@ int CMPlugin::Load() // load dll with icons hIconsDll = LoadLibraryW(g_pwszIconsName); - // load options and set defaults - LoadOptions(); - - // reset the weather data at startup for individual contacts - EraseAllInfo(); - // 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 - HookEvent(ME_OPT_INITIALISE, OptInit); - HookEvent(ME_SYSTEM_MODULESLOADED, WeatherInit); - HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); - HookEvent(ME_CLIST_DOUBLECLICKED, BriefInfo); - HookEvent(ME_WEATHER_UPDATED, WeatherPopup); - HookEvent(ME_WEATHER_ERROR, WeatherError); - HookEvent(ME_SYSTEM_PRESHUTDOWN, WeatherShutdown); - HookEvent(ME_CLIST_PREBUILDCONTACTMENU, BuildContactMenu); + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); hDataWindowList = WindowList_Create(); hWindowList = WindowList_Create(); - hUpdateMutex = CreateMutex(nullptr, FALSE, nullptr); - // initialize weather protocol services InitServices(); @@ -208,7 +145,7 @@ int CMPlugin::Load() mir_snwprintf(SvcFunc, L"%s__PopupWindow", _A2W(MODULENAME)); hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW, L"static", SvcFunc, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, nullptr, g_plugin.getInst(), nullptr); - SetWindowLongPtr(hPopupWindow, GWLP_WNDPROC, (LONG_PTR)PopupWndProc); + SetWindowLongPtr(hPopupWindow, GWLP_WNDPROC, (LONG_PTR)&CWeatherProto::PopupWndProc); return 0; } @@ -220,20 +157,11 @@ int CMPlugin::Unload() if (hIconsDll) FreeModule(hIconsDll); - DestroyMwin(); DestroyWindow(hPopupWindow); - DestroyHookableEvent(hHookWeatherUpdated); - DestroyHookableEvent(hHookWeatherError); - - Netlib_CloseHandle(hNetlibUser); - - DestroyUpdateList(); DestroyWIList(); // unload all ini data from memory WindowList_Destroy(hDataWindowList); WindowList_Destroy(hWindowList); - - CloseHandle(hUpdateMutex); return 0; } diff --git a/protocols/Weather/src/weather_addstn.cpp b/protocols/Weather/src/weather_addstn.cpp index eb2a85b9fb..3704dc68c4 100644 --- a/protocols/Weather/src/weather_addstn.cpp +++ b/protocols/Weather/src/weather_addstn.cpp @@ -28,18 +28,16 @@ to the contact list. Contain code for both name and ID search. static int sttSearchId = -1; static wchar_t name1[256]; -// ============ ADDING NEW STATION ============ - +///////////////////////////////////////////////////////////////////////////////////////// // protocol service function for adding a new contact onto contact list -// lParam = PROTOSEARCHRESULT -INT_PTR WeatherAddToList(WPARAM, LPARAM lParam) + +MCONTACT CWeatherProto::AddToList(int, PROTOSEARCHRESULT *psr) { - PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)lParam; if (!psr || !psr->email.w) return 0; // search for existing contact - for (auto &hContact : Contacts(MODULENAME)) { + for (auto &hContact : AccContacts()) { DBVARIANT dbv; // check ID to see if the contact already exist in the database if (!g_plugin.getWString(hContact, "ID", &dbv)) { @@ -74,54 +72,55 @@ INT_PTR WeatherAddToList(WPARAM, LPARAM lParam) // set settings by obtaining the default for the service if (psr->lastName.w[0] != 0) { WIDATA *sData = GetWIData(svc); - g_plugin.setWString(hContact, "MapURL", sData->DefaultMap); - g_plugin.setString(hContact, "InfoURL", sData->DefaultURL); + setWString(hContact, "MapURL", sData->DefaultMap); + setString(hContact, "InfoURL", sData->DefaultURL); } else { // if no valid service is found, create empty strings for MapURL and InfoURL - g_plugin.setString(hContact, "MapURL", ""); - g_plugin.setString(hContact, "InfoURL", ""); + setString(hContact, "MapURL", ""); + setString(hContact, "InfoURL", ""); } // write the other info and settings to the database - g_plugin.setWString(hContact, "ID", psr->email.w); - g_plugin.setWString(hContact, "Nick", psr->nick.w); - g_plugin.setWord(hContact, "Status", ID_STATUS_OFFLINE); + setWString(hContact, "ID", psr->email.w); + setWString(hContact, "Nick", psr->nick.w); + setWord(hContact, "Status", ID_STATUS_OFFLINE); AvatarDownloaded(hContact); wchar_t str[256]; mir_snwprintf(str, TranslateT("Current weather information for %s."), psr->nick.w); - g_plugin.setWString(hContact, "About", str); + setWString(hContact, "About", str); // make the last update tags to something invalid - g_plugin.setString(hContact, "LastLog", "never"); - g_plugin.setString(hContact, "LastCondition", "None"); - g_plugin.setString(hContact, "LastTemperature", "None"); + setString(hContact, "LastLog", "never"); + setString(hContact, "LastCondition", "None"); + setString(hContact, "LastTemperature", "None"); // ignore status change db_set_dw(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, _countof(opt.Default)); opt.DefStn = hContact; - if (!g_plugin.getWString(hContact, "Nick", &dbv)) { + ptrW wszNick(g_plugin.getWStringA(hContact, "Nick")); + if (mir_wstrlen(wszNick)) { // notification message box - mir_snwprintf(str, TranslateT("%s is now the default weather station"), dbv.pwszVal); - db_free(&dbv); + mir_snwprintf(str, TranslateT("%s is now the default weather station"), wszNick); MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); } + g_plugin.setWString("Default", opt.Default); } + // display the Edit Settings dialog box EditSettings(hContact, 0); - return (INT_PTR)hContact; + return hContact; } -// ============ WARNING DIALOG ============ +///////////////////////////////////////////////////////////////////////////////////////// +// shows a message box and cancel search if update is in process -// show a message box and cancel search if update is in process BOOL CheckSearch() { if (UpdateListHead != nullptr) { @@ -131,53 +130,36 @@ BOOL CheckSearch() return TRUE; } -// ============ BASIC ID SEARCH ============ - +///////////////////////////////////////////////////////////////////////////////////////// // A timer process for the ID search (threaded) -static void __cdecl BasicSearchTimerProc(void *pParam) + +void __cdecl CWeatherProto::BasicSearchThread(void *pParam) { ptrW sID((wchar_t *)pParam); - int result; // search only when it's not current updating weather. if (CheckSearch()) - result = IDSearch(sID, sttSearchId); + IDSearch(sID, sttSearchId); // broadcast the search result - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)sttSearchId); + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)sttSearchId); // exit the search sttSearchId = -1; } -// the service function for ID search -// lParam = ID search string -INT_PTR WeatherBasicSearch(WPARAM, LPARAM lParam) +HANDLE CWeatherProto::SearchBasic(const wchar_t *id) { if (sttSearchId != -1) return 0; // only one search at a time sttSearchId = 1; - mir_forkthread(BasicSearchTimerProc, mir_a2u((char *)lParam)); // create a thread for the ID search - return sttSearchId; + ForkThread(&CWeatherProto::BasicSearchThread, mir_wstrdup(id)); + return (HANDLE)sttSearchId; } -// ============ NAME SEARCH ============ -// +///////////////////////////////////////////////////////////////////////////////////////// // name search timer process (threaded) -static void __cdecl NameSearchTimerProc(LPVOID) -{ - // search only when it's not current updating weather. - if (CheckSearch()) - if (name1[0] != 0) - NameSearch(name1, sttSearchId); // search nickname field - - // broadcast the result - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)sttSearchId); - - // exit the search - sttSearchId = -1; -} static INT_PTR CALLBACK WeatherSearchAdvancedDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM) { @@ -194,36 +176,52 @@ static INT_PTR CALLBACK WeatherSearchAdvancedDlgProc(HWND hwndDlg, UINT msg, WPA return FALSE; } -INT_PTR WeatherCreateAdvancedSearchUI(WPARAM, LPARAM lParam) +MWindow CWeatherProto::CreateExtendedSearchUI(MWindow hwndOwner) { - HWND parent = (HWND)lParam; - if (parent) - return (INT_PTR)CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SEARCHCITY), parent, WeatherSearchAdvancedDlgProc, 0); + if (hwndOwner) + return CreateDialogParamW(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SEARCHCITY), hwndOwner, WeatherSearchAdvancedDlgProc, 0); return 0; } +///////////////////////////////////////////////////////////////////////////////////////// // service function for name search -INT_PTR WeatherAdvancedSearch(WPARAM, LPARAM lParam) + +void __cdecl CWeatherProto::NameSearchThread(void *) { - if (sttSearchId != -1) return 0; //only one search at a time + // search only when it's not current updating weather. + if (CheckSearch()) + if (name1[0] != 0) + NameSearch(name1, sttSearchId); // search nickname field + + // broadcast the result + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)sttSearchId); + + // exit the search + sttSearchId = -1; +} + +HANDLE CWeatherProto::SearchAdvanced(MWindow hwndOwner) +{ + if (sttSearchId != -1) + return 0; //only one search at a time sttSearchId = 1; - GetDlgItemText((HWND)lParam, IDC_SEARCHCITY, name1, _countof(name1)); + GetDlgItemText(hwndOwner, IDC_SEARCHCITY, name1, _countof(name1)); // search for the weather station using a thread - mir_forkthread(NameSearchTimerProc); - return sttSearchId; + ForkThread(&CWeatherProto::NameSearchThread); + return (HANDLE)sttSearchId; } -// ============ SEARCH FOR A WEATHER STATION USING ID ============ - -// Seaching station ID from a single weather service (Threaded) +///////////////////////////////////////////////////////////////////////////////////////// +// Seaching station ID from a single weather service // 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(wchar_t *sID, const int searchId, WIIDSEARCH *sData, wchar_t *svc, wchar_t *svcname) + +int CWeatherProto::IDSearchProc(wchar_t *sID, const int searchId, WIIDSEARCH *sData, wchar_t *svc, wchar_t *svcname) { wchar_t str[MAX_DATA_LEN], newID[MAX_DATA_LEN]; @@ -259,16 +257,12 @@ int IDSearchProc(wchar_t *sID, const int searchId, WIIDSEARCH *sData, wchar_t *s psr.firstName.w = L" "; psr.lastName.w = svcname; psr.email.w = newID; - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); + ProtoBroadcastAck(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(wchar_t *sID, const int searchId) +int CWeatherProto::IDSearch(wchar_t *sID, const int searchId) { // for a normal ID search (ID != #) if (mir_wstrcmp(sID, L"#")) { @@ -289,20 +283,20 @@ int IDSearch(wchar_t *sID, const int searchId) psr.firstName.w = L" "; psr.lastName.w = L""; psr.email.w = TranslateT("<Enter station ID here>"); // to be entered - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); + ProtoBroadcastAck(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(wchar_t *name, const int searchId, WINAMESEARCH *sData, wchar_t *svc, wchar_t *svcname) + +int CWeatherProto::NameSearchProc(wchar_t *name, const int searchId, WINAMESEARCH *sData, wchar_t *svc, wchar_t *svcname) { wchar_t Name[MAX_DATA_LEN], str[MAX_DATA_LEN], sID[MAX_DATA_LEN], *szData = nullptr, *search; @@ -352,7 +346,7 @@ int NameSearchProc(wchar_t *name, const int searchId, WINAMESEARCH *sData, wchar psr.lastName.w = svcname; psr.email.w = sID; psr.id.w = sID; - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); mir_free(szData); return 0; } @@ -390,7 +384,7 @@ int NameSearchProc(wchar_t *name, const int searchId, WINAMESEARCH *sData, wchar psr.lastName.w = svcname; psr.email.w = sID; psr.id.w = sID; - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr); } } } @@ -403,11 +397,7 @@ int NameSearchProc(wchar_t *name, const int searchId, WINAMESEARCH *sData, wchar return 1; } -// name search (Threaded) -// name: the station name to search for -// searchId: don't change -// return 0 if no error -int NameSearch(wchar_t *name, const int searchId) +int CWeatherProto::NameSearch(wchar_t *name, const int searchId) { // search every weather service using the search station name WIDATALIST *Item = WIHead; @@ -419,13 +409,3 @@ int NameSearch(wchar_t *name, const int searchId) return 0; } - -// ======================MENU ITEM FUNCTION ============ - -// add a new weather station via find/add dialog -int WeatherAdd(WPARAM, LPARAM) -{ - db_set_s(0, "FindAdd", "LastSearched", "Weather"); - CallService(MS_FINDADD_FINDADD, 0, 0); - return 0; -} diff --git a/protocols/Weather/src/weather_contacts.cpp b/protocols/Weather/src/weather_contacts.cpp index 2833521275..8db99359c0 100644 --- a/protocols/Weather/src/weather_contacts.cpp +++ b/protocols/Weather/src/weather_contacts.cpp @@ -33,11 +33,16 @@ static void OpenUrl(wchar_t *format, wchar_t *id) Utils_OpenUrlW(loc); } -//============ BASIC CONTACTS FUNCTIONS AND LINKS ============ +bool CWeatherProto::IsMyContact(MCONTACT hContact) +{ + return !mir_strcmp(m_szModuleName, Proto_GetBaseAccountName(hContact)); +} +///////////////////////////////////////////////////////////////////////////////////////// // view weather log for the contact // wParam = current contact -INT_PTR ViewLog(WPARAM wParam, LPARAM lParam) + +INT_PTR CWeatherProto::ViewLog(WPARAM wParam, LPARAM lParam) { // see if the log path is set DBVARIANT dbv; @@ -52,9 +57,11 @@ INT_PTR ViewLog(WPARAM wParam, LPARAM lParam) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// // read complete forecast // wParam = current contact -INT_PTR LoadForecast(WPARAM wParam, LPARAM) + +INT_PTR CWeatherProto::LoadForecast(WPARAM wParam, LPARAM) { wchar_t id[256], loc2[256]; GetStationID(wParam, id, _countof(id)); @@ -70,9 +77,11 @@ INT_PTR LoadForecast(WPARAM wParam, LPARAM) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// // load weather map // wParam = current contact -INT_PTR WeatherMap(WPARAM wParam, LPARAM) + +INT_PTR CWeatherProto::WeatherMap(WPARAM wParam, LPARAM) { wchar_t id[256], loc2[256]; GetStationID(wParam, id, _countof(id)); @@ -90,314 +99,331 @@ INT_PTR WeatherMap(WPARAM wParam, LPARAM) return 0; } -//============ EDIT SETTINGS ============ +///////////////////////////////////////////////////////////////////////////////////////// +// edit weather settings +// lParam = current contact -typedef struct +class CEditDlg : public CWeatherDlgBase { MCONTACT hContact; HICON hRename; HICON hUserDetail; HICON hFile; HICON hSrchAll; -} CntSetWndDataType; -// edit weather settings -// lParam = current contact -static INT_PTR CALLBACK DlgProcChange(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - DBVARIANT dbv; + CCtrlEdit edtID, edtName; + CCtrlButton btnGetName, btnExternal, btnBrowse, btnView1, btnView2, btnReset1, btnReset2, btnSvcInfo, btnChange; + wchar_t str[MAX_DATA_LEN], str2[256], city[256], filter[256], *chop; char loc[512]; OPENFILENAME ofn; // common dialog box structure - MCONTACT hContact; WIDATA *sData; - CntSetWndDataType *wndData = nullptr; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - wndData = (CntSetWndDataType*)mir_alloc(sizeof(CntSetWndDataType)); - wndData->hContact = hContact = lParam; - wndData->hRename = Skin_LoadIcon(SKINICON_OTHER_RENAME); - wndData->hUserDetail = Skin_LoadIcon(SKINICON_OTHER_USERDETAILS); - wndData->hFile = Skin_LoadIcon(SKINICON_EVENT_FILE); - wndData->hSrchAll = Skin_LoadIcon(SKINICON_OTHER_SEARCHALL); +public: + CEditDlg(CWeatherProto *ppro, MCONTACT _1) : + CWeatherDlgBase(ppro, IDD_EDIT), + hContact(_1), + edtID(this, IDC_ID), + edtName(this, IDC_NAME), + btnView1(this, IDC_VIEW1), + btnView2(this, IDC_VIEW2), + btnReset1(this, IDC_RESET1), + btnReset2(this, IDC_RESET2), + btnBrowse(this, IDC_BROWSE), + btnChange(this, IDC_CHANGE), + btnGetName(this, IDC_GETNAME), + btnSvcInfo(this, IDC_SVCINFO), + btnExternal(this, IDC_External) + { + edtID.OnChange = Callback(this, &CEditDlg::onChanged_ID); + edtName.OnChange = Callback(this, &CEditDlg::onChanged_Name); + + btnView1.OnClick = Callback(this, &CEditDlg::onClick_View1); + btnView2.OnClick = Callback(this, &CEditDlg::onClick_View2); + btnReset1.OnClick = Callback(this, &CEditDlg::onClick_Reset1); + btnReset2.OnClick = Callback(this, &CEditDlg::onClick_Reset2); + btnBrowse.OnClick = Callback(this, &CEditDlg::onClick_Browse); + btnChange.OnClick = Callback(this, &CEditDlg::onClick_Change); + btnGetName.OnClick = Callback(this, &CEditDlg::onClick_GetName); + btnSvcInfo.OnClick = Callback(this, &CEditDlg::onClick_SvcInfo); + btnExternal.OnClick = Callback(this, &CEditDlg::onClick_External); + } - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)wndData); + bool OnInitDialog() override + { + hRename = Skin_LoadIcon(SKINICON_OTHER_RENAME); + hUserDetail = Skin_LoadIcon(SKINICON_OTHER_USERDETAILS); + hFile = Skin_LoadIcon(SKINICON_EVENT_FILE); + hSrchAll = Skin_LoadIcon(SKINICON_OTHER_SEARCHALL); // 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); + SendDlgItemMessage(m_hwnd, IDC_GETNAME, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hRename); + SendDlgItemMessage(m_hwnd, IDC_SVCINFO, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hUserDetail); + SendDlgItemMessage(m_hwnd, IDC_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hFile); + SendDlgItemMessage(m_hwnd, IDC_VIEW1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hSrchAll); + SendDlgItemMessage(m_hwnd, IDC_RESET1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hRename); + SendDlgItemMessage(m_hwnd, IDC_VIEW2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hSrchAll); + SendDlgItemMessage(m_hwnd, IDC_RESET2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hRename); // make all buttons flat - SendDlgItemMessage(hwndDlg, IDC_GETNAME, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_BROWSE, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_VIEW1, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_RESET1, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_VIEW2, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_RESET2, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_GETNAME, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_SVCINFO, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_BROWSE, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_VIEW1, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_RESET1, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_VIEW2, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_RESET2, BUTTONSETASFLATBTN, TRUE, 0); // set tooltip for the buttons - SendDlgItemMessage(hwndDlg, IDC_GETNAME, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Get city name from ID"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Weather INI information"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_BROWSE, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Browse"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_VIEW1, BUTTONADDTOOLTIP, (WPARAM)LPGENW("View webpage"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_RESET1, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Reset to default"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_VIEW2, BUTTONADDTOOLTIP, (WPARAM)LPGENW("View webpage"), BATF_UNICODE); - SendDlgItemMessage(hwndDlg, IDC_RESET2, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Reset to default"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_GETNAME, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Get city name from ID"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_SVCINFO, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Weather INI information"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_BROWSE, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Browse"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_VIEW1, BUTTONADDTOOLTIP, (WPARAM)LPGENW("View webpage"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_RESET1, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Reset to default"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_VIEW2, BUTTONADDTOOLTIP, (WPARAM)LPGENW("View webpage"), BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_RESET2, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Reset to default"), BATF_UNICODE); // save the handle for the contact - WindowList_Add(hWindowList, hwndDlg, hContact); + WindowList_Add(hWindowList, m_hwnd, hContact); // start to get the settings // if the setting not exist, leave the dialog box blank - if (!g_plugin.getWString(hContact, "ID", &dbv)) { - SetDlgItemText(hwndDlg, IDC_ID, dbv.pwszVal); + DBVARIANT dbv; + if (!m_proto->getWString(hContact, "ID", &dbv)) { + SetDlgItemText(m_hwnd, IDC_ID, dbv.pwszVal); // check if the station is a default station - CheckDlgButton(hwndDlg, IDC_DEFA, mir_wstrcmp(dbv.pwszVal, opt.Default) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_DEFA, mir_wstrcmp(dbv.pwszVal, m_proto->opt.Default) != 0 ? BST_CHECKED : BST_UNCHECKED); db_free(&dbv); } - if (!g_plugin.getWString(hContact, "Nick", &dbv)) { - SetDlgItemText(hwndDlg, IDC_NAME, dbv.pwszVal); + if (!m_proto->getWString(hContact, "Nick", &dbv)) { + SetDlgItemText(m_hwnd, IDC_NAME, dbv.pwszVal); db_free(&dbv); } - if (!g_plugin.getWString(hContact, "Log", &dbv)) { - SetDlgItemText(hwndDlg, IDC_LOG, dbv.pwszVal); + if (!m_proto->getWString(hContact, "Log", &dbv)) { + SetDlgItemText(m_hwnd, IDC_LOG, dbv.pwszVal); // if the log path is not empty, check the checkbox for external log - if (dbv.pwszVal[0]) CheckDlgButton(hwndDlg, IDC_External, BST_CHECKED); + if (dbv.pwszVal[0]) CheckDlgButton(m_hwnd, IDC_External, BST_CHECKED); db_free(&dbv); } // enable/disable the browse button depending on the value of external log checkbox - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_External)); + EnableWindow(GetDlgItem(m_hwnd, IDC_BROWSE), (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_External)); // other checkbox options - CheckDlgButton(hwndDlg, IDC_DPop, g_plugin.getByte(hContact, "DPopUp", FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_DAutoUpdate, g_plugin.getByte(hContact, "DAutoUpdate", FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_Internal, g_plugin.getByte(hContact, "History", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_DPop, m_proto->getByte(hContact, "DPopUp", FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_DAutoUpdate, m_proto->getByte(hContact, "DAutoUpdate", FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_Internal, m_proto->getByte(hContact, "History", 0) ? BST_CHECKED : BST_UNCHECKED); - if (!g_plugin.getWString(hContact, "InfoURL", &dbv)) { - SetDlgItemText(hwndDlg, IDC_IURL, dbv.pwszVal); + if (!m_proto->getWString(hContact, "InfoURL", &dbv)) { + SetDlgItemText(m_hwnd, IDC_IURL, dbv.pwszVal); db_free(&dbv); } - if (!g_plugin.getWString(hContact, "MapURL", &dbv)) { - SetDlgItemText(hwndDlg, IDC_MURL, dbv.pwszVal); + if (!m_proto->getWString(hContact, "MapURL", &dbv)) { + SetDlgItemText(m_hwnd, IDC_MURL, dbv.pwszVal); db_free(&dbv); } // display the dialog box and free memory - Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, MODULENAME, "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, _countof(str)); - chop = wcschr(str, '/'); - if (chop == nullptr) - 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, _countof(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 - 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, _countof(str)); - GetSvc(str); - sData = GetWIData(str); - GetDlgItemText(hwndDlg, IDC_ID, str, _countof(str)); - GetID(str); - // if ID search is available, do it - if (sData->IDSearch.Available) { - // load the page - mir_snprintf(loc, sData->IDSearch.SearchURL, str); - str[0] = 0; - wchar_t *pData = nullptr; - if (InternetDownloadFile(loc, nullptr, sData->UserAgent, &pData) == 0) { - wchar_t *szInfo = pData; - wchar_t *search = wcsstr(szInfo, sData->IDSearch.NotFoundStr); - - // if the page is found (ie. valid ID), get the name of the city - if (search == nullptr) - GetDataValue(&sData->IDSearch.Name, str, &szInfo); - } - // free memory - mir_free(pData); + Utils_RestoreWindowPositionNoMove(m_hwnd, NULL, MODULENAME, "EditSetting_"); + ShowWindow(m_hwnd, SW_SHOW); + return true; + } + + void OnDestroy() override + { + IcoLib_ReleaseIcon(hFile); + IcoLib_ReleaseIcon(hRename); + IcoLib_ReleaseIcon(hSrchAll); + IcoLib_ReleaseIcon(hUserDetail); + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); + + WindowList_Remove(hWindowList, m_hwnd); + Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "EditSetting_"); + } + + void onChanged_ID(CCtrlEdit *) + { + // check if there are 2 parts in the ID (svc/id) seperated by "/" + // if not, don't let user change the setting + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + chop = wcschr(str, '/'); + if (chop == nullptr) + EnableWindow(GetDlgItem(m_hwnd, IDC_CHANGE), FALSE); + else + EnableWindow(GetDlgItem(m_hwnd, IDC_CHANGE), TRUE); + } + + void onChanged_Name(CCtrlEdit *) + { + // check if station name is entered + // if not, don't let user change the setting + GetDlgItemText(m_hwnd, IDC_NAME, str, _countof(str)); + EnableWindow(GetDlgItem(m_hwnd, IDC_CHANGE), str[0] != 0); + } + + void onClick_GetName(CCtrlButton *) + { + // the button for getting station name from the internet + // this function uses the ID search for add/find weather station + if (!CheckSearch()) + return; // don't download if update is in progress + + // get the weather update data using the string in the ID field + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + GetSvc(str); + sData = GetWIData(str); + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + GetID(str); + + // if ID search is available, do it + if (sData->IDSearch.Available) { + // load the page + mir_snprintf(loc, sData->IDSearch.SearchURL, str); + str[0] = 0; + wchar_t *pData = nullptr; + if (m_proto->InternetDownloadFile(loc, nullptr, sData->UserAgent, &pData) == 0) { + wchar_t *szInfo = pData; + wchar_t *search = wcsstr(szInfo, sData->IDSearch.NotFoundStr); + + // if the page is found (ie. valid ID), get the name of the city + if (search == nullptr) + m_proto->GetDataValue(&sData->IDSearch.Name, str, &szInfo); } + // free memory + mir_free(pData); + } + + // give no station name but only ID if the search is unavailable + if (str[0] != 0) + SetDlgItemText(m_hwnd, IDC_NAME, str); + } + + void onClick_External(CCtrlButton *) + { + // enable/disable the borwse button depending if the external log is enabled + EnableWindow(GetDlgItem(m_hwnd, IDC_BROWSE), (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_External)); + if (!(uint8_t)IsDlgButtonChecked(m_hwnd, IDC_External)) + return; - // 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), (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_External)); - if (!(uint8_t)IsDlgButtonChecked(hwndDlg, IDC_External)) - return TRUE; - __fallthrough; - - case IDC_BROWSE: - // browse for the external log file - GetDlgItemText(hwndDlg, IDC_LOG, str, _countof(str)); - // Initialize OPENFILENAME - memset(&ofn, 0, sizeof(OPENFILENAME)); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hwndDlg; - ofn.lpstrFile = str; - ofn.nMaxFile = _countof(str); - - // set filters - mir_snwprintf(filter, L"%s (*.txt)%c*.txt%c%s (*.*)%c*.*%c%c", TranslateT("Text Files"), 0, 0, TranslateT("All Files"), 0, 0, 0); - ofn.lpstrFilter = filter; - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = nullptr; - 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, _countof(str)); - if (str[0] == 0) - return TRUE; - GetDlgItemText(hwndDlg, IDC_ID, str2, _countof(str2)); + onClick_Browse(0); + } + + void onClick_Browse(CCtrlButton *) + { + // browse for the external log file + GetDlgItemText(m_hwnd, IDC_LOG, str, _countof(str)); + + // Initialize OPENFILENAME + memset(&ofn, 0, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = m_hwnd; + ofn.lpstrFile = str; + ofn.nMaxFile = _countof(str); + + // set filters + mir_snwprintf(filter, L"%s (*.txt)%c*.txt%c%s (*.*)%c*.*%c%c", TranslateT("Text Files"), 0, 0, TranslateT("All Files"), 0, 0, 0); + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = nullptr; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = nullptr; + ofn.Flags = OFN_PATHMUSTEXIST; + + // Display a Open dialog box and put the file name on the dialog + if (GetOpenFileName(&ofn)) + SetDlgItemText(m_hwnd, IDC_LOG, ofn.lpstrFile); + + // if there is no log file specified, disable external logging + EnableWindow(GetDlgItem(m_hwnd, IDC_CHANGE), ofn.lpstrFile[0] != 0); + } + + void onClick_View1(CCtrlButton *) + { + // view the page for more info + GetDlgItemText(m_hwnd, IDC_IURL, str, _countof(str)); + if (str[0]) { + GetDlgItemText(m_hwnd, IDC_ID, str2, _countof(str2)); OpenUrl(str, str2); - break; - - case IDC_VIEW2: - // view the page for weather map - GetDlgItemText(hwndDlg, IDC_MURL, str, _countof(str)); - if (str[0] == 0) - return TRUE; - GetDlgItemText(hwndDlg, IDC_ID, str2, _countof(str2)); + } + } + + void onClick_View2(CCtrlButton *) + { + // view the page for weather map + GetDlgItemText(m_hwnd, IDC_MURL, str, _countof(str)); + if (str[0]) { + GetDlgItemText(m_hwnd, IDC_ID, str2, _countof(str2)); OpenUrl(str, str2); - break; - - case IDC_RESET1: - // reset the more info url to service default - GetDlgItemText(hwndDlg, IDC_ID, str, _countof(str)); - GetSvc(str); - sData = GetWIData(str); - SetDlgItemTextA(hwndDlg, IDC_IURL, sData->DefaultURL); - break; - - case IDC_RESET2: - // reset the weathe map url to service default - GetDlgItemText(hwndDlg, IDC_ID, str, _countof(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, _countof(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, _countof(str)); - g_plugin.setWString(hContact, "ID", str); - if ((uint8_t)IsDlgButtonChecked(hwndDlg, IDC_DEFA)) { // if default station is set - mir_wstrcpy(opt.Default, str); - opt.DefStn = hContact; - g_plugin.setWString("Default", opt.Default); - } - GetDlgItemText(hwndDlg, IDC_NAME, city, _countof(city)); - g_plugin.setWString(hContact, "Nick", city); - mir_snwprintf(str2, TranslateT("Current weather information for %s."), city); - if ((uint8_t)IsDlgButtonChecked(hwndDlg, IDC_External)) { - GetDlgItemText(hwndDlg, IDC_LOG, str, _countof(str)); - g_plugin.setWString(hContact, "Log", str); - } - else g_plugin.delSetting(hContact, "Log"); - - GetDlgItemText(hwndDlg, IDC_IURL, str, _countof(str)); - g_plugin.setWString(hContact, "InfoURL", str); - - GetDlgItemText(hwndDlg, IDC_MURL, str, _countof(str)); - g_plugin.setWString(hContact, "MapURL", str); - g_plugin.setWord(hContact, "Status", ID_STATUS_OFFLINE); - g_plugin.setWord(hContact, "StatusIcon", -1); - AvatarDownloaded(hContact); - g_plugin.setWString(hContact, "About", str2); - g_plugin.setByte(hContact, "History", (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_Internal)); - g_plugin.setByte(hContact, "Overwrite", (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_Overwrite)); - g_plugin.setByte(hContact, "File", (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_External)); - g_plugin.setByte(hContact, "DPopUp", (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_DPop)); - g_plugin.setByte(hContact, "DAutoUpdate", (uint8_t)IsDlgButtonChecked(hwndDlg, IDC_DAutoUpdate)); - - // re-enable the protocol and update the data for the station - g_plugin.setString(hContact, "LastCondition", "None"); - UpdateSingleStation(hContact, 0); - __fallthrough; - - case IDCANCEL: - // 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); - IcoLib_ReleaseIcon(wndData->hFile); - IcoLib_ReleaseIcon(wndData->hRename); - IcoLib_ReleaseIcon(wndData->hSrchAll); - IcoLib_ReleaseIcon(wndData->hUserDetail); - mir_free(wndData); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - - WindowList_Remove(hWindowList, hwndDlg); - Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, "EditSetting_"); - break; } - return FALSE; -} -// show edit settings dialog -// wParam = current contact -INT_PTR EditSettings(WPARAM wParam, LPARAM) + void onClick_Reset1(CCtrlButton *) + { + // reset the more info url to service default + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + GetSvc(str); + sData = GetWIData(str); + SetDlgItemTextA(m_hwnd, IDC_IURL, sData->DefaultURL); + } + + void onClick_Reset2(CCtrlButton *) + { + // reset the weathe map url to service default + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + GetSvc(str); + sData = GetWIData(str); + SetDlgItemText(m_hwnd, IDC_MURL, sData->DefaultMap); + } + + void onClick_SvcInfo(CCtrlButton *) + { + // display the information of the ini file used by the weather station + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + GetSvc(str); + GetINIInfo(str); + } + + void onClick_Change(CCtrlButton *) + { + // temporary disable the protocol while applying the change + // start writing the new settings to database + GetDlgItemText(m_hwnd, IDC_ID, str, _countof(str)); + g_plugin.setWString(hContact, "ID", str); + if ((uint8_t)IsDlgButtonChecked(m_hwnd, IDC_DEFA)) { // if default station is set + mir_wstrcpy(m_proto->opt.Default, str); + m_proto->opt.DefStn = hContact; + g_plugin.setWString("Default", m_proto->opt.Default); + } + GetDlgItemText(m_hwnd, IDC_NAME, city, _countof(city)); + g_plugin.setWString(hContact, "Nick", city); + mir_snwprintf(str2, TranslateT("Current weather information for %s."), city); + if ((uint8_t)IsDlgButtonChecked(m_hwnd, IDC_External)) { + GetDlgItemText(m_hwnd, IDC_LOG, str, _countof(str)); + m_proto->setWString(hContact, "Log", str); + } + else m_proto->delSetting(hContact, "Log"); + + GetDlgItemText(m_hwnd, IDC_IURL, str, _countof(str)); + m_proto->setWString(hContact, "InfoURL", str); + + GetDlgItemText(m_hwnd, IDC_MURL, str, _countof(str)); + m_proto->setWString(hContact, "MapURL", str); + m_proto->setWord(hContact, "Status", ID_STATUS_OFFLINE); + m_proto->setWord(hContact, "StatusIcon", -1); + AvatarDownloaded(hContact); + m_proto->setWString(hContact, "About", str2); + m_proto->setByte(hContact, "History", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_Internal)); + m_proto->setByte(hContact, "Overwrite", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_Overwrite)); + m_proto->setByte(hContact, "File", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_External)); + m_proto->setByte(hContact, "DPopUp", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_DPop)); + m_proto->setByte(hContact, "DAutoUpdate", (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_DAutoUpdate)); + + // re-enable the protocol and update the data for the station + g_plugin.setString(hContact, "LastCondition", "None"); + m_proto->UpdateSingleStation(hContact, 0); + } +}; + +INT_PTR CWeatherProto::EditSettings(WPARAM wParam, LPARAM) { HWND hEditDlg = WindowList_Find(hWindowList, wParam); @@ -410,34 +436,30 @@ INT_PTR EditSettings(WPARAM wParam, LPARAM) else { // if the dialog box is not opened, open a new one if (IsMyContact(wParam)) - CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_EDIT), nullptr, DlgProcChange, (LPARAM)wParam); + (new CEditDlg(this, wParam))->Create(); } return 0; } -//============ 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) -{ - if (!IsMyContact(wParam)) - return 0; - removeWindow(wParam); +bool CWeatherProto::OnContactDeleted(MCONTACT hContact, uint32_t) +{ + removeWindow(hContact); // exit this function if it is not default station - ptrW tszID(g_plugin.getWStringA(wParam, "ID")); + ptrW tszID(getWStringA(hContact, "ID")); if (tszID != NULL) if (mir_wstrcmp(tszID, opt.Default)) - return 0; + return false; // now the default station is deleted, try to get a new one // start looking for other weather stations - for (auto &hContact : Contacts(MODULENAME)) { - tszID = g_plugin.getWStringA(hContact, "ID"); + for (auto &cc: AccContacts()) { + tszID = getWStringA(cc, "ID"); if (tszID == NULL) continue; @@ -445,15 +467,15 @@ int ContactDeleted(WPARAM wParam, LPARAM) // this is the first weather station encountered from the search if (mir_wstrcmp(opt.Default, tszID)) { wcsncpy_s(opt.Default, tszID, _TRUNCATE); - opt.DefStn = hContact; - ptrW tszNick(g_plugin.getWStringA(hContact, "Nick")); + opt.DefStn = cc; + ptrW tszNick(g_plugin.getWStringA(cc, "Nick")); if (tszNick != NULL) { wchar_t str[255]; mir_snwprintf(str, TranslateT("%s is now the default weather station"), (wchar_t*)tszNick); MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); } g_plugin.setWString("Default", opt.Default); - return 0; // exit this function quickly + return true; } } @@ -461,11 +483,5 @@ int ContactDeleted(WPARAM wParam, LPARAM) opt.Default[0] = 0; // no default station opt.DefStn = NULL; g_plugin.setWString("Default", opt.Default); - return 0; -} - -BOOL IsMyContact(MCONTACT hContact) -{ - const char *szProto = Proto_GetBaseAccountName(hContact); - return szProto != nullptr && mir_strcmp(MODULENAME, szProto) == 0; + return true; } diff --git a/protocols/Weather/src/weather_conv.cpp b/protocols/Weather/src/weather_conv.cpp index f2d18dc240..7b1897834e 100644 --- a/protocols/Weather/src/weather_conv.cpp +++ b/protocols/Weather/src/weather_conv.cpp @@ -25,11 +25,11 @@ string conversions, display text parsing, etc #include "stdafx.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(wchar_t *s) { BOOL tag = FALSE; @@ -47,7 +47,7 @@ BOOL is_number(wchar_t *s) return FALSE; } -static void numToStr(double num, wchar_t *str, size_t strSize) +void CWeatherProto::numToStr(double num, wchar_t *str, size_t strSize) { int i = (int)(num * (opt.NoFrac ? 10 : 100)); int u = abs(i); @@ -69,13 +69,13 @@ static void numToStr(double num, wchar_t *str, size_t strSize) mir_snwprintf(str, strSize, L"%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(wchar_t *tempchar, wchar_t *unit, wchar_t *str) + +void CWeatherProto::GetTemp(wchar_t *tempchar, wchar_t *unit, wchar_t *str) { // unit can be C, F double temp; @@ -123,11 +123,13 @@ void GetTemp(wchar_t *tempchar, wchar_t *unit, wchar_t *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // 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(wchar_t *tempchar, wchar_t *unit, wchar_t *str) + +void CWeatherProto::GetPressure(wchar_t *tempchar, wchar_t *unit, wchar_t *str) { // unit can be kPa, hPa, mb, in, mm, torr double tempunit = 0, output; @@ -180,11 +182,13 @@ void GetPressure(wchar_t *tempchar, wchar_t *unit, wchar_t *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // speed conversion // tempchar = the string containing the speed value // unit = the unit for speed // return value = the converted speed with unit; if fail, return _T("" -void GetSpeed(wchar_t *tempchar, wchar_t *unit, wchar_t *str) + +void CWeatherProto::GetSpeed(wchar_t *tempchar, wchar_t *unit, wchar_t *str) { // unit can be km/h, mph, m/s, knots double tempunit; @@ -229,11 +233,13 @@ void GetSpeed(wchar_t *tempchar, wchar_t *unit, wchar_t *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // 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(wchar_t *tempchar, wchar_t *unit, wchar_t *str) + +void CWeatherProto::GetDist(wchar_t *tempchar, wchar_t *unit, wchar_t *str) { // unit can be km, miles double tempunit = 0, output; @@ -269,11 +275,13 @@ void GetDist(wchar_t *tempchar, wchar_t *unit, wchar_t *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // 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(wchar_t *tempchar, wchar_t *unit, wchar_t *str) + +void CWeatherProto::GetElev(wchar_t *tempchar, wchar_t *unit, wchar_t *str) { // unit can be ft, m double tempunit = 0, output; @@ -309,8 +317,7 @@ void GetElev(wchar_t *tempchar, wchar_t *unit, wchar_t *str) } } -//============ 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 @@ -373,9 +380,9 @@ uint16_t GetIcon(const wchar_t *cond, WIDATA *Data) return NA; } -//============ STRING CONVERSIONS ============ -// +///////////////////////////////////////////////////////////////////////////////////////// // this function convert the string to the format with 1 upper case followed by lower case char + void CaseConv(wchar_t *str) { bool nextUp = true; @@ -391,9 +398,10 @@ void CaseConv(wchar_t *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // the next 2 functions are copied from miranda source // str = the string to modify -// + void TrimString(char *str) { size_t len, start; @@ -414,7 +422,9 @@ void TrimString(wchar_t *str) memmove(str, str + start, (len - start + 1) * sizeof(wchar_t)); } +///////////////////////////////////////////////////////////////////////////////////////// // convert \t to tab and \n to linefeed + void ConvertBackslashes(char *str) { for (char *pstr = str; *pstr; pstr = CharNextA(pstr)) { @@ -429,9 +439,11 @@ void ConvertBackslashes(char *str) } } +///////////////////////////////////////////////////////////////////////////////////////// // replace spaces with _T("%20" // dis = original string // return value = the modified string with space -> _T("%20" + char *GetSearchStr(char *dis) { char *pstr = dis; @@ -448,12 +460,12 @@ char *GetSearchStr(char *dis) 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 + wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t *str) { wchar_t lpzDate[32], chr; @@ -542,11 +554,11 @@ INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam) return (INT_PTR)GetDisplay(&winfo, (wchar_t*)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(wchar_t *pszID) { wchar_t *chop = wcschr(pszID, '/'); @@ -556,9 +568,11 @@ void GetSvc(wchar_t *pszID) 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(wchar_t *pszID) { wchar_t *chop = wcschr(pszID, '/'); @@ -568,7 +582,7 @@ void GetID(wchar_t *pszID) 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 diff --git a/protocols/Weather/src/weather_data.cpp b/protocols/Weather/src/weather_data.cpp index 0f3cf9ccc9..2ee99cda25 100644 --- a/protocols/Weather/src/weather_data.cpp +++ b/protocols/Weather/src/weather_data.cpp @@ -25,11 +25,11 @@ saving individual weather data for a weather contact. #include "stdafx.h" -//============ 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(MCONTACT hContact, wchar_t *id, int idlen) { // accessing the database @@ -37,9 +37,11 @@ void GetStationID(MCONTACT hContact, wchar_t *id, int idlen) id[0] = 0; } +///////////////////////////////////////////////////////////////////////////////////////// // initialize weather info by loading values from database // hContact = current contact handle // return value = the current weather information in WEATHERINFO struct + WEATHERINFO LoadWeatherInfo(MCONTACT hContact) { // obtaining values from the DB @@ -82,8 +84,10 @@ WEATHERINFO LoadWeatherInfo(MCONTACT hContact) return winfo; } +///////////////////////////////////////////////////////////////////////////////////////// // getting weather setting from database // return 0 on success + int DBGetData(MCONTACT hContact, char *setting, DBVARIANT *dbv) { if (db_get_ws(hContact, WEATHERCONDITION, setting, dbv)) { @@ -99,47 +103,47 @@ int DBGetData(MCONTACT hContact, char *setting, DBVARIANT *dbv) } -//============ ERASE OLD SETTINGS ============ -// +///////////////////////////////////////////////////////////////////////////////////////// // erase all current weather information from database // lastver = the last used version number in dword (using PLUGIN_MAKE_VERSION) -void EraseAllInfo() + +void CWeatherProto::EraseAllInfo() { wchar_t str[255]; int ContactCount = 0; MCONTACT LastContact = NULL; DBVARIANT dbv; // loop through all contacts - for (auto &hContact : Contacts(MODULENAME)) { - g_plugin.setWord(hContact, "Status", ID_STATUS_OFFLINE); - g_plugin.setWord(hContact, "StatusIcon", -1); + for (auto &hContact : AccContacts()) { + setWord(hContact, "Status", ID_STATUS_OFFLINE); + setWord(hContact, "StatusIcon", -1); db_unset(hContact, "CList", "MyHandle"); // clear all data - if (g_plugin.getWString(hContact, "Nick", &dbv)) { - g_plugin.setWString(hContact, "Nick", TranslateT("<Enter city name here>")); - g_plugin.setString(hContact, "LastLog", "never"); - g_plugin.setString(hContact, "LastCondition", "None"); - g_plugin.setString(hContact, "LastTemperature", "None"); + if (getWString(hContact, "Nick", &dbv)) { + setWString(hContact, "Nick", TranslateT("<Enter city name here>")); + setString(hContact, "LastLog", "never"); + setString(hContact, "LastCondition", "None"); + setString(hContact, "LastTemperature", "None"); } else db_free(&dbv); DBDataManage(hContact, WDBM_REMOVE, 0, 0); db_set_s(hContact, "UserInfo", "MyNotes", ""); // reset update tag - g_plugin.setByte(hContact, "IsUpdated", FALSE); + setByte(hContact, "IsUpdated", FALSE); // reset logging settings - if (!g_plugin.getWString(hContact, "Log", &dbv)) { - g_plugin.setByte(hContact, "File", (uint8_t)(dbv.pwszVal[0] != 0)); + if (!getWString(hContact, "Log", &dbv)) { + setByte(hContact, "File", (uint8_t)(dbv.pwszVal[0] != 0)); db_free(&dbv); } - else g_plugin.setByte(hContact, "File", FALSE); + else setByte(hContact, "File", FALSE); // if no default station find, assign a new one if (opt.Default[0] == 0) { GetStationID(hContact, opt.Default, _countof(opt.Default)); opt.DefStn = hContact; - if (!g_plugin.getWString(hContact, "Nick", &dbv)) { + if (!getWString(hContact, "Nick", &dbv)) { mir_snwprintf(str, TranslateT("%s is now the default weather station"), dbv.pwszVal); db_free(&dbv); MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); @@ -147,7 +151,7 @@ void EraseAllInfo() } // get the handle of the default station if (opt.DefStn == NULL) { - if (!g_plugin.getWString(hContact, "ID", &dbv)) { + if (!getWString(hContact, "ID", &dbv)) { if (!mir_wstrcmp(dbv.pwszVal, opt.Default)) opt.DefStn = hContact; db_free(&dbv); @@ -161,22 +165,24 @@ void EraseAllInfo() // if (ContactCount != 0) status = ONLINE; // in case where the default station is missing if (opt.DefStn == NULL && ContactCount != 0) { - if (!g_plugin.getWString(LastContact, "ID", &dbv)) { + if (!getWString(LastContact, "ID", &dbv)) { wcsncpy(opt.Default, dbv.pwszVal, _countof(opt.Default) - 1); db_free(&dbv); } opt.DefStn = LastContact; - if (!g_plugin.getWString(LastContact, "Nick", &dbv)) { + if (!getWString(LastContact, "Nick", &dbv)) { mir_snwprintf(str, TranslateT("%s is now the default weather station"), dbv.pwszVal); db_free(&dbv); MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION); } } // save option in case of default station changed - g_plugin.setWString("Default", opt.Default); + setWString("Default", opt.Default); } -void ConvertDataValue(WIDATAITEM *UpdateData, wchar_t *Data) +///////////////////////////////////////////////////////////////////////////////////////// + +void CWeatherProto::ConvertDataValue(WIDATAITEM *UpdateData, wchar_t *Data) { wchar_t str[MAX_DATA_LEN]; @@ -236,14 +242,13 @@ void ConvertDataValue(WIDATAITEM *UpdateData, wchar_t *Data) } } -//============ 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, wchar_t *Data, wchar_t **szData) + +void CWeatherProto::GetDataValue(WIDATAITEM *UpdateData, wchar_t *Data, wchar_t **szData) { wchar_t last = 0, current, *start, *end; unsigned startloc = 0, endloc = 0, respos = 0; @@ -340,8 +345,7 @@ void GetDataValue(WIDATAITEM *UpdateData, wchar_t *Data, wchar_t **szData) *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 @@ -388,10 +392,11 @@ void wfree(wchar_t *&Data) Data = nullptr; } -//============ MANAGE THE ITEMS STORED IN DB ============ +///////////////////////////////////////////////////////////////////////////////////////// // get single setting that is found // szSetting = the setting name // lparam = the counter + int GetWeatherDataFromDB(const char *szSetting, void *lparam) { LIST<char> *pList = (LIST<char>*)lparam; @@ -399,9 +404,10 @@ int GetWeatherDataFromDB(const char *szSetting, void *lparam) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// // remove or display the weather information for a contact // hContact - the contact in which the info is going to be removed -// + void DBDataManage(MCONTACT hContact, uint16_t Mode, WPARAM wParam, LPARAM) { // get all the settings and store them in a temporary list diff --git a/protocols/Weather/src/weather_http.cpp b/protocols/Weather/src/weather_http.cpp index bfbcadc589..91ae9b911c 100644 --- a/protocols/Weather/src/weather_http.cpp +++ b/protocols/Weather/src/weather_http.cpp @@ -25,15 +25,13 @@ from the web using netlib #include "stdafx.h" -HNETLIBUSER hNetlibUser; - -//============ 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 *userAgent, wchar_t **szData) + +int CWeatherProto::InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **szData) { if (userAgent == nullptr || userAgent[0] == 0) userAgent = NETLIB_USER_AGENT; @@ -50,7 +48,7 @@ int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **s nlhr.AddHeader("Cookie", cookie); // download the page - NLHR_PTR nlhrReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); + NLHR_PTR nlhrReply(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); if (nlhrReply == nullptr) { // if the data does not downloaded successfully (ie. disconnected), then return 1000 as error code *szData = (wchar_t*)mir_alloc(512); @@ -117,15 +115,3 @@ int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **s // make a copy of the retrieved data, then free the memory of the http reply return result; } - -//============ NETLIB INITIALIZATION ============ -// -// initialize netlib support for weather protocol -void NetlibInit(void) -{ - NETLIBUSER nlu = {}; - nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_NOHTTPSOPTION; - nlu.szSettingsModule = MODULENAME; - nlu.szDescriptiveName.a = MODULENAME; - hNetlibUser = Netlib_RegisterUser(&nlu); -} diff --git a/protocols/Weather/src/weather_ini.cpp b/protocols/Weather/src/weather_ini.cpp index 0929b06c1e..0296e0a7d8 100644 --- a/protocols/Weather/src/weather_ini.cpp +++ b/protocols/Weather/src/weather_ini.cpp @@ -198,7 +198,8 @@ static INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPAR break; case IDC_STEP4: - WeatherAdd(0, 0); + db_set_s(0, "FindAdd", "LastSearched", "Weather"); + CallService(MS_FINDADD_FINDADD, 0, 0); __fallthrough; case IDCANCEL: diff --git a/protocols/Weather/src/weather_mwin.cpp b/protocols/Weather/src/weather_mwin.cpp index da08be4ce1..d6ae726046 100644 --- a/protocols/Weather/src/weather_mwin.cpp +++ b/protocols/Weather/src/weather_mwin.cpp @@ -27,6 +27,7 @@ HGENMENU hMwinMenu; struct MWinDataType { + CWeatherProto *ppro; MCONTACT hContact; HWND hAvt; BOOL haveAvatar; @@ -44,7 +45,8 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); data->hContact = (DWORD_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams; - data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD, 0, 0, opt.AvatarSize, opt.AvatarSize, hwnd, 0, g_plugin.getInst(), 0); + data->ppro = (CWeatherProto *)Proto_GetContactInstance(data->hContact); + data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD, 0, 0, data->ppro->opt.AvatarSize, data->ppro->opt.AvatarSize, hwnd, 0, g_plugin.getInst(), 0); if (data->hAvt) SendMessage(data->hAvt, AVATAR_SETCONTACT, 0, (LPARAM)data->hContact); break; @@ -97,7 +99,7 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara break; case WM_LBUTTONDBLCLK: - BriefInfo(data->hContact, 0); + data->ppro->BriefInfo(data->hContact, 0); break; case WM_COMMAND: //Needed by the contact's context menu @@ -124,7 +126,7 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara break; case WM_REDRAWWIN: - if (data->hAvt != nullptr) MoveWindow(data->hAvt, 0, 0, opt.AvatarSize, opt.AvatarSize, TRUE); + if (data->hAvt != nullptr) MoveWindow(data->hAvt, 0, 0, data->ppro->opt.AvatarSize, data->ppro->opt.AvatarSize, TRUE); RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); break; @@ -133,7 +135,7 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara RECT r, rc; if (GetUpdateRect(hwnd, &r, FALSE)) { - int picSize = opt.AvatarSize; + int picSize = data->ppro->opt.AvatarSize; HICON hIcon = nullptr; if (!data->haveAvatar) { @@ -274,9 +276,9 @@ INT_PTR Mwin_MenuClicked(WPARAM wParam, LPARAM) return 0; } -int BuildContactMenu(WPARAM wparam, LPARAM) +int CWeatherProto::BuildContactMenu(WPARAM wparam, LPARAM) { - int flags = g_plugin.getDword(wparam, "mwin") ? CMIF_CHECKED : 0; + int flags = getDword(wparam, "mwin") ? CMIF_CHECKED : 0; Menu_ModifyItem(hMwinMenu, nullptr, INVALID_HANDLE_VALUE, flags); return 0; } @@ -287,7 +289,7 @@ int RedrawFrame(WPARAM, LPARAM) return 0; } -void InitMwin(void) +void CWeatherProto::InitMwin(void) { if (!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) return; @@ -337,16 +339,16 @@ void InitMwin(void) mir_strcpy(fontid.setting, "fnt1"); g_plugin.addFont(&fontid); - for (auto &hContact : Contacts(MODULENAME)) + for (auto &hContact : AccContacts()) if (g_plugin.getDword(hContact, "mwin")) addWindow(hContact); hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame); } -void DestroyMwin(void) +void CWeatherProto::DestroyMwin(void) { - for (auto &hContact : Contacts(MODULENAME)) { + for (auto &hContact : AccContacts()) { uint32_t frameId = g_plugin.getDword(hContact, "mwin"); if (frameId) CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0); diff --git a/protocols/Weather/src/weather_opt.cpp b/protocols/Weather/src/weather_opt.cpp index 1d92f20191..5ee7e3353d 100644 --- a/protocols/Weather/src/weather_opt.cpp +++ b/protocols/Weather/src/weather_opt.cpp @@ -24,7 +24,6 @@ contain code for saving/loading options from the database. #include "stdafx.h" -static BOOL opt_startup; int RedrawFrame(WPARAM wParam, LPARAM lParam); //============ LOADING AND SAVING OPTIONS =========== @@ -54,21 +53,21 @@ const wchar_t* GetDefaultText(int c) return L""; } -CMStringW GetTextValue(int c) +CMStringW CWeatherProto::GetTextValue(int c) { CMStringW ret; switch (c) { - case 'C': ret = g_plugin.getMStringW("DisplayText"); break; - case 'b': ret = g_plugin.getMStringW("BriefTextTitle"); break; - case 'B': ret = g_plugin.getMStringW("BriefText"); break; - case 'N': ret = g_plugin.getMStringW("NoteText"); break; - case 'E': ret = g_plugin.getMStringW("ExtText"); break; - case 'H': ret = g_plugin.getMStringW("HistoryText"); break; - case 'X': ret = g_plugin.getMStringW("ExtraText"); break; - case 'S': ret = g_plugin.getMStringW("StatusText"); break; - case 'P': ret = g_plugin.getMStringW("PopupTitle"); break; - case 'p': ret = g_plugin.getMStringW("PopupText"); break; + case 'C': ret = getMStringW("DisplayText"); break; + case 'b': ret = getMStringW("BriefTextTitle"); break; + case 'B': ret = getMStringW("BriefText"); break; + case 'N': ret = getMStringW("NoteText"); break; + case 'E': ret = getMStringW("ExtText"); break; + case 'H': ret = getMStringW("HistoryText"); break; + case 'X': ret = getMStringW("ExtraText"); break; + case 'S': ret = getMStringW("StatusText"); break; + case 'P': ret = getMStringW("PopupTitle"); break; + case 'p': ret = getMStringW("PopupText"); break; } return (ret.IsEmpty()) ? GetDefaultText(c) : ret; @@ -76,248 +75,228 @@ CMStringW GetTextValue(int c) // load options from database + set default if the setting does not exist -void LoadOptions(void) +void CWeatherProto::LoadOptions(void) { memset(&opt, 0, sizeof(opt)); // main options - opt.StartupUpdate = g_plugin.getByte("StartupUpdate", true); - opt.AutoUpdate = g_plugin.getByte("AutoUpdate", true); - opt.UpdateTime = g_plugin.getWord("UpdateTime", 30); - opt.NoProtoCondition = g_plugin.getByte("NoStatus", true); - opt.UpdateOnlyConditionChanged = g_plugin.getByte("CondChangeAsUpdate", true); - opt.RemoveOldData = g_plugin.getByte("RemoveOld", false); - opt.MakeItalic = g_plugin.getByte("MakeItalic", true); - opt.AvatarSize = g_plugin.getByte("AvatarSize", 128); + opt.StartupUpdate = getByte("StartupUpdate", true); + opt.AutoUpdate = getByte("AutoUpdate", true); + opt.UpdateTime = getWord("UpdateTime", 30); + opt.UpdateOnlyConditionChanged = getByte("CondChangeAsUpdate", true); + opt.RemoveOldData = getByte("RemoveOld", false); + opt.MakeItalic = getByte("MakeItalic", true); + opt.AvatarSize = getByte("AvatarSize", 128); // units - opt.tUnit = g_plugin.getWord("tUnit", 1); - opt.wUnit = g_plugin.getWord("wUnit", 2); - opt.vUnit = g_plugin.getWord("vUnit", 1); - opt.pUnit = g_plugin.getWord("pUnit", 4); - opt.dUnit = g_plugin.getWord("dUnit", 1); - opt.eUnit = g_plugin.getWord("eUnit", 2); - - ptrW szValue(g_plugin.getWStringA("DegreeSign")); + opt.tUnit = getWord("tUnit", 1); + opt.wUnit = getWord("wUnit", 2); + opt.vUnit = getWord("vUnit", 1); + opt.pUnit = getWord("pUnit", 4); + opt.dUnit = getWord("dUnit", 1); + opt.eUnit = getWord("eUnit", 2); + + ptrW szValue(getWStringA("DegreeSign")); wcsncpy_s(opt.DegreeSign, (szValue == NULL) ? L"" : szValue, _TRUNCATE); - opt.DoNotAppendUnit = g_plugin.getByte("DoNotAppendUnit", 0); - opt.NoFrac = g_plugin.getByte("NoFractions", 0); + opt.DoNotAppendUnit = getByte("DoNotAppendUnit", 0); + opt.NoFrac = getByte("NoFractions", 0); // advanced - opt.DisCondIcon = g_plugin.getByte("DisableConditionIcon", false); + opt.DisCondIcon = getByte("DisableConditionIcon", false); // popup options - opt.UpdatePopup = g_plugin.getByte("UpdatePopup", true); - opt.AlertPopup = g_plugin.getByte("AlertPopup", true); - opt.PopupOnChange = g_plugin.getByte("PopUpOnChange", true); - opt.ShowWarnings = g_plugin.getByte("ShowWarnings", true); + opt.UpdatePopup = getByte("UpdatePopup", true); + opt.AlertPopup = getByte("AlertPopup", true); + opt.PopupOnChange = getByte("PopUpOnChange", true); + opt.ShowWarnings = getByte("ShowWarnings", true); // popup colors - opt.BGColour = g_plugin.getDword("BackgroundColour", GetSysColor(COLOR_BTNFACE)); - opt.TextColour = g_plugin.getDword("TextColour", GetSysColor(COLOR_WINDOWTEXT)); - opt.UseWinColors = g_plugin.getByte("UseWinColors", false); + opt.BGColour = getDword("BackgroundColour", GetSysColor(COLOR_BTNFACE)); + opt.TextColour = getDword("TextColour", GetSysColor(COLOR_WINDOWTEXT)); + opt.UseWinColors = getByte("UseWinColors", false); // popup actions - opt.LeftClickAction = g_plugin.getDword("LeftClickAction", IDM_M2); - opt.RightClickAction = g_plugin.getDword("RightClickAction", IDM_M1); + opt.LeftClickAction = getDword("LeftClickAction", IDM_M2); + opt.RightClickAction = getDword("RightClickAction", IDM_M1); // popup delay - opt.pDelay = g_plugin.getDword("PopupDelay", 0); + opt.pDelay = getDword("PopupDelay", 0); // misc - if (szValue = g_plugin.getWStringA("Default")) + if (szValue = getWStringA("Default")) wcsncpy_s(opt.Default, szValue, _TRUNCATE); else opt.Default[0] = 0; } // save the options to database -void SaveOptions(void) +void CWeatherProto::SaveOptions(void) { // main options - g_plugin.setByte("StartupUpdate", (uint8_t)opt.StartupUpdate); - g_plugin.setByte("AutoUpdate", (uint8_t)opt.AutoUpdate); - g_plugin.setWord("UpdateTime", opt.UpdateTime); - g_plugin.setByte("NoStatus", (uint8_t)opt.NoProtoCondition); - g_plugin.setByte("CondChangeAsUpdate", (uint8_t)opt.UpdateOnlyConditionChanged); - g_plugin.setByte("RemoveOld", (uint8_t)opt.RemoveOldData); - g_plugin.setByte("MakeItalic", (uint8_t)opt.MakeItalic); - g_plugin.setByte("AvatarSize", (uint8_t)opt.AvatarSize); + setByte("StartupUpdate", (uint8_t)opt.StartupUpdate); + setByte("AutoUpdate", (uint8_t)opt.AutoUpdate); + setWord("UpdateTime", opt.UpdateTime); + setByte("CondChangeAsUpdate", (uint8_t)opt.UpdateOnlyConditionChanged); + setByte("RemoveOld", (uint8_t)opt.RemoveOldData); + setByte("MakeItalic", (uint8_t)opt.MakeItalic); + setByte("AvatarSize", (uint8_t)opt.AvatarSize); // units - g_plugin.setWord("tUnit", opt.tUnit); - g_plugin.setWord("wUnit", opt.wUnit); - g_plugin.setWord("vUnit", opt.vUnit); - g_plugin.setWord("pUnit", opt.pUnit); - g_plugin.setWord("dUnit", opt.dUnit); - g_plugin.setWord("eUnit", opt.eUnit); - g_plugin.setWString("DegreeSign", opt.DegreeSign); - g_plugin.setByte("DoNotAppendUnit", (uint8_t)opt.DoNotAppendUnit); - g_plugin.setByte("NoFractions", (uint8_t)opt.NoFrac); + setWord("tUnit", opt.tUnit); + setWord("wUnit", opt.wUnit); + setWord("vUnit", opt.vUnit); + setWord("pUnit", opt.pUnit); + setWord("dUnit", opt.dUnit); + setWord("eUnit", opt.eUnit); + setWString("DegreeSign", opt.DegreeSign); + setByte("DoNotAppendUnit", (uint8_t)opt.DoNotAppendUnit); + setByte("NoFractions", (uint8_t)opt.NoFrac); // advanced - g_plugin.setByte("DisableConditionIcon", (uint8_t)opt.DisCondIcon); + setByte("DisableConditionIcon", (uint8_t)opt.DisCondIcon); // popup options - g_plugin.setByte("UpdatePopup", (uint8_t)opt.UpdatePopup); - g_plugin.setByte("AlertPopup", (uint8_t)opt.AlertPopup); - g_plugin.setByte("PopUpOnChange", (uint8_t)opt.PopupOnChange); - g_plugin.setByte("ShowWarnings", (uint8_t)opt.ShowWarnings); + setByte("UpdatePopup", (uint8_t)opt.UpdatePopup); + setByte("AlertPopup", (uint8_t)opt.AlertPopup); + setByte("PopUpOnChange", (uint8_t)opt.PopupOnChange); + setByte("ShowWarnings", (uint8_t)opt.ShowWarnings); // popup colors - g_plugin.setDword("BackgroundColour", opt.BGColour); - g_plugin.setDword("TextColour", opt.TextColour); - g_plugin.setByte("UseWinColors", (uint8_t)opt.UseWinColors); + setDword("BackgroundColour", opt.BGColour); + setDword("TextColour", opt.TextColour); + setByte("UseWinColors", (uint8_t)opt.UseWinColors); // popup actions - g_plugin.setDword("LeftClickAction", opt.LeftClickAction); - g_plugin.setDword("RightClickAction", opt.RightClickAction); + setDword("LeftClickAction", opt.LeftClickAction); + setDword("RightClickAction", opt.RightClickAction); // popup delay - g_plugin.setDword("PopupDelay", opt.pDelay); + setDword("PopupDelay", opt.pDelay); // misc stuff - g_plugin.setWString("Default", opt.Default); + setWString("Default", opt.Default); } -//============ MAIN OPTIONS ============ +///////////////////////////////////////////////////////////////////////////////////////// // weather options -static INT_PTR CALLBACK OptionsProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) +class COptionsDlg : public CWeatherDlgBase { - wchar_t str[512]; +public: + COptionsDlg(CWeatherProto *ppro) : + CWeatherDlgBase(ppro, IDD_OPTIONS) + {} + + bool OnInitDialog() override + { + wchar_t str[512]; + auto &opt = m_proto->opt; - switch (msg) { - case WM_INITDIALOG: - opt_startup = TRUE; - TranslateDialogDefault(hdlg); - // load settings _ltow(opt.UpdateTime, str, 10); - SetDlgItemText(hdlg, IDC_UPDATETIME, str); - SetDlgItemText(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 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_UPDATE, opt.AutoUpdate ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_PROTOCOND, !opt.NoProtoCondition ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_UPDCONDCHG, opt.UpdateOnlyConditionChanged ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_REMOVEOLD, opt.RemoveOldData ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_MAKEI, opt.MakeItalic ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_DISCONDICON, opt.DisCondIcon ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_DONOTAPPUNITS, opt.DoNotAppendUnit ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_NOFRAC, opt.NoFrac ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemText(m_hwnd, IDC_UPDATETIME, str); + SetDlgItemText(m_hwnd, IDC_DEGREE, opt.DegreeSign); + + SendDlgItemMessage(m_hwnd, IDC_AVATARSPIN, UDM_SETRANGE32, 0, 999); + SendDlgItemMessage(m_hwnd, IDC_AVATARSPIN, UDM_SETPOS, 0, opt.AvatarSize); + SendDlgItemMessage(m_hwnd, IDC_AVATARSIZE, EM_LIMITTEXT, 3, 0); + + CheckDlgButton(m_hwnd, IDC_STARTUPUPD, opt.StartupUpdate ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_UPDATE, opt.AutoUpdate ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_UPDCONDCHG, opt.UpdateOnlyConditionChanged ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_REMOVEOLD, opt.RemoveOldData ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_MAKEI, opt.MakeItalic ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_DISCONDICON, opt.DisCondIcon ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_DONOTAPPUNITS, opt.DoNotAppendUnit ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_NOFRAC, opt.NoFrac ? BST_CHECKED : BST_UNCHECKED); // 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; + case 1: CheckRadioButton(m_hwnd, IDC_T1, IDC_T2, IDC_T1); break; + case 2: CheckRadioButton(m_hwnd, 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; + case 1: CheckRadioButton(m_hwnd, IDC_W1, IDC_W4, IDC_W1); break; + case 2: CheckRadioButton(m_hwnd, IDC_W1, IDC_W4, IDC_W2); break; + case 3: CheckRadioButton(m_hwnd, IDC_W1, IDC_W4, IDC_W3); break; + case 4: CheckRadioButton(m_hwnd, 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; + case 1: CheckRadioButton(m_hwnd, IDC_V1, IDC_V2, IDC_V1); break; + case 2: CheckRadioButton(m_hwnd, 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; + case 1: CheckRadioButton(m_hwnd, IDC_P1, IDC_P4, IDC_P1); break; + case 2: CheckRadioButton(m_hwnd, IDC_P1, IDC_P4, IDC_P2); break; + case 3: CheckRadioButton(m_hwnd, IDC_P1, IDC_P4, IDC_P3); break; + case 4: CheckRadioButton(m_hwnd, 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; + case 1: CheckRadioButton(m_hwnd, IDC_D1, IDC_D3, IDC_D1); break; + case 2: CheckRadioButton(m_hwnd, IDC_D1, IDC_D3, IDC_D2); break; + case 3: CheckRadioButton(m_hwnd, 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; + case 1: CheckRadioButton(m_hwnd, IDC_E1, IDC_E2, IDC_E1); break; + case 2: CheckRadioButton(m_hwnd, 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 = MapCondToStatus(opt.DefStn); - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); - } - - // get update time and remove the old timer - GetDlgItemText(hdlg, IDC_UPDATETIME, str, _countof(str)); - opt.UpdateTime = (uint16_t)_wtoi(str); - if (opt.UpdateTime < 1) opt.UpdateTime = 1; - KillTimer(nullptr, timerId); - timerId = SetTimer(nullptr, 0, opt.UpdateTime * 60000, timerProc); - - // other general options - GetDlgItemText(hdlg, IDC_DEGREE, opt.DegreeSign, _countof(opt.DegreeSign)); - opt.StartupUpdate = IsDlgButtonChecked(hdlg, IDC_STARTUPUPD); - opt.AutoUpdate = IsDlgButtonChecked(hdlg, IDC_UPDATE); - opt.NoProtoCondition = BST_UNCHECKED == IsDlgButtonChecked(hdlg, IDC_PROTOCOND); - opt.DisCondIcon = IsDlgButtonChecked(hdlg, IDC_DISCONDICON); - opt.UpdateOnlyConditionChanged = (uint8_t)IsDlgButtonChecked(hdlg, IDC_UPDCONDCHG); - opt.RemoveOldData = IsDlgButtonChecked(hdlg, IDC_REMOVEOLD); - opt.MakeItalic = IsDlgButtonChecked(hdlg, IDC_MAKEI); - opt.AvatarSize = GetDlgItemInt(hdlg, IDC_AVATARSIZE, nullptr, 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 true; } - return 0; -} -//============ TEXT OPTION DIALOG ============ + bool OnApply() override + { + wchar_t str[512]; + auto &opt = m_proto->opt; + + // get update time and remove the old timer + GetDlgItemText(m_hwnd, IDC_UPDATETIME, str, _countof(str)); + opt.UpdateTime = (uint16_t)_wtoi(str); + if (opt.UpdateTime < 1) opt.UpdateTime = 1; + m_proto->RestartTimer(); + + // other general options + GetDlgItemText(m_hwnd, IDC_DEGREE, opt.DegreeSign, _countof(opt.DegreeSign)); + opt.StartupUpdate = IsDlgButtonChecked(m_hwnd, IDC_STARTUPUPD); + opt.AutoUpdate = IsDlgButtonChecked(m_hwnd, IDC_UPDATE); + opt.DisCondIcon = IsDlgButtonChecked(m_hwnd, IDC_DISCONDICON); + opt.UpdateOnlyConditionChanged = (uint8_t)IsDlgButtonChecked(m_hwnd, IDC_UPDCONDCHG); + opt.RemoveOldData = IsDlgButtonChecked(m_hwnd, IDC_REMOVEOLD); + opt.MakeItalic = IsDlgButtonChecked(m_hwnd, IDC_MAKEI); + opt.AvatarSize = GetDlgItemInt(m_hwnd, IDC_AVATARSIZE, nullptr, FALSE); + opt.DoNotAppendUnit = IsDlgButtonChecked(m_hwnd, IDC_DONOTAPPUNITS); + opt.NoFrac = IsDlgButtonChecked(m_hwnd, IDC_NOFRAC); + m_proto->UpdateMenu(opt.AutoUpdate); + + // save the units + if (IsDlgButtonChecked(m_hwnd, IDC_T1)) opt.tUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_T2)) opt.tUnit = 2; + if (IsDlgButtonChecked(m_hwnd, IDC_W1)) opt.wUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_W2)) opt.wUnit = 2; + if (IsDlgButtonChecked(m_hwnd, IDC_W3)) opt.wUnit = 3; + if (IsDlgButtonChecked(m_hwnd, IDC_W4)) opt.wUnit = 4; + if (IsDlgButtonChecked(m_hwnd, IDC_V1)) opt.vUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_V2)) opt.vUnit = 2; + if (IsDlgButtonChecked(m_hwnd, IDC_P1)) opt.pUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_P2)) opt.pUnit = 2; + if (IsDlgButtonChecked(m_hwnd, IDC_P3)) opt.pUnit = 3; + if (IsDlgButtonChecked(m_hwnd, IDC_P4)) opt.pUnit = 4; + if (IsDlgButtonChecked(m_hwnd, IDC_D1)) opt.dUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_D2)) opt.dUnit = 2; + if (IsDlgButtonChecked(m_hwnd, IDC_D3)) opt.dUnit = 3; + if (IsDlgButtonChecked(m_hwnd, IDC_E1)) opt.eUnit = 1; + if (IsDlgButtonChecked(m_hwnd, IDC_E2)) opt.eUnit = 2; + + // save the new weather options + m_proto->SaveOptions(); + + RedrawFrame(0, 0); + return true; + } +}; +///////////////////////////////////////////////////////////////////////////////////////// // text option dialog struct @@ -338,172 +317,156 @@ static controls[] = { 'S', IDC_BTITLE2, "StatusText" }, }; -static INT_PTR CALLBACK DlgProcText(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) +class COptionsTextDlg : public CWeatherDlgBase { - RECT rc, pos; - HWND button; - HMENU hMenu, hMenu1; - switch (msg) { - case WM_INITDIALOG: - opt_startup = TRUE; + CCtrlMButton btnMore, btnReset, tm1, tm2, tm3, tm4, tm5, tm6, tm7, tm8; + +public: + COptionsTextDlg(CWeatherProto *ppro) : + CWeatherDlgBase(ppro, IDD_TEXTOPT), + btnMore(this, IDC_MORE, 0, 0), + btnReset(this, IDC_RESET, 0, 0), + tm1(this, IDC_TM1, 0, 0), + tm2(this, IDC_TM2, 0, 0), + tm3(this, IDC_TM3, 0, 0), + tm4(this, IDC_TM4, 0, 0), + tm5(this, IDC_TM5, 0, 0), + tm6(this, IDC_TM6, 0, 0), + tm7(this, IDC_TM7, 0, 0), + tm8(this, IDC_TM8, 0, 0) + { + btnMore.OnClick = Callback(this, &COptionsTextDlg::onClick_More); + btnReset.OnClick = Callback(this, &COptionsTextDlg::onClick_Reset); + + tm1.OnClick = tm2.OnClick = tm3.OnClick = tm4.OnClick = tm5.OnClick = tm6.OnClick = tm7.OnClick = tm8.OnClick = + Callback(this, &COptionsTextDlg::onClick_TM); + } + + bool OnInitDialog() override + { // set windows position, make it top-most - GetWindowRect(hdlg, &rc); - SetWindowPos(hdlg, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); - TranslateDialogDefault(hdlg); + RECT rc; + GetWindowRect(m_hwnd, &rc); + SetWindowPos(m_hwnd, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); // generate the display text for variable list - SetDlgItemText(hdlg, IDC_VARLIST, VAR_LIST_OPT); + SetDlgItemText(m_hwnd, IDC_VARLIST, VAR_LIST_OPT); for (auto &it : controls) - SetDlgItemText(hdlg, it.id, GetTextValue(it.c)); + SetDlgItemText(m_hwnd, it.id, m_proto->GetTextValue(it.c)); // make the more variable and other buttons flat - SendDlgItemMessage(hdlg, IDC_MORE, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM1, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM2, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM3, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM4, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM5, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM6, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM7, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_TM8, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_RESET, BUTTONSETASFLATBTN, TRUE, 0); - - // load the settings - 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; + tm1.MakeFlat(); + tm2.MakeFlat(); + tm3.MakeFlat(); + tm4.MakeFlat(); + tm5.MakeFlat(); + tm6.MakeFlat(); + tm7.MakeFlat(); + tm8.MakeFlat(); + btnMore.MakeFlat(); + btnReset.MakeFlat(); + return true; + } - case IDC_MORE: - // display custom variables list - MoreVarList(); - break; + bool OnApply() override + { + // save the option + wchar_t textstr[MAX_TEXT_SIZE]; + for (auto &it : controls) { + GetDlgItemText(m_hwnd, it.id, textstr, _countof(textstr)); + if (!mir_wstrcmpi(textstr, GetDefaultText(it.c))) + g_plugin.delSetting(it.setting); + else + g_plugin.setWString(it.setting, textstr); + } - case IDC_TM1: - case IDC_TM2: - case IDC_TM3: - case IDC_TM4: - case IDC_TM5: - case IDC_TM6: - case IDC_TM7: - case IDC_TM8: - // display the menu - button = GetDlgItem(hdlg, LOWORD(wParam)); - GetWindowRect(button, &pos); - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - TranslateMenu(hMenu1); - { - auto &var = controls[int(LOWORD(wParam)) - IDC_TM1]; - - switch (TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, nullptr)) { - case ID_MPREVIEW: - { - // show the preview in a message box, using the weather data from the default station - WEATHERINFO winfo = LoadWeatherInfo(opt.DefStn); - wchar_t buf[2] = { var.c, 0 }, str[4096]; - GetDisplay(&winfo, buf, str); - MessageBox(nullptr, str, TranslateT("Weather Protocol Text Preview"), MB_OK | MB_TOPMOST); - } - break; - - case ID_MRESET: - SetDlgItemText(hdlg, var.id, GetDefaultText(var.c)); - break; - } - DestroyMenu(hMenu); - } - break; + m_proto->SaveOptions(); + m_proto->UpdateAllInfo(0, 0); + return true; + } - case IDC_RESET: - // left click action selection menu - button = GetDlgItem(hdlg, IDC_RESET); - GetWindowRect(button, &pos); - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - TranslateMenu(hMenu1); - switch (TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, nullptr)) { - case ID_T1: - // reset to the strings in memory, discard all changes - for (auto &it : controls) - SetDlgItemText(hdlg, it.id, GetTextValue(it.c)); + void onClick_More(CCtrlButton *) + { + MoreVarList(); + } + + void onClick_TM(CCtrlButton *pButton) + { + // display the menu + RECT pos; + GetWindowRect(pButton->GetHwnd(), &pos); + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMMENU)); + HMENU hMenu1 = GetSubMenu(hMenu, 0); + TranslateMenu(hMenu1); + { + auto &var = controls[pButton->GetCtrlId() - IDC_TM1]; + + switch (TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, m_hwnd, nullptr)) { + case ID_MPREVIEW: + { + // show the preview in a message box, using the weather data from the default station + WEATHERINFO winfo = LoadWeatherInfo(m_proto->opt.DefStn); + wchar_t buf[2] = { var.c, 0 }, str[4096]; + GetDisplay(&winfo, buf, str); + MessageBox(nullptr, str, TranslateT("Weather Protocol Text Preview"), MB_OK | MB_TOPMOST); + } break; - case ID_T2: - // reset to the default setting - for (auto &it : controls) - SetDlgItemText(hdlg, it.id, GetDefaultText(it.c)); + case ID_MRESET: + SetDlgItemText(m_hwnd, var.id, GetDefaultText(var.c)); break; } DestroyMenu(hMenu); - break; } - return TRUE; - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - // save the option - wchar_t textstr[MAX_TEXT_SIZE]; - for (auto &it : controls) { - GetDlgItemText(hdlg, it.id, textstr, _countof(textstr)); - if (!mir_wstrcmpi(textstr, GetDefaultText(it.c))) - g_plugin.delSetting(it.setting); - else - g_plugin.setWString(it.setting, textstr); - } + } + + void onClick_Reset(CCtrlButton *) + { + // left click action selection menu + RECT pos; + GetWindowRect(btnReset.GetHwnd(), &pos); + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMENU)); + HMENU hMenu1 = GetSubMenu(hMenu, 0); + TranslateMenu(hMenu1); + switch (TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, m_hwnd, nullptr)) { + case ID_T1: + // reset to the strings in memory, discard all changes + for (auto &it : controls) + SetDlgItemText(m_hwnd, it.id, m_proto->GetTextValue(it.c)); + break; - SaveOptions(); - UpdateAllInfo(0, 0); + case ID_T2: + // reset to the default setting + for (auto &it : controls) + SetDlgItemText(m_hwnd, it.id, GetDefaultText(it.c)); break; } - break; + DestroyMenu(hMenu); } - return FALSE; -} - - -//============ OPTION INITIALIZATION ============ +}; +///////////////////////////////////////////////////////////////////////////////////////// // register the weather option pages -int OptInit(WPARAM wParam, LPARAM) + +int CWeatherProto::OptInit(WPARAM wParam, LPARAM) { - // plugin options OPTIONSDIALOGPAGE odp = {}; + odp.szGroup.w = LPGENW("Network"); + odp.szTitle.w = m_tszUserName; odp.position = 95600; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.pfnDlgProc = OptionsProc; - odp.szGroup.a = LPGEN("Network"); - odp.szTitle.a = MODULENAME; + odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE; + + // plugin options + odp.pDialog = new COptionsDlg(this); odp.szTab.a = LPGEN("General"); - odp.flags = ODPF_BOLDGROUPS; g_plugin.addOptions(wParam, &odp); // text options - odp.pszTemplate = MAKEINTRESOURCEA(IDD_TEXTOPT); - odp.pfnDlgProc = DlgProcText; + odp.pDialog = new COptionsTextDlg(this); odp.szTab.a = LPGEN("Display"); g_plugin.addOptions(wParam, &odp); - // if popup service exists, load the weather popup options - odp.position = 100000000; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_POPUP); - odp.szGroup.a = LPGEN("Popups"); - odp.szTab.a = nullptr; - odp.pfnDlgProc = DlgPopupOpts; - g_plugin.addOptions(wParam, &odp); + InitPopupOptions(wParam); return 0; } diff --git a/protocols/Weather/src/weather_popup.cpp b/protocols/Weather/src/weather_popup.cpp index 992db0a69a..e9fa6bd427 100644 --- a/protocols/Weather/src/weather_popup.cpp +++ b/protocols/Weather/src/weather_popup.cpp @@ -27,37 +27,33 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. // variables for weather_popup.c static MCONTACT hPopupContact; -//============ SHOW WEATHER POPUPS ============ - -//============ WEATHER ERROR POPUPS ============ +///////////////////////////////////////////////////////////////////////////////////////// +// wrapper function for displaying weather warning popup by triggering an event (threaded) +// lpzText = error text +// kind = display type (see m_popup.h) -// 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) +int CWeatherProto::WPShowMessage(const wchar_t *lpzText, int kind) { if (!g_plugin.bPopups) return 0; - wchar_t* tszMsg = (wchar_t*)wParam; - - if ((uint32_t)lParam == SM_WARNING) - PUShowMessageW(tszMsg, SM_WARNING); - else if ((uint32_t)lParam == SM_NOTIFY) - PUShowMessageW(tszMsg, SM_NOTIFY); - else if ((uint32_t)lParam == SM_WEATHERALERT) { + if (kind == SM_WARNING) + PUShowMessageW(lpzText, SM_WARNING); + else if (kind == SM_NOTIFY) + PUShowMessageW(lpzText, SM_NOTIFY); + else if (kind == SM_WEATHERALERT) { POPUPDATAW ppd; wchar_t str1[512], str2[512]; // get the 2 strings - wcsncpy(str1, tszMsg, _countof(str1) - 1); - wcsncpy(str2, tszMsg, _countof(str2) - 1); + wcsncpy(str1, lpzText, _countof(str1) - 1); + wcsncpy(str2, lpzText, _countof(str2) - 1); wchar_t *chop = wcschr(str1, 255); if (chop != nullptr) *chop = '\0'; else str1[0] = 0; + chop = wcschr(str2, 255); if (chop != nullptr) wcsncpy(str2, chop + 1, _countof(str2) - 1); @@ -77,38 +73,28 @@ int WeatherError(WPARAM wParam, LPARAM lParam) 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(const wchar_t* lpzText, uint16_t 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 + static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - uint32_t ID = 0; - MCONTACT hContact; - hContact = PUGetContact(hWnd); + uint32_t ID; + MCONTACT hContact = PUGetContact(hWnd); + auto *ppro = (CWeatherProto*)Proto_GetContactInstance(hContact); switch (message) { case WM_COMMAND: - ID = opt.LeftClickAction; + ID = (ppro) ? ppro->opt.LeftClickAction : 0; if (ID != IDM_M7) PUDeletePopup(hWnd); - SendMessage(hPopupWindow, ID, hContact, 0); + SendMessage(hPopupWindow, ID, hContact, LPARAM(ppro)); return TRUE; case WM_CONTEXTMENU: - ID = opt.RightClickAction; + ID = (ppro) ? ppro->opt.RightClickAction : IDM_M7; if (ID != IDM_M7) PUDeletePopup(hWnd); - SendMessage(hPopupWindow, ID, hContact, 0); + SendMessage(hPopupWindow, ID, hContact, LPARAM(ppro)); return TRUE; case UM_FREEPLUGINDATA: @@ -119,13 +105,15 @@ static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPA return DefWindowProc(hWnd, message, wParam, lParam); } +///////////////////////////////////////////////////////////////////////////////////////// // display weather popups // wParam = the contact to display popup // lParam = whether the weather data is changed or not -int WeatherPopup(WPARAM hContact, LPARAM lParam) + +int CWeatherProto::WeatherPopup(MCONTACT hContact, bool bAlways) { // determine if the popup should display or not - if (g_plugin.bPopups && opt.UpdatePopup && (!opt.PopupOnChange || (BOOL)lParam) && !g_plugin.getByte(hContact, "DPopUp")) { + if (g_plugin.bPopups && opt.UpdatePopup && (!opt.PopupOnChange || bAlways) && !g_plugin.getByte(hContact, "DPopUp")) { WEATHERINFO winfo = LoadWeatherInfo(hContact); // setup the popup @@ -143,24 +131,27 @@ int WeatherPopup(WPARAM hContact, LPARAM lParam) return 0; } - +///////////////////////////////////////////////////////////////////////////////////////// // process for the popup window // containing the code for popup actions -LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + +LRESULT CALLBACK CWeatherProto::PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { POINT pt; HMENU hMenu; + auto *ppro = (CWeatherProto *)lParam; + switch (uMsg) { case IDM_M2: // brief info - BriefInfo(wParam, 0); + ppro->BriefInfo(wParam, 0); break; case IDM_M3: // read complete forecast - LoadForecast(wParam, 0); + ppro->LoadForecast(wParam, 0); break; case IDM_M4: // display weather map - WeatherMap(wParam, 0); + ppro->WeatherMap(wParam, 0); break; case IDM_M5: // open history window @@ -168,7 +159,7 @@ LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam break; case IDM_M6: // open external log - ViewLog(wParam, 0); + ppro->ViewLog(wParam, 0); break; case IDM_M7: // display contact menu @@ -197,7 +188,7 @@ LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE; } -//============ POPUP OPTIONS ============ +///////////////////////////////////////////////////////////////////////////////////////// struct { @@ -218,225 +209,245 @@ static void SelectMenuItem(HMENU hMenu, int Check) CheckMenuItem(hMenu, i, MF_BYPOSITION | ((int)GetMenuItemID(hMenu, i) == Check) * 8); } -// temporary read the current option to memory -// but does not write to the database -void ReadPopupOpt(HWND hdlg) +class CPopupOptsDlg : public CWeatherDlgBase { - wchar_t 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, _countof(str)); - int num = _wtoi(str); - opt.pDelay = num; - - // other options - opt.UseWinColors = (uint8_t)IsDlgButtonChecked(hdlg, IDC_USEWINCOLORS); - opt.UpdatePopup = (uint8_t)IsDlgButtonChecked(hdlg, IDC_POP1); - opt.AlertPopup = (uint8_t)IsDlgButtonChecked(hdlg, IDC_POP2); - opt.PopupOnChange = (uint8_t)IsDlgButtonChecked(hdlg, IDC_CH); - opt.ShowWarnings = (uint8_t)IsDlgButtonChecked(hdlg, IDC_W); -} + CCtrlEdit edtDelay; + CCtrlCheck chkUseWin; + CCtrlButton btnLeft, btnRight, btnPD1, btnPD2, btnPdef, btnVars, btnPreview; + + // temporary read the current option to memory + // but does not write to the database + void ReadPopupOpt(HWND hdlg) + { + wchar_t str[512]; + auto &opt = m_proto->opt; -// copied and modified from NewStatusNotify -INT_PTR CALLBACK DlgPopupOpts(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - int ID; - HMENU hMenu, hMenu1; - RECT pos; - HWND button; - MCONTACT hContact; + // 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, _countof(str)); + int num = _wtoi(str); + opt.pDelay = num; - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hdlg); - SaveOptions(); + // other options + opt.UseWinColors = (uint8_t)IsDlgButtonChecked(hdlg, IDC_USEWINCOLORS); + opt.UpdatePopup = (uint8_t)IsDlgButtonChecked(hdlg, IDC_POP1); + opt.AlertPopup = (uint8_t)IsDlgButtonChecked(hdlg, IDC_POP2); + opt.PopupOnChange = (uint8_t)IsDlgButtonChecked(hdlg, IDC_CH); + opt.ShowWarnings = (uint8_t)IsDlgButtonChecked(hdlg, IDC_W); + } + +public: + CPopupOptsDlg(CWeatherProto *ppro) : + CWeatherDlgBase(ppro, IDD_POPUP), + btnPD1(this, IDC_PD1), + btnPD2(this, IDC_PD2), + btnPdef(this, IDC_PDEF), + btnVars(this, IDC_VAR3), + btnLeft(this, IDC_LeftClick), + btnRight(this, IDC_RightClick), + btnPreview(this, IDC_PREVIEW), + edtDelay(this, IDC_DELAY), + chkUseWin(this, IDC_USEWINCOLORS) + { + edtDelay.OnChange = Callback(this, &CPopupOptsDlg::onChanged_Delay); + chkUseWin.OnChange = Callback(this, &CPopupOptsDlg::onChanged_UseWin); + + btnPD1.OnClick = Callback(this, &CPopupOptsDlg::onClick_PD1); + btnPD2.OnClick = Callback(this, &CPopupOptsDlg::onClick_PD2); + btnPdef.OnClick = Callback(this, &CPopupOptsDlg::onClick_Pdef); + btnVars.OnClick = Callback(this, &CPopupOptsDlg::onClick_Vars); + btnLeft.OnClick = Callback(this, &CPopupOptsDlg::onClick_Left); + btnRight.OnClick = Callback(this, &CPopupOptsDlg::onClick_Right); + btnPreview.OnClick = Callback(this, &CPopupOptsDlg::onClick_Preview); + } + + bool OnInitDialog() override + { + m_proto->SaveOptions(); // click actions - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); + HMENU hMenu1 = GetSubMenu(hMenu, 0); wchar_t str[512]; - GetMenuString(hMenu1, opt.LeftClickAction, str, _countof(str), MF_BYCOMMAND); - SetDlgItemText(hdlg, IDC_LeftClick, TranslateW(str)); - GetMenuString(hMenu1, opt.RightClickAction, str, _countof(str), MF_BYCOMMAND); - SetDlgItemText(hdlg, IDC_RightClick, TranslateW(str)); + auto &opt = m_proto->opt; + GetMenuStringW(hMenu1, opt.LeftClickAction, str, _countof(str), MF_BYCOMMAND); + SetDlgItemTextW(m_hwnd, IDC_LeftClick, TranslateW(str)); + GetMenuStringW(hMenu1, opt.RightClickAction, str, _countof(str), MF_BYCOMMAND); + SetDlgItemTextW(m_hwnd, IDC_RightClick, TranslateW(str)); DestroyMenu(hMenu); // other options - CheckDlgButton(hdlg, IDC_E, g_plugin.bPopups ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_POP2, opt.AlertPopup ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_POP1, opt.UpdatePopup ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_CH, opt.PopupOnChange ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hdlg, IDC_W, opt.ShowWarnings ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_E, g_plugin.bPopups ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_POP2, opt.AlertPopup ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_POP1, opt.UpdatePopup ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_CH, opt.PopupOnChange ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(m_hwnd, IDC_W, opt.ShowWarnings ? BST_CHECKED : BST_UNCHECKED); for (auto &it : controls) - SetDlgItemText(hdlg, it.id, GetTextValue(it.c)); + SetDlgItemText(m_hwnd, it.id, m_proto->GetTextValue(it.c)); // setting popup delay option _ltow(opt.pDelay, str, 10); - SetDlgItemText(hdlg, IDC_DELAY, str); + SetDlgItemText(m_hwnd, IDC_DELAY, str); if (opt.pDelay == -1) - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); + CheckRadioButton(m_hwnd, IDC_PD1, IDC_PD3, IDC_PD2); else if (opt.pDelay == 0) - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); + CheckRadioButton(m_hwnd, IDC_PD1, IDC_PD3, IDC_PD1); else - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); + CheckRadioButton(m_hwnd, 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); + SendDlgItemMessage(m_hwnd, IDC_BGCOLOUR, CPM_SETCOLOUR, 0, opt.BGColour); + SendDlgItemMessage(m_hwnd, 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); + CheckDlgButton(m_hwnd, IDC_USEWINCOLORS, opt.UseWinColors ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(m_hwnd, IDC_BGCOLOUR), !opt.UseWinColors); + EnableWindow(GetDlgItem(m_hwnd, IDC_TEXTCOLOUR), !opt.UseWinColors); // buttons - SendDlgItemMessage(hdlg, IDC_PREVIEW, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_PDEF, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_LeftClick, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_RightClick, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hdlg, IDC_VAR3, BUTTONSETASFLATBTN, TRUE, 0); - return TRUE; + SendDlgItemMessage(m_hwnd, IDC_PREVIEW, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_PDEF, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_LeftClick, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_RightClick, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_VAR3, BUTTONSETASFLATBTN, TRUE, 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; + bool OnApply() override + { + ReadPopupOpt(m_hwnd); + + wchar_t textstr[MAX_TEXT_SIZE]; + for (auto &it : controls) { + GetDlgItemText(m_hwnd, it.id, textstr, _countof(textstr)); + if (!mir_wstrcmpi(textstr, GetDefaultText(it.c))) + g_plugin.delSetting(it.setting); + else + g_plugin.setWString(it.setting, textstr); + } - 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; + // save the options, and update main menu + m_proto->SaveOptions(); + return true; + } - case IDC_E: - case IDC_CH: - SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0); - break; + void onChanged_UseWin(CCtrlCheck *) + { + // use window color - enable/disable color selection controls + EnableWindow(GetDlgItem(m_hwnd, IDC_BGCOLOUR), !(m_proto->opt.UseWinColors)); + EnableWindow(GetDlgItem(m_hwnd, IDC_TEXTCOLOUR), !(m_proto->opt.UseWinColors)); + } - case IDC_RightClick: - // right click action selection menu - button = GetDlgItem(hdlg, IDC_RightClick); - GetWindowRect(button, &pos); - - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - TranslateMenu(hMenu1); - SelectMenuItem(hMenu1, opt.RightClickAction); - ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, nullptr); - if (ID) - opt.RightClickAction = ID; - DestroyMenu(hMenu); - - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - GetMenuString(hMenu1, opt.RightClickAction, str, _countof(str), MF_BYCOMMAND); - SetDlgItemText(hdlg, IDC_RightClick, TranslateW(str)); - DestroyMenu(hMenu); - break; + void onClick_Right(CCtrlButton *) + { + // right click action selection menu + RECT pos; + GetWindowRect(GetDlgItem(m_hwnd, IDC_RightClick), &pos); + + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); + HMENU hMenu1 = GetSubMenu(hMenu, 0); + TranslateMenu(hMenu1); + SelectMenuItem(hMenu1, m_proto->opt.RightClickAction); + int ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, m_hwnd, nullptr); + if (ID) + m_proto->opt.RightClickAction = ID; + DestroyMenu(hMenu); - case IDC_LeftClick: - // left click action selection menu - button = GetDlgItem(hdlg, IDC_LeftClick); - GetWindowRect(button, &pos); - - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - TranslateMenu(hMenu1); - SelectMenuItem(hMenu1, opt.LeftClickAction); - ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, nullptr); - if (ID) opt.LeftClickAction = ID; - DestroyMenu(hMenu); - - hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); - hMenu1 = GetSubMenu(hMenu, 0); - GetMenuString(hMenu1, opt.LeftClickAction, str, _countof(str), MF_BYCOMMAND); - SetDlgItemText(hdlg, IDC_LeftClick, TranslateW(str)); - DestroyMenu(hMenu); - break; + hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); - case IDC_PD1: - // Popup delay setting from popup plugin - SetDlgItemText(hdlg, IDC_DELAY, L"0"); - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1); - break; + wchar_t str[512]; + GetMenuString(hMenu1, m_proto->opt.RightClickAction, str, _countof(str), MF_BYCOMMAND); + SetDlgItemText(m_hwnd, IDC_RightClick, TranslateW(str)); + DestroyMenu(hMenu); + } - case IDC_PD2: - // Popup delay = permanent - SetDlgItemText(hdlg, IDC_DELAY, L"-1"); - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2); - break; + void onClick_Left(CCtrlButton *) + { + // left click action selection menu + RECT pos; + GetWindowRect(GetDlgItem(m_hwnd, IDC_LeftClick), &pos); + + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); + HMENU hMenu1 = GetSubMenu(hMenu, 0); + TranslateMenu(hMenu1); + SelectMenuItem(hMenu1, m_proto->opt.LeftClickAction); + int ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, m_hwnd, nullptr); + if (ID) + m_proto->opt.LeftClickAction = ID; + DestroyMenu(hMenu); - case IDC_DELAY: - // if text is edited - CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3); - break; + hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_PMENU)); + hMenu1 = GetSubMenu(hMenu, 0); - case IDC_PDEF: - // set the default value for popup texts - for (auto &it : controls) - SetDlgItemText(hdlg, it.id, GetDefaultText(it.c)); - break; + wchar_t str[512]; + GetMenuString(hMenu1, m_proto->opt.LeftClickAction, str, _countof(str), MF_BYCOMMAND); + SetDlgItemText(m_hwnd, IDC_LeftClick, TranslateW(str)); + DestroyMenu(hMenu); + } - case IDC_VAR3: - // display variable list - { - CMStringW wszText; - wszText += L" \n"; // to make the message box wider - wszText += TranslateT("%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"); - wszText += L"\n"; - wszText += TranslateT("%[..]\tcustom variables"); - MessageBox(nullptr, wszText, TranslateT("Variable List"), MB_OK | MB_ICONASTERISK | MB_TOPMOST); - } - break; + void onClick_PD1(CCtrlButton *) + { + // Popup delay setting from popup plugin + SetDlgItemText(m_hwnd, IDC_DELAY, L"0"); + CheckRadioButton(m_hwnd, IDC_PD1, IDC_PD3, IDC_PD1); + } - 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 - LoadOptions(); // restore old option in memory - opt.DefStn = hContact; - break; - } - break; + void onClick_PD2(CCtrlButton *) + { + // Popup delay = permanent + SetDlgItemText(m_hwnd, IDC_DELAY, L"-1"); + CheckRadioButton(m_hwnd, IDC_PD1, IDC_PD3, IDC_PD2); + } - case WM_NOTIFY: //Here we have pressed either the OK or the APPLY button. - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - ReadPopupOpt(hdlg); - - wchar_t textstr[MAX_TEXT_SIZE]; - for (auto &it : controls) { - GetDlgItemText(hdlg, it.id, textstr, _countof(textstr)); - if (!mir_wstrcmpi(textstr, GetDefaultText(it.c))) - g_plugin.delSetting(it.setting); - else - g_plugin.setWString(it.setting, textstr); - } - - // save the options, and update main menu - SaveOptions(); - return TRUE; - } - break; + void onChanged_Delay(CCtrlEdit *) + { + // if text is edited + CheckRadioButton(m_hwnd, IDC_PD1, IDC_PD3, IDC_PD3); } - return FALSE; + + void onClick_Pdef(CCtrlButton *) + { + // set the default value for popup texts + for (auto &it : controls) + SetDlgItemText(m_hwnd, it.id, GetDefaultText(it.c)); + } + + void onClick_Vars(CCtrlButton *) + { + // display variable list + CMStringW wszText; + wszText += L" \n"; // to make the message box wider + wszText += TranslateT("%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"); + wszText += L"\n"; + wszText += TranslateT("%[..]\tcustom variables"); + MessageBox(nullptr, wszText, TranslateT("Variable List"), MB_OK | MB_ICONASTERISK | MB_TOPMOST); + } + + void onClick_Preview(CCtrlButton *) + { + // popup preview + MCONTACT hContact = m_proto->opt.DefStn; + ReadPopupOpt(m_hwnd); // read new options to memory + m_proto->WeatherPopup(m_proto->opt.DefStn, true); // display popup using new opt + m_proto->LoadOptions(); // restore old option in memory + m_proto->opt.DefStn = hContact; + } +}; + +void CWeatherProto::InitPopupOptions(WPARAM wParam) +{ + // if popup service exists, load the weather popup options + OPTIONSDIALOGPAGE odp = {}; + odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE; + odp.position = 100000000; + odp.szGroup.w = LPGENW("Popups"); + odp.szTitle.w = m_tszUserName; + odp.pDialog = new CPopupOptsDlg(this); + g_plugin.addOptions(wParam, &odp); } diff --git a/protocols/Weather/src/weather_proto.cpp b/protocols/Weather/src/weather_proto.cpp new file mode 100644 index 0000000000..235f62294e --- /dev/null +++ b/protocols/Weather/src/weather_proto.cpp @@ -0,0 +1,116 @@ +/* +Copyright (C) 2012-25 Miranda NG team (https://miranda-ng.org) + +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 <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h" + +CWeatherProto::CWeatherProto(const char *protoName, const wchar_t *userName) : + PROTO<CWeatherProto>(protoName, userName), + m_impl(*this), + hUpdateMutex(CreateMutex(nullptr, FALSE, nullptr)) +{ + HookProtoEvent(ME_OPT_INITIALISE, &CWeatherProto::OptInit); + HookProtoEvent(ME_CLIST_DOUBLECLICKED, &CWeatherProto::BriefInfoEvt); + HookProtoEvent(ME_CLIST_PREBUILDCONTACTMENU, &CWeatherProto::BuildContactMenu); + + InitMwin(); + + // reset the weather data at startup for individual contacts + EraseAllInfo(); + + // load options and set defaults + LoadOptions(); + + // menu items + InitMenuItems(); + + // netlib + NETLIBUSER nlu = {}; + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_NOHTTPSOPTION | NUF_UNICODE; + nlu.szSettingsModule = m_szModuleName; + nlu.szDescriptiveName.w = m_tszUserName; + m_hNetlibUser = Netlib_RegisterUser(&nlu); +} + +CWeatherProto::~CWeatherProto() +{ + DestroyMwin(); + DestroyUpdateList(); + + CloseHandle(hUpdateMutex); +} + +void CWeatherProto::OnModulesLoaded() +{ + // timer for the first update + m_impl.m_start.Start(5000); // first update is 5 sec after load + + // weather user detail + HookProtoEvent(ME_USERINFO_INITIALISE, &CWeatherProto::UserInfoInit); +} + +void CWeatherProto::OnShutdown() +{ + m_impl.m_update.Stop(); + + SaveOptions(); // save options once more + + WindowList_Broadcast(hWindowList, WM_CLOSE, 0, 0); + WindowList_Broadcast(hDataWindowList, WM_CLOSE, 0, 0); + SendMessage(hWndSetup, WM_CLOSE, 0, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CWeatherProto::SetStatus(int new_status) +{ + // if we don't want to show status for default station + if (m_iStatus != new_status) { + int old_status = m_iStatus; + m_iStatus = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; + + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); + + UpdateMenu(m_iStatus != ID_STATUS_OFFLINE); + if (m_iStatus != ID_STATUS_OFFLINE) + UpdateAll(FALSE, FALSE); + } + + return 0; +} + +// get capabilities protocol service function +INT_PTR CWeatherProto::GetCaps(int type, MCONTACT) +{ + switch (type) { + case PFLAGNUM_1: + // support search and visible list + return PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_EXTSEARCH | PF1_MODEMSGRECV; + + case PFLAGNUM_2: + return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT; + + case PFLAGNUM_4: + return PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_FORCEAUTH; + + case PFLAGNUM_5: /* this is PFLAGNUM_5 change when alpha SDK is released */ + return PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT; + + case PFLAG_UNIQUEIDTEXT: + return (INT_PTR)TranslateT("Station ID"); + } + return 0; +} diff --git a/protocols/Weather/src/weather_svcs.cpp b/protocols/Weather/src/weather_svcs.cpp index daeb7f8bd1..9c87328209 100644 --- a/protocols/Weather/src/weather_svcs.cpp +++ b/protocols/Weather/src/weather_svcs.cpp @@ -32,62 +32,6 @@ extern VARSW g_pwszIconsName; //============ MIRANDA PROTOCOL SERVICES ============ -// protocol service function for setting weather protocol status -INT_PTR WeatherSetStatus(WPARAM new_status, LPARAM) -{ - // if we don't want to show status for default station - if (status != new_status) { - old_status = status; - status = new_status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; - - if (!opt.NoProtoCondition) { - ProtoBroadcastAck(MODULENAME, 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) -{ - INT_PTR ret = 0; - - switch (wParam) { - case PFLAGNUM_1: - // support search and visible list - ret = PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_EXTSEARCH | PF1_MODEMSGRECV; - break; - - case PFLAGNUM_2: - ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT; - break; - - case PFLAGNUM_4: - ret = PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | 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; - break; - - case PFLAG_UNIQUEIDTEXT: - ret = (INT_PTR)TranslateT("Station ID"); - break; - } - return ret; -} - -// protocol service function to get the current status of the protocol -INT_PTR WeatherGetStatus(WPARAM, LPARAM) -{ - return status; -} - // protocol service function to get the icon of the protocol INT_PTR WeatherLoadIcon(WPARAM wParam, LPARAM) { @@ -256,18 +200,10 @@ static INT_PTR WeatherAdvancedStatusIcon(WPARAM hContact, LPARAM) // protocol services void InitServices(void) { - CreateProtoServiceFunction(MODULENAME, PS_GETCAPS, WeatherGetCaps); CreateProtoServiceFunction(MODULENAME, PS_LOADICON, WeatherLoadIcon); - CreateProtoServiceFunction(MODULENAME, PS_SETSTATUS, WeatherSetStatus); - CreateProtoServiceFunction(MODULENAME, PS_GETSTATUS, WeatherGetStatus); - CreateProtoServiceFunction(MODULENAME, PS_BASICSEARCH, WeatherBasicSearch); - CreateProtoServiceFunction(MODULENAME, PS_SEARCHBYEMAIL, WeatherBasicSearch); - CreateProtoServiceFunction(MODULENAME, PS_ADDTOLIST, WeatherAddToList); CreateProtoServiceFunction(MODULENAME, PS_GETINFO, WeatherGetInfo); CreateProtoServiceFunction(MODULENAME, PS_GETAVATARINFO, WeatherGetAvatarInfo); CreateProtoServiceFunction(MODULENAME, PS_GETAWAYMSG, WeatherGetAwayMsg); - CreateProtoServiceFunction(MODULENAME, PS_CREATEADVSEARCHUI, WeatherCreateAdvancedSearchUI); - CreateProtoServiceFunction(MODULENAME, PS_SEARCHBYADVANCED, WeatherAdvancedSearch); CreateProtoServiceFunction(MODULENAME, PS_GETADVANCEDSTATUSICON, WeatherAdvancedStatusIcon); CreateProtoServiceFunction(MODULENAME, MS_WEATHER_GETDISPLAY, GetDisplaySvcFunc); @@ -275,11 +211,11 @@ void InitServices(void) //============ MENU INITIALIZATION ============ -void UpdateMenu(BOOL State) +void CWeatherProto::UpdateMenu(BOOL State) { // update option setting opt.CAutoUpdate = State; - g_plugin.setByte("AutoUpdate", (uint8_t)State); + setByte("AutoUpdate", (uint8_t)State); if (State) { // to enable auto-update Menu_ModifyItem(hEnableDisableMenu, LPGENW("Auto Update Enabled"), g_plugin.getIconHandle(IDI_ICON)); @@ -294,87 +230,81 @@ void UpdateMenu(BOOL State) } // update the weather auto-update menu item when click on it -static INT_PTR EnableDisableCmd(WPARAM wParam, LPARAM lParam) +INT_PTR CWeatherProto::EnableDisableCmd(WPARAM wParam, LPARAM lParam) { UpdateMenu(wParam == TRUE ? (BOOL)lParam : !opt.CAutoUpdate); return 0; } -// displays contact info dialog -static INT_PTR BriefInfoSvc(WPARAM wParam, LPARAM lParam) -{ - return BriefInfo(wParam, lParam); -} - // adding weather contact menus // copied and modified form "modified MSN Protocol" -void AddMenuItems(void) +void CWeatherProto::InitMenuItems() { CMenuItem mi(&g_plugin); // contact menu SET_UID(mi, 0x266ef52b, 0x869a, 0x4cac, 0xa9, 0xf8, 0xea, 0x5b, 0xb8, 0xab, 0xe0, 0x24); - CreateServiceFunction(MS_WEATHER_UPDATE, UpdateSingleStation); mi.position = -0x7FFFFFFA; mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE); mi.name.a = LPGEN("Update Weather"); - mi.pszService = MS_WEATHER_UPDATE; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Update"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::UpdateSingleStation); SET_UID(mi, 0x45361b4, 0x8de, 0x44b4, 0x8f, 0x11, 0x9b, 0xe9, 0x6e, 0xa8, 0x83, 0x54); - CreateServiceFunction(MS_WEATHER_REFRESH, UpdateSingleRemove); mi.position = -0x7FFFFFF9; mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE2); mi.name.a = LPGEN("Remove Old Data then Update"); - mi.pszService = MS_WEATHER_REFRESH; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Refresh"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::UpdateSingleRemove); SET_UID(mi, 0x4232975e, 0xb181, 0x46a5, 0xb7, 0x6e, 0xd2, 0x5f, 0xef, 0xb8, 0xc4, 0x4d); - CreateServiceFunction(MS_WEATHER_BRIEF, BriefInfoSvc); mi.position = -0x7FFFFFF8; mi.hIcolibItem = g_plugin.getIconHandle(IDI_S); mi.name.a = LPGEN("Brief Information"); - mi.pszService = MS_WEATHER_BRIEF; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Brief"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::BriefInfo); SET_UID(mi, 0x3d6ed729, 0xd49a, 0x4ae9, 0x8e, 0x2, 0x9f, 0xe0, 0xf0, 0x2c, 0xcc, 0xb1); - CreateServiceFunction(MS_WEATHER_COMPLETE, LoadForecast); mi.position = -0x7FFFFFF7; mi.hIcolibItem = g_plugin.getIconHandle(IDI_READ); mi.name.a = LPGEN("Read Complete Forecast"); - mi.pszService = MS_WEATHER_COMPLETE; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/CompleteForecast"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::LoadForecast); SET_UID(mi, 0xc4b6c5e0, 0x13c3, 0x4e02, 0x8a, 0xeb, 0xeb, 0x8a, 0xe2, 0x66, 0x40, 0xd4); - CreateServiceFunction(MS_WEATHER_MAP, WeatherMap); mi.position = -0x7FFFFFF6; mi.hIcolibItem = g_plugin.getIconHandle(IDI_MAP); mi.name.a = LPGEN("Weather Map"); - mi.pszService = MS_WEATHER_MAP; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Map"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::WeatherMap); SET_UID(mi, 0xee3ad7f4, 0x3377, 0x4e4c, 0x8f, 0x3c, 0x3b, 0xf5, 0xd4, 0x86, 0x28, 0x25); - CreateServiceFunction(MS_WEATHER_LOG, ViewLog); mi.position = -0x7FFFFFF5; mi.hIcolibItem = g_plugin.getIconHandle(IDI_LOG); mi.name.a = LPGEN("View Log"); - mi.pszService = MS_WEATHER_LOG; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Log"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::ViewLog); SET_UID(mi, 0x1b01cd6a, 0xe5ee, 0x42b4, 0xa1, 0x6d, 0x43, 0xb9, 0x4, 0x58, 0x43, 0x2e); - CreateServiceFunction(MS_WEATHER_EDIT, EditSettings); mi.position = -0x7FFFFFF4; mi.hIcolibItem = g_plugin.getIconHandle(IDI_EDIT); mi.name.a = LPGEN("Edit Settings"); - mi.pszService = MS_WEATHER_EDIT; - Menu_AddContactMenuItem(&mi, MODULENAME); + mi.pszService = "/Edit"; + Menu_AddContactMenuItem(&mi, m_szModuleName); + CreateProtoService(mi.pszService, &CWeatherProto::EditSettings); // adding main menu items mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Weather"), 500099000); Menu_ConfigureItem(mi.root, MCI_OPT_UID, "82809D2F-2CF0-4E15-9350-D257A7748552"); SET_UID(mi, 0x5ad16188, 0xe0a0, 0x4c31, 0x85, 0xc3, 0xe4, 0x85, 0x79, 0x7e, 0x4b, 0x9c); - CreateServiceFunction(MS_WEATHER_ENABLED, EnableDisableCmd); + CreateProtoService(MS_WEATHER_ENABLED, &CWeatherProto::EnableDisableCmd); mi.name.a = LPGEN("Enable/Disable Weather Update"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_ICON); mi.position = 10100001; @@ -383,7 +313,7 @@ void AddMenuItems(void) UpdateMenu(opt.AutoUpdate); SET_UID(mi, 0x2b1c2054, 0x2991, 0x4025, 0x87, 0x73, 0xb6, 0xf7, 0x85, 0xac, 0xc7, 0x37); - CreateServiceFunction(MS_WEATHER_UPDATEALL, UpdateAllInfo); + CreateProtoService(MS_WEATHER_UPDATEALL, &CWeatherProto::UpdateAllInfo); mi.position = 20100001; mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE); mi.name.a = LPGEN("Update All Weather"); @@ -391,7 +321,7 @@ void AddMenuItems(void) Menu_AddMainMenuItem(&mi); SET_UID(mi, 0x8234c00e, 0x788e, 0x424f, 0xbc, 0xc4, 0x2, 0xfd, 0x67, 0x58, 0x2d, 0x19); - CreateServiceFunction(MS_WEATHER_REFRESHALL, UpdateAllRemove); + CreateProtoService(MS_WEATHER_REFRESHALL, &CWeatherProto::UpdateAllRemove); mi.position = 20100002; mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE2); mi.name.a = LPGEN("Remove Old Data then Update All"); @@ -406,6 +336,6 @@ void AddMenuItems(void) mi.hIcolibItem = nullptr; mi.root = nullptr; mi.name.a = LPGEN("Display in a frame"); - hMwinMenu = Menu_AddContactMenuItem(&mi, MODULENAME); + hMwinMenu = Menu_AddContactMenuItem(&mi, m_szModuleName); } } diff --git a/protocols/Weather/src/weather_update.cpp b/protocols/Weather/src/weather_update.cpp index f872d2031f..54bf94c994 100644 --- a/protocols/Weather/src/weather_update.cpp +++ b/protocols/Weather/src/weather_update.cpp @@ -29,10 +29,10 @@ menu items). UPDATELIST *UpdateListHead = nullptr, *UpdateListTail = nullptr; //============ RETRIEVE NEW WEATHER ============ -// // retrieve weather info and display / log them // hContact = current contact -int UpdateWeather(MCONTACT hContact) + +int CWeatherProto::UpdateWeather(MCONTACT hContact) { wchar_t str2[MAX_TEXT_SIZE]; DBVARIANT dbv; @@ -44,10 +44,10 @@ int UpdateWeather(MCONTACT hContact) dbv.pszVal = ""; // log to netlib log for debug purpose - Netlib_LogfW(hNetlibUser, L"************************************************************************"); + Netlib_LogfW(m_hNetlibUser, L"************************************************************************"); int dbres = g_plugin.getWString(hContact, "Nick", &dbv); - Netlib_LogfW(hNetlibUser, L"<-- Start update for station -->"); + Netlib_LogfW(m_hNetlibUser, L"<-- Start update for station -->"); // download the info and parse it // result are stored in database @@ -62,12 +62,15 @@ int UpdateWeather(MCONTACT hContact) WPShowMessage(str, SM_WARNING); } // log to netlib - Netlib_LogfW(hNetlibUser, L"Error! Update cannot continue... Start to free memory"); - Netlib_LogfW(hNetlibUser, L"<-- Error occurs while updating station: %s -->", dbv.pwszVal); - if (!dbres) db_free(&dbv); + Netlib_LogfW(m_hNetlibUser, L"Error! Update cannot continue... Start to free memory"); + Netlib_LogfW(m_hNetlibUser, L"<-- Error occurs while updating station: %s -->", dbv.pwszVal); + if (!dbres) + db_free(&dbv); return 1; } - if (!dbres) db_free(&dbv); + + if (!dbres) + db_free(&dbv); // initialize, load new weather Data WEATHERINFO winfo = LoadWeatherInfo(hContact); @@ -136,7 +139,7 @@ int UpdateWeather(MCONTACT hContact) else db_unset(hContact, "CList", "StatusMsg"); - ProtoBroadcastAck(MODULENAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, nullptr, (LPARAM)(str2[0] ? str2 : nullptr)); + ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, nullptr, (LPARAM)(str2[0] ? str2 : nullptr)); // save descriptions in MyNotes GetDisplay(&winfo, GetTextValue('N'), str2); @@ -147,15 +150,14 @@ int UpdateWeather(MCONTACT hContact) // set the update tag g_plugin.setByte(hContact, "IsUpdated", TRUE); - // save info for default weather condition - if (!mir_wstrcmp(winfo.id, opt.Default) && !opt.NoProtoCondition) { - // save current condition for default station to be displayed after the update - old_status = status; - status = iStatus; - // a workaround for a default station that currently have an n/a icon assigned - if (status == ID_STATUS_OFFLINE) status = NOSTATUSDATA; - ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status); - } + // save current condition for default station to be displayed after the update + int old_status = m_iStatus; + m_iStatus = iStatus; + + // a workaround for a default station that currently have an n/a icon assigned + if (m_iStatus == ID_STATUS_OFFLINE) + m_iStatus = ID_STATUS_CONNECTING; + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); // logging if (Ch) { @@ -198,11 +200,11 @@ int UpdateWeather(MCONTACT hContact) } // show the popup - NotifyEventHooks(hHookWeatherUpdated, hContact, (LPARAM)Ch); + WeatherPopup(hContact, Ch); } - Netlib_LogfW(hNetlibUser, L"Update Completed - Start to free memory"); - Netlib_LogfW(hNetlibUser, L"<-- Update successful for station -->"); + Netlib_LogfW(m_hNetlibUser, L"Update Completed - Start to free memory"); + Netlib_LogfW(m_hNetlibUser, L"<-- Update successful for station -->"); // Update frame data UpdateMwinData(hContact); @@ -214,12 +216,12 @@ int UpdateWeather(MCONTACT hContact) 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(MCONTACT hContact) + +void CWeatherProto::UpdateListAdd(MCONTACT hContact) { UPDATELIST *newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST)); newItem->hContact = hContact; @@ -236,7 +238,7 @@ void UpdateListAdd(MCONTACT hContact) // get the first item from the update queue and remove it from the queue // return value = the contact for next update -MCONTACT UpdateGetFirst() +MCONTACT CWeatherProto::UpdateGetFirst() { MCONTACT hContact = NULL; @@ -258,7 +260,7 @@ MCONTACT UpdateGetFirst() return hContact; } -void DestroyUpdateList(void) +void CWeatherProto::DestroyUpdateList(void) { WaitForSingleObject(hUpdateMutex, INFINITE); @@ -275,9 +277,11 @@ void DestroyUpdateList(void) ReleaseMutex(hUpdateMutex); } +///////////////////////////////////////////////////////////////////////////////////////// // update all weather thread // this thread update each weather station from the queue -static void UpdateThreadProc(void *) + +void CWeatherProto::UpdateThread(void *) { WaitForSingleObject(hUpdateMutex, INFINITE); if (ThreadRunning) { @@ -295,15 +299,15 @@ static void UpdateThreadProc(void *) ThreadRunning = FALSE; } -//============ 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) + +void CWeatherProto::UpdateAll(BOOL AutoUpdate, BOOL RemoveData) { // add all weather contact to the update queue list - for (auto &hContact : Contacts(MODULENAME)) + for (auto &hContact : AccContacts()) if (!g_plugin.getByte(hContact, "AutoUpdate") || !AutoUpdate) { if (RemoveData) DBDataManage(hContact, WDBM_REMOVE, 0, 0); @@ -313,12 +317,14 @@ void UpdateAll(BOOL AutoUpdate, BOOL RemoveData) // 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); + ForkThread(&CWeatherProto::UpdateThread); } +///////////////////////////////////////////////////////////////////////////////////////// // update a single station // wParam = handle for the weather station that is going to be updated -INT_PTR UpdateSingleStation(WPARAM wParam, LPARAM) + +INT_PTR CWeatherProto::UpdateSingleStation(WPARAM wParam, LPARAM) { if (IsMyContact(wParam)) { // add the station to the end of the update queue @@ -328,15 +334,17 @@ INT_PTR UpdateSingleStation(WPARAM wParam, LPARAM) // if it is updating, the stations just added to the queue will get // updated by the already-running process if (!ThreadRunning) - mir_forkthread(UpdateThreadProc); + ForkThread(&CWeatherProto::UpdateThread); } 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) + +INT_PTR CWeatherProto::UpdateSingleRemove(WPARAM wParam, LPARAM) { if (IsMyContact(wParam)) { // add the station to the end of the update queue, and also remove old data @@ -346,33 +354,37 @@ INT_PTR UpdateSingleRemove(WPARAM wParam, LPARAM) // 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); + ForkThread(&CWeatherProto::UpdateThread); } return 0; } +///////////////////////////////////////////////////////////////////////////////////////// // the "Update All" menu item in main menu -INT_PTR UpdateAllInfo(WPARAM, LPARAM) + +INT_PTR CWeatherProto::UpdateAllInfo(WPARAM, 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, LPARAM) + +INT_PTR CWeatherProto::UpdateAllRemove(WPARAM, 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(MCONTACT hContact) + +int CWeatherProto::GetWeatherData(MCONTACT hContact) { // get each part of the id's wchar_t id[256]; @@ -577,28 +589,29 @@ int GetWeatherData(MCONTACT hContact) return 0; } -//============ UPDATE TIMERS ============ -// +///////////////////////////////////////////////////////////////////////////////////////// // main auto-update timer -void CALLBACK timerProc(HWND, UINT, UINT_PTR, DWORD) + +void CWeatherProto::DoUpdate() { // only run if it is not current updating and the auto update option is enabled - if (!ThreadRunning && opt.CAutoUpdate && !Miranda_IsTerminated() && (opt.NoProtoCondition || status == ID_STATUS_ONLINE)) + if (!ThreadRunning && opt.CAutoUpdate && !Miranda_IsTerminated() && m_iStatus == 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, UINT, UINT_PTR, DWORD) + +void CWeatherProto::StartUpdate() { - KillTimer(nullptr, timerId); - ThreadRunning = FALSE; + ThreadRunning = false; - if (Miranda_IsTerminated()) - return; + if (!Miranda_IsTerminated()) + m_impl.m_update.Start(opt.UpdateTime * 60000); +} - if (opt.StartupUpdate && opt.NoProtoCondition) - UpdateAll(FALSE, FALSE); - timerId = SetTimer(nullptr, 0, ((int)opt.UpdateTime) * 60000, timerProc); +void CWeatherProto::RestartTimer() +{ + m_impl.m_update.Stop(); + m_impl.m_update.Start(opt.UpdateTime * 60000); } diff --git a/protocols/Weather/src/weather_userinfo.cpp b/protocols/Weather/src/weather_userinfo.cpp index ecee919ce5..d8e06bbde9 100644 --- a/protocols/Weather/src/weather_userinfo.cpp +++ b/protocols/Weather/src/weather_userinfo.cpp @@ -27,73 +27,47 @@ information #include "stdafx.h" -//============ BRIEF INFORMATION ============ -// -static int BriefDlgResizer(HWND, 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 -// set the title of the dialog and on the which rectangle -// also load brief info into message box -static void LoadBriefInfoText(HWND hwndDlg, MCONTACT hContact) +class CBriefInfoDlg : public CWeatherDlgBase { - wchar_t str[4096]; + static const unsigned tabstops = 48; + MCONTACT hContact; - // load weather information from the contact into the WEATHERINFO struct - WEATHERINFO winfo = LoadWeatherInfo(hContact); - // check if data exist. If not, display error message box - if (!g_plugin.getByte(hContact, "IsUpdated")) - SetDlgItemTextW(hwndDlg, IDC_MTEXT, TranslateT("No information available.\r\nPlease update weather condition first.")); - else { - // set the display text and show the message box - GetDisplay(&winfo, GetTextValue('B'), str); - SetDlgItemTextW(hwndDlg, IDC_MTEXT, str); - } + UI_MESSAGE_MAP(CBriefInfoDlg, CWeatherDlgBase); + UI_MESSAGE(WM_UPDATEDATA, OnUpdate); + UI_MESSAGE_MAP_END(); - GetDisplay(&winfo, L"%c, %t", str); - SetWindowTextW(hwndDlg, winfo.city); - SetDlgItemTextW(hwndDlg, IDC_HEADERBAR, str); -} + CCtrlButton btnUpdate, btnWebpage, btnToggle; -// dialog process for more data in the user info window -// lParam = contact handle -static INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static const unsigned tabstops = 48; - MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); +public: + CBriefInfoDlg(CWeatherProto *ppro, MCONTACT _1) : + CWeatherDlgBase(ppro, IDD_BRIEF), + hContact(_1), + btnToggle(this, IDC_MTOGGLE), + btnUpdate(this, IDC_MUPDATE), + btnWebpage(this, IDC_MWEBPAGE) + { + SetMinSize(350, 300); - switch (msg) { - case WM_INITDIALOG: - // save the contact handle for later use - hContact = lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact); + btnToggle.OnClick = Callback(this, &CBriefInfoDlg::onClick_Toggle); + btnUpdate.OnClick = Callback(this, &CBriefInfoDlg::onClick_Update); + btnWebpage.OnClick = Callback(this, &CBriefInfoDlg::onClick_Webpage); + } - 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); + bool OnInitDialog() override + { + SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_AUTOURLDETECT, (WPARAM)TRUE, 0); + SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETEVENTMASK, 0, ENM_LINK); + SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETMARGINS, EC_LEFTMARGIN, 5); + SendDlgItemMessage(m_hwnd, IDC_MTEXT, EM_SETTABSTOPS, 1, (LPARAM)&tabstops); // get the list to display { LV_COLUMN lvc = {}; - HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); + HWND hList = GetDlgItem(m_hwnd, IDC_DATALIST); RECT aRect = {}; GetClientRect(hList, &aRect); @@ -113,146 +87,140 @@ static INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, L ListView_InsertColumn(hList, 1, &lvc); // inserting data - SendMessage(hwndDlg, WM_UPDATEDATA, 0, 0); + SendMessage(m_hwnd, WM_UPDATEDATA, 0, 0); } - TranslateDialogDefault(hwndDlg); + TranslateDialogDefault(m_hwnd); // prevent dups of the window - WindowList_Add(hDataWindowList, hwndDlg, hContact); + WindowList_Add(hDataWindowList, m_hwnd, hContact); // restore window position - Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, MODULENAME, "BriefInfo_"); - return TRUE; - - case WM_UPDATEDATA: - ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_DATALIST)); - LoadBriefInfoText(hwndDlg, hContact); - DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)hwndDlg, 0); - - // set icons - { - HICON hIcon = GetStatusIconBig(hContact); - DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, LPARAM(hIcon))); - DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, LPARAM(hIcon))); - } - - RedrawWindow(GetDlgItem(hwndDlg, IDC_HEADERBAR), nullptr, nullptr, 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)); + Utils_RestoreWindowPositionNoMove(m_hwnd, NULL, MODULENAME, "BriefInfo_"); + return true; + } - Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_BRIEF), BriefDlgResizer); - } - break; + void OnDestroy() override + { + DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, 0)); + DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, 0)); - case WM_GETMINMAXINFO: - { - LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; + Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "BriefInfo_"); + WindowList_Remove(hDataWindowList, m_hwnd); + } - // The minimum width in points - mmi->ptMinTrackSize.x = 350; - // The minimum height in points - mmi->ptMinTrackSize.y = 300; - } - break; + int Resizer(UTILRESIZECONTROL *urc) override + { + switch (urc->wId) { + case IDC_HEADERBAR: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDCANCEL: - // close the info window - DestroyWindow(hwndDlg); - break; + case IDC_MTEXT: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - case IDC_MUPDATE: + case IDC_DATALIST: { - HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST); - - // update current data - // set the text to "updating" - SetDlgItemText(hwndDlg, IDC_MTEXT, TranslateT("Retrieving new data, please wait...")); - ListView_DeleteAllItems(hList); - - LV_ITEM lvi = {}; - lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.lParam = 1; - lvi.pszText = L""; - lvi.iItem = ListView_InsertItem(hList, &lvi); - lvi.pszText = TranslateT("Retrieving new data, please wait..."); - ListView_SetItemText(hList, lvi.iItem, 1, lvi.pszText); - UpdateSingleStation(hContact, 0); - break; + HWND hList = GetDlgItem(m_hwnd, IDC_DATALIST); + RECT rc; + GetWindowRect(hList, &rc); + ListView_SetColumnWidth(hList, 1, ListView_GetColumnWidth(hList, 1) + urc->dlgNewSize.cx - (rc.right - rc.left)); } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - case IDC_MWEBPAGE: - LoadForecast(hContact, 0); // read complete forecast - break; + case IDC_MUPDATE: + return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; case IDC_MTOGGLE: - if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_DATALIST))) - SetDlgItemText(hwndDlg, IDC_MTOGGLE, TranslateT("More Info")); - else - SetDlgItemText(hwndDlg, IDC_MTOGGLE, TranslateT("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; + case IDC_MWEBPAGE: + case IDCANCEL: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; } - break; + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; + } - case WM_NOTIFY: - { - LPNMHDR pNmhdr = (LPNMHDR)lParam; - if (pNmhdr->idFrom == IDC_MTEXT && pNmhdr->code == EN_LINK) { - ENLINK *enlink = (ENLINK *)lParam; - switch (enlink->msg) { - case WM_LBUTTONUP: - TEXTRANGE tr; - tr.chrg = enlink->chrg; - tr.lpstrText = (wchar_t*)mir_alloc(sizeof(wchar_t)*(tr.chrg.cpMax - tr.chrg.cpMin + 8)); - SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - Utils_OpenUrlW(tr.lpstrText); - mir_free(tr.lpstrText); - break; - } - } + INT_PTR OnUpdate(UINT, WPARAM, LPARAM) + { + ListView_DeleteAllItems(GetDlgItem(m_hwnd, IDC_DATALIST)); + + wchar_t str[4096]; + + // load weather information from the contact into the WEATHERINFO struct + WEATHERINFO winfo = LoadWeatherInfo(hContact); + // check if data exist. If not, display error message box + if (!g_plugin.getByte(hContact, "IsUpdated")) + SetDlgItemTextW(m_hwnd, IDC_MTEXT, TranslateT("No information available.\r\nPlease update weather condition first.")); + else { + // set the display text and show the message box + GetDisplay(&winfo, m_proto->GetTextValue('B'), str); + SetDlgItemTextW(m_hwnd, IDC_MTEXT, str); } - break; - case WM_CLOSE: - DestroyWindow(hwndDlg); - break; + GetDisplay(&winfo, L"%c, %t", str); + SetWindowTextW(m_hwnd, winfo.city); + SetDlgItemTextW(m_hwnd, IDC_HEADERBAR, str); + + DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)m_hwnd, 0); + + // set icons + HICON hIcon = GetStatusIconBig(hContact); + DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, LPARAM(hIcon))); + DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, LPARAM(hIcon))); - case WM_DESTROY: - DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); - DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); + RedrawWindow(GetDlgItem(m_hwnd, IDC_HEADERBAR), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); + return 0; + } - Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, "BriefInfo_"); - WindowList_Remove(hDataWindowList, hwndDlg); - break; + void onClick_Update(CCtrlButton *) + { + HWND hList = GetDlgItem(m_hwnd, IDC_DATALIST); + + // update current data + // set the text to "updating" + SetDlgItemText(m_hwnd, IDC_MTEXT, TranslateT("Retrieving new data, please wait...")); + ListView_DeleteAllItems(hList); + + LV_ITEM lvi = {}; + lvi.mask = LVIF_TEXT | LVIF_PARAM; + lvi.lParam = 1; + lvi.pszText = L""; + lvi.iItem = ListView_InsertItem(hList, &lvi); + lvi.pszText = TranslateT("Retrieving new data, please wait..."); + ListView_SetItemText(hList, lvi.iItem, 1, lvi.pszText); + m_proto->UpdateSingleStation(hContact, 0); } - return FALSE; -} + void onClick_Webpage(CCtrlButton *) + { + m_proto->LoadForecast(hContact, 0); // read complete forecast + } -// show brief information dialog -// wParam = current contact -int BriefInfo(WPARAM wParam, LPARAM) + void onClick_Toggle(CCtrlButton *) + { + if (IsWindowVisible(GetDlgItem(m_hwnd, IDC_DATALIST))) + SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("More Info")); + else + SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("Brief Info")); + ShowWindow(GetDlgItem(m_hwnd, IDC_DATALIST), (int)!IsWindowVisible( + GetDlgItem(m_hwnd, IDC_DATALIST))); + ShowWindow(GetDlgItem(m_hwnd, IDC_MTEXT), (int)!IsWindowVisible(GetDlgItem(m_hwnd, IDC_MTEXT))); + } +}; + +INT_PTR CWeatherProto::BriefInfo(WPARAM hContact, LPARAM) { // make sure that the contact is actually a weather one - if (!IsMyContact(wParam)) + if (!IsMyContact(hContact)) return 0; - HWND hMoreDataDlg = WindowList_Find(hDataWindowList, wParam); + HWND hMoreDataDlg = WindowList_Find(hDataWindowList, hContact); if (hMoreDataDlg != nullptr) { SetForegroundWindow(hMoreDataDlg); SetFocus(hMoreDataDlg); } - else hMoreDataDlg = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_BRIEF), nullptr, DlgProcMoreData, (LPARAM)wParam); + else { + auto *pDlg = new CBriefInfoDlg(this, hContact); + pDlg->Create(); + hMoreDataDlg = pDlg->GetHwnd(); + } ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 0); ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 1); @@ -260,6 +228,11 @@ int BriefInfo(WPARAM wParam, LPARAM) return 1; } +int CWeatherProto::BriefInfoEvt(WPARAM wParam, LPARAM) +{ + return BriefInfo(wParam, 0); +} + ///////////////////////////////////////////////////////////////////////////////////////// // User info dialog @@ -323,8 +296,12 @@ public: void onClick_Detail(CCtrlButton *) { HWND hMoreDataDlg = WindowList_Find(hDataWindowList, m_hContact); - if (hMoreDataDlg == nullptr) - hMoreDataDlg = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_BRIEF), nullptr, DlgProcMoreData, m_hContact); + if (hMoreDataDlg == nullptr) { + auto *ppro = (CWeatherProto*)Proto_GetContactInstance(m_hContact); + auto *pDlg = new CBriefInfoDlg(ppro, m_hContact); + pDlg->Create(); + hMoreDataDlg = pDlg->GetHwnd(); + } else { SetForegroundWindow(hMoreDataDlg); SetFocus(hMoreDataDlg); @@ -334,7 +311,7 @@ public: } }; -int UserInfoInit(WPARAM wParam, LPARAM hContact) +int CWeatherProto::UserInfoInit(WPARAM wParam, LPARAM hContact) { USERINFOPAGE uip = {}; uip.szTitle.a = MODULENAME; diff --git a/protocols/Weather/weather.vcxproj b/protocols/Weather/weather.vcxproj index 35e9cf3032..938d3773d0 100644 --- a/protocols/Weather/weather.vcxproj +++ b/protocols/Weather/weather.vcxproj @@ -40,9 +40,11 @@ <ClCompile Include="src\weather_mwin.cpp" /> <ClCompile Include="src\weather_opt.cpp" /> <ClCompile Include="src\weather_popup.cpp" /> + <ClCompile Include="src\weather_proto.cpp" /> <ClCompile Include="src\weather_svcs.cpp" /> <ClCompile Include="src\weather_update.cpp" /> <ClCompile Include="src\weather_userinfo.cpp" /> + <ClInclude Include="src\proto.h" /> <ClInclude Include="src\resource.h" /> <ClInclude Include="src\stdafx.h" /> <ClInclude Include="src\version.h" /> diff --git a/protocols/Weather/weather.vcxproj.filters b/protocols/Weather/weather.vcxproj.filters index a8fbc7147e..07d844fda7 100644 --- a/protocols/Weather/weather.vcxproj.filters +++ b/protocols/Weather/weather.vcxproj.filters @@ -47,6 +47,9 @@ <ClCompile Include="src\weather_userinfo.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\weather_proto.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\resource.h"> @@ -58,6 +61,9 @@ <ClInclude Include="src\version.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="src\proto.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="res\resource.rc"> |
