summaryrefslogtreecommitdiff
path: root/plugins/Weather/src/weather_contacts.cpp
blob: 5fdb1d097da5ce49041960e604d62c60f3796295 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/*
Weather Protocol plugin for Miranda IM
Copyright (c) 2012 Miranda NG team
Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved
Copyright (c) 2002-2005 Calvin Che

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* This file contain the source that is related to weather contacts,
include the links, edit settings, and loading weather information for
the contact.
*/

#include "stdafx.h"

static void OpenUrl(wchar_t* format, wchar_t* id)
{
	wchar_t loc[512];
	GetID(id);
	mir_snwprintf(loc, format, id);
	Utils_OpenUrlW(loc);
}

//============ BASIC CONTACTS FUNCTIONS AND LINKS  ============

// view weather log for the contact
// wParam = current contact
INT_PTR ViewLog(WPARAM wParam, LPARAM lParam)
{
	// see if the log path is set
	DBVARIANT dbv;
	if (!db_get_ws(wParam, WEATHERPROTONAME, "Log", &dbv)) {
		if (dbv.pszVal[0] != 0)
			ShellExecute((HWND)lParam, L"open", dbv.ptszVal, L"", L"", SW_SHOW);
		db_free(&dbv);
	}
	else	// display warning dialog if no path is specified
		MessageBox(nullptr, TranslateT("Weather condition was not logged."),
			TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION);
	return 0;
}

// read complete forecast
// wParam = current contact
INT_PTR LoadForecast(WPARAM wParam, LPARAM)
{
	wchar_t id[256], loc2[256];
	GetStationID(wParam, id, _countof(id));
	if (id[0] != 0) {
		// check if the complte forecast URL is set. If it is not, display warning and quit
		if (db_get_wstatic(wParam, WEATHERPROTONAME, "InfoURL", loc2, _countof(loc2)) || loc2[0] == 0) {
			MessageBox(nullptr, NO_FORECAST_URL, TranslateT("Weather Protocol"), MB_ICONINFORMATION);
			return 1;
		}
		// set the url and open the webpage
		OpenUrl(loc2, id);
	}
	return 0;
}

// load weather map
// wParam = current contact
INT_PTR WeatherMap(WPARAM wParam, LPARAM)
{
	wchar_t id[256], loc2[256];
	GetStationID(wParam, id, _countof(id));
	if (id[0] != 0) {
		// check if the weather map URL is set. If it is not, display warning and quit
		if (db_get_wstatic(wParam, WEATHERPROTONAME, "MapURL", loc2, _countof(loc2)) || loc2[0] == 0) {
			MessageBox(nullptr, NO_MAP_URL, TranslateT("Weather Protocol"), MB_ICONINFORMATION);
			return 1;
		}

		// set the url and open the webpage
		OpenUrl(loc2, id);
	}

	return 0;
}

//============ EDIT SETTINGS  ============

