summaryrefslogtreecommitdiff
path: root/protocols/Weather
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Weather')
-rw-r--r--protocols/Weather/docs/history.txt930
-rw-r--r--protocols/Weather/docs/license.txt340
-rw-r--r--protocols/Weather/docs/readme.html230
-rw-r--r--protocols/Weather/docs/sample_ini.ini428
-rw-r--r--protocols/Weather/docs/weather/gismeteo_com.ini1254
-rw-r--r--protocols/Weather/docs/weather/gismeteo_ru.ini1331
-rw-r--r--protocols/Weather/docs/weather/msn.ini1057
-rw-r--r--protocols/Weather/res/resource.rc172
-rw-r--r--protocols/Weather/src/proto.h296
-rw-r--r--protocols/Weather/src/resource.h31
-rw-r--r--protocols/Weather/src/stdafx.cxx2
-rw-r--r--protocols/Weather/src/stdafx.h457
-rw-r--r--protocols/Weather/src/version.h8
-rw-r--r--protocols/Weather/src/weather.cpp125
-rw-r--r--protocols/Weather/src/weather_addstn.cpp382
-rw-r--r--protocols/Weather/src/weather_contacts.cpp511
-rw-r--r--protocols/Weather/src/weather_conv.cpp286
-rw-r--r--protocols/Weather/src/weather_data.cpp420
-rw-r--r--protocols/Weather/src/weather_http.cpp132
-rw-r--r--protocols/Weather/src/weather_info.cpp203
-rw-r--r--protocols/Weather/src/weather_ini.cpp581
-rw-r--r--protocols/Weather/src/weather_mwin.cpp70
-rw-r--r--protocols/Weather/src/weather_opt.cpp673
-rw-r--r--protocols/Weather/src/weather_popup.cpp475
-rw-r--r--protocols/Weather/src/weather_proto.cpp166
-rw-r--r--protocols/Weather/src/weather_svcs.cpp274
-rw-r--r--protocols/Weather/src/weather_update.cpp590
-rw-r--r--protocols/Weather/src/weather_userinfo.cpp409
-rw-r--r--protocols/Weather/weather.vcxproj5
-rw-r--r--protocols/Weather/weather.vcxproj.filters15
30 files changed, 2275 insertions, 9578 deletions
diff --git a/protocols/Weather/docs/history.txt b/protocols/Weather/docs/history.txt
deleted file mode 100644
index bf3351da1d..0000000000
--- a/protocols/Weather/docs/history.txt
+++ /dev/null
@@ -1,930 +0,0 @@
-Weather Protocol - Version History
-==================================
-Version 0.3.8.19 2011/09/03
- - Fixed Brief window update on weather station update
- - Fixed No ini window no show
-
-Version 0.3.8.18 2010/08/20
- - Specialized translations for all weather conditions
- - Fixed possible crashes
-
-Version 0.3.8.17 2010/05/29
- - Added possibility to add specialized translations for weather conditions
- format: #condition Weather
- - Added 32x32 icon support
- - 32x32 icon is used in a frame in a frame if no avatar present
- - Added support for Miranda 0.9 persistent http trasactions
- - Changed Breif dialog appearence
- - Fixed translation issues
- - Fixed keyborad navigation in UserInfo dialog
- - Requires Miranda 0.8 or higher
-
-Version 0.3.8.16 2009/08/09
- - Increased allowed size of station id
- - Removed built-in support for HTTP compression (compression not supported with pre 0.8 Miranda any longer)
- - Fixed crash with no ini files
- - x64 port
-
-Version 0.3.8.15 2009/03/22
- - Added support for gif avatars
- - Added support for 4 urls per ini
- - Added supoort for html metadata (utf8)
- - Fixed rounding with fractional reading display
- - Added more http redirection support
- - Allow to draw forced avatar in frame
-
-Version 0.3.8.14 2009/01/10
- - Fixed Set Data failures
- - Fixed crashes with http
- - Fixed http errors processing
- - Added support for temperature in format -<space><number>
-
-Version 0.3.8.13 2008/12/25
- - Changed search UI to have more descriptive labels
- - Documentation updates
-
-Version 0.3.8.12 2008/12/22
- - Added support for cookies (cakes and ice cream)
-
-Version 0.3.8.10 2008/12/07
- - Fixed temperature display
-
-Version 0.3.8.9 2008/12/06
- - Added support for deflate compressed http streams
- - Fixes for weather crashes
- - Added option to round all values to nearest integer
-
-Version 0.3.8.8 2008/11/22
- - Improved formatting for numerical values
- - Fixed crashes due to compressed http stream
- - Added support for gzip encoded http stream
-
-Version 0.3.8.7 2008/08/02
- - Fixed crash for people measuring speed in km/h
-
-Version 0.3.8.6 2008/08/01
- - Added display fraction of temperature and wind speed when available
- - Added handling of UTF8 pages (needed for GisMeteo)
-
-Version 0.3.8.5 2008/07/27
- - Fixed option dialog layout
- - Fixed ini version display
- - Fixed memory leak with multiurl ini
- - Fixed plugin version number
-
-Version 0.3.8.3 2008/07/24
- - Fixed url tag
- - Added headers to variable view
- - Fixed options dialog layout
-
-Version 0.3.8.2 2008/06/08
- - Fixed ini version display in User Info
- - Fixes for wind in Weather Underground ini to work correctly
-
-Version 0.3.8.1 2008/05/25
- - Added ability to parse upto 3 URL per ini file for weather data
- - Fixed break data and parameters with units
- - Added ability to skin weather frame with clist_modern ("Main,ID=WeatherFrame")
- - Added display "nickname" in the first line of the frame
- - Added avatar display in the weather frame
-
-Version 0.3.7.2 2008/01/19
- - Fixed updates in normal mode
- - Fixed option dialog layout
-
-Version 0.3.7.1 2007/12/22
- - Partial workaround for core HTTP problem
- - Tabbed option dialog
-
-Version 0.3.7.0 2007/12/21
- - Added icolib support
- - Added frames support
- - New icons by Angeli-Ka
- - Compatible with Miranda 0.7 and later
-
-Version 0.3.6.5 2007/08/17
- - Workaround for tray icon
-
-Version 0.3.6.4 2007/07/27
- - Fixed caching problems
-
-Version 0.3.6.3 2007/07/08
- - Fixed error message at stratup (with updater)
- - Increased possible weather variable size
- - More generic couldy definition
-
-Version 0.3.6.2 2007/06/02
- - More sensible autoupdate Enable/Disable operation
-
-Version 0.3.6.1 2007/06/01
- - Fixed popup click action
- - Fixed translation
-
-Version 0.3.6.0 2007/05/18
- - New icons by Angeli-Ka
- - Protocol icons split into separate dll
- - Option dialog and menus redesign
- - Instant avatar update
- - Ini file display name now used as client ID (MirVer)
- - Moved ini file list into View/Change My Details
- - Support for new plugin interface
- - Fixed few parsing issues
-
-Version 0.3.5.19 2007/01/27
- - Fixed translation
-
-Version 0.3.5.18 2007/01/26
- - Fixed translation
- - Fixed resource leaks
- - Fixed crash
- - Partial unicode support
-
-Version 0.3.5.17 2007/01/20
- - Reduced GDI resource utilization
- - Fixed memory leak with old ini files
- - Fixed search function for stations with special characters
-
-Version 0.3.5.16 2006/11/27
- - Fixed units conversion
- - Fixed memory corruption
- - Added ability to show clickable links in Brief window
-
-Version 0.3.5.15 2006/11/16
- - Fixed web page parsing (Wind Speed in Yahoo)
- - Fixed "No wind" condition handling
- - Performance improvments for HTTP transfers
- - Fixed memory corruption
-
-Version 0.3.5.14 2006/10/31
- - Fixed status message operation
-
-Version 0.3.5.13 2006/10/29
- - Fixed non english alphabets operation
- - Fixed Weather condition update issues
- - Added option to keep station status from reflecting weather condition
- (should resolve avatar overlay problems with clist modern)
- - Moved Weather main menu entry into the protocol group
- - Improvements for forecast window sizing
-
-Version 0.3.5.12 2006/07/23
- - Fixed non english alphabets operation
-
-Version 0.3.5.11 2006/07/22
- - Fixed text corruption
- - Added ability to display avatars for each weather condition
- - Fixed Win95 operation
-
-Version 0.3.5.10 2006/07/16
- - Changed Current Date/Time display (%d) according to locale
- - Changed handling of HTTP redirect requests
-
-Version 0.3.5.9 2006/04/08
- - Fixed misplaced buttons on forecast view window
- - Fixed weather history incorrect source
- - Fixed incorrect PopUp notification text in the menu
-
-Version 0.3.5.8 2005/09/20
- - Fixed automatic set of deafult station logic failure and as a result crash at power-up
- - Fixed INI info dialog layout and ini version information
- - Fixed rare crash on exit
- - Fixed resource leak
- - Fixed few memory leaks
- - Fixed crash at power-up with corrupted ini file
- - A lot of code robustness updates
-
-Version 0.3.5.7 2005/09/18
- - Fixed few resource leaks
- - Fixed gloabal status
- - Fixed weather alert format
- - Fixed very rare crash on exit
-
-Version 0.3.5.6 2005/09/14
- - Fixed few crashes on exit and
- - A lot of code robustness updates
- - Updater compatibility
- - Fixed resource leaks
-
-Version 0.3.5.5 2005/09/11
- - Fixed crash on exit
- - Support for custom "Status Messages"
-
-Version 0.3.5.4 2005/09/08
- - Fixed crash in my User details
- - Fixed endless "updating user info ..."
- - Fixed search function regression
-
-Version 0.3.5.3 2005/09/07
- - Fixed crash at Powerup
- - Fixed crash on Miranda exit
- - Fixed numerous other crashes
- - Fixed numerous memory leaks
- - Fixed memory corruption
- - Fixed resource leak
-
-Version 0.3.5.2 2005/09/07
- - Fixed crash on Miranda exit
- - Fixed numerous other crashes
- - Fixed numerous memory leaks
- - Fixed memory corruption
- - Fixed resource leak
-
-Version 0.3.5.0 2005/03/21
- - New Option: Disable update on startup
- - New Option: Enable/Disable popups by type: update, alert, error
- - INI Option: Support breaking string
- - INI Option: Support hidden fields
- - INI Option: Support icon assignment from ini
- - Updated sample_ini.ini and translation
- - Some other minor changes that I can't remember
-
-Version 0.3.4.4 2004/12/28
- - Load window list correctly, fix problem with brief info and edit dlg not showing
- - Some internal changes with new service functions
-
-Version 0.3.4.3 2004/12/26
- - Minor change in INI loading
-
-Version 0.3.4.2 Beta 2004/12/16
- - Bug fix: Miranda cannot quit after forkthread is used
- - Bug fix: The unit % does not work anymore
- - Bug fix: No longer crash when the link settings is not set
- - Update the weather ini download link to the new location
-
-Version 0.3.4.1 Beta 2004/12/09
- - ESC now works in weather dialogs
- - More changes to forkthread
- - Document updated: weather-translation, sample_ini
-
-Version 0.3.4.0 Beta 2004/11/21
- - Change the threading to forkthread
- - New option: Custom status when condition is unavailable
- - New option: Convert day/month string into 2 char or 3 char format
- - Some internal changes
- - Minor change in ini format
-
-Version 0.3.3.17 2004/11/19
- - Condition translated correctly when writing into database
- - Correctly restore the windows position for edit setting dialog
-
-Version 0.3.3.16 2004/11/10
-
-Version 0.3.3.15 2004/10/21
- - Remember the window position for edit settings dialog
- - Minor change in dialog (I still can't get the close on ESC to work...)
-
-Version 0.3.3.14 Beta 2004/10/20
- - Fix the crash in option page bug (hopefully)
- - Fix the support for \n in text input
- - Minor change in dialog
-
-Version 0.3.3.13 2004/10/16
- - Another fix for default station
- - Some changes to reduce database read/write for default station changes
- - Now the plugin is correctly registered in known module list for DBEditor++
- - Save the setting for popup and update enable/disable directly after menu click
- - Some update in readme, more changes in translation (thanks smyle again)
-
-Version 0.3.3.12 2004/10/16
- - Fix 2 possible crashes regarding default station
-
-Version 0.3.3.11 2004/10/15
- - Fix a bug with global status
- - Updated translation list (thanks smyle)
-
-Version 0.3.3.10 2004/10/14
- - Changes in default station handling, hopefully will fix a crash in option page
- - Add new sound event: Weather alert
- - Add new menu item: Add new weather station (call up the find/add dialog)
- - Document updated: weather_translation.txt
-
-Version 0.3.3.9 2004/09/26
- - Some changes in code.
-
-Version 0.3.3.8 2004/09/24
- - Now uses default system text for brief info and setup dialog.
-
-Version 0.3.3.7 (Beta)
- - Test releases for crash in option page
-
-Version 0.3.3.6 2004/09/24
- - Add a sound event when weather condition is updated
- - Use the default system color for brief info and setup dialog
- - Minor change in unit conversion
- - Fix in brief info when there is no data for current conditions
- - Add entry to Database Editor++ known module
-
-Version 0.3.3.5 2004/08/14
- - Fix apply button in option pages
- - Fix "Humidity" in default settings
- - Ignore the sample ini file if it is placed in plugin\weather dir
- - Minor changes in update timer and option dialog
-
-Version 0.3.3.4 (Beta) 2004/07/23
- - Fix some bug in text option
- - Take proto_weather.dll icon into account when auto-assigning icon
- - Option to disable automatic icon assignment
- - Few minor changes
- - Document updated: weather_translation.txt
-
-Version 0.3.3.3 2004/07/21
- - Automatically set to default weather icon if no custom one is set
- - Add a ini setup information dialog to help setup weather protocol
- - Update in brief info now retrieve new data from the internet
- - Few minor changes
- - Document updated: weather_translation.txt
-
-Version 0.3.3.2 (Beta) 2004/07/14
- - Show error detail on update errors
- - Includes simple set of 16-colors weather icons in the dll file
- - Option to disable italic display for station with alert issued
- - Option to disable warning dialog if ini is not found at startup
- - Attempt to fix the black bar bug in brief info
- - Fix the bug that shows connecting as weather status
- - Document updated: weather_translation.txt
-
-Version 0.3.3.1 2004/06/19
- - Minor change in the brief info dialog
- - More info items are now translatable
- - Case conversion in condition to make them translatable (use unit: Cond)
- - Save window size for the brief info dialog
- - Fix crash when invalid ID or ini file for the station is not found
- - Few minor changes
- - Document updated: sample_ini
-
-Version 0.3.3.0 (Beta) 2004/06/12
- - A new feature that erase old data while updating for new data
- - A change in the brief information dialog (thanks micron-x for last seen plugin)
- - Double click a contact shows brief info dialog (thanks Matrix and JdGordon)
- - Add brief info title setting
- - Change in the weather, text, and popup options dialogs
- - Add reset to default and preview for all display text field
- - Change the way the plugin handles protocol status
- - Enable/disable auto-update from the main menu
- - Reconizes dust conditions and assign a fog icon (thanks Klenje)
- - Support the units "%" and "Deg"
- - Fix a crash if miranda32.exe is renamed
- - Fix crashes in between updating of 2 stations (thanks Targaff)
- - Update links in the readme and DLL to the new weather category (thanks lynlimz)
- - Other bug fixes and minor changes
- - Document updated: weather-translation, langpack_defweather, sample_ini
-
-Version 0.3.2.16 2004/05/27
- - Reconizes condition in lower case
- - Few changes.
-
-Version 0.3.2.15 2004/05/24
- - Now reconizes the condition string "T-storm"
- - No longer skip hidden weather contact while updating
- - Bug fix when previewing weather popups
- - Bug fix in parsing the HTML content (in cases where "&" exists)
- - Few other minor fixes and changes.
-
-Version 0.3.2.14 2004/05/12
- - Popup preview include a preview of popup text settings (use default station)
- - Fix memory leaks in various places.
-
-Version 0.3.2.13 2004/05/08
- - Changed some linker options to prevent plugin not loading
-
-Version 0.3.2.12 2004/05/08
- - Assign fog icon to the sand conditions
-
-Version 0.3.2.11 2004/05/07
- - Really ignore the "Ignore" item in the ini file
- - Fix crash when unloading ini's (at reload or shutdown)
- - Change in weather alert popup
- - Few minor changes
-
-Version 0.3.2.10 2004/05/02
- - Rebuild using Visual C++
-
-Version 0.3.2.9 2004/04/29
- - Attempt to fix crash when searching for cities by name
- - Display a list of custom variables
- - Fix memory leak when reloading strings from ini files
- - Changes in the code for parsing weather info and loading ini files
- - Other minor changes
-
-Version 0.3.2.8 2004/04/28
- - Fix on loading ini strings, support for v1.1a again
- - Fix in weather station search
- - Fix crash when not connected to the internet
- - Add a new debug function (need DB Editor)
- - A few other minor fixes and changes
-
-Version 0.3.2.7 2004/04/19
- - Fixing the crash on startup bug one more time :(
-
-Version 0.3.2.6 2004/04/19
- - Attempt to fix an crash on startup bug again.
- - Temporary remove support for v1.1a of the INI file. :(
-
-Version 0.3.2.5 2004/04/19
- - Attempt to fix an crash on startup bug.
-
-Version 0.3.2.4 2004/04/19
- - Fix some error while loading weather ini file.
- - Obtain station name from the net in edit dialog.
- - Display N/A when temperature is unavail. and the string retrieved is not "N/A"
- - Some minor changes.
-
-Version 0.3.2.3 2004/04/18
- - Automatically suppress online notification for all weather contact when upgrade.
- - Fixed crash when adding new contact.
- - Fixed crash when importing contact using mContacts.
- - Some minor changes.
-
-Version 0.3.2.2 2004/04/18
- - Change the way weather handles status, now properly display NA for def stn.
- - Protocol status can be changed freely if "Do not display weather conditions
- as protocol status" is enabled.
- - More memory leak fixes and crash fixes.
-
-Version 0.3.2.1 2004/04/17
- - Reduce memory use by more than 60% and fixed some memory leaks
- - Support a revision of v1.1 ini file (the length string now can be unlimited)
- - Incrase the maximun text length to 4k (but try keep it as short as possible)
- - A few minor fixes and changes
- - Updated readme file.
-
-Version 0.3.2.0 2004/04/12
- - Support new variable %% (same as \%) and %[..] (see readme)
- - Now with the complete support of weather INI v1.1
- - Very basic support of weather alert notifications (if the INI supports it)
- - Add browse, view webpage, and reset to default buttons edit settings dialog
- - Interface changes and fixed tab order for all dialogs
- - Display information for the weather INI files
- - Some other monor changes and fixes
- - Updates Read Me, and now it is in HTML format.
-
-Version 0.3.1.8 2004/04/09
- - "My Notes" text are copied to "Current\WeatherInfo" (might be useful for some plugins)
- - Increase the length of display texts from 512b to 4k
- - Bug Fix: when temperature is N/A, display N/A
- - Bug Fix: rounding in unit conversion, err...
- - Bug Fix: crash with new ini setting "Set Data="
-
-Version 0.3.1.7 2004/04/08
- - Now correctly support the new ini files.
-
-Version 0.3.1.6 2004/04/04
- - Support escape characters "\%" for displaying %
- - Changes in warning popups
-
-Version 0.3.1.5 2004/04/02
- - New option: Consider weather info updated only when cond and temp are changed
- - Support v1.1 of weather ini files - only support loading, but not the new features ;)
- - Rounding is used when converting units
- - Attempt to fix the crash on exit and reload weather data bug
- - The default update time is changed to 20 min
- - Other minor fixes and changes that I don't remember
-
-Version 0.3.1.1 2004/03/27
- - Fix the crash when opening brief info dialog
- - The default for "Support online notification" is on when adding new station
-
-Version 0.3.1.0 2004/03/25
- - Change the way popup is handled, no longer need to enable the threading option
- - Manually add station without searching by entering "#" in the ID field
- - Always provide a search result if the weather service has no ID search available.
- - Some error handling and popups to prevent crashes.
- - New hookable event: ME_WEATHER_UPDATED
- - Bug fix: Translation of retrieved data
- - Bug fix: Search don't work for city that has more than 1 word
- - Bug fix: Speed conversion is wrong
- - Bug fix: weatherch.ini: Crash if adding/updating a station in US Eastern timezone
- - Updated: weatherch.ini, Read Me, Translation, Sample INI, m_weather.h
-
-Version 0.3.0.1 (Beta) 2004/03/23
- - Do not update contacts that are hidden from list (see it as "disabled" contacts)
- - Give error message box when selecting more info and weather map before setting the URL
- - Bug fix: Find and search contacts (no result found + crashes)
- - Bug fix: Issue with StartupStatus, now weather will update at least once on startup
- regardless of what's the setting there.
- - Bug fix: Visibility unit conversion
- - Bug fix: Weather contacts appear offline if langpack is installed
- - Bug fix: Some spelling error
- - Bug fix: Feel-like temperature can't be displayed by mToolTip
- - Bug fix: WU: Find and search for station that doesn't have current condition
- - Updated: All 4 INI files, Read Me, Translation
-
-Version 0.3.0.0 (Beta) 2004/03/22
- - Combine the weather dll's into one
- - Using external file for getting update (in plugins\weather directory)
- - Added user detail page for weather contacts
- - New and improved option pages
- - Proxy support (now uses netlib)
- - Unit conversion for pressure, visibility, and wind
- - Optimization in the edit setting dialog - Allow multiple window
- - Changes in brief info dialog - able to open multiple brief info
- - Reduce the number of DB access for getting settings
- - Add more variables such as feel-like temperature, pressure
- - Add menu item for enable/disable popup
- - Support weather icon determination for site in other languages using langpack
- - Support for plugin uninstaller
- - Optimization in weather update - now update using a queue and minimize DB access
- - Optimizaiton in add/search - now don't do unnecessary searches
- - Other code optimization and reduce file size
- - Reload weather update data file from the main menu
- - Some other major and minor UI change
- - Remove some useless features
- - Bug fix: temperature conversion (thanks to sirius)
- - Bug fix: crash on adding new station
- - Some minor changes and fixes in webpage downloading.
- - Includes documentation for INI update data file and icon selection translation.
- - Major changes in translation strings.
- - Some update in the readme documentation.
- - Included in this version:
- Weather Channel, Weather Underground (both US and International), Yahoo Weather.
-
-Version 0.2.5.2
-
-Version 0.2.5.1 2003/07/19
- - Minor bug fixes
-
-Version 0.2.5.0 2003/06/09
- - New feature: short weather information as status message and/or note.
- - New option: display weather options inside plugin options.
- - Create a seperate page for text and display options.
- - Other minor changes and bug fixes
-
-Version 0.2.4.5 2003/06/12
- - Bug fix: Backup/restore protocol icon (including rebuild icon) if status is hidden.
- - Bug fix: Popup only condition changes.
-
-Version 0.2.4.4 2003/06/08
- - Fixed typo in option
- - Weather underground: Retrieve data for high/low temperature even if
- current info is unavailable
- - Minor code change.
-
-Version 0.2.4.3 2003/06/07
- - Fix weather underground searching station
-
-Version 0.2.4.2 2003/06/06
- - Fixed weather underground station name display problem.
- - Changes to make compatible with earlier version in case of downgrading
- - Reorganize language pack strings.
-
-Version 0.2.4.1 (Beta) 2003/05/28
- - New preview using the selected timeout value.
- - Modified timeout warning message box.
-
-Version 0.2.4.0 (Beta) 2003/05/28
- - Added advanced option page
- - New option: Popup timeout
- - Restore the hide icons in status / task bar option
- - Use old weather information if new data is unavailable
- - Add the debug setting in advanced option page
- - Major internal / weather update / DB settings change
-
-Version 0.2.3.13 2003/05/30
- - Fixed searching weather underground station
- - Few minor changes
-
-Version 0.2.3.12 2003/05/28
-
-Version 0.2.3.11 (Beta) 2003/05/27
- - Fixed Weather Channel for the FOURTH time
-
-Version 0.2.3.10 2003/05/27
- - Third fix for Weather Channel.
- - Note: If v0.2.3.9 works, there is no need to upgrade
-
-Version 0.2.3.9 2003/05/26
- - Fixed download from Weather Channel
- - Few minor changes and updates
-
-Version 0.2.3.8 2003/05/25
- - Removed some unnecessary popup that causes crash and/or confusion
- - Minor code change in weather update.
-
-Version 0.2.3.7 (Beta) 2003/05/08
- - Now compile using latest Miranda source code
-
-Version 0.2.3.6 (Beta) 2003/04/15
-
-Version 0.2.3.5 2003/03/16
- - Fix in "Do not display weather condition as protocol status" option
- - Fix in maximun temperature for weather channel plugin.
-
-Version 0.2.3.4 2003/03/16
-
-Version 0.2.3.3 (Beta) 2003/03/10
- - Remove features that are incompatiable with latest version of Miranda
- - Bug fix on retrieving weather (again!)
-
-Version 0.2.3.2 (Beta) 2003/02/28
- - Few minor bug fixes
-
-Version 0.2.3.1 (Beta) 2003/02/17
- - Bug fix in retrieving high and low temperature.
- - Other minor fixes.
-
-Version 0.2.3.0 2003/02/05
- - New option: Do not display default condition as protocol status
- - Support Miranda Installer
- - Other minor code changes.
-
-Version 0.2.2.11 2003/01/31
- - Fixed some weather info parsing problems
-
-Version 0.2.2.10 2003/01/26
- - Fix some minor errors in weather update
-
-Version 0.2.2.9 2003/01/25
- - Add some warning messages.
-
-Version 0.2.2.8 (Beta) 2003/01/25
- - Fixed on popup display.
- - More infinite loop prevention.
-
-Version 0.2.2.7 2003/01/24
- - Forget to update version number in last release
-
-Version 0.2.2.6 2003/01/24
- - Popup only when condition changes now work properly.
- - Minor bug fix in logging
- - Smaller file size.
- - Other minor changes.
-
-Version 0.2.2.5 (Beta) 2003/01/23
- - Fixed weatherch.dll for new website format.
-
-Version 0.2.2.4 (Beta) 2003/01/18
- - Minor code change
-
-Version 0.2.2.3 2003/01/16
-
-Version 0.2.2.2 2003/01/15
- - Show popup action selection when menu is opened.
- - Bug fix: Modified weather station now can update normally.
-
-Version 0.2.2.1 (Beta) 2003/01/12
- - Bug fix: Opening menu when click on PopUp.
- - Added link in main menu to the homepage of weathe source.
- - New protocol icon.
-
-Version 0.2.2.0 (Beta) 2003/01/11
- - Move pop-up related options to popup option page.
- - New option: Set popup title
- - New option: Specify command for popups when mouse is clicked.
- - Added variable information popup.
- - Some UI changes.
- - Added version info.
- - Some translation string added / changed.
-
-Version 0.2.1.6 (Beta) 2003/01/09
- - Shorten code in some functions.
-
-Version 0.2.1.5 2003/01/08
- - Updated weatherch.dll for data retrieval.
- - Bug fix: Searching new weather station.
- - Bug fix: Loading default settings.
- - Few other minor changes.
-
-Version 0.2.1.3 (Beta) 2003/01/07
- - Minor bug fix.
-
-Version 0.2.1.2 2003/01/04
- - New option: Overwrite File upon Update.
- - Update in translation doc.
-
-Version 0.2.1.1 2003/01/03
- - Better support for multiline popups.
- - Minor change in codes and readme document.
-
-Version 0.2.1.0 2002/12/31
- - New option: Override default URL settings for each contact
- - Display text are no longer case sensitive.
- - Prevent opening two dialogs at the same time.
-
-Version 0.2.0.5 2002/12/18
- - Few minor changes and bug fixes
-
-Version 0.2.0.4 (Beta) 2002/12/15
- - Bug fix: changing status and popups.
- - Minor change in weather update.
-
-Version 0.2.0.3 (Beta) 2002/12/14
- - Bug fix: disable popup st startup.
- - Other minor changes.
-
-Version 0.2.0.2 (Beta) 2002/12/12
- - Try to make string compatible between each weather source (not tested)
- - Bug fix: crash when not connected (not tested)
- - New weather condition in translation string.
- - Various other minor bug fixes and changes.
-
-Version 0.2.0.1 (Beta) 2002/12/11
- - Fix in updating weather information in wunderground.dll
- - Various other minor bug fixes and changes.
-
-Version 0.2.0.0 (Beta) 2002/12/10
- - Completed wunderground.dll
- - Bug fix: Update all weather.
- - Bug fix: Weather update in weatherch.dll
- - Various other bug fixes and improvements.
-
-Version 0.1.9.5 (Preview) 2002/12/10
- - Completed weatherch.dll
- - Weather Underground (wunderground.dll) included - not complete yet.
- - Bug fix: Default weather station and weather status.
- - Bug fix: Crash when edit weather station.
- - Bug fix: Crash when adding new weather station.
- - Bug fix: Searching for weather station when no contact found.
- - Various other changes and bug fixes.
-
-Version 0.1.9.0 (Preview) 2002/12/09
- - Split code into different files for easier modification.
- - Support for multiple weather protocols (required minimal change + new build)
- - Minor changes and bug fixes
-
-Version 0.1.5.2 2002/12/09
- - Bug fix: crash when "Show multiple icons only when statuses differ" enabled
- - Bug fix: some options not saved properly.
- - Bug fix: bug fix when adding the first station.
-
-Version 0.1.5.1 2002/12/07
- - Bug fix in showing notifying messages.
-
-Version 0.1.5.0 2002/12/06
- - Error detections.
- - New option: Show errors on popups.
- - Display default station weather condition as status icon.
- - Enable / Disable weather update through status.
- - New weather conditions.
- - Slight change in adding new weather station.
- - Fixed tab orders.
-
-Version 0.1.4.9 2002/12/06
-
-Version 0.1.2.0 2002/11/29
- - Add links to weather maps.
- - Add option to change Popup text, Log text, and URL links.
- - New variables: %d, %s, %S
- - New option: open webpage in new window.
- - Internal code changes and bug fixes.
-
-Version 0.1.1.1 2002/11/25
- - Bug fix: Translations
- - Minor code change and translation updates.
-
-Version 0.1.1.0 2002/11/24
- - Brief Information template now translable.
- - Add set to default button for Brief Information display.
- - UI change in Brief Information dialog.
- - Add some control over looping.
- - Set default weather station (currently has no use, but it maybe useful later or by
- other plugins)
- - Bug fix: Searching for station using city names.
- - Bug fix: Assigning icon to weather conditions.
- - Fixed tab order.
- - Other minor UI and code changes (hope this will fix some bugs).
-
-Version 0.1.0.0 2002/11/23
- - Now add weather station via Find/Add Contact dialog.
- - Able to search for station using city name.
- - Customize string for showing brief information.
- - New option: Log weather station in history.
- - New option: Disable popup for specific weather station.
- - Bug fix: Update after editing weather station.
- - Bug fix: Now correctly update using the new webpage format.
- - Updated translation string (both dll and weather condition).
- - Updated debug output method.
- - Smaller file size.
- - Re-organized readme and language files.
- - Various other minor bug fixes and improvement.
-
-Version 0.0.8.5 2002/11/22
- - Bug fix: Hiding icon in task bar.
- - New weather condition added (both dll and langpack).
-
-Version 0.0.8.4 2002/11/22
- - Bug fix: Update issues.
- - Updated translation string.
-
-Version 0.0.8.3 2002/11/21
- - Interface change in option screen.
- - Prevent displaying invalid data.
- - Minor code change for update weather condition.
- - Added missing translation string.
-
-Version 0.0.8.2 2002/11/20
- - Bug fix: Translation of weather condition on contact list
- - Bug fix: Temperature conversion.
- - Minor change in option screens and edit setting screen.
-
-Version 0.0.8.1 2002/11/19
- - Bug fix: Fixed temperature display.
- - Fixed tab orders.
-
-Version 0.0.8.0 (Beta) 2002/11/19
- - Retrieve high and low temperature forecast for the current day.
- - Search and display temperature from alternative source when it is unknown.
- (For the people who have N/A display beside their city, this ver should work now)
- - More customizable contact list name display.
- - Bug fix: C and F conversion when temperature < 0 degree C.
- - Bug fix: Some update problems.
- - Language pack updated: more weather conditions.
-
-Version 0.0.7.5 (Beta) 2002/11/18
- - Right click -> Update Weather will no longer freeze Miranda.
- - New option: Disable popup if condition doesn't change.
- - Bug fix: prevent manual update when auto-update is in progress.
- - Added missing translation string.
-
-Version 0.0.7.0 (Beta) 2002/11/17
- - Updating weather will no longer freeze up miranda.
- - Add option to disable popup.
- - Bug fix: Now saves the degree sign in option.
- - Bug fix: Logging weather condition and view log command.
- - Bug fix: Update weather condition after modifying weather station.
- - Added missing translation string.
- - Various other improvements.
-
-Version 0.0.6.1 (Beta) 2002/11/16
- - Bug fix: Update after modifying weather station.
- - Bug fix: No cache (slower but more accurate info).
-
-Version 0.0.6.0 (Beta) 2002/11/16
- - The plugin has it's own popup (not using NewStatusNotify's anymore)
- - Add option to hide icon in status bar and status menu (expreimental release).
- - Various minor changes.
-
-Version 0.0.5.1 (Alpha) 2002/11/16
-
-Version 0.0.5.0 (Alpha) 2002/11/15
-
-Version 0.0.4.3 (Beta) 2002/11/15
- - Added option to disable main menu item.
- - Various minor improvements.
-
-Version 0.0.4.2 (Beta) 2002/11/15
- - Bug fix: translation strings.
- - Bug fix: no longer open miranda directory when no log is found.
-
-Version 0.0.4.1 (Beta) 2002/11/15
- - Bug fix on retrieving weather information.
- - Removed debug string that was accidentally built in the last release. (see above)
-
-Version 0.0.4.0 (Beta) 2002/11/14
- - Retrieve weather information no longer require temp files.
- - Able to modify weather station settings.
- - Add link to log file in contact menu.
- - Add an option for degree sign (I can't think of a better way to do this).
- - Relocate main menu item.
- - Bug fix: DB: Attempt to get wrong type of value, word.
- - Various other minor bug fixes.
-
-Version 0.0.3.7 (Beta) 2002/11/14
- - Bug fix: degree signs (sorry for the copy-and-paste error).
- - Move the temporary file to miranda directory.
-
-Version 0.0.3.6 (Beta) 2002/11/14
- - Bug fix: degree signs (changable using language pack)
- - Bug fix: DB: Attempt to get wrong type of value, word.
- - More weather condition are now able to display with correct icon.
-
-Version 0.0.3.5 (Beta) 2002/11/13
- - Initial public beta release.
-
-Version 0.0.3.1 (Beta) 2002/11/13
-
-Version 0.0.3.0 (Beta) 2002/11/12
- - Disable auto update option.
- - Logging weather condition.
- - New option for displaying weather conditions on contact list.
- - Bug fix: some tarnslation strings.
- - Bug fix: switching between English and metric units.
- - Bug fix: time of update.
-
-Version 0.0.2.1 (Preview) 2002/11/12
- - Bug fix: F to C conversion.
- - Bug fix: Display complete forcast page in correct unit system.
-
-Version 0.0.2.0 (Preview) 2002/11/12
- - Display temperature on contact list.
- - Translable strings.
- - Display brief weather information as message box.
- - Faster information download.
- - Various other fixes.
-
-Version 0.0.1.2 (Pre-Alpha) 2002/11/12
-
-Version 0.0.1.1 (Pre-Alpha) 2002/11/11
- - Faster and more reliable download.
- - Various bug fixes.
-
-Version 0.0.1.0 (Pre-Alpha) 2002/11/11
- - Retrieve temperature and update time.
-
-Version 0.0.0.3 (Pre-Alpha) 2002/11/11
- - Bug fix in weather condition and icons.
- - Various other bug fixes.
-
-Version 0.0.0.2 (Pre-Alpha) 2002/11/11
- - Set the name for city, retrieve weather condition.
-
-Version 0.0.0.1 (Pre-Alpha) 2002/11/10
- - Initial build
diff --git a/protocols/Weather/docs/license.txt b/protocols/Weather/docs/license.txt
deleted file mode 100644
index 5b6e7c66c2..0000000000
--- a/protocols/Weather/docs/license.txt
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/protocols/Weather/docs/readme.html b/protocols/Weather/docs/readme.html
deleted file mode 100644
index 0f3e8d80c8..0000000000
--- a/protocols/Weather/docs/readme.html
+++ /dev/null
@@ -1,230 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
- <head>
- <title>Read Me for Weather Protocol</title>
- <script language="javascript" type="text/javascript">
-function link(num){document.location="http://addons.miranda-im.org/details.php?action=viewfile&id="+num;}
- </script>
- </head>
- <body>
- <h2>Read Me for Weather Protocol</h2>
- <hr/>
- <pre>
-<a name="top"><font color="red">
-<b>*** IMPORTANT NOTICE ***</b>
-Be cautious when choosing the "special status" selection for selecting the status
-assign to contact whose current condition is unavailable. This feature is not
-officially support by Miranda and may cause a lot of plugins to crash. Be sure to
-backup your profile before you try this feature.</font>
-
-</a>
-</pre>
-<hr/>
-<pre>
-
-<b><u>File Content</u></b>
-
-<a href="#fea">Features</a>
-<a href="#fi">Files Included</a>
-<a href="#sr">System Requirement</a>
-<a href="#ins">Installation</a>
-<a href="#faq">Frequently Asked Questions</a>
-<a href="#lic">License</a>
-
-</pre>
-<hr/>
-<pre>
-
-<a name="fea"><b><u>Features</u></b>
-
- - Retrieve weather information and display them on your Miranda contact list.
- - Provide a contact information page for viewing the current weather conditions.
- - Display PopUp when information is retrieved.
- - Log weather conditions to a file or in history.
- - Quick links for viewing complete forecast and weather maps.
-
-
-</a><a name="fi"><b><u>Files Included</u></b>
-
- - plugins\weather.dll
- The core to the weather plugin. Required component
- - </a><a href="langpack_defweather.txt">langpack_defweather.txt</a> (stored in the documentation folder by default)
- Langpack for weather icon assignment, containing documentation for how to use
- - <a href="weather-readme.html">plugins\weather-doc\weather-readme.html</a>
- Documentation and FAQ for Weather Protocol (this file).
- - <a href="sample_ini.ini">plugins\weather-doc\sample_ini.ini</a>
- Documentation of the format of the weather INI file.
- - <a href="weather-translation.txt">plugins\weather-doc\weather-translation.txt</a>
- A file that contains a translation of hopefully all string used in Weather Protocol.
-
-
-<a name="sr"><b><u>System Requirement</u></b>
-
- - </a><a href=
-"http://www.miranda-im.org">Miranda IM</a> (v0.7.3.0 or later)
- - <a href="http://addons.miranda-im.org/index.php?action=display&amp;id=78">Weather INI file</a>
- - Weather icons (Optional)
- Numerous choices available in <a href=
-"http://addons.miranda-im.org/index.php?action=display&amp;id=35">icon downloads</a>.
- - <a href=
-"javascript:link(2759)">YAPP plugin</a> by sje or <a href=
-"javascript:link(3400)">PopUp Plus plugin</a> by nullbie (Optional)
-
-
-<a name="ins"><b><u>Installation</u></b>
- For installation of weather protocol, it is recommended for installing it using Miranda
- Installer. For manual installation, please following these steps:
-
- 1. Copy weather.dll into plugins directory.
- 2. Get the ini's from file listing and place them into plugin\weather directory.
- 3. If you want external file for status icon selection, copy the content of
- langpack_defweather.txt into your language pack and (optionally) enable
- "Disable internal icon selection" from the option page.
- 4. In icon option, customize the weather icon or use the default one in the dll
-
- IMPORTANT UPGRADE NOTICE
- Due to the changes made in this version, Weather 0.3.x is not compatible with older
- releases (v0.2.x). Therefore, you should delete your weather contacts before
- upgrading to this new version.
-
-
-</a><a name="faq"><b><u>Frequently Asked Question</u></b>
-
-<i><u>Setting Up Weather Protocol</u></i>
-For installation, follow the steps describe in the </a><a href=
-"#ins">installation</a> section of the readme.
-
-<b>Q1-1. Weather Protocol does not do anything after I installed it, and it
- cannot go online.</b>
-A. You need to add a new station before you can go online.
-
-<b>Q1-2. How do I add new stations?</b>
-A. Use the find/add dialog box. You can either search for station ID (see the readme
- for the ini file to see how it can be obtained) or search by city name by entering
- the name in either one of the Nickname, Firstname, or Lastname field.
-
-<b>Q1-3. I can't find my station! Any help?</b>
-A. Make sure you have installed the plugin and ini file correctly. At least one INI
- file must exist in the plugins\weather directory in order for the plugin to funciton
- properly. For more information, click <a href=
-"#ins">here</a>.
-
-<b>Q1-4. I have installed the plugin properly, and it still doesn't work. I have
- noticed that there is no traffic generated by the plugin.</b>
-A. Check you proxy setting, some proxy does not work properly under Miranda IM 0.3.3.0.
- If your proxy is having problem connecting, you need to upgrade to Miranda IM 0.3.3.1
- or try the <a href="http://www.miranda-im.org/development/">nightly builds</a>
- (Note: They are experimental builds!)
- Also, if you are using <a href="javascript:link(844)">traffic counter</a> plugin,
- please make sure that you are using the latest version. The old version stops Weather
- and some other plugin from working.
-
-<i><u>INI and Development Related Questions</u></i>
-
-<b>Q2-1. What are those INI files for?</b>
-A. The INI files contain information for downloading and parsing weather information
- from a particular weather site. At least one INI file must exist in order for the
- plugin to work. For a list of available INI's, click <a href="#top">here</a>.
-
-<b>Q2-2. Can I install or modify the INI files without restarting Miranda?</b>
-A. Yes, choose: M (main menu) -&gt; Weather -&gt; Reload Weather Data
-
-<b>Q2-3. I want to retrieve weather information from a different source than those
- that are currently available. How can this be done?</b>
-A. You can write your own INI file. For more information, click <a href="sample_ini.ini">here</a>.
-
-<b>Q2-4. I wrote/downloaded an ini file that retrieve weather condition in a
- language that weather protocol doesn't seems to reconize and always
- display N/A. What should I do?</b>
-A. You can use translation string for assigning icons. For more information, click <a href="langpack_defweather.txt">here</a>.
-
-<b>Q2-5. How does weather assign status icons for each status?</b>
-A. Online = Sunny
- Away = Partly Cloudy
- NA = Cloudy
- Occupied = Rain
- DND = Rain Shower
- Free for Chat = Snow / Wintery Conditions
- Invisible = Lightning / Thunderstorm
- On the Phone = Snow Shower
- Out to Lunch = Fog / Haze
- Offline = No Data Available
-
-<u><i>Obtaining Weather Data</i></u>
-
-<b>Q3-1. Does weather protocol retreve weather forecasts?</b>
-A. Support of this feature depend on the ini file you use. If it is supported, the most
- likely variable you use for it is %[Forecast Day #] or %[FD#] where # is the day you
- want the forecast for. See the readme supplied in the INI file package for more
- information.
-
-<b>Q3-2. How long should the time between update be?</b>
-A. This depend on the update interval on the website. Generally, this field should set
- to a value between 10 to 30 minutes. If the value is too small, a lot of traffics
- will be generated by the protocol.
-
-<b>Q3-3. How can I temporary disable weather procotol?</b>
-A. Switch the weather status to OFFLINE, but this will not work if you have "Do not
- display weather condition as protocol status" option enabled. To enable the
- protocol again, switch it to a status other than OFFLINE. Automatic update of
- weather condition can be disabled through menu and option page.
-
-<b>Q3-4. Why are the name of some weather contacts italic on my contact?</b>
-A. There are weather alerts issued for those cities. To see the alert title, use the
- %[Alert] variable. You can disable this function in option page.
-
-<b>Q3-5. There are some status that the weather plugin doesn't seems to
- reconize and always shows as N/A on the contact list. What can I do?</b>
-A. If the source of weather info is in a language other than English, please check the
- INI package for instruction of how to install language pack. If the source is in
- English, notify me.
-
-<u><i>Customizing the Weather Protocol</i></u>
-
-<b>Q4-1. Can I hide Weather from status bar and protocol menu?</b>
-A. Go to Options-&gt;Plugins-&gt;Weather, enable "Hide Weather in status bar and status menu".
-
-<b>Q4-2. I can't find Weather in the icon option drop-down list. How can I change
- weather icons?</b>
-A. Weather icon cannot be changed if "Hide Weather in status bar and status menu" is
- enabled. To change icons, disable the option (see Q4-1), make your change, then re-
- enable it.
-
-<b>Q4-3. I can't find the options for changing display text.</b>
-A. Go to Options-&gt;Plugins-&gt;Weather, then click on the icon beside "Change display texts"
-
-<b>Q4-4. How can I change the display name of my city?</b>
-A. Right-click on the city and select "Edit Settings". Change the field "City name"
- to the new display name.
-
-<b>Q4-5. How can I change the default station?</b>
-A. Use the Edit Settings dialog (See A4-4). Note that only 1 station can be default.
-
-<b>Q4-6. What is the %[..] variable for?</b>
-A. They are the custom variables. Replace the ".." with a setting name that can be
- found in \Weather in the database. For more information about the availability of
- the settings, use <a href=
-"javascript:link(2957)">Database Editor</a> or refer to the readme of the ini file.
-
-<b>Q4-7. What are the "Extra Text" for?</b>
-A. The field has no use internally. However, it can be useful for some other plugin
- to obtain a weather information string that is already parsed.
-
-<b>Q4-8. I want weather protocol to have the same status as the other protocols.
- Is such option available?</b>
-A.
-Disable the option "Use weather condition as protocol status", then you will be
- able to change the status freely.
-
-<b>Q4-9. How do I create avatars for each weather condition?</b>
-A. Put the following files into the Miranda\Plugins\Weather folder:
- Light.png, Fog.png, SShower.png, Snow.png, RShower.png, Rain.png
- PCloudy.png, Cloudy.png, Sunny.png, NA.png
-
-
-<a name="lic">License
-
-This plugin is released under </a><a href="http://www.gnu.org/licenses/gpl.txt">GPL</a>.
-</pre>
- </body>
-</html>
diff --git a/protocols/Weather/docs/sample_ini.ini b/protocols/Weather/docs/sample_ini.ini
deleted file mode 100644
index 9a045e1a3c..0000000000
--- a/protocols/Weather/docs/sample_ini.ini
+++ /dev/null
@@ -1,428 +0,0 @@
-[Weather 0.3.x Update Data 1.5]
-
-; This file contains the information required for the weather protocol to obtain update.
-; For the plugin to function properly, at least one of these file must be present.
-; The proper location of these files is: plugins\weather
-
-; Note that for the entire file, DO NOT put spaces before or after the "=". The groups
-; and setting names (for example, [Header] and Name) are not case sensitive; however,
-; the values set for each settings ARE case sensitive.
-
-; Also note that the first line of this file must be either one of the following:
-; [Weather 0.3.x Update Data] (min. req. v0.3.0.0)
-; [Weather 0.3.x Update Data 1.1] (min. req. v0.3.1.8)
-; [Weather 0.3.x Update Data 1.1a] (min. req. v0.3.2.8)
-; [Weather 0.3.x Update Data 1.2] (min. req. v0.3.5.0)
-; [Weather 0.3.x Update Data 1.3] (min. req. v0.3.8.0)
-; [Weather 0.3.x Update Data 1.4] (min. req. v0.3.8.12)
-; [Weather 0.3.x Update Data 1.5] (min. req. v0.4.0.2)
-
-; Minimun version for not crashing Miranda (Set to this version to prevent the ini from
-; loading in an old version of weather plugin and crash Miranda)
-; 1.1a String longer than 256 characters.
-; 1.1 More than 16 data items in the ini
-; Not using [/...] footer at the end of the list
-; 1.0 All other features
-
-; Minimun version for using the new features (Set to this version to prevent invalid data
-; for user with old version of weather plugin. However, the other features still works)
-; 1.5 Using "UserAgent="
-; 1.4 Using "Cookie="
-; 1.3 Using "Update Url2=" & "Update Url3="
-; 1.2 Using the operation "Break Data="
-; Using the setting "Hidden=" for each data item
-; Assign weather icons from ini
-; 1.1a Support for the units: Day, Month, %, Deg, Cond
-; 1.1 Using the operation "Set Data="
-; 1.0 All other features
-
-; Revision history:
-; 1.5 (Updated in v0.4.0.2)
-; New "UserAgent="
-; 1.4 (Updated in v0.3.8.12)
-; New "Cookie="
-; 1.3 (Updated in v0.3.8.0)
-; New "Update Url2=" & "Update Url3="
-; 1.2 (Updated in v0.3.5.0; minimun req. v0.3.5.0)
-; New operation "Break Data="
-; New setting "Hidden=" that hide the data item from the mor data list
-; Weather icon assignment from the ini
-; 1.1a (Updated in v0.3.4.0; minimun req. v0.3.2.8)
-; Support for Day, Month units
-; 1.1a (Updated in v0.3.3.0; minimun req. v0.3.2.8)
-; Support the %, Deg, Cond units
-; 1.1a (For v0.3.2.8; minimun req. v0.3.2.8)
-; Now the string can be unlimited long (at least when it's within 4096 characters)
-; 1.1 (For v0.3.2.0; minimun req. v0.3.1.8)
-; No more need to use [/...] headers (now it just like a normal INI file)
-; Support more weather data, and the number of data is no longer limited to 16
-; New operation "Set Data=" that assign data items without download the info
-; 1.0 (For v0.3.0.0; minimun req. v0.3.0.0)
-; Initial version.
-
-; ======================================================================================
-
-; INI Headers
-
-[Header]
-; The name field contains the string that will appear to the user. Please be unique.
-; (for example, "Yahoo Weather")
-Name=
-
-; The internal name is the string that will be used to set the weather ID, and are used
-; internally to obtain the weather update information. This string should be short and
-; unique.
-; (for example, "yw" for "Yahoo Weather")
-Internal Name=
-
-; The following 3 fields are used in the plugin for INI information only, but it also
-; gives user some information about the file.
-Description=
-Author=
-Version=
-
-; For the following three default fields, %s is used for station ID (the one with the
-; internal name taken away, for example, CAXX0001)
-[Default]
-; The default URL for getting more weather information from contact menu or brief info
-; dialog. This setting is the default one assigned to the weather contact when it is
-; added, but can be changed by user in the Edit Settings dialog.
-Default URL=
-
-; The default URL for getting weather map from contact menu. Same as above.
-Default Map=
-
-; The URL for retrieving weather updates.
-Update URL=
-Update URL2=
-Update URL3=
-Update URL4=
-
-; Set cookie(s) when retrieving weather updates.
-Cookie=
-
-; Set user agent for http requests.
-UserAgent=
-
-; ======================================================================================
-
-; Weather Data Fields
-
-; The following section list the data fields that are used to assign the data to be stored
-; in the database. These fields should be placed in the order of appearance in the
-; download information. For each item searched, the string before the item are discarded
-; so if the order is wrong, no information can be obtained from the latter item.
-
-; Format (not all settings are necessary):
-; [Field Name]
-; Start=
-; End=
-; Set Data=
-; Break Data=
-; Source=
-; Unit=
-; Hidden=
-
-; Default Fields:
-; [Condition] Current condition, to assign condition icon
-; [Update] For display of the update time of the weather data
-; [Temperature] Current temperature
-; [Feel] Feel-like temperature
-; [High] Today's high
-; [Low] Today's low
-; [Sunrise] Sun rise time
-; [Sunset] Sun set time
-; [Wind Direction] Wind direction (not including speed)
-; Be careful to consider the no wind situation (ie. calm)
-; [Wind Speed] The speed of the wind
-; [Pressure] Barometer pressure
-; [Visibility] Visibility, if the value is 0 or non-numerical value, then unit conversion
-; for this will not run and original string is retained
-; [Humidity] Humidity, without a % sign.
-
-; Special Fields:
-; [Alert]
-; Special item for weather alert.
-; If the data retrieved for this field is non-empty, then a special alert popup will
-; display and the city on the contact list will be in a special state (using the
-; setting for "Contact to whom you have a different visibility".
-; This will be reset to normal once the alert field becomes empty.
-; [Ignore]
-; Special item for the plugin to ignore what the value it gets and all errors when
-; getting it. The value obtained for this field will not be written into the
-; database, and no popup and notification will be raised. This is useful to skip
-; some specific text or end the download script. Multiple placement of this field
-; is allowed.
-; Note: For prevent the popup of error message, v0.3.2.11 is required
-
-; Custom Fields:
-; [%name%]
-; Where %name% can be any string you want.
-
-
-; Settings:
-; Settings for obtaining data: "Start=", "End=", "Set Data=", "Break Data=", "Source="
-
-; There are 3 ways for the plugin to obtain the information string:
-; 1. Parse directly from the webpage by specifying start and end strings. Note that these
-; strings are case sensitive.
-
-; When parsing the information, the following items are removed:
-; HTML tags example: <b> </b>
-; symbols example: &nbsp;
-; linefeed and tabs
-; multiple spaces, spaces at the beginning and at the end of the string
-; Also, if the start field is blank, that means the information starts immediately
-; after the string from the last "End=" field. If the end field is blank, that means
-; the information ends at the first space the plugin encounters (even if it is inside
-; a HTML tag).
-
-; An example, for parsing
-; "<sth before>Partly <!-- something in middle -->&nbsp; Cloudy<sth after>
-; The code to give "Partly Cloudy" (without quotation):
-; [Condition]
-; Start=<sth before>
-; End=<sth after>
-
-; 2. Concatenate strings, using "Set Data=", can merge various string together by placing
-; them around the operator " & " (without the quotation mark but with the 2 spaces).
-; For the variable strings (ie. the data item retrieved previously), use []
-; For constant strings, use ""
-
-; For example, merging two condition strings "Condition 1" and "Condition 2":
-; [Condition]
-; Set Data=[Condition 1] & " and " & [Condition 2]
-
-; Another example, copy the content of "Condition
-; [Copy of Condition]
-; Set Data=[Condition]
-
-; 3. Break a string into 2, using "Break Data=", by specifying the string in between the
-; two substrings. The first half will store into the name specify by the header, and
-; the second half will be specified by "End="
-
-; An example, to reverse what we did in Example 2 (the two condition strings):
-; [Condition 1]
-; Break Data= and
-; Source=Condition
-; End=Condition 2
-
-; Other Settings:
-; Unit=
-; Specify the unit for the data, for use in unit conversion. The conversion to use
-; depends on the value assigned.
-; For temperature conversion: C, F, K
-; For speed conversion: km/h, m/s, mph, knots
-; For pressure conversion: hPa, kPa, mb, torr, mm, in
-; For distance conversion: km, miles
-; For adding a percent sign at the end: %
-; For adding a degree sign at the end: Deg
-; Convert condition str to proper case: Cond
-; For weekday string length: Day
-; For month string length: Month
-
-; Hidden=
-; Acceptable values: true, false
-; Using this on any field will prevent it from being displayed in the "More Info"
-; list, but its value will still be stored in the database.
-
-; Url=
-; Acceptable values: 1, 2, 3
-; Specifies the url on where to look for data item
-; If parameter is not specified item is searched on all urls, the last found will be used
-
-; Here's an example:
-[Condition]
-Start=
-End=
-Unit=Cond
-
-[Temperature]
-Start=
-End=
-Unit=C
-
-[Humidity TEMP]
-Start=
-End=
-Hidden=true
-
-[Humidity]
-Set Data=[Humidity TEMP] & "%"
-
-; - or -
-
-[Humidity]
-Start=
-End=
-Unit=%
-
-
-; ======================================================================================
-
-; The setting for find and add contacts.
-
-; ID search is used when the user type in the ID in the "Station ID" field and pressed
-; "Search"
-[ID Search]
-
-; This can be "true" or "false" (without quotation, not case sensitive)
-; If this is set to "false", all the following strings are ignored and the ID are NOT
-; going to search for this weather service.
-; If this field is set to FALSE, no matter what the user type for station ID, the
-; plugin will always return a result with station name empty and ID the same as what
-; the user has typed.
-Available=
-
-; The URL for ID search. Note that %s is used for placing the ID.
-Search URL=
-
-; The string appeared in the downloaded information when there is no match
-; (ie. "Document not found")
-; If this string is found while searching, the search process quit and return no result.
-Not Found Str=
-
-; Similar to weather information retrival above. This is the string preceeding the
-; station name obtained from searching. Note that the parsing is the same as above, and
-; spaces can be used.
-Name Start=
-
-; This is what's after the station name.
-Name End=
-
-; END ID SEARCH
-
-; Name search is used when the user type in any of the name field (Nick, First, Last) and
-; click on the "search" button.
-[Name Search]
-
-; This can be "true" or "false" (without quotation, not case sensitive)
-; If this is set to "false", then the plugin igmore the information stated in the Single
-; fields (ie. from "Single Name Start" to "Single ID End")
-Single Result=
-
-; This can be "true" or "false" (without quotation, not case sensitive)
-; If this is set to "false", then the plugin igmore the information stated in the Multiple
-; fields (ie. from Multiple Name Start" to Multiple ID End")
-; Note that if both single and multiple are disabled, the Name search are disabled for
-; this weather service.
-Multiple Result=
-
-; The URL for doing the name search. %s will be replaced by the station name input from
-; the user.
-Search URL=
-
-; The string appeared in the downloaded information when there is no match
-; (ie. "Document not found")
-; If this string is found while searching, the search process quit and return no result.
-Not Found Str=
-
-; This field determines whether the search will return a single result or multiple result
-; If the string stated in this field is found and Single Result is enabled from above, the
-; settings for single result will be used. Otherwise, the settings in multiple result
-; will be used.
-Single Result Str=
-
-; These fields are for the single result
-
-; Determine which item is the first to appear in the download search result file
-; This field can be ID or Name (not case sensitive).
-; For example, if ID is used here, it means that station ID appears before the station
-; name in the downloaded document.
-Single First=
-
-; The start and end string for station name. Parsing using the same way as discribed
-; above for weather information.
-; Note that if both fields are empty, then whatever the user type into the search field
-; will be used for the station name.
-Single Name Start=
-Single Name End=
-
-; The start and end string for station name. Parsing using the same way as discribed
-; above for weather information.
-Single ID Start=
-Single ID End=
-
-; The multiple result is similar to the single result as described above.
-; For this search, the plugin will loop until no more Name's and ID's can be founded
-; in the downloaded file.
-Mult First=
-Mult Name Start=
-Mult Name End=
-Mult ID Start=
-Mult ID End=
-
-; END NAME SEARCH
-
-; For a workaround of URL forwarding issue:
-; If the page retrieved contains URL forward (ie. the 302 code), the download content
-; will appears as:
-; Moved/Location: <forwarded URL>
-; This might be useful for writing the start/end string settings for the single result
-; Name Search.
-; A typical use of this is:
-; Single Result Str=Moved/Location:
-; Single First=ID (this isn't really matter)
-; Single Name Start=
-; Single Name End= (this will use whatever user type in as stn name)
-; Single ID Start=/newpages/ (what's before the station ID in the URL)
-; Single ID End=.html (what's after the station ID)
-
-; ======================================================================================
-
-; INI Defined Icon Assignments (new in v1.2)
-
-; These assignment will take the highest priority (before the internal and the langpack
-; defined assignment) when matching the condition (icon) to the current condition.
-; These settings are INI specific, which means that the setting in one INI will not affect
-; the stations that are associated to another INI.
-
-; Format:
-; {icon name}={string to search}
-
-; The "icon name" is the icon to assigned with the condition string containing the string
-; specified in "string to search" is found.
-
-; Available icon names are (in order of assigning priority):
-; Lightning, Fog, Snow Shower, Snow, Rain Shower, Rain, Partly Cloudy, Cloudy, Sunny, N/A
-
-; For examples, mimicking what internal icon selection and langpack_defweather do (of
-; course, putting these in an actual INI is not needed and is waste of space and memory).
-
-[Icons]
-Sunny=Sunny
-Sunny=Clear
-Sunny=Fair
-
-Partly Cloudy=Mainly Sunny
-Partly Cloudy=Mainly Clear
-Partly Cloudy=Partly
-Partly Cloudy=Mostly
-Partly Cloudy=Clouds
-
-Cloudy=Cloudy
-Cloudy=Overcast
-
-Rain=Drizzle
-Rain=Rain
-
-Rain Shower=Rain Shower
-Rain Shower=Shower
-
-Snow=Snow
-Snow=Ice
-Snow=Freezing
-Snow=Wintery
-
-Snow Shower=Snow Shower
-Snow Shower=Flurries
-
-Ligntning=Thunder
-Ligntning=T-storm
-
-Fog=Fog
-Fog=Mist
-Fog=Smoke
-Fog=Haze
-Fog=Sand
-Fog=Dust
diff --git a/protocols/Weather/docs/weather/gismeteo_com.ini b/protocols/Weather/docs/weather/gismeteo_com.ini
deleted file mode 100644
index 2d7a4a48dc..0000000000
--- a/protocols/Weather/docs/weather/gismeteo_com.ini
+++ /dev/null
@@ -1,1254 +0,0 @@
-[Weather 0.3.x Update Data 1.5]
-
-;*********************************************************
-;
-; Прогноз для gismeteo.com.
-;
-; Поиск по названию города добавлен.
-; Можно искать по ID города, который предварительно выясняем на сайте Gismeteo.
-;
-; Перед использованием желательно удалить старые контакты
-; с погодой и найти нужные города по новой. Первый раз обновиться
-; из меню (правый клик на контакте) через "Удалить данные и обновить" .
-;
-; Чтобы все было красиво и понятно видно в миранде идем в
-; Параметры->Модули->Погода->Показывать и поле "Кратко" (остальные поля по вкусу)
-; полностью заменяем на:
-
-; Состояние погоды в %[CityName] на %u
-; ----------------------------------------------------------------
-; Условия: %c
-; Температура: %t
-; Давление: %p
-; Влажность: %m
-; Ветер: %i %w
-; Температура воды: %[TW]
-; Восход: %r, Закат: %y, Продолжительность дня: %[Day Length], Фаза Луны: %[Moon phase]
-;
-; Прогноз (Дата, Температура [Комфорт], Условия, Ветер, Давление, Влажность)
-; -------------------------------------------------------------------------------------------------------
-; %[Forecast Day 1]
-; %[Forecast Day 2]
-; %[Forecast Day 3]
-; %[Forecast Day 4]
-; %[Forecast Day 5]
-; %[Forecast Day 6]
-; %[Forecast Day 7]
-; %[Forecast Day 8]
-; %[Forecast Day 9]
-
-[Header]
-Name=GisMeteo.com
-Internal Name=gm_com
-Description=Weather information from Gismeteo.com
-Author=Dimtr
-Version=2023.05.24
-Utf8=true
-
-[Default]
-Default URL=https://www.gismeteo.com/weather-%s/
-Default Map=https://www.gismeteo.com/nowcast-%s/?utm_campaign=radar&utm_source=gismeteo&utm_medium=radar_teaser
-Update URL=https://www.gismeteo.com/weather-%s/now/
-Update URL2=https://www.gismeteo.com/weather-%s/
-Update URL3=https://www.gismeteo.com/weather-%s/10-days/
-
-;-----------------------------------------------------
-
-;[Condition]
-;Start=data-text="
-;Start="description":["
-;End="]
-;End=">
-;Unit=Cond
-;Url=2
-
-;[TempNow]
-;Start="temperatureAir":[
-;End=]
-;Url=2
-;Hidden=true
-
-;[TempWater]
-;Start="temperatureWater":[
-;End=]
-;Url=2
-;Hidden=true
-
-;[Visibility]
-;Start="visibility":[
-;End=]
-;Url=2
-
-;[Humidity]
-;Start="humidity":[
-;End=]
-;Unit=%
-;Url=2
-
-;[Pressure]
-;Start="pressure":[
-;End=]
-;Unit=mm
-;Url=2
-
-;[WS]
-;Start="windSpeed":[
-;End=]
-;Unit=m/s
-;Url=2
-;Hidden=true
-
-[Condition]
-Start=data-text="
-End="
-Unit=Cond
-Url=1
-
-[Update]
-Start=data-pattern="G:i">
-End=</div>
-Url=1
-
-[TempNow]
-Start=<span class="sign">
-End=<span class="unit
-Url=1
-Hidden=true
-
-[Temperature]
-Set Data=[TempNow] & " °C"
-
-[TempFeel]
-Start=<span class="sign">
-End=<span class="unit
-Url=1
-Hidden=true
-
-[Feel]
-Set Data=[TempFeel] & " °C"
-
-[Low]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=1
-
-[High]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=1
-
-[WS]
-Start=<div class="unit unit_wind_m_s">
-End=<div
-;Unit=m/s
-Url=1
-Hidden=true
-
-[Wind speed]
-Set Data=[WS] & " " & "m/s"
-
-;[Visibility]
-;Set Data=[Condition]
-;[/Visibility]
-
-[Wind direction]
-Start=</div><div>
-End=</div>
-Url=1
-
-[Pressure]
-Start=<div class="unit unit_pressure_mm_hg_atm">
-End=<div
-Unit=mm
-Url=1
-
-[Humidity]
-Start=<div class="item-value">
-End=</div>
-Unit=%
-Url=1
-
-[TempWater]
-Start=<span class="sign">
-End=<span class="unit
-Url=1
-Hidden=true
-
-[TW]
-Set Data=[TempWater] & " °C"
-
-[Day Length]
-Start=<div class="astro-progress">
-End=</div>
-Url=2
-
-[Sunrise]
-Start=<div>
-End=</div>
-Url=2
-
-[Sunset]
-Start=<div>
-End=</div>
-Url=2
-
-[Moon phase]
-Start=<div class="astro-progress">
-End=</div>
-Url=2
-
-[Moonrise]
-Start=<div>
-End=</div>
-Url=2
-
-[Moonset]
-Start=<div>
-End=</div>
-Url=2
-
-; DATE: T - time, D - day, M - month, W - weekday
-
-[FD0DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD0DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1DW]
-Start=/tomorrow/"><div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-;---------------//////////////////////////
-;------1--------//////////////////////////
-;---------------//////////////////////////
-;---------1-234--------------
-
-[FD0D]
-Set Data=[FD0DW] & " " & [FD0DDM]
-Hidden=true
-
-[FD1D]
-Set Data=[FD1DW] & " " & [FD1DDM]
-Hidden=true
-
-[FD2D]
-Set Data=[FD2DW] & " " & [FD2DDM]
-Hidden=true
-
-[FD3D]
-Set Data=[FD3DW] & " " & [FD3DDM]
-Hidden=true
-
-[FD4D]
-Set Data=[FD4DW] & " " & [FD4DDM]
-Hidden=true
-
-[FD5D]
-Set Data=[FD5DW] & " " & [FD5DDM]
-Hidden=true
-
-[FD6D]
-Set Data=[FD6DW] & " " & [FD6DDM]
-Hidden=true
-
-[FD7D]
-Set Data=[FD7DW] & " " & [FD7DDM]
-Hidden=true
-
-[FD8D]
-Set Data=[FD8DW] & " " & [FD8DDM]
-Hidden=true
-
-[FD9D]
-Set Data=[FD9DW] & " " & [FD9DDM]
-Hidden=true
-
-; CONDITION
-
-[FD0C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD1C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD2C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD3C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD4C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD5C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD6C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD7C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD8C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD9C]
-Start=data-text="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-;temperature
-
-[FD0TH]
-Start=<div class="maxt"><span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD0L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD1TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD1L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD2TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD2L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD3TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD3L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD4TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD4L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD5TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD5L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD6TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD6L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD7TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD7L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD8TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD8L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD9TH]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-[FD9L]
-Start=<span class="unit unit_temperature_c">
-End=</span>
-Unit=C
-Url=3
-Hidden=true
-
-; WIND: H - Hidden data D - direction, S - Speed
-
-[FD0WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD1WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD2WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD3WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD4WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD5WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD6WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD7WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD8WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD9WS]
-Start=<span class="wind-unit unit unit_wind_m_s">
-End=</span>
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD0WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD0W]
-Set Data=[FD0WD] & " " & [FD0WS]
-Hidden=true
-
-[FD1W]
-Set Data=[FD1WD] & " " & [FD1WS]
-Hidden=true
-
-[FD2W]
-Set Data=[FD2WD] & " " & [FD2WS]
-Hidden=true
-
-[FD3W]
-Set Data=[FD3WD] & " " & [FD3WS]
-Hidden=true
-
-[FD4W]
-Set Data=[FD4WD] & " " & [FD4WS]
-Hidden=true
-
-[FD5W]
-Set Data=[FD5WD] & " " & [FD5WS]
-Hidden=true
-
-[FD6W]
-Set Data=[FD6WD] & " " & [FD6WS]
-Hidden=true
-
-[FD7W]
-Set Data=[FD7WD] & " " & [FD7WS]
-Hidden=true
-
-[FD8W]
-Set Data=[FD8WD] & " " & [FD8WS]
-Hidden=true
-
-[FD9W]
-Set Data=[FD9WD] & " " & [FD9WS]
-Hidden=true
-
-;Precipitation
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[Prec]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Precipitation]
-Set Data=[Prec] & " " & "mm"
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD1PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD2PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD3PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD4PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD5PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD6PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD7PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD8PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD9PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-; PRESSURE
-[FD0P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD1P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD2P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD3P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD4P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD5P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD6P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD7P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD8P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-[FD9P]
-Start=<div class="maxt"><span class="unit unit_pressure_mm_hg_atm">
-End=</span>
-Unit=mm
-Url=3
-Hidden=true
-
-; Humidity
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD0H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD1H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD2H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD3H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD4H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD5H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD6H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD7H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD8H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD9H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-; UV Index
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[UV Index]
-Start=
-End=</div>
-Url=3
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD1UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD2UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD3UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD4UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD5UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD6UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD7UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD8UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD9UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-;================================================
-;====================3===========================
-;================================================
-
-[Forecast Day 0]
-Set Data=[FD0D] & ": (" & [FD0TH] & "/" & [FD0L] & ")" & ", " & [FD0C] & ", " & "Precipitation" & ": " & [Prec] & " " & "mm" & ", \n" & "Wind" & ": " & [FD0W] & ", " & "Pressure" & ": " & [FD0P] & ", " & "Humidity" & ": " & [FD0H] & ", " & "UV Index" & ": " & [UV Index]
-
-[Forecast Day 1]
-Set Data=[FD1D] & ": (" & [FD1TH] & "/" & [FD1L] & ")" & ", " & [FD1C] & ", " & "Precipitation" & ": " & [FD1PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD1W] & ", " & "Pressure" & ": " & [FD1P] & ", " & "Humidity" & ": " & [FD1H] & ", " & "UV Index" & ": " & [FD1UV]
-
-[Forecast Day 2]
-Set Data=[FD2D] & ": (" & [FD2TH] & "/" & [FD2L] & ")" & ", " & [FD2C] & ", " & "Precipitation" & ": " & [FD2PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD2W] & ", " & "Pressure" & ": " & [FD2P] & ", " & "Humidity" & ": " & [FD2H] & ", " & "UV Index" & ": " & [FD2UV]
-
-[Forecast Day 3]
-Set Data=[FD3D] & ": (" & [FD3TH] & "/" & [FD3L] & ")" & ", " & [FD3C] & ", " & "Precipitation" & ": " & [FD3PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD3W] & ", " & "Pressure" & ": " & [FD3P] & ", " & "Humidity" & ": " & [FD3H] & ", " & "UV Index" & ": " & [FD3UV]
-
-[Forecast Day 4]
-Set Data=[FD4D] & ": (" & [FD4TH] & "/" & [FD4L] & ")" & ", " & [FD4C] & ", " & "Precipitation" & ": " & [FD4PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD4W] & ", " & "Pressure" & ": " & [FD4P] & ", " & "Humidity" & ": " & [FD4H] & ", " & "UV Index" & ": " & [FD4UV]
-
-[Forecast Day 5]
-Set Data=[FD5D] & ": (" & [FD5TH] & "/" & [FD5L] & ")" & ", " & [FD5C] & ", " & "Precipitation" & ": " & [FD5PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD5W] & ", " & "Pressure" & ": " & [FD5P] & ", " & "Humidity" & ": " & [FD5H] & ", " & "UV Index" & ": " & [FD5UV]
-
-[Forecast Day 6]
-Set Data=[FD6D] & ": (" & [FD6TH] & "/" & [FD6L] & ")" & ", " & [FD6C] & ", " & "Precipitation" & ": " & [FD6PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD6W] & ", " & "Pressure" & ": " & [FD6P] & ", " & "Humidity" & ": " & [FD6H] & ", " & "UV Index" & ": " & [FD6UV]
-
-[Forecast Day 7]
-Set Data=[FD7D] & ": (" & [FD7TH] & "/" & [FD7L] & ")" & ", " & [FD7C] & ", " & "Precipitation" & ": " & [FD7PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD7W] & ", " & "Pressure" & ": " & [FD7P] & ", " & "Humidity" & ": " & [FD7H] & ", " & "UV Index" & ": " & [FD7UV]
-
-[Forecast Day 8]
-Set Data=[FD8D] & ": (" & [FD8TH] & "/" & [FD8L] & ")" & ", " & [FD8C] & ", " & "Precipitation" & ": " & [FD8PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD8W] & ", " & "Pressure" & ": " & [FD8P] & ", " & "Humidity" & ": " & [FD8H] & ", " & "UV Index" & ": " & [FD8UV]
-
-[Forecast Day 9]
-Set Data=[FD9D] & ": (" & [FD9TH] & "/" & [FD9L] & ")" & ", " & [FD9C] & ", " & "Precipitation" & ": " & [FD9PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD9W] & ", " & "Pressure" & ": " & [FD9P] & ", " & "Humidity" & ": " & [FD9H] & ", " & "UV Index" & ": " & [FD9UV]
-
-;--------------------------------------------
-
-[Icons]
-Sunny=ясно
-Sunny=штиль
-Partly Cloudy=малооблачно
-Cloudy=облачно
-Cloudy=пасмурно
-Rain=небольшой дождь
-Rain Shower=дождь
-Rain Shower=ливень
-Snow=снег
-Snow=небольшой снег
-Snow=слабый снег хлопьями
-Snow Shower=снегопад
-Snow Shower=шквал
-Lightning=Storm
-Fog=туман
-
-[ID Search]
-Available=TRUE
-Search URL=https://www.gismeteo.com/search/%s/
-Not Found Str=Not Found
-Name Start=
-Name End=
-
-[Name Search]
-Single Result=false
-Multiple Result=true
-Search URL=https://www.gismeteo.com/search/%s/
-Not Found Str=Not found
-
-Mult First=ID
-Mult ID Start=<a href="/weather-
-Mult ID End=/"
-Mult Name Start=</i>
-Mult Name End=</a> \ No newline at end of file
diff --git a/protocols/Weather/docs/weather/gismeteo_ru.ini b/protocols/Weather/docs/weather/gismeteo_ru.ini
deleted file mode 100644
index 43a8886c74..0000000000
--- a/protocols/Weather/docs/weather/gismeteo_ru.ini
+++ /dev/null
@@ -1,1331 +0,0 @@
-[Weather 0.3.x Update Data 1.5]
-
-;*********************************************************
-;
-; Прогноз для gismeteo.ru.
-;
-; Поиск по названию города добавлен.
-; Можно искать по ID города, который предварительно выясняем на сайте Gismeteo.
-;
-; Перед использованием желательно удалить старые контакты
-; с погодой и найти нужные города по новой. Первый раз обновиться
-; из меню (правый клик на контакте) через "Удалить данные и обновить" .
-;
-; Чтобы все было красиво и понятно видно в миранде идем в
-; Параметры->Модули->Погода->Показывать и поле "Кратко" (остальные поля по вкусу)
-; полностью заменяем на:
-
-; Состояние погоды в %[CityName] на %u
-; ----------------------------------------------------------------
-; Условия: %c
-; Температура: %t
-; Давление: %p
-; Влажность: %m
-; Ветер: %i %w
-; Температура воды: %[TW]
-; Восход: %r, Закат: %y, Продолжительность дня: %[Day Length], Фаза Луны: %[Moon phase]
-;
-; Прогноз (Дата, Температура [Комфорт], Условия, Ветер, Давление, Влажность)
-; -------------------------------------------------------------------------------------------------------
-; %[Forecast Day 1]
-; %[Forecast Day 2]
-; %[Forecast Day 3]
-; %[Forecast Day 4]
-; %[Forecast Day 5]
-; %[Forecast Day 6]
-; %[Forecast Day 7]
-; %[Forecast Day 8]
-; %[Forecast Day 9]
-
-[Header]
-Name=GisMeteo.ru
-Internal Name=gm_ru
-Description=Weather information from Gismeteo.ru
-Author=Dimtr
-Version=2023.05.24
-Utf8=true
-
-[Default]
-Default URL=https://www.gismeteo.ru/weather-%s/
-Default Map=https://www.gismeteo.ru/nowcast-%s/?utm_campaign=radar&utm_source=gismeteo&utm_medium=radar_teaser
-Update URL=https://www.gismeteo.ru/weather-%s/now/
-Update URL2=https://www.gismeteo.ru/weather-%s/
-Update URL3=https://www.gismeteo.ru/weather-%s/10-days/
-
-;-----------------------------------------------------
-
-[Condition]
-Start=<div class="weathertab is-active" data-tooltip="
-End="
-Unit=Cond
-Url=1
-
-[Update]
-Start=data-pattern="G:i">
-End=</div>
-Url=1
-
-[TempNow]
-Start=<temperature-value value="
-End="
-Url=1
-Hidden=true
-
-[Temperature]
-Set Data=[TempNow] & " °C"
-
-[TempFeel]
-Start=<temperature-value value="
-End="
-Url=1
-Hidden=true
-
-[Feel]
-Set Data=[TempFeel] & " °C"
-
-[Low]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=1
-
-[High]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=1
-
-[WS]
-Start=<speed-value value="
-End="
-;Unit=m/s
-Url=1
-Hidden=true
-
-[Wind speed]
-Set Data=[WS] & " " & "m/s"
-
-;[Visibility]
-;Set Data=[Condition]
-;[/Visibility]
-
-[Ignore]
-Start=<speed-value reactive show-units></speed-value>
-End=>
-Url=1
-
-[Wind direction]
-Start=
-End=</div>
-Url=1
-
-[Pressure]
-Start=<pressure-value value="
-End="
-Unit=mm
-Url=1
-
-[Humidity]
-Start=<div class="item-value">
-End=</div>
-Unit=%
-Url=1
-
-[Geo]
-Start=<div class="item-value">
-End=</div>
-Url=1
-
-[TempWater]
-Start=<temperature-value value="
-End="
-Url=1
-Hidden=true
-
-[TW]
-Set Data=[TempWater] & " °C"
-
-[Day Length]
-Start=<div class="astro-progress">
-End=</div>
-Url=2
-
-[Sunrise]
-Start=<div>
-End=</div>
-Url=2
-
-[Sunset]
-Start=<div>
-End=</div>
-Url=2
-
-[Moon phase]
-Start=<div class="astro-progress">
-End=</div>
-Url=2
-
-[Moonrise]
-Start=<div>
-End=</div>
-Url=2
-
-[Moonset]
-Start=<div>
-End=</div>
-Url=2
-
-; DATE: T - time, D - day, M - month, W - weekday
-
-[FD0DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD0DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1DW]
-Start=/tomorrow/"><div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9DW]
-Start=<div class="day">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9DDM]
-Start=<div class="date">
-End=</div>
-Url=3
-Hidden=true
-
-;---------------//////////////////////////
-;------1--------//////////////////////////
-;---------------//////////////////////////
-;---------1-234--------------
-
-[FD0D]
-Set Data=[FD0DW] & " " & [FD0DDM]
-Hidden=true
-
-[FD1D]
-Set Data=[FD1DW] & " " & [FD1DDM]
-Hidden=true
-
-[FD2D]
-Set Data=[FD2DW] & " " & [FD2DDM]
-Hidden=true
-
-[FD3D]
-Set Data=[FD3DW] & " " & [FD3DDM]
-Hidden=true
-
-[FD4D]
-Set Data=[FD4DW] & " " & [FD4DDM]
-Hidden=true
-
-[FD5D]
-Set Data=[FD5DW] & " " & [FD5DDM]
-Hidden=true
-
-[FD6D]
-Set Data=[FD6DW] & " " & [FD6DDM]
-Hidden=true
-
-[FD7D]
-Set Data=[FD7DW] & " " & [FD7DDM]
-Hidden=true
-
-[FD8D]
-Set Data=[FD8DW] & " " & [FD8DDM]
-Hidden=true
-
-[FD9D]
-Set Data=[FD9DW] & " " & [FD9DDM]
-Hidden=true
-
-; CONDITION
-
-[FD0C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD1C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD2C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD3C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD4C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD5C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD6C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD7C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD8C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-[FD9C]
-Start=data-tooltip="
-End="
-Unit=Cond
-Url=3
-Hidden=true
-
-;temperature
-
-[FD0TH]
-Start=<div class="maxt"><temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD0L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD1TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD1L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD2TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD2L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD3TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD3L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD4TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD4L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD5TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD5L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD6TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD6L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD7TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD7L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD8TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD8L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD9TH]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-[FD9L]
-Start=<temperature-value value="
-End="
-Unit=C
-Url=3
-Hidden=true
-
-; WIND: H - Hidden data D - direction, S - Speed
-
-[FD0WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD1WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD2WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD3WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD4WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD5WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD6WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD7WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD8WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD9WS]
-Start=<speed-value value="
-End="
-Unit=m/s
-Url=3
-Hidden=true
-
-[FD0WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD1WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD2WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD3WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD4WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD5WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD6WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD7WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD8WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD9WD]
-Start=<div class="direction">
-End=</div>
-Url=3
-Hidden=true
-
-[FD0W]
-Set Data=[FD0WD] & " " & [FD0WS]
-Hidden=true
-
-[FD1W]
-Set Data=[FD1WD] & " " & [FD1WS]
-Hidden=true
-
-[FD2W]
-Set Data=[FD2WD] & " " & [FD2WS]
-Hidden=true
-
-[FD3W]
-Set Data=[FD3WD] & " " & [FD3WS]
-Hidden=true
-
-[FD4W]
-Set Data=[FD4WD] & " " & [FD4WS]
-Hidden=true
-
-[FD5W]
-Set Data=[FD5WD] & " " & [FD5WS]
-Hidden=true
-
-[FD6W]
-Set Data=[FD6WD] & " " & [FD6WS]
-Hidden=true
-
-[FD7W]
-Set Data=[FD7WD] & " " & [FD7WS]
-Hidden=true
-
-[FD8W]
-Set Data=[FD8WD] & " " & [FD8WS]
-Hidden=true
-
-[FD9W]
-Set Data=[FD9WD] & " " & [FD9WS]
-Hidden=true
-
-;Precipitation
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[Prec]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Precipitation]
-Set Data=[Prec] & " " & "mm"
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD1PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD2PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD3PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD4PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD5PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD6PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD7PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD8PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="item-unit
-End=">
-Url=3
-
-[FD9PR]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-; PRESSURE
-[FD0P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD1P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD2P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD3P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD4P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD5P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD6P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD7P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD8P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-[FD9P]
-Start=<div class="maxt"><pressure-value value="
-End="
-Unit=mm
-Url=3
-Hidden=true
-
-; Humidity
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD0H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD1H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD2H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD3H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD4H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD5H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD6H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD7H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD8H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD9H]
-Start=
-End=</div>
-Unit=%
-Url=3
-Hidden=true
-
-; UV Index
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[UV Index]
-Start=
-End=</div>
-Url=3
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD1UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD2UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD3UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD4UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD5UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD6UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD7UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD8UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD9UV]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-; Geo Magnetism
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD0GM]
-Start=
-End=</div>
-Url=3
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD1GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD2GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD3GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD4GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD5GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD6GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD7GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD8GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-[Ignore]
-Start=<div class="row-item
-End=">
-Url=3
-
-[FD9GM]
-Start=
-End=</div>
-Url=3
-Hidden=true
-
-;================================================
-;====================3===========================
-;================================================
-
-[Forecast Day 0]
-Set Data=[FD0D] & ": (" & [FD0TH] & "/" & [FD0L] & ")" & ", " & [FD0C] & ", " & "Precipitation" & ": " & [Prec] & " " & "mm" & ", \n" & "Wind" & ": " & [FD0W] & ", " & "Pressure" & ": " & [FD0P] & ", " & "Humidity" & ": " & [FD0H] & ", " & "UV Index" & ": " & [UV Index] & ", " & "G/M" & ": " & [FD0GM]
-
-[Forecast Day 1]
-Set Data=[FD1D] & ": (" & [FD1TH] & "/" & [FD1L] & ")" & ", " & [FD1C] & ", " & "Precipitation" & ": " & [FD1PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD1W] & ", " & "Pressure" & ": " & [FD1P] & ", " & "Humidity" & ": " & [FD1H] & ", " & "UV Index" & ": " & [FD1UV] & ", " & "G/M" & ": " & [FD1GM]
-
-[Forecast Day 2]
-Set Data=[FD2D] & ": (" & [FD2TH] & "/" & [FD2L] & ")" & ", " & [FD2C] & ", " & "Precipitation" & ": " & [FD2PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD2W] & ", " & "Pressure" & ": " & [FD2P] & ", " & "Humidity" & ": " & [FD2H] & ", " & "UV Index" & ": " & [FD2UV] & ", " & "G/M" & ": " & [FD2GM]
-
-[Forecast Day 3]
-Set Data=[FD3D] & ": (" & [FD3TH] & "/" & [FD3L] & ")" & ", " & [FD3C] & ", " & "Precipitation" & ": " & [FD3PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD3W] & ", " & "Pressure" & ": " & [FD3P] & ", " & "Humidity" & ": " & [FD3H] & ", " & "UV Index" & ": " & [FD3UV] & ", " & "G/M" & ": " & [FD3GM]
-
-[Forecast Day 4]
-Set Data=[FD4D] & ": (" & [FD4TH] & "/" & [FD4L] & ")" & ", " & [FD4C] & ", " & "Precipitation" & ": " & [FD4PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD4W] & ", " & "Pressure" & ": " & [FD4P] & ", " & "Humidity" & ": " & [FD4H] & ", " & "UV Index" & ": " & [FD4UV] & ", " & "G/M" & ": " & [FD4GM]
-
-[Forecast Day 5]
-Set Data=[FD5D] & ": (" & [FD5TH] & "/" & [FD5L] & ")" & ", " & [FD5C] & ", " & "Precipitation" & ": " & [FD5PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD5W] & ", " & "Pressure" & ": " & [FD5P] & ", " & "Humidity" & ": " & [FD5H] & ", " & "UV Index" & ": " & [FD5UV] & ", " & "G/M" & ": " & [FD5GM]
-
-[Forecast Day 6]
-Set Data=[FD6D] & ": (" & [FD6TH] & "/" & [FD6L] & ")" & ", " & [FD6C] & ", " & "Precipitation" & ": " & [FD6PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD6W] & ", " & "Pressure" & ": " & [FD6P] & ", " & "Humidity" & ": " & [FD6H] & ", " & "UV Index" & ": " & [FD6UV] & ", " & "G/M" & ": " & [FD6GM]
-
-[Forecast Day 7]
-Set Data=[FD7D] & ": (" & [FD7TH] & "/" & [FD7L] & ")" & ", " & [FD7C] & ", " & "Precipitation" & ": " & [FD7PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD7W] & ", " & "Pressure" & ": " & [FD7P] & ", " & "Humidity" & ": " & [FD7H] & ", " & "UV Index" & ": " & [FD7UV] & ", " & "G/M" & ": " & [FD7GM]
-
-[Forecast Day 8]
-Set Data=[FD8D] & ": (" & [FD8TH] & "/" & [FD8L] & ")" & ", " & [FD8C] & ", " & "Precipitation" & ": " & [FD8PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD8W] & ", " & "Pressure" & ": " & [FD8P] & ", " & "Humidity" & ": " & [FD8H] & ", " & "UV Index" & ": " & [FD8UV] & ", " & "G/M" & ": " & [FD8GM]
-
-[Forecast Day 9]
-Set Data=[FD9D] & ": (" & [FD9TH] & "/" & [FD9L] & ")" & ", " & [FD9C] & ", " & "Precipitation" & ": " & [FD9PR] & " " & "mm" & ", \n" & "Wind" & ": " & [FD9W] & ", " & "Pressure" & ": " & [FD9P] & ", " & "Humidity" & ": " & [FD9H] & ", " & "UV Index" & ": " & [FD9UV] & ", " & "G/M" & ": " & [FD9GM]
-
-;--------------------------------------------
-
-[Icons]
-Sunny=ясно
-Sunny=штиль
-Partly Cloudy=малооблачно
-Cloudy=облачно
-Cloudy=пасмурно
-Rain=небольшой дождь
-Rain Shower=дождь
-Rain Shower=ливень
-Snow=снег
-Snow=небольшой снег
-Snow=слабый снег хлопьями
-Snow Shower=снегопад
-Snow Shower=шквал
-Lightning=гроза
-Fog=туман
-
-[ID Search]
-Available=TRUE
-Search URL=https://www.gismeteo.ru/search/%s/
-Not Found Str=Not Found
-Name Start=
-Name End=
-
-[Name Search]
-Single Result=false
-Multiple Result=true
-Search URL=https://www.gismeteo.ru/search/%s/
-Not Found Str=Not found
-
-Mult First=ID
-Mult ID Start=<a href="/weather-
-Mult ID End=/"
-Mult Name Start=</i>
-Mult Name End=</a> \ No newline at end of file
diff --git a/protocols/Weather/docs/weather/msn.ini b/protocols/Weather/docs/weather/msn.ini
deleted file mode 100644
index 7075c4c9b8..0000000000
--- a/protocols/Weather/docs/weather/msn.ini
+++ /dev/null
@@ -1,1057 +0,0 @@
-[Weather 0.3.x Update Data 1.5]
-[Header]
-Name=MSN Weather (New Layout)
-Internal Name=msn2021
-Description=Get Weather from www.msn.com/en-us/weather
-Author=HostedDinner updated by pranza
-Version=2021-04-21
-Utf8=true
-
-;Id of the station is lat,long as for example New York: "40.78,-73.83"
-
-[Default]
-Default URL=https://www.msn.com/en-us/weather/today/x/we-city?q=%s
-Default Map=https://www.msn.com/en-us/weather/maps/x/we-city?q=%s
-Update URL=https://www.msn.com/en-us/weather/today/x/we-city?q=%s&weadegreetype=C
-UserAgent=Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
-
-[Update]
-Start=xdmap:
-End=;
-Url=1
-
-;current Weather
-[Ignore]
-Start=<div class="current-info">
-End=">
-
-[Temperature]
-Start=
-End=</span>
-Unit=C
-Url=1
-
-[Condition]
-Start=<span>
-End=</span>
-Url=1
-Unit=Cond
-
-[Feel]
-Start=Feels Like</span>
-End=&#176;
-Unit=C
-Url=1
-
-[Wind direction]
-Start=title="
-End="
-Url=1
-
-[Wind speed]
-Start=</div>
-End=km/h
-Url=1
-Unit=km/h
-
-[Pressure]
-Start=<span>Barometer</span>
-End=</li>
-Url=1
-Unit=mb
-
-[Visibility]
-Start=<span>Visibility</span>
-End=km
-Url=1
-Unit=km
-
-[Humidity]
-Start=<span>Humidity</span>
-End=%
-Url=1
-Unit=%
-
-[Dew point]
-Start=<span>Dew Point</span>
-End=&#176;
-Url=1
-unit=C
-
-;First entry is still today
-[Sunrise]
-Start=&quot;sunrise&quot;:&quot;
-End=&quot;
-Url=1
-
-[Sunset]
-Start=&quot;sunset&quot;:&quot;
-End=&quot;
-Url=1
-
-[Moonrise]
-Start=&quot;moonrise&quot;:&quot;
-End=&quot;
-Url=1
-
-[Moonset]
-Start=&quot;moonset&quot;:&quot;
-End=&quot;
-Url=1
-
-[Moon phase]
-Start=&quot;moon&quot;:&quot;
-End=&quot;
-Url=1
-
-[UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-
-[High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-
-[Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-
-;Forecast
-
-;[Forecast Day 1 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 1 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 1 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 1 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 1 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 1 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 1 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 1 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 1 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 1 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 1 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 1 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 1 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 2 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 2 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 2 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 2 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 2 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 2 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 2 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 2 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 2 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 2 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 2 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 2 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 2 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 3 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 3 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 3 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 3 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 3 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 3 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 3 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 3 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 3 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 3 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 3 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 3 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 3 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 4 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 4 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 4 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 4 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 4 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 4 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 4 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 4 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 4 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 4 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 4 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 4 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 4 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 5 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 5 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 5 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 5 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 5 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 5 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 5 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 5 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 5 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 5 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 5 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 5 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 5 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 6 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 6 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 6 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 6 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 6 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 6 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 6 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 6 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 6 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 6 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 6 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 6 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 6 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 7 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 7 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 7 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 7 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 7 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 7 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 7 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 7 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 7 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 7 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 7 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 7 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 7 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 8 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 8 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 8 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 8 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 8 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 8 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 8 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 8 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 8 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 8 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 8 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 8 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 8 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-;[Forecast Day 9 Sunrise]
-;Start=&quot;sunrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 9 Sunset]
-;Start=&quot;sunset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 9 Moonrise]
-;Start=&quot;moonrise&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 9 Moonset]
-;Start=&quot;moonset&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-;[Forecast Day 9 Moonphase]
-;Start=&quot;moon&quot;:&quot;
-;End=&quot;
-;Url=1
-;Hidden=true
-
-[Forecast Day 9 Humidity]
-Start=&quot;humidity&quot;:&quot;
-End=%&quot;
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 9 UV Index]
-Start=&quot;uvindex&quot;:&quot;
-End=&quot;
-Url=1
-Hidden=true
-
-;[Ignore]
-;Start=class="dt"
-;End=>
-;Url=1
-
-[Forecast Day 9 WeekDay]
-Start=<span>
-End=</span>
-Url=1
-Unit=Day
-Hidden=true
-
-[Forecast Day 9 Day]
-Start=<span>
-End=</span>
-Url=1
-Hidden=true
-
-[Forecast Day 9 Condition]
-Start=title="
-End="
-Url=1
-Unit=Cond
-Hidden=true
-
-[Ignore]
-Start=class="precipicn
-End=>
-Url=1
-
-[Forecast Day 9 Precipitation]
-Start=>
-End=%</span>
-Url=1
-Unit=%
-Hidden=true
-
-[Forecast Day 9 High]
-Start=<p>
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-[Forecast Day 9 Low]
-Start=<p class="transparent">
-End=&#176;
-Url=1
-Unit=C
-Hidden=true
-
-
-
-
-
-
-
-[Forecast Day 1]
-Set Data=[Forecast Day 1 WeekDay] & ", " & [Forecast Day 1 Day] & ": " & [Forecast Day 1 Condition] & " (" & [Forecast Day 1 Low] & "/" & [Forecast Day 1 High] & "), " & [Forecast Day 1 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 1 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 1 Humidity]
-
-[Forecast Day 2]
-Set Data=[Forecast Day 2 WeekDay] & ", " & [Forecast Day 2 Day] & ": " & [Forecast Day 2 Condition] & " (" & [Forecast Day 2 Low] & "/" & [Forecast Day 2 High] & "), " & [Forecast Day 2 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 2 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 2 Humidity]
-
-[Forecast Day 3]
-Set Data=[Forecast Day 3 WeekDay] & ", " & [Forecast Day 3 Day] & ": " & [Forecast Day 3 Condition] & " (" & [Forecast Day 3 Low] & "/" & [Forecast Day 3 High] & "), " & [Forecast Day 3 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 3 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 3 Humidity]
-
-[Forecast Day 4]
-Set Data=[Forecast Day 4 WeekDay] & ", " & [Forecast Day 4 Day] & ": " & [Forecast Day 4 Condition] & " (" & [Forecast Day 4 Low] & "/" & [Forecast Day 4 High] & "), " & [Forecast Day 4 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 4 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 4 Humidity]
-
-[Forecast Day 5]
-Set Data=[Forecast Day 5 WeekDay] & ", " & [Forecast Day 5 Day] & ": " & [Forecast Day 5 Condition] & " (" & [Forecast Day 5 Low] & "/" & [Forecast Day 5 High] & "), " & [Forecast Day 5 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 5 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 5 Humidity]
-
-[Forecast Day 6]
-Set Data=[Forecast Day 6 WeekDay] & ", " & [Forecast Day 6 Day] & ": " & [Forecast Day 6 Condition] & " (" & [Forecast Day 6 Low] & "/" & [Forecast Day 6 High] & "), " & [Forecast Day 6 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 6 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 6 Humidity]
-
-[Forecast Day 7]
-Set Data=[Forecast Day 7 WeekDay] & ", " & [Forecast Day 7 Day] & ": " & [Forecast Day 7 Condition] & " (" & [Forecast Day 7 Low] & "/" & [Forecast Day 7 High] & "), " & [Forecast Day 7 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 7 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 7 Humidity]
-
-[Forecast Day 8]
-Set Data=[Forecast Day 8 WeekDay] & ", " & [Forecast Day 8 Day] & ": " & [Forecast Day 8 Condition] & " (" & [Forecast Day 8 Low] & "/" & [Forecast Day 8 High] & "), " & [Forecast Day 8 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 8 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 8 Humidity]
-
-[Forecast Day 9]
-Set Data=[Forecast Day 9 WeekDay] & ", " & [Forecast Day 9 Day] & ": " & [Forecast Day 9 Condition] & " (" & [Forecast Day 9 Low] & "/" & [Forecast Day 9 High] & "), " & [Forecast Day 9 Precipitation] & " " & "Rain" & ", " & "UV" & ": " & [Forecast Day 9 UV Index] & ", " & "Humidity" & ": " & [Forecast Day 9 Humidity]
-
-
-
-[ID Search]
-Available=false
-
-[Name Search]
-Single Result=false
-Multiple Result=false
-
-;It's impossible to parse that...
-;the id is the lat/long of the town seperated with comma...
-;Search URL=http://api.bing.com/qsonhs.aspx?ds=w8weather&mkt=en-us&q=%s
-
-[Icons]
-;Sunny=Sunny
-Sunny=Clear
-Sunny=Fair
-Sunny=Sunny (Clear)
-
-;Partly Cloudy=Partly Cloudy
-Partly Cloudy=Mostly Cloudy
-
-;Cloudy=Cloudy
-
-;Rain=Rain
-
-;Rain Shower=Rain Shower
-Rain Shower=Sprinkles
-;To fix this one:
-Rain Shower=Sleet
-
-;Snow=Snow
-
-;Snow Shower=Snow Shower
-
-;Ligntning=Ligntning
-Ligntning=T-storms
-Ligntning=Scattered Thunderstorms
-Ligntning=Isolated Thunderstorms
-
-;Fog=Fog
-
diff --git a/protocols/Weather/res/resource.rc b/protocols/Weather/res/resource.rc
index 34e5f32c83..8c6e6227d8 100644
--- a/protocols/Weather/res/resource.rc
+++ b/protocols/Weather/res/resource.rc
@@ -43,40 +43,36 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- GROUPBOX "Options",IDC_STATIC,3,0,299,70,WS_GROUP
- CONTROL "Update weather information on startup",IDC_STARTUPUPD,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,12,286,8
- CONTROL "Update weather information every",IDC_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,23,206,8
- EDITTEXT IDC_UPDATETIME,223,21,33,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
- LTEXT "minutes",IDC_STATIC,260,23,39,8
+ GROUPBOX "Options",IDC_STATIC,3,0,299,69,WS_GROUP
+ CONTROL "Update weather information every",IDC_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,13,206,8
+ EDITTEXT IDC_UPDATETIME,223,11,33,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
+ LTEXT "minutes",IDC_STATIC,260,13,39,8
CONTROL "Consider weather info updated only when condition and temperature are changed",IDC_UPDCONDCHG,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,34,286,8
- CONTROL "Remove old data when updating",IDC_REMOVEOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,45,286,8
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,27,286,8
+ CONTROL "Remove old data when updating",IDC_REMOVEOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,41,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 "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
- CONTROL "Fahrenheit",IDC_T2,"Button",BS_AUTORADIOBUTTON,120,116,47,8
- RTEXT "Degree sign:",IDC_STATIC,194,116,85,8
- EDITTEXT IDC_DEGREE,283,116,13,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
- LTEXT "Wind",IDC_STATIC,8,125,53,8
- CONTROL "km/h",IDC_W1,"Button",BS_AUTORADIOBUTTON,65,125,34,8
- CONTROL "m/s",IDC_W2,"Button",BS_AUTORADIOBUTTON,120,125,34,8
- CONTROL "mph",IDC_W3,"Button",BS_AUTORADIOBUTTON,176,125,34,8
- CONTROL "knots",IDC_W4,"Button",BS_AUTORADIOBUTTON,232,125,49,8
- LTEXT "Visibility",IDC_STATIC,8,134,53,8
- CONTROL "km",IDC_V1,"Button",BS_AUTORADIOBUTTON,65,134,34,8
- CONTROL "miles",IDC_V2,"Button",BS_AUTORADIOBUTTON,120,134,34,8
- LTEXT "Pressure",IDC_STATIC,8,143,53,8
- CONTROL "kPa",IDC_P1,"Button",BS_AUTORADIOBUTTON,65,143,38,8
- CONTROL "mb (hPa)",IDC_P2,"Button",BS_AUTORADIOBUTTON,120,143,56,8
- CONTROL "inches",IDC_P3,"Button",BS_AUTORADIOBUTTON,176,143,38,8
- CONTROL "mm Hg (torr)",IDC_P4,"Button",BS_AUTORADIOBUTTON,232,143,62,8
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,55,286,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,99,299,87,WS_GROUP
+ LTEXT "Temperature",IDC_STATIC,8,111,53,8
+ CONTROL "Celsius",IDC_T1,"Button",BS_AUTORADIOBUTTON,65,111,40,8
+ CONTROL "Fahrenheit",IDC_T2,"Button",BS_AUTORADIOBUTTON,120,111,47,8
+ RTEXT "Degree sign:",IDC_STATIC,194,111,85,8
+ EDITTEXT IDC_DEGREE,283,111,13,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
+ LTEXT "Wind",IDC_STATIC,8,121,53,8
+ CONTROL "km/h",IDC_W1,"Button",BS_AUTORADIOBUTTON,65,121,34,8
+ CONTROL "m/s",IDC_W2,"Button",BS_AUTORADIOBUTTON,120,121,34,8
+ CONTROL "mph",IDC_W3,"Button",BS_AUTORADIOBUTTON,176,121,34,8
+ CONTROL "knots",IDC_W4,"Button",BS_AUTORADIOBUTTON,232,121,49,8
+ LTEXT "Visibility",IDC_STATIC,8,131,53,8
+ CONTROL "km",IDC_V1,"Button",BS_AUTORADIOBUTTON,65,131,34,8
+ CONTROL "miles",IDC_V2,"Button",BS_AUTORADIOBUTTON,120,131,34,8
+ LTEXT "Pressure",IDC_STATIC,8,142,53,8
+ CONTROL "kPa",IDC_P1,"Button",BS_AUTORADIOBUTTON,65,142,38,8
+ CONTROL "mb (hPa)",IDC_P2,"Button",BS_AUTORADIOBUTTON,120,142,56,8
+ CONTROL "inches",IDC_P3,"Button",BS_AUTORADIOBUTTON,176,142,38,8
+ CONTROL "mm Hg (torr)",IDC_P4,"Button",BS_AUTORADIOBUTTON,232,142,62,8
LTEXT "Day/Month",IDC_STATIC,8,153,53,8
CONTROL "No change",IDC_D1,"Button",BS_AUTORADIOBUTTON,65,153,52,8
CONTROL "2 chars",IDC_D2,"Button",BS_AUTORADIOBUTTON,120,153,56,8
@@ -92,7 +88,7 @@ BEGIN
LTEXT "Avatar size",IDC_STATIC,60,200,95,9
END
-IDD_EDIT DIALOGEX 0, 0, 241, 226
+IDD_EDIT DIALOGEX 0, 0, 241, 175
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
CAPTION "Edit Weather Station"
@@ -100,9 +96,9 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
GROUPBOX "Weather Station",IDC_STATIC,5,7,231,46
LTEXT "City name",IDC_STATIC,12,21,57,8,SS_CENTERIMAGE
- EDITTEXT IDC_NAME,69,19,146,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_NAME,69,19,162,12,ES_AUTOHSCROLL
LTEXT "ID",IDC_STATIC,12,37,57,8,SS_CENTERIMAGE
- EDITTEXT IDC_ID,69,35,146,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_ID,69,35,162,12,ES_AUTOHSCROLL | WS_DISABLED
GROUPBOX "Log Information",IDC_STATIC,5,55,231,53
CONTROL "Use internal history",IDC_Internal,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,68,218,8
CONTROL "Use external file",IDC_External,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,80,98,8
@@ -110,24 +106,13 @@ BEGIN
LTEXT "Path:",IDC_STATIC,25,93,37,8,SS_CENTERIMAGE
EDITTEXT IDC_LOG,69,91,146,12,ES_AUTOHSCROLL | ES_READONLY
CONTROL "6",IDC_BROWSE,"MButtonClass",WS_TABSTOP,217,91,13,12,WS_EX_NOACTIVATE | 0x10000000L
- GROUPBOX "Link Settings",IDC_STATIC,5,110,231,44
- LTEXT "More Info URL",IDC_STATIC,12,123,57,8
- EDITTEXT IDC_IURL,69,121,131,12,ES_AUTOHSCROLL
- CONTROL "6",IDC_VIEW1,"MButtonClass",WS_TABSTOP,202,121,13,12,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "6",IDC_RESET1,"MButtonClass",WS_TABSTOP,217,121,13,12,WS_EX_NOACTIVATE | 0x10000000L
- LTEXT "Weather Map",IDC_STATIC,12,138,57,8
- EDITTEXT IDC_MURL,69,137,131,12,ES_AUTOHSCROLL
- CONTROL "6",IDC_VIEW2,"MButtonClass",WS_TABSTOP,202,137,13,12,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "6",IDC_RESET2,"MButtonClass",WS_TABSTOP,217,137,13,12,WS_EX_NOACTIVATE | 0x10000000L
- GROUPBOX "Other Options",IDC_STATIC,5,157,231,46
- CONTROL "Set as default station",IDC_DEFA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,168,218,8
+ GROUPBOX "Other Options",IDC_STATIC,5,108,231,46
+ CONTROL "Set as default station",IDC_DEFA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,119,218,8
CONTROL "Disable automatic update for this station",IDC_DAutoUpdate,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,179,218,8
- CONTROL "Disable Popup for this station",IDC_DPop,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,190,218,8
- PUSHBUTTON "Change",IDC_CHANGE,57,207,46,14
- DEFPUSHBUTTON "Cancel",IDCANCEL,136,207,46,14
- CONTROL "",IDC_SVCINFO,"MButtonClass",WS_TABSTOP,217,35,13,12,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "",IDC_GETNAME,"MButtonClass",WS_TABSTOP,217,19,13,12,WS_EX_NOACTIVATE | 0x10000000L
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,130,218,8
+ CONTROL "Disable Popup for this station",IDC_DPop,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,141,218,8
+ PUSHBUTTON "Change",IDC_CHANGE,57,158,46,14
+ DEFPUSHBUTTON "Cancel",IDCANCEL,136,158,46,14
END
IDD_POPUP DIALOGEX 0, 0, 312, 236
@@ -136,7 +121,6 @@ EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
GROUPBOX "Popup Options",IDC_STATIC,4,5,158,54
- CONTROL "Enable popups",IDC_E,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,15,143,9
CONTROL "Popup only when condition changes",IDC_CH,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,44,140,10
GROUPBOX "Colors",IDC_STATIC,168,5,139,54
CONTROL "",IDC_BGCOLOUR,"ColourPicker",WS_TABSTOP,177,16,39,11
@@ -163,9 +147,19 @@ BEGIN
CONTROL "Variables",IDC_VAR3,"MButtonClass",WS_TABSTOP,7,153,62,12,WS_EX_NOACTIVATE | 0x10000000L
CONTROL "Default",IDC_PDEF,"MButtonClass",WS_TABSTOP,7,175,62,12,WS_EX_NOACTIVATE | 0x10000000L
CONTROL "Preview",IDC_PREVIEW,"MButtonClass",WS_TABSTOP,7,197,61,12,WS_EX_NOACTIVATE | 0x10000000L
- CONTROL "Updates",IDC_POP1,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,29,24,64,9
- CONTROL "Alerts",IDC_POP2,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,29,34,64,9
- CONTROL "Errors",IDC_W,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,97,24,54,9
+ CONTROL "Updates",IDC_POP1,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,14,18,64,9
+ CONTROL "Alerts",IDC_POP2,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,14,31,64,9
+ CONTROL "Errors",IDC_W,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,82,18,54,9
+END
+
+IDD_ACCOUNT_OPT DIALOGEX 0, 0, 309, 233
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Enter your personal API key from Visual Crossing Weather site",IDC_STATIC,8,7,294,8
+ EDITTEXT IDC_KEY,8,19,294,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Obtain key",IDC_OBTAIN,172,38,130,14
END
IDD_TEXTOPT DIALOGEX 0, 0, 309, 233
@@ -188,7 +182,7 @@ BEGIN
CONTROL "History Log",IDC_TM7,"MButtonClass",WS_TABSTOP,2,221,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
EDITTEXT IDC_HTEXT,80,219,183,12,ES_AUTOHSCROLL
GROUPBOX "Variable List",IDC_STATIC,207,14,99,191
- LTEXT "",IDC_VARLIST,213,25,86,157
+ CONTROL "",IDC_VARLIST,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,213,25,86,157
CONTROL "More Variables",IDC_MORE,"MButtonClass",WS_TABSTOP,216,187,81,15,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
CONTROL "Reset",IDC_RESET,"MButtonClass",WS_TABSTOP,266,208,40,21,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
EDITTEXT IDC_BTITLE2,80,28,125,12,ES_AUTOHSCROLL
@@ -229,40 +223,6 @@ BEGIN
CONTROL "More...",IDC_MOREDETAIL,"MButtonClass",WS_TABSTOP,129,104,61,12,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
END
-IDD_SETUP DIALOGEX 0, 0, 259, 142
-STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-CAPTION "Weather Protocol INI Setup"
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- CONTROL "Install and load your weather ini file here",IDC_HEADERBAR,
- "MHeaderbarCtrl",0x0,0,0,259,28
- CTEXT "Weather Protocol cannot find any weather INI file stored in your computer. To setup weather INI and add weather stations, please follow the steps:",IDC_STATIC,11,32,222,26
- CONTROL "Click here to download a weather ini file from Miranda file listing",IDC_STEP1,
- "MButtonClass",WS_TABSTOP,5,62,249,12,WS_EX_WINDOWEDGE | 0x800000L
- CONTROL "Extract the weather ini file from archive to this directory",IDC_STEP2,
- "MButtonClass",WS_TABSTOP,5,74,249,12,WS_EX_WINDOWEDGE | 0x800000L
- CONTROL "Click here to load the data from the new ini file into memory",IDC_STEP3,
- "MButtonClass",WS_TABSTOP,5,86,249,13,WS_EX_WINDOWEDGE | 0x800000L
- CONTROL "Add new weather station and close this dialog",IDC_STEP4,
- "MButtonClass",WS_TABSTOP,5,99,249,12,WS_EX_WINDOWEDGE | 0x800000L
- PUSHBUTTON "Close",IDCANCEL,107,122,48,13
- CONTROL "",IDC_MFRAME,"Static",SS_ETCHEDHORZ,0,117,259,1
-END
-
-IDD_INFO DIALOGEX 0, 0, 225, 155
-STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
-EXSTYLE WS_EX_CONTROLPARENT
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- CONTROL "",IDC_INFOLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,210,115
- LTEXT "Total INI files",IDC_STATIC,7,125,95,8
- LTEXT "Total memory used",IDC_STATIC,7,138,92,8
- LTEXT "",IDC_INICOUNT,104,125,30,10,SS_SUNKEN
- LTEXT "",IDC_MEMUSED,104,138,29,10,SS_SUNKEN
- PUSHBUTTON "Reload INI",IDC_RELOADINI,145,128,64,18
-END
-
IDD_SEARCHCITY DIALOGEX 0, 0, 114, 55
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_TRANSPARENT | WS_EX_CONTROLPARENT
@@ -289,33 +249,26 @@ BEGIN
IDD_OPTIONS, DIALOG
BEGIN
- VERTGUIDE, 8
- VERTGUIDE, 294
BOTTOMMARGIN, 209
END
- IDD_POPUP, DIALOG
+ IDD_EDIT, DIALOG
BEGIN
- RIGHTMARGIN, 306
- BOTTOMMARGIN, 233
END
- IDD_TEXTOPT, DIALOG
+ IDD_POPUP, DIALOG
BEGIN
- BOTTOMMARGIN, 232
+ RIGHTMARGIN, 306
+ BOTTOMMARGIN, 233
END
- IDD_SETUP, DIALOG
+ IDD_ACCOUNT_OPT, DIALOG
BEGIN
- BOTTOMMARGIN, 136
END
- IDD_INFO, DIALOG
+ IDD_TEXTOPT, DIALOG
BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 217
- TOPMARGIN, 7
- BOTTOMMARGIN, 148
+ BOTTOMMARGIN, 232
END
IDD_SEARCHCITY, DIALOG
@@ -374,15 +327,24 @@ END
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON ICON "icon.ico"
+
IDI_UPDATE ICON "update.ico"
+
IDI_READ ICON "more.ico"
+
IDI_S ICON "brief.ico"
+
IDI_LOG ICON "log.ico"
+
IDI_EDIT ICON "edit.ico"
+
IDI_MAP ICON "map.ico"
+
IDI_UPDATE2 ICON "update2.ico"
+
IDI_DISABLED ICON "disabled.ico"
+
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
diff --git a/protocols/Weather/src/proto.h b/protocols/Weather/src/proto.h
new file mode 100644
index 0000000000..b44c193110
--- /dev/null
+++ b/protocols/Weather/src/proto.h
@@ -0,0 +1,296 @@
+#pragma once
+
+struct WIDATAITEM
+{
+ WIDATAITEM(const wchar_t *_1, const wchar_t *_2, const CMStringW &_3) :
+ Name(_1),
+ Unit(_2),
+ Value(_3)
+ {}
+
+ const wchar_t *Name, *Unit;
+ CMStringW Value;
+};
+
+struct WIDATAITEMLIST : public OBJLIST<WIDATAITEM>
+{
+ WIDATAITEMLIST() :
+ OBJLIST<WIDATAITEM>(20)
+ {}
+
+ WIDATAITEM* Find(const wchar_t *pwszName)
+ {
+ for (auto &it : *this)
+ if (!mir_wstrcmp(it->Name, pwszName))
+ return it;
+ return 0;
+ }
+};
+
+struct WEATHERINFO
+{
+ MCONTACT hContact;
+ TCHAR id[128];
+ TCHAR city[128];
+ TCHAR update[64];
+ TCHAR cond[128];
+ TCHAR temp[16];
+ TCHAR low[16];
+ TCHAR high[16];
+ TCHAR feel[16];
+ TCHAR wind[16];
+ TCHAR winddir[64];
+ TCHAR dewpoint[16];
+ TCHAR pressure[16];
+ TCHAR humid[16];
+ TCHAR vis[16];
+ TCHAR sunrise[32];
+ TCHAR sunset[32];
+};
+
+struct MYOPTIONS
+{
+ // main options
+ uint8_t AutoUpdate;
+ uint8_t CAutoUpdate;
+ 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 CPopupOptsDlg;
+ friend class CBriefInfoDlg;
+ friend class COptionsTextDlg;
+ friend class CGeneralOptionsDlg;
+ friend class WeatherUserInfoDlg;
+
+ 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;
+
+ // avatars
+ void AvatarDownloaded(MCONTACT hContact);
+
+ INT_PTR __cdecl AdvancedStatusIconSvc(WPARAM, LPARAM);
+ INT_PTR __cdecl GetAvatarInfoSvc(WPARAM, LPARAM);
+
+ // contacts
+ INT_PTR __cdecl ViewLog(WPARAM, LPARAM);
+ INT_PTR __cdecl LoadForecast(WPARAM, LPARAM);
+ INT_PTR __cdecl WeatherMap(WPARAM, LPARAM);
+ INT_PTR __cdecl EditSettings(WPARAM, LPARAM);
+
+ int __cdecl BriefInfoEvt(WPARAM, LPARAM);
+
+ bool IsMyContact(MCONTACT hContact);
+
+ // conversions
+ void numToStr(double num, wchar_t *str, size_t strSize);
+
+ void GetTemp(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str);
+ void GetSpeed(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str);
+ void GetPressure(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str);
+ void GetDist(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str);
+ void GetElev(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str);
+
+ // data
+ void ConvertDataValue(WIDATAITEM *UpdateData);
+ void EraseAllInfo(void);
+ WEATHERINFO LoadWeatherInfo(MCONTACT hContact);
+
+ MHttpResponse* RunQuery(const wchar_t *id, int days);
+
+ // menu items
+ HGENMENU hEnableDisableMenu;
+
+ void InitMenuItems();
+ void UpdateMenu(BOOL State);
+
+ INT_PTR __cdecl EnableDisableCmd(WPARAM, LPARAM);
+
+ // mwin
+ void AddFrameWindow(MCONTACT hContact);
+ void RemoveFrameWindow(MCONTACT hContact);
+
+ void InitMwin(void);
+ void DestroyMwin(void);
+
+ INT_PTR __cdecl Mwin_MenuClicked(WPARAM, LPARAM);
+
+ // options
+ void LoadOptions();
+ void SaveOptions();
+ void RestartTimer();
+ void InitPopupOptions(WPARAM);
+
+ int __cdecl OptInit(WPARAM, LPARAM);
+
+ CMStringW GetTextValue(int c);
+ void GetVarsDescr(CMStringW &str);
+
+ // popups
+ int WPShowMessage(const wchar_t *lpzText, int kind);
+ int WeatherPopup(MCONTACT hContact, bool bNew);
+
+ // search
+ bool CheckSearch();
+
+ int IDSearch(wchar_t *id, int searchId);
+ int NameSearch(wchar_t *name, int searchId);
+
+ void __cdecl NameSearchThread(void *);
+ void __cdecl BasicSearchThread(void *);
+
+ // update weather
+ std::vector<MCONTACT> m_updateList;
+
+ // check if weather is currently updating
+ bool m_bThreadRunning;
+ mir_cs m_csUpdate;
+
+ void DoUpdate();
+ void StartUpdate();
+
+ 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, LPARAM);
+ INT_PTR __cdecl UpdateAllRemove(WPARAM, LPARAM);
+
+ // user info
+ int __cdecl UserInfoInit(WPARAM, LPARAM);
+
+public:
+ CWeatherProto(const char *protoName, const wchar_t *userName);
+ ~CWeatherProto();
+
+ MYOPTIONS opt;
+
+ CMOption<bool> m_bPopups;
+ CMOption<wchar_t *> m_szApiKey;
+ INT_PTR __cdecl BriefInfo(WPARAM, LPARAM);
+
+ int MapCondToStatus(MCONTACT hContact);
+ HICON GetStatusIcon(MCONTACT hContact);
+ HICON GetStatusIconBig(MCONTACT hContact);
+
+ static LRESULT CALLBACK CWeatherProto::PopupWndProc(HWND hWnd, UINT uMsg, WPARAM, 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;
+
+ void __cdecl GetAwayMsgThread(void *arg);
+ HANDLE GetAwayMsg(MCONTACT hContact) override;
+
+ void __cdecl AckThreadProc(void *arg);
+ int GetInfo(MCONTACT hContact, int) override;
+
+ bool OnContactDeleted(MCONTACT, uint32_t flags) override;
+ void OnModulesLoaded() override;
+ void OnShutdown() override;
+
+ static void GlobalMenuInit();
+ int __cdecl BuildContactMenu(MCONTACT);
+
+ int __cdecl OnToolbarLoaded(WPARAM, LPARAM);
+};
+
+typedef CProtoDlgBase<CWeatherProto> CWeatherDlgBase;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Plugin class
+
+struct CMPlugin : public ACCPROTOPLUGIN<CWeatherProto>
+{
+ CMPlugin();
+
+ HINSTANCE hIconsDll = nullptr;
+
+ int Load() override;
+ int Unload() override;
+};
diff --git a/protocols/Weather/src/resource.h b/protocols/Weather/src/resource.h
index 67e9006fb3..809c94857b 100644
--- a/protocols/Weather/src/resource.h
+++ b/protocols/Weather/src/resource.h
@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by ..\res\resource.rc
+// Used by W:\miranda-ng\protocols\Weather\res\resource.rc
//
#define IDI_ICON 101
#define IDD_USERINFO 201
@@ -9,6 +9,7 @@
#define IDD_POPUP 204
#define IDD_OPTIONS 205
#define IDI_LOG 206
+#define IDD_ACCOUNT_OPT 207
#define IDI_UPDATE2 208
#define IDI_READ 209
#define IDI_UPDATE 210
@@ -17,11 +18,9 @@
#define IDR_PMENU 213
#define IDD_TEXTOPT 216
#define IDD_BRIEF 217
-#define IDD_SETUP 218
#define IDR_TMENU 219
#define IDR_TMMENU 220
#define IDI_EDIT 222
-#define IDD_INFO 224
#define IDD_SEARCHCITY 225
#define IDC_NAME 2000
#define IDC_ID 2001
@@ -31,7 +30,6 @@
#define IDC_AVATARSIZE 2006
#define IDC_UPDATE 2007
#define IDC_BTITLE 2008
-#define IDC_STARTUPUPD 2008
#define IDC_CHANGE 2009
#define IDC_BTITLE2 2009
#define IDC_USEWINCOLORS 2010
@@ -39,7 +37,6 @@
#define IDC_CH 2013
#define IDC_NTEXT 2015
#define IDC_DEGREE 2016
-#define IDC_E 2017
#define IDC_W 2018
#define IDC_POP1 2019
#define IDC_XTEXT 2020
@@ -56,9 +53,6 @@
#define IDC_HTEXT 2028
#define IDC_DPop 2029
#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
@@ -78,14 +72,8 @@
#define IDC_W3 2052
#define IDC_W4 2053
#define IDC_BROWSE 2054
-#define IDC_VIEW1 2055
-#define IDC_RESET1 2056
-#define IDC_VIEW2 2057
#define IDC_V1 2058
#define IDC_V2 2059
-#define IDC_RESET2 2060
-#define IDC_SVCINFO 2061
-#define IDC_GETNAME 2062
#define IDC_P1 2063
#define IDC_P2 2064
#define IDC_P3 2065
@@ -125,23 +113,17 @@
#define IDC_MOREDETAIL 2095
#define IDC_DATALIST 2096
#define IDC_MUPDATE 2097
-#define IDC_MFRAME 2099
#define IDC_MTOGGLE 2101
#define IDC_MWEBPAGE 2102
#define IDC_MTEXT 2103
-#define IDC_STEP1 2107
-#define IDC_STEP2 2108
-#define IDC_STEP3 2109
-#define IDC_STEP4 2110
-#define IDC_INFOLIST 2117
-#define IDC_RELOADINI 2118
-#define IDC_MEMUSED 2119
-#define IDC_INICOUNT 2120
#define IDC_AVATARSPIN 2124
#define IDC_SEARCHCITY 2125
#define IDC_HEADERBAR 2126
#define IDC_E1 2128
+#define IDC_EDIT1 2128
+#define IDC_KEY 2128
#define IDC_E2 2129
+#define IDC_OBTAIN 2129
#define OIC_HAND 32513
#define OIC_QUES 32514
#define OIC_BANG 32515
@@ -158,7 +140,6 @@
#define ID_T2 40011
#define ID_MPREVIEW 40020
#define ID_MRESET 40021
-#define IDC_STATIC -1
// Next default values for new objects
//
@@ -167,7 +148,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 226
#define _APS_NEXT_COMMAND_VALUE 40030
-#define _APS_NEXT_CONTROL_VALUE 2128
+#define _APS_NEXT_CONTROL_VALUE 2130
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/Weather/src/stdafx.cxx b/protocols/Weather/src/stdafx.cxx
index 13f28e1314..f111565f38 100644
--- a/protocols/Weather/src/stdafx.cxx
+++ b/protocols/Weather/src/stdafx.cxx
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2012-24 Miranda NG team (https://miranda-ng.org)
+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
diff --git a/protocols/Weather/src/stdafx.h b/protocols/Weather/src/stdafx.h
index 64993c86ef..cf1f3240a3 100644
--- a/protocols/Weather/src/stdafx.h
+++ b/protocols/Weather/src/stdafx.h
@@ -1,6 +1,6 @@
/*
Weather Protocol plugin for Miranda NG
-Copyright (C) 2012-24 Miranda NG team
+Copyright (C) 2012-25 Miranda NG team
Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved
Copyright (c) 2002-2005 Calvin Che
@@ -24,8 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
-//============ THE INCLUDES ===========
-
#include <share.h>
#include <time.h>
#include <windows.h>
@@ -33,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <richedit.h>
#include <malloc.h>
+#include <vector>
+
#include <newpluginapi.h>
#include <m_acc.h>
#include <m_avatars.h>
@@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_history.h>
#include <m_icolib.h>
#include <m_ignore.h>
+#include <m_json.h>
#include <m_langpack.h>
#include <m_netlib.h>
#include <m_options.h>
@@ -57,13 +58,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_xstatus.h>
#include <m_tipper.h>
-#include <m_weather.h>
#include <m_toptoolbar.h>
#include "resource.h"
#include "version.h"
+#include "proto.h"
-//============ CONSTANTS ============
+/////////////////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
// name
#define MODULENAME "Weather"
@@ -86,17 +88,10 @@ enum EWeatherCondition
MAX_COND
};
-// status
-#define NOSTATUSDATA 1
-
// limits
#define MAX_TEXT_SIZE 4096
#define MAX_DATA_LEN 1024
-// db info mangement mode
-#define WDBM_REMOVE 1
-#define WDBM_DETAILDISPLAY 2
-
// more info list column width
#define LIST_COLUMN 150
@@ -105,442 +100,62 @@ 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
-
-// weather update error text
-#define E10 TranslateT("Invalid ID format, missing \"/\" (10)")
-#define E11 TranslateT("Invalid service (11)")
-#define E12 TranslateT("Invalid station (12)")
-#define E20 TranslateT("Weather service ini for this station is not found (20)")
-#define E30 TranslateT("Netlib error - check your internet connection (30)")
-#define E40 TranslateT("Empty data is retrieved (40)")
-#define E42 TranslateT("Document not found (42)")
-#define E43 TranslateT("Document too short to contain any weather data (43)")
-#define E99 TranslateT("Unknown error (99)")
-
-// HTTP error... not all translated
-// 100 Continue
-// 101 Switching Protocols
-// 200 OK
-// 201 Created
-// 202 Accepted
-// 203 Non-Authoritative Information
-#define E204 TranslateT("HTTP Error: No content (204)")
-// 205 Reset Content
-// 206 Partial Content
-// 300 Multiple Choices
-#define E301 TranslateT("HTTP Error: Data moved (301)")
-// 302 Found
-// 303 See Other
-// 304 Not Modified
-#define E305 TranslateT("HTTP Error: Use proxy (305)")
-// 306 (Unused)
-#define E307 TranslateT("HTTP Error: Temporary redirect (307)")
-#define E400 TranslateT("HTTP Error: Bad request (400)")
-#define E401 TranslateT("HTTP Error: Unauthorized (401)")
-#define E402 TranslateT("HTTP Error: Payment required (402)")
-#define E403 TranslateT("HTTP Error: Forbidden (403)")
-#define E404 TranslateT("HTTP Error: Not found (404)")
-#define E405 TranslateT("HTTP Error: Method not allowed (405)")
-// 406 Not Acceptable
-#define E407 TranslateT("HTTP Error: Proxy authentication required (407)")
-// 408 Request Timeout
-// 409 Conflict
-#define E410 TranslateT("HTTP Error: Gone (410)")
-// 411 Length Required
-// 412 Precondition Failed
-// 413 Request Entity Too Large
-// 414 Request-URI Too Long
-// 415 Unsupported Media Type
-// 416 Requested Range Not Satisfiable
-// 417 Expectation Failed
-#define E500 TranslateT("HTTP Error: Internal server error (500)")
-// 501 Not Implemented
-#define E502 TranslateT("HTTP Error: Bad gateway (502)")
-#define E503 TranslateT("HTTP Error: Service unavailable (503)")
-#define E504 TranslateT("HTTP Error: Gateway timeout (504)")
-// 505 HTTP Version Not Supported
-
-// 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;
- struct WCONTACTLIST *next;
-};
-
-typedef struct WCONTACTLIST UPDATELIST;
-
-extern UPDATELIST *UpdateListHead, *UpdateListTail;
-
-void DestroyUpdateList(void);
-
-//============ DATA FORMAT STRUCT ============
-
-#define WID_NORMAL 0
-#define WID_SET 1
-#define WID_BREAK 2
-
-struct WIDATAITEM
-{
- wchar_t *Name;
- wchar_t *Start;
- wchar_t *End;
- wchar_t *Unit;
- char *Url;
- wchar_t *Break;
- int Type;
-};
-
-struct WITEMLIST
+#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)
+
+struct WeatherReply : public JsonReply
{
- WIDATAITEM Item;
- struct WITEMLIST *Next;
+ WeatherReply(MHttpResponse *response) :
+ JsonReply(response)
+ {
+ delete response;
+ }
};
-typedef struct WITEMLIST WIDATAITEMLIST;
-
-struct WIIDSEARCH
-{
- BOOL Available;
- char *SearchURL;
- wchar_t *NotFoundStr;
- WIDATAITEM Name;
-};
+/////////////////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARIABLES
-struct WINAMESEARCHTYPE
-{
- BOOL Available;
- wchar_t *First;
- WIDATAITEM Name;
- WIDATAITEM ID;
-};
-
-struct WINAMESEARCH
-{
- char *SearchURL;
- wchar_t *NotFoundStr;
- wchar_t *SingleStr;
- WINAMESEARCHTYPE Single;
- WINAMESEARCHTYPE Multiple;
-};
-
-struct STRLIST
-{
- wchar_t *Item;
- struct STRLIST *Next;
-};
-
-typedef struct STRLIST WICONDITEM;
-
-struct WICONDLIST
-{
- WICONDITEM *Head;
- WICONDITEM *Tail;
-};
-
-struct WIDATA
-{
- wchar_t *FileName;
- wchar_t *ShortFileName;
- BOOL Enabled;
-
- // header
- wchar_t *DisplayName;
- wchar_t *InternalName;
- wchar_t *Description;
- wchar_t *Author;
- wchar_t *Version;
- int InternalVer;
- size_t MemUsed;
-
- // default
- char *DefaultURL;
- wchar_t *DefaultMap;
- char *UpdateURL;
- char *UpdateURL2;
- char *UpdateURL3;
- char *UpdateURL4;
- char *Cookie;
- char *UserAgent;
-
- // items
- int UpdateDataCount;
- WIDATAITEMLIST *UpdateData;
- WIDATAITEMLIST *UpdateDataTail;
- WIIDSEARCH IDSearch;
- WINAMESEARCH NameSearch;
- WICONDLIST CondList[MAX_COND];
-};
-
-//============ DATA LIST (LINKED LIST) ============
-
-struct DATALIST
-{
- WIDATA Data;
- struct DATALIST *next;
-};
-
-typedef struct DATALIST WIDATALIST;
-
-//============ GLOBAL VARIABLES ============
-
-extern WIDATALIST *WIHead, *WITail;
-
-extern HWND hPopupWindow, hWndSetup;
-
-extern MYOPTIONS opt;
-
-extern unsigned status, old_status;
+extern HWND hPopupWindow;
extern MWindowList hDataWindowList, hWindowList;
-extern HNETLIBUSER hNetlibUser;
-extern HANDLE hHookWeatherUpdated, hHookWeatherError, hTBButton, hUpdateMutex;
-extern UINT_PTR timerId;
+extern HANDLE hTBButton;
extern HGENMENU hMwinMenu;
-// check if weather is currently updating
-extern BOOL ThreadRunning;
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);
-HICON GetStatusIconBig(MCONTACT hContact);
-uint16_t GetIcon(const wchar_t* cond, WIDATA *Data);
void CaseConv(wchar_t *str);
void TrimString(char *str);
void TrimString(wchar_t *str);
void ConvertBackslashes(char *str);
char *GetSearchStr(char *dis);
-wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t* str);
-INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam);
-
-void GetSvc(wchar_t *pszID);
-void GetID(wchar_t *pszID);
+CMStringW GetDisplay(WEATHERINFO *w, const wchar_t *dis);
wchar_t *GetError(int code);
-// functions in weather_data.c
-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);
-void wfree(char *&Data);
-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);
-
-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);
-
-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);
+const wchar_t *GetDefaultText(int c);
+/////////////////////////////////////////////////////////////////////////////////////////
// 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
-{
- CCtrlButton btnReload;
-
-public:
- WeatherMyDetailsDlg();
-
- bool OnInitDialog() override;
-
- void onClick_Reload(CCtrlButton *);
-};
-
-//============ Plugin Class ============
-
-struct CMPlugin : public PLUGIN<CMPlugin>
-{
- CMPlugin();
-
- HINSTANCE hIconsDll = nullptr;
- CMOption<bool> bPopups;
-
- int Load() override;
- int Unload() override;
-};
+void UpdateMwinData(MCONTACT hContact);
diff --git a/protocols/Weather/src/version.h b/protocols/Weather/src/version.h
index b63cb63edb..cf07dd1fa3 100644
--- a/protocols/Weather/src/version.h
+++ b/protocols/Weather/src/version.h
@@ -1,7 +1,7 @@
-#define __MAJOR_VERSION 0
-#define __MINOR_VERSION 4
+#define __MAJOR_VERSION 1
+#define __MINOR_VERSION 1
#define __RELEASE_NUM 0
-#define __BUILD_NUM 8
+#define __BUILD_NUM 1
#include <stdver.h>
@@ -10,4 +10,4 @@
#define __DESCRIPTION "Retrieves weather information and displays it in your contact list."
#define __AUTHOR "Miranda NG team"
#define __AUTHORWEB "https://miranda-ng.org/p/Weather"
-#define __COPYRIGHT "© 2002-2005 NoName, 2005-2010 Boris Krasnovskiy, 2012-24 Miranda NG team"
+#define __COPYRIGHT "© 2002-2005 NoName, 2005-2010 Boris Krasnovskiy, 2012-25 Miranda NG team"
diff --git a/protocols/Weather/src/weather.cpp b/protocols/Weather/src/weather.cpp
index f5e6bb2e7b..b0ee091b46 100644
--- a/protocols/Weather/src/weather.cpp
+++ b/protocols/Weather/src/weather.cpp
@@ -28,33 +28,12 @@ belong to any other file.
//============ GLOBAL VARIABLES ============
-WIDATALIST *WIHead;
-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;
-
-// check if weather is currently updating
-BOOL ThreadRunning;
-
-// variable to determine if module loaded
-BOOL ModuleLoaded = FALSE;
-
VARSW g_pwszIconsName(L"%miranda_path%\\Icons\\proto_Weather.dll");
HANDLE hTBButton = nullptr;
@@ -77,11 +56,8 @@ static const PLUGININFOEX pluginInfoEx =
};
CMPlugin::CMPlugin() :
- PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx),
- bPopups(MODULENAME, "UsePopup", true)
+ ACCPROTOPLUGIN<CWeatherProto>(MODULENAME, pluginInfoEx)
{
- opt.NoProtoCondition = g_plugin.getByte("NoStatus", true);
- RegisterProtocol((opt.NoProtoCondition) ? PROTOTYPE_VIRTUAL : PROTOTYPE_PROTOCOL);
SetUniqueId("ID");
}
@@ -91,52 +67,10 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOC
/////////////////////////////////////////////////////////////////////////////////////////
-int WeatherShutdown(WPARAM, LPARAM)
+static int OnPreShutdown(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)
-{
- TTBButton ttb = {};
- ttb.name = LPGEN("Enable/disable auto update");
- ttb.pszService = MS_WEATHER_ENABLED;
- ttb.pszTooltipUp = LPGEN("Auto Update Enabled");
- ttb.pszTooltipDn = LPGEN("Auto Update Disabled");
- ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_ICON);
- ttb.hIconHandleDn = g_plugin.getIconHandle(IDI_DISABLED);
- ttb.dwFlags = (g_plugin.getByte("AutoUpdate", 1) ? 0 : TTBBF_PUSHED) | TTBBF_ASPUSHBUTTON | TTBBF_VISIBLE;
- hTBButton = g_plugin.addTTB(&ttb);
- return 0;
-}
-
-// weather protocol initialization function
-// run after the event ME_SYSTEM_MODULESLOADED occurs
-int WeatherInit(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;
}
@@ -159,56 +93,26 @@ int CMPlugin::Load()
{
g_plugin.registerIcon(MODULENAME, iconList, MODULENAME);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreShutdown);
+
// 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);
-
+ // window lists
hDataWindowList = WindowList_Create();
hWindowList = WindowList_Create();
- hUpdateMutex = CreateMutex(nullptr, FALSE, nullptr);
-
- // initialize weather protocol services
- InitServices();
+ // add global menus
+ CWeatherProto::GlobalMenuInit();
// add sound event
addSound("weatherupdated", _A2W(MODULENAME), LPGENW("Condition Changed"));
addSound("weatheralert", _A2W(MODULENAME), LPGENW("Alert Issued"));
- // popup initialization
- addPopupOption(LPGEN("Weather notifications"), bPopups);
-
// window needed for popup commands
- wchar_t SvcFunc[100];
- mir_snwprintf(SvcFunc, L"%s__PopupWindow", _A2W(MODULENAME));
- hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW, L"static", SvcFunc, 0, CW_USEDEFAULT, CW_USEDEFAULT,
+ hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW, L"static", _A2W(MODULENAME) L"__PopupWindow", 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 +124,9 @@ 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 79504143ae..026b9f8c67 100644
--- a/protocols/Weather/src/weather_addstn.cpp
+++ b/protocols/Weather/src/weather_addstn.cpp
@@ -28,157 +28,126 @@ 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)
+ if (!psr || !psr->id.w)
return 0;
// search for existing contact
- for (auto &hContact : Contacts()) {
- // check if it is a weather contact
- if (IsMyContact(hContact)) {
- DBVARIANT dbv;
- // check ID to see if the contact already exist in the database
- if (!g_plugin.getWString(hContact, "ID", &dbv)) {
- if (!mir_wstrcmpi(psr->email.w, dbv.pwszVal)) {
- // remove the flag for not on list and hidden, thus make the contact visible
- // and add them on the list
- if (!Contact::OnList(hContact)) {
- Contact::PutOnList(hContact);
- Contact::Hide(hContact, false);
- }
- db_free(&dbv);
- // contact is added, function quitting
- return (INT_PTR)hContact;
+ for (auto &hContact : AccContacts()) {
+ DBVARIANT dbv;
+ // check ID to see if the contact already exist in the database
+ if (!getWString(hContact, "ID", &dbv)) {
+ if (!mir_wstrcmpi(psr->id.w, dbv.pwszVal)) {
+ // remove the flag for not on list and hidden, thus make the contact visible
+ // and add them on the list
+ if (!Contact::OnList(hContact)) {
+ Contact::PutOnList(hContact);
+ Contact::Hide(hContact, false);
}
db_free(&dbv);
+ // contact is added, function quitting
+ return (INT_PTR)hContact;
}
+ db_free(&dbv);
}
}
// if contact with the same ID was not found, add it
- if (psr->cbSize < sizeof(PROTOSEARCHRESULT)) return 0;
+ if (psr->cbSize < sizeof(PROTOSEARCHRESULT))
+ return 0;
+
MCONTACT hContact = db_add_contact();
- Proto_AddToContact(hContact, MODULENAME);
+ Proto_AddToContact(hContact, m_szModuleName);
// suppress online notification for the new contact
Ignore_Ignore(hContact, IGNOREEVENT_USERONLINE);
- // set contact info and settings
- wchar_t svc[256];
- wcsncpy(svc, psr->email.w, _countof(svc)); svc[_countof(svc) - 1] = 0;
- GetSvc(svc);
- // 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);
- }
- else { // if no valid service is found, create empty strings for MapURL and InfoURL
- g_plugin.setString(hContact, "MapURL", "");
- g_plugin.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->id.w);
+ setWString(hContact, "Nick", psr->nick.w);
+ if (psr->firstName.w)
+ setWString(hContact, "FirstName", psr->firstName.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));
+ wcsncpy_s(opt.Default, getMStringW(hContact, "ID"), _countof(opt.Default));
opt.DefStn = hContact;
- if (!g_plugin.getWString(hContact, "Nick", &dbv)) {
+ ptrW wszNick(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);
+
+ 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()
+bool CWeatherProto::CheckSearch()
{
- if (UpdateListHead != nullptr) {
+ if (!m_updateList.empty()) {
MessageBox(nullptr, TranslateT("Please try again after weather update is completed."), TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR);
- return FALSE;
+ return false;
}
- return TRUE;
+ 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)
{
@@ -195,238 +164,67 @@ 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
- sttSearchId = 1;
- GetDlgItemText((HWND)lParam, IDC_SEARCHCITY, name1, _countof(name1));
+ // broadcast the result
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)sttSearchId);
- // search for the weather station using a thread
- mir_forkthread(NameSearchTimerProc);
- return sttSearchId;
+ // exit the search
+ sttSearchId = -1;
}
-// ============ SEARCH FOR A WEATHER STATION USING ID ============
-
-// Seaching station ID from a single weather service (Threaded)
-// sID = search string for the station ID
-// searchId = -1
-// sData = the ID search data for that particular weather service
-// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather)
-int IDSearchProc(wchar_t *sID, const int searchId, WIIDSEARCH *sData, wchar_t *svc, wchar_t *svcname)
+HANDLE CWeatherProto::SearchAdvanced(MWindow hwndOwner)
{
- wchar_t str[MAX_DATA_LEN], newID[MAX_DATA_LEN];
-
- if (sData->Available) {
- char loc[255];
- wchar_t *szData = nullptr;
-
- // load the page
- mir_snprintf(loc, sData->SearchURL, _T2A(sID).get());
- BOOL bFound = (InternetDownloadFile(loc, nullptr, nullptr, &szData) == 0);
- if (bFound) {
- wchar_t *szInfo = szData;
-
- // not found
- if (wcsstr(szInfo, sData->NotFoundStr) == nullptr)
- GetDataValue(&sData->Name, str, &szInfo);
- }
-
- mir_free(szData);
- // Station not found exit
- if (!bFound)
- return 1;
- }
-
- // give no station name but only ID if the search is unavailable
- else wcsncpy(str, TranslateT("<Enter station name here>"), MAX_DATA_LEN - 1);
- mir_snwprintf(newID, L"%s/%s", svc, sID);
+ if (sttSearchId != -1)
+ return 0; //only one search at a time
- // set the search result and broadcast it
- PROTOSEARCHRESULT psr = { sizeof(psr) };
- psr.flags = PSR_UNICODE;
- psr.nick.w = str;
- psr.firstName.w = L" ";
- psr.lastName.w = svcname;
- psr.email.w = newID;
- ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ sttSearchId = 1;
+ GetDlgItemText(hwndOwner, IDC_SEARCHCITY, name1, _countof(name1));
- return 0;
+ // search for the weather station using a thread
+ ForkThread(&CWeatherProto::NameSearchThread);
+ return (HANDLE)sttSearchId;
}
-// 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, int searchId)
{
- // for a normal ID search (ID != #)
- if (mir_wstrcmp(sID, L"#")) {
- WIDATALIST *Item = WIHead;
-
- // search every weather service using the search station ID
- while (Item != nullptr) {
- IDSearchProc(sID, searchId, &Item->Data.IDSearch, Item->Data.InternalName, Item->Data.DisplayName);
- Item = Item->next;
- }
- }
- // if the station ID is #, return a dummy result and quit the funciton
- else {
- // return an empty contact on "#"
+ WeatherReply reply(RunQuery(sID, 0));
+ if (reply) {
+ auto &data = reply.data();
+ CMStringW id(FORMAT, L"%lf, %lf", data["latitude"].as_float(), data["longitude"].as_float());
+ CMStringW address1 = data["address"].as_mstring();
+ CMStringW address2 = data["resolvedAddress"].as_mstring();
+
PROTOSEARCHRESULT psr = { sizeof(psr) };
psr.flags = PSR_UNICODE;
- psr.nick.w = TranslateT("<Enter station name here>"); // to be entered
- psr.firstName.w = L" ";
+ psr.email.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);
- }
-
- 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)
-{
- wchar_t Name[MAX_DATA_LEN], str[MAX_DATA_LEN], sID[MAX_DATA_LEN], *szData = nullptr, *search;
-
- // replace spaces with %20
- char loc[256];
- T2Utf szSearchName(name);
- mir_snprintf(loc, sData->SearchURL, mir_urlEncode(szSearchName).c_str());
- if (InternetDownloadFile(loc, nullptr, nullptr, &szData) == 0) {
- wchar_t *szInfo = szData;
- search = wcsstr(szInfo, sData->NotFoundStr); // determine if data is available
- if (search == nullptr) { // if data is found
- // test if it is single result
- if (sData->Single.Available && sData->Multiple.Available)
- search = wcsstr(szInfo, sData->SingleStr);
- // for single result
- if (sData->Single.Available && (search != nullptr || !sData->Multiple.Available)) { // single result
- // if station ID appears first in the downloaded data
- if (!mir_wstrcmpi(sData->Single.First, L"ID")) {
- GetDataValue(&sData->Single.ID, str, &szInfo);
- mir_snwprintf(sID, L"%s/%s", svc, str);
- GetDataValue(&sData->Single.Name, Name, &szInfo);
- }
- // if station name appears first in the downloaded data
- else if (!mir_wstrcmpi(sData->Single.First, L"NAME")) {
- GetDataValue(&sData->Single.Name, Name, &szInfo);
- GetDataValue(&sData->Single.ID, str, &szInfo);
- mir_snwprintf(sID, L"%s/%s", svc, str);
- }
- else
- str[0] = 0;
-
- // if no station ID is obtained, quit the search
- if (str[0] == 0) {
- mir_free(szData);
- return 1;
- }
-
- // if can't get the name, use the search string as name
- if (Name[0] == 0)
- wcsncpy(Name, name, _countof(Name));
-
- // set the data and broadcast it
- PROTOSEARCHRESULT psr = { sizeof(psr) };
- psr.flags = PSR_UNICODE;
- psr.nick.w = Name;
- psr.firstName.w = L" ";
- psr.lastName.w = svcname;
- psr.email.w = sID;
- psr.id.w = sID;
- ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
- mir_free(szData);
- return 0;
- }
- // for multiple result
- else if (sData->Multiple.Available) { // multiple results
- // search for the next occurrence of the string
- while (true) {
- // if station ID appears first in the downloaded data
- if (!mir_wstrcmpi(sData->Multiple.First, L"ID")) {
- GetDataValue(&sData->Multiple.ID, str, &szInfo);
- mir_snwprintf(sID, L"%s/%s", svc, str);
- GetDataValue(&sData->Multiple.Name, Name, &szInfo);
- }
- // if station name appears first in the downloaded data
- else if (!mir_wstrcmpi(sData->Multiple.First, L"NAME")) {
- GetDataValue(&sData->Multiple.Name, Name, &szInfo);
- GetDataValue(&sData->Multiple.ID, str, &szInfo);
- mir_snwprintf(sID, L"%s/%s", svc, str);
- }
- else
- break;
-
- // if no station ID is obtained, search completed and quit the search
- if (str[0] == 0)
- break;
-
- // if can't get the name, use the search string as name
- if (Name[0] == 0)
- wcsncpy(Name, name, _countof(Name));
-
- PROTOSEARCHRESULT psr = { sizeof(psr) };
- psr.flags = PSR_UNICODE;
- psr.nick.w = Name;
- psr.firstName.w = L"";
- psr.lastName.w = svcname;
- psr.email.w = sID;
- psr.id.w = sID;
- ProtoBroadcastAck(MODULENAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
- }
- }
- }
-
- mir_free(szData);
- return 0;
- }
-
- mir_free(szData);
- return 1;
-}
-
-// name search (Threaded)
-// name: the station name to search for
-// searchId: don't change
-// return 0 if no error
-int NameSearch(wchar_t *name, const int searchId)
-{
- // search every weather service using the search station name
- WIDATALIST *Item = WIHead;
- while (Item != nullptr) {
- if (Item->Data.NameSearch.Single.Available || Item->Data.NameSearch.Multiple.Available)
- NameSearchProc(name, searchId, &Item->Data.NameSearch, Item->Data.InternalName, Item->Data.DisplayName);
- Item = Item->next;
+ psr.id.w = id.GetBuffer();
+ psr.nick.w = address1.GetBuffer();
+ psr.firstName.w = address2.GetBuffer();
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
}
return 0;
}
-// ======================MENU ITEM FUNCTION ============
-
-// add a new weather station via find/add dialog
-int WeatherAdd(WPARAM, LPARAM)
+int CWeatherProto::NameSearch(wchar_t *name, int searchId)
{
- db_set_s(0, "FindAdd", "LastSearched", "Weather");
- CallService(MS_FINDADD_FINDADD, 0, 0);
- return 0;
+ return IDSearch(name, searchId);
}
diff --git a/protocols/Weather/src/weather_contacts.cpp b/protocols/Weather/src/weather_contacts.cpp
index 2833521275..2f5a08f4ef 100644
--- a/protocols/Weather/src/weather_contacts.cpp
+++ b/protocols/Weather/src/weather_contacts.cpp
@@ -25,23 +25,20 @@ the contact.
#include "stdafx.h"
-static void OpenUrl(wchar_t *format, wchar_t *id)
+bool CWeatherProto::IsMyContact(MCONTACT hContact)
{
- wchar_t loc[512];
- GetID(id);
- mir_snwprintf(loc, format, id);
- Utils_OpenUrlW(loc);
+ return hContact && !mir_strcmp(m_szModuleName, Proto_GetBaseAccountName(hContact));
}
-//============ BASIC CONTACTS FUNCTIONS AND LINKS ============
-
+/////////////////////////////////////////////////////////////////////////////////////////
// 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;
- if (!g_plugin.getWString(wParam, "Log", &dbv)) {
+ if (!getWString(wParam, "Log", &dbv)) {
if (dbv.pszVal[0] != 0)
ShellExecute((HWND)lParam, L"open", dbv.pwszVal, L"", L"", SW_SHOW);
db_free(&dbv);
@@ -52,352 +49,203 @@ 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 hContact, 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, MODULENAME, "InfoURL", loc2, _countof(loc2)) || loc2[0] == 0) {
- MessageBox(nullptr, TranslateT("The URL for complete forecast has not been set. You can set it from the Edit Settings dialog."), TranslateT("Weather Protocol"), MB_ICONINFORMATION);
- return 1;
- }
+ CMStringW wszID(getMStringW(hContact, "ID"));
+ if (!wszID.IsEmpty()) {
// set the url and open the webpage
- OpenUrl(loc2, id);
+ CMStringA szUrl("https://www.visualcrossing.com/weather-forecast/" + mir_urlEncode(T2Utf(wszID)) + "/metric");
+ Utils_OpenUrl(szUrl);
}
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, MODULENAME, "MapURL", loc2, _countof(loc2)) || loc2[0] == 0) {
- MessageBox(nullptr, TranslateT("The URL for weather map has not been set. You can set it from the Edit Settings dialog."), TranslateT("Weather Protocol"), MB_ICONINFORMATION);
- return 1;
- }
+INT_PTR CWeatherProto::WeatherMap(WPARAM hContact, LPARAM)
+{
+ CMStringW wszID(getMStringW(hContact, "ID"));
+ if (!wszID.IsEmpty()) {
// set the url and open the webpage
- OpenUrl(loc2, id);
+ CMStringA szUrl("https://www.visualcrossing.com/weather-history/" + mir_urlEncode(T2Utf(wszID)) + "/metric");
+ Utils_OpenUrl(szUrl);
}
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)
+
+class CEditDlg : public CWeatherDlgBase
{
- DBVARIANT dbv;
- 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);
-
- 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);
+ CCtrlEdit edtName;
+ CCtrlButton btnExternal, btnChange;
+ CCtrlMButton btnBrowse;
+
+ wchar_t str[MAX_DATA_LEN], str2[256];
+
+public:
+ CEditDlg(CWeatherProto *ppro, MCONTACT _1) :
+ CWeatherDlgBase(ppro, IDD_EDIT),
+ hContact(_1),
+ edtName(this, IDC_NAME),
+ btnBrowse(this, IDC_BROWSE, SKINICON_EVENT_FILE, LPGEN("Browse")),
+ btnChange(this, IDC_CHANGE),
+ btnExternal(this, IDC_External)
+ {
+ edtName.OnChange = Callback(this, &CEditDlg::onChanged_Name);
+
+ btnBrowse.OnClick = Callback(this, &CEditDlg::onClick_Browse);
+ btnChange.OnClick = Callback(this, &CEditDlg::onClick_Change);
+ btnExternal.OnClick = Callback(this, &CEditDlg::onClick_External);
+ }
+
+ bool OnInitDialog() override
+ {
// 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);
+ btnBrowse.MakeFlat();
// 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);
-
- if (!g_plugin.getWString(hContact, "InfoURL", &dbv)) {
- SetDlgItemText(hwndDlg, IDC_IURL, dbv.pwszVal);
- db_free(&dbv);
- }
- if (!g_plugin.getWString(hContact, "MapURL", &dbv)) {
- SetDlgItemText(hwndDlg, IDC_MURL, dbv.pwszVal);
- db_free(&dbv);
- }
+ 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);
// 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_RestoreWindowPositionNoSize(m_hwnd, NULL, MODULENAME, "EditSetting_");
+ ShowWindow(m_hwnd, SW_SHOW);
+ return true;
+ }
- // 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));
- 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));
- 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;
+ void OnDestroy() override
+ {
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
+
+ WindowList_Remove(hWindowList, m_hwnd);
+ Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "EditSetting_");
+ }
+
+ 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_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;
+
+ onClick_Browse(0);
+ }
+
+ void onClick_Browse(CCtrlButton *)
+ {
+ // browse for the external log file
+ GetDlgItemText(m_hwnd, IDC_LOG, str, _countof(str));
+
+ // Initialize OPENFILENAME
+ OPENFILENAME ofn = {};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = m_hwnd;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = _countof(str);
+
+ // set filters
+ wchar_t filter[256];
+ 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_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));
+ m_proto->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;
+ m_proto->setWString("Default", m_proto->opt.Default);
+ }
+
+ wchar_t city[256];
+ GetDlgItemText(m_hwnd, IDC_NAME, city, _countof(city));
+ m_proto->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);
}
- 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;
+ else m_proto->delSetting(hContact, "Log");
+
+ m_proto->setWord(hContact, "Status", ID_STATUS_OFFLINE);
+ m_proto->setWord(hContact, "StatusIcon", -1);
+ m_proto->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
+ m_proto->setString(hContact, "LastCondition", "None");
+ m_proto->UpdateSingleStation(hContact, 0);
}
- return FALSE;
-}
+};
-// show edit settings dialog
-// wParam = current contact
-INT_PTR EditSettings(WPARAM wParam, LPARAM)
+INT_PTR CWeatherProto::EditSettings(WPARAM wParam, LPARAM)
{
HWND hEditDlg = WindowList_Find(hWindowList, wParam);
@@ -410,34 +258,29 @@ 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)
+{
+ RemoveFrameWindow(hContact);
// exit this function if it is not default station
- ptrW tszID(g_plugin.getWStringA(wParam, "ID"));
- if (tszID != NULL)
- if (mir_wstrcmp(tszID, opt.Default))
- return 0;
+ ptrW tszID(getWStringA(hContact, "ID"));
+ if (mir_wstrcmp(tszID, opt.Default))
+ return true;
// 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,27 +288,21 @@ 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(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
+ setWString("Default", opt.Default);
+ return true;
}
}
// got here if no more weather station left
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;
+ setWString("Default", opt.Default);
+ return true;
}
diff --git a/protocols/Weather/src/weather_conv.cpp b/protocols/Weather/src/weather_conv.cpp
index 649ca37a91..4d2c79f0ce 100644
--- a/protocols/Weather/src/weather_conv.cpp
+++ b/protocols/Weather/src/weather_conv.cpp
@@ -25,12 +25,12 @@ 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 is_number(const wchar_t *s)
{
BOOL tag = FALSE;
// looking character by character
@@ -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,22 +69,18 @@ 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(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str)
{
// unit can be C, F
double temp;
wchar_t tstr[20];
- TrimString(tempchar);
- if (tempchar[0] == '-' && tempchar[1] == ' ')
- memmove(&tempchar[1], &tempchar[2], sizeof(wchar_t) * (mir_wstrlen(&tempchar[2]) + 1));
-
// quit if the value obtained is N/A or not a number
if (!mir_wstrcmp(tempchar, NODATA) || !mir_wstrcmp(tempchar, L"N/A")) {
mir_wstrcpy(str, tempchar);
@@ -123,11 +119,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(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str)
{
// unit can be kPa, hPa, mb, in, mm, torr
double tempunit = 0, output;
@@ -180,11 +178,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(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str)
{
// unit can be km/h, mph, m/s, knots
double tempunit;
@@ -229,11 +229,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(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str)
{
// unit can be km, miles
double tempunit = 0, output;
@@ -269,11 +271,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(const wchar_t *tempchar, const wchar_t *unit, wchar_t *str)
{
// unit can be ft, m
double tempunit = 0, output;
@@ -309,73 +313,9 @@ 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
-// return value = status for the icon (ONLINE, OFFLINE, etc)
-
-static const wchar_t *statusStr[MAX_COND] = { L"Lightning", L"Fog", L"Snow", L"Rain", L"Partly Cloudy", L"Cloudy", L"Sunny", L"N/A", L"Rain Shower", L"Snow Shower"};
-static const uint16_t statusValue[MAX_COND] = { LIGHT, FOG, SNOW, RAIN, PCLOUDY, CLOUDY, SUNNY, NA, RSHOWER, SSHOWER };
-
-uint16_t GetIcon(const wchar_t *cond, WIDATA *Data)
-{
- // set the icon using ini
- for (int i = 0; i < _countof(statusValue); i++)
- if (IsContainedInCondList(cond, &Data->CondList[i]))
- return statusValue[i];
-
- // internal detection
- if (wcsstr(cond, L"mainy sunny") || wcsstr(cond, L"mainy clear") || wcsstr(cond, L"partly sunny") || wcsstr(cond, L"partly cloudy") || wcsstr(cond, L"mostly") || wcsstr(cond, L"clouds"))
- return PCLOUDY;
-
- if (wcsstr(cond, L"sunny") || wcsstr(cond, L"clear") || wcsstr(cond, L"fair"))
- return SUNNY;
-
- if (wcsstr(cond, L"thunder") || wcsstr(cond, L"t-storm"))
- return LIGHT;
-
- if (wcsstr(cond, L"cloud") || wcsstr(cond, L"overcast"))
- return CLOUDY;
-
- if (wcsstr(cond, L"fog") || wcsstr(cond, L"mist") || wcsstr(cond, L"smoke") || wcsstr(cond, L"sand") || wcsstr(cond, L"dust") || wcsstr(cond, L"haze"))
- return FOG;
-
- if (wcsstr(cond, L"snow shower"))
- return SSHOWER;
-
- if (wcsstr(cond, L"snow") || wcsstr(cond, L"ice") || wcsstr(cond, L"freezing") || wcsstr(cond, L"wintry"))
- return SNOW;
-
- if (wcsstr(cond, L"rain shower"))
- return RSHOWER;
-
- if (wcsstr(cond, L"drizzle") || wcsstr(cond, L"rain"))
- return RAIN;
-
- // set the icon using langpack
- for (int i = 0; i < _countof(statusStr)-1; i++) {
- wchar_t LangPackStr[64], LangPackStr1[128];
- int j = 0;
- do {
- j++;
- // using the format _T("# Weather <condition name> <counter> #"
- mir_snwprintf(LangPackStr, L"# Weather %s %i #", statusStr[i], j);
- wcsncpy_s(LangPackStr1, TranslateW(LangPackStr), _TRUNCATE);
- CharLowerBuff(LangPackStr1, (uint32_t)mir_wstrlen(LangPackStr1));
- if (wcsstr(cond, LangPackStr1) != nullptr)
- return statusValue[i];
- // loop until the translation string exists (ie, the translated string is differ from original)
- } while (mir_wstrcmp(TranslateW(LangPackStr), LangPackStr));
- }
-
- return NA;
-}
-
-//============ STRING CONVERSIONS ============
-//
+/////////////////////////////////////////////////////////////////////////////////////////
// this function convert the string to the format with 1 upper case followed by lower case char
+
void CaseConv(wchar_t *str)
{
bool nextUp = true;
@@ -391,9 +331,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 +355,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,10 +372,12 @@ 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* GetSearchStr(char *dis)
{
char *pstr = dis;
size_t len = mir_strlen(dis);
@@ -448,13 +393,13 @@ 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)
+
+CMStringW GetDisplay(WEATHERINFO *w, const wchar_t *dis)
{
wchar_t lpzDate[32], chr;
char name[256], temp[2];
@@ -462,7 +407,7 @@ wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t *str)
size_t i;
// Clear the string
- str[0] = 0;
+ CMStringW str;
// looking character by character
for (i = 0; i < mir_wstrlen(dis); i++) {
@@ -471,10 +416,10 @@ wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t *str)
i++;
chr = dis[i];
switch (chr) {
- case '%': mir_wstrcat(str, L"%"); break;
- case 't': mir_wstrcat(str, L"\t"); break;
- case 'n': mir_wstrcat(str, L"\r\n"); break;
- case '\\': mir_wstrcat(str, L"\\"); break;
+ case '%': str.Append(L"%"); break;
+ case 't': str.Append(L"\t"); break;
+ case 'n': str.Append(L"\r\n"); break;
+ case '\\': str.Append(L"\\"); break;
}
}
@@ -485,29 +430,31 @@ wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t *str)
// turn capitalized characters to small case
if (chr < 'a' && chr != '[' && chr != '%') chr = (char)((int)chr + 32);
switch (chr) {
- case 'c': mir_wstrcat(str, w->cond); break;
+ case 'c': str.Append(w->cond); break;
case 'd': // get the current date
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, nullptr, nullptr, lpzDate, _countof(lpzDate));
- mir_wstrcat(str, lpzDate); break;
- case 'e': mir_wstrcat(str, w->dewpoint); break;
- case 'f': mir_wstrcat(str, w->feel); break;
- case 'h': mir_wstrcat(str, w->high); break;
- case 'i': mir_wstrcat(str, w->winddir); break;
- case 'l': mir_wstrcat(str, w->low); break;
- case 'm': mir_wstrcat(str, w->humid); break;
- case 'n': mir_wstrcat(str, w->city); break;
- case 'p': mir_wstrcat(str, w->pressure); break;
- case 'r': mir_wstrcat(str, w->sunrise); break;
- case 's': mir_wstrcat(str, w->id); break;
- case 't': mir_wstrcat(str, w->temp); break;
+ str.Append(lpzDate); break;
+ case 'e': str.Append(w->dewpoint); break;
+ case 'f': str.Append(w->feel); break;
+ case 'h': str.Append(w->high); break;
+ case 'i': str.Append(w->winddir); break;
+ case 'l': str.Append(w->low); break;
+ case 'm': str.Append(w->humid); break;
+ case 'n': str.Append(w->city); break;
+ case 'p': str.Append(w->pressure); break;
+ case 'r': str.Append(w->sunrise); break;
+ case 's': str.Append(w->id); break;
+ case 't': str.Append(w->temp); break;
case 'u':
- if (mir_wstrcmp(w->update, NODATA)) mir_wstrcat(str, w->update);
- else mir_wstrcat(str, TranslateT("<unknown time>"));
+ if (mir_wstrcmp(w->update, NODATA))
+ str.Append(w->update);
+ else
+ str.Append(TranslateT("<unknown time>"));
break;
- case 'v': mir_wstrcat(str, w->vis); break;
- case 'w': mir_wstrcat(str, w->wind); break;
- case 'y': mir_wstrcat(str, w->sunset); break;
- case '%': mir_wstrcat(str, L"%"); break;
+ case 'v': str.Append(w->vis); break;
+ case 'w': str.Append(w->wind); break;
+ case 'y': str.Append(w->sunset); break;
+ case '%': str.Append(L"%"); break;
case '[': // custom variables
i++;
name[0] = 0;
@@ -519,90 +466,77 @@ wchar_t *GetDisplay(WEATHERINFO *w, const wchar_t *dis, wchar_t *str)
// access the database to get its value
if (!db_get_ws(w->hContact, WEATHERCONDITION, name, &dbv)) {
if (dbv.pwszVal != TranslateW(NODATA) && dbv.pwszVal != TranslateT("<Error>"))
- mir_wstrcat(str, dbv.pwszVal);
+ str.Append(dbv.pwszVal);
db_free(&dbv);
}
break;
}
}
// if the character is not a variable, write the original character to the new string
- else {
- mir_snwprintf(lpzDate, L"%c", dis[i]);
- mir_wstrcat(str, lpzDate);
- }
+ else str.AppendChar(dis[i]);
}
return str;
}
-wchar_t svcReturnText[MAX_TEXT_SIZE];
-INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam)
-{
- WEATHERINFO winfo = LoadWeatherInfo(wParam);
- 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, '/');
- if (chop != nullptr)
- *chop = '\0';
- else
- pszID[0] = 0;
-}
-
-// get the id use for update without the service internal name
-// mod/id <- the id part
-// pszID = original 2-part id, return the single part id
-void GetID(wchar_t *pszID)
-{
- wchar_t *chop = wcschr(pszID, '/');
- if (chop != nullptr)
- mir_wstrcpy(pszID, chop + 1);
- else
- pszID[0] = 0;
-}
-
-//============ WEATHER ERROR CODE ============
-//
+/////////////////////////////////////////////////////////////////////////////////////////
// Get the text when an error code is specified
// code = the error code obtained when updating weather
// str = the string for the error
-//
+
wchar_t *GetError(int code)
{
wchar_t *str, str2[100];
switch (code) {
- case 10: str = E10; break;
- case 11: str = E11; break;
- case 12: str = E12; break;
- case 20: str = E20; break;
- case 30: str = E30; break;
- case 40: str = E40; break;
- case 42: str = E42; break;
- case 43: str = E43; break;
- case 99: str = E99; break;
- case 204: str = E204; break;
- case 301: str = E301; break;
- case 305: str = E305; break;
- case 307: str = E307; break;
- case 400: str = E400; break;
- case 401: str = E401; break;
- case 402: str = E402; break;
- case 403: str = E403; break;
- case 404: str = E404; break;
- case 405: str = E405; break;
- case 407: str = E407; break;
- case 410: str = E410; break;
- case 500: str = E500; break;
- case 502: str = E502; break;
- case 503: str = E503; break;
- case 504: str = E504; break;
+ case 10: str = TranslateT("Invalid ID format, missing \"/\" (10)"); break;
+ case 11: str = TranslateT("Invalid service (11)"); break;
+ case 12: str = TranslateT("Invalid station (12)"); break;
+ case 20: str = TranslateT("Weather service ini for this station is not found (20)"); break;
+ case 30: str = TranslateT("Netlib error - check your internet connection (30)"); break;
+ case 40: str = TranslateT("Empty data is retrieved (40)"); break;
+ case 42: str = TranslateT("Document not found (42)"); break;
+ case 43: str = TranslateT("Document too short to contain any weather data (43)"); break;
+ case 99: str = TranslateT("Unknown error (99)"); break;
+ // 100 Continue
+ // 101 Switching Protocols
+ // 200 OK
+ // 201 Created
+ // 202 Accepted
+ // 203 Non-Authoritative Information
+ case 204: str = TranslateT("HTTP Error: No content (204)"); break;
+ // 205 Reset Content
+ // 206 Partial Content
+ // 300 Multiple Choices
+ case 301: str = TranslateT("HTTP Error: Data moved (301)"); break;
+ // 302 Found
+ // 303 See Other
+ // 304 Not Modified
+ case 305: str = TranslateT("HTTP Error: Use proxy (305)"); break;
+ case 307: str = TranslateT("HTTP Error: Temporary redirect (307)"); break;
+ case 400: str = TranslateT("HTTP Error: Bad request (400)"); break;
+ case 401: str = TranslateT("HTTP Error: Unauthorized (401)"); break;
+ case 402: str = TranslateT("HTTP Error: Payment required (402)"); break;
+ case 403: str = TranslateT("HTTP Error: Forbidden (403)"); break;
+ case 404: str = TranslateT("HTTP Error: Not found (404)"); break;
+ case 405: str = TranslateT("HTTP Error: Method not allowed (405)"); break;
+ // 406 Not Acceptable
+ case 407: str = TranslateT("HTTP Error: Proxy authentication required (407)"); break;
+ // 408 Request Timeout
+ // 409 Conflict
+ case 410: str = TranslateT("HTTP Error: Gone (410)"); break;
+ // 411 Length Required
+ // 412 Precondition Failed
+ // 413 Request Entity Too Large
+ // 414 Request-URI Too Long
+ // 415 Unsupported Media Type
+ // 416 Requested Range Not Satisfiable
+ // 417 Expectation Failed
+ case 500: str = TranslateT("HTTP Error: Internal server error (500)"); break;
+ // 501 Not Implemented
+ case 502: str = TranslateT("HTTP Error: Bad gateway (502)"); break;
+ case 503: str = TranslateT("HTTP Error: Service unavailable (503)"); break;
+ case 504: str = TranslateT("HTTP Error: Gateway timeout (504)"); break;
+ // 505 HTTP Version Not Supported
default:
mir_snwprintf(str2, TranslateT("HTTP Error %i"), code);
str = str2;
diff --git a/protocols/Weather/src/weather_data.cpp b/protocols/Weather/src/weather_data.cpp
index 0f3cf9ccc9..76e50ca139 100644
--- a/protocols/Weather/src/weather_data.cpp
+++ b/protocols/Weather/src/weather_data.cpp
@@ -25,31 +25,21 @@ 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
- if (db_get_wstatic(hContact, MODULENAME, "ID", id, 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)
+
+WEATHERINFO CWeatherProto::LoadWeatherInfo(MCONTACT hContact)
{
// obtaining values from the DB
// assuming station ID must exist at all time, but others does not have to
// if the string is not found in database, a value of "N/A" is stored in the field
WEATHERINFO winfo;
winfo.hContact = hContact;
- GetStationID(hContact, winfo.id, _countof(winfo.id));
+ wcsncpy_s(winfo.id, getMStringW(hContact, "ID"), _countof(winfo.id));
- if (db_get_wstatic(hContact, MODULENAME, "Nick", winfo.city, _countof(winfo.city)))
+ if (db_get_wstatic(hContact, m_szModuleName, "Nick", winfo.city, _countof(winfo.city)))
wcsncpy(winfo.city, NODATA, _countof(winfo.city) - 1);
if (db_get_wstatic(hContact, WEATHERCONDITION, "Update", winfo.update, _countof(winfo.update)))
wcsncpy(winfo.update, NODATA, _countof(winfo.update) - 1);
@@ -82,64 +72,47 @@ 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)) {
- size_t len = mir_strlen(setting) + 1;
- char *set = (char*)alloca(len + 1);
- *set = '#';
- memcpy(set + 1, setting, len);
-
- if (db_get_ws(hContact, WEATHERCONDITION, set, dbv))
- return 1;
- }
- return 0;
-}
-
-
-//============ 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_delete_module(hContact, WEATHERCONDITION);
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));
+ wcsncpy_s(opt.Default, getMStringW(hContact, "ID"), _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 +120,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,281 +134,132 @@ 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)
-{
- wchar_t str[MAX_DATA_LEN];
+/////////////////////////////////////////////////////////////////////////////////////////
- // convert the unit
- if (mir_wstrcmp(Data, TranslateT("<Error>")) && mir_wstrcmp(Data, NODATA) && mir_wstrcmp(Data, TranslateW(NODATA))) {
- // temperature
- if (!mir_wstrcmp(UpdateData->Name, L"Temperature") || !mir_wstrcmp(UpdateData->Name, L"High") ||
- !mir_wstrcmp(UpdateData->Name, L"Low") || !mir_wstrcmp(UpdateData->Name, L"Feel") ||
- !mir_wstrcmp(UpdateData->Name, L"Dew point") ||
- !mir_wstrcmpi(UpdateData->Unit, L"C") || !mir_wstrcmpi(UpdateData->Unit, L"F") ||
- !mir_wstrcmpi(UpdateData->Unit, L"K")) {
- GetTemp(Data, UpdateData->Unit, str);
- mir_wstrcpy(Data, str);
- }
- // pressure
- else if (!mir_wstrcmp(UpdateData->Name, L"Pressure") || !mir_wstrcmpi(UpdateData->Unit, L"HPA") ||
- !mir_wstrcmpi(UpdateData->Unit, L"KPA") || !mir_wstrcmpi(UpdateData->Unit, L"MB") ||
- !mir_wstrcmpi(UpdateData->Unit, L"TORR") || !mir_wstrcmpi(UpdateData->Unit, L"IN") ||
- !mir_wstrcmpi(UpdateData->Unit, L"MM")) {
- GetPressure(Data, UpdateData->Unit, str);
- mir_wstrcpy(Data, str);
- }
- // speed
- else if (!mir_wstrcmp(UpdateData->Name, L"Wind Speed") || !mir_wstrcmpi(UpdateData->Unit, L"KM/H") ||
- !mir_wstrcmpi(UpdateData->Unit, L"M/S") || !mir_wstrcmpi(UpdateData->Unit, L"MPH") ||
- !mir_wstrcmpi(UpdateData->Unit, L"KNOTS")) {
- GetSpeed(Data, UpdateData->Unit, str);
- mir_wstrcpy(Data, str);
- }
- // visibility
- else if (!mir_wstrcmp(UpdateData->Name, L"Visibility") || !mir_wstrcmpi(UpdateData->Unit, L"KM") ||
- !mir_wstrcmpi(UpdateData->Unit, L"MILES")) {
- GetDist(Data, UpdateData->Unit, str);
- mir_wstrcpy(Data, str);
- }
- // elevation
- else if (!mir_wstrcmp(UpdateData->Name, L"Elevation") || !mir_wstrcmpi(UpdateData->Unit, L"FT") ||
- !mir_wstrcmpi(UpdateData->Unit, L"M")) {
- GetElev(Data, UpdateData->Unit, str);
- mir_wstrcpy(Data, str);
- }
- // converting case for condition to the upper+lower format
- else if (!mir_wstrcmpi(UpdateData->Unit, L"COND"))
- CaseConv(Data);
- // degree sign
- else if (!mir_wstrcmpi(UpdateData->Unit, L"DEG")) {
- if (!opt.DoNotAppendUnit) mir_wstrcat(Data, opt.DegreeSign);
- }
- // percent sign
- else if (!mir_wstrcmpi(UpdateData->Unit, L"%")) {
- if (!opt.DoNotAppendUnit) mir_wstrcat(Data, L"%");
- }
- // truncating strings for day/month to 2 or 3 characters
- else if (!mir_wstrcmpi(UpdateData->Unit, L"DAY") || !mir_wstrcmpi(UpdateData->Unit, L"MONTH"))
- if (opt.dUnit > 1 && mir_wstrlen(Data) > opt.dUnit)
- Data[opt.dUnit] = '\0';
- }
-}
+static wchar_t rumbs[][16] = {
+ LPGENW("N"), LPGENW("NNE"), LPGENW("NE"), LPGENW("ENE"),
+ LPGENW("E"), LPGENW("ESE"), LPGENW("ES"), LPGENW("SSE"),
+ LPGENW("S"), LPGENW("SSW"), LPGENW("SW"), LPGENW("WSW"),
+ LPGENW("W"), LPGENW("WNW"), LPGENW("WN"), LPGENW("NNW")
+};
-//============ 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)
+static wchar_t *degree2str(double angle)
{
- wchar_t last = 0, current, *start, *end;
- unsigned startloc = 0, endloc = 0, respos = 0;
- BOOL tag = FALSE, symb = FALSE;
- wchar_t *szInfo = *szData;
-
- Data[0] = 0;
- // parse the data if available
- if (UpdateData->Start[0] == 0 && UpdateData->End[0] == 0) return;
- start = szInfo;
- // the start string must be found
- if (UpdateData->Start[0] != 0) {
- start = wcsstr(szInfo, UpdateData->Start);
- if (start != nullptr) {
- // set the starting location for getting data
- start += mir_wstrlen(UpdateData->Start);
- szInfo = start;
- }
- }
-
- // the end string must be found too
- if (UpdateData->End[0] != 0)
- end = wcsstr(szInfo, UpdateData->End);
- else
- end = wcschr(szInfo, ' ');
-
- if (end != nullptr) {
- // set the ending location
- startloc = 0;
- endloc = end - szInfo;
- end += mir_wstrlen(UpdateData->End);
- last = '\n';
- }
+ double a = 11.25;
- // ignore if not both of the string found - this prevent crashes
- if (start != nullptr && end != nullptr) {
- // begin reading the data from start location to end location
- // remove all HTML tag in between, as well as leading space, ending space,
- // multiple spaces, tabs, and return key
- while (startloc < endloc) {
- if (szInfo[startloc] == '<') tag = TRUE;
- else if (szInfo[startloc] == '&' &&
- (szInfo[startloc + 1] == ';' || szInfo[startloc + 2] == ';' || szInfo[startloc + 3] == ';' ||
- szInfo[startloc + 4] == ';' || szInfo[startloc + 5] == ';' || szInfo[startloc + 6] == ';')) {
- // ...but do NOT strip &minus;
- if ((endloc - startloc) > 7 && wcsncmp(szInfo + startloc, L"&minus;", 7) == 0) {
- Data[respos++] = '-';
- startloc += 7;
- continue;
- }
- symb = TRUE;
- }
- else if (szInfo[startloc] == '>') tag = FALSE;
- else if (szInfo[startloc] == ';') symb = FALSE;
- else {
- if (!tag && !symb) {
- current = szInfo[startloc];
- if (current == '\n' || current == '\t' || current == ' ' || current == '\r')
- current = ' ';
- if (current != ' ' || last != ' ') {
- if (last != '\n' && (respos != 0 || (respos == 0 && last != ' ')))
- Data[respos++] = last;
- last = current;
- }
- }
- }
- ++startloc;
- // prevent crashes if the string go over maximun length -> generate an error
- if (respos >= MAX_DATA_LEN) {
- if (opt.ShowWarnings && UpdateData->Name[0] != 0 && mir_wstrcmp(UpdateData->Name, L"Ignore")) {
- mir_snwprintf(Data, MAX_DATA_LEN, TranslateT("Error when obtaining data: %s"), UpdateData->Name);
- WPShowMessage(Data, SM_WARNING);
- }
- wcsncpy(Data, TranslateT("<Error>"), MAX_DATA_LEN);
- last = ' ';
- respos = MAX_DATA_LEN - 1;
- break;
- }
- }
+ for (int i = 0; i < _countof(rumbs); i++, a += 22.5)
+ if (angle < a)
+ return TranslateW(rumbs[i]);
- // get the last character
- if (last != ' ')
- Data[respos++] = last;
-
- // null terminate the string
- Data[respos] = 0;
-
- // convert the unit
- ConvertDataValue(UpdateData, Data);
-
- // remove the string before the data from szInfo
- szInfo = end;
- }
- *szData = szInfo;
-}
-
-//============ ALLOCATE SPACE AND COPY STRING ============
-//
-// copy a string into a new memory location
-// Data = the field the data is copied to
-// Value = the original string, the string where data is copied from
-
-bool g_bIsUtf = false;
-
-void wSetData(char *&Data, const char *Value)
-{
- if (Value[0] != 0)
- Data = mir_strdup(Value);
- else
- Data = "";
-}
-
-void wSetData(wchar_t *&Data, const char *Value)
-{
- if (Value[0] != 0)
- Data = (g_bIsUtf) ? mir_utf8decodeW(Value) : mir_a2u(Value);
- else
- Data = L"";
+ // area between 348.75 & 360 degrees
+ return TranslateT("N");
}
-void wSetData(wchar_t *&Data, const wchar_t *Value)
+void CWeatherProto::ConvertDataValue(WIDATAITEM *p)
{
- if (Value[0] != 0)
- Data = mir_wstrdup(Value);
- else
- Data = L"";
-}
+ wchar_t str[MAX_DATA_LEN];
-// A safer free function that free memory for a string
-// Data = the string occuping the data to be freed
-void wfree(char *&Data)
-{
- if (Data && mir_strlen(Data) > 0)
- mir_free(Data);
- Data = nullptr;
+ // temperature
+ if (!mir_wstrcmp(p->Name, L"Temperature") || !mir_wstrcmp(p->Name, L"High") ||
+ !mir_wstrcmp(p->Name, L"Low") || !mir_wstrcmp(p->Name, L"Feel") ||
+ !mir_wstrcmp(p->Name, L"Dew point") ||
+ !mir_wstrcmpi(p->Unit, L"C") || !mir_wstrcmpi(p->Unit, L"F") ||
+ !mir_wstrcmpi(p->Unit, L"K")) {
+ GetTemp(p->Value, p->Unit, str);
+ p->Value = str;
+ }
+ // pressure
+ else if (!mir_wstrcmp(p->Name, L"Pressure") || !mir_wstrcmpi(p->Unit, L"HPA") ||
+ !mir_wstrcmpi(p->Unit, L"KPA") || !mir_wstrcmpi(p->Unit, L"MB") ||
+ !mir_wstrcmpi(p->Unit, L"TORR") || !mir_wstrcmpi(p->Unit, L"IN") ||
+ !mir_wstrcmpi(p->Unit, L"MM")) {
+ GetPressure(p->Value, p->Unit, str);
+ p->Value = str;
+ }
+ // speed
+ else if (!mir_wstrcmp(p->Name, L"Wind Speed") || !mir_wstrcmpi(p->Unit, L"KM/H") ||
+ !mir_wstrcmpi(p->Unit, L"M/S") || !mir_wstrcmpi(p->Unit, L"MPH") ||
+ !mir_wstrcmpi(p->Unit, L"KNOTS")) {
+ GetSpeed(p->Value, p->Unit, str);
+ p->Value = str;
+ }
+ // visibility
+ else if (!mir_wstrcmp(p->Name, L"Visibility") || !mir_wstrcmpi(p->Unit, L"KM") ||
+ !mir_wstrcmpi(p->Unit, L"MILES")) {
+ GetDist(p->Value, p->Unit, str);
+ p->Value = str;
+ }
+ // elevation
+ else if (!mir_wstrcmp(p->Name, L"Elevation") || !mir_wstrcmpi(p->Unit, L"FT") ||
+ !mir_wstrcmpi(p->Unit, L"M")) {
+ GetElev(p->Value, p->Unit, str);
+ p->Value = str;
+ }
+ // convert degrees to compass
+ else if (!mir_wstrcmpi(p->Unit, L"GRAD")) {
+ p->Value = degree2str(_wtof(p->Value));
+ }
+ // degree sign
+ else if (!mir_wstrcmpi(p->Unit, L"DEG")) {
+ if (!opt.DoNotAppendUnit)
+ p->Value.Append(opt.DegreeSign);
+ }
+ // percent sign
+ else if (!mir_wstrcmpi(p->Unit, L"%")) {
+ if (!opt.DoNotAppendUnit)
+ p->Value.Append(L"%");
+ }
+ // truncating strings for day/month to 2 or 3 characters
+ else if (!mir_wstrcmpi(p->Unit, L"DAY") || !mir_wstrcmpi(p->Unit, L"MONTH"))
+ if (opt.dUnit > 1 && mir_wstrlen(p->Value) > opt.dUnit)
+ p->Value.SetAt(opt.dUnit, '\0');
}
-void wfree(wchar_t *&Data)
-{
- if (Data && mir_wstrlen(Data) > 0)
- mir_free(Data);
- Data = nullptr;
-}
+/////////////////////////////////////////////////////////////////////////////////////////
+// data query
-//============ 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)
+MHttpResponse* CWeatherProto::RunQuery(const wchar_t *id, int days)
{
- LIST<char> *pList = (LIST<char>*)lparam;
- pList->insert(mir_strdup(szSetting));
- return 0;
-}
+ wchar_t *pKey = m_szApiKey;
+ if (!mir_wstrlen(pKey)) {
+ WPShowMessage(TranslateT("You need to obtain the personal key and enter it in the account's Options dialog"), SM_WARNING);
+ return nullptr;
+ }
-// 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
- LIST<char> arSettings(10);
- db_enum_settings(hContact, GetWeatherDataFromDB, WEATHERCONDITION, &arSettings);
+ auto *pReq = new MHttpRequest(REQUEST_GET);
+ pReq->flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT;
+ pReq->m_szUrl = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/" + mir_urlEncode(T2Utf(id).get());
- // begin deleting settings
- auto T = arSettings.rev_iter();
- for (auto &str : T) {
- ptrW wszText(db_get_wsa(hContact, WEATHERCONDITION, str));
- if (wszText == nullptr)
- continue;
+ if (days) {
+ time_t today = time(0);
+ struct tm *p = localtime(&today);
+ pReq->m_szUrl.AppendFormat("/%04d-%02d-%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday);
- switch (Mode) {
- case WDBM_REMOVE:
- db_unset(hContact, WEATHERCONDITION, str);
- break;
+ today += 86400 * 7; // add one week
+ p = localtime(&today);
+ pReq->m_szUrl.AppendFormat("/%04d-%02d-%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday);
+ }
- case WDBM_DETAILDISPLAY:
- // skip the "WeatherInfo" variable
- if (!mir_strcmp(str, "WeatherInfo") || !mir_strcmp(str, "Ignore") || str[0] == '#')
- continue;
+ pReq << CHAR_PARAM("unitGroup", "metric") << WCHAR_PARAM("key", pKey) << CHAR_PARAM("contentType", "json");
+ if (days)
+ pReq << CHAR_PARAM("elements", "+elevation");
- _A2T strW(str);
- HWND hList = GetDlgItem((HWND)wParam, IDC_DATALIST);
- LV_ITEM lvi = {};
- lvi.mask = LVIF_TEXT | LVIF_PARAM;
- lvi.lParam = T.indexOf(&str);
- lvi.pszText = TranslateW(strW);
- lvi.iItem = ListView_InsertItem(hList, &lvi);
- lvi.pszText = wszText;
- ListView_SetItemText(hList, lvi.iItem, 1, wszText);
- break;
- }
- mir_free(str);
- }
+ auto *ret = Netlib_HttpTransaction(m_hNetlibUser, pReq);
+ delete pReq;
+ return ret;
}
diff --git a/protocols/Weather/src/weather_http.cpp b/protocols/Weather/src/weather_http.cpp
deleted file mode 100644
index 79c9efd21e..0000000000
--- a/protocols/Weather/src/weather_http.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-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 related to downloading weather info
-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)
-{
- if (userAgent == nullptr || userAgent[0] == 0)
- userAgent = NETLIB_USER_AGENT;
-
- // initialize the netlib request
- MHttpRequest nlhr(REQUEST_GET);
- nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT;
- nlhr.m_szUrl = szUrl;
- nlhr.AddHeader("User-Agent", userAgent);
- nlhr.AddHeader("Cache-Control", "no-cache");
- nlhr.AddHeader("Pragma", "no-cache");
- nlhr.AddHeader("Connection", "close");
- if (mir_strlen(cookie) > 0)
- nlhr.AddHeader("Cookie", cookie);
-
- // download the page
- NLHR_PTR nlhrReply(Netlib_HttpTransaction(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);
- // store the error code in szData
- mir_wstrcpy(*szData, L"NetLib error occurred!!");
- return NLHRF_REDIRECT;
- }
-
- // if the recieved code is 200 OK
- int result;
- if (nlhrReply->resultCode == 200) {
- if (!nlhrReply->body.IsEmpty()) {
- bool bIsUtf = false;
- result = 0;
-
- // allocate memory and save the retrieved data
- auto *pszHdr = nlhrReply->FindHeader("Content-Type");
- // look for Content-Type=utf-8 in header
- if (pszHdr && strstr(_strlwr(pszHdr), "utf-8"))
- bIsUtf = true;
- else {
- char *end = nlhrReply->body.GetBuffer();
- while (end) {
- // look for
- // <meta http-equiv="Content-Type" content="utf-8" />
- char *beg = strstr(end, "<meta");
- if (beg) {
- end = strchr(beg, '>');
- if (end) {
- char tmp = *end;
- *end = 0;
-
- char *method = strstr(beg, "http-equiv=\"");
- if (method && _strnicmp(method + 12, "Content-Type", 12) == 0 && strstr(method, "utf-8")) {
- bIsUtf = true;
- *end = tmp;
- break;
- }
- else *end = tmp;
- }
- }
- else
- break;
- }
- }
-
- wchar_t *retVal = nullptr;
- if (bIsUtf)
- retVal = mir_utf8decodeW(nlhrReply->body);
- if (retVal == nullptr)
- retVal = mir_a2u(nlhrReply->body);
- *szData = retVal;
- }
- else result = DATA_EMPTY;
- }
- // return error code if the recieved code is neither 200 OK nor 302 Moved
- else {
- // store the error code in szData
- CMStringW wszError(FORMAT, L"Error occured! HTTP Error: %i\n", nlhrReply->resultCode);
- *szData = wszError.Detach();
- result = nlhrReply->resultCode;
- }
-
- // 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_info.cpp b/protocols/Weather/src/weather_info.cpp
deleted file mode 100644
index 5e4c79fb4a..0000000000
--- a/protocols/Weather/src/weather_info.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-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 for displaying information for the
-ini files, as well as function that are used for debug purpose
-regrading the loading of ini contents
-*/
-
-#include "stdafx.h"
-
-//============ INI INFORMATION ============
-
-// List INI Information for all loaded INI files
-static void INIInfo(HWND hwndDlg)
-{
- wchar_t str[16];
- size_t memused = 0;
-
- HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST);
-
- ListView_DeleteAllItems(hIniList);
-
- LVITEM lvi = {};
- lvi.mask = LVIF_TEXT;
- lvi.iItem = 0;
- for (WIDATALIST *Item = WIHead; Item != nullptr; Item = Item->next) {
- // get the data for the ini file
- lvi.iSubItem = 0;
- lvi.pszText = Item->Data.InternalName;
- ListView_InsertItem(hIniList, &lvi);
- lvi.iSubItem = 1;
- lvi.pszText = Item->Data.Author;
- ListView_SetItem(hIniList, &lvi);
- lvi.iSubItem = 2;
- lvi.pszText = Item->Data.Version;
- ListView_SetItem(hIniList, &lvi);
- lvi.iSubItem = 3;
- lvi.pszText = GetINIVersionNum(Item->Data.InternalVer);
- ListView_SetItem(hIniList, &lvi);
- lvi.iSubItem = 4;
- lvi.pszText = _ltow(Item->Data.UpdateDataCount, str, 10);
- ListView_SetItem(hIniList, &lvi);
- lvi.iSubItem = 5;
- lvi.pszText = Item->Data.DisplayName;
- ListView_SetItem(hIniList, &lvi);
- lvi.iSubItem = 6;
- lvi.pszText = Item->Data.ShortFileName;
- ListView_SetItem(hIniList, &lvi);
-
- memused += Item->Data.MemUsed;
-
- ++lvi.iItem;
- }
- SetDlgItemText(hwndDlg, IDC_INICOUNT, _itow(lvi.iItem, str, 10));
- SetDlgItemText(hwndDlg, IDC_MEMUSED, _ltow((long)memused, str, 10));
-}
-
-struct
-{
- const wchar_t *name;
- unsigned size;
-}
-static columns[] =
-{
- { LPGENW("Name"), 70 },
- { LPGENW("Author"), 100 },
- { LPGENW("File Version"), 70 },
- { LPGENW("INI Version"), 70 },
- { LPGENW("Items"), 40 },
- { LPGENW("Display Name"), 200 },
- { LPGENW("File Name"), 150 },
-};
-
-WeatherMyDetailsDlg::WeatherMyDetailsDlg() :
- CUserInfoPageDlg(g_plugin, IDD_INFO),
- btnReload(this, IDC_RELOADINI)
-{
- btnReload.OnClick = Callback(this, &WeatherMyDetailsDlg::onClick_Reload);
-}
-
-bool WeatherMyDetailsDlg::OnInitDialog()
-{
- HWND hIniList = GetDlgItem(m_hwnd, IDC_INFOLIST);
-
- LVCOLUMN lvc = {};
- lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
- lvc.fmt = LVCFMT_LEFT;
- for (auto &it : columns) {
- lvc.iSubItem = int(&it - columns);
- lvc.pszText = TranslateW(it.name);
- lvc.cx = it.size;
- ListView_InsertColumn(hIniList, lvc.iSubItem, &lvc);
- }
-
- INIInfo(m_hwnd);
- return true;
-}
-
-void WeatherMyDetailsDlg::onClick_Reload(CCtrlButton*)
-{
- DestroyWIList();
- LoadWIData(true);
- INIInfo(m_hwnd);
-}
-
-// get the info of individual ini file
-// pszSvc = the internal name of the service to get the data
-
-wchar_t* GetINIVersionNum(int iVersion)
-{
- switch (iVersion) {
- case 1: return L"1.0";
- case 2: return L"1.1";
- case 3: return L"1.1a";
- case 4: return L"1.2";
- case 5: return L"1.3";
- case 6: return L"1.4";
- case 7: return L"1.5";
- }
- return L"";
-}
-
-void GetINIInfo(wchar_t *pszSvc)
-{
- CMStringW str;
- WIDATA *sData = GetWIData(pszSvc);
- // if the service does not exist among the loaded INI's
- if (sData == nullptr) {
- str.Format(TranslateT("The corresponding INI file for \"%s\" is not found."), pszSvc);
- }
- // if exist, get the information
- else {
- str.AppendFormat(TranslateT("Weather INI information for \"%s\":"), pszSvc);
- str += L"\n\n";
- str.AppendFormat(L"%s\t%s\n", TranslateT("Name:"), sData->DisplayName);
- str.AppendFormat(L"%s\t%s\n", TranslateT("Internal Name:"), sData->InternalName);
- str.AppendFormat(L"%s\t%s\n", TranslateT("Author:"), sData->Author);
- str.AppendFormat(L"%s\t%s\n", TranslateT("Version:"), sData->Version);
- str.AppendFormat(L"%s\t%s\n", TranslateT("INI Version:"), GetINIVersionNum(sData->InternalVer));
- str.AppendFormat(L"%s\t%s\n", TranslateT("File Name:"), sData->ShortFileName);
- str.AppendFormat(L"%s\t%i\n", TranslateT("Item Count:"), sData->UpdateDataCount);
- str.AppendFormat(L"%s\t%i %s\n\n", TranslateT("Memory Used:"), (int)sData->MemUsed, TranslateT("bytes"));
- str.AppendFormat(L"%s\n%s", TranslateT("Description:"), sData->Description);
- }
-
- MessageBox(nullptr, str, TranslateT("Weather INI information"), MB_OK | MB_ICONINFORMATION);
-}
-
-//============ DISPLAY A LIST FOR CUSTOM VARIABLES ============
-//
-// a message box for displaying the list of custom variables
-// can be found when click on "More" in text option dialog
-void MoreVarList(void)
-{
- // heading
- CMStringW str(TranslateT("Here is a list of custom variables that are currently available"));
- str += L"\n\n";
-
- // loop through all weather services to find custom variables
- bool bFirst = true;
- for (WIDATALIST *Item = WIHead; Item != nullptr; Item = Item->next) {
- // loop through all update items in a service
- for (WIDATAITEMLIST *WItem = Item->Data.UpdateData; WItem != nullptr; WItem = WItem->Next) {
- // the custom variable is defined as "%[<variable name>]"
- // ignore the "hi" item and hidden items
- if (mir_wstrcmp(WItem->Item.Name, L"Ignore") && WItem->Item.Name[0] != '#') {
- wchar_t tempstr[1024];
- mir_snwprintf(tempstr, L"%c[%s]", '%', WItem->Item.Name);
- auto *find = wcsstr(str, tempstr);
- // if the custom variable does not exist in the list, add it to the list
- if (find == nullptr) {
- if (bFirst)
- bFirst = false;
- else
- str += L", ";
- str += tempstr;
- }
- }
- }
- }
-
- // display the list in a message box
- MessageBox(nullptr, str, TranslateT("More Variables"), MB_OK | MB_ICONINFORMATION | MB_TOPMOST);
-}
diff --git a/protocols/Weather/src/weather_ini.cpp b/protocols/Weather/src/weather_ini.cpp
deleted file mode 100644
index 0929b06c1e..0000000000
--- a/protocols/Weather/src/weather_ini.cpp
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
-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 related to loading the reading the
-weather ini files and store them into memory. Also containing
-code for unloading and getting weather data from the ini settings.
-*/
-
-#include "stdafx.h"
-
-HWND hWndSetup;
-
-//============ DATA LIST (LINKED LIST) ============
-//
-// add an item into weather service data list
-// Data = the service data to be added to the list
-static void WIListAdd(WIDATA Data)
-{
- // create a new datalist item and point to the data
- WIDATALIST *newItem = (WIDATALIST*)mir_alloc(sizeof(WIDATALIST));
- newItem->Data = Data;
- // add to the linked list
- newItem->next = nullptr;
- if (WITail == nullptr) WIHead = newItem;
- else WITail->next = newItem;
- WITail = newItem;
-}
-
-// get the service data (from loaded ini file) by internal name
-// pszServ = internal name for the service
-// return value = the matching WIDATA struct for pszServ, NULL if no match found
-WIDATA* GetWIData(wchar_t *pszServ)
-{
- // loop through the list to find matching internal name
- for (WIDATALIST *Item = WIHead; Item != nullptr; Item = Item->next)
- // if internal name found, return the data
- if (mir_wstrcmp(Item->Data.InternalName, pszServ) == 0)
- return &Item->Data;
-
- // return NULL when no match found
- return nullptr;
-}
-
-//============ DATA ITEM LIST (LINKED LIST) ============
-//
-// add a new update item into the current list
-void WIItemListAdd(WIDATAITEM *DataItem, WIDATA *Data)
-{
- WIDATAITEMLIST *newItem = (WIDATAITEMLIST*)mir_alloc(sizeof(WIDATAITEMLIST));
- newItem->Item = *DataItem;
- newItem->Next = nullptr;
- if (Data->UpdateData == nullptr) Data->UpdateData = newItem;
- else Data->UpdateDataTail->Next = newItem;
- Data->UpdateDataTail = newItem;
-}
-
-// reset the data item by using empty string
-// Item = the item to set
-// name = the string to store in the "name" field
-void ResetDataItem(WIDATAITEM *Item, const wchar_t *name)
-{
- Item->Name = mir_wstrdup(name);
- Item->Start = L"";
- Item->End = L"";
- Item->Unit = L"";
- Item->Url = "";
- Item->Break = L"";
- Item->Type = 0;
-}
-
-// free the data item by using empty string
-// Item = the item to free
-void FreeDataItem(WIDATAITEM *Item)
-{
- wfree(Item->Name);
- wfree(Item->Start);
- wfree(Item->End);
- wfree(Item->Unit);
- wfree(Item->Url);
- wfree(Item->Break);
-}
-
-//============ Condition Icon List ============
-//
-// initiate icon assignmet list
-void WICondListInit(WICONDLIST *List)
-{
- List->Tail = nullptr;
- List->Head = nullptr;
-}
-
-// add a new update item into the current list
-void WICondListAdd(char *str, WICONDLIST *List)
-{
- WICONDITEM *newItem = (WICONDITEM*)mir_alloc(sizeof(WICONDITEM));
- wSetData(newItem->Item, str);
- CharLowerW(newItem->Item);
- newItem->Next = nullptr;
- if (List->Tail == nullptr) List->Head = newItem;
- else List->Tail->Next = newItem;
- List->Tail = newItem;
-}
-
-// check if the condition string matched for the assignment
-bool IsContainedInCondList(const wchar_t *pszStr, WICONDLIST *List)
-{
- // loop through the list to find matching internal name
- for (WICONDITEM *Item = List->Head; Item != nullptr; Item = Item->Next) {
- // if internal name found, return true indicating that the data is found
- if (wcsstr(pszStr, Item->Item))
- return true;
-
- }
- // return false when no match found
- return false;
-}
-
-// free the memory for icon assignment list
-void DestroyCondList(WICONDLIST *List)
-{
- // free the list one by one
- for (WICONDITEM *temp = List->Head; temp != nullptr; temp = List->Head) {
- List->Head = temp->Next;
- wfree(temp->Item); // free the data struct
- mir_free(temp);
- }
- // make sure the entire list is clear
- List->Tail = nullptr;
-}
-
-
-//============ WEATHER INI SETUP DIALOG ============
-//
-static INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
-
- // make the buttons flat
- SendDlgItemMessage(hwndDlg, IDC_STEP1, BUTTONSETASFLATBTN, TRUE, 0);
- SendDlgItemMessage(hwndDlg, IDC_STEP2, BUTTONSETASFLATBTN, TRUE, 0);
- SendDlgItemMessage(hwndDlg, IDC_STEP3, BUTTONSETASFLATBTN, TRUE, 0);
- SendDlgItemMessage(hwndDlg, IDC_STEP4, BUTTONSETASFLATBTN, TRUE, 0);
-
- // set icons
- Window_SetIcon_IcoLib(hwndDlg, g_plugin.getIconHandle(IDI_ICON));
-
- WindowList_Add(hWindowList, hwndDlg);
- ShowWindow(hwndDlg, SW_SHOW);
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDC_STEP1:
- // update current data
- Utils_OpenUrl("https://miranda-ng.org/");
- break;
-
- case IDC_STEP2:
- {
- CMStringW wszPath('\x00', MAX_PATH);
- GetModuleFileName(GetModuleHandle(nullptr), wszPath.GetBuffer(), MAX_PATH);
- int idx = wszPath.Find('\\');
- if (idx != -1) {
- wszPath.Truncate(idx);
- wszPath += L"\\Plugins\\weather\\";
- if (_wmkdir(wszPath) == 0)
- ShellExecute((HWND)lParam, L"open", wszPath, L"", L"", SW_SHOW);
- }
- break;
- }
-
- case IDC_STEP3:
- if (LoadWIData(false))
- MessageBox(nullptr,
- TranslateT("All update data has been reloaded."),
- TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION);
- break;
-
- case IDC_STEP4:
- WeatherAdd(0, 0);
- __fallthrough;
-
- case IDCANCEL:
- // close the info window
- DestroyWindow(hwndDlg);
- break;
- }
- break;
-
- case WM_CLOSE:
- DestroyWindow(hwndDlg);
- break;
-
- case WM_DESTROY:
- Window_FreeIcon_IcoLib(hwndDlg);
- break;
- }
- return FALSE;
-}
-
-// load the station data from a file
-// pszFile = the file name + path for the ini file to be loaded
-// pszShortFile = the file name of the ini file, but not including the path
-// Data = the struct to load the ini content to, and return to previous function
-
-static const char *statusStr[MAX_COND] =
-{
- "LIGHTNING",
- "FOG",
- "SNOW",
- "RAIN",
- "PARTLY CLOUDY",
- "CLOUDY",
- "SUNNY",
- "N/A",
- "RAIN SHOWER",
- "SNOW SHOWER",
-};
-
-static void LoadStationData(const wchar_t *pszFile, wchar_t *pszShortFile, WIDATA *Data)
-{
- WIDATAITEM DataItem;
-
- // clean up old stuff
- memset(Data, 0, sizeof(*Data));
- Data->Enabled = FALSE;
-
- // open the ini file
- FILE *pfile = _wfsopen(pszFile, L"rt", _SH_DENYWR);
- if (pfile == nullptr)
- return;
-
- char Line[4096];
- fgets(Line, _countof(Line), pfile);
- TrimString(Line);
-
- // make sure it is a valid weather protocol ini file
- if (!mir_strcmp(Line, "[Weather 0.3.x Update Data]"))
- Data->InternalVer = 1;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.1]"))
- Data->InternalVer = 2;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.1a]"))
- Data->InternalVer = 3;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.2]"))
- Data->InternalVer = 4;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.3]"))
- Data->InternalVer = 5;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.4]"))
- Data->InternalVer = 6;
- else if (!mir_strcmp(Line, "[Weather 0.3.x Update Data 1.5]"))
- Data->InternalVer = 7;
- else {
- wchar_t str[4096];
- mir_snwprintf(str, TranslateT("Invalid ini format for: %s"), pszFile);
- MessageBox(nullptr, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR);
- fclose(pfile);
- return;
- }
-
- // initialize all data fields
- char *Group = "";
-
- Data->DisplayName = L"";
- Data->InternalName = L"";
- Data->Description = L"";
- Data->Author = L"";
- Data->Version = L"";
- Data->DefaultURL = "";
- Data->DefaultMap = L"";
- Data->UpdateURL = "";
- Data->UpdateURL2 = "";
- Data->UpdateURL3 = "";
- Data->UpdateURL4 = "";
- Data->Cookie = "";
- Data->UserAgent = "";
- Data->IDSearch.SearchURL = "";
- Data->IDSearch.NotFoundStr = L"";
- Data->NameSearch.SearchURL = "";
- Data->NameSearch.NotFoundStr = L"";
- Data->NameSearch.SingleStr = L"";
- Data->NameSearch.Single.First = L"";
- Data->NameSearch.Multiple.First = L"";
- Data->IDSearch.Available = FALSE;
- Data->NameSearch.Single.Available = FALSE;
- Data->NameSearch.Multiple.Available = FALSE;
- wSetData(Data->FileName, pszFile);
- wSetData(Data->ShortFileName, pszShortFile);
-
- ResetDataItem(&Data->IDSearch.Name, L"ID Search - Station Name");
- ResetDataItem(&Data->NameSearch.Single.Name, L"Name Search Single Result - Station Name");
- ResetDataItem(&Data->NameSearch.Single.ID, L"Name Search Single Result - Station ID");
- ResetDataItem(&Data->NameSearch.Multiple.Name, L"Name Search Multiple Result - Station Name");
- ResetDataItem(&Data->NameSearch.Multiple.ID, L"Name Search Multiple Result - Station ID");
-
- DataItem.Name = L"";
- DataItem.Start = L"";
- DataItem.End = L"";
- DataItem.Unit = L"";
- DataItem.Url = "";
- DataItem.Break = L"";
- DataItem.Type = 0;
-
- // initialize the linked list for update items
- Data->UpdateDataCount = 0;
- Data->MemUsed = sizeof(WIDATA) + sizeof(WIDATALIST) + (mir_wstrlen(pszShortFile) + mir_wstrlen(pszFile) + 20) * sizeof(wchar_t);
- Data->UpdateData = nullptr;
- Data->UpdateDataTail = nullptr;
-
- // initialize the icon assignment list
- for (auto &it : Data->CondList)
- WICondListInit(&it);
-
- g_bIsUtf = false;
-
- while (!feof(pfile)) {
- // determine current tag
- if (fgets(Line, _countof(Line), pfile) == nullptr)
- break;
-
- TrimString(Line);
-
- // if the line is a group header/footer
- if (Line[0] == '[') {
- char *chop = strchr(Line + 1, ']');
- if (chop == nullptr)
- continue;
-
- if (Line[1] != '/') { // if it is not a footer (for old ini)
- // save the group name
- char *Temp = (char *)mir_alloc(mir_strlen(Line) + 10);
- strncpy(Temp, Line + 1, chop - Line - 1);
- Temp[chop - Line - 1] = 0;
- wfree(Group);
- wSetData(Group, Temp);
-
- // see if it is a update item, if it is, add a new item to the linked list
- if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") &&
- _stricmp(Group, "NAME SEARCH") && _stricmp(Group, "ICONS")) {
- wSetData(DataItem.Name, Temp);
- DataItem.Type = WID_NORMAL;
- WIItemListAdd(&DataItem, Data);
- Data->UpdateDataCount++;
- }
- mir_free(Temp);
- }
- else {
- wfree(Group);
- wSetData(Group, "");
- }
- }
-
- // ignore comments and all lines without an '='
- char *Value = strchr(Line, '=');
- if (Value == nullptr)
- continue;
-
- // get the string before '=' (ValName) and after '=' (Value)
- char *ValName = (char *)mir_alloc(mir_strlen(Line) + 1);
- strncpy(ValName, Line, Value - Line);
- ValName[Value - Line] = 0;
- Value++;
- ConvertBackslashes(Value);
-
- // store the value for each string
- if (!_stricmp(Group, "HEADER")) {
- if (!_stricmp(ValName, "NAME")) wSetData(Data->DisplayName, Value);
- else if (!_stricmp(ValName, "INTERNAL NAME")) wSetData(Data->InternalName, Value);
- else if (!_stricmp(ValName, "DESCRIPTION")) wSetData(Data->Description, Value);
- else if (!_stricmp(ValName, "AUTHOR")) wSetData(Data->Author, Value);
- else if (!_stricmp(ValName, "VERSION")) wSetData(Data->Version, Value);
- else if (!_stricmp(ValName, "UTF8")) g_bIsUtf = (0 == _stricmp(Value, "true"));
- }
- else if (!_stricmp(Group, "DEFAULT")) {
- if (!_stricmp(ValName, "DEFAULT URL")) wSetData(Data->DefaultURL, Value);
- else if (!_stricmp(ValName, "DEFAULT MAP")) wSetData(Data->DefaultMap, Value);
- else if (!_stricmp(ValName, "UPDATE URL")) wSetData(Data->UpdateURL, Value);
- else if (!_stricmp(ValName, "UPDATE URL2")) wSetData(Data->UpdateURL2, Value);
- else if (!_stricmp(ValName, "UPDATE URL3")) wSetData(Data->UpdateURL3, Value);
- else if (!_stricmp(ValName, "UPDATE URL4")) wSetData(Data->UpdateURL4, Value);
- else if (!_stricmp(ValName, "COOKIE")) wSetData(Data->Cookie, Value);
- else if (!_stricmp(ValName, "USERAGENT")) wSetData(Data->UserAgent, Value);
- }
- else if (!_stricmp(Group, "ID SEARCH")) {
- if (!_stricmp(ValName, "AVAILABLE")) Data->IDSearch.Available = (0 == _stricmp(Value, "true"));
- else if (!_stricmp(ValName, "SEARCH URL")) wSetData(Data->IDSearch.SearchURL, Value);
- else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(Data->IDSearch.NotFoundStr, Value);
- else if (!_stricmp(ValName, "NAME START")) wSetData(Data->IDSearch.Name.Start, Value);
- else if (!_stricmp(ValName, "NAME END")) wSetData(Data->IDSearch.Name.End, Value);
- }
- else if (!_stricmp(Group, "NAME SEARCH")) {
- if (!_stricmp(ValName, "SINGLE RESULT")) Data->NameSearch.Single.Available = (0 == _stricmp(Value, "true"));
- else if (!_stricmp(ValName, "MULTIPLE RESULT")) Data->NameSearch.Multiple.Available = (0 == _stricmp(Value, "true"));
- else if (!_stricmp(ValName, "SEARCH URL")) wSetData(Data->NameSearch.SearchURL, Value);
- else if (!_stricmp(ValName, "NOT FOUND STR")) wSetData(Data->NameSearch.NotFoundStr, Value);
- else if (!_stricmp(ValName, "SINGLE RESULT STR")) wSetData(Data->NameSearch.SingleStr, Value);
- else if (!_stricmp(ValName, "SINGLE FIRST")) wSetData(Data->NameSearch.Single.First, Value);
- else if (!_stricmp(ValName, "SINGLE NAME START")) wSetData(Data->NameSearch.Single.Name.Start, Value);
- else if (!_stricmp(ValName, "SINGLE NAME END")) wSetData(Data->NameSearch.Single.Name.End, Value);
- else if (!_stricmp(ValName, "SINGLE ID START")) wSetData(Data->NameSearch.Single.ID.Start, Value);
- else if (!_stricmp(ValName, "SINGLE ID END")) wSetData(Data->NameSearch.Single.ID.End, Value);
- else if (!_stricmp(ValName, "MULT FIRST")) wSetData(Data->NameSearch.Multiple.First, Value);
- else if (!_stricmp(ValName, "MULT NAME START")) wSetData(Data->NameSearch.Multiple.Name.Start, Value);
- else if (!_stricmp(ValName, "MULT NAME END")) wSetData(Data->NameSearch.Multiple.Name.End, Value);
- else if (!_stricmp(ValName, "MULT ID START")) wSetData(Data->NameSearch.Multiple.ID.Start, Value);
- else if (!_stricmp(ValName, "MULT ID END")) wSetData(Data->NameSearch.Multiple.ID.End, Value);
- }
- else if (!_stricmp(Group, "ICONS")) {
- for (int i = 0; i < _countof(statusStr); i++) {
- if (!_stricmp(ValName, statusStr[i])) {
- WICondListAdd(Value, &Data->CondList[i]);
- break;
- }
- }
- }
- else if (Data->UpdateDataCount != 0) {
- if (!_stricmp(ValName, "START")) wSetData(Data->UpdateDataTail->Item.Start, Value);
- else if (!_stricmp(ValName, "SOURCE")) wSetData(Data->UpdateDataTail->Item.Start, Value);
- else if (!_stricmp(ValName, "END")) wSetData(Data->UpdateDataTail->Item.End, Value);
- else if (!_stricmp(ValName, "UNIT")) wSetData(Data->UpdateDataTail->Item.Unit, Value);
- else if (!_stricmp(ValName, "URL")) wSetData(Data->UpdateDataTail->Item.Url, Value);
- else if (!_stricmp(ValName, "HIDDEN")) {
- if (!_stricmp(Value, "TRUE")) {
- wchar_t *nm = Data->UpdateDataTail->Item.Name;
- size_t len = mir_wstrlen(nm) + 1;
-
- Data->UpdateDataTail->Item.Name = nm = (wchar_t*)mir_realloc(nm, sizeof(wchar_t)*(len + 3));
- memmove(nm + 1, nm, len*sizeof(wchar_t));
- *nm = '#';
- }
- }
- else if (!_stricmp(ValName, "SET DATA")) {
- Data->UpdateDataTail->Item.Type = WID_SET;
- wSetData(Data->UpdateDataTail->Item.End, Value);
- }
- else if (!_stricmp(ValName, "BREAK DATA")) {
- Data->UpdateDataTail->Item.Type = WID_BREAK;
- wSetData(Data->UpdateDataTail->Item.Break, Value);
- }
- }
- // recalculate memory used
- Data->MemUsed += (mir_strlen(Value) + 10);
- wfree(ValName);
- }
-
- // calcualate memory used for the ini and close the file
- Data->MemUsed += sizeof(WIDATAITEMLIST)*Data->UpdateDataCount;
- Data->Enabled = TRUE; // enable the service
- fclose(pfile);
- wfree(Group);
-}
-
-//============ LOADING INI FILES ============
-//
-// load the weather update data form INI files
-bool LoadWIData(bool dial)
-{
- // make sure that the current service data list is empty
- WITail = nullptr;
- WIHead = WITail;
-
- // find all *.ini file in the plugin\weather directory
- CMStringW wszFileName('\x00', MAX_PATH);
- GetModuleFileName(GetModuleHandle(nullptr), wszFileName.GetBuffer(), MAX_PATH);
- int idx = wszFileName.ReverseFind('\\');
- if (idx == -1)
- return false;
- wszFileName.Truncate(idx);
- wszFileName += L"\\Plugins\\Weather\\";
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(wszFileName + L"*.ini", &fd);
-
- // load the content of the ini file into memory
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- if (mir_wstrcmpi(fd.cFileName, L"SAMPLE_INI.INI")) {
- WIDATA Data;
- LoadStationData(wszFileName + fd.cFileName, fd.cFileName, &Data);
- if (Data.Enabled)
- WIListAdd(Data);
- }
- // look through the entire "plugins\weather" directory
- } while (FindNextFile(hFind, &fd));
- FindClose(hFind);
- }
-
- if (WIHead == nullptr) {
- // no ini found, display an error message box.
- if (dial)
- hWndSetup = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SETUP), nullptr, DlgProcSetup);
- else
- MessageBox(nullptr,
- TranslateT("No update data file is found. Please check your Plugins\\Weather directory."),
- TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR);
- return false;
- }
- return true;
-}
-
-//============ FREE WIDATA ITEM FROM MEMORY ============
-//
-// free the WIDATA struct from memory
-// Data = the struct to be freed
-static void FreeWIData(WIDATA *Data)
-{
- // free update items linked list first
- WIDATAITEMLIST *WItem = Data->UpdateData;
- while (WItem != nullptr) {
- Data->UpdateData = WItem->Next;
- FreeDataItem(&WItem->Item);
- mir_free(WItem);
- WItem = Data->UpdateData;
- }
-
- // free the strings in the rest of the struct
- wfree(Data->DisplayName);
- wfree(Data->InternalName);
- wfree(Data->Description);
- wfree(Data->Author);
- wfree(Data->Version);
- wfree(Data->DefaultURL);
- wfree(Data->DefaultMap);
- wfree(Data->UpdateURL);
- wfree(Data->UpdateURL2);
- wfree(Data->UpdateURL3);
- wfree(Data->UpdateURL4);
- wfree(Data->Cookie);
- wfree(Data->UserAgent);
- wfree(Data->IDSearch.SearchURL);
- wfree(Data->IDSearch.NotFoundStr);
- FreeDataItem(&Data->IDSearch.Name);
- wfree(Data->NameSearch.SearchURL);
- wfree(Data->NameSearch.NotFoundStr);
- wfree(Data->NameSearch.SingleStr);
- wfree(Data->NameSearch.Single.First);
- FreeDataItem(&Data->NameSearch.Single.Name);
- FreeDataItem(&Data->NameSearch.Single.ID);
- wfree(Data->NameSearch.Multiple.First);
- FreeDataItem(&Data->NameSearch.Multiple.Name);
- FreeDataItem(&Data->NameSearch.Multiple.ID);
- wfree(Data->ShortFileName);
- wfree(Data->FileName);
- for (auto &it : Data->CondList)
- DestroyCondList(&it);
-}
-
-// remove all service data from memory
-void DestroyWIList(void)
-{
- // free the list one by one
- while (WIHead != nullptr) {
- WIDATALIST *wi = WIHead;
- WIHead = wi->next;
- FreeWIData(&wi->Data); // free the data struct
- mir_free(wi);
- }
-
- // make sure the entire list is clear
- WITail = nullptr;
-}
diff --git a/protocols/Weather/src/weather_mwin.cpp b/protocols/Weather/src/weather_mwin.cpp
index da08be4ce1..cb1e33849b 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,16 +135,16 @@ 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) {
picSize = GetSystemMetrics(SM_CXICON);
- hIcon = GetStatusIconBig(data->hContact);
+ hIcon = data->ppro->GetStatusIconBig(data->hContact);
}
LOGFONT lfnt, lfnt1;
- COLORREF clr = g_plugin.getDword("ColorMwinFrame", GetSysColor(COLOR_3DFACE));
+ COLORREF clr = data->ppro->getDword("ColorMwinFrame", GetSysColor(COLOR_3DFACE));
COLORREF fntc = Font_GetW(_A2W(MODULENAME), LPGENW("Frame Font"), &lfnt);
COLORREF fntc1 = Font_GetW(_A2W(MODULENAME), LPGENW("Frame Title Font"), &lfnt1);
@@ -218,10 +220,17 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
return(TRUE);
}
-static void addWindow(MCONTACT hContact)
+void UpdateMwinData(MCONTACT hContact)
+{
+ HWND hwnd = WindowList_Find(hMwinWindowList, hContact);
+ if (hwnd != nullptr)
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+}
+
+void CWeatherProto::AddFrameWindow(MCONTACT hContact)
{
DBVARIANT dbv;
- if (g_plugin.getWString(hContact, "Nick", &dbv))
+ if (getWString(hContact, "Nick", &dbv))
return;
wchar_t winname[512];
@@ -229,7 +238,7 @@ static void addWindow(MCONTACT hContact)
db_free(&dbv);
HWND hWnd = CreateWindow(L"WeatherFrame", L"", WS_CHILD | WS_VISIBLE,
- 0, 0, 10, 10, g_clistApi.hwndContactList, nullptr, g_plugin.getInst(), (void*)hContact);
+ 0, 0, 10, 10, g_clistApi.hwndContactList, nullptr, g_plugin.getInst(), (void *)hContact);
WindowList_Add(hMwinWindowList, hWnd, hContact);
CLISTFrame Frame = {};
@@ -242,41 +251,34 @@ static void addWindow(MCONTACT hContact)
Frame.height = 32;
int frameID = g_plugin.addFrame(&Frame);
- g_plugin.setDword(hContact, "mwin", frameID);
+ setDword(hContact, "mwin", frameID);
Contact::Hide(hContact);
}
-void removeWindow(MCONTACT hContact)
+void CWeatherProto::RemoveFrameWindow(MCONTACT hContact)
{
- uint32_t frameId = g_plugin.getDword(hContact, "mwin");
+ uint32_t frameId = getDword(hContact, "mwin");
WindowList_Remove(hMwinWindowList, WindowList_Find(hMwinWindowList, hContact));
CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0);
- g_plugin.setDword(hContact, "mwin", 0);
+ setDword(hContact, "mwin", 0);
Contact::Hide(hContact, false);
}
-void UpdateMwinData(MCONTACT hContact)
+INT_PTR CWeatherProto::Mwin_MenuClicked(WPARAM hContact, LPARAM)
{
- HWND hwnd = WindowList_Find(hMwinWindowList, hContact);
- if (hwnd != nullptr)
- RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
-}
-
-INT_PTR Mwin_MenuClicked(WPARAM wParam, LPARAM)
-{
- BOOL addwnd = WindowList_Find(hMwinWindowList, wParam) == nullptr;
- if (addwnd)
- addWindow(wParam);
+ if (WindowList_Find(hMwinWindowList, hContact))
+ RemoveFrameWindow(hContact);
else
- removeWindow(wParam);
+ AddFrameWindow(hContact);
+
return 0;
}
-int BuildContactMenu(WPARAM wparam, LPARAM)
+int CWeatherProto::BuildContactMenu(MCONTACT hContact)
{
- int flags = g_plugin.getDword(wparam, "mwin") ? CMIF_CHECKED : 0;
+ int flags = getDword(hContact, "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,17 +339,17 @@ void InitMwin(void)
mir_strcpy(fontid.setting, "fnt1");
g_plugin.addFont(&fontid);
- for (auto &hContact : Contacts(MODULENAME))
- if (g_plugin.getDword(hContact, "mwin"))
- addWindow(hContact);
+ for (auto &hContact : AccContacts())
+ if (getDword(hContact, "mwin"))
+ AddFrameWindow(hContact);
hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame);
}
-void DestroyMwin(void)
+void CWeatherProto::DestroyMwin(void)
{
- for (auto &hContact : Contacts(MODULENAME)) {
- uint32_t frameId = g_plugin.getDword(hContact, "mwin");
+ for (auto &hContact : AccContacts()) {
+ uint32_t frameId = 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..765309e414 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 ===========
@@ -37,9 +36,9 @@ const wchar_t* GetDefaultText(int c)
case 'b':
return TranslateT("Weather Condition for %n as of %u");
case 'B':
- return TranslateT("Feel-Like: %f\\nPressure: %p\\nWind: %i %w\\nHumidity: %m\\nDew Point: %e\\nVisibility: %v\\n\\nSun Rise: %r\\nSun Set: %y\\n\\n5 Days Forecast:\\n%[Forecast Day 1]\\n%[Forecast Day 2]\\n%[Forecast Day 3]\\n%[Forecast Day 4]\\n%[Forecast Day 5]");
+ return TranslateT("Feel-Like: %f\\nPressure: %p\\nWind: %i %w\\nHumidity: %m\\nDew Point: %e\\nVisibility: %v\\n\\nSun Rise: %r\\nSun Set: %y\\n\\n5 Days Forecast:\\n\\n%[Forecast Day 1]\\n\\n%[Forecast Day 2]\\n\\n%[Forecast Day 3]\\n\\n%[Forecast Day 4]\\n\\n%[Forecast Day 5]");
case 'X': case 'N':
- return TranslateT("%c\\nTemperature: %t\\nFeel-Like: %f\\nPressure: %p\\nWind: %i %w\\nHumidity: %m\\nDew Point: %e\\nVisibility: %v\\n\\nSun Rise: %r\\nSun Set: %y\\n\\n5 Days Forecast:\\n%[Forecast Day 1]\\n%[Forecast Day 2]\\n%[Forecast Day 3]\\n%[Forecast Day 4]\\n%[Forecast Day 5]");
+ return TranslateT("%c\\nTemperature: %t\\nFeel-Like: %f\\nPressure: %p\\nWind: %i %w\\nHumidity: %m\\nDew Point: %e\\nVisibility: %v\\n\\nSun Rise: %r\\nSun Set: %y\\n\\n5 Days Forecast:\\n\\n%[Forecast Day 1]\\n\\n%[Forecast Day 2]\\n\\n%[Forecast Day 3]\\n\\n%[Forecast Day 4]\\n\\n%[Forecast Day 5]");
case 'E':
return TranslateT("%n at %u: %c, %t (feel-like %f) Wind: %i %w Humidity: %m");
case 'H':
@@ -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,224 @@ 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.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);
+ 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(g_plugin.getWStringA("DegreeSign"));
- wcsncpy_s(opt.DegreeSign, (szValue == NULL) ? L"" : szValue, _TRUNCATE);
+ ptrW szValue(getWStringA("DegreeSign"));
+ wcsncpy_s(opt.DegreeSign, !mir_wstrlen(szValue) ? L"\xB0" : 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("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 CGeneralOptionsDlg : public CWeatherDlgBase
{
- wchar_t str[512];
+public:
+ CGeneralOptionsDlg(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);
+ SetDlgItemTextW(m_hwnd, IDC_UPDATETIME, str);
+ SetDlgItemTextW(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_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.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 +313,224 @@ static controls[] =
{ 'S', IDC_BTITLE2, "StatusText" },
};
-static INT_PTR CALLBACK DlgProcText(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
+struct
+{
+ wchar_t symbol;
+ const wchar_t *pwszText;
+}
+static variables[] =
+{
+ { 'c', LPGENW("Current condition") },
+ { 'd', LPGENW("Current date") },
+ { 'e', LPGENW("Dewpoint") },
+ { 'f', LPGENW("Feel-like temp") },
+ { 'h', LPGENW("Today's high") },
+ { 'i', LPGENW("Wind direction") },
+ { 'l', LPGENW("Today's low") },
+ { 'm', LPGENW("Humidity") },
+ { 'n', LPGENW("Station name") },
+ { 'p', LPGENW("Pressure") },
+ { 'r', LPGENW("Sunrise") },
+ { 's', LPGENW("Station ID") },
+ { 't', LPGENW("Temperature") },
+ { 'u', LPGENW("Update time") },
+ { 'v', LPGENW("Visibility") },
+ { 'w', LPGENW("Wind speed") },
+ { 'y', LPGENW("Sunset") },
+};
+
+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),
+ btnReset(this, IDC_RESET),
+ tm1(this, IDC_TM1),
+ tm2(this, IDC_TM2),
+ tm3(this, IDC_TM3),
+ tm4(this, IDC_TM4),
+ tm5(this, IDC_TM5),
+ tm6(this, IDC_TM6),
+ tm7(this, IDC_TM7),
+ tm8(this, IDC_TM8)
+ {
+ 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);
+ CMStringW str;
+ for (auto &it : variables)
+ str.AppendFormat(L"%%%c\t%s\r\n", it.symbol, TranslateW(it.pwszText));
+ str.Append(L"----------\r\n");
+ str.AppendFormat(L"\\n\t%s\r\n", TranslateT("new line"));
+ SetDlgItemTextW(m_hwnd, IDC_VARLIST, str);
for (auto &it : controls)
- SetDlgItemText(hdlg, it.id, GetTextValue(it.c));
+ SetDlgItemTextW(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
+ for (auto &it : controls) {
+ wchar_t textstr[MAX_TEXT_SIZE];
+ GetDlgItemText(m_hwnd, it.id, textstr, _countof(textstr));
+ if (!mir_wstrcmpi(textstr, GetDefaultText(it.c)))
+ m_proto->delSetting(it.setting);
+ else
+ m_proto->setWString(it.setting, textstr);
+ }
+
+ m_proto->SaveOptions();
+ m_proto->UpdateAllInfo(0, 0);
+ return true;
+ }
+
+ void onClick_More(CCtrlButton *)
+ {
+ // heading
+ CMStringW str(TranslateT("Here is a list of custom variables that are currently available"));
+ str += L"\n\n";
+ m_proto->GetVarsDescr(str);
- 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);
+ // display the list in a message box
+ MessageBox(nullptr, str, TranslateT("More Variables"), MB_OK | MB_ICONINFORMATION | MB_TOPMOST);
+ }
+
+ void onClick_TM(CCtrlButton *pButton)
+ {
+ // display the menu
+ HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMMENU));
+ HMENU hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+
+ auto &var = controls[pButton->GetCtrlId() - IDC_TM1];
+
+ RECT pos;
+ GetWindowRect(pButton->GetHwnd(), &pos);
+ switch (TrackPopupMenu(hMenu1, TPM_LEFTBUTTON | TPM_RETURNCMD, pos.left, pos.bottom, 0, m_hwnd, nullptr)) {
+ case ID_MPREVIEW:
{
- 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);
+ // show the preview in a message box, using the weather data from the default station
+ WEATHERINFO winfo = m_proto->LoadWeatherInfo(m_proto->opt.DefStn);
+ wchar_t buf[MAX_TEXT_SIZE];
+ GetDlgItemTextW(m_hwnd, var.id, buf, _countof(buf));
+ MessageBox(nullptr, GetDisplay(&winfo, buf), TranslateT("Weather Protocol Text Preview"), MB_OK | MB_TOPMOST);
}
break;
- 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));
- break;
-
- case ID_T2:
- // reset to the default setting
- for (auto &it : controls)
- SetDlgItemText(hdlg, it.id, GetDefaultText(it.c));
- break;
- }
- DestroyMenu(hMenu);
+ case ID_MRESET:
+ SetDlgItemTextW(m_hwnd, var.id, GetDefaultText(var.c));
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);
- }
+ DestroyMenu(hMenu);
+ }
+
+ void onClick_Reset(CCtrlButton *)
+ {
+ // left click action selection menu
+ HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_TMENU));
+ HMENU hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+
+ RECT pos;
+ GetWindowRect(btnReset.GetHwnd(), &pos);
+ 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)
+ SetDlgItemTextW(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)
+ SetDlgItemTextW(m_hwnd, it.id, GetDefaultText(it.c));
break;
}
- break;
+ DestroyMenu(hMenu);
}
- return FALSE;
-}
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// account options dialog
-//============ OPTION INITIALIZATION ============
+class CAccountOptionsDlg : public CWeatherDlgBase
+{
+ CCtrlEdit edtKey;
+ CCtrlButton btnObtain;
+
+public:
+ CAccountOptionsDlg(CWeatherProto *ppro) :
+ CWeatherDlgBase(ppro, IDD_ACCOUNT_OPT),
+ edtKey(this, IDC_KEY),
+ btnObtain(this, IDC_OBTAIN)
+ {
+ CreateLink(edtKey, m_proto->m_szApiKey);
+
+ btnObtain.OnClick = Callback(this, &CAccountOptionsDlg::onClick_Obtain);
+ }
+
+ void onClick_Obtain(CCtrlButton *)
+ {
+ Utils_OpenUrl("https://www.visualcrossing.com/account");
+ }
+};
+/////////////////////////////////////////////////////////////////////////////////////////
// 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.szTab.a = LPGEN("General");
- odp.flags = ODPF_BOLDGROUPS;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE;
+
+ // account options
+ odp.pDialog = new CAccountOptionsDlg(this);
+ odp.szTab.w = LPGENW("Account");
g_plugin.addOptions(wParam, &odp);
- // text options
- odp.pszTemplate = MAKEINTRESOURCEA(IDD_TEXTOPT);
- odp.pfnDlgProc = DlgProcText;
- odp.szTab.a = LPGEN("Display");
+ // plugin options
+ odp.pDialog = new CGeneralOptionsDlg(this);
+ odp.szTab.w = LPGENW("General");
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;
+ // text options
+ odp.pDialog = new COptionsTextDlg(this);
+ odp.szTab.w = LPGENW("Display");
g_plugin.addOptions(wParam, &odp);
+
+ if (m_bPopups)
+ InitPopupOptions(wParam);
return 0;
}
diff --git a/protocols/Weather/src/weather_popup.cpp b/protocols/Weather/src/weather_popup.cpp
index 992db0a69a..b9f938e41d 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)
+ if (!m_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,21 +105,23 @@ 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 (m_bPopups && opt.UpdatePopup && (!opt.PopupOnChange || bAlways) && !getByte(hContact, "DPopUp")) {
WEATHERINFO winfo = LoadWeatherInfo(hContact);
// setup the popup
POPUPDATAW ppd;
ppd.lchContact = hContact;
ppd.PluginData = ppd.lchIcon = GetStatusIcon(winfo.hContact);
- GetDisplay(&winfo, GetTextValue('P'), ppd.lpwzContactName);
- GetDisplay(&winfo, GetTextValue('p'), ppd.lpwzText);
+ wcsncpy_s(ppd.lpwzContactName, GetDisplay(&winfo, GetTextValue('P')), _TRUNCATE);
+ wcsncpy_s(ppd.lpwzText, GetDisplay(&winfo, GetTextValue('p')), _TRUNCATE);
ppd.PluginWindowProc = PopupDlgProc;
ppd.colorBack = (opt.UseWinColors) ? GetSysColor(COLOR_BTNFACE) : opt.BGColour;
ppd.colorText = (opt.UseWinColors) ? GetSysColor(COLOR_WINDOWTEXT) : opt.TextColour;
@@ -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, btnPD3, 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 = chkUseWin.IsChecked();
+ 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),
+ btnPD3(this, IDC_PD3),
+ 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);
+ btnPD3.OnClick = Callback(this, &CPopupOptsDlg::onChanged_Delay);
+ 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_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);
+ chkUseWin.SetState(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)))
+ m_proto->delSetting(it.setting);
+ else
+ m_proto->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 *pCheck)
+ {
+ // use window color - enable/disable color selection controls
+ bool bEnable = !pCheck->IsChecked();
+ EnableWindow(GetDlgItem(m_hwnd, IDC_BGCOLOUR), bEnable);
+ EnableWindow(GetDlgItem(m_hwnd, IDC_TEXTCOLOUR), bEnable);
+ }
- 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..fdb1fe443d
--- /dev/null
+++ b/protocols/Weather/src/weather_proto.cpp
@@ -0,0 +1,166 @@
+/*
+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),
+ m_bPopups(m_szModuleName, "UsePopup", true),
+ m_szApiKey(m_szModuleName, "ApiKey", L"")
+{
+ m_hProtoIcon = g_plugin.getIconHandle(IDI_ICON);
+
+ CreateProtoService(PS_GETAVATARINFO, &CWeatherProto::GetAvatarInfoSvc);
+ CreateProtoService(PS_GETADVANCEDSTATUSICON, &CWeatherProto::AdvancedStatusIconSvc);
+
+ HookProtoEvent(ME_OPT_INITIALISE, &CWeatherProto::OptInit);
+ HookProtoEvent(ME_CLIST_DOUBLECLICKED, &CWeatherProto::BriefInfoEvt);
+
+ // load options and set defaults
+ LoadOptions();
+
+ // reset the weather data at startup for individual contacts
+ EraseAllInfo();
+
+ // popup initialization
+ CMStringW wszTitle(FORMAT, L"%s %s", m_tszUserName, TranslateT("notifications"));
+ g_plugin.addPopupOption(wszTitle, m_bPopups);
+
+ // 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();
+}
+
+void CWeatherProto::OnModulesLoaded()
+{
+ InitMwin();
+ InitMenuItems();
+
+ // 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);
+ HookProtoEvent(ME_TTB_MODULELOADED, &CWeatherProto::OnToolbarLoaded);
+}
+
+int CWeatherProto::OnToolbarLoaded(WPARAM, LPARAM)
+{
+ CMStringA szName(FORMAT, "%s/Enabled", m_szModuleName);
+
+ TTBButton ttb = {};
+ ttb.name = LPGEN("Enable/disable auto update");
+ ttb.pszService = szName.GetBuffer();
+ ttb.pszTooltipUp = LPGEN("Auto Update Enabled");
+ ttb.pszTooltipDn = LPGEN("Auto Update Disabled");
+ ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_ICON);
+ ttb.hIconHandleDn = g_plugin.getIconHandle(IDI_DISABLED);
+ ttb.dwFlags = (getByte("AutoUpdate", 1) ? 0 : TTBBF_PUSHED) | TTBBF_ASPUSHBUTTON | TTBBF_VISIBLE;
+ hTBButton = g_plugin.addTTB(&ttb);
+ return 0;
+}
+
+void CWeatherProto::OnShutdown()
+{
+ m_impl.m_update.Stop();
+
+ SaveOptions(); // save options once more
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+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:
+ case PFLAGNUM_5:
+ 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 PFLAG_UNIQUEIDTEXT:
+ return (INT_PTR)TranslateT("Coordinates");
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// nothing to do here because weather proto do not need to retrieve contact info form network
+// so just return a 0
+
+void CWeatherProto::AckThreadProc(void *param)
+{
+ Sleep(100);
+
+ ProtoBroadcastAck((DWORD_PTR)param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1);
+}
+
+int CWeatherProto::GetInfo(MCONTACT hContact, int)
+{
+ ForkThread(&CWeatherProto::AckThreadProc, (void *)hContact);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void __cdecl CWeatherProto::GetAwayMsgThread(void *arg)
+{
+ Sleep(100);
+
+ MCONTACT hContact = (DWORD_PTR)arg;
+ ptrW wszStatus(db_get_wsa(hContact, "CList", "StatusMsg"));
+ ProtoBroadcastAck(hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, this, wszStatus);
+}
+
+HANDLE CWeatherProto::GetAwayMsg(MCONTACT hContact)
+{
+ ForkThread(&CWeatherProto::GetAwayMsgThread, (void*)hContact);
+ return this;
+}
diff --git a/protocols/Weather/src/weather_svcs.cpp b/protocols/Weather/src/weather_svcs.cpp
index daeb7f8bd1..6f897e3d7a 100644
--- a/protocols/Weather/src/weather_svcs.cpp
+++ b/protocols/Weather/src/weather_svcs.cpp
@@ -26,89 +26,8 @@ building/changing the weather menu items.
#include "stdafx.h"
-static HGENMENU hEnableDisableMenu;
-
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)
-{
- return (LOWORD(wParam) == PLI_PROTOCOL) ? (INT_PTR)CopyIcon(g_plugin.getIcon(IDI_ICON)) : 0;
-}
-
-static void __cdecl AckThreadProc(HANDLE param)
-{
- Sleep(100);
- ProtoBroadcastAck(MODULENAME, (DWORD_PTR)param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1);
-}
-
-// nothing to do here because weather proto do not need to retrieve contact info form network
-// so just return a 0
-INT_PTR WeatherGetInfo(WPARAM, LPARAM lParam)
-{
- CCSDATA *ccs = (CCSDATA *)lParam;
- mir_forkthread(AckThreadProc, (void*)ccs->hContact);
- return 0;
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
// avatars
@@ -132,7 +51,7 @@ static statusIcons[MAX_COND] =
{ L"Light", 130, ID_STATUS_INVISIBLE },
};
-INT_PTR WeatherGetAvatarInfo(WPARAM, LPARAM lParam)
+INT_PTR CWeatherProto::GetAvatarInfoSvc(WPARAM, LPARAM lParam)
{
wchar_t szSearchPath[MAX_PATH];
GetModuleFileName(GetModuleHandle(nullptr), szSearchPath, _countof(szSearchPath));
@@ -144,7 +63,7 @@ INT_PTR WeatherGetAvatarInfo(WPARAM, LPARAM lParam)
szSearchPath[0] = 0;
PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION*)lParam;
- int iCond = g_plugin.getWord(pai->hContact, "StatusIcon", -1);
+ int iCond = getWord(pai->hContact, "StatusIcon", -1);
if (iCond < 0 || iCond >= MAX_COND)
return GAIR_NOAVATAR;
@@ -163,34 +82,15 @@ INT_PTR WeatherGetAvatarInfo(WPARAM, LPARAM lParam)
return GAIR_NOAVATAR;
}
-void AvatarDownloaded(MCONTACT hContact)
+void CWeatherProto::AvatarDownloaded(MCONTACT hContact)
{
PROTO_AVATAR_INFORMATION ai = {};
ai.hContact = hContact;
- if (WeatherGetAvatarInfo(GAIF_FORCE, (LPARAM)&ai) == GAIR_SUCCESS)
- ProtoBroadcastAck(MODULENAME, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai);
+ if (GetAvatarInfoSvc(GAIF_FORCE, (LPARAM)&ai) == GAIR_SUCCESS)
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai);
else
- ProtoBroadcastAck(MODULENAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr);
-}
-
-static void __cdecl WeatherGetAwayMsgThread(void *arg)
-{
- Sleep(100);
-
- MCONTACT hContact = (DWORD_PTR)arg;
- ptrW wszStatus(db_get_wsa(hContact, "CList", "StatusMsg"));
- ProtoBroadcastAck(MODULENAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, wszStatus);
-}
-
-static INT_PTR WeatherGetAwayMsg(WPARAM, LPARAM lParam)
-{
- CCSDATA* ccs = (CCSDATA*)lParam;
- if (ccs == nullptr)
- return 0;
-
- mir_forkthread(WeatherGetAwayMsgThread, (void*)ccs->hContact);
- return 1;
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -202,18 +102,18 @@ void ClearStatusIcons()
it.clistIconId = 0;
}
-int MapCondToStatus(MCONTACT hContact)
+int CWeatherProto::MapCondToStatus(MCONTACT hContact)
{
- int iCond = g_plugin.getWord(hContact, "StatusIcon", -1);
+ int iCond = getWord(hContact, "StatusIcon", -1);
if (iCond < 0 || iCond >= MAX_COND)
return ID_STATUS_OFFLINE;
return statusIcons[iCond].status;
}
-HICON GetStatusIcon(MCONTACT hContact)
+HICON CWeatherProto::GetStatusIcon(MCONTACT hContact)
{
- int iCond = g_plugin.getWord(hContact, "StatusIcon", -1);
+ int iCond = getWord(hContact, "StatusIcon", -1);
if (iCond < 0 || iCond >= MAX_COND)
return nullptr;
@@ -224,9 +124,9 @@ HICON GetStatusIcon(MCONTACT hContact)
return ImageList_GetIcon(Clist_GetImageList(), pIcon.clistIconId, ILD_NORMAL);
}
-HICON GetStatusIconBig(MCONTACT hContact)
+HICON CWeatherProto::GetStatusIconBig(MCONTACT hContact)
{
- int iCond = g_plugin.getWord(hContact, "StatusIcon", -1);
+ int iCond = getWord(hContact, "StatusIcon", -1);
if (iCond < 0 || iCond >= MAX_COND)
return nullptr;
@@ -236,12 +136,12 @@ HICON GetStatusIconBig(MCONTACT hContact)
return hIcon;
}
-static INT_PTR WeatherAdvancedStatusIcon(WPARAM hContact, LPARAM)
+INT_PTR CWeatherProto::AdvancedStatusIconSvc(WPARAM hContact, LPARAM)
{
if (!hContact || !g_plugin.hIconsDll)
return -1;
- int iCond = g_plugin.getWord(hContact, "StatusIcon", -1);
+ int iCond = getWord(hContact, "StatusIcon", -1);
if (iCond < 0 || iCond >= MAX_COND)
return -1;
@@ -252,34 +152,14 @@ static INT_PTR WeatherAdvancedStatusIcon(WPARAM hContact, LPARAM)
return MAKELONG(0, pIcon.clistIconId);
}
-//============ PROTOCOL INITIALIZATION ============
-// 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);
-}
-
-//============ MENU INITIALIZATION ============
+/////////////////////////////////////////////////////////////////////////////////////////
+// menus
-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));
@@ -293,119 +173,137 @@ void UpdateMenu(BOOL State)
CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTBButton, !State ? TTBST_PUSHED : 0);
}
+/////////////////////////////////////////////////////////////////////////////////////////
// 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)
+/////////////////////////////////////////////////////////////////////////////////////////
+// adding weather contact menus
+
+static std::vector<HGENMENU> g_menuItems;
+
+static int OnPrebuildMenu(WPARAM hContact, LPARAM)
{
- return BriefInfo(wParam, lParam);
+ auto *ppro = CMPlugin::getInstance(hContact);
+ for (auto &it : g_menuItems)
+ Menu_ShowItem(it, ppro != 0);
+
+ if (ppro)
+ ppro->BuildContactMenu(hContact);
+ return 0;
}
-// adding weather contact menus
-// copied and modified form "modified MSN Protocol"
-void AddMenuItems(void)
+void CWeatherProto::GlobalMenuInit()
{
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 = MODULENAME "/Update";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/Refresh";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/Brief";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/CompleteForecast";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/Map";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/Log";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&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 = MODULENAME "/Edit";
+ g_menuItems.push_back(Menu_AddContactMenuItem(&mi));
+ CreateServiceFunction(mi.pszService, GlobalService<&CWeatherProto::EditSettings>);
- // adding main menu items
- mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Weather"), 500099000);
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ SET_UID(mi, 0xe193fe9b, 0xf6ad, 0x41ac, 0x95, 0x29, 0x45, 0x4, 0x44, 0xb1, 0xeb, 0x5d);
+ mi.pszService = MODULENAME "/mwin_menu";
+ CreateServiceFunction(mi.pszService, GlobalService<&CWeatherProto::Mwin_MenuClicked>);
+ mi.position = -0x7FFFFFF0;
+ mi.hIcolibItem = Skin_GetIconHandle(SKINICON_OTHER_FRAME);
+ mi.root = nullptr;
+ mi.name.a = LPGEN("Display in a frame");
+ g_menuItems.push_back(hMwinMenu = Menu_AddContactMenuItem(&mi));
+ }
+
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, &OnPrebuildMenu);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// adding main menu items
+
+void CWeatherProto::InitMenuItems()
+{
+ CMenuItem mi(&g_plugin);
+ mi.root = g_plugin.addRootMenu(MO_MAIN, m_tszUserName, 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);
mi.name.a = LPGEN("Enable/Disable Weather Update");
mi.hIcolibItem = g_plugin.getIconHandle(IDI_ICON);
mi.position = 10100001;
- mi.pszService = MS_WEATHER_ENABLED;
- hEnableDisableMenu = Menu_AddMainMenuItem(&mi);
+ mi.pszService = "/EnableDisable";
+ hEnableDisableMenu = Menu_AddMainMenuItem(&mi, m_szModuleName);
UpdateMenu(opt.AutoUpdate);
+ CreateProtoService(mi.pszService, &CWeatherProto::EnableDisableCmd);
SET_UID(mi, 0x2b1c2054, 0x2991, 0x4025, 0x87, 0x73, 0xb6, 0xf7, 0x85, 0xac, 0xc7, 0x37);
- CreateServiceFunction(MS_WEATHER_UPDATEALL, UpdateAllInfo);
mi.position = 20100001;
mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE);
mi.name.a = LPGEN("Update All Weather");
- mi.pszService = MS_WEATHER_UPDATEALL;
- Menu_AddMainMenuItem(&mi);
+ mi.pszService = "/UpdateAll";
+ Menu_AddMainMenuItem(&mi, m_szModuleName);
+ CreateProtoService(mi.pszService, &CWeatherProto::UpdateAllInfo);
SET_UID(mi, 0x8234c00e, 0x788e, 0x424f, 0xbc, 0xc4, 0x2, 0xfd, 0x67, 0x58, 0x2d, 0x19);
- CreateServiceFunction(MS_WEATHER_REFRESHALL, UpdateAllRemove);
mi.position = 20100002;
mi.hIcolibItem = g_plugin.getIconHandle(IDI_UPDATE2);
mi.name.a = LPGEN("Remove Old Data then Update All");
- mi.pszService = MS_WEATHER_REFRESHALL;
- Menu_AddMainMenuItem(&mi);
-
- if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
- SET_UID(mi, 0xe193fe9b, 0xf6ad, 0x41ac, 0x95, 0x29, 0x45, 0x4, 0x44, 0xb1, 0xeb, 0x5d);
- mi.pszService = "Weather/mwin_menu";
- CreateServiceFunction(mi.pszService, Mwin_MenuClicked);
- mi.position = -0x7FFFFFF0;
- mi.hIcolibItem = nullptr;
- mi.root = nullptr;
- mi.name.a = LPGEN("Display in a frame");
- hMwinMenu = Menu_AddContactMenuItem(&mi, MODULENAME);
- }
+ mi.pszService = "/RefreshAll";
+ Menu_AddMainMenuItem(&mi, m_szModuleName);
+ CreateProtoService(mi.pszService, &CWeatherProto::UpdateAllRemove);
}
diff --git a/protocols/Weather/src/weather_update.cpp b/protocols/Weather/src/weather_update.cpp
index fc71bfc0a7..806d41002c 100644
--- a/protocols/Weather/src/weather_update.cpp
+++ b/protocols/Weather/src/weather_update.cpp
@@ -26,15 +26,12 @@ menu items).
#include "stdafx.h"
-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;
BOOL Ch = FALSE;
@@ -44,10 +41,10 @@ int UpdateWeather(MCONTACT hContact)
dbv.pszVal = "";
// log to netlib log for debug purpose
- Netlib_LogfW(hNetlibUser, L"************************************************************************");
- int dbres = g_plugin.getWString(hContact, "Nick", &dbv);
+ Netlib_LogfW(m_hNetlibUser, L"************************************************************************");
+ int dbres = 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 +59,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);
@@ -77,19 +77,19 @@ int UpdateWeather(MCONTACT hContact)
// compare the old condition and determine if the weather had changed
if (opt.UpdateOnlyConditionChanged) { // consider condition change
- if (!g_plugin.getWString(hContact, "LastCondition", &dbv)) {
+ if (!getWString(hContact, "LastCondition", &dbv)) {
if (mir_wstrcmpi(winfo.cond, dbv.pwszVal)) Ch = TRUE; // the weather condition is changed
db_free(&dbv);
}
else Ch = TRUE;
- if (!g_plugin.getWString(hContact, "LastTemperature", &dbv)) {
+ if (!getWString(hContact, "LastTemperature", &dbv)) {
if (mir_wstrcmpi(winfo.temp, dbv.pwszVal)) Ch = TRUE; // the temperature is changed
db_free(&dbv);
}
else Ch = TRUE;
}
else { // consider update time change
- if (!g_plugin.getWString(hContact, "LastUpdate", &dbv)) {
+ if (!getWString(hContact, "LastUpdate", &dbv)) {
if (mir_wstrcmpi(winfo.update, dbv.pwszVal)) Ch = TRUE; // the update time is changed
db_free(&dbv);
}
@@ -99,74 +99,60 @@ int UpdateWeather(MCONTACT hContact)
// have weather alert issued?
dbres = db_get_ws(hContact, WEATHERCONDITION, "Alert", &dbv);
if (!dbres && dbv.pwszVal[0] != 0) {
- if (opt.AlertPopup && !g_plugin.getByte(hContact, "DPopUp") && Ch) {
+ if (opt.AlertPopup && !getByte(hContact, "DPopUp") && Ch) {
// display alert popup
CMStringW str(FORMAT, L"Alert for %s%c%s", winfo.city, 255, dbv.pwszVal);
WPShowMessage(str, SM_WEATHERALERT);
}
// alert issued, set display to italic
if (opt.MakeItalic)
- g_plugin.setWord(hContact, "ApparentMode", ID_STATUS_OFFLINE);
+ setWord(hContact, "ApparentMode", ID_STATUS_OFFLINE);
Skin_PlaySound("weatheralert");
}
// alert dropped, set the display back to normal
- else g_plugin.delSetting(hContact, "ApparentMode");
+ else delSetting(hContact, "ApparentMode");
if (!dbres) db_free(&dbv);
// backup current condition for checking if the weather is changed or not
- g_plugin.setWString(hContact, "LastLog", winfo.update);
- g_plugin.setWString(hContact, "LastCondition", winfo.cond);
- g_plugin.setWString(hContact, "LastTemperature", winfo.temp);
- g_plugin.setWString(hContact, "LastUpdate", winfo.update);
+ setWString(hContact, "LastLog", winfo.update);
+ setWString(hContact, "LastCondition", winfo.cond);
+ setWString(hContact, "LastTemperature", winfo.temp);
+ setWString(hContact, "LastUpdate", winfo.update);
// display condition on contact list
int iStatus = MapCondToStatus(winfo.hContact);
if (opt.DisCondIcon && iStatus != ID_STATUS_OFFLINE)
- g_plugin.setWord(hContact, "Status", ID_STATUS_ONLINE);
+ setWord(hContact, "Status", ID_STATUS_ONLINE);
else
- g_plugin.setWord(hContact, "Status", iStatus);
+ setWord(hContact, "Status", iStatus);
AvatarDownloaded(hContact);
- GetDisplay(&winfo, GetTextValue('C'), str2);
- db_set_ws(hContact, "CList", "MyHandle", str2);
+ db_set_ws(hContact, "CList", "MyHandle", GetDisplay(&winfo, GetTextValue('C')));
- GetDisplay(&winfo, GetTextValue('S'), str2);
- if (str2[0])
+ CMStringW str2(GetDisplay(&winfo, GetTextValue('S')));
+ if (!str2.IsEmpty())
db_set_ws(hContact, "CList", "StatusMsg", str2);
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.IsEmpty() ? nullptr : str2.c_str()));
// save descriptions in MyNotes
- GetDisplay(&winfo, GetTextValue('N'), str2);
- db_set_ws(hContact, "UserInfo", "MyNotes", str2);
- GetDisplay(&winfo, GetTextValue('X'), str2);
- db_set_ws(hContact, WEATHERCONDITION, "WeatherInfo", str2);
+ db_set_ws(hContact, "UserInfo", "MyNotes", GetDisplay(&winfo, GetTextValue('N')));
+ db_set_ws(hContact, WEATHERCONDITION, "WeatherInfo", GetDisplay(&winfo, GetTextValue('X')));
// 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);
- }
+ setByte(hContact, "IsUpdated", TRUE);
// logging
if (Ch) {
// play the sound event
Skin_PlaySound("weatherupdated");
- if (g_plugin.getByte(hContact, "File")) {
+ if (getByte(hContact, "File")) {
// external log
- if (!g_plugin.getWString(hContact, "Log", &dbv)) {
+ if (!getWString(hContact, "Log", &dbv)) {
// for the option for overwriting the file, delete old file first
- if (g_plugin.getByte(hContact, "Overwrite"))
+ if (getByte(hContact, "Overwrite"))
DeleteFile(dbv.pwszVal);
// open the file and set point to the end of file
@@ -174,22 +160,19 @@ int UpdateWeather(MCONTACT hContact)
db_free(&dbv);
if (file != nullptr) {
// write data to the file and close
- GetDisplay(&winfo, GetTextValue('E'), str2);
- fputws(str2, file);
+ fputws(GetDisplay(&winfo, GetTextValue('E')), file);
fclose(file);
}
}
}
- if (g_plugin.getByte(hContact, "History")) {
+ if (getByte(hContact, "History")) {
// internal log using history
- GetDisplay(&winfo, GetTextValue('H'), str2);
-
- T2Utf szMessage(str2);
+ T2Utf szMessage(GetDisplay(&winfo, GetTextValue('H')));
DBEVENTINFO dbei = {};
- dbei.szModule = MODULENAME;
- dbei.timestamp = (uint32_t)time(0);
+ dbei.szModule = m_szModuleName;
+ dbei.iTimestamp = (uint32_t)time(0);
dbei.flags = DBEF_READ | DBEF_UTF;
dbei.eventType = EVENTTYPE_MESSAGE;
dbei.pBlob = szMessage;
@@ -198,11 +181,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,111 +197,84 @@ 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)
-{
- UPDATELIST *newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST));
- newItem->hContact = hContact;
- newItem->next = nullptr;
-
- WaitForSingleObject(hUpdateMutex, INFINITE);
-
- if (UpdateListTail == nullptr) UpdateListHead = newItem;
- else UpdateListTail->next = newItem;
- UpdateListTail = newItem;
- ReleaseMutex(hUpdateMutex);
+void CWeatherProto::UpdateListAdd(MCONTACT hContact)
+{
+ mir_cslock lck(m_csUpdate);
+ m_updateList.push_back(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;
-
- WaitForSingleObject(hUpdateMutex, INFINITE);
-
- if (UpdateListHead != nullptr) {
- UPDATELIST *Item = UpdateListHead;
-
- hContact = Item->hContact;
- UpdateListHead = Item->next;
- mir_free(Item);
-
- if (UpdateListHead == nullptr)
- UpdateListTail = nullptr;
- }
-
- ReleaseMutex(hUpdateMutex);
+ mir_cslock lck(m_csUpdate);
+ if (m_updateList.empty())
+ return 0;
+ auto it = m_updateList.begin();
+ MCONTACT hContact = *it;
+ m_updateList.erase(it);
return hContact;
}
-void DestroyUpdateList(void)
+void CWeatherProto::DestroyUpdateList(void)
{
- WaitForSingleObject(hUpdateMutex, INFINITE);
-
- // free the list one by one
- UPDATELIST *temp = UpdateListHead;
- while (temp != nullptr) {
- UpdateListHead = temp->next;
- mir_free(temp);
- temp = UpdateListHead;
- }
- // make sure the entire list is clear
- UpdateListTail = nullptr;
-
- ReleaseMutex(hUpdateMutex);
+ mir_cslock lck(m_csUpdate);
+ m_updateList.clear();
}
+/////////////////////////////////////////////////////////////////////////////////////////
// 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) {
- ReleaseMutex(hUpdateMutex);
- return;
+ { mir_cslock lck(m_csUpdate);
+ if (m_bThreadRunning)
+ return;
+
+ m_bThreadRunning = true; // prevent 2 instance of this thread running
}
- ThreadRunning = TRUE; // prevent 2 instance of this thread running
- ReleaseMutex(hUpdateMutex);
// update weather by getting the first station from the queue until the queue is empty
- while (UpdateListHead != nullptr && !Miranda_IsTerminated())
+ while (!m_updateList.empty() && !Miranda_IsTerminated())
UpdateWeather(UpdateGetFirst());
// exit the update thread
- ThreadRunning = FALSE;
+ m_bThreadRunning = 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))
- if (!g_plugin.getByte(hContact, "AutoUpdate") || !AutoUpdate) {
+ for (auto &hContact : AccContacts())
+ if (!getByte(hContact, "AutoUpdate") || !AutoUpdate) {
if (RemoveData)
- DBDataManage(hContact, WDBM_REMOVE, 0, 0);
+ db_delete_module(hContact, WEATHERCONDITION);
UpdateListAdd(hContact);
}
// 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);
+ if (!m_bThreadRunning)
+ 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
@@ -327,278 +283,244 @@ INT_PTR UpdateSingleStation(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);
+ if (!m_bThreadRunning)
+ 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 hContact, LPARAM)
{
- if (IsMyContact(wParam)) {
+ if (IsMyContact(hContact)) {
// add the station to the end of the update queue, and also remove old data
- DBDataManage(wParam, WDBM_REMOVE, 0, 0);
- UpdateListAdd(wParam);
+ db_delete_module(hContact, WEATHERCONDITION);
+ UpdateListAdd(hContact);
// 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);
+ if (!m_bThreadRunning)
+ 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)
+ if (!m_bThreadRunning)
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)
+ if (!m_bThreadRunning)
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)
-{
- // get each part of the id's
- wchar_t id[256];
- GetStationID(hContact, id, _countof(id));
-
- // test ID format
- wchar_t *szInfo = wcschr(id, '/');
- if (szInfo == nullptr)
- return INVALID_ID_FORMAT;
-
- GetID(id);
-
- wchar_t Svc[256];
- GetStationID(hContact, Svc, _countof(Svc));
- GetSvc(Svc);
-
- // check for invalid station
- if (id[0] == 0) return INVALID_ID;
- if (Svc[0] == 0) return INVALID_SVC;
- // get the update strings (loaded to memory from ini files)
- WIDATA *Data = GetWIData(Svc);
- if (Data == nullptr)
- return SVC_NOT_FOUND; // the ini for the station cannot be found
+static wchar_t *moon2str(double phase)
+{
+ if (phase < 0.05) return TranslateT("New moon");
+ if (phase < 0.26) return TranslateT("Waxing crescent");
+ if (phase < 0.51) return TranslateT("Waxing gibbous");
+ if (phase < 0.76) return TranslateT("Waning gibbous");
+ return TranslateT("Waning crescent");
+}
- uint16_t cond = NA;
- char loc[256];
- for (int i = 0; i < 4; ++i) {
- // generate update URL
- switch (i) {
- case 0:
- mir_snprintf(loc, Data->UpdateURL, _T2A(id).get());
+static CMStringW parseConditions(const CMStringW &str)
+{
+ CMStringW ret;
+ int iStart = 0;
+ while (true) {
+ auto substr = str.Tokenize(L",", iStart);
+ if (substr.IsEmpty())
break;
- case 1:
- mir_snprintf(loc, Data->UpdateURL2, _T2A(id).get());
- break;
+ substr.Trim();
+ if (!ret.IsEmpty())
+ ret += ", ";
+ ret += TranslateW(substr);
+ }
+ return ret;
+}
- case 2:
- mir_snprintf(loc, Data->UpdateURL3, _T2A(id).get());
- break;
+static double g_elevation = 0;
- case 3:
- mir_snprintf(loc, Data->UpdateURL4, _T2A(id).get());
- break;
+static void getData(OBJLIST<WIDATAITEM> &arValues, const JSONNode &node)
+{
+ arValues.insert(new WIDATAITEM(LPGENW("Date"), L"", node["datetime"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Condition"), L"", parseConditions(node["conditions"].as_mstring())));
+ arValues.insert(new WIDATAITEM(LPGENW("Temperature"), L"C", node["temp"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("High"), L"C", node["tempmax"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Low"), L"C", node["tempmin"].as_mstring()));
+
+ CMStringW wszPressure(FORMAT, L"%lf", node["pressure"].as_float() - g_elevation);
+ arValues.insert(new WIDATAITEM(LPGENW("Pressure"), L"mb", wszPressure));
+
+ arValues.insert(new WIDATAITEM(LPGENW("Sunset"), L"", node["sunset"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Sunrise"), L"", node["sunrise"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Moon phase"), L"", moon2str(node["moonphase"].as_float())));
+ arValues.insert(new WIDATAITEM(LPGENW("Wind speed"), L"km/h", node["windspeed"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Wind direction"), L"grad", node["winddir"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Dew point"), L"C", node["dew"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Visibility"), L"km", node["visibility"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Humidity"), L"", node["humidity"].as_mstring()));
+ arValues.insert(new WIDATAITEM(LPGENW("Feel"), L"C", node["feelslike"].as_mstring()));
+}
- default:
- continue;
- }
+int CWeatherProto::GetWeatherData(MCONTACT hContact)
+{
+ // get each part of the id's
+ CMStringW wszID(getMStringW(hContact, "ID"));
+ if (wszID.IsEmpty())
+ return INVALID_ID;
- if (loc[0] == 0)
- continue;
+ uint16_t cond = NA;
- // download the html file from the internet
- wchar_t *szData = nullptr;
- int retval = InternetDownloadFile(loc, Data->Cookie, Data->UserAgent, &szData);
- if (retval != 0) {
- mir_free(szData);
- return retval;
- }
- if (wcsstr(szData, L"Document Not Found") != nullptr) {
- mir_free(szData);
- return DOC_NOT_FOUND;
- }
+ // download the html file from the internet
+ WeatherReply reply(RunQuery(wszID, 7));
+ if (!reply)
+ return reply.error();
+
+ auto &root = reply.data();
+
+ // writing current conditions
+ auto &curr = root["currentConditions"];
+ g_elevation = root["elevation"].as_float() / 7.877;
+
+ WIDATAITEMLIST arValues;
+ getData(arValues, curr);
+
+ auto szIcon = curr["icon"].as_string();
+ if (szIcon == "snow")
+ cond = SNOW;
+ else if (szIcon == "snow-showers-day" || szIcon == "snow-showers-night")
+ cond = SSHOWER;
+ else if (szIcon == "thunder" || szIcon == "thunder-showers-day" || szIcon == "thunder-showers-night")
+ cond = LIGHT;
+ else if (szIcon == "partly-cloudy-day" || szIcon == "partly-cloudy-night" || szIcon == "wind")
+ cond = PCLOUDY;
+ else if (szIcon == "fog")
+ cond = FOG;
+ else if (szIcon == "rain")
+ cond = RAIN;
+ else if (szIcon == "showers-day" || szIcon == "showers-night")
+ cond = RSHOWER;
+ else if (szIcon == "clear-day" || szIcon == "clear-night")
+ cond = SUNNY;
+ else if (szIcon == "rain")
+ cond = RAIN;
+ else if (szIcon == "cloudy")
+ cond = CLOUDY;
+
+ // writing forecast
+ db_set_ws(hContact, WEATHERCONDITION, "Update", curr["datetime"].as_mstring());
+
+ for (auto &it : arValues) {
+ ConvertDataValue(it);
+ if (!it->Value.IsEmpty())
+ db_set_ws(hContact, WEATHERCONDITION, _T2A(it->Name), it->Value);
+ }
- szInfo = szData;
- WIDATAITEMLIST *Item = Data->UpdateData;
+ int iFore = 0;
+ for (auto &fore : root["days"]) {
+ WIDATAITEMLIST arDaily;
+ getData(arDaily, fore);
- // begin parsing item by item
- while (Item != nullptr) {
- if (Item->Item.Url[0] != 0 && Item->Item.Url[0] != (i + '1')) {
- Item = Item->Next;
+ CMStringW result;
+ for (auto &it : arDaily) {
+ ConvertDataValue(it);
+ if (it->Value.IsEmpty())
continue;
- }
- wchar_t DataValue[MAX_DATA_LEN];
- switch (Item->Item.Type) {
- case WID_NORMAL:
- // if it is a normal item with start= and end=, then parse through the downloaded string
- // to get a data value.
- GetDataValue(&Item->Item, DataValue, &szInfo);
- if (mir_wstrcmp(Item->Item.Name, L"Condition") && mir_wstrcmpi(Item->Item.Unit, L"Cond"))
- wcsncpy(DataValue, TranslateW(DataValue), MAX_DATA_LEN - 1);
- break;
-
- case WID_SET:
- {
- // for the "Set Data=" operation
- DBVARIANT dbv;
- wchar_t *chop, *str, str2[MAX_DATA_LEN];
- BOOL hasvar = FALSE;
- size_t stl;
-
- // get the set data operation string
- str = Item->Item.End;
- DataValue[0] = 0;
- // go through each part of the operation string seperated by the & operator
- do {
- // the end of the string, last item
- chop = wcsstr(str, L" & ");
- if (chop == nullptr)
- chop = wcschr(str, '\0');
-
- stl = min(sizeof(str2) - 1, (unsigned)(chop - str - 2));
- wcsncpy(str2, str + 1, stl);
- str2[stl] = 0;
-
- switch (str[0]) {
- case '[': // variable, add the value to the result string
- hasvar = TRUE;
- if (!DBGetData(hContact, _T2A(str2), &dbv)) {
- mir_wstrncat(DataValue, TranslateW(dbv.pwszVal), _countof(DataValue) - mir_wstrlen(DataValue));
- DataValue[_countof(DataValue) - 1] = 0;
- db_free(&dbv);
- }
- break;
-
- case'\"': // constant, add it to the result string
- mir_wstrncat(DataValue, TranslateW(str2), _countof(DataValue) - mir_wstrlen(DataValue));
- DataValue[_countof(DataValue) - 1] = 0;
- break;
- }
-
- // remove the front part of the string that is done and continue parsing
- str = chop + 3;
- } while (chop[0] && str[0]);
-
- if (!hasvar) ConvertDataValue(&Item->Item, DataValue);
- break;
- }
- case WID_BREAK:
- {
- // for the "Break Data=" operation
- DBVARIANT dbv;
- if (!DBGetData(hContact, _T2A(Item->Item.Start), &dbv)) {
- wcsncpy(DataValue, dbv.pwszVal, _countof(DataValue));
- DataValue[_countof(DataValue) - 1] = 0;
- db_free(&dbv);
- }
- else {
- DataValue[0] = 0;
- break; // do not continue if the source is invalid
- }
-
- // generate the strings
- wchar_t *end = wcsstr(DataValue, Item->Item.Break);
- if (end == nullptr) {
- DataValue[0] = 0;
- break; // exit if break string is not found
- }
- *end = '\0';
- end += mir_wstrlen(Item->Item.Break);
- while (end[0] == ' ')
- end++; // remove extra space
-
- ConvertDataValue(&Item->Item, DataValue);
-
- // write the 2 strings created from the break operation
- if (Item->Item.End[0])
- db_set_ws(hContact, WEATHERCONDITION, _T2A(Item->Item.End), end);
- break;
- }
- }
+ // insert missing values from day 0 into current
+ if (iFore == 0)
+ if (auto *pOld = arValues.Find(it->Name))
+ if (pOld->Value.IsEmpty() || pOld->Value == NODATA)
+ db_set_ws(hContact, WEATHERCONDITION, _T2A(it->Name), it->Value);
- // don't store data if it is not available
- if ((DataValue[0] != 0 && mir_wstrcmp(DataValue, NODATA) &&
- mir_wstrcmp(DataValue, TranslateW(NODATA)) && mir_wstrcmp(Item->Item.Name, L"Ignore")) ||
- (!mir_wstrcmp(Item->Item.Name, L"Alert") && i == 0)) {
- // temporary workaround for mToolTip to show feel-like temperature
- if (!mir_wstrcmp(Item->Item.Name, L"Feel"))
- db_set_ws(hContact, WEATHERCONDITION, "Heat Index", DataValue);
- GetStationID(hContact, Svc, _countof(Svc));
- if (!mir_wstrcmp(Svc, opt.Default))
- db_set_ws(0, DEFCURRENTWEATHER, _T2A(Item->Item.Name), DataValue);
- if (!mir_wstrcmp(Item->Item.Name, L"Condition")) {
- wchar_t buf[128], *cbuf;
- mir_snwprintf(buf, L"#%s Weather", DataValue);
- cbuf = TranslateW(buf);
- if (cbuf[0] == '#')
- cbuf = TranslateW(DataValue);
- db_set_ws(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), cbuf);
- CharLowerBuff(DataValue, (uint32_t)mir_wstrlen(DataValue));
- cond = GetIcon(DataValue, Data);
- }
- else if (mir_wstrcmpi(Item->Item.Unit, L"Cond") == 0) {
- wchar_t buf[128], *cbuf;
- mir_snwprintf(buf, L"#%s Weather", DataValue);
- cbuf = TranslateW(buf);
- if (cbuf[0] == '#')
- cbuf = TranslateW(DataValue);
- db_set_ws(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), cbuf);
- }
- else db_set_ws(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), DataValue);
- }
- Item = Item->Next;
+ if (!result.IsEmpty())
+ result += L"; ";
+ result.AppendFormat(L"%s: %s", TranslateW(it->Name), it->Value.c_str());
}
- mir_free(szData);
+
+ CMStringA szSetting(FORMAT, "Forecast Day %d", iFore++);
+ db_set_ws(hContact, WEATHERCONDITION, szSetting, result);
+ arValues.destroy();
}
// assign condition icon
- g_plugin.setWord(hContact, "StatusIcon", cond);
+ setWord(hContact, "StatusIcon", cond);
return 0;
}
-//============ UPDATE TIMERS ============
-//
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int enumSettings(const char *pszSetting, void *param)
+{
+ auto *pList = (OBJLIST<char>*)param;
+ if (!pList->find((char*)pszSetting))
+ pList->insert(newStr(pszSetting));
+ return 0;
+}
+
+void CWeatherProto::GetVarsDescr(CMStringW &wszDescr)
+{
+ OBJLIST<char> vars(10, strcmp);
+ for (int i = 1; i <= 7; i++)
+ vars.insert(newStr(CMStringA(FORMAT, "Forecast Day %d", i)));
+
+ for (auto &cc : AccContacts())
+ db_enum_settings(cc, &enumSettings, WEATHERCONDITION, &vars);
+
+ CMStringW str;
+ for (auto &it : vars) {
+ if (!str.IsEmpty())
+ str.Append(L", ");
+ str.AppendFormat(L"%%[%S]", it);
+ }
+ wszDescr += str;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
// 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 (!m_bThreadRunning && 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;
+ m_bThreadRunning = 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..1207d01b4a 100644
--- a/protocols/Weather/src/weather_userinfo.cpp
+++ b/protocols/Weather/src/weather_userinfo.cpp
@@ -27,232 +27,252 @@ 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;
+/////////////////////////////////////////////////////////////////////////////////////////
+// dialog for more data in the user info window
- case IDC_MUPDATE:
- return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+static unsigned tabstops = 48;
- case IDC_MTOGGLE:
- case IDC_MWEBPAGE:
- case IDCANCEL:
- return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
- }
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+static int GetWeatherDataFromDB(const char *szSetting, void *lparam)
+{
+ auto *pList = (OBJLIST<char>*)lparam;
+ pList->insert(newStr(szSetting));
+ return 0;
}
-// 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];
+ MCONTACT hContact;
+ wchar_t m_buf[4098];
+ int iOldItem = -1;
- // 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);
-}
+ CTimer m_timer;
+ CCtrlButton btnUpdate, btnWebpage, btnToggle;
+ CCtrlListView m_list;
-// 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),
+ m_list(this, IDC_DATALIST),
+ m_timer(this, 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);
+ m_list.OnHotTrack = Callback(this, &CBriefInfoDlg::onList_Track);
- 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);
+ m_timer.OnEvent = Callback(this, &CBriefInfoDlg::onTimer);
+
+ btnToggle.OnClick = Callback(this, &CBriefInfoDlg::onClick_Toggle);
+ btnUpdate.OnClick = Callback(this, &CBriefInfoDlg::onClick_Update);
+ btnWebpage.OnClick = Callback(this, &CBriefInfoDlg::onClick_Webpage);
+ }
+
+ 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);
RECT aRect = {};
- GetClientRect(hList, &aRect);
+ GetClientRect(m_list.GetHwnd(), &aRect);
// managing styles
- lvc.mask = LVCF_WIDTH | LVCF_TEXT;
- ListView_SetExtendedListViewStyleEx(hList,
- LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
- LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
+ DWORD dwStyle = LVS_EX_FULLROWSELECT;
+ m_list.SetExtendedListViewStyleEx(dwStyle, dwStyle);
// inserting columns
+ LV_COLUMN lvc = {};
+ lvc.mask = LVCF_WIDTH | LVCF_TEXT;
+
lvc.cx = LIST_COLUMN;
lvc.pszText = TranslateT("Variable");
- ListView_InsertColumn(hList, 0, &lvc);
+ m_list.InsertColumn(0, &lvc);
lvc.cx = aRect.right - LIST_COLUMN - GetSystemMetrics(SM_CXVSCROLL) - 3;
lvc.pszText = TranslateT("Information");
- ListView_InsertColumn(hList, 1, &lvc);
+ m_list.InsertColumn(1, &lvc);
- // inserting data
- SendMessage(hwndDlg, WM_UPDATEDATA, 0, 0);
+ // insert data
+ OnUpdate();
}
- TranslateDialogDefault(hwndDlg);
// 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;
+ Utils_RestoreWindowPositionNoMove(m_hwnd, NULL, MODULENAME, "BriefInfo_");
+ return true;
+ }
- case WM_UPDATEDATA:
- ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_DATALIST));
- LoadBriefInfoText(hwndDlg, hContact);
- DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)hwndDlg, 0);
+ void OnDestroy() override
+ {
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_BIG, 0));
+ DestroyIcon((HICON)SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, 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)));
- }
+ Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "BriefInfo_");
+ WindowList_Remove(hDataWindowList, m_hwnd);
+ }
- RedrawWindow(GetDlgItem(hwndDlg, IDC_HEADERBAR), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
- break;
+ int Resizer(UTILRESIZECONTROL *urc) override
+ {
+ switch (urc->wId) {
+ case IDC_HEADERBAR:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH;
- 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));
+ case IDC_MTEXT:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+ case IDC_DATALIST:
+ m_list.SetColumnWidth(1, urc->dlgNewSize.cx - m_list.GetColumnWidth(0) - GetSystemMetrics(SM_CXVSCROLL));
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
- Utils_ResizeDialog(hwndDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_BRIEF), BriefDlgResizer);
+ 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;
}
- break;
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+ }
- case WM_GETMINMAXINFO:
- {
- LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;
+ INT_PTR OnUpdate(UINT = 0, WPARAM = 0, LPARAM = 0)
+ {
+ m_list.DeleteAllItems();
+
+ // load weather information from the contact into the WEATHERINFO struct
+ WEATHERINFO winfo = m_proto->LoadWeatherInfo(hContact);
+ // check if data exist. If not, display error message box
+ if (!m_proto->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
+ SetDlgItemTextW(m_hwnd, IDC_MTEXT, GetDisplay(&winfo, m_proto->GetTextValue('B')));
+ }
- // The minimum width in points
- mmi->ptMinTrackSize.x = 350;
- // The minimum height in points
- mmi->ptMinTrackSize.y = 300;
+ SetWindowTextW(m_hwnd, winfo.city);
+ SetDlgItemTextW(m_hwnd, IDC_HEADERBAR, GetDisplay(&winfo, L"%c, %t"));
+
+ // get all the settings and store them in a temporary list
+ LIST<char> arSettings(10);
+ db_enum_settings(hContact, GetWeatherDataFromDB, WEATHERCONDITION, &arSettings);
+
+ auto T = arSettings.rev_iter();
+ for (auto &it: T) {
+ CMStringW wszText(db_get_wsm(hContact, WEATHERCONDITION, it));
+ if (wszText.IsEmpty())
+ continue;
+
+ // skip the "WeatherInfo" variable
+ if (!mir_strcmp(it, "WeatherInfo") || !mir_strcmp(it, "Ignore") || it[0] == '#')
+ continue;
+
+ wszText.Replace(L"; ", L";\r\n ");
+
+ _A2T strW(it);
+ LV_ITEM lvi = {};
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.lParam = T.indexOf(&it);
+ lvi.pszText = TranslateW(strW);
+ lvi.iItem = m_list.InsertItem(&lvi);
+ lvi.pszText = wszText.GetBuffer();
+ m_list.SetItemText(lvi.iItem, 1, wszText);
}
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDCANCEL:
- // close the info window
- DestroyWindow(hwndDlg);
- break;
+ // set icons
+ HICON hIcon = m_proto->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 IDC_MUPDATE:
- {
- 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;
- }
+ RedrawWindow(GetDlgItem(m_hwnd, IDC_HEADERBAR), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+ return 0;
+ }
- case IDC_MWEBPAGE:
- LoadForecast(hContact, 0); // read complete forecast
- break;
+ void onList_Track(CCtrlListView::TEventInfo *ev)
+ {
+ auto *nlv = ev->nmlv;
+ if (nlv->iItem == -1 || nlv->iItem == iOldItem || nlv->iSubItem != 1)
+ return;
- 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;
- }
- break;
+ iOldItem = nlv->iItem;
- 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;
- }
- }
- }
- break;
+ m_list.GetItemText(nlv->iItem, nlv->iSubItem, m_buf, _countof(m_buf));
+ m_timer.Start(100);
+ }
- case WM_CLOSE:
- DestroyWindow(hwndDlg);
- break;
+ void onTimer(CTimer *pTimer)
+ {
+ pTimer->Stop();
- case WM_DESTROY:
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
- DestroyIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
+ if (wcslen(m_buf) > 50) {
+ CLCINFOTIP ti = {};
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.hItem = (HANDLE)iOldItem;
+ Tipper_ShowTip(m_buf, &ti);
+ }
+ else Tipper_Hide();
+ }
- Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, "BriefInfo_");
- WindowList_Remove(hDataWindowList, hwndDlg);
- break;
+ void onClick_Update(CCtrlButton *)
+ {
+ // update current data
+ // set the text to "updating"
+ SetDlgItemText(m_hwnd, IDC_MTEXT, TranslateT("Retrieving new data, please wait..."));
+ m_list.DeleteAllItems();
+
+ LV_ITEM lvi = {};
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.lParam = 1;
+ lvi.pszText = L"";
+ lvi.iItem = m_list.InsertItem(&lvi);
+ lvi.pszText = TranslateT("Retrieving new data, please wait...");
+ m_list.SetItemText(lvi.iItem, 1, lvi.pszText);
+ m_proto->UpdateSingleStation(hContact, 0);
}
- return FALSE;
-}
+ void onClick_Webpage(CCtrlButton *)
+ {
+ m_proto->LoadForecast(hContact, 0); // read complete forecast
+ }
+
+ void onClick_Toggle(CCtrlButton *)
+ {
+ if (IsWindowVisible(m_list.GetHwnd()))
+ SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("More Info"));
+ else
+ SetDlgItemText(m_hwnd, IDC_MTOGGLE, TranslateT("Brief Info"));
+ ShowWindow(m_list.GetHwnd(), (int)!IsWindowVisible(m_list.GetHwnd()));
+ ShowWindow(GetDlgItem(m_hwnd, IDC_MTEXT), (int)!IsWindowVisible(GetDlgItem(m_hwnd, IDC_MTEXT)));
+ }
+};
-// show brief information dialog
-// wParam = current contact
-int BriefInfo(WPARAM wParam, LPARAM)
+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,12 +280,18 @@ int BriefInfo(WPARAM wParam, LPARAM)
return 1;
}
+int CWeatherProto::BriefInfoEvt(WPARAM wParam, LPARAM)
+{
+ return BriefInfo(wParam, 0);
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// User info dialog
class WeatherUserInfoDlg : public CUserInfoPageDlg
{
CCtrlButton btnDetail;
+ CWeatherProto *ppro;
public:
WeatherUserInfoDlg() :
@@ -278,13 +304,13 @@ public:
bool OnInitDialog() override
{
SendDlgItemMessage(m_hwnd, IDC_MOREDETAIL, BUTTONSETASFLATBTN, TRUE, 0);
+ ppro = (CWeatherProto *)Proto_GetContactInstance(m_hContact);
// load weather info for the contact
- wchar_t str[MAX_TEXT_SIZE];
- WEATHERINFO w = LoadWeatherInfo(m_hContact);
- SetDlgItemText(m_hwnd, IDC_INFO1, GetDisplay(&w, TranslateT("Current condition for %n"), str));
+ WEATHERINFO w = ppro->LoadWeatherInfo(m_hContact);
+ SetDlgItemText(m_hwnd, IDC_INFO1, GetDisplay(&w, TranslateT("Current condition for %n")));
- SendDlgItemMessage(m_hwnd, IDC_INFOICON, STM_SETICON, (WPARAM)GetStatusIconBig(m_hContact), 0);
+ SendDlgItemMessage(m_hwnd, IDC_INFOICON, STM_SETICON, (WPARAM)ppro->GetStatusIconBig(m_hContact), 0);
// bold and enlarge the current condition
LOGFONT lf;
@@ -296,19 +322,16 @@ public:
SendDlgItemMessage(m_hwnd, IDC_INFO2, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0);
// set the text for displaying other current weather conditions data
- GetDisplay(&w, L"%c %t", str);
- SetDlgItemText(m_hwnd, IDC_INFO2, str);
+ SetDlgItemText(m_hwnd, IDC_INFO2, GetDisplay(&w, L"%c %t"));
SetDlgItemText(m_hwnd, IDC_INFO3, w.feel);
SetDlgItemText(m_hwnd, IDC_INFO4, w.pressure);
- GetDisplay(&w, L"%i %w", str);
- SetDlgItemText(m_hwnd, IDC_INFO5, str);
+ SetDlgItemText(m_hwnd, IDC_INFO5, GetDisplay(&w, L"%i %w"));
SetDlgItemText(m_hwnd, IDC_INFO6, w.dewpoint);
SetDlgItemText(m_hwnd, IDC_INFO7, w.sunrise);
SetDlgItemText(m_hwnd, IDC_INFO8, w.sunset);
SetDlgItemText(m_hwnd, IDC_INFO9, w.high);
SetDlgItemText(m_hwnd, IDC_INFO10, w.low);
- GetDisplay(&w, TranslateT("Last update on: %u"), str);
- SetDlgItemText(m_hwnd, IDC_INFO11, str);
+ SetDlgItemText(m_hwnd, IDC_INFO11, GetDisplay(&w, TranslateT("Last update on: %u")));
SetDlgItemText(m_hwnd, IDC_INFO12, w.humid);
SetDlgItemText(m_hwnd, IDC_INFO13, w.vis);
return true;
@@ -323,8 +346,11 @@ 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 *pDlg = new CBriefInfoDlg(ppro, m_hContact);
+ pDlg->Create();
+ hMoreDataDlg = pDlg->GetHwnd();
+ }
else {
SetForegroundWindow(hMoreDataDlg);
SetFocus(hMoreDataDlg);
@@ -334,21 +360,16 @@ public:
}
};
-int UserInfoInit(WPARAM wParam, LPARAM hContact)
+int CWeatherProto::UserInfoInit(WPARAM wParam, LPARAM hContact)
{
- USERINFOPAGE uip = {};
- uip.szTitle.a = MODULENAME;
- uip.position = 100000000;
- uip.flags = ODPF_ICON;
- uip.dwInitParam = LPARAM(g_plugin.getIconHandle(IDI_ICON));
-
- if (hContact == 0) {
- uip.pDialog = new WeatherMyDetailsDlg();
- g_plugin.addUserInfo(wParam, &uip);
- }
- else if (IsMyContact(hContact)) { // check if it is a weather contact
+ // check if it is a weather contact
+ if (IsMyContact(hContact)) {
+ USERINFOPAGE uip = {};
+ uip.szTitle.w = m_tszUserName;
+ uip.position = 100000000;
+ uip.flags = ODPF_ICON | ODPF_BOLDGROUPS | ODPF_UNICODE;
+ uip.dwInitParam = LPARAM(g_plugin.getIconHandle(IDI_ICON));
uip.pDialog = new WeatherUserInfoDlg();
- uip.flags |= ODPF_BOLDGROUPS;
g_plugin.addUserInfo(wParam, &uip);
}
return 0;
diff --git a/protocols/Weather/weather.vcxproj b/protocols/Weather/weather.vcxproj
index 35e9cf3032..56a2b52edd 100644
--- a/protocols/Weather/weather.vcxproj
+++ b/protocols/Weather/weather.vcxproj
@@ -34,15 +34,14 @@
<ClCompile Include="src\weather_contacts.cpp" />
<ClCompile Include="src\weather_conv.cpp" />
<ClCompile Include="src\weather_data.cpp" />
- <ClCompile Include="src\weather_http.cpp" />
- <ClCompile Include="src\weather_info.cpp" />
- <ClCompile Include="src\weather_ini.cpp" />
<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..92a72a4653 100644
--- a/protocols/Weather/weather.vcxproj.filters
+++ b/protocols/Weather/weather.vcxproj.filters
@@ -20,15 +20,6 @@
<ClCompile Include="src\weather_data.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\weather_http.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\weather_info.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\weather_ini.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\weather_mwin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -47,6 +38,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 +52,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">