typedef struct
{
	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;
	wchar_t str[MAX_DATA_LEN], str2[256], city[256], filter[256], *pfilter, *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);

		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)wndData);

		// set button images
		SendDlgItemMessage(hwndDlg, IDC_GETNAME, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);
		SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hUserDetail);
		SendDlgItemMessage(hwndDlg, IDC_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hFile);
		SendDlgItemMessage(hwndDlg, IDC_VIEW1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll);
		SendDlgItemMessage(hwndDlg, IDC_RESET1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);
		SendDlgItemMessage(hwndDlg, IDC_VIEW2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll);
		SendDlgItemMessage(hwndDlg, IDC_RESET2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);

		// make all buttons flat
		SendDlgItemMessage(hwndDlg, IDC_GETNAME, BUTTONSETASFLATBTN, 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);

		// 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);

		// save the handle for the contact
		WindowList_Add(hWindowList, hwndDlg, hContact);

		// start to get the settings
		// if the setting not exist, leave the dialog box blank
		if (!db_get_ws(hContact, WEATHERPROTONAME, "ID", &dbv)) {
			SetDlgItemText(hwndDlg, IDC_ID, dbv.ptszVal);
			// check if the station is a default station
			CheckDlgButton(hwndDlg, IDC_DEFA, mir_wstrcmp(dbv.ptszVal, opt.Default) != 0 ? BST_CHECKED : BST_UNCHECKED);
			db_free(&dbv);
		}
		if (!db_get_ws(hContact, WEATHERPROTONAME, "Nick", &dbv)) {
			SetDlgItemText(hwndDlg, IDC_NAME, dbv.ptszVal);
			db_free(&dbv);
		}
		if (!db_get_ws(hContact, WEATHERPROTONAME, "Log", &dbv)) {
			SetDlgItemText(hwndDlg, IDC_LOG, dbv.ptszVal);
			// if the log path is not empty, check the checkbox for external log
			if (dbv.ptszVal[0]) CheckDlgButton(hwndDlg, IDC_External, BST_CHECKED);
			db_free(&dbv);
		}
		// enable/disable the browse button depending on the value of external log checkbox
		EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));

		// other checkbox options
		CheckDlgButton(hwndDlg, IDC_DPop, db_get_b(hContact, WEATHERPROTONAME, "DPopUp", FALSE) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_DAutoUpdate, db_get_b(hContact, WEATHERPROTONAME, "DAutoUpdate", FALSE) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_Internal, db_get_b(hContact, WEATHERPROTONAME, "History", 0) ? BST_CHECKED : BST_UNCHECKED);

		if (!db_get_ws(hContact, WEATHERPROTONAME, "InfoURL", &dbv)) {
			SetDlgItemText(hwndDlg, IDC_IURL, dbv.ptszVal);
			db_free(&dbv);
		}
		if (!db_get_ws(hContact, WEATHERPROTONAME, "MapURL", &dbv)) {
			SetDlgItemText(hwndDlg, IDC_MURL, dbv.ptszVal);
			db_free(&dbv);
		}

		// display the dialog box and free memory
		Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, WEATHERPROTONAME, "EditSetting_");
		ShowWindow(hwndDlg, SW_SHOW);
		break;

	case WM_COMMAND:
		wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
		hContact = wndData ? wndData->hContact : NULL;

		switch (LOWORD(wParam)) {
		case IDC_ID:
			// check if there are 2 parts in the ID (svc/id) seperated by "/"
			// if not, don't let user change the setting
			GetDlgItemText(hwndDlg, IDC_ID, str, _countof(str));
			chop = wcsstr(str, L"/");
			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);
			}

			// give no station name but only ID if the search is unavailable
			if (str[0] != 0)
				SetDlgItemText(hwndDlg, IDC_NAME, str);
			break;

		case IDC_External:
			// enable/disable the borwse button depending if the external log is enabled
			EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));
			if (!(BYTE)IsDlgButtonChecked(hwndDlg, IDC_External))
				return TRUE;
			__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
			wcsncpy(filter, TranslateT("Text Files"), _countof(filter) - 1);
			mir_wstrncat(filter, L" (*.txt)", _countof(filter) - mir_wstrlen(filter));
			pfilter = filter + mir_wstrlen(filter) + 1;
			wcsncpy(pfilter, L"*.txt", _countof(filter) - 1);
			pfilter = pfilter + mir_wstrlen(pfilter) + 1;
			wcsncpy(pfilter, TranslateT("All Files"), _countof(filter) - 1);
			mir_wstrncat(pfilter, L" (*.*)", _countof(filter) - mir_wstrlen(filter));
			pfilter = pfilter + mir_wstrlen(pfilter) + 1;
			wcsncpy(pfilter, L"*.*", _countof(filter) - 1);
			pfilter = pfilter + mir_wstrlen(pfilter) + 1;
			*pfilter = '\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));
			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));
			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));
			db_set_ws(hContact, WEATHERPROTONAME, "ID", str);
			if ((BYTE)IsDlgButtonChecked(hwndDlg, IDC_DEFA)) {	// if default station is set
				mir_wstrcpy(opt.Default, str);
				opt.DefStn = hContact;
				db_set_ws(NULL, WEATHERPROTONAME, "Default", opt.Default);
			}
			GetDlgItemText(hwndDlg, IDC_NAME, city, _countof(city));
			db_set_ws(hContact, WEATHERPROTONAME, "Nick", city);
			mir_snwprintf(str2, TranslateT("Current weather information for %s."), city);
			if ((BYTE)IsDlgButtonChecked(hwndDlg, IDC_External)) {
				GetDlgItemText(hwndDlg, IDC_LOG, str, _countof(str));
				db_set_ws(hContact, WEATHERPROTONAME, "Log", str);
			}
			else db_unset(hContact, WEATHERPROTONAME, "Log");

			GetDlgItemText(hwndDlg, IDC_IURL, str, _countof(str));
			db_set_ws(hContact, WEATHERPROTONAME, "InfoURL", str);

			GetDlgItemText(hwndDlg, IDC_MURL, str, _countof(str));
			db_set_ws(hContact, WEATHERPROTONAME, "MapURL", str);
			db_set_w(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE);
			db_set_w(hContact, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE);
			AvatarDownloaded(hContact);
			db_set_ws(hContact, WEATHERPROTONAME, "About", str2);
			db_set_b(hContact, WEATHERPROTONAME, "History", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_Internal));
			db_set_b(hContact, WEATHERPROTONAME, "Overwrite", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_Overwrite));
			db_set_b(hContact, WEATHERPROTONAME, "File", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));
			db_set_b(hContact, WEATHERPROTONAME, "DPopUp", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DPop));
			db_set_b(hContact, WEATHERPROTONAME, "DAutoUpdate", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DAutoUpdate));

			// re-enable the protocol and update the data for the station
			db_set_s(hContact, WEATHERPROTONAME, "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, WEATHERPROTONAME, "EditSetting_");
		break;
	}
	return FALSE;
}

// show edit settings dialog
// wParam = current contact
INT_PTR EditSettings(WPARAM wParam, LPARAM)
{
	HWND hEditDlg = WindowList_Find(hWindowList, wParam);

	// search the dialog list to prevent multiple instance of dialog for the same contact
	if (hEditDlg != nullptr) {
		// if the dialog box already opened, bring it to the front
		SetForegroundWindow(hEditDlg);
		SetFocus(hEditDlg);
	}
	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);
	}

	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);

	// exit this function if it is not default station
	ptrW tszID(db_get_wsa(wParam, WEATHERPROTONAME, "ID"));
	if (tszID != NULL)
		if (mir_wstrcmp(tszID, opt.Default))
			return 0;

	// now the default station is deleted, try to get a new one

	// start looking for other weather stations
	for (auto &hContact : Contacts(WEATHERPROTONAME)) {
		tszID = db_get_wsa(hContact, WEATHERPROTONAME, "ID");
		if (tszID == NULL)
			continue;

		// if the station is not a default station, set it as the new default station
		// this is the first weather station encountered from the search
		if (mir_wstrcmp(opt.Default, tszID)) {
			wcsncpy_s(opt.Default, tszID, _TRUNCATE);
			opt.DefStn = hContact;
			ptrW tszNick(db_get_wsa(hContact, WEATHERPROTONAME, "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);
			}
			db_set_ws(NULL, WEATHERPROTONAME, "Default", opt.Default);
			return 0;		// exit this function quickly
		}
	}

	// got here if no more weather station left
	opt.Default[0] = 0;	// no default station
	opt.DefStn = NULL;
	db_set_ws(NULL, WEATHERPROTONAME, "Default", opt.Default);
	return 0;
}

BOOL IsMyContact(MCONTACT hContact)
{
	const char *szProto = GetContactProto(hContact);
	return szProto != nullptr && mir_strcmp(WEATHERPROTONAME, szProto) == 0;
}