summaryrefslogtreecommitdiff
path: root/plugins/Weather
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Weather')
-rw-r--r--plugins/Weather/docs/license.txt340
-rw-r--r--plugins/Weather/docs/sample_ini.ini421
-rw-r--r--plugins/Weather/docs/weather-history.txt930
-rw-r--r--plugins/Weather/docs/weather-readme.html230
-rw-r--r--plugins/Weather/proto_weather/proto_weather_10.vcxproj128
-rw-r--r--plugins/Weather/proto_weather/proto_weather_10.vcxproj.filters14
-rw-r--r--plugins/Weather/proto_weather/res/Cloud.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/FOG.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/LIGHT.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/NA.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/PCLOUDY.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/RAIN.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/RSHOWER.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/SNOW.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/SSHOWER.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/SUN.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/proto_weather/res/resource.rc41
-rw-r--r--plugins/Weather/res/brief.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/disabled.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/edit.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/icon.icobin0 -> 6830 bytes
-rw-r--r--plugins/Weather/res/info.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/infologo.icobin0 -> 2238 bytes
-rw-r--r--plugins/Weather/res/log.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/map.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/more.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/popup.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/popup_no.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/reload.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/resource.rc467
-rw-r--r--plugins/Weather/res/update.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/res/update2.icobin0 -> 2550 bytes
-rw-r--r--plugins/Weather/src/resource.h176
-rw-r--r--plugins/Weather/src/stdafx.cpp18
-rw-r--r--plugins/Weather/src/version.h6
-rw-r--r--plugins/Weather/src/weather.cpp266
-rw-r--r--plugins/Weather/src/weather.h545
-rw-r--r--plugins/Weather/src/weather_addstn.cpp428
-rw-r--r--plugins/Weather/src/weather_contacts.cpp486
-rw-r--r--plugins/Weather/src/weather_conv.cpp644
-rw-r--r--plugins/Weather/src/weather_data.cpp472
-rw-r--r--plugins/Weather/src/weather_http.cpp206
-rw-r--r--plugins/Weather/src/weather_icons.cpp87
-rw-r--r--plugins/Weather/src/weather_info.cpp252
-rw-r--r--plugins/Weather/src/weather_ini.cpp613
-rw-r--r--plugins/Weather/src/weather_mwin.cpp420
-rw-r--r--plugins/Weather/src/weather_opt.cpp642
-rw-r--r--plugins/Weather/src/weather_popup.cpp438
-rw-r--r--plugins/Weather/src/weather_svcs.cpp386
-rw-r--r--plugins/Weather/src/weather_update.cpp615
-rw-r--r--plugins/Weather/src/weather_userinfo.cpp402
-rw-r--r--plugins/Weather/weather_10.vcxproj218
-rw-r--r--plugins/Weather/weather_10.vcxproj.filters86
53 files changed, 9977 insertions, 0 deletions
diff --git a/plugins/Weather/docs/license.txt b/plugins/Weather/docs/license.txt
new file mode 100644
index 0000000000..45645b4b53
--- /dev/null
+++ b/plugins/Weather/docs/license.txt
@@ -0,0 +1,340 @@
+ 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/plugins/Weather/docs/sample_ini.ini b/plugins/Weather/docs/sample_ini.ini
new file mode 100644
index 0000000000..dc36eda754
--- /dev/null
+++ b/plugins/Weather/docs/sample_ini.ini
@@ -0,0 +1,421 @@
+[Weather 0.3.x Update Data 1.4]
+
+; 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)
+
+; 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.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.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=
+
+; ======================================================================================
+
+; 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/plugins/Weather/docs/weather-history.txt b/plugins/Weather/docs/weather-history.txt
new file mode 100644
index 0000000000..ff936f56f2
--- /dev/null
+++ b/plugins/Weather/docs/weather-history.txt
@@ -0,0 +1,930 @@
+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/plugins/Weather/docs/weather-readme.html b/plugins/Weather/docs/weather-readme.html
new file mode 100644
index 0000000000..ff81561171
--- /dev/null
+++ b/plugins/Weather/docs/weather-readme.html
@@ -0,0 +1,230 @@
+<!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/plugins/Weather/proto_weather/proto_weather_10.vcxproj b/plugins/Weather/proto_weather/proto_weather_10.vcxproj
new file mode 100644
index 0000000000..8187912e95
--- /dev/null
+++ b/plugins/Weather/proto_weather/proto_weather_10.vcxproj
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>Proto_Weather</ProjectName>
+ <ProjectGuid>{B2F4BA6C-1BD6-4A50-A706-DCBC6A5D439B}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Icons\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <NoEntryPoint>true</NoEntryPoint>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Weather/proto_weather/proto_weather_10.vcxproj.filters b/plugins/Weather/proto_weather/proto_weather_10.vcxproj.filters
new file mode 100644
index 0000000000..27e90fab59
--- /dev/null
+++ b/plugins/Weather/proto_weather/proto_weather_10.vcxproj.filters
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Weather/proto_weather/res/Cloud.ico b/plugins/Weather/proto_weather/res/Cloud.ico
new file mode 100644
index 0000000000..2edb539dcb
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/Cloud.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/FOG.ico b/plugins/Weather/proto_weather/res/FOG.ico
new file mode 100644
index 0000000000..fbd81b9a03
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/FOG.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/LIGHT.ico b/plugins/Weather/proto_weather/res/LIGHT.ico
new file mode 100644
index 0000000000..d266094fbe
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/LIGHT.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/NA.ico b/plugins/Weather/proto_weather/res/NA.ico
new file mode 100644
index 0000000000..3e4a3aa324
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/NA.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/PCLOUDY.ico b/plugins/Weather/proto_weather/res/PCLOUDY.ico
new file mode 100644
index 0000000000..be3d0c88bd
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/PCLOUDY.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/RAIN.ico b/plugins/Weather/proto_weather/res/RAIN.ico
new file mode 100644
index 0000000000..4b65fb6714
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/RAIN.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/RSHOWER.ico b/plugins/Weather/proto_weather/res/RSHOWER.ico
new file mode 100644
index 0000000000..442552e155
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/RSHOWER.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/SNOW.ico b/plugins/Weather/proto_weather/res/SNOW.ico
new file mode 100644
index 0000000000..1a482c3bc8
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/SNOW.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/SSHOWER.ico b/plugins/Weather/proto_weather/res/SSHOWER.ico
new file mode 100644
index 0000000000..0bd2264413
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/SSHOWER.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/SUN.ico b/plugins/Weather/proto_weather/res/SUN.ico
new file mode 100644
index 0000000000..b37fc6ad2a
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/SUN.ico
Binary files differ
diff --git a/plugins/Weather/proto_weather/res/resource.rc b/plugins/Weather/proto_weather/res/resource.rc
new file mode 100644
index 0000000000..b059c0696d
--- /dev/null
+++ b/plugins/Weather/proto_weather/res/resource.rc
@@ -0,0 +1,41 @@
+//Microsoft Developer Studio generated resource script.
+//
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+104 ICON "SUN.ico"
+105 ICON "NA.ico"
+128 ICON "PCLOUDY.ico"
+129 ICON "RSHOWER.ico"
+130 ICON "LIGHT.ico"
+131 ICON "RAIN.ico"
+158 ICON "SNOW.ico"
+159 ICON "CLOUD.ico"
+1002 ICON "SSHOWER.ico"
+1003 ICON "FOG.ico"
+
+#endif // English (U.S.) resources
+///////////////////////////////////////////////////////////////////////////// \ No newline at end of file
diff --git a/plugins/Weather/res/brief.ico b/plugins/Weather/res/brief.ico
new file mode 100644
index 0000000000..717ef66669
--- /dev/null
+++ b/plugins/Weather/res/brief.ico
Binary files differ
diff --git a/plugins/Weather/res/disabled.ico b/plugins/Weather/res/disabled.ico
new file mode 100644
index 0000000000..ed6e27b691
--- /dev/null
+++ b/plugins/Weather/res/disabled.ico
Binary files differ
diff --git a/plugins/Weather/res/edit.ico b/plugins/Weather/res/edit.ico
new file mode 100644
index 0000000000..f59dc79b9c
--- /dev/null
+++ b/plugins/Weather/res/edit.ico
Binary files differ
diff --git a/plugins/Weather/res/icon.ico b/plugins/Weather/res/icon.ico
new file mode 100644
index 0000000000..be3d0c88bd
--- /dev/null
+++ b/plugins/Weather/res/icon.ico
Binary files differ
diff --git a/plugins/Weather/res/info.ico b/plugins/Weather/res/info.ico
new file mode 100644
index 0000000000..97d34dc4a5
--- /dev/null
+++ b/plugins/Weather/res/info.ico
Binary files differ
diff --git a/plugins/Weather/res/infologo.ico b/plugins/Weather/res/infologo.ico
new file mode 100644
index 0000000000..cf22ece1b1
--- /dev/null
+++ b/plugins/Weather/res/infologo.ico
Binary files differ
diff --git a/plugins/Weather/res/log.ico b/plugins/Weather/res/log.ico
new file mode 100644
index 0000000000..86139d5e23
--- /dev/null
+++ b/plugins/Weather/res/log.ico
Binary files differ
diff --git a/plugins/Weather/res/map.ico b/plugins/Weather/res/map.ico
new file mode 100644
index 0000000000..8c4c70742d
--- /dev/null
+++ b/plugins/Weather/res/map.ico
Binary files differ
diff --git a/plugins/Weather/res/more.ico b/plugins/Weather/res/more.ico
new file mode 100644
index 0000000000..47e13df383
--- /dev/null
+++ b/plugins/Weather/res/more.ico
Binary files differ
diff --git a/plugins/Weather/res/popup.ico b/plugins/Weather/res/popup.ico
new file mode 100644
index 0000000000..7e0301b42f
--- /dev/null
+++ b/plugins/Weather/res/popup.ico
Binary files differ
diff --git a/plugins/Weather/res/popup_no.ico b/plugins/Weather/res/popup_no.ico
new file mode 100644
index 0000000000..08de082ec2
--- /dev/null
+++ b/plugins/Weather/res/popup_no.ico
Binary files differ
diff --git a/plugins/Weather/res/reload.ico b/plugins/Weather/res/reload.ico
new file mode 100644
index 0000000000..3c81203c03
--- /dev/null
+++ b/plugins/Weather/res/reload.ico
Binary files differ
diff --git a/plugins/Weather/res/resource.rc b/plugins/Weather/res/resource.rc
new file mode 100644
index 0000000000..f8dd82df30
--- /dev/null
+++ b/plugins/Weather/res/resource.rc
@@ -0,0 +1,467 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "..\src\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "..\src\version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_BRIEF DIALOGEX 0, 0, 245, 231
+STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_HEADERBAR,"MHeaderbarCtrl",0x0,0,0,245,25
+ CONTROL "",IDC_MTEXT,"RichEdit20W",ES_MULTILINE | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP,0,25,244,180,WS_EX_STATICEDGE
+ CONTROL "List1",IDC_DATALIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING | WS_TABSTOP,0,25,244,180,WS_EX_STATICEDGE
+ PUSHBUTTON "Update",IDC_MUPDATE,10,213,48,13
+ PUSHBUTTON "Brief Info",IDC_MTOGGLE,79,213,48,13
+ PUSHBUTTON "Webpage",IDC_MWEBPAGE,132,213,48,13
+ DEFPUSHBUTTON "Close",IDCANCEL,184,213,48,13
+END
+
+IDD_OPTIONS DIALOGEX 0, 0, 306, 222
+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,10,219,8
+ CONTROL "Update weather information every",IDC_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,19,206,8
+ EDITTEXT IDC_UPDATETIME,231,15,21,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
+ LTEXT "minutes",IDC_STATIC,257,16,43,9
+ CONTROL "Consider weather info updated only when condition and temperature are changed",IDC_UPDCONDCHG,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,28,282,8
+ CONTROL "Remove old data when updating",IDC_REMOVEOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,38,282,8
+ CONTROL "Make the contact italic when weather alert is issued",IDC_MAKEI,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,48,282,8
+ CONTROL "Open URLs in new browser window",IDC_NEWWIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,57,287,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
+ LTEXT "Degree sign:",IDC_STATIC,227,116,55,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
+ 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
+ CONTROL "3 chars",IDC_D3,"Button",BS_AUTORADIOBUTTON,176,153,56,8
+ LTEXT "Elevation",IDC_STATIC,8,163,53,8
+ CONTROL "ft",IDC_E1,"Button",BS_AUTORADIOBUTTON,65,163,34,8
+ CONTROL "m",IDC_E2,"Button",BS_AUTORADIOBUTTON,120,163,34,8
+ CONTROL "Do not append units to values",IDC_DONOTAPPUNITS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,174,144,8
+ CONTROL "Do not display fractional values",IDC_NOFRAC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,174,146,8
+ GROUPBOX "Frame",IDC_STATIC,3,187,300,29
+ EDITTEXT IDC_AVATARSIZE,11,197,29,14,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_BORDER,WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
+ CONTROL "",IDC_AVATARSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,28,197,11,14
+ LTEXT "Avatar size",IDC_STATIC,42,200,85,9
+END
+
+IDD_EDIT DIALOGEX 0, 0, 241, 226
+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"
+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
+ LTEXT "ID",IDC_STATIC,12,37,57,8,SS_CENTERIMAGE
+ EDITTEXT IDC_ID,69,35,146,12,ES_AUTOHSCROLL
+ 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
+ CONTROL "Overwrite file upon update",IDC_Overwrite,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,80,111,8
+ 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
+ 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
+END
+
+IDD_POPUP DIALOGEX 0, 0, 312, 182
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "PopUp Options",IDC_STATIC,6,5,156,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 "Colours",IDC_STATIC,168,5,139,54
+ CONTROL "",IDC_BGCOLOUR,"ColourPicker",WS_TABSTOP,177,16,39,11
+ LTEXT "Background colour",IDC_STATIC,223,18,78,8,SS_CENTERIMAGE
+ CONTROL "",IDC_TEXTCOLOUR,"ColourPicker",WS_TABSTOP,177,30,39,11
+ LTEXT "Text colour",IDC_STATIC,223,31,80,8,SS_CENTERIMAGE
+ CONTROL "Use Windows colours",IDC_USEWINCOLORS,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,177,43,125,13
+ GROUPBOX "Popup Actions",IDC_STATIC,6,63,155,46
+ LTEXT "Left Click",IDC_STATIC,15,77,40,8
+ CONTROL "",IDC_LeftClick,"MButtonClass",WS_TABSTOP,59,76,95,9,WS_EX_NOACTIVATE | 0x10000000L
+ LTEXT "Right Click",IDC_STATIC,15,93,42,8
+ CONTROL "",IDC_RightClick,"MButtonClass",WS_TABSTOP,59,92,95,9,WS_EX_NOACTIVATE | 0x10000000L
+ GROUPBOX "Popup Delay",IDC_STATIC,167,63,141,46
+ CONTROL "Delay",IDC_PD3,"Button",BS_AUTORADIOBUTTON,177,74,53,8
+ EDITTEXT IDC_DELAY,233,73,36,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER | NOT WS_BORDER,WS_EX_STATICEDGE
+ LTEXT "seconds",IDC_STATIC,272,73,34,10
+ CONTROL "From PopUp plugin",IDC_PD1,"Button",BS_AUTORADIOBUTTON,177,85,110,8
+ CONTROL "Permanent",IDC_PD2,"Button",BS_AUTORADIOBUTTON,177,96,110,8
+ GROUPBOX "Popup Text",IDC_STATIC,6,112,302,66
+ LTEXT "Popup Title",IDC_STATIC,15,127,56,9
+ EDITTEXT IDC_PTitle,74,124,163,12,ES_AUTOHSCROLL
+ LTEXT "Popup Text",IDC_STATIC,15,142,55,9
+ EDITTEXT IDC_PText,73,140,164,31,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "Variables",IDC_VAR3,"MButtonClass",WS_TABSTOP,244,124,47,12,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "Default",IDC_PDEF,"MButtonClass",WS_TABSTOP,244,141,47,12,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "Preview",IDC_PREVIEW,"MButtonClass",WS_TABSTOP,244,158,47,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
+END
+
+IDD_TEXTOPT DIALOGEX 0, 0, 309, 228
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Contact List",IDC_TM1,"MButtonClass",WS_TABSTOP | 0x100,2,9,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_CTEXT,80,8,124,12,ES_AUTOHSCROLL
+ CONTROL "Brief Info Title",IDC_TM2,"MButtonClass",WS_TABSTOP,2,41,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_BTITLE,80,40,124,12,ES_AUTOHSCROLL
+ CONTROL "Brief Info",IDC_TM3,"MButtonClass",WS_TABSTOP,2,55,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_BTEXT,80,54,124,44,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "Note Text",IDC_TM4,"MButtonClass",WS_TABSTOP,2,101,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_NTEXT,80,100,124,44,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "Extra Text",IDC_TM5,"MButtonClass",WS_TABSTOP,2,147,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_XTEXT,80,146,124,44,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "External Log",IDC_TM6,"MButtonClass",WS_TABSTOP,2,193,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_ETEXT,80,192,124,12,ES_AUTOHSCROLL
+ CONTROL "History Log",IDC_TM7,"MButtonClass",WS_TABSTOP,2,208,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_HTEXT,80,207,124,12,ES_AUTOHSCROLL
+ GROUPBOX "Variable List",IDC_STATIC,206,4,99,198
+ LTEXT "",IDC_VARLIST,213,15,86,158
+ CONTROL "More Variables",IDC_MORE,"MButtonClass",WS_TABSTOP,214,188,76,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "Reset",IDC_RESET,"MButtonClass",WS_TABSTOP,222,208,61,12,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+ EDITTEXT IDC_BTITLE2,80,24,124,12,ES_AUTOHSCROLL
+ CONTROL "Status Message",IDC_TM8,"MButtonClass",WS_TABSTOP | 0x100,2,25,77,9,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+END
+
+IDD_USERINFO DIALOGEX 0, 0, 222, 132
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ ICON "",IDC_INFOICON,16,15,20,20,SS_CENTERIMAGE
+ LTEXT "",IDC_INFO1,12,8,193,10
+ LTEXT "Sunset",IDC_STATIC,112,58,54,8
+ LTEXT "Feel-like",IDC_STATIC,12,46,39,8
+ LTEXT "Today's Low",IDC_STATIC,112,82,54,8
+ LTEXT "Wind",IDC_STATIC,12,70,39,8
+ LTEXT "Today's High",IDC_STATIC,112,70,54,8
+ LTEXT "Sunrise",IDC_STATIC,112,46,54,8
+ LTEXT "",IDC_INFO11,12,121,195,9
+ LTEXT "Dewpoint",IDC_STATIC,12,94,39,8
+ LTEXT "Pressure",IDC_STATIC,12,58,39,8
+ GROUPBOX "",IDC_STATIC,4,36,211,84
+ GROUPBOX "",IDC_STATIC,4,1,211,35
+ EDITTEXT IDC_INFO2,42,20,165,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO3,51,46,57,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO4,51,58,57,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO5,51,70,56,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO6,51,94,56,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO7,166,46,41,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO8,166,58,41,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO9,166,70,41,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_INFO10,166,82,41,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Humidity",IDC_STATIC,12,82,39,8
+ EDITTEXT IDC_INFO12,51,82,56,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ LTEXT "Visibility",IDC_STATIC,12,106,39,8
+ EDITTEXT IDC_INFO13,51,106,56,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ CONTROL "More...",IDC_MOREDETAIL,"MButtonClass",WS_TABSTOP,129,104,61,12,WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE | 0x10000000L
+END
+
+IDD_SETUP DIALOGEX 0, 0, 244, 146
+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 "Weather Protocol INI Setup\nInstall and load your weather ini file here",IDC_HEADERBAR,
+ "MHeaderbarCtrl",0x0,0,0,243,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,234,12,WS_EX_WINDOWEDGE | 0x800000L
+ CONTROL "Extract the weather ini file from archive to this directory",IDC_STEP2,
+ "MButtonClass",WS_TABSTOP,5,74,234,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,234,13,WS_EX_WINDOWEDGE | 0x800000L
+ CONTROL "Add new weather station and close this dialog",IDC_STEP4,
+ "MButtonClass",WS_TABSTOP,5,99,234,12,WS_EX_WINDOWEDGE | 0x800000L
+ PUSHBUTTON "Close",IDCANCEL,95,122,48,13
+ CONTROL "",IDC_MFRAME,"Static",SS_ETCHEDHORZ,0,117,244,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
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ EDITTEXT IDC_SEARCHCITY,3,18,103,12,0,WS_EX_CLIENTEDGE
+ LTEXT "City:",IDC_STATIC,6,7,99,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_BRIEF, DIALOG
+ BEGIN
+ RIGHTMARGIN, 241
+ BOTTOMMARGIN, 226
+ END
+
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ VERTGUIDE, 12
+ BOTTOMMARGIN, 209
+ END
+
+ IDD_POPUP, DIALOG
+ BEGIN
+ RIGHTMARGIN, 306
+ END
+
+ IDD_TEXTOPT, DIALOG
+ BEGIN
+ RIGHTMARGIN, 308
+ END
+
+ IDD_SETUP, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 140
+ END
+
+ IDD_INFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 217
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 148
+ END
+
+ IDD_SEARCHCITY, DIALOG
+ BEGIN
+ RIGHTMARGIN, 113
+ BOTTOMMARGIN, 54
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_PMENU MENU
+BEGIN
+ POPUP "Menu"
+ BEGIN
+ MENUITEM "Dismiss PopUp", IDM_M1
+ MENUITEM "Open brief information", IDM_M2
+ MENUITEM "Open complete forecast", IDM_M3
+ MENUITEM "Open weather map", IDM_M4
+ MENUITEM "View history", IDM_M5
+ MENUITEM "Open log file", IDM_M6
+ MENUITEM "Show user menu", IDM_M7
+ MENUITEM "Show user detail", IDM_M8
+ END
+END
+
+IDR_TMENU MENU
+BEGIN
+ POPUP "Menu"
+ BEGIN
+ MENUITEM "To old setting", ID_T1
+ MENUITEM "To default", ID_T2
+ END
+END
+
+IDR_TMMENU MENU
+BEGIN
+ POPUP "Menu"
+ BEGIN
+ MENUITEM "Preview", ID_MPREVIEW
+ MENUITEM "Reset", ID_MRESET
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// 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_POPUP ICON "popup.ico"
+IDI_NOPOPUP ICON "popup_no.ico"
+IDI_UPDATE2 ICON "update2.ico"
+IDI_DISABLED ICON "disabled.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\\src\\resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <windows.h>\r\n"
+ "#include ""..\\src\\version.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "borkra, noname"
+ VALUE "FileDescription", "Miranda Weather Protocol"
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", "Weather Protocol"
+ VALUE "LegalCopyright", "Copyright © 2005 - 2010 Boris Krasnovskiy All Rights Reserved"
+ VALUE "OriginalFilename", "weather.dll"
+ VALUE "ProductName", "Weather Protocol"
+ VALUE "ProductVersion", __VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Weather/res/update.ico b/plugins/Weather/res/update.ico
new file mode 100644
index 0000000000..ccc4d4611d
--- /dev/null
+++ b/plugins/Weather/res/update.ico
Binary files differ
diff --git a/plugins/Weather/res/update2.ico b/plugins/Weather/res/update2.ico
new file mode 100644
index 0000000000..f71be51ee2
--- /dev/null
+++ b/plugins/Weather/res/update2.ico
Binary files differ
diff --git a/plugins/Weather/src/resource.h b/plugins/Weather/src/resource.h
new file mode 100644
index 0000000000..e88e4c19de
--- /dev/null
+++ b/plugins/Weather/src/resource.h
@@ -0,0 +1,176 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDI_ICON 101
+#define IDD_USERINFO 201
+#define IDD_EDIT 202
+#define IDI_DISABLED 203
+#define IDD_POPUP 204
+#define IDD_OPTIONS 205
+#define IDI_LOG 206
+#define IDI_UPDATE2 208
+#define IDI_READ 209
+#define IDI_UPDATE 210
+#define IDI_S 211
+#define IDI_MAP 212
+#define IDR_PMENU 213
+#define IDI_POPUP 214
+#define IDI_NOPOPUP 215
+#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
+#define IDC_LOG 2003
+#define IDC_UPDATETIME 2005
+#define IDC_CTEXT 2006
+#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
+#define IDC_BTEXT 2011
+#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
+#define IDC_POP2 2020
+#define IDC_PText 2021
+#define IDC_PTitle 2023
+#define IDC_Internal 2024
+#define IDC_ETEXT 2025
+#define IDC_DISCONDICON 2025
+#define IDC_External 2026
+#define IDC_DONOTAPPUNITS 2026
+#define IDC_DEFA 2027
+#define IDC_NOFRAC 2027
+#define IDC_HTEXT 2028
+#define IDC_DPop 2029
+#define IDC_DAutoUpdate 2030
+#define IDC_NEWWIN 2031
+#define IDC_IURL 2032
+#define IDC_MURL 2033
+#define IDC_PROTOCOND 2034
+#define IDC_Overwrite 2035
+#define IDC_UPDCONDCHG 2036
+#define IDC_REMOVEOLD 2037
+#define IDC_MAKEI 2039
+#define IDC_BGCOLOUR 2040
+#define IDC_TEXTCOLOUR 2041
+#define IDC_LeftClick 2042
+#define IDC_PREVIEW 2043
+#define IDC_VAR3 2044
+#define IDC_RightClick 2045
+#define IDC_DELAY 2046
+#define IDC_PDEF 2047
+#define IDC_T1 2048
+#define IDC_T2 2049
+#define IDC_W1 2050
+#define IDC_W2 2051
+#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
+#define IDC_P4 2066
+#define IDC_RESET 2067
+#define IDC_D1 2067
+#define IDC_D2 2068
+#define IDC_D3 2069
+#define IDC_INFO1 2069
+#define IDC_INFOICON 2070
+#define IDC_INFO11 2071
+#define IDC_INFO2 2072
+#define IDC_INFO3 2073
+#define IDC_VARLIST 2074
+#define IDC_INFO4 2075
+#define IDC_INFO5 2076
+#define IDC_PD1 2077
+#define IDC_PD2 2078
+#define IDC_PD3 2079
+#define IDC_INFO6 2079
+#define IDC_TM1 2080
+#define IDC_TM2 2081
+#define IDC_TM3 2082
+#define IDC_TM4 2083
+#define IDC_TM5 2084
+#define IDC_TM6 2085
+#define IDC_TM7 2086
+#define IDC_TM8 2087
+#define IDC_INFO7 2087
+#define IDC_TM9 2088
+#define IDC_INFO8 2089
+#define IDC_INFO9 2090
+#define IDC_INFO10 2091
+#define IDC_INFO12 2092
+#define IDC_INFO13 2093
+#define IDC_MORE 2094
+#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_E2 2129
+#define OIC_HAND 32513
+#define OIC_QUES 32514
+#define OIC_BANG 32515
+#define OIC_NOTE 32516
+#define IDM_M1 40002
+#define IDM_M2 40003
+#define IDM_M3 40004
+#define IDM_M4 40005
+#define IDM_M5 40006
+#define IDM_M6 40007
+#define IDM_M7 40008
+#define IDM_M8 40009
+#define ID_T1 40010
+#define ID_T2 40011
+#define ID_MPREVIEW 40020
+#define ID_MRESET 40021
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#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_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Weather/src/stdafx.cpp b/plugins/Weather/src/stdafx.cpp
new file mode 100644
index 0000000000..2d786344e5
--- /dev/null
+++ b/plugins/Weather/src/stdafx.cpp
@@ -0,0 +1,18 @@
+/*
+Copyright (c) 2012 Miranda NG team (http://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 "weather.h" \ No newline at end of file
diff --git a/plugins/Weather/src/version.h b/plugins/Weather/src/version.h
new file mode 100644
index 0000000000..58a8f34a3c
--- /dev/null
+++ b/plugins/Weather/src/version.h
@@ -0,0 +1,6 @@
+#define __FILEVERSION_STRING 0,3,9,1
+#define __VERSION_STRING "0.3.9.1"
+#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 3, 9, 1)
+
+#define BETA FALSE
+#define AUTH "NoName, borkra"
diff --git a/plugins/Weather/src/weather.cpp b/plugins/Weather/src/weather.cpp
new file mode 100644
index 0000000000..9eb22252b5
--- /dev/null
+++ b/plugins/Weather/src/weather.cpp
@@ -0,0 +1,266 @@
+/*
+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/>.
+*/
+
+/*
+Main file for the Weather Protocol, includes loading, unloading,
+upgrading, support for plugin uninsaller, and anything that doesn't
+belong to any other file.
+*/
+
+#include "weather.h"
+
+//============ GLOBAL VARIABLES ============
+
+WIDATALIST *WIHead;
+WIDATALIST *WITail;
+
+HINSTANCE hInst;
+HWND hPopupWindow;
+
+HANDLE hHookWeatherUpdated;
+HANDLE hHookWeatherError;
+
+HANDLE hDataWindowList;
+HANDLE hWindowList;
+
+HANDLE hUpdateMutex;
+
+unsigned status;
+unsigned old_status;
+
+UINT_PTR timerId;
+int hLangpack;
+
+MYOPTIONS opt;
+
+// check if weather is currently updating
+BOOL ThreadRunning;
+
+// variable to determine if module loaded
+BOOL ModuleLoaded;
+
+
+
+
+// plugin info
+// VER = version, AUTH = author, defined in weather.h
+static const PLUGININFOEX pluginInfoEx =
+{
+ sizeof(PLUGININFOEX),
+ "Weather Protocol",
+ __VERSION_DWORD,
+ "Retrieves weather information and displays it in your contact list.",
+ AUTH,
+ "borkra@miranda-im.org",
+ "(c) 2002-2005 NoName, 2005-2010 Boris Krasnovskiy",
+ "http://miranda-ng.org/",
+ UNICODE_AWARE,
+ MIID_WEATHER
+};
+
+extern "C" __declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+// MirandaInterfaces - returns the protocol interface to the core
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+int WeatherShutdown(WPARAM wParam,LPARAM lParam)
+{
+ KillTimer(NULL, timerId); // kill update timer
+
+ SaveOptions(); // save options once more
+ status = ID_STATUS_OFFLINE; // set status to offline
+
+ CallService(MS_NETLIB_SHUTDOWN, (WPARAM)hNetlibHttp, 0);
+
+ WindowList_Broadcast(hWindowList, WM_CLOSE, 0, 0);
+ WindowList_Broadcast(hDataWindowList, WM_CLOSE, 0, 0);
+ SendMessage(hWndSetup, WM_CLOSE, 0, 0);
+
+ return 0;
+}
+
+// update some settings/db values for new version
+// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION
+void Upgrade(DWORD lastver)
+{
+ // for version below v0.3.2.3, remove the "TriggerText" setting
+ if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3))
+ db_unset(NULL, WEATHERPROTONAME, "TriggerText");
+ if (lastver < PLUGIN_MAKE_VERSION(0,3,3,13))
+ db_unset(NULL, "KnownModules", "Weather");
+
+ db_set_dw(NULL, WEATHERPROTONAME, "Version", __VERSION_DWORD);
+}
+
+// weather protocol initialization function
+// run after the event ME_SYSTEM_MODULESLOADED occurs
+int WeatherInit(WPARAM wParam,LPARAM lParam)
+{
+ // initialize netlib
+ NetlibInit();
+
+ InitIcons();
+ InitMwin();
+
+ // load weather menu items
+ AddMenuItems();
+
+ // timer for the first update
+ timerId = SetTimer(NULL, 0, 5000, timerProc2); // first update is 5 sec after load
+
+ // weather user detail
+ HookEvent(ME_USERINFO_INITIALISE, UserInfoInit);
+
+ hDataWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+ hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+
+ return 0;
+}
+
+// update some settings/db values for new version, this one is for contact
+// lastver = dword value for the last version made by PLUGIN_MAKE_VERSION
+// hContact = current contact
+void UpgradeContact(DWORD lastver, HANDLE hContact)
+{
+ // for version below v0.3.2.3, suppress online notifications for all weather contacts
+ if (lastver < PLUGIN_MAKE_VERSION(0,3,2,3))
+ {
+ db_set_dw(hContact, "Ignore", "Mask", 8);
+ db_set_dw(hContact, "Ignore", "Mask1", 8);
+ }
+}
+
+//============ MISC FUNCTIONS ============
+
+// initialize the global variables at startup
+void InitVar()
+{
+ // setup the linklist for weather update list
+ UpdateListTail = NULL;
+ UpdateListHead = NULL;
+
+ // other settings
+ timerId = 0;
+ opt.DefStn = NULL;
+ ModuleLoaded = FALSE;
+}
+
+// unload function
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ DestroyMwin();
+ DestroyWindow(hPopupWindow);
+
+ DestroyHookableEvent(hHookWeatherUpdated);
+ DestroyHookableEvent(hHookWeatherError);
+
+ NetlibHttpDisconnect();
+ Netlib_CloseHandle(hNetlibUser);
+
+ DestroyUpdateList();
+ DestroyOptions();
+ DestroyWIList(); // unload all ini data from memory
+
+ CloseHandle(hUpdateMutex);
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ DWORD lastver;
+
+ mir_getLP(&pluginInfoEx);
+
+ // initialize global variables
+ InitVar();
+
+ // load options and set defaults
+ LoadOptions();
+
+ // upgrade check
+ // I only support version check and upgrade for my own version, so check if the author is my name
+ if (strstr(AUTH, "NoName") != NULL)
+ {
+ lastver = db_get_dw(NULL, WEATHERPROTONAME, "Version", PLUGIN_MAKE_VERSION(0,3,1,8));
+ if (lastver < __VERSION_DWORD) Upgrade(lastver);
+ }
+ else // if it is not my build, ignore upgrade procedure
+ lastver = PLUGIN_MAKE_VERSION(255,255,255,255);
+
+ // reset the weather data at startup for individual contacts
+ EraseAllInfo(lastver);
+
+ // load weather update data
+ LoadWIData(TRUE);
+
+ // set status to online if "Do not display weather condition as protocol status" is enabled
+ old_status = status = ID_STATUS_OFFLINE;
+
+ // add an event on weather update and error
+ hHookWeatherUpdated = CreateHookableEvent(ME_WEATHER_UPDATED);
+ hHookWeatherError = CreateHookableEvent(ME_WEATHER_ERROR);
+
+ // initialize options and network
+ 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);
+
+ hUpdateMutex = CreateMutex(NULL, FALSE, NULL);
+
+ // register weather protocol
+ PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE };
+ pd.szName = WEATHERPROTONAME;
+ pd.type = (opt.NoProtoCondition) ? PROTOTYPE_VIRTUAL : PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE,0, (LPARAM)&pd);
+
+ // initialize weather protocol services
+ InitServices();
+
+ // add our modules to the KnownModules list
+ db_set_s(NULL, "KnownModules", "Weather Protocol", "Weather,WeatherCondition,Current");
+
+ // add sound event
+ SkinAddNewSoundExT("weatherupdated", _T(WEATHERPROTONAME), LPGENT("Weather Condition Changed"));
+ SkinAddNewSoundExT("weatheralert", _T(WEATHERPROTONAME), LPGENT("Weather Alert Issued"));
+
+ // window needed for popup commands
+ TCHAR SvcFunc[100];
+ mir_sntprintf( SvcFunc, SIZEOF(SvcFunc), _T("%s__PopupWindow"), _T(WEATHERPROTONAME));
+ hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW,_T("static"),SvcFunc,0,CW_USEDEFAULT,CW_USEDEFAULT,
+ CW_USEDEFAULT,CW_USEDEFAULT,HWND_DESKTOP,NULL, hInst,NULL);
+ SetWindowLongPtr(hPopupWindow, GWLP_WNDPROC, (LONG_PTR)PopupWndProc);
+
+ return 0;
+}
diff --git a/plugins/Weather/src/weather.h b/plugins/Weather/src/weather.h
new file mode 100644
index 0000000000..072860c914
--- /dev/null
+++ b/plugins/Weather/src/weather.h
@@ -0,0 +1,545 @@
+/*
+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 contains the includes, weather constants/declarations,
+ the structs, and the primitives for some of the functions.
+*/
+
+//============ THE INCLUDES ===========
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <m_stdhdr.h>
+
+#include <stdio.h>
+#include <io.h>
+#include <share.h>
+#include <direct.h>
+#include <process.h>
+#include <time.h>
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+
+#include <win2k.h>
+
+#define MIRANDA_VER 0x0A00
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_icolib.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_skin.h>
+#include <m_database.h>
+#include <m_history.h>
+#include <m_utils.h>
+#include <m_userinfo.h>
+#include <m_netlib.h>
+#include <m_ignore.h>
+#include <m_findadd.h>
+#include <m_button.h>
+#include <m_avatars.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_fontservice.h>
+#include <m_skin_eng.h>
+#include <m_cluiframes.h>
+
+#include <m_popup.h>
+
+#include "m_weather.h"
+#include "resource.h"
+#include "version.h"
+
+//============ CONSTANTS ============
+
+// 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
+
+// others
+#define NODATA TranslateT("N/A")
+#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 C_DEFAULT TranslateT("%n [%t, %c]")
+#define N_DEFAULT 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]")
+#define B_DEFAULT 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]")
+#define b_DEFAULT TranslateT("Weather Condition for %n as of %u")
+#define X_DEFAULT N_DEFAULT
+#define H_DEFAULT TranslateT("%c, %t (feel-like %f) Wind: %i %w Humidity: %m")
+#define E_DEFAULT TranslateT("%n at %u: %c, %t (feel-like %f) Wind: %i %w Humidity: %m")
+#define P_DEFAULT TranslateT("%n (%u)")
+#define p_DEFAULT TranslateT("%c, %t\nToday: High %h, Low %l")
+#define s_DEFAULT TranslateT("Temperature: %[Temperature]")
+
+
+//============ OPTION STRUCT ============
+
+// option struct
+typedef struct {
+// main options
+ BOOL AutoUpdate;
+ BOOL CAutoUpdate;
+ BOOL StartupUpdate;
+ WORD UpdateTime;
+ WORD AvatarSize;
+ BOOL NewBrowserWin;
+ BOOL NoProtoCondition;
+ BOOL UpdateOnlyConditionChanged;
+ BOOL RemoveOldData;
+ BOOL MakeItalic;
+// units
+ WORD tUnit;
+ WORD wUnit;
+ WORD vUnit;
+ WORD pUnit;
+ WORD dUnit;
+ WORD eUnit;
+ TCHAR DegreeSign[4];
+ BOOL DoNotAppendUnit;
+ BOOL NoFrac;
+// texts
+ TCHAR *cText;
+ TCHAR *bTitle;
+ TCHAR *bText;
+ TCHAR *nText;
+ TCHAR *eText;
+ TCHAR *hText;
+ TCHAR *xText;
+ TCHAR *sText;
+// advanced
+ BOOL DisCondIcon;
+// popup options
+ BOOL UsePopup;
+ BOOL UpdatePopup;
+ BOOL AlertPopup;
+ BOOL PopupOnChange;
+ BOOL ShowWarnings;
+// popup colors
+ BOOL UseWinColors;
+ COLORREF BGColour;
+ COLORREF TextColour;
+// popup actions
+ DWORD LeftClickAction;
+ DWORD RightClickAction;
+// popup delay
+ DWORD pDelay;
+// popup texts
+ TCHAR *pTitle;
+ TCHAR *pText;
+// other misc stuff
+ TCHAR Default[64];
+ HANDLE DefStn;
+} MYOPTIONS;
+
+void DestroyOptions(void);
+
+//============ STRUCT USED TO MAKE AN UPDATE LIST ============
+
+struct WCONTACTLIST {
+ HANDLE hContact;
+ struct WCONTACTLIST *next;
+};
+
+typedef struct WCONTACTLIST UPDATELIST;
+
+extern UPDATELIST *UpdateListHead;
+extern UPDATELIST *UpdateListTail;
+
+void DestroyUpdateList(void);
+
+//============ DATA FORMAT STRUCT ============
+
+#define WID_NORMAL 0
+#define WID_SET 1
+#define WID_BREAK 2
+
+typedef struct {
+ TCHAR *Name;
+ TCHAR *Start;
+ TCHAR *End;
+ TCHAR *Unit;
+ char *Url;
+ TCHAR *Break;
+ int Type;
+} WIDATAITEM;
+
+struct WITEMLIST {
+ WIDATAITEM Item;
+ struct WITEMLIST *Next;
+};
+
+typedef struct WITEMLIST WIDATAITEMLIST;
+
+typedef struct {
+ BOOL Available;
+ char *SearchURL;
+ TCHAR *NotFoundStr;
+ WIDATAITEM Name;
+} WIIDSEARCH;
+
+typedef struct {
+ BOOL Available;
+ TCHAR *First;
+ WIDATAITEM Name;
+ WIDATAITEM ID;
+} WINAMESEARCHTYPE;
+
+typedef struct {
+ char *SearchURL;
+ TCHAR *NotFoundStr;
+ TCHAR *SingleStr;
+ WINAMESEARCHTYPE Single;
+ WINAMESEARCHTYPE Multiple;
+} WINAMESEARCH;
+
+struct STRLIST {
+ TCHAR *Item;
+ struct STRLIST *Next;
+};
+
+typedef struct STRLIST WICONDITEM;
+
+typedef struct {
+ WICONDITEM *Head;
+ WICONDITEM *Tail;
+} WICONDLIST;
+
+typedef struct {
+ TCHAR *FileName;
+ TCHAR *ShortFileName;
+ BOOL Enabled;
+
+ // header
+ TCHAR *DisplayName;
+ TCHAR *InternalName;
+ TCHAR *Description;
+ TCHAR *Author;
+ TCHAR *Version;
+ int InternalVer;
+ size_t MemUsed;
+
+ // default
+ char *DefaultURL;
+ TCHAR *DefaultMap;
+ char *UpdateURL;
+ char *UpdateURL2;
+ char *UpdateURL3;
+ char *UpdateURL4;
+ char *Cookie;
+// items
+ int UpdateDataCount;
+ WIDATAITEMLIST *UpdateData;
+ WIDATAITEMLIST *UpdateDataTail;
+ WIIDSEARCH IDSearch;
+ WINAMESEARCH NameSearch;
+ WICONDLIST CondList[10];
+} WIDATA;
+
+//============ DATA LIST (LINKED LIST) ============
+
+struct DATALIST {
+ WIDATA Data;
+ struct DATALIST *next;
+};
+
+typedef struct DATALIST WIDATALIST;
+
+//============ GLOBAL VARIABLES ============
+
+extern WIDATALIST *WIHead;
+extern WIDATALIST *WITail;
+
+extern HINSTANCE hInst;
+extern HWND hPopupWindow;
+extern HWND hWndSetup;
+
+extern MYOPTIONS opt;
+
+extern unsigned status;
+extern unsigned old_status;
+
+extern HANDLE hDataWindowList;
+extern HANDLE hNetlibUser, hNetlibHttp;
+extern HANDLE hHookWeatherUpdated;
+extern HANDLE hHookWeatherError;
+extern HANDLE hWindowList;
+extern HANDLE hMwinMenu;
+
+extern UINT_PTR timerId;
+
+// check if weather is currently updating
+extern BOOL ThreadRunning;
+
+//============ FUNCTION PRIMITIVES ============
+
+// functions in weather.c
+void UpgradeContact(DWORD lastver, HANDLE hContact);
+
+// functions in weather_addstn.c
+INT_PTR WeatherAddToList(WPARAM wParam,LPARAM lParam);
+BOOL CheckSearch();
+
+int IDSearch(TCHAR *id, const int searchId);
+int NameSearch(TCHAR *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_PTR CALLBACK DlgProcChange(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int ContactDeleted(WPARAM wParam,LPARAM lParam);
+
+BOOL IsMyContact(HANDLE hContact);
+
+// functions in weather_conv.c
+BOOL is_number(char *s);
+
+void GetTemp(TCHAR *tempchar, TCHAR *unit, TCHAR *str);
+void GetSpeed(TCHAR *tempchar, TCHAR *unit, TCHAR *str);
+void GetPressure(TCHAR *tempchar, TCHAR *unit, TCHAR *str);
+void GetDist(TCHAR *tempchar, TCHAR *unit, TCHAR *str);
+void GetElev(TCHAR *tempchar, TCHAR *unit, TCHAR *str);
+
+WORD GetIcon(const TCHAR* cond, WIDATA *Data);
+void CaseConv(TCHAR *str);
+void TrimString(char *str);
+void TrimString(WCHAR *str);
+void ConvertBackslashes(char *str);
+char *GetSearchStr(char *dis);
+
+TCHAR *GetDisplay(WEATHERINFO *w, const TCHAR *dis, TCHAR* str);
+INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam);
+
+void GetSvc(TCHAR *pszID);
+void GetID(TCHAR *pszID);
+
+TCHAR *GetError(int code);
+
+// functions in weather_data.c
+void GetStationID(HANDLE hContact, TCHAR* id, size_t idlen);
+WEATHERINFO LoadWeatherInfo(HANDLE Change);
+int DBGetData(HANDLE hContact, char *setting, DBVARIANT *dbv);
+int DBGetStaticString(HANDLE hContact, const char *szModule, const char *valueName, TCHAR *dest, size_t dest_len);
+
+void EraseAllInfo(DWORD lastver);
+
+void LoadStationData(TCHAR *pszFile, TCHAR *pszShortFile, WIDATA *Data);
+void GetDataValue(WIDATAITEM *UpdateData, TCHAR *Data, TCHAR** szInfo);
+void ConvertDataValue(WIDATAITEM *UpdateData, TCHAR *Data);
+void wSetData(char **Data, const char *Value);
+void wSetData(WCHAR **Data, const char *Value);
+void wSetData(WCHAR **Data, const WCHAR *Value);
+void wfree(char **Data);
+void wfree(WCHAR **Data);
+
+void DBDataManage(HANDLE hContact, WORD Mode, WPARAM wParam, LPARAM lParam);
+
+// functions in weather_http.c
+int InternetDownloadFile (char *szUrl, char *cookie, TCHAR** szData);
+void NetlibInit();
+void NetlibHttpDisconnect(void);
+
+// functions in weather_ini.c
+void WIListAdd(WIDATA Data);
+WIDATA* GetWIData(TCHAR *pszServ);
+
+BOOL IsContainedInCondList(const TCHAR *pszStr, WICONDLIST *List);
+
+void DestroyWIList();
+BOOL LoadWIData(BOOL dial);
+void FreeWIData(WIDATA *Data);
+
+INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// functions in weather_info.c
+void GetINIInfo(TCHAR *pszSvc);
+
+void MoreVarList();
+
+// functions in weather_opt.c
+void SetTextDefault(const char* in);
+void LoadOptions();
+void SaveOptions();
+
+int OptInit(WPARAM wParam,LPARAM lParam);
+
+INT_PTR CALLBACK OptionsProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam);
+void SetIconDefault();
+void RemoveIconSettings();
+
+BOOL CALLBACK TextOptionsProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam);
+BOOL CALLBACK AdvOptionsProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam);
+INT_PTR CALLBACK DlgProcText(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgPopUpOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// functions in weather_popup.c
+int WeatherPopup(WPARAM wParam, LPARAM lParam);
+int WeatherError(WPARAM wParam, LPARAM lParam);
+int WPShowMessage(TCHAR* lpzText, WORD kind);
+
+LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+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(HANDLE hContact);
+
+// functions in weather_update.c
+int UpdateWeather(HANDLE hContact);
+
+int RetrieveWeather(HANDLE hContact, WEATHERINFO *winfo);
+
+void UpdateAll(BOOL AutoUpdate, BOOL RemoveOld);
+void UpdateThreadProc(LPVOID hWnd);
+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(HANDLE hContact);
+
+void CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+void CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+// function from multiwin module
+void InitMwin(void);
+void DestroyMwin(void);
+INT_PTR Mwin_MenuClicked(WPARAM wParam, LPARAM lParam);
+int BuildContactMenu(WPARAM wparam, LPARAM lparam);
+void UpdateMwinData(HANDLE hContact);
+void removeWindow(HANDLE hContact);
+
+// functions in weather_userinfo.c
+int UserInfoInit(WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#define WM_UPDATEDATA WM_USER + 2687
+
+int BriefInfo(WPARAM wParam, LPARAM lParam);
+INT_PTR BriefInfoSvc(WPARAM wParam, LPARAM lParam);
+void LoadBriefInfoText(HWND hwndDlg, HANDLE hContact);
+INT_PTR CALLBACK DlgProcBrief(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void InitIcons(void);
+HICON LoadIconEx(const char* name, BOOL big);
+HANDLE GetIconHandle(const char* name);
+void ReleaseIconEx(HICON hIcon);
diff --git a/plugins/Weather/src/weather_addstn.cpp b/plugins/Weather/src/weather_addstn.cpp
new file mode 100644
index 0000000000..9a3f1fd19f
--- /dev/null
+++ b/plugins/Weather/src/weather_addstn.cpp
@@ -0,0 +1,428 @@
+/*
+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 search and add a weather station
+to the contact list. Contain code for both name and ID search.
+*/
+
+#include "weather.h"
+
+// variables used for weather_addstn.c
+static int searchId = -1;
+static TCHAR name1[256];
+
+// ============ ADDING NEW STATION ============
+
+// protocol service function for adding a new contact onto contact list
+// lParam = PROTOSEARCHRESULT
+INT_PTR WeatherAddToList(WPARAM wParam, LPARAM lParam)
+{
+ PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)lParam;
+ WIDATA *sData;
+
+ // search for existing contact
+ HANDLE hContact = db_find_first();
+ while (hContact != NULL) {
+ // check if it is a weather contact
+ if ( IsMyContact(hContact)) {
+ DBVARIANT dbv;
+ // check ID to see if the contact already exist in the database
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "ID", &dbv)) {
+ if ( !_tcsicmp(psr->email, dbv.ptszVal)) {
+ // remove the flag for not on list and hidden, thus make the contact visible
+ // and add them on the list
+ if (db_get_b(hContact, "CList", "NotOnList", 1)) {
+ db_unset(hContact, "CList", "NotOnList");
+ db_unset(hContact, "CList", "Hidden");
+ }
+ db_free(&dbv);
+ // contact is added, function quitting
+ return (INT_PTR)hContact;
+ }
+ db_free(&dbv);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+
+ // if contact with the same ID was not found, add it
+ if (psr->cbSize < sizeof(PROTOSEARCHRESULT)) return 0;
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)WEATHERPROTONAME);
+ // suppress online notification for the new contact
+ CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, IGNOREEVENT_USERONLINE);
+
+ // set contact info and settings
+ TCHAR svc[256];
+ _tcsncpy(svc, psr->email, SIZEOF(svc)); svc[SIZEOF(svc)-1] = 0;
+ GetSvc(svc);
+ // set settings by obtaining the default for the service
+ if (psr->lastName[0] != 0) {
+ sData = GetWIData(svc);
+ db_set_ts(hContact, WEATHERPROTONAME, "MapURL", sData->DefaultMap);
+ db_set_s(hContact, WEATHERPROTONAME, "InfoURL", sData->DefaultURL);
+ }
+ else { // if no valid service is found, create empty strings for MapURL and InfoURL
+ db_set_s(hContact, WEATHERPROTONAME, "MapURL", "");
+ db_set_s(hContact, WEATHERPROTONAME, "InfoURL", "");
+ }
+ // write the other info and settings to the database
+ db_set_ts(hContact, WEATHERPROTONAME, "ID", psr->email);
+ db_set_ts(hContact, WEATHERPROTONAME, "Nick", psr->nick);
+ db_set_w(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE);
+
+ AvatarDownloaded(hContact);
+
+ TCHAR str[256];
+ mir_sntprintf(str, SIZEOF(str), TranslateT("Current weather information for %s."), psr->nick);
+ db_set_ts(hContact, WEATHERPROTONAME, "About", str);
+
+ // make the last update tags to something invalid
+ db_set_s(hContact, WEATHERPROTONAME, "LastLog", "never");
+ db_set_s(hContact, WEATHERPROTONAME, "LastCondition", "None");
+ db_set_s(hContact, WEATHERPROTONAME, "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, SIZEOF(opt.Default));
+
+ opt.DefStn = hContact;
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv)) {
+ // notification message box
+ wsprintf(str, TranslateT("%s is now the default weather station"), dbv.ptszVal);
+ db_free(&dbv);
+ MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK|MB_ICONINFORMATION);
+ }
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+ }
+ // display the Edit Settings dialog box
+ EditSettings((WPARAM)hContact, 0);
+ return (INT_PTR)hContact;
+}
+
+// ============ WARNING DIALOG ============
+
+// show a message box and cancel search if update is in process
+BOOL CheckSearch() {
+ if (UpdateListHead != NULL) {
+ MessageBox(NULL, TranslateT("Please try again after weather update is completed."), TranslateT("Weather Protocol"), MB_OK|MB_ICONERROR);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// ============ BASIC ID SEARCH ============
+
+static TCHAR sID[32];
+
+// A timer process for the ID search (threaded)
+static void __cdecl BasicSearchTimerProc(LPVOID hWnd)
+{
+ int result;
+ // search only when it's not current updating weather.
+ if (CheckSearch())
+ result = IDSearch(sID, searchId);
+
+ // broadcast the search result
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)searchId, 0);
+
+ // exit the search
+ searchId = -1;
+}
+
+// the service function for ID search
+// lParam = ID search string
+INT_PTR WeatherBasicSearch(WPARAM wParam, LPARAM lParam)
+{
+ if (searchId != -1) return 0; //only one search at a time
+ _tcsncpy(sID, ( TCHAR* )lParam, SIZEOF(sID));
+ sID[SIZEOF(sID)-1] = 0;
+ searchId = 1;
+ // create a thread for the ID search
+ mir_forkthread(BasicSearchTimerProc, NULL);
+ return searchId;
+}
+
+// ============ NAME SEARCH ============
+
+// name search timer process (threaded)
+static void __cdecl NameSearchTimerProc(LPVOID hWnd)
+{
+ // search only when it's not current updating weather.
+ if (CheckSearch())
+ if (name1[0] != 0)
+ NameSearch(name1, searchId); // search nickname field
+
+ // broadcast the result
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)searchId, 0);
+
+ // exit the search
+ searchId = -1;
+}
+
+static INT_PTR CALLBACK WeatherSearchAdvancedDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetFocus(GetDlgItem(hwndDlg, IDC_SEARCHCITY));
+ return TRUE;
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) == EN_SETFOCUS)
+ PostMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndDlg);
+ }
+ return FALSE;
+}
+
+INT_PTR WeatherCreateAdvancedSearchUI(WPARAM wParam, LPARAM lParam)
+{
+ HWND parent = (HWND)lParam;
+ if (parent)
+ return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHCITY), parent, WeatherSearchAdvancedDlgProc, 0);
+
+ return 0;
+}
+
+// service function for name search
+INT_PTR WeatherAdvancedSearch(WPARAM wParam, LPARAM lParam)
+{
+ if (searchId != -1) return 0; //only one search at a time
+
+ searchId = 1;
+ GetDlgItemText((HWND)lParam, IDC_SEARCHCITY, name1, 256);
+
+ // search for the weather station using a thread
+ mir_forkthread(NameSearchTimerProc, NULL);
+ return searchId;
+}
+
+// ============ SEARCH FOR A WEATHER STATION USING ID ============
+
+// Seaching station ID from a single weather service (Threaded)
+// sID = search string for the station ID
+// searchId = -1
+// sData = the ID search data for that particular weather service
+// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather)
+int IDSearchProc(TCHAR *sID, const int searchId, WIIDSEARCH *sData, TCHAR *svc, TCHAR *svcname)
+{
+ TCHAR str[MAX_DATA_LEN], newID[MAX_DATA_LEN];
+
+ if (sData->Available) {
+ char loc[255];
+ TCHAR *szData = NULL;
+
+ // load the page
+ mir_snprintf(loc, SIZEOF(loc), sData->SearchURL, sID);
+ if (InternetDownloadFile(loc, NULL, &szData) == 0) {
+ TCHAR* szInfo = szData;
+
+ // not found
+ if ( _tcsstr(szInfo, sData->NotFoundStr) == NULL)
+ GetDataValue(&sData->Name, str, &szInfo);
+ }
+ mir_free(szData);
+ // Station not found exit
+ if (str[0] == 0) return 1;
+ }
+
+ // give no station name but only ID if the search is unavailable
+ else _tcscpy(str, TranslateT("<Enter station name here>"));
+ mir_sntprintf(newID, SIZEOF(newID), _T("%s/%s"), svc, sID);
+
+ // set the search result and broadcast it
+ PROTOSEARCHRESULT psr = { sizeof(psr) };
+ psr.flags = PSR_TCHAR;
+ psr.nick = str;
+ psr.firstName = _T(" ");
+ psr.lastName = svcname;
+ psr.email = newID;
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+
+ return 0;
+}
+
+// ID search (Threaded)
+// sID: the ID to search for
+// searchId: don't change
+// return 0 if no error
+int IDSearch(TCHAR *sID, const int searchId)
+{
+ // for a normal ID search (ID != #)
+ if ( _tcscmp(sID, _T("#"))) {
+ WIDATALIST *Item = WIHead;
+
+ // search every weather service using the search station ID
+ while (Item != NULL) {
+ IDSearchProc(sID, searchId, &Item->Data.IDSearch, Item->Data.InternalName, Item->Data.DisplayName);
+ Item = Item->next;
+ }
+ NetlibHttpDisconnect();
+ }
+ // if the station ID is #, return a dummy result and quit the funciton
+ else {
+ // return an empty contact on "#"
+ PROTOSEARCHRESULT psr = { sizeof(psr) };
+ psr.flags = PSR_TCHAR;
+ psr.nick = TranslateT("<Enter station name here>"); // to be entered
+ psr.firstName = _T(" ");
+ psr.lastName = _T("");
+ psr.email = TranslateT("<Enter station ID here>"); // to be entered
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ }
+
+ return 0;
+}
+
+// ============ SEARCH FOR A WEATHER STATION BY NAME ============
+
+// Seaching station name from a single weather service (Threaded)
+// name = the name of the weather station to be searched
+// searchId = -1
+// sData = the name search data for that particular weather service
+// svcname = the name of the weather service that is currently searching (ie. Yahoo Weather)
+int NameSearchProc(TCHAR *name, const int searchId, WINAMESEARCH *sData, TCHAR *svc, TCHAR *svcname)
+{
+ char loc[256];
+ TCHAR Name[MAX_DATA_LEN], str[MAX_DATA_LEN], sID[MAX_DATA_LEN], *szData = NULL, *search;
+
+ // replace spaces with %20
+ {
+ mir_ptr<char> szSearchName( mir_utf8encodeT(name));
+ char *pstr = (char*)CallService(MS_NETLIB_URLENCODE, 0, (LPARAM)(char*)szSearchName);
+ wsprintfA(loc, sData->SearchURL, pstr);
+ HeapFree(GetProcessHeap(), 0, pstr);
+ }
+
+ if (InternetDownloadFile(loc, NULL, &szData) == 0) {
+ TCHAR* szInfo = szData;
+ search = _tcsstr(szInfo, sData->NotFoundStr); // determine if data is available
+ if (search == NULL) { // if data is found
+ // test if it is single result
+ if (sData->Single.Available && sData->Multiple.Available)
+ search = _tcsstr(szInfo, sData->SingleStr);
+ // for single result
+ if (sData->Single.Available && (search != NULL || !sData->Multiple.Available)) { // single result
+ // if station ID appears first in the downloaded data
+ if ( !_tcsicmp(sData->Single.First, _T("ID"))) {
+ GetDataValue(&sData->Single.ID, str, &szInfo);
+ wsprintf(sID, _T("%s/%s"), svc, str);
+ GetDataValue(&sData->Single.Name, Name, &szInfo);
+ }
+ // if station name appears first in the downloaded data
+ else if ( !_tcsicmp(sData->Single.First, _T("NAME"))) {
+ GetDataValue(&sData->Single.Name, Name, &szInfo);
+ GetDataValue(&sData->Single.ID, str, &szInfo);
+ wsprintf(sID, _T("%s/%s"), svc, str);
+ }
+ // if no station ID is obtained, quit the search
+ if (str[0] == 0) {
+ mir_free(szData);
+ return 1;
+ }
+
+ // if can't get the name, use the search string as name
+ if (Name[0] == 0)
+ _tcscpy(Name, name);
+
+ // set the data and broadcast it
+ PROTOSEARCHRESULT psr = { sizeof(psr) };
+ psr.flags = PSR_TCHAR;
+ psr.nick = Name;
+ psr.firstName = _T(" ");
+ psr.lastName = svcname;
+ psr.email = sID;
+ psr.id = sID;
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ mir_free(szData);
+ return 0;
+ }
+ // for multiple result
+ else if (sData->Multiple.Available) { // multiple results
+ // search for the next occurrence of the string
+ for (;;) {
+ // if station ID appears first in the downloaded data
+ if ( !_tcsicmp(sData->Multiple.First, _T("ID"))) {
+ GetDataValue(&sData->Multiple.ID, str, &szInfo);
+ wsprintf(sID, _T("%s/%s"), svc, str);
+ GetDataValue(&sData->Multiple.Name, Name, &szInfo);
+ }
+ // if station name appears first in the downloaded data
+ else if ( !_tcsicmp(sData->Multiple.First, _T("NAME"))) {
+ GetDataValue(&sData->Multiple.Name, Name, &szInfo);
+ GetDataValue(&sData->Multiple.ID, str, &szInfo);
+ wsprintf(sID, _T("%s/%s"), svc, str);
+ }
+ // if no station ID is obtained, search completed and quit the search
+ if (str[0] == 0) break;
+ // if can't get the name, use the search string as name
+ if (Name[0] == 0)
+ _tcscpy(Name, name);
+
+ PROTOSEARCHRESULT psr = { sizeof(psr) };
+ psr.flags = PSR_TCHAR;
+ psr.nick = Name;
+ psr.firstName = _T("");
+ psr.lastName = svcname;
+ psr.email = sID;
+ psr.id = sID;
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ } } }
+
+ mir_free(szData);
+ return 0;
+ }
+
+ mir_free(szData);
+ return 1;
+}
+
+// name search (Threaded)
+// name: the station name to search for
+// searchId: don't change
+// return 0 if no error
+int NameSearch(TCHAR *name, const int searchId)
+{
+ WIDATALIST *Item = WIHead;
+
+ // search every weather service using the search station name
+ while (Item != NULL) {
+ if (Item->Data.NameSearch.Single.Available || Item->Data.NameSearch.Multiple.Available)
+ NameSearchProc(name, searchId, &Item->Data.NameSearch, Item->Data.InternalName, Item->Data.DisplayName);
+ Item = Item->next;
+ }
+
+ NetlibHttpDisconnect();
+ return 0;
+}
+
+// ======================MENU ITEM FUNCTION ============
+
+// add a new weather station via find/add dialog
+int WeatherAdd(WPARAM wParam, LPARAM lParam)
+{
+ db_set_s(NULL, "FindAdd", "LastSearched", "Weather");
+ CallService(MS_FINDADD_FINDADD, 0, 0);
+ return 0;
+}
diff --git a/plugins/Weather/src/weather_contacts.cpp b/plugins/Weather/src/weather_contacts.cpp
new file mode 100644
index 0000000000..4c049f5d26
--- /dev/null
+++ b/plugins/Weather/src/weather_contacts.cpp
@@ -0,0 +1,486 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG Team
+Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved
+Copyright (c) 2002-2005 Calvin Che
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This file contain the source that is related to weather contacts,
+include the links, edit settings, and loading weather information for
+the contact.
+*/
+
+#include "weather.h"
+
+static void OpenUrl( TCHAR* format, TCHAR* id )
+{
+ TCHAR loc[512];
+
+ GetID( id );
+ mir_sntprintf( loc, SIZEOF(loc), format, id );
+
+ CallService(MS_UTILS_OPENURL, opt.NewBrowserWin | OUF_TCHAR, (LPARAM)loc );
+}
+
+//============ BASIC CONTACTS FUNCTIONS AND LINKS ============
+
+// view weather log for the contact
+// wParam = current contact
+INT_PTR ViewLog(WPARAM wParam, LPARAM lParam)
+{
+ // see if the log path is set
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString((HANDLE)wParam, WEATHERPROTONAME, "Log", &dbv)) {
+ if (dbv.pszVal[0] != 0)
+ ShellExecute((HWND)lParam, _T("open"), dbv.ptszVal, _T(""), _T(""), SW_SHOW);
+ db_free(&dbv);
+ }
+ else // display warning dialog if no path is specified
+ MessageBox(NULL, TranslateT("Weather condition was not logged."),
+ TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION);
+ return 0;
+}
+
+// read complete forecast
+// wParam = current contact
+INT_PTR LoadForecast(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR id[256], loc2[256];
+ GetStationID((HANDLE)wParam, id, SIZEOF(id));
+ if (id[0] != 0) {
+ // check if the complte forecast URL is set. If it is not, display warning and quit
+ if ( DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "InfoURL", loc2, SIZEOF(loc2)) || loc2[0] == 0) {
+ MessageBox(NULL, TranslateT("The URL for complete forcast have not been set. You can set it from the Edit Settings dialog."),
+ TranslateT("Weather Protocol"), MB_ICONINFORMATION);
+ return 1;
+ }
+ // set the url and open the webpage
+ OpenUrl(loc2, id );
+ }
+ return 0;
+}
+
+// load weather map
+// wParam = current contact
+INT_PTR WeatherMap(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR id[256], loc2[256];
+ GetStationID((HANDLE)wParam, id, SIZEOF(id));
+ if (id[0] != 0) {
+ // check if the weather map URL is set. If it is not, display warning and quit
+ if ( DBGetStaticString((HANDLE)wParam, WEATHERPROTONAME, "MapURL", loc2, SIZEOF(loc2)) || loc2[0] == 0) {
+ MessageBox(NULL, TranslateT("The URL for weather map have not been set. You can set it from the Edit Settings dialog."), TranslateT("Weather Protocol"), MB_ICONINFORMATION);
+ return 1;
+ }
+
+ // set the url and open the webpage
+ OpenUrl(loc2, id);
+ }
+
+ return 0;
+}
+
+//============ EDIT SETTINGS ============
+
+// show edit settings dialog
+// wParam = current contact
+INT_PTR EditSettings(WPARAM wParam, LPARAM lParam)
+{
+ HWND hEditDlg = WindowList_Find(hWindowList, (HANDLE)wParam);
+
+ // search the dialog list to prevent multiple instance of dialog for the same contact
+ if (hEditDlg != NULL) {
+ // if the dialog box already opened, bring it to the front
+ SetForegroundWindow(hEditDlg);
+ SetFocus(hEditDlg);
+ }
+ else {
+ // if the dialog box is not opened, open a new one
+ if (IsMyContact((HANDLE)wParam))
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_EDIT), NULL, DlgProcChange, (LPARAM)wParam);
+ }
+
+ return 0;
+}
+
+typedef struct
+{
+ HANDLE hContact;
+ HICON hRename;
+ HICON hUserDetail;
+ HICON hFile;
+ HICON hSrchAll;
+} CntSetWndDataType;
+
+// edit weather settings
+// lParam = current contact
+INT_PTR CALLBACK DlgProcChange(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ TCHAR str[256], str2[256], city[256], filter[256], *pfilter, *chop;
+ char loc[512];
+ OPENFILENAME ofn; // common dialog box structure
+ HANDLE hContact;
+ WIDATA *sData;
+ CntSetWndDataType *wndData = NULL;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ wndData = ( CntSetWndDataType* )mir_alloc(sizeof(CntSetWndDataType));
+ wndData->hContact = hContact = (HANDLE)lParam;
+ wndData->hRename = LoadSkinnedIcon(SKINICON_OTHER_RENAME);
+ wndData->hUserDetail = LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS);
+ wndData->hFile = LoadSkinnedIcon(SKINICON_EVENT_FILE);
+ wndData->hSrchAll = LoadSkinnedIcon(SKINICON_OTHER_SEARCHALL);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)wndData);
+
+ // set button images
+ SendDlgItemMessage(hwndDlg, IDC_GETNAME, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);
+ SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hUserDetail);
+ SendDlgItemMessage(hwndDlg, IDC_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hFile);
+ SendDlgItemMessage(hwndDlg, IDC_VIEW1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll);
+ SendDlgItemMessage(hwndDlg, IDC_RESET1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);
+ SendDlgItemMessage(hwndDlg, IDC_VIEW2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hSrchAll);
+ SendDlgItemMessage(hwndDlg, IDC_RESET2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)wndData->hRename);
+
+ // make all buttons flat
+ SendDlgItemMessage(hwndDlg, IDC_GETNAME, BUTTONSETASFLATBTN, 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) LPGENT("Get city name from ID"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_SVCINFO, BUTTONADDTOOLTIP, (WPARAM) LPGENT("Weather INI information"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_BROWSE, BUTTONADDTOOLTIP, (WPARAM) LPGENT("Browse"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_VIEW1, BUTTONADDTOOLTIP, (WPARAM) LPGENT("View webpage"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_RESET1, BUTTONADDTOOLTIP, (WPARAM) LPGENT("Reset to default"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_VIEW2, BUTTONADDTOOLTIP, (WPARAM) LPGENT("View webpage"), BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_RESET2, BUTTONADDTOOLTIP, (WPARAM) LPGENT("Reset to default"), BATF_TCHAR);
+
+ // save the handle for the contact
+ WindowList_Add(hWindowList, hwndDlg, hContact);
+
+ // start to get the settings
+ // if the setting not exist, leave the dialog box blank
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "ID", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_ID, dbv.ptszVal);
+ // check if the station is a default station
+ CheckDlgButton(hwndDlg, IDC_DEFA, _tcscmp(dbv.ptszVal, opt.Default) != 0);
+ db_free(&dbv);
+ }
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_NAME, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Log", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_LOG, dbv.ptszVal);
+ // if the log path is not empty, check the checkbox for external log
+ if (dbv.ptszVal[0]) CheckDlgButton(hwndDlg, IDC_External, TRUE);
+ db_free(&dbv);
+ }
+ // enable/disable the browse button depending on the value of external log checkbox
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));
+
+ // other checkbox options
+ CheckDlgButton(hwndDlg, IDC_DPop, db_get_b(hContact, WEATHERPROTONAME, "DPopUp", FALSE));
+ CheckDlgButton(hwndDlg, IDC_DAutoUpdate, db_get_b(hContact, WEATHERPROTONAME, "DAutoUpdate", FALSE));
+ CheckDlgButton(hwndDlg, IDC_Internal, db_get_b(hContact, WEATHERPROTONAME, "History", 0));
+
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "InfoURL", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_IURL, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "MapURL", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_MURL, dbv.ptszVal);
+ db_free(&dbv);
+ }
+
+ // display the dialog box and free memory
+ Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, WEATHERPROTONAME, "EditSetting_");
+ ShowWindow(hwndDlg, SW_SHOW);
+ break;
+
+ case WM_COMMAND:
+ wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ hContact = wndData ? wndData->hContact : NULL;
+
+ switch(LOWORD(wParam)) {
+ case IDC_ID:
+ // check if there are 2 parts in the ID (svc/id) seperated by "/"
+ // if not, don't let user change the setting
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(str));
+ chop = _tcsstr(str, _T("/"));
+ if (chop == NULL)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE);
+ else
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE);
+ break;
+
+ case IDC_NAME:
+ // check if station name is entered
+ // if not, don't let user change the setting
+ GetDlgItemText(hwndDlg, IDC_NAME, str, SIZEOF(str));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), str[0] != 0);
+ break;
+
+ case IDC_GETNAME:
+ {
+ // the button for getting station name from the internet
+ // this function uses the ID search for add/find weather station
+
+ if ( !CheckSearch()) return TRUE; // don't download if update is in progress
+ // get the weather update data using the string in the ID field
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(str));
+ GetSvc(str);
+ WIDATA *sData = GetWIData(str);
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(str));
+ GetID(str);
+ // if ID search is available, do it
+ if (sData->IDSearch.Available) {
+ TCHAR *szData = NULL;
+
+ // load the page
+ wsprintfA(loc, sData->IDSearch.SearchURL, str);
+ str[0] = 0;
+ if (InternetDownloadFile(loc, NULL, &szData) == 0) {
+ TCHAR *szInfo = szData;
+ TCHAR* search = _tcsstr(szInfo, sData->IDSearch.NotFoundStr);
+
+ // if the page is found (ie. valid ID), get the name of the city
+ if (search == NULL)
+ GetDataValue(&sData->IDSearch.Name, str, &szInfo);
+
+ // free memory
+ mir_free(szData);
+ }
+ NetlibHttpDisconnect();
+ }
+ // give no station name but only ID if the search is unavailable
+ if (str[0] != 0) SetDlgItemText(hwndDlg, IDC_NAME, str);
+ break;
+ }
+ case IDC_External:
+ // enable/disable the borwse button depending if the external log is enabled
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));
+ if ( !(BYTE)IsDlgButtonChecked(hwndDlg, IDC_External)) return TRUE;
+
+ case IDC_BROWSE: // fall through
+ // browse for the external log file
+ GetDlgItemText(hwndDlg, IDC_LOG, str, SIZEOF(str));
+ // Initialize OPENFILENAME
+ ZeroMemory(&ofn, sizeof(OPENFILENAME));
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFile = str;
+ ofn.nMaxFile = SIZEOF(str);
+ // set filters
+ _tcscpy(filter, TranslateT("Text Files"));
+ _tcscat(filter, _T(" (*.txt)"));
+ pfilter = filter + _tcslen(filter)+1;
+ _tcscpy(pfilter, _T("*.txt"));
+ pfilter = pfilter + _tcslen(pfilter)+1;
+ _tcscpy(pfilter, TranslateT("All Files"));
+ _tcscat(pfilter, _T(" (*.*)"));
+ pfilter = pfilter + _tcslen(pfilter)+1;
+ _tcscpy(pfilter, _T("*.*"));
+ pfilter = pfilter + _tcslen(pfilter)+1;
+ *pfilter = '\0';
+ ofn.lpstrFilter = filter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ // Display a Open dialog box and put the file name on the dialog
+ if (GetOpenFileName(&ofn))
+ SetDlgItemText(hwndDlg, IDC_LOG, ofn.lpstrFile);
+ // if there is no log file specified, disable external logging
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), ofn.lpstrFile[0] != 0);
+ break;
+
+ case IDC_VIEW1:
+ // view the page for more info
+ GetDlgItemText(hwndDlg, IDC_IURL, str, SIZEOF(str));
+ if (str[0] == 0) return TRUE;
+ GetDlgItemText(hwndDlg, IDC_ID, str2, SIZEOF(str2));
+ OpenUrl(str, str2);
+ break;
+
+ case IDC_VIEW2:
+ // view the page for weather map
+ GetDlgItemText(hwndDlg, IDC_MURL, str, SIZEOF(str));
+ if (str[0] == 0) return TRUE;
+ GetDlgItemText(hwndDlg, IDC_ID, str2, SIZEOF(str2));
+ OpenUrl(str, str2);
+ break;
+
+ case IDC_RESET1:
+ // reset the more info url to service default
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(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, SIZEOF(str));
+ GetSvc(str);
+ sData = GetWIData(str);
+ SetDlgItemText(hwndDlg, IDC_MURL, sData->DefaultMap);
+ break;
+
+ case IDC_SVCINFO:
+ // display the information of the ini file used by the weather station
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(str));
+ GetSvc(str);
+ GetINIInfo(str);
+ break;
+
+ case IDC_CHANGE:
+ // temporary disable the protocol while applying the change
+ // start writing the new settings to database
+ GetDlgItemText(hwndDlg, IDC_ID, str, SIZEOF(str));
+ db_set_ts(hContact, WEATHERPROTONAME, "ID", str);
+ if ((BYTE)IsDlgButtonChecked(hwndDlg, IDC_DEFA)) { // if default station is set
+ _tcscpy(opt.Default, str);
+ opt.DefStn = hContact;
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+ }
+ GetDlgItemText(hwndDlg, IDC_NAME, city, SIZEOF(city));
+ db_set_ts(hContact, WEATHERPROTONAME, "Nick", city);
+ wsprintf(str2, TranslateT("Current weather information for %s."), city);
+ if ((BYTE)IsDlgButtonChecked(hwndDlg, IDC_External)) {
+ GetDlgItemText(hwndDlg, IDC_LOG, str, SIZEOF(str));
+ db_set_ts(hContact, WEATHERPROTONAME, "Log", str);
+ }
+ else db_unset(hContact, WEATHERPROTONAME, "Log");
+
+ GetDlgItemText(hwndDlg, IDC_IURL, str, SIZEOF(str));
+ db_set_ts(hContact, WEATHERPROTONAME, "InfoURL", str);
+
+ GetDlgItemText(hwndDlg, IDC_MURL, str, SIZEOF(str));
+ db_set_ts(hContact, WEATHERPROTONAME, "MapURL", str);
+ db_set_w(hContact, WEATHERPROTONAME, "Status", ID_STATUS_OFFLINE);
+ db_set_w(hContact, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE);
+ AvatarDownloaded(hContact);
+ db_set_ts(hContact, WEATHERPROTONAME, "About", str2);
+ db_set_b(hContact, WEATHERPROTONAME, "History", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_Internal));
+ db_set_b(hContact, WEATHERPROTONAME, "Overwrite", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_Overwrite));
+ db_set_b(hContact, WEATHERPROTONAME, "File", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_External));
+ db_set_b(hContact, WEATHERPROTONAME, "DPopUp", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DPop));
+ db_set_b(hContact, WEATHERPROTONAME, "DAutoUpdate", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DAutoUpdate));
+
+ // re-enable the protocol and update the data for the station
+ db_set_s(hContact, WEATHERPROTONAME, "LastCondition", "None");
+ UpdateSingleStation((WPARAM)hContact, 0);
+
+ case IDCANCEL: // fall through
+ // remove the dialog from window list and close it
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ // remove the dialog from window list and close it
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ wndData = (CntSetWndDataType*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ Skin_ReleaseIcon(wndData->hFile);
+ Skin_ReleaseIcon(wndData->hRename);
+ Skin_ReleaseIcon(wndData->hSrchAll);
+ Skin_ReleaseIcon(wndData->hUserDetail);
+ mir_free(wndData);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+
+ WindowList_Remove(hWindowList, hwndDlg);
+ Utils_SaveWindowPosition(hwndDlg, NULL, WEATHERPROTONAME, "EditSetting_");
+ break;
+ }
+ return FALSE;
+}
+
+//============ CONTACT DELETION ============
+
+// when a contact is deleted, make sure some other contact take over the default station
+// wParam = deleted contact
+int ContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ if ( !IsMyContact((HANDLE)wParam))
+ return 0;
+
+ removeWindow((HANDLE)wParam);
+
+ // exit this function if it is not default station
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString((HANDLE)wParam, WEATHERPROTONAME, "ID", &dbv)) {
+ if ( _tcscmp(dbv.ptszVal, opt.Default)) {
+ db_free(&dbv);
+ return 0;
+ }
+ db_free(&dbv);
+ }
+
+ // now the default station is deleted, try to get a new one
+
+ // start looking for other weather stations
+ HANDLE hContact = db_find_first();
+ while(hContact) {
+ if (IsMyContact(hContact)) {
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "ID", &dbv)) {
+ // if the station is not a default station, set it as the new default station
+ // this is the first weather station encountered from the search
+ if ( _tcscmp(opt.Default, dbv.ptszVal)) {
+ _tcscpy(opt.Default, dbv.ptszVal);
+ opt.DefStn = hContact;
+ db_free(&dbv);
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv)) {
+ TCHAR str[255];
+ mir_sntprintf(str, SIZEOF(str), TranslateT("%s is now the default weather station"), dbv.ptszVal);
+ db_free(&dbv);
+ MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK | MB_ICONINFORMATION);
+ }
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+ return 0; // exit this function quickly
+ }
+ db_free(&dbv);
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ // got here if no more weather station left
+ opt.Default[0] = 0; // no default station
+ opt.DefStn = NULL;
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+ return 0;
+}
+
+BOOL IsMyContact(HANDLE hContact)
+{
+ const char* szProto = GetContactProto(hContact);
+ return szProto != NULL && strcmp(WEATHERPROTONAME, szProto) == 0;
+}
diff --git a/plugins/Weather/src/weather_conv.cpp b/plugins/Weather/src/weather_conv.cpp
new file mode 100644
index 0000000000..780253b8ac
--- /dev/null
+++ b/plugins/Weather/src/weather_conv.cpp
@@ -0,0 +1,644 @@
+/*
+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 unit conversion, icon assignment,
+string conversions, display text parsing, etc
+*/
+
+#include "weather.h"
+
+//============ SOME HELPER FUNCTIONS ============
+
+// see if a string is a number
+// s = the string to be determined
+// return value = true if the string is a number, false if it isn't
+BOOL is_number(TCHAR *s)
+{
+ BOOL tag = FALSE;
+ // looking character by character
+ // for a number: numerous spaces in front, then optional +/-, then the number
+ // don't care anything that comes after it
+ while(*s != '\0')
+ {
+ if (*s >= '0' && *s <= '9') return TRUE;
+ else if (*s == ' ');
+ else if (*s != '+' && *s != '-') return FALSE;
+ else if ((*s == '+' || *s == '-') && !tag) tag = TRUE;
+ else return FALSE;
+ s++;
+ }
+ return FALSE;
+}
+
+static void numToStr(double num, TCHAR* str)
+{
+ int i = (int)(num * (opt.NoFrac ? 10 : 100));
+ int u = abs(i);
+
+ int r = u % 10;
+ int w = u / 10 + (r >= 5);
+
+ if (opt.NoFrac)
+ r = 0;
+ else {
+ r = w % 10;
+ w /= 10;
+ }
+
+ if (i < 0 && (w || r)) *(str++) = '-';
+ if (r)
+ wsprintf(str, _T("%i.%i"), w, r);
+ else
+ wsprintf(str, _T("%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(TCHAR *tempchar, TCHAR *unit, TCHAR* str)
+{
+ // unit can be C, F
+ double temp;
+ TCHAR tstr[20];
+
+ TrimString(tempchar);
+ if (tempchar[0] == '-' && tempchar[1] == ' ')
+ memmove(&tempchar[1], &tempchar[2], sizeof(TCHAR)*(_tcslen(&tempchar[2])+1));
+
+ // quit if the value obtained is N/A or not a number
+ if ( !_tcscmp(tempchar, NODATA) || !_tcscmp(tempchar, _T("N/A"))) {
+ _tcscpy(str, tempchar);
+ return;
+ }
+ if ( !is_number(tempchar)) {
+ _tcscpy(str, NODATA);
+ return;
+ }
+
+ // convert the string to an integer
+ temp = _ttof(tempchar);
+
+ // convert all to F first
+ if ( !_tcsicmp(unit, _T("C"))) temp = (temp*9/5)+32;
+ else if ( !_tcsicmp(unit, _T("K"))) temp = ((temp-273.15)*9/5)+32;
+
+ // convert to apporiate unit
+ switch (opt.tUnit) {
+ case 1:
+ // rounding
+ numToStr((temp-32)/9*5, tstr);
+ if (opt.DoNotAppendUnit)
+ wsprintf(str, _T("%s"), tstr);
+ else
+ wsprintf(str, _T("%s%sC"), tstr, opt.DegreeSign);
+ break;
+
+ case 2:
+ numToStr(temp, tstr);
+ if (opt.DoNotAppendUnit)
+ wsprintf(str, _T("%s"), tstr);
+ else
+ wsprintf(str, _T("%s%sF"), tstr, opt.DegreeSign);
+ break;
+ }
+}
+
+// temperature conversion
+// tempchar = the string containing the pressure value
+// unit = the unit for pressure
+// return value = the converted pressure with unit; if fail, return the original string
+void GetPressure(TCHAR *tempchar, TCHAR *unit, TCHAR* str)
+{
+ // unit can be kPa, hPa, mb, in, mm, torr
+ double tempunit = 0, output;
+ int intunit;
+
+ // convert the string to a floating point number (always positive)
+ // if it end up with 0, then it's not a number, return the original string and quit
+ output = _ttof(tempchar);
+ if (output == 0) {
+ _tcscpy(str, tempchar);
+ return;
+ }
+
+ // convert all to mb first
+ if ( !_tcsicmp(unit, _T("KPA")))
+ tempunit = (double)output * 10;
+ else if ( !_tcsicmp(unit, _T("HPA")))
+ tempunit = (double)output;
+ else if ( !_tcsicmp(unit, _T("MB")))
+ tempunit = (double)output;
+ else if ( !_tcsicmp(unit, _T("IN")))
+ tempunit = (double)output * 33.86388;
+ else if ( !_tcsicmp(unit, _T("MM")))
+ tempunit = (double)output * 1.33322;
+ else if ( !_tcsicmp(unit, _T("TORR")))
+ tempunit = (double)output * 1.33322;
+
+ // convert to apporiate unit
+ switch (opt.pUnit) {
+ case 1:
+ intunit = (int)(tempunit + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("kPa"));
+ break;
+ case 2:
+ intunit = (int)(tempunit + 0.5);
+ wsprintf(str, _T("%i %s"), intunit, opt.DoNotAppendUnit ? _T("") : TranslateT("mb"));
+ break;
+ case 3:
+ intunit = (int)((tempunit*10 / 33.86388) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("in"));
+ break;
+ case 4:
+ intunit = (int)((tempunit*10 / 1.33322) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("mm"));
+ break;
+ default:
+ _tcscpy(str, tempchar);
+ break;
+
+ }
+}
+
+// speed conversion
+// tempchar = the string containing the speed value
+// unit = the unit for speed
+// return value = the converted speed with unit; if fail, return _T(""
+void GetSpeed(TCHAR *tempchar, TCHAR *unit, TCHAR *str)
+{
+ // unit can be km/h, mph, m/s, knots
+ double tempunit;
+ TCHAR tstr[20];
+
+ str[0] = 0;
+
+ // convert the string into an integer (always positive)
+ // if the result is 0, then the string is not a number, return _T(""
+ tempunit = _ttof(tempchar);
+ if (tempunit == 0 && tempchar[0] != '0')
+ return;
+
+ // convert all to m/s first
+ if ( !_tcsicmp(unit, _T("KM/H")))
+ tempunit /= 3.6;
+// else if ( !_tcsicmp(unit, _T("M/S"))
+// tempunit = tempunit;
+ else if ( !_tcsicmp(unit, _T("MPH")))
+ tempunit *= 0.44704;
+ else if ( !_tcsicmp(unit, _T("KNOTS")))
+ tempunit *= 0.514444;
+
+ // convert to apporiate unit
+ switch (opt.wUnit) {
+ case 1:
+ numToStr(tempunit * 3.6, tstr);
+ wsprintf(str, _T("%s %s"), tstr, opt.DoNotAppendUnit ? _T("") : TranslateT("km/h"));
+ break;
+ case 2:
+ numToStr(tempunit, tstr);
+ wsprintf(str, _T("%s %s"), tstr, opt.DoNotAppendUnit ? _T("") : TranslateT("m/s"));
+ break;
+ case 3:
+ numToStr(tempunit / 0.44704, tstr);
+ wsprintf(str, _T("%s %s"), tstr, opt.DoNotAppendUnit ? _T("") : TranslateT("mph"));
+ break;
+ case 4:
+ numToStr(tempunit / 0.514444, tstr);
+ wsprintf(str, _T("%s %s"), tstr, opt.DoNotAppendUnit ? _T("") : TranslateT("knots"));
+ break;
+ }
+}
+
+// distance conversion
+// tempchar = the string containing the distance value
+// unit = the unit for distance
+// return value = the converted distance with unit; if fail, return original string
+void GetDist(TCHAR *tempchar, TCHAR *unit, TCHAR *str)
+{
+ // unit can be km, miles
+ double tempunit = 0, output;
+ int intunit;
+
+ // convert the string to a floating point number (always positive)
+ // if it end up with 0, then it's not a number, return the original string and quit
+ output = _ttof(tempchar);
+ if (output == 0) {
+ _tcscpy(str, tempchar);
+ return;
+ }
+
+ // convert all to km first
+ if ( !_tcsicmp(unit, _T("KM")))
+ tempunit = (double)output;
+ else if ( !_tcsicmp(unit, _T("MILES")))
+ tempunit = (double)output * 1.609;
+
+ // convert to apporiate unit
+ switch (opt.vUnit) {
+ case 1:
+ intunit = (int)((tempunit*10) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("km"));
+ break;
+ case 2:
+ intunit = (int)((tempunit*10 / 1.609) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("miles"));
+ break;
+ default:
+ _tcscpy(str, tempchar);
+ break;
+ }
+}
+
+// elevation conversion
+// tempchar = the string containing the elevation value
+// unit = the unit for elevation
+// return value = the converted elevation with unit; if fail, return original string
+void GetElev(TCHAR *tempchar, TCHAR *unit, TCHAR *str)
+{
+ // unit can be ft, m
+ double tempunit = 0, output;
+ int intunit;
+
+ // convert the string to a floating point number (always positive)
+ // if it end up with 0, then it's not a number, return the original string and quit
+ output = _ttof(tempchar);
+ if (output == 0) {
+ _tcscpy(str, tempchar);
+ return;
+ }
+
+ // convert all to m first
+ if ( !_tcsicmp(unit, _T("M")))
+ tempunit = (double)output;
+ else if ( !_tcsicmp(unit, _T("FT")))
+ tempunit = (double)output / 3.28;
+
+ // convert to apporiate unit
+ switch (opt.eUnit) {
+ case 1:
+ intunit = (int)((tempunit*10 * 3.28) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("ft"));
+ break;
+ case 2:
+ intunit = (int)((tempunit*10) + 0.5);
+ wsprintf(str, _T("%i.%i %s"), intunit/10, intunit%10, opt.DoNotAppendUnit ? _T("") : TranslateT("m"));
+ break;
+ default:
+ _tcscpy(str, tempchar);
+ break;
+ }
+}
+
+//============ CONDITION ICON ASSIGNMENT ============
+
+// assign the contact icon (status) from the condition string
+// the description may be different between different sources
+// cond = the string for weather condition
+// return value = status for the icon (ONLINE, OFFLINE, etc)
+
+static const TCHAR *statusStr[10] = { _T("Lightning"), _T("Fog"), _T("Snow Shower"), _T("Snow"), _T("Rain Shower"), _T("Rain"), _T("Partly Cloudy"), _T("Cloudy"), _T("Sunny"), _T("N/A") };
+static const WORD statusValue[10] = { LIGHT, FOG, SSHOWER, SNOW, RSHOWER, RAIN, PCLOUDY, CLOUDY, SUNNY, NA };
+
+WORD GetIcon(const TCHAR* cond, WIDATA *Data)
+{
+ int i;
+
+ // set the icon using ini
+ for (i=0; i<10; i++)
+ if ( IsContainedInCondList(cond, &Data->CondList[i]))
+ return statusValue[i];
+
+ // internal detection
+ if (
+ _tcsstr(cond, _T("mainy sunny")) != NULL ||
+ _tcsstr(cond, _T("mainy clear")) != NULL ||
+ _tcsstr(cond, _T("partly cloudy")) != NULL ||
+ _tcsstr(cond, _T("mostly")) != NULL ||
+ _tcsstr(cond, _T("clouds")) != NULL) {
+ return PCLOUDY;
+ }
+ else if (
+ _tcsstr(cond, _T("sunny")) != NULL ||
+ _tcsstr(cond, _T("clear")) != NULL ||
+ _tcsstr(cond, _T("fair")) != NULL) {
+ return SUNNY;
+ }
+ else if (
+ _tcsstr(cond, _T("thunder")) != NULL ||
+ _tcsstr(cond, _T("t-storm")) != NULL) {
+ return LIGHT;
+ }
+ else if (
+ _tcsstr(cond, _T("cloud")) != NULL ||
+ _tcsstr(cond, _T("overcast")) != NULL) {
+ return CLOUDY;
+ }
+ else if (
+ _tcsstr(cond, _T("fog")) != NULL ||
+ _tcsstr(cond, _T("mist")) != NULL ||
+ _tcsstr(cond, _T("smoke")) != NULL ||
+ _tcsstr(cond, _T("sand")) != NULL ||
+ _tcsstr(cond, _T("dust")) != NULL ||
+ _tcsstr(cond, _T("haze")) != NULL) {
+ return FOG;
+ }
+ else if (
+ (_tcsstr(cond, _T("shower")) != NULL && _tcsstr(cond, _T("snow")) != NULL) ||
+ _tcsstr(cond, _T("flurries")) != NULL) {
+ return SSHOWER;
+ }
+ else if (
+ _tcsstr(cond, _T("rain shower")) != NULL ||
+ _tcsstr(cond, _T("shower")) != NULL)
+ {
+ return RSHOWER;
+ }
+ else if (
+ _tcsstr(cond, _T("snow")) != NULL ||
+ _tcsstr(cond, _T("ice")) != NULL ||
+ _tcsstr(cond, _T("freezing")) != NULL ||
+ _tcsstr(cond, _T("wintry")) != NULL) {
+ return SNOW;
+ }
+ else if (
+ _tcsstr(cond, _T("drizzle")) != NULL ||
+ _tcsstr(cond, _T("rain")) != NULL)
+ {
+ return RAIN;
+ }
+
+ // set the icon using langpack
+ for (i=0; i < 9; i++) {
+ TCHAR LangPackStr[64], LangPackStr1[128];
+ int j = 0;
+ do {
+ j++;
+ // using the format _T("# Weather <condition name> <counter> #"
+ mir_sntprintf(LangPackStr, SIZEOF(LangPackStr), _T("# Weather %s %i #"), statusStr[i], j);
+ mir_sntprintf(LangPackStr1, SIZEOF(LangPackStr1), _T("%s"), TranslateTS(LangPackStr));
+ CharLowerBuff(LangPackStr1, (DWORD)_tcslen(LangPackStr1));
+ if (_tcsstr(cond, LangPackStr1) != NULL)
+ return statusValue[i];
+ // loop until the translation string exists (ie, the translated string is differ from original)
+ }
+ while ( _tcscmp(TranslateTS(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(TCHAR *str)
+{
+ TCHAR *pstr;
+ BOOL nextUp = TRUE;
+
+ CharLowerBuff(str, (DWORD)_tcslen(str));
+ for(pstr = str; *pstr; pstr++) {
+ if (*pstr == ' ' || *pstr == '-')
+ nextUp = TRUE;
+ else {
+ TCHAR ch = *(TCHAR*)pstr;
+ if (nextUp)
+ *pstr = ( TCHAR )CharUpper((LPTSTR)ch);
+ nextUp = FALSE;
+} } }
+
+// the next 2 functions are copied from miranda source
+// str = the string to modify
+
+void TrimString(char *str)
+{
+ size_t len, start;
+
+ len = strlen(str);
+ while(len && (unsigned char)str[len-1] <= ' ') str[--len] = 0;
+ for(start=0; (unsigned char)str[start] <= ' ' && str[start]; start++);
+ memmove(str, str+start, len-start+1);
+}
+
+void TrimString(WCHAR *str)
+{
+ size_t len, start;
+
+ len = wcslen(str);
+ while(len && (unsigned char)str[len-1] <= ' ') str[--len] = 0;
+ for(start=0; (unsigned char)str[start] <= ' ' && str[start]; start++);
+ memmove(str, str+start, (len-start+1)*sizeof(WCHAR));
+}
+
+// convert \t to tab and \n to linefeed
+void ConvertBackslashes(char *str)
+{
+ for (char *pstr=str; *pstr; pstr = CharNextA(pstr)) {
+ if (*pstr == '\\') {
+ switch(pstr[1]) {
+ case 'n': *pstr = '\n'; break;
+ case 't': *pstr = '\t'; break;
+ default: *pstr = pstr[1]; break;
+ }
+ memmove(pstr+1, pstr+2, strlen(pstr+2)+1);
+} } }
+
+// replace spaces with _T("%20"
+// dis = original string
+// return value = the modified string with space -> _T("%20"
+char *GetSearchStr(char *dis)
+{
+ char *pstr = dis;
+ size_t len = strlen(dis);
+ while (*pstr != 0)
+ {
+ if (*pstr == ' ')
+ {
+ memmove(pstr+3, pstr+1, len);
+ memcpy(pstr, _T("%20"), 3);
+ pstr += 2;
+ }
+ pstr++;
+ len--;
+ }
+ return dis;
+}
+
+//============ ICON ASSIGNMENT ============
+
+// make display and history strings
+// w = WEATHERINFO data to be parsed
+// dis = the string to parse
+// return value = the parsed string
+TCHAR* GetDisplay(WEATHERINFO *w, const TCHAR *dis, TCHAR* str)
+{
+ TCHAR lpzDate[32], chr;
+ char name[256], temp[2];
+ DBVARIANT dbv;
+ size_t i;
+
+ // Clear the string
+ str[0] = 0;
+
+ // looking character by character
+ for (i=0; i < _tcslen(dis); i++) {
+ // for the escape characters
+ if (dis[i] == '\\') {
+ i++;
+ chr = dis[i];
+ switch (chr) {
+ case '%': _tcscat(str, _T("%")); break;
+ case 't': _tcscat(str, _T("\t")); break;
+ case 'n': _tcscat(str, _T("\r\n")); break;
+ case '\\': _tcscat(str, _T("\\")); break;
+ }
+ }
+
+ // for the % varaibles
+ else if (dis[i] == '%')
+ {
+ i++;
+ chr = dis[i];
+ // turn capitalized characters to small case
+ if (chr < 'a' && chr != '[' && chr != '%') chr = (char)((int)chr + 32);
+ switch (chr) {
+ case 'c': _tcscat(str, w->cond); break;
+ case 'd': // get the current date
+ GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, lpzDate, SIZEOF(lpzDate));
+ _tcscat(str, lpzDate); break;
+ case 'e': _tcscat(str, w->dewpoint); break;
+ case 'f': _tcscat(str, w->feel); break;
+ case 'h': _tcscat(str, w->high); break;
+ case 'i': _tcscat(str, w->winddir); break;
+ case 'l': _tcscat(str, w->low); break;
+ case 'm': _tcscat(str, w->humid); break;
+ case 'n': _tcscat(str, w->city); break;
+ case 'p': _tcscat(str, w->pressure); break;
+ case 'r': _tcscat(str, w->sunrise); break;
+ case 's': _tcscat(str, w->id); break;
+ case 't': _tcscat(str, w->temp); break;
+ case 'u':
+ if (_tcscmp(w->update, NODATA)) _tcscat(str, w->update);
+ else _tcscat(str, TranslateT("<unknown time>"));
+ break;
+ case 'v': _tcscat(str, w->vis); break;
+ case 'w': _tcscat(str, w->wind); break;
+ case 'y': _tcscat(str, w->sunset); break;
+ case '%': _tcscat(str, _T("%")); break;
+ case '[': // custom variables
+ i++;
+ name[0] = 0;
+ // read the entire variable name
+ while (dis[i] != ']' && i < _tcslen(dis)) {
+ wsprintfA(temp, "%c", dis[i++]);
+ strcat(name, temp);
+ }
+ // access the database to get its value
+ if ( !DBGetContactSettingTString(w->hContact, WEATHERCONDITION, name, &dbv)) {
+ if (dbv.ptszVal != TranslateTS(NODATA) && dbv.ptszVal != TranslateT("<Error>"))
+ _tcscat(str, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ break;
+ }
+ }
+ // if the character is not a variable, write the original character to the new string
+ else {
+ wsprintf( lpzDate, _T("%c"), dis[i]);
+ _tcscat(str, lpzDate);
+ } }
+
+ return str;
+}
+
+TCHAR svcReturnText[MAX_TEXT_SIZE];
+INT_PTR GetDisplaySvcFunc(WPARAM wParam, LPARAM lParam)
+{
+ WEATHERINFO winfo = LoadWeatherInfo((HANDLE)wParam);
+ return (INT_PTR)GetDisplay(&winfo, (TCHAR*)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(TCHAR *pszID)
+{
+ TCHAR *chop = _tcsstr(pszID, _T("/"));
+ if (chop != NULL) *chop = '\0';
+ else pszID[0] = 0;
+}
+
+// get the id use for update without the service internal name
+// mod/id <- the id part
+// pszID = original 2-part id, return the single part id
+void GetID(TCHAR *pszID)
+{
+ TCHAR *chop = _tcsstr(pszID, _T("/"));
+ if (chop != NULL) _tcscpy(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
+
+TCHAR *GetError(int code)
+{
+ TCHAR *str, str2[100];
+ switch (code) {
+ case 10: str = E10; break;
+ case 11: str = E11; break;
+ case 12: str = E12; break;
+ case 20: str = E20; break;
+ case 30: str = E30; break;
+ case 40: str = E40; break;
+ case 42: str = E42; break;
+ case 43: str = E43; break;
+ case 99: str = E99; break;
+ case 204: str = E204; break;
+ case 301: str = E301; break;
+ case 305: str = E305; break;
+ case 307: str = E307; break;
+ case 400: str = E400; break;
+ case 401: str = E401; break;
+ case 402: str = E402; break;
+ case 403: str = E403; break;
+ case 404: str = E404; break;
+ case 405: str = E405; break;
+ case 407: str = E407; break;
+ case 410: str = E410; break;
+ case 500: str = E500; break;
+ case 502: str = E502; break;
+ case 503: str = E503; break;
+ case 504: str = E504; break;
+ default:
+ mir_sntprintf(str2, SIZEOF(str2), TranslateT("HTTP Error %i"), code);
+ str = str2;
+ break;
+ }
+ return str;
+}
diff --git a/plugins/Weather/src/weather_data.cpp b/plugins/Weather/src/weather_data.cpp
new file mode 100644
index 0000000000..5def028c3d
--- /dev/null
+++ b/plugins/Weather/src/weather_data.cpp
@@ -0,0 +1,472 @@
+/*
+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 loading, obtaining, and
+saving individual weather data for a weather contact.
+*/
+
+#include "weather.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(HANDLE hContact, TCHAR* id, size_t idlen)
+{
+ // accessing the database
+ if ( DBGetStaticString(hContact, WEATHERPROTONAME, "ID", id, idlen))
+ id[0] = 0;
+}
+
+// initialize weather info by loading values from database
+// hContact = current contact handle
+// return value = the current weather information in WEATHERINFO struct
+WEATHERINFO LoadWeatherInfo(HANDLE 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, SIZEOF(winfo.id));
+
+ if ( DBGetStaticString(hContact, WEATHERPROTONAME, "Nick", winfo.city, SIZEOF(winfo.city)))
+ _tcscpy(winfo.city, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Update", winfo.update, SIZEOF(winfo.update)))
+ _tcscpy(winfo.update, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Condition", winfo.cond, SIZEOF(winfo.cond)))
+ _tcscpy(winfo.cond, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Temperature", winfo.temp, SIZEOF(winfo.temp)))
+ _tcscpy(winfo.temp, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "High", winfo.high, SIZEOF(winfo.high)))
+ _tcscpy(winfo.high, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Low", winfo.low, SIZEOF(winfo.low)))
+ _tcscpy(winfo.low, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Sunset", winfo.sunset, SIZEOF(winfo.sunset)))
+ _tcscpy(winfo.sunset, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Sunrise", winfo.sunrise, SIZEOF(winfo.sunrise)))
+ _tcscpy(winfo.sunrise, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Wind Speed", winfo.wind, SIZEOF(winfo.wind)))
+ _tcscpy(winfo.wind, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Wind Direction", winfo.winddir, SIZEOF(winfo.winddir)))
+ _tcscpy(winfo.winddir, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Dewpoint", winfo.dewpoint, SIZEOF(winfo.dewpoint)))
+ _tcscpy(winfo.dewpoint, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Pressure", winfo.pressure, SIZEOF(winfo.pressure)))
+ _tcscpy(winfo.pressure, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Visibility", winfo.vis, SIZEOF(winfo.vis)))
+ _tcscpy(winfo.vis, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Humidity", winfo.humid, SIZEOF(winfo.humid)))
+ _tcscpy(winfo.humid, NODATA);
+ if ( DBGetStaticString(hContact, WEATHERCONDITION, "Feel", winfo.feel, SIZEOF(winfo.feel)))
+ _tcscpy(winfo.feel, NODATA);
+
+ winfo.status = (WORD)db_get_w(hContact, WEATHERPROTONAME, "StatusIcon", ID_STATUS_OFFLINE);
+ return winfo;
+}
+
+// getting weather setting from database
+// return 0 on success
+int DBGetData(HANDLE hContact, char *setting, DBVARIANT *dbv)
+{
+ if ( DBGetContactSettingTString(hContact, WEATHERCONDITION, setting, dbv)) {
+ size_t len = strlen(setting) + 1;
+ char *set = (char*)alloca(len + 1);
+ *set = '#';
+ memcpy(set + 1, setting, len);
+
+ if ( DBGetContactSettingTString(hContact, WEATHERCONDITION, set, dbv))
+ return 1;
+ }
+ return 0;
+}
+
+int DBGetStaticString(HANDLE hContact, const char *szModule, const char *valueName, TCHAR *dest, size_t dest_len)
+{
+ DBVARIANT dbv;
+ if ( DBGetContactSettingTString( hContact, szModule, valueName, &dbv ))
+ return 1;
+
+ _tcsncpy( dest, dbv.ptszVal, dest_len );
+ dest[ dest_len-1 ] = 0;
+ db_free( &dbv );
+ 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(DWORD lastver)
+{
+ TCHAR str[255];
+ int ContactCount = 0;
+ HANDLE LastContact = NULL;
+ DBVARIANT dbv;
+ // loop through all contacts
+ HANDLE hContact = db_find_first();
+ while(hContact) {
+ // see if the contact is a weather contact
+ if ( IsMyContact(hContact)) {
+ // check for upgrade
+ if (lastver < __VERSION_DWORD)
+ UpgradeContact(lastver, hContact);
+ db_set_w(hContact,WEATHERPROTONAME, "Status",ID_STATUS_OFFLINE);
+ db_set_w(hContact,WEATHERPROTONAME, "StatusIcon",ID_STATUS_OFFLINE);
+ db_unset(hContact, "CList", "MyHandle");
+ // clear all data
+ if ( DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv)) {
+ db_set_ts(hContact, WEATHERPROTONAME, "Nick", TranslateT("<Enter city name here>"));
+ db_set_s(hContact, WEATHERPROTONAME, "LastLog", "never");
+ db_set_s(hContact, WEATHERPROTONAME, "LastCondition", "None");
+ db_set_s(hContact, WEATHERPROTONAME, "LastTemperature", "None");
+ }
+ else db_free(&dbv);
+
+ DBDataManage(hContact, WDBM_REMOVE, 0, 0);
+ db_set_s(hContact, "UserInfo", "MyNotes", "");
+ // reset update tag
+ db_set_b(hContact,WEATHERPROTONAME, "IsUpdated",FALSE);
+ // reset logging settings
+ if ( !DBGetContactSettingTString(hContact,WEATHERPROTONAME, "Log", &dbv)) {
+ db_set_b(hContact,WEATHERPROTONAME, "File",(BYTE)(dbv.ptszVal[0] != 0));
+ db_free(&dbv);
+ }
+ else db_set_b(hContact,WEATHERPROTONAME, "File",FALSE);
+
+ // if no default station find, assign a new one
+ if (opt.Default[0] == 0) {
+ GetStationID(hContact, opt.Default, SIZEOF(opt.Default));
+
+ opt.DefStn = hContact;
+ if ( !DBGetContactSettingTString(hContact,WEATHERPROTONAME, "Nick",&dbv)) {
+ wsprintf(str, TranslateT("%s is now the default weather station"), dbv.ptszVal);
+ db_free(&dbv);
+ MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK|MB_ICONINFORMATION);
+ }
+ }
+ // get the handle of the default station
+ if (opt.DefStn == NULL) {
+ if ( !DBGetContactSettingTString(hContact,WEATHERPROTONAME, "ID",&dbv)) {
+ if ( !_tcscmp(dbv.ptszVal, opt.Default))
+ opt.DefStn = hContact;
+ db_free(&dbv);
+ }
+ }
+ ContactCount++; // increment counter
+ LastContact = hContact;
+ }
+ hContact = db_find_next(hContact);
+ }
+
+ // if weather contact exists, set the status to online so it is ready for update
+ // if (ContactCount != 0) status = ONLINE;
+ // in case where the default station is missing
+ if (opt.DefStn == NULL && ContactCount != 0) {
+ if ( !DBGetContactSettingTString(LastContact, WEATHERPROTONAME, "ID", &dbv)) {
+ _tcscpy(opt.Default, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ opt.DefStn = LastContact;
+ if ( !DBGetContactSettingTString(LastContact,WEATHERPROTONAME, "Nick",&dbv)) {
+ wsprintf(str, TranslateT("%s is now the default weather station"), dbv.ptszVal);
+ db_free(&dbv);
+ MessageBox(NULL, str, TranslateT("Weather Protocol"), MB_OK|MB_ICONINFORMATION);
+ }
+ }
+ // save option in case of default station changed
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+}
+
+void ConvertDataValue(WIDATAITEM *UpdateData, TCHAR *Data)
+{
+ TCHAR str[MAX_DATA_LEN];
+
+ // convert the unit
+ if ( _tcscmp(Data, TranslateT("<Error>")) && _tcscmp(Data, NODATA) && _tcscmp(Data, TranslateTS(NODATA))) {
+ // temperature
+ if ( !_tcscmp(UpdateData->Name, _T("Temperature")) || !_tcscmp(UpdateData->Name, _T("High")) ||
+ !_tcscmp(UpdateData->Name, _T("Low")) || !_tcscmp(UpdateData->Name, _T("Feel")) ||
+ !_tcscmp(UpdateData->Name, _T("Dewpoint")) ||
+ !_tcsicmp(UpdateData->Unit, _T("C")) || !_tcsicmp(UpdateData->Unit, _T("F")) ||
+ !_tcsicmp(UpdateData->Unit, _T("K")))
+ {
+ GetTemp(Data, UpdateData->Unit, str);
+ _tcscpy(Data, str);
+ }
+ // pressure
+ else if ( !_tcscmp(UpdateData->Name, _T("Pressure")) || !_tcsicmp(UpdateData->Unit, _T("HPA")) ||
+ !_tcsicmp(UpdateData->Unit, _T("KPA")) || !_tcsicmp(UpdateData->Unit, _T("MB")) ||
+ !_tcsicmp(UpdateData->Unit, _T("TORR")) || !_tcsicmp(UpdateData->Unit, _T("IN")) ||
+ !_tcsicmp(UpdateData->Unit, _T("MM")))
+ {
+ GetPressure(Data, UpdateData->Unit, str);
+ _tcscpy(Data, str);
+ }
+ // speed
+ else if ( !_tcscmp(UpdateData->Name, _T("Wind Speed")) || !_tcsicmp(UpdateData->Unit, _T("KM/H")) ||
+ !_tcsicmp(UpdateData->Unit, _T("M/S")) || !_tcsicmp(UpdateData->Unit, _T("MPH")) ||
+ !_tcsicmp(UpdateData->Unit, _T("KNOTS")))
+ {
+ GetSpeed(Data, UpdateData->Unit, str);
+ _tcscpy(Data, str);
+ }
+ // visibility
+ else if ( !_tcscmp(UpdateData->Name, _T("Visibility")) || !_tcsicmp(UpdateData->Unit, _T("KM")) ||
+ !_tcsicmp(UpdateData->Unit, _T("MILES")))
+ {
+ GetDist(Data, UpdateData->Unit, str);
+ _tcscpy(Data, str);
+ }
+ // elevation
+ else if ( !_tcscmp(UpdateData->Name, _T("Elevation")) || !_tcsicmp(UpdateData->Unit, _T("FT")) ||
+ !_tcsicmp(UpdateData->Unit, _T("M")))
+ {
+ GetElev(Data, UpdateData->Unit, str);
+ _tcscpy(Data, str);
+ }
+ // converting case for condition to the upper+lower format
+ else if ( !_tcsicmp(UpdateData->Unit, _T("COND")))
+ CaseConv(Data);
+ // degree sign
+ else if ( !_tcsicmp(UpdateData->Unit, _T("DEG")))
+ {
+ if ( !opt.DoNotAppendUnit) _tcscat(Data, opt.DegreeSign);
+ }
+ // percent sign
+ else if ( !_tcsicmp(UpdateData->Unit, _T("%")))
+ {
+ if ( !opt.DoNotAppendUnit) _tcscat(Data, _T("%"));
+ }
+ // truncating strings for day/month to 2 or 3 characters
+ else if ( !_tcsicmp(UpdateData->Unit, _T("DAY")) || !_tcsicmp(UpdateData->Unit, _T("MONTH")))
+ if (opt.dUnit > 1 && _tcslen(Data) > opt.dUnit)
+ Data[opt.dUnit] = '\0';
+ }
+}
+
+//============ GET THE VALUE OF A DATAITEM ============
+
+// get the value of the data using the start, end strings
+// UpdateData = the WIDATAITEM struct containing start, end, unit
+// Data = the string containing weather data obtained from UpdateData
+// global var. used: szInfo = the downloaded string
+
+void GetDataValue(WIDATAITEM *UpdateData, TCHAR *Data, TCHAR** szData)
+{
+ TCHAR last = 0, current, *start, *end;
+ unsigned startloc = 0, endloc = 0, respos = 0;
+ BOOL tag = FALSE, symb = FALSE;
+ TCHAR *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 = _tcsstr(szInfo, UpdateData->Start);
+ if (start != NULL) {
+ // set the starting location for getting data
+ start += _tcslen(UpdateData->Start);
+ szInfo = start;
+ }
+ }
+ // the end string must be found too
+ if (UpdateData->End[0] != 0)
+ end = _tcsstr(szInfo, UpdateData->End);
+ else
+ end = _tcsstr(szInfo, _T(" "));
+
+ if (end != NULL) {
+ // set the ending location
+ startloc = 0;
+ endloc = end - szInfo;
+ end += _tcslen(UpdateData->End);
+ last = '\n';
+ }
+ // ignore if not both of the string found - this prevent crashes
+ if (start != NULL && end != NULL)
+ {
+ // begin reading the data from start location to end location
+ // remove all HTML tag in between, as well as leading space, ending space,
+ // multiple spaces, tabs, and return key
+ while (startloc < endloc)
+ {
+ if (szInfo[startloc] == '<') tag = TRUE;
+ else if (szInfo[startloc] == '&' &&
+ (szInfo[startloc+1] == ';' || szInfo[startloc+2] == ';' || szInfo[startloc+3] == ';' ||
+ szInfo[startloc+4] == ';' || szInfo[startloc+5] == ';' || szInfo[startloc+6] == ';'))
+ symb = TRUE;
+ else if (szInfo[startloc] == '>') tag = FALSE;
+ else if (szInfo[startloc] == ';') symb = FALSE;
+ else {
+ if ( !tag && !symb) {
+ current = szInfo[startloc];
+ if (current == '\n' || current == '\t' || current == ' ' || current == '\r')
+ current = ' ';
+ if (current != ' ' || last != ' ') {
+ if (last != '\n' && (respos != 0 || (respos == 0 && last != ' ')))
+ Data[respos++] = last;
+ last = current;
+ }
+ }
+ }
+ ++startloc;
+ // prevent crashes if the string go over maximun length -> generate an error
+ if (respos >= MAX_DATA_LEN) {
+ if (opt.ShowWarnings && UpdateData->Name[0] != 0 && _tcscmp(UpdateData->Name, _T("Ignore"))) {
+ mir_sntprintf(Data, MAX_DATA_LEN, TranslateT("Error when obtaining data: %s"), UpdateData->Name);
+ WPShowMessage(Data, SM_WARNING);
+ }
+ _tcsncpy(Data, TranslateT("<Error>"), MAX_DATA_LEN);
+ last = ' ';
+ respos = MAX_DATA_LEN - 1;
+ break;
+ }
+ }
+
+ // get the last character
+ if (last != ' ')
+ Data[respos++] = last;
+
+ // null terminate the string
+ Data[respos] = 0;
+
+ // convert the unit
+ ConvertDataValue(UpdateData, Data);
+
+ // remove the string before the data from szInfo
+ szInfo = end;
+ }
+ *szData = szInfo;
+}
+
+//============ ALLOCATE SPACE AND COPY STRING ============
+
+// copy a string into a new memory location
+// Data = the field the data is copied to
+// Value = the original string, the string where data is copied from
+void wSetData(char **Data, const char *Value)
+{
+ if (Value[0] != 0)
+ {
+ char *newData = (char*)mir_alloc(strlen(Value)+3);
+ strcpy(newData, Value);
+ *Data = newData;
+ }
+ else
+ *Data = "";
+}
+
+void wSetData(WCHAR **Data, const char *Value)
+{
+ if (Value[0] != 0)
+ *Data = mir_a2u( Value );
+ else
+ *Data = L"";
+}
+
+void wSetData(WCHAR **Data, const WCHAR *Value)
+{
+ if (Value[0] != 0) {
+ WCHAR *newData = (WCHAR*)mir_alloc( sizeof(WCHAR)*(wcslen(Value)+3));
+ wcscpy(newData, Value);
+ *Data = newData;
+ }
+ else *Data = L"";
+}
+
+// A safer free function that free memory for a string
+// Data = the string occuping the data to be freed
+void wfree(char **Data)
+{
+ if (*Data && strlen(*Data) > 0) mir_free(*Data);
+ *Data = NULL;
+}
+
+void wfree(WCHAR **Data)
+{
+ if (*Data && wcslen(*Data) > 0)
+ mir_free(*Data);
+ *Data = NULL;
+}
+
+//============ MANAGE THE ITEMS STORED IN DB ============
+// get single setting that is found
+// szSetting = the setting name
+// lparam = the counter
+int GetWeatherDataFromDB(const char *szSetting, LPARAM lparam)
+{
+ LIST<char> *pList = (LIST<char>*)lparam;
+ pList->insert( mir_strdup(szSetting));
+ return 0;
+}
+
+// remove or display the weather information for a contact
+// hContact - the contact in which the info is going to be removed
+
+void DBDataManage(HANDLE hContact, WORD Mode, WPARAM wParam, LPARAM lParam)
+{
+ LIST<char> arSettings(10);
+
+ // get all the settings and stored them in a temporary list
+ DBCONTACTENUMSETTINGS dbces;
+ dbces.lParam = (LPARAM)&arSettings;
+ dbces.pfnEnumProc = GetWeatherDataFromDB;
+ dbces.szModule = WEATHERCONDITION;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact, (LPARAM)&dbces);
+
+ // begin deleting settings
+ for (int i=arSettings.getCount()-1; i >= 0; i--) {
+ char *szSetting = arSettings[i];
+
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(hContact, WEATHERCONDITION, szSetting, &dbv)) {
+ switch (Mode) {
+ case WDBM_REMOVE:
+ db_unset(hContact, WEATHERCONDITION, szSetting);
+ break;
+
+ case WDBM_DETAILDISPLAY:
+ // skip the "WeatherInfo" variable
+ if ( !strcmp(szSetting, "WeatherInfo") || !strcmp(szSetting, "Ignore") || szSetting[0] == '#')
+ continue;
+ else {
+ HWND hList = GetDlgItem((HWND)wParam, IDC_DATALIST);
+ LV_ITEM lvi = { 0 };
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.lParam = i;
+ lvi.pszText = TranslateTS( _A2T(szSetting ));
+ lvi.iItem = ListView_InsertItem(hList, &lvi);
+ lvi.pszText = dbv.ptszVal;
+ ListView_SetItemText(hList, lvi.iItem, 1, dbv.ptszVal );
+ break;
+ }
+ }
+ db_free(&dbv);
+ }
+ mir_free(szSetting);
+ }
+ arSettings.destroy();
+}
diff --git a/plugins/Weather/src/weather_http.cpp b/plugins/Weather/src/weather_http.cpp
new file mode 100644
index 0000000000..d9038db9c8
--- /dev/null
+++ b/plugins/Weather/src/weather_http.cpp
@@ -0,0 +1,206 @@
+/*
+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 "weather.h"
+
+HANDLE hNetlibUser, hNetlibHttp;
+
+int findHeader(NETLIBHTTPREQUEST *nlhrReply, char *hdr)
+{
+ int res = -1, i;
+ for (i=0; i<nlhrReply->headersCount; i++)
+ {
+ if (_stricmp(nlhrReply->headers[i].szName, hdr) == 0)
+ {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+//============ DOWNLOAD NEW WEATHER ============
+
+// function to download webpage from the internet
+// szUrl = URL of the webpage to be retrieved
+// return value = 0 for success, 1 or HTTP error code for failure
+// global var used: szData, szInfo = containing the retrieved data
+int InternetDownloadFile (char *szUrl, char* cookie, TCHAR** szData)
+{
+ int result = 0xBADBAD;
+ char* szRedirUrl = NULL;
+ NETLIBHTTPREQUEST nlhr = {0};
+ NETLIBHTTPHEADER headers[6];
+
+ // initialize the netlib request
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_PERSISTENT | NLHRF_REDIRECT;
+ nlhr.szUrl = szUrl;
+ nlhr.nlc = hNetlibHttp;
+
+ // change the header so the plugin is pretended to be IE 6 + WinXP
+ nlhr.headersCount = 5;
+ nlhr.headers = headers;
+ nlhr.headers[0].szName = "User-Agent";
+ nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
+ nlhr.headers[1].szName = "Cache-Control";
+ nlhr.headers[1].szValue = "no-cache";
+ nlhr.headers[2].szName = "Pragma";
+ nlhr.headers[2].szValue = "no-cache";
+ nlhr.headers[3].szName = "Connection";
+ nlhr.headers[3].szValue = "close";
+ nlhr.headers[4].szName = "Cookie";
+ nlhr.headers[4].szValue = cookie;
+// nlhr.headers[5].szName = "If-Modified-Since";
+// nlhr.headers[5].szValue = "Tue, 24 Feb 2009 03:44:23 GMT";
+
+ if (cookie == NULL || cookie[0] == 0) --nlhr.headersCount;
+
+ while (result == 0xBADBAD) {
+ // download the page
+ NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION,
+ (WPARAM)hNetlibUser, (LPARAM)&nlhr);
+
+ if (nlhrReply) {
+ // if the recieved code is 200 OK
+ if (nlhrReply->resultCode == 200) {
+ if (nlhrReply->dataLength) {
+ result = 0;
+ bool bIsUtf = false;
+
+ // allocate memory and save the retrieved data
+ int i = findHeader(nlhrReply, "Content-Type");
+ if (i != -1 && strstr(_strlwr((char*)nlhrReply->headers[i].szValue), "utf-8"))
+ bIsUtf = true;
+ else {
+ char* end = nlhrReply->pData;
+ for (;;) {
+ char* beg = strstr(end, "<meta");
+ if (beg == NULL) break;
+ else {
+ char* method, tmp;
+ end = strchr(beg, '>');
+ tmp = *end; *end = 0;
+
+ method = strstr(beg, "http-equiv=\"");
+ if (method && _strnicmp(method+12, "Content-Type", 12) == 0 && strstr(method, "utf-8")) {
+ bIsUtf = true;
+ break;
+ }
+ else *end = tmp;
+ } } }
+
+ if ( bIsUtf )
+ *szData = mir_utf8decodeT( nlhrReply->pData );
+ else
+ *szData = mir_a2t( nlhrReply->pData );
+
+ }
+ else result = DATA_EMPTY;
+ }
+ // if the recieved code is 302 Moved, Found, etc
+ // workaround for url forwarding
+ else if (nlhrReply->resultCode == 302 || nlhrReply->resultCode == 301 || nlhrReply->resultCode == 303 ) // page moved
+ {
+ // get the url for the new location and save it to szInfo
+ // look for the reply header "Location"
+ int i = findHeader(nlhrReply, "Location");
+
+ if (i != -1)
+ {
+ size_t rlen = 0;
+ if (nlhrReply->headers[i].szValue[0] == '/')
+ {
+ char* szPath;
+ char* szPref = strstr(szUrl, "://");
+ szPref = szPref ? szPref + 3 : szUrl;
+ szPath = strchr(szPref, '/');
+ rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl);
+ }
+
+ szRedirUrl = (char*)mir_realloc(szRedirUrl,
+ rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1);
+
+ strncpy(szRedirUrl, szUrl, rlen);
+ strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue);
+
+ GetSearchStr(szRedirUrl);
+
+ nlhr.szUrl = szRedirUrl;
+ }
+ }
+ // return error code if the recieved code is neither 200 OK nor 302 Moved
+ else {
+ *szData = ( TCHAR* )mir_alloc(512);
+ // store the error code in szData
+ wsprintf(*szData, _T("Error occured! HTTP Error: %i\n"), nlhrReply->resultCode);
+ result = (int)nlhrReply->resultCode;
+ }
+
+ hNetlibHttp = nlhrReply->nlc;
+ // make a copy of the retrieved data, then free the memory of the http reply
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0, (LPARAM)nlhrReply);
+ }
+ // if the data does not downloaded successfully (ie. disconnected), then return 1000 as error code
+ else
+ {
+ *szData = ( TCHAR* )mir_alloc(512);
+ // store the error code in szData
+ _tcscpy(*szData, _T("NetLib error occurred!!"));
+ result = NETLIB_ERROR;
+ hNetlibHttp = NULL;
+ }
+
+ }
+
+ mir_free(szRedirUrl);
+
+ return result;
+}
+
+//============ NETLIB INITIALIZATION ============
+
+// initialize netlib support for weather protocol
+void NetlibInit(void)
+{
+ NETLIBUSER nlu = {0};
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION|NUF_TCHAR;
+ nlu.szSettingsModule = WEATHERPROTONAME;
+ nlu.ptszDescriptiveName = TranslateT("Weather HTTP connections");
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER,0, (LPARAM)&nlu);
+}
+
+void NetlibHttpDisconnect(void)
+{
+ if (hNetlibHttp)
+ {
+ HANDLE hConn = hNetlibHttp;
+ hNetlibHttp = NULL;
+ Netlib_CloseHandle(hConn);
+ }
+}
+
diff --git a/plugins/Weather/src/weather_icons.cpp b/plugins/Weather/src/weather_icons.cpp
new file mode 100644
index 0000000000..321d758ca2
--- /dev/null
+++ b/plugins/Weather/src/weather_icons.cpp
@@ -0,0 +1,87 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG Team
+Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "weather.h"
+
+HANDLE hIcoLibIconsChanged = NULL;
+
+struct _tag_iconList
+{
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+ HANDLE hIconLibItem;
+}
+static iconList[] =
+{
+ { LPGENT("Protocol icon"), "main", IDI_ICON },
+ { LPGENT("Update Disabled"), "disabled", IDI_DISABLED },
+ { LPGENT("View Log"), "log", IDI_LOG },
+ { LPGENT("Update with Clear"), "update2", IDI_UPDATE2 },
+ { LPGENT("View Brief"), "brief", IDI_S },
+ { LPGENT("View Complete"), "read", IDI_READ },
+ { LPGENT("Weather Update"), "update", IDI_UPDATE },
+ { LPGENT("Weather Map"), "map", IDI_MAP },
+ { LPGENT("Popup"), "popup", IDI_POPUP },
+ { LPGENT("No Popup"), "nopopup", IDI_NOPOPUP },
+ { LPGENT("Edit Settings"), "edit", IDI_EDIT },
+};
+
+void InitIcons(void)
+{
+ char szSettingName[100];
+ TCHAR szFile[MAX_PATH];
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.ptszDefaultFile = szFile;
+ sid.pszName = szSettingName;
+ sid.ptszSection = _T(WEATHERPROTONAME);
+ sid.flags = SIDF_ALL_TCHAR;
+
+ for (int i = 0; i < SIZEOF(iconList); i++) {
+ mir_snprintf(szSettingName, SIZEOF( szSettingName ), "%s_%s", WEATHERPROTONAME, iconList[i].szName);
+
+ sid.ptszDescription = iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIconLibItem = Skin_AddIcon(&sid);
+} }
+
+HICON LoadIconEx(const char* name, BOOL big)
+{
+ char szSettingName[100];
+ mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", WEATHERPROTONAME, name);
+ return Skin_GetIcon(szSettingName, big);
+}
+
+HANDLE GetIconHandle(const char* name)
+{
+ unsigned i;
+ for (i=0; i < SIZEOF(iconList); i++)
+ if (strcmp(iconList[i].szName, name) == 0)
+ return iconList[i].hIconLibItem;
+ return NULL;
+}
+
+void ReleaseIconEx(HICON hIcon)
+{
+ Skin_ReleaseIcon(hIcon);
+}
diff --git a/plugins/Weather/src/weather_info.cpp b/plugins/Weather/src/weather_info.cpp
new file mode 100644
index 0000000000..f02fc79a28
--- /dev/null
+++ b/plugins/Weather/src/weather_info.cpp
@@ -0,0 +1,252 @@
+/*
+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 "weather.h"
+
+//============ INI INFORMATION ============
+
+// List INI Information for all loaded INI files
+void INIInfo(HWND hwndDlg)
+{
+ TCHAR str[16];
+ size_t memused = 0;
+ LVITEM lvi = {0};
+ WIDATALIST *Item = WIHead;
+
+ HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST);
+
+ ListView_DeleteAllItems(hIniList);
+
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = 0;
+ while (Item != NULL)
+ {
+ // get the data for the ini file
+ lvi.iSubItem = 0;
+ lvi.pszText = Item->Data.InternalName;
+ ListView_InsertItem(hIniList, &lvi);
+ lvi.iSubItem = 1;
+ lvi.pszText = Item->Data.Author;
+ ListView_SetItem(hIniList, &lvi);
+ lvi.iSubItem = 2;
+ lvi.pszText = Item->Data.Version;
+ ListView_SetItem(hIniList, &lvi);
+ lvi.iSubItem = 3;
+ switch (Item->Data.InternalVer)
+ {
+ case 1: lvi.pszText = _T("1.0"); break;
+ case 2: lvi.pszText = _T("1.1"); break;
+ case 3: lvi.pszText = _T("1.1a"); break;
+ case 4: lvi.pszText = _T("1.2"); break;
+ case 5: lvi.pszText = _T("1.3"); break;
+ case 6: lvi.pszText = _T("1.4"); break;
+ default: lvi.pszText = _T(""); break;
+ }
+ ListView_SetItem(hIniList, &lvi);
+ lvi.iSubItem = 4;
+ lvi.pszText = _ltot(Item->Data.UpdateDataCount, str, 10);
+ ListView_SetItem(hIniList, &lvi);
+ lvi.iSubItem = 5;
+ lvi.pszText = Item->Data.DisplayName;
+ ListView_SetItem(hIniList, &lvi);
+ lvi.iSubItem = 6;
+ lvi.pszText = Item->Data.ShortFileName;
+ ListView_SetItem(hIniList, &lvi);
+
+ memused += Item->Data.MemUsed;
+
+ Item = Item->next;
+ ++lvi.iItem;
+ }
+ SetDlgItemText(hwndDlg, IDC_INICOUNT, _itot(lvi.iItem, str, 10));
+ SetDlgItemText(hwndDlg, IDC_MEMUSED, _ltot((long)memused, str, 10));
+}
+
+static const struct tag_Columns
+{
+ const TCHAR *name;
+ unsigned size;
+}
+columns[] =
+{
+ { _T("Name"), 70 },
+ { _T("Author"), 100 },
+ { _T("File Version"), 70 },
+ { _T("INI Version"), 70 },
+ { _T("Items"), 40 },
+ { _T("Display Name"), 200 },
+ { _T("File Name"), 150 },
+};
+
+
+INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ HWND hIniList = GetDlgItem(hwndDlg, IDC_INFOLIST);
+ LVCOLUMN lvc = {0};
+
+ lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ for ( int i=0; i<7; ++i) {
+ lvc.iSubItem = i;
+ lvc.pszText = TranslateTS(columns[i].name);
+ lvc.cx = columns[i].size;
+ ListView_InsertColumn(hIniList, i, &lvc);
+ }
+ INIInfo(hwndDlg);
+ }
+
+ break;
+
+ case WM_DESTROY:
+ break;
+
+ case WM_COMMAND:
+ if ( HIWORD(wParam) == BN_CLICKED &&
+ LOWORD(wParam) == IDC_RELOADINI )
+ {
+ DestroyWIList();
+ LoadWIData(TRUE);
+ INIInfo(hwndDlg);
+ }
+ break;
+ }
+ return 0;
+}
+
+
+// get the info of individual ini file
+// pszSvc = the internal name of the service to get the data
+void GetINIInfo(TCHAR *pszSvc)
+{
+ TCHAR str2[2048];
+ WIDATA *sData = GetWIData(pszSvc);
+ // if the service does not exist among the loaded INI's
+ if (sData == NULL)
+ {
+ wsprintf(str2, TranslateT("The corresponding INI file for \"%s\" is not found."), pszSvc);
+ MessageBox(NULL, str2, TranslateT("Weather INI information"), MB_OK|MB_ICONINFORMATION);
+ }
+ // if exist, get the information
+ else
+ {
+ wsprintf(str2, TranslateT("Weather INI information for \"%s\":"), pszSvc);
+ _tcscat(str2,_T("\n\n"));
+ _tcscat(str2, TranslateT("Name:"));
+ _tcscat(str2,_T("\t\t"));
+ _tcscat(str2, sData->DisplayName);
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, TranslateT("Internal Name:"));
+ _tcscat(str2,_T("\t"));
+ _tcscat(str2, sData->InternalName);
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, TranslateT("Author:"));
+ _tcscat(str2,_T("\t\t"));
+ _tcscat(str2, sData->Author);
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, TranslateT("Version:"));
+ _tcscat(str2,_T("\t\t"));
+ _tcscat(str2, sData->Version);
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, TranslateT("INI Version:"));
+ _tcscat(str2,_T("\t"));
+ switch (sData->InternalVer) {
+ case 1: _tcscat(str2,_T("1.0")); break;
+ case 2: _tcscat(str2,_T("1.1")); break;
+ case 3: _tcscat(str2,_T("1.1a")); break;
+ case 4: _tcscat(str2,_T("1.2")); break;
+ case 5: _tcscat(str2,_T("1.3")); break;
+ case 6: _tcscat(str2,_T("1.4")); break;
+ }
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, TranslateT("File Name:"));
+ _tcscat(str2,_T("\t"));
+ _tcscat(str2, sData->ShortFileName);
+ _tcscat(str2, _T("\n"));
+ _tcscat(str2, TranslateT("Item Count:"));
+ wsprintf(str2, _T("%s\t%i\n"), str2, sData->UpdateDataCount);
+ _tcscat(str2, TranslateT("Memory Used:"));
+ wsprintf(str2, _T("%s\t%i "), str2, sData->MemUsed);
+ _tcscat(str2, TranslateT("bytes"));
+ _tcscat(str2,_T("\n\n"));
+ _tcscat(str2, TranslateT("Description:"));
+ _tcscat(str2,_T("\n"));
+ _tcscat(str2, sData->Description);
+
+ // display the message box and quit
+ MessageBox(NULL, str2, 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)
+{
+ TCHAR str[10240], tempstr[1024];
+
+ WIDATALIST *Item = WIHead;
+ // heading
+ _tcscpy(str, TranslateT("Here is a list of custom variables that are currently available"));
+ _tcscat(str, _T("\n\n"));
+ // loop through all weather services to find custom variables
+ while (Item != NULL)
+ {
+ WIDATAITEMLIST* WItem;
+ WItem = Item->Data.UpdateData;
+ // loop through all update items in a service
+ while (WItem != NULL)
+ {
+ // the custom variable is defined as "%[<variable name>]"
+ // ignore the "hi" item and hidden items
+ if ( _tcscmp(WItem->Item.Name, _T("Ignore")) && WItem->Item.Name[0] != '#') {
+ wsprintf(tempstr, _T("%c[%s]"), '%', WItem->Item.Name);
+ TCHAR* find = _tcsstr(str, tempstr);
+ // if the custom variable does not exist in the list, add it to the list
+ if (find == NULL) {
+ _tcscat(str, tempstr);
+ _tcscat(str, _T(", "));
+ }
+ }
+ WItem = WItem->Next;
+ }
+ Item = Item->next;
+ }
+ // remove the last comma in the list
+ TCHAR* find = _tcsrchr(str, ',');
+ if (find != NULL)
+ *find = '\0';
+
+ // display the list in a message box
+ MessageBox(NULL, str, TranslateT("More Variables"), MB_OK|MB_ICONINFORMATION|MB_TOPMOST);
+}
+
diff --git a/plugins/Weather/src/weather_ini.cpp b/plugins/Weather/src/weather_ini.cpp
new file mode 100644
index 0000000000..69f9ba40bb
--- /dev/null
+++ b/plugins/Weather/src/weather_ini.cpp
@@ -0,0 +1,613 @@
+/*
+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 "weather.h"
+
+HWND hWndSetup;
+
+//============ DATA LIST (LINKED LIST) ============
+
+// add an item into weather service data list
+// Data = the service data to be added to the list
+void WIListAdd(WIDATA Data)
+{
+ WIDATALIST *newItem;
+
+ // create a new datalist item and point to the data
+ newItem = (WIDATALIST*)mir_alloc(sizeof(WIDATALIST));
+ newItem->Data = Data;
+ // add to the linked list
+ newItem->next = NULL;
+ if (WITail == NULL) WIHead = newItem;
+ else WITail->next = newItem;
+ WITail = newItem;
+}
+
+// get the service data (from loaded ini file) by internal name
+// pszServ = internal name for the service
+// return value = the matching WIDATA struct for pszServ, NULL if no match found
+WIDATA* GetWIData(TCHAR *pszServ)
+{
+ WIDATALIST *Item = WIHead;
+
+ // loop through the list to find matching internal name
+ while (Item != NULL) {
+ // if internal name found, return the data
+ if ( _tcscmp(Item->Data.InternalName, pszServ) == 0)
+ return &Item->Data;
+ Item = Item->next;
+ }
+ // return NULL when no match found
+ return NULL;
+}
+
+// remove all service data from memory
+void DestroyWIList(void)
+{
+ // free the list one by one
+ while (WIHead != NULL)
+ {
+ WIDATALIST *wi = WIHead;
+ WIHead = wi->next;
+ FreeWIData(&wi->Data); // free the data struct
+ mir_free(wi);
+ }
+
+ // make sure the entire list is clear
+ WITail = NULL;
+}
+
+//============ DATA ITEM LIST (LINKED LIST) ============
+
+// add a new update item into the current list
+void WIItemListAdd(WIDATAITEM *DataItem, WIDATA *Data)
+{
+ WIDATAITEMLIST *newItem;
+
+ newItem = (WIDATAITEMLIST*)mir_alloc(sizeof(WIDATAITEMLIST));
+ newItem->Item = *DataItem;
+ newItem->Next = NULL;
+ if (Data->UpdateData == NULL) Data->UpdateData = newItem;
+ else Data->UpdateDataTail->Next = newItem;
+ Data->UpdateDataTail = newItem;
+}
+
+// reset the data item by using empty string
+// Item = the item to set
+// name = the string to store in the "name" field
+void ResetDataItem(WIDATAITEM *Item, const TCHAR *name)
+{
+ TCHAR str[] = _T("ID Search - Station Name");
+ Item->Name = ( TCHAR* )mir_alloc( sizeof(str));
+ _tcscpy(Item->Name, str);
+ Item->Start = _T("");
+ Item->End = _T("");
+ Item->Unit = _T("");
+ Item->Url = "";
+ Item->Break = _T("");
+ Item->Type = 0;
+}
+
+// free the data item by using empty string
+// Item = the item to free
+void FreeDataItem(WIDATAITEM *Item)
+{
+ wfree(&Item->Name);
+ wfree(&Item->Start);
+ wfree(&Item->End);
+ wfree(&Item->Unit);
+ wfree(&Item->Url);
+ wfree(&Item->Break);
+}
+
+//============ Condition Icon List ============
+
+// initiate icon assignmet list
+void WICondListInit(WICONDLIST *List)
+{
+ List->Tail = NULL;
+ List->Head = NULL;
+}
+
+// add a new update item into the current list
+void WICondListAdd(char *str, WICONDLIST *List)
+{
+ WICONDITEM *newItem = (WICONDITEM*)mir_alloc(sizeof(WICONDITEM));
+ wSetData(&newItem->Item, str);
+ CharLowerBuff(newItem->Item, (DWORD)_tcslen( newItem->Item ));
+ newItem->Next = NULL;
+ if (List->Tail == NULL) List->Head = newItem;
+ else List->Tail->Next = newItem;
+ List->Tail = newItem;
+}
+
+// check if the condition string matched for the assignment
+BOOL IsContainedInCondList(const TCHAR *pszStr, WICONDLIST *List)
+{
+ WICONDITEM *Item = List->Head;
+
+ // loop through the list to find matching internal name
+ while (Item != NULL) {
+ // if internal name found, return true indicating that the data is found
+ if ( _tcsstr(pszStr, Item->Item))
+ return TRUE;
+ Item = Item->Next;
+ }
+ // return false when no match found
+ return FALSE;
+}
+
+// free the memory for icon assignment list
+void DestroyCondList(WICONDLIST *List)
+{
+ WICONDITEM *temp;
+
+ temp = List->Head;
+
+ // free the list one by one
+ while (temp != NULL)
+ {
+ List->Head = temp->Next;
+ wfree(&temp->Item); // free the data struct
+ mir_free(temp);
+ temp = List->Head;
+ }
+ // make sure the entire list is clear
+ List->Tail = NULL;
+}
+
+
+//============ LOADING INI FILES ============
+
+// load the weather update data form INI files
+BOOL LoadWIData(BOOL dial)
+{
+ HANDLE hFind;
+ TCHAR szSearchPath[MAX_PATH], FileName[MAX_PATH], *chop;
+ WIN32_FIND_DATA fd;
+ WIDATA Data;
+
+ // make sure that the current service data list is empty
+ WITail = NULL;
+ WIHead = WITail;
+
+ // find all *.ini file in the plugin\weather directory
+ GetModuleFileName(GetModuleHandle(NULL), szSearchPath, SIZEOF(szSearchPath));
+ chop = _tcsrchr(szSearchPath, '\\');
+ *chop = '\0';
+ _tcscat(szSearchPath, _T("\\Plugins\\Weather\\*.ini"));
+ _tcscpy(FileName, szSearchPath);
+
+ hFind = FindFirstFile(szSearchPath, &fd);
+
+ // load the content of the ini file into memory
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ chop = _tcsrchr(FileName, '\\');
+ chop[1] = '\0';
+ _tcscat(FileName, fd.cFileName);
+ if ( _tcsicmp(fd.cFileName, _T("SAMPLE_INI.INI"))) {
+ LoadStationData(FileName, fd.cFileName, &Data);
+ if (Data.Enabled) WIListAdd(Data);
+ }
+ // look through the entire "plugins\weather" directory
+ }
+ while(FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+
+ if (WIHead == NULL) {
+ // no ini found, display an error message box.
+ if (dial)
+ hWndSetup = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SETUP), NULL, DlgProcSetup);
+ else
+ MessageBox(NULL,
+ TranslateT("No update data file is found. Please check your Plugins\\Weather directory."),
+ TranslateT("Weather Protocol"), MB_OK | MB_ICONERROR);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// load the station data from a file
+// pszFile = the file name + path for the ini file to be loaded
+// pszShortFile = the file name of the ini file, but not including the path
+// Data = the struct to load the ini content to, and return to previous function
+void LoadStationData(TCHAR *pszFile, TCHAR *pszShortFile, WIDATA *Data)
+{
+ WIDATAITEM DataItem;
+ FILE *pfile;
+ int i;
+ char *Group, *Temp;
+ char *ValName, *Value;
+
+ static const char *statusStr[10] =
+ {
+ "LIGHTNING",
+ "FOG",
+ "SNOW SHOWER",
+ "SNOW",
+ "RAIN SHOWER",
+ "RAIN",
+ "PARTLY CLOUDY",
+ "CLOUDY",
+ "SUNNY",
+ "N/A"
+ };
+
+ // clean up old stuff
+ ZeroMemory(Data, sizeof(Data));
+ Data->Enabled = FALSE;
+
+ // open the ini file
+ pfile = _tfsopen(pszFile, _T("rt"), _SH_DENYWR);
+ if (pfile != NULL) {
+ char Line[4096];
+ fgets(Line, SIZEOF(Line), pfile);
+ TrimString(Line);
+
+ // make sure it is a valid weather protocol ini file
+ if ( !strcmp(Line, "[Weather 0.3.x Update Data]"))
+ Data->InternalVer = 1;
+ else if ( !strcmp(Line, "[Weather 0.3.x Update Data 1.1]"))
+ Data->InternalVer = 2;
+ else if ( !strcmp(Line, "[Weather 0.3.x Update Data 1.1a]"))
+ Data->InternalVer = 3;
+ else if ( !strcmp(Line, "[Weather 0.3.x Update Data 1.2]"))
+ Data->InternalVer = 4;
+ else if ( !strcmp(Line, "[Weather 0.3.x Update Data 1.3]"))
+ Data->InternalVer = 5;
+ else if ( !strcmp(Line, "[Weather 0.3.x Update Data 1.4]"))
+ Data->InternalVer = 6;
+ else
+ {
+ wsprintfA(Line, Translate("Invalid ini format for: %s"), pszFile);
+ MessageBoxA(NULL, Line, Translate("Weather Protocol"), MB_OK|MB_ICONERROR);
+ fclose(pfile);
+ return;
+ }
+
+ // initialize all data fields
+ Group = "";
+
+ Data->DisplayName = _T("");
+ Data->InternalName = _T("");
+ Data->Description = _T("");
+ Data->Author = _T("");
+ Data->Version = _T("");
+ Data->DefaultURL = "";
+ Data->DefaultMap = _T("");
+ Data->UpdateURL = "";
+ Data->UpdateURL2 = "";
+ Data->UpdateURL3 = "";
+ Data->UpdateURL4 = "";
+ Data->Cookie = "";
+ Data->IDSearch.SearchURL = "";
+ Data->IDSearch.NotFoundStr = _T("");
+ Data->NameSearch.SearchURL = "";
+ Data->NameSearch.NotFoundStr = _T("");
+ Data->NameSearch.SingleStr = _T("");
+ Data->NameSearch.Single.First = _T("");
+ Data->NameSearch.Multiple.First = _T("");
+ 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, _T("ID Search - Station Name"));
+ ResetDataItem(&Data->NameSearch.Single.Name, _T("Name Search Single Result - Station Name"));
+ ResetDataItem(&Data->NameSearch.Single.ID, _T("Name Search Single Result - Station ID"));
+ ResetDataItem(&Data->NameSearch.Multiple.Name, _T("Name Search Multiple Result - Station Name"));
+ ResetDataItem(&Data->NameSearch.Multiple.ID, _T("Name Search Multiple Result - Station ID"));
+
+ DataItem.Name = _T("");
+ DataItem.Start = _T("");
+ DataItem.End = _T("");
+ DataItem.Unit = _T("");
+ DataItem.Url = "";
+ DataItem.Break = _T("");
+ DataItem.Type = 0;
+
+ Temp = "";
+
+ // initialize the linked list for update items
+ Data->UpdateDataCount = 0;
+ Data->MemUsed = sizeof(WIDATA) + sizeof(WIDATALIST) + (_tcslen(pszShortFile) + _tcslen(pszFile) + 20)*sizeof( TCHAR );
+ Data->UpdateData = NULL;
+ Data->UpdateDataTail = NULL;
+
+ // initialize the icon assignment list
+ for (i=0; i<10; i++)
+ WICondListInit( &Data->CondList[i] );
+
+ while (!feof(pfile)) {
+ // determine current tag
+
+ if (fgets(Line, SIZEOF(Line), pfile) == NULL)
+ break;
+ TrimString(Line);
+
+ // if the line is a group header/footer
+ if (Line[0] == '[') {
+ char *chop = strchr(Line+1,']');
+ if (chop == NULL)
+ continue;
+
+ if (Line[1] != '/') { // if it is not a footer (for old ini)
+ // save the group name
+ Temp = (char *)mir_alloc(strlen(Line)+10);
+ strncpy(Temp, Line+1, chop-Line-1);
+ Temp[chop-Line-1] = 0;
+ wfree(&Group);
+ wSetData(&Group, Temp);
+ // see if it is a update item, if it is, add a new item to the linked list
+ // if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") &&
+ // strcmpi(Group, "NAME SEARCH"))
+ // wSetData(&DataItem.Name, Group);
+ if (_stricmp(Group, "HEADER") && _stricmp(Group, "DEFAULT") && _stricmp(Group, "ID SEARCH") &&
+ _stricmp(Group, "NAME SEARCH") && _stricmp(Group, "ICONS"))
+ {
+ wSetData(&DataItem.Name, Temp);
+ DataItem.Type = WID_NORMAL;
+ WIItemListAdd(&DataItem, Data);
+ Data->UpdateDataCount++;
+ }
+ mir_free(Temp);
+ }
+ else
+ {
+ wfree(&Group);
+ wSetData(&Group, "");
+ }
+ }
+ // ignore comments and all lines without an '='
+ Value = strstr(Line, "=");
+ if (Value == NULL) continue;
+
+ // get the string before '=' (ValName) and after '=' (Value)
+ ValName = (char *)mir_alloc(strlen(Line)+1);
+ strncpy(ValName, Line, Value-Line);
+ ValName[Value-Line] = 0;
+ Value++;
+ ConvertBackslashes(Value);
+ // store the value for each string
+ if ( !_stricmp(Group, "HEADER")) {
+ if ( !_stricmp(ValName, "NAME")) wSetData(&Data->DisplayName, Value);
+ else if ( !_stricmp(ValName, "INTERNAL NAME")) wSetData(&Data->InternalName, Value);
+ else if ( !_stricmp(ValName, "DESCRIPTION")) wSetData(&Data->Description, Value);
+ else if ( !_stricmp(ValName, "AUTHOR")) wSetData(&Data->Author, Value);
+ else if ( !_stricmp(ValName, "VERSION")) wSetData(&Data->Version, Value);
+ }
+ else if ( !_stricmp(Group, "DEFAULT")) {
+ if ( !_stricmp(ValName, "DEFAULT URL")) wSetData(&Data->DefaultURL, Value);
+ else if ( !_stricmp(ValName, "DEFAULT MAP")) wSetData(&Data->DefaultMap, Value);
+ else if ( !_stricmp(ValName, "UPDATE URL")) wSetData(&Data->UpdateURL, Value);
+ else if ( !_stricmp(ValName, "UPDATE URL2")) wSetData(&Data->UpdateURL2, Value);
+ else if ( !_stricmp(ValName, "UPDATE URL3")) wSetData(&Data->UpdateURL3, Value);
+ else if ( !_stricmp(ValName, "UPDATE URL4")) wSetData(&Data->UpdateURL4, Value);
+ else if ( !_stricmp(ValName, "COOKIE")) wSetData(&Data->Cookie, Value);
+ }
+ else if ( !_stricmp(Group, "ID SEARCH")) {
+ if ( !_stricmp(ValName, "AVAILABLE")) {
+ if ( !_stricmp(Value, "TRUE")) Data->IDSearch.Available = TRUE;
+ else Data->IDSearch.Available = FALSE;
+ }
+ else if ( !_stricmp(ValName, "SEARCH URL")) wSetData(&Data->IDSearch.SearchURL, Value);
+ else if ( !_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->IDSearch.NotFoundStr, Value);
+ else if ( !_stricmp(ValName, "NAME START")) wSetData(&Data->IDSearch.Name.Start, Value);
+ else if ( !_stricmp(ValName, "NAME END")) wSetData(&Data->IDSearch.Name.End, Value);
+ }
+ else if ( !_stricmp(Group, "NAME SEARCH")) {
+ if ( !_stricmp(ValName, "SINGLE RESULT")) {
+ if ( !_stricmp(Value, "TRUE")) Data->NameSearch.Single.Available = TRUE;
+ else Data->NameSearch.Single.Available = FALSE;
+ }
+ else if ( !_stricmp(ValName, "MULTIPLE RESULT")) {
+ if ( !_stricmp(Value, "TRUE")) Data->NameSearch.Multiple.Available = TRUE;
+ else Data->NameSearch.Multiple.Available = FALSE;
+ }
+ else if ( !_stricmp(ValName, "SEARCH URL")) wSetData(&Data->NameSearch.SearchURL, Value);
+ else if ( !_stricmp(ValName, "NOT FOUND STR")) wSetData(&Data->NameSearch.NotFoundStr, Value);
+ else if ( !_stricmp(ValName, "SINGLE RESULT STR")) wSetData(&Data->NameSearch.SingleStr, Value);
+ else if ( !_stricmp(ValName, "SINGLE FIRST")) wSetData(&Data->NameSearch.Single.First, Value);
+ else if ( !_stricmp(ValName, "SINGLE NAME START"))wSetData(&Data->NameSearch.Single.Name.Start, Value);
+ else if ( !_stricmp(ValName, "SINGLE NAME END")) wSetData(&Data->NameSearch.Single.Name.End, Value);
+ else if ( !_stricmp(ValName, "SINGLE ID START")) wSetData(&Data->NameSearch.Single.ID.Start, Value);
+ else if ( !_stricmp(ValName, "SINGLE ID END")) wSetData(&Data->NameSearch.Single.ID.End, Value);
+ else if ( !_stricmp(ValName, "MULT FIRST")) wSetData(&Data->NameSearch.Multiple.First, Value);
+ else if ( !_stricmp(ValName, "MULT NAME START")) wSetData(&Data->NameSearch.Multiple.Name.Start, Value);
+ else if ( !_stricmp(ValName, "MULT NAME END")) wSetData(&Data->NameSearch.Multiple.Name.End, Value);
+ else if ( !_stricmp(ValName, "MULT ID START")) wSetData(&Data->NameSearch.Multiple.ID.Start, Value);
+ else if ( !_stricmp(ValName, "MULT ID END")) wSetData(&Data->NameSearch.Multiple.ID.End, Value);
+ }
+ else if ( !_stricmp(Group, "ICONS")) {
+ for (i=0; i<10; i++) {
+ if ( !_stricmp(ValName, statusStr[i])) {
+ WICondListAdd(Value, &Data->CondList[i]);
+ break;
+ }
+ }
+ }
+ else if (Data->UpdateDataCount != 0) {
+ if ( !_stricmp(ValName, "START")) wSetData(&Data->UpdateDataTail->Item.Start, Value);
+ else if ( !_stricmp(ValName, "SOURCE")) wSetData(&Data->UpdateDataTail->Item.Start, Value);
+ else if ( !_stricmp(ValName, "END")) wSetData(&Data->UpdateDataTail->Item.End, Value);
+ else if ( !_stricmp(ValName, "UNIT")) wSetData(&Data->UpdateDataTail->Item.Unit, Value);
+ else if ( !_stricmp(ValName, "URL")) wSetData(&Data->UpdateDataTail->Item.Url, Value);
+ else if ( !_stricmp(ValName, "HIDDEN")) {
+ if ( !_stricmp(Value, "TRUE")) {
+ TCHAR *nm = Data->UpdateDataTail->Item.Name;
+ size_t len = _tcslen(nm) + 1;
+
+ Data->UpdateDataTail->Item.Name = nm = ( TCHAR* )mir_realloc(nm, sizeof(TCHAR)*(len + 3));
+ memmove(nm + 1, nm, len*sizeof( TCHAR ));
+ *nm = '#';
+ }
+ }
+ else if ( !_stricmp(ValName, "SET DATA")) {
+ Data->UpdateDataTail->Item.Type = WID_SET;
+ wSetData(&Data->UpdateDataTail->Item.End, Value);
+ }
+ else if ( !_stricmp(ValName, "BREAK DATA")) {
+ Data->UpdateDataTail->Item.Type = WID_BREAK;
+ wSetData(&Data->UpdateDataTail->Item.Break, Value);
+ }
+ }
+ // recalculate memory used
+ Data->MemUsed += (strlen(Value) + 10);
+ wfree(&ValName);
+ }
+ // calcualate memory used for the ini and close the file
+ Data->MemUsed += sizeof(WIDATAITEMLIST)*Data->UpdateDataCount;
+ Data->Enabled = TRUE; // enable the service
+ fclose(pfile);
+ wfree(&Group);
+ }
+}
+
+//============ FREE WIDATA ITEM FROM MEMORY ============
+
+// free the WIDATA struct from memory
+// Data = the struct to be freed
+void FreeWIData(WIDATA *Data)
+{
+ WIDATAITEMLIST* WItem;
+ int i;
+
+ // free update items linked list first
+ WItem = Data->UpdateData;
+ while (WItem != NULL)
+ {
+ Data->UpdateData = WItem->Next;
+ FreeDataItem(&WItem->Item);
+ mir_free(WItem);
+ WItem = Data->UpdateData;
+ }
+
+ // free the strings in the rest of the struct
+ wfree(&Data->DisplayName);
+ wfree(&Data->InternalName);
+ wfree(&Data->Description);
+ wfree(&Data->Author);
+ wfree(&Data->Version);
+ wfree(&Data->DefaultURL);
+ wfree(&Data->DefaultMap);
+ wfree(&Data->UpdateURL);
+ wfree(&Data->UpdateURL2);
+ wfree(&Data->UpdateURL3);
+ wfree(&Data->UpdateURL4);
+ wfree(&Data->Cookie);
+ wfree(&Data->IDSearch.SearchURL);
+ wfree(&Data->IDSearch.NotFoundStr);
+ FreeDataItem(&Data->IDSearch.Name);
+ wfree(&Data->NameSearch.SearchURL);
+ wfree(&Data->NameSearch.NotFoundStr);
+ wfree(&Data->NameSearch.SingleStr);
+ wfree(&Data->NameSearch.Single.First);
+ FreeDataItem(&Data->NameSearch.Single.Name);
+ FreeDataItem(&Data->NameSearch.Single.ID);
+ wfree(&Data->NameSearch.Multiple.First);
+ FreeDataItem(&Data->NameSearch.Multiple.Name);
+ FreeDataItem(&Data->NameSearch.Multiple.ID);
+ wfree(&Data->ShortFileName);
+ wfree(&Data->FileName);
+ for (i=0; i<10; i++) DestroyCondList(&Data->CondList[i]);
+}
+
+//============ WEATHER INI SETUP DIALOG ============
+
+INT_PTR CALLBACK DlgProcSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ // make the buttons flat
+ SendMessage(GetDlgItem(hwndDlg,IDC_STEP1), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_STEP2), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_STEP3), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_STEP4), BUTTONSETASFLATBTN, TRUE, 0);
+
+ // set icons
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx("main", TRUE));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx("main", FALSE));
+
+ WindowList_Add(hWindowList, hwndDlg, NULL);
+ ShowWindow(hwndDlg, SW_SHOW);
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_STEP1:
+ // update current data
+ CallService(MS_UTILS_OPENURL, opt.NewBrowserWin | OUF_TCHAR, (WPARAM)_T("http://miranda-ng.org/"));
+ break;
+
+ case IDC_STEP2:
+ {
+ TCHAR szPath[1024], *chop;
+ GetModuleFileName(GetModuleHandle(NULL), szPath, sizeof(szPath));
+ chop = _tcsrchr(szPath, '\\');
+ *chop = '\0';
+ _tcscat(szPath, _T("\\Plugins\\weather\\"));
+ _tmkdir(szPath);
+ ShellExecute((HWND)lParam, _T("open"), szPath, _T(""), _T(""), SW_SHOW);
+ break;
+ }
+
+ case IDC_STEP3:
+ if (LoadWIData(FALSE))
+ MessageBox(NULL,
+ TranslateT("All update data has been reloaded."),
+ TranslateT("Weather Protocol"), MB_OK|MB_ICONINFORMATION);
+ break;
+
+ case IDC_STEP4:
+ WeatherAdd(0, 0);
+
+ case IDCANCEL:
+ // close the info window
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
+ break;
+ }
+ return FALSE;
+}
+
diff --git a/plugins/Weather/src/weather_mwin.cpp b/plugins/Weather/src/weather_mwin.cpp
new file mode 100644
index 0000000000..8a7798b3b1
--- /dev/null
+++ b/plugins/Weather/src/weather_mwin.cpp
@@ -0,0 +1,420 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG Team
+Copyright (c) 2006-2009 Boris Krasnovskiy All Rights Reserved
+Copyright (c) 2002-2006 Calvin Che
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "weather.h"
+#include "m_acc.h"
+
+#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip"
+#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip"
+
+typedef BOOL (WINAPI *ft_TrackMouseEvent) (LPTRACKMOUSEEVENT lpEventTrack);
+
+static ft_TrackMouseEvent f_TrackMouseEvent = NULL;
+static HANDLE hMwinWindowList;
+static HANDLE hFontHook;
+
+HANDLE hMwinMenu;
+
+typedef struct
+{
+ HANDLE hContact;
+ HWND hAvt;
+ BOOL haveAvatar;
+} MWinDataType;
+
+#define WM_REDRAWWIN (WM_USER + 17369)
+
+static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MWinDataType *data = (MWinDataType*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch(msg)
+ {
+ case WM_CREATE:
+ data = (MWinDataType*)mir_calloc(sizeof(MWinDataType));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data);
+
+ data->hContact = (HANDLE)((LPCREATESTRUCT)lParam)->lpCreateParams;
+ data->hAvt = CreateWindow(AVATAR_CONTROL_CLASS, TEXT(""), WS_CHILD,
+ 0, 0, opt.AvatarSize, opt.AvatarSize, hwnd, NULL, hInst, 0);
+ if (data->hAvt) SendMessage(data->hAvt, AVATAR_SETCONTACT, 0, (LPARAM)data->hContact);
+ break;
+
+ case WM_DESTROY:
+ mir_free(data);
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ POINT pt;
+
+ HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)data->hContact, 0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if (f_TrackMouseEvent)
+ {
+ TRACKMOUSEEVENT tme = {0};
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.hwndTrack = hwnd;
+ tme.dwFlags = TME_QUERY;
+ f_TrackMouseEvent(&tme);
+
+ if (tme.dwFlags == 0)
+ {
+ tme.dwFlags = TME_HOVER | TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ tme.dwHoverTime = CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0);
+ f_TrackMouseEvent(&tme);
+ }
+ }
+ break;
+
+ case WM_MOUSEHOVER:
+ {
+ POINT pt;
+ CLCINFOTIP ti = {0};
+
+ GetCursorPos(&pt);
+ GetWindowRect(hwnd, &ti.rcItem);
+
+ ti.cbSize = sizeof(ti);
+ ti.hItem = data->hContact;
+ ti.ptCursor = pt;
+ ti.isTreeFocused = 1;
+ CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti);
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ BriefInfo((WPARAM)data->hContact, 0);
+ break;
+
+ case WM_COMMAND: //Needed by the contact's context menu
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)data->hContact))
+ break;
+ return FALSE;
+
+ case WM_MEASUREITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+
+ case WM_DRAWITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == NM_AVATAR_CHANGED)
+ {
+ BOOL newava = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)data->hContact, 0) != 0;
+ if (newava != data->haveAvatar)
+ {
+ LONG_PTR style = GetWindowLongPtr(data->hAvt, GWL_STYLE);
+ data->haveAvatar = newava;
+ SetWindowLongPtr(data->hAvt, GWL_STYLE, newava ? (style | WS_VISIBLE) : (style & ~WS_VISIBLE));
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ }
+ }
+ break;
+
+ case WM_REDRAWWIN:
+ if (data->hAvt != NULL) MoveWindow(data->hAvt, 0, 0, opt.AvatarSize, opt.AvatarSize, TRUE);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ break;
+
+ case WM_PAINT:
+ {
+ RECT r, rc;
+
+ if (GetUpdateRect(hwnd, &r, FALSE))
+ {
+ DBVARIANT dbv = {0};
+ PAINTSTRUCT ps;
+ LOGFONT lfnt, lfnt1;
+ COLORREF fntc, fntc1;
+ COLORREF clr;
+ int picSize = opt.AvatarSize;
+ HICON hIcon = NULL;
+
+ if ( !data->haveAvatar)
+ {
+ int statusIcon = db_get_w(data->hContact, WEATHERPROTONAME, "Status", 0);
+
+ picSize = GetSystemMetrics(SM_CXICON);
+ hIcon = LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon);
+ if ((INT_PTR)hIcon == CALLSERVICE_NOTFOUND)
+ {
+ picSize = GetSystemMetrics(SM_CXSMICON);
+ hIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon);
+ }
+ }
+
+ clr = db_get_dw(NULL, WEATHERPROTONAME, "ColorMwinFrame", GetSysColor(COLOR_3DFACE));
+
+ {
+ FontIDT fntid = {0};
+ _tcscpy(fntid.group, _T(WEATHERPROTONAME));
+ _tcscpy(fntid.name, LPGENT("Frame Font"));
+ fntc = CallService(MS_FONT_GETT, (WPARAM)&fntid, (LPARAM)&lfnt);
+
+ _tcscpy(fntid.name, LPGENT("Frame Title Font"));
+ fntc1 = CallService(MS_FONT_GETT, (WPARAM)&fntid, (LPARAM)&lfnt1);
+ }
+
+ DBGetContactSettingTString(data->hContact, WEATHERCONDITION, "WeatherInfo", &dbv);
+
+ GetClientRect(hwnd, &rc);
+
+ HDC hdc = BeginPaint(hwnd, &ps);
+
+ if ( ServiceExists(MS_SKIN_DRAWGLYPH)) {
+ SKINDRAWREQUEST rq;
+ memset(&rq, 0, sizeof(rq));
+ rq.hDC = hdc;
+ rq.rcDestRect = rc;
+ rq.rcClipRect = rc;
+
+ strcpy(rq.szObjectID, "Main,ID=WeatherFrame");
+ CallService(MS_SKIN_DRAWGLYPH, (WPARAM)&rq, 0);
+ }
+
+ if (clr != 0xFFFFFFFF) {
+ HBRUSH hBkgBrush = CreateSolidBrush(clr);
+ FillRect(hdc, &rc, hBkgBrush);
+ DeleteObject(hBkgBrush);
+ }
+
+ if ( !data->haveAvatar)
+ DrawIconEx(hdc, 1, 1, hIcon, 0, 0, 0, NULL, DI_NORMAL);
+
+ SetBkMode(hdc, TRANSPARENT);
+
+ HFONT hfnt = CreateFontIndirect(&lfnt1);
+ HFONT hfntold = ( HFONT )SelectObject(hdc, hfnt);
+ SIZE fontSize;
+
+ TCHAR *nick = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)data->hContact, GCDNF_TCHAR);
+
+ GetTextExtentPoint32(hdc, _T("|"), 1, &fontSize);
+
+ rc.top += 1;
+ rc.left += picSize + fontSize.cx;
+
+ SetTextColor(hdc, fntc1);
+ DrawText(hdc, nick, -1, &rc, DT_LEFT | DT_EXPANDTABS);
+
+ rc.top += fontSize.cy;
+
+ SelectObject(hdc, hfntold);
+ DeleteObject(hfnt);
+
+ if (dbv.pszVal)
+ {
+ HFONT hfnt = CreateFontIndirect(&lfnt);
+ HFONT hfntold = ( HFONT )SelectObject(hdc, hfnt);
+
+ SetTextColor(hdc, fntc);
+ DrawText(hdc, dbv.ptszVal, -1, &rc, DT_LEFT | DT_EXPANDTABS);
+
+ SelectObject(hdc, hfntold);
+ DeleteObject(hfnt);
+ }
+ EndPaint(hwnd, &ps);
+ Skin_ReleaseIcon(hIcon);
+ db_free(&dbv);
+ }
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return(TRUE);
+}
+
+static void addWindow(HANDLE hContact)
+{
+ DBVARIANT dbv;
+ DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv);
+
+ TCHAR winname[512];
+ mir_sntprintf(winname, SIZEOF(winname), _T("Weather: %s"), dbv.ptszVal);
+ db_free(&dbv);
+
+ HWND hWnd = CreateWindow( _T("WeatherFrame"), _T(""), WS_CHILD | WS_VISIBLE,
+ 0, 0, 10, 10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, hContact);
+ WindowList_Add(hMwinWindowList, hWnd, hContact);
+
+ CLISTFrame Frame = {0};
+ Frame.tname = winname;
+ Frame.hIcon = LoadIconEx("main",FALSE);
+ Frame.cbSize = sizeof(Frame);
+ Frame.hWnd = hWnd;
+ Frame.align = alBottom;
+ Frame.Flags = F_VISIBLE|F_NOBORDER|F_TCHAR;
+ Frame.height = 32;
+ DWORD frameID = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0);
+
+ db_set_dw(hContact, WEATHERPROTONAME, "mwin", frameID);
+ db_set_b(hContact, "CList", "Hidden", TRUE);
+}
+
+void removeWindow(HANDLE hContact)
+{
+ DWORD frameId = db_get_dw(hContact, WEATHERPROTONAME, "mwin", 0);
+
+ WindowList_Remove(hMwinWindowList, WindowList_Find(hMwinWindowList, hContact));
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0);
+
+ db_set_dw(hContact, WEATHERPROTONAME, "mwin", 0);
+ db_unset(hContact, "CList", "Hidden");
+}
+
+void UpdateMwinData(HANDLE hContact)
+{
+ HWND hwnd = WindowList_Find(hMwinWindowList, hContact);
+ if (hwnd != NULL)
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+}
+
+
+INT_PTR Mwin_MenuClicked(WPARAM wParam,LPARAM lParam)
+{
+ BOOL addwnd = WindowList_Find(hMwinWindowList, (HANDLE)wParam) == NULL;
+ if (addwnd)
+ addWindow((HANDLE)wParam);
+ else
+ removeWindow((HANDLE)wParam);
+ return 0;
+}
+
+
+int BuildContactMenu(WPARAM wparam,LPARAM lparam)
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS |
+ (db_get_dw((HANDLE)wparam, WEATHERPROTONAME, "mwin", 0) ? CMIF_CHECKED : 0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMwinMenu, (LPARAM)&mi);
+ return 0;
+}
+
+
+int RedrawFrame(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_Broadcast(hMwinWindowList, WM_REDRAWWIN, 0, 0);
+ return 0;
+}
+
+
+void InitMwin(void)
+{
+ HMODULE hUser = GetModuleHandle(_T("user32.dll"));
+
+ if ( !ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) return;
+
+ f_TrackMouseEvent = (ft_TrackMouseEvent)GetProcAddress(hUser, "TrackMouseEvent");
+
+
+ hMwinWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+
+ {
+ WNDCLASS wndclass;
+ wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = wndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = _T("WeatherFrame");
+ RegisterClass(&wndclass);
+ }
+
+ {
+ ColourIDT colourid = {0};
+ colourid.cbSize = sizeof(ColourIDT);
+ strcpy(colourid.dbSettingsGroup, WEATHERPROTONAME);
+ strcpy(colourid.setting, "ColorMwinFrame");
+ _tcscpy(colourid.name, LPGENT("Frame Background"));
+ _tcscpy(colourid.group, _T(WEATHERPROTONAME));
+ colourid.defcolour = GetSysColor(COLOR_3DFACE);
+ ColourRegisterT(&colourid);
+
+ FontIDT fontid = {0};
+ fontid.cbSize = sizeof(FontIDT);
+ fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID;
+ strcpy(fontid.dbSettingsGroup, WEATHERPROTONAME);
+ _tcscpy(fontid.group, _T(WEATHERPROTONAME));
+ _tcscpy(fontid.name, LPGENT("Frame Font"));
+ strcpy(fontid.prefix, "fnt0");
+
+ HDC hdc = GetDC(NULL);
+ fontid.deffontsettings.size = -13;
+ ReleaseDC(0, hdc);
+
+ fontid.deffontsettings.charset = DEFAULT_CHARSET;
+ _tcscpy(fontid.deffontsettings.szFace, _T("Verdana"));
+ _tcscpy(fontid.backgroundGroup, _T(WEATHERPROTONAME));
+ _tcscpy(fontid.backgroundName, LPGENT("Frame Background"));
+ FontRegisterT(&fontid);
+
+ fontid.deffontsettings.style = DBFONTF_BOLD;
+ _tcscpy(fontid.name, LPGENT("Frame Title Font"));
+ strcpy(fontid.prefix, "fnt1");
+ FontRegisterT(&fontid);
+ }
+
+ HANDLE hContact = db_find_first();
+ while(hContact)
+ {
+ // see if the contact is a weather contact
+ if (IsMyContact(hContact))
+ {
+ if (db_get_dw(hContact, WEATHERPROTONAME, "mwin", 0))
+ addWindow(hContact);
+ }
+ hContact = db_find_next(hContact);
+ }
+ hFontHook = HookEvent(ME_FONT_RELOAD, RedrawFrame);
+}
+
+void DestroyMwin(void)
+{
+ HANDLE hContact = db_find_first();
+ while(hContact)
+ {
+ // see if the contact is a weather contact
+ if (IsMyContact(hContact))
+ {
+ DWORD frameId = db_get_dw(hContact, WEATHERPROTONAME, "mwin", 0);
+ if (frameId)
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, frameId, 0);
+ }
+ hContact = db_find_next(hContact);
+ }
+ UnregisterClass( _T("WeatherFrame"), hInst);
+ UnhookEvent(hFontHook);
+}
diff --git a/plugins/Weather/src/weather_opt.cpp b/plugins/Weather/src/weather_opt.cpp
new file mode 100644
index 0000000000..f242adb0f1
--- /dev/null
+++ b/plugins/Weather/src/weather_opt.cpp
@@ -0,0 +1,642 @@
+/*
+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 weather option pages. It also
+contain code for saving/loading options from the database.
+*/
+
+#include "weather.h"
+
+static BOOL opt_startup;
+int RedrawFrame(WPARAM wParam, LPARAM lParam);
+
+//============ LOADING AND SAVING OPTIONS ===========
+
+// set a string to default
+// in = string to determine which field to set default "CBNEHXPp"
+void SetTextDefault(const char* in)
+{
+ TCHAR str[MAX_TEXT_SIZE];
+
+ if (strchr(in, 'C') != NULL)
+ {
+ _tcscpy(str, C_DEFAULT);
+ wSetData(&opt.cText, str);
+ }
+ if (strchr(in, 'b') != NULL)
+ {
+ _tcscpy(str, b_DEFAULT);
+ wSetData(&opt.bTitle, str);
+ }
+ if (strchr(in, 'B') != NULL)
+ {
+ _tcscpy(str, B_DEFAULT);
+ wSetData(&opt.bText, str);
+ }
+ if (strchr(in, 'N') != NULL)
+ {
+ _tcscpy(str, N_DEFAULT);
+ wSetData(&opt.nText, str);
+ }
+ if (strchr(in, 'E') != NULL)
+ {
+ _tcscpy(str, E_DEFAULT);
+ wSetData(&opt.eText, str);
+ }
+ if (strchr(in, 'H') != NULL)
+ {
+ _tcscpy(str, H_DEFAULT);
+ wSetData(&opt.hText, str);
+ }
+ if (strchr(in, 'X') != NULL)
+ {
+ _tcscpy(str, X_DEFAULT);
+ wSetData(&opt.xText, str);
+ }
+ if (strchr(in, 'P') != NULL)
+ {
+ _tcscpy(str, P_DEFAULT);
+ wSetData(&opt.pTitle, str);
+ }
+ if (strchr(in, 'p') != NULL)
+ {
+ _tcscpy(str, p_DEFAULT);
+ wSetData(&opt.pText, str);
+ }
+ if (strchr(in, 'S') != NULL)
+ {
+ _tcscpy(str, s_DEFAULT);
+ wSetData(&opt.sText, str);
+ }
+}
+
+void DestroyOptions(void)
+{
+ wfree(&opt.cText);
+ wfree(&opt.bTitle);
+ wfree(&opt.bText);
+ wfree(&opt.nText);
+ wfree(&opt.eText);
+ wfree(&opt.hText);
+ wfree(&opt.xText);
+ wfree(&opt.pTitle);
+ wfree(&opt.pText);
+ wfree(&opt.sText);
+}
+
+// load options from database + set default if the setting does not exist
+void LoadOptions(void)
+{
+ DBVARIANT dbv;
+ ZeroMemory(&opt, sizeof(opt));
+
+ // main options
+ opt.StartupUpdate = db_get_b(NULL, WEATHERPROTONAME, "StartupUpdate",TRUE);
+ opt.AutoUpdate = db_get_b(NULL, WEATHERPROTONAME, "AutoUpdate",TRUE);
+ opt.UpdateTime = db_get_w(NULL, WEATHERPROTONAME, "UpdateTime",30);
+ opt.NewBrowserWin = db_get_b(NULL, WEATHERPROTONAME, "NewWindow",TRUE);
+ opt.NoProtoCondition = db_get_b(NULL, WEATHERPROTONAME, "NoStatus",0);
+ opt.UpdateOnlyConditionChanged = db_get_b(NULL, WEATHERPROTONAME, "CondChangeAsUpdate",TRUE);
+ opt.RemoveOldData = db_get_b(NULL, WEATHERPROTONAME, "RemoveOld",FALSE);
+ opt.MakeItalic = db_get_b(NULL, WEATHERPROTONAME, "MakeItalic",TRUE);
+ opt.AvatarSize = db_get_b(NULL, WEATHERPROTONAME, "AvatarSize", 128);
+ // units
+ opt.tUnit = db_get_w(NULL, WEATHERPROTONAME, "tUnit", 1);
+ opt.wUnit = db_get_w(NULL, WEATHERPROTONAME, "wUnit", 2);
+ opt.vUnit = db_get_w(NULL, WEATHERPROTONAME, "vUnit", 1);
+ opt.pUnit = db_get_w(NULL, WEATHERPROTONAME, "pUnit", 4);
+ opt.dUnit = db_get_w(NULL, WEATHERPROTONAME, "dUnit", 1);
+ opt.eUnit = db_get_w(NULL, WEATHERPROTONAME, "eUnit", 2);
+ if (DBGetContactSettingTString(NULL, WEATHERPROTONAME, "DegreeSign",&dbv))
+ _tcscpy(opt.DegreeSign, _T(""));
+ else {
+ _tcscpy(opt.DegreeSign, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ opt.DoNotAppendUnit = db_get_b(NULL, WEATHERPROTONAME, "DoNotAppendUnit", 0);
+ opt.NoFrac = db_get_b(NULL, WEATHERPROTONAME, "NoFractions", 0);
+ // texts
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "DisplayText",&dbv)) {
+ wSetData(&opt.cText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("C");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "BriefTextTitle",&dbv)) {
+ wSetData(&opt.bTitle, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("b");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "BriefText",&dbv)) {
+ wSetData(&opt.bText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("B");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "NoteText",&dbv)) {
+ wSetData(&opt.nText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("N");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "ExtText",&dbv)) {
+ wSetData(&opt.eText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("E");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "HistoryText",&dbv)) {
+ wSetData(&opt.hText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("H");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "ExtraText",&dbv)) {
+ wSetData(&opt.xText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("X");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "StatusText",&dbv)) {
+ wSetData(&opt.sText, TranslateTS(dbv.ptszVal));
+ db_free(&dbv);
+ }
+ else SetTextDefault("S");
+
+ // advanced
+ opt.DisCondIcon = db_get_b(NULL, WEATHERPROTONAME, "DisableConditionIcon",FALSE);
+ // popup options
+ opt.UsePopup = db_get_b(NULL, WEATHERPROTONAME, "UsePopUp",TRUE);
+ opt.UpdatePopup = db_get_b(NULL, WEATHERPROTONAME, "UpdatePopup",TRUE);
+ opt.AlertPopup = db_get_b(NULL, WEATHERPROTONAME, "AlertPopup",TRUE);
+ opt.PopupOnChange = db_get_b(NULL, WEATHERPROTONAME, "PopUpOnChange",TRUE);
+ opt.ShowWarnings = db_get_b(NULL, WEATHERPROTONAME, "ShowWarnings",TRUE);
+ // popup colors
+ opt.BGColour = db_get_dw(NULL, WEATHERPROTONAME, "BackgroundColour",GetSysColor(COLOR_BTNFACE));
+ opt.TextColour = db_get_dw(NULL, WEATHERPROTONAME, "TextColour",GetSysColor(COLOR_WINDOWTEXT));
+ opt.UseWinColors = (BOOL)db_get_b(NULL, WEATHERPROTONAME, "UseWinColors", FALSE);
+ // popup actions
+ opt.LeftClickAction = db_get_dw(NULL, WEATHERPROTONAME, "LeftClickAction",IDM_M2);
+ opt.RightClickAction = db_get_dw(NULL, WEATHERPROTONAME, "RightClickAction",IDM_M1);
+ // popup delay
+ opt.pDelay = db_get_dw(NULL, WEATHERPROTONAME, "PopupDelay",0);
+ // popup texts
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "PopupTitle",&dbv)) {
+ wSetData(&opt.pTitle, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ else SetTextDefault("P");
+
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "PopupText",&dbv)) {
+ wSetData(&opt.pText, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ else SetTextDefault("p");
+
+ // misc
+ if ( !DBGetContactSettingTString(NULL, WEATHERPROTONAME, "Default",&dbv)) {
+ _tcscpy(opt.Default, dbv.ptszVal);
+ db_free(&dbv);
+ }
+ else opt.Default[0] = 0;
+}
+
+// save the options to database
+void SaveOptions(void)
+{
+ // main options
+ db_set_b(NULL, WEATHERPROTONAME, "StartupUpdate", (BYTE)opt.StartupUpdate);
+ db_set_b(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate);
+ db_set_w(NULL, WEATHERPROTONAME, "UpdateTime", opt.UpdateTime);
+ db_set_b(NULL, WEATHERPROTONAME, "NewWindow", (BYTE)opt.NewBrowserWin);
+ db_set_b(NULL, WEATHERPROTONAME, "NoStatus", (BYTE)opt.NoProtoCondition);
+ db_set_b(NULL, WEATHERPROTONAME, "CondChangeAsUpdate", (BYTE)opt.UpdateOnlyConditionChanged);
+ db_set_b(NULL, WEATHERPROTONAME, "RemoveOld", (BYTE)opt.RemoveOldData);
+ db_set_b(NULL, WEATHERPROTONAME, "MakeItalic", (BYTE)opt.MakeItalic);
+ db_set_b(NULL, WEATHERPROTONAME, "AvatarSize", (BYTE)opt.AvatarSize);
+ // units
+ db_set_w(NULL, WEATHERPROTONAME, "tUnit", opt.tUnit);
+ db_set_w(NULL, WEATHERPROTONAME, "wUnit", opt.wUnit);
+ db_set_w(NULL, WEATHERPROTONAME, "vUnit", opt.vUnit);
+ db_set_w(NULL, WEATHERPROTONAME, "pUnit", opt.pUnit);
+ db_set_w(NULL, WEATHERPROTONAME, "dUnit", opt.dUnit);
+ db_set_w(NULL, WEATHERPROTONAME, "eUnit", opt.eUnit);
+ db_set_ts(NULL, WEATHERPROTONAME, "DegreeSign", opt.DegreeSign);
+ db_set_b(NULL, WEATHERPROTONAME, "DoNotAppendUnit", (BYTE)opt.DoNotAppendUnit);
+ db_set_b(NULL, WEATHERPROTONAME, "NoFractions", (BYTE)opt.NoFrac);
+ // texts
+ db_set_ts(NULL, WEATHERPROTONAME, "DisplayText", opt.cText);
+ db_set_ts(NULL, WEATHERPROTONAME, "BriefTextTitle", opt.bTitle);
+ db_set_ts(NULL, WEATHERPROTONAME, "BriefText", opt.bText);
+ db_set_ts(NULL, WEATHERPROTONAME, "NoteText", opt.nText);
+ db_set_ts(NULL, WEATHERPROTONAME, "ExtText", opt.eText);
+ db_set_ts(NULL, WEATHERPROTONAME, "HistoryText", opt.hText);
+ db_set_ts(NULL, WEATHERPROTONAME, "ExtraText", opt.xText);
+ db_set_ts(NULL, WEATHERPROTONAME, "StatusText", opt.sText);
+ // advanced
+ db_set_b(NULL, WEATHERPROTONAME, "DisableConditionIcon", (BYTE)opt.DisCondIcon);
+ // popup options
+ db_set_b(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup);
+ db_set_b(NULL, WEATHERPROTONAME, "UpdatePopup", (BYTE)opt.UpdatePopup);
+ db_set_b(NULL, WEATHERPROTONAME, "AlertPopup", (BYTE)opt.AlertPopup);
+ db_set_b(NULL, WEATHERPROTONAME, "PopUpOnChange", (BYTE)opt.PopupOnChange);
+ db_set_b(NULL, WEATHERPROTONAME, "ShowWarnings", (BYTE)opt.ShowWarnings);
+ // popup colors
+ db_set_dw(NULL, WEATHERPROTONAME, "BackgroundColour", opt.BGColour);
+ db_set_dw(NULL, WEATHERPROTONAME, "TextColour", opt.TextColour);
+ db_set_b(NULL, WEATHERPROTONAME, "UseWinColors", (BYTE)opt.UseWinColors);
+ // popup actions
+ db_set_dw(NULL, WEATHERPROTONAME, "LeftClickAction", opt.LeftClickAction);
+ db_set_dw(NULL, WEATHERPROTONAME, "RightClickAction", opt.RightClickAction);
+ // popup delay
+ db_set_dw(NULL, WEATHERPROTONAME, "PopupDelay", opt.pDelay);
+ // popup texts
+ db_set_ts(NULL, WEATHERPROTONAME, "PopupTitle", opt.pTitle);
+ db_set_ts(NULL, WEATHERPROTONAME, "PopupText", opt.pText);
+ // misc stuff
+ db_set_ts(NULL, WEATHERPROTONAME, "Default", opt.Default);
+}
+
+//============ OPTION INITIALIZATION ============
+
+// register the weather option pages
+int OptInit(WPARAM wParam,LPARAM lParam) {
+ OPTIONSDIALOGPAGE odp = {0};
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+
+ // plugin options
+ odp.position = 95600;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.pfnDlgProc = OptionsProc;
+ odp.ptszGroup = LPGENT("Network");
+ odp.ptszTitle = _T(WEATHERPROTOTEXT);
+ odp.ptszTab = LPGENT("General");
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ Options_AddPage(wParam, &odp);
+
+ // text options
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_TEXTOPT);
+ odp.pfnDlgProc = DlgProcText;
+ odp.ptszTab = LPGENT("Display");
+ Options_AddPage(wParam, &odp);
+
+ // if popup service exists, load the weather popup options
+ if (( ServiceExists(MS_POPUP_ADDPOPUPT))) {
+ odp.position = 100000000;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_POPUP);
+ odp.ptszGroup = LPGENT("PopUps");
+ odp.groupPosition = 910000000;
+ odp.ptszTab = NULL;
+ odp.pfnDlgProc = DlgPopUpOpts;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+}
+
+//============ MAIN OPTIONS ============
+
+// weather options
+INT_PTR CALLBACK OptionsProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ TCHAR str[512];
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ opt_startup = TRUE;
+ TranslateDialogDefault(hdlg);
+ // load settings
+ _ltot(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);
+ CheckDlgButton(hdlg, IDC_UPDATE, opt.AutoUpdate);
+ CheckDlgButton(hdlg, IDC_PROTOCOND, !opt.NoProtoCondition);
+ CheckDlgButton(hdlg, IDC_UPDCONDCHG, opt.UpdateOnlyConditionChanged);
+ CheckDlgButton(hdlg, IDC_NEWWIN, opt.NewBrowserWin);
+ CheckDlgButton(hdlg, IDC_REMOVEOLD, opt.RemoveOldData);
+ CheckDlgButton(hdlg, IDC_MAKEI, opt.MakeItalic);
+ CheckDlgButton(hdlg, IDC_DISCONDICON, opt.DisCondIcon);
+ CheckDlgButton(hdlg, IDC_DONOTAPPUNITS, opt.DoNotAppendUnit);
+ CheckDlgButton(hdlg, IDC_NOFRAC, opt.NoFrac);
+
+ // load units
+ switch (opt.tUnit) { // temperature
+ case 1: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T1); break;
+ case 2: CheckRadioButton(hdlg, IDC_T1, IDC_T2, IDC_T2); break;
+ }
+ switch (opt.wUnit) { // wind
+ case 1: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W1); break;
+ case 2: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W2); break;
+ case 3: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W3); break;
+ case 4: CheckRadioButton(hdlg, IDC_W1, IDC_W4, IDC_W4); break;
+ }
+ switch (opt.vUnit) { // visibility
+ case 1: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V1); break;
+ case 2: CheckRadioButton(hdlg, IDC_V1, IDC_V2, IDC_V2); break;
+ }
+ switch (opt.pUnit) { // pressure
+ case 1: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P1); break;
+ case 2: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P2); break;
+ case 3: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P3); break;
+ case 4: CheckRadioButton(hdlg, IDC_P1, IDC_P4, IDC_P4); break;
+ }
+ switch (opt.dUnit) { // pressure
+ case 1: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D1); break;
+ case 2: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D2); break;
+ case 3: CheckRadioButton(hdlg, IDC_D1, IDC_D3, IDC_D3); break;
+ }
+
+ switch (opt.eUnit) { // elev
+ case 1: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E1); break;
+ case 2: CheckRadioButton(hdlg, IDC_E1, IDC_E2, IDC_E2); break;
+ }
+
+ opt_startup = FALSE;
+ return 0;
+
+ case WM_COMMAND:
+ if (HIWORD(wparam)==BN_CLICKED && GetFocus()==(HWND)lparam)
+ if ( !opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ if ( !((LOWORD(wparam) == IDC_UPDATE || LOWORD(wparam) == IDC_DEGREE) &&
+ (HIWORD(wparam) != EN_CHANGE || (HWND)lparam != GetFocus())))
+ if ( !opt_startup) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ return 0;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lparam)->code) {
+ case PSN_APPLY:
+ // change the status for weather protocol
+ if (IsDlgButtonChecked(hdlg, IDC_PROTOCOND) && opt.DefStn != NULL) {
+ old_status = status;
+ status = db_get_w(opt.DefStn, WEATHERPROTONAME, "StatusIcon", NOSTATUSDATA);
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status);
+ }
+
+ // get update time and remove the old timer
+ GetDlgItemText(hdlg, IDC_UPDATETIME, str, sizeof(str));
+ opt.UpdateTime = (WORD)_ttoi(str);
+ if (opt.UpdateTime < 1) opt.UpdateTime = 1;
+ KillTimer(NULL, timerId);
+ timerId = SetTimer(NULL, 0, opt.UpdateTime*60000, (TIMERPROC)timerProc);
+
+ // other general options
+ GetDlgItemText(hdlg, IDC_DEGREE, opt.DegreeSign, sizeof(opt.DegreeSign));
+ opt.StartupUpdate = IsDlgButtonChecked(hdlg, IDC_STARTUPUPD);
+ opt.AutoUpdate = IsDlgButtonChecked(hdlg, IDC_UPDATE);
+ opt.NewBrowserWin = IsDlgButtonChecked(hdlg, IDC_NEWWIN);
+ opt.NoProtoCondition = !IsDlgButtonChecked(hdlg, IDC_PROTOCOND);
+ opt.DisCondIcon = IsDlgButtonChecked(hdlg, IDC_DISCONDICON);
+ opt.UpdateOnlyConditionChanged = (BYTE)IsDlgButtonChecked(hdlg, IDC_UPDCONDCHG);
+ opt.RemoveOldData = IsDlgButtonChecked(hdlg, IDC_REMOVEOLD);
+ opt.MakeItalic = IsDlgButtonChecked(hdlg, IDC_MAKEI);
+ opt.AvatarSize = GetDlgItemInt(hdlg, IDC_AVATARSIZE, NULL, FALSE);;
+ opt.DoNotAppendUnit = IsDlgButtonChecked(hdlg, IDC_DONOTAPPUNITS);
+ opt.NoFrac = IsDlgButtonChecked(hdlg, IDC_NOFRAC);
+ UpdateMenu(opt.AutoUpdate);
+
+ // save the units
+ if (IsDlgButtonChecked(hdlg, IDC_T1)) opt.tUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_T2)) opt.tUnit = 2;
+ if (IsDlgButtonChecked(hdlg, IDC_W1)) opt.wUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_W2)) opt.wUnit = 2;
+ if (IsDlgButtonChecked(hdlg, IDC_W3)) opt.wUnit = 3;
+ if (IsDlgButtonChecked(hdlg, IDC_W4)) opt.wUnit = 4;
+ if (IsDlgButtonChecked(hdlg, IDC_V1)) opt.vUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_V2)) opt.vUnit = 2;
+ if (IsDlgButtonChecked(hdlg, IDC_P1)) opt.pUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_P2)) opt.pUnit = 2;
+ if (IsDlgButtonChecked(hdlg, IDC_P3)) opt.pUnit = 3;
+ if (IsDlgButtonChecked(hdlg, IDC_P4)) opt.pUnit = 4;
+ if (IsDlgButtonChecked(hdlg, IDC_D1)) opt.dUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_D2)) opt.dUnit = 2;
+ if (IsDlgButtonChecked(hdlg, IDC_D3)) opt.dUnit = 3;
+ if (IsDlgButtonChecked(hdlg, IDC_E1)) opt.eUnit = 1;
+ if (IsDlgButtonChecked(hdlg, IDC_E2)) opt.eUnit = 2;
+
+ // save the new weather options
+ SaveOptions();
+
+ RedrawFrame(0, 0);
+
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+//============ TEXT OPTION DIALOG ============
+
+void LoadTextSettings(HWND hdlg)
+{
+ // load text option settings from memory
+ SetDlgItemText(hdlg, IDC_CTEXT, opt.cText);
+ SetDlgItemText(hdlg, IDC_BTITLE, opt.bTitle);
+ SetDlgItemText(hdlg, IDC_BTEXT, opt.bText);
+ SetDlgItemText(hdlg, IDC_ETEXT, opt.eText);
+ SetDlgItemText(hdlg, IDC_NTEXT, opt.nText);
+ SetDlgItemText(hdlg, IDC_HTEXT, opt.hText);
+ SetDlgItemText(hdlg, IDC_XTEXT, opt.xText);
+ SetDlgItemText(hdlg, IDC_BTITLE2, opt.sText);
+}
+
+// free the display text settings from memory
+void FreeTextVar(void)
+{
+ wfree(&opt.cText);
+ wfree(&opt.bText);
+ wfree(&opt.bTitle);
+ wfree(&opt.eText);
+ wfree(&opt.nText);
+ wfree(&opt.hText);
+ wfree(&opt.xText);
+ wfree(&opt.sText);
+}
+
+// text option dialog
+
+static const char *varname[8] = {"C", "b", "B", "N", "X", "E", "H", "S"};
+static const int cname[8] = {IDC_CTEXT, IDC_BTITLE, IDC_BTEXT, IDC_NTEXT, IDC_XTEXT, IDC_ETEXT, IDC_HTEXT, IDC_BTITLE2 };
+static TCHAR* const *var[8] = {&opt.cText, &opt.bTitle, &opt.bText, &opt.nText, &opt.xText, &opt.eText, &opt.hText, &opt.sText };
+
+INT_PTR CALLBACK DlgProcText(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc, pos;
+ HWND button;
+ HMENU hMenu, hMenu1;
+ TCHAR str[4096];
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ opt_startup = TRUE;
+ // set windows position, make it top-most
+ GetWindowRect(hdlg, &rc);
+ SetWindowPos(hdlg, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE);
+ TranslateDialogDefault(hdlg);
+ // generate the display text for variable list
+ _tcscpy(str, 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"));
+ SetDlgItemText(hdlg, IDC_VARLIST, str);
+
+ // make the more variable and other buttons flat
+ SendMessage(GetDlgItem(hdlg,IDC_MORE), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM1), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM2), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM3), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM4), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM5), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM6), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM7), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_TM8), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_RESET), BUTTONSETASFLATBTN, TRUE, 0);
+ // load the settings
+ LoadTextSettings(hdlg);
+ opt_startup = FALSE;
+ return TRUE;
+
+ case WM_COMMAND:
+ if (opt_startup) return TRUE;
+ switch(LOWORD(wParam)) {
+ case IDC_CTEXT:
+ case IDC_BTITLE:
+ case IDC_BTEXT:
+ case IDC_NTEXT:
+ case IDC_XTEXT:
+ case IDC_ETEXT:
+ case IDC_HTEXT:
+ case IDC_BTITLE2:
+ if (HIWORD(wParam) == EN_CHANGE)
+ SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ break;
+
+ case IDC_MORE:
+ // display custom variables list
+ MoreVarList();
+ break;
+
+ case IDC_TM1:
+ case IDC_TM2:
+ case IDC_TM3:
+ case IDC_TM4:
+ case IDC_TM5:
+ case IDC_TM6:
+ case IDC_TM7:
+ case IDC_TM8:
+ {
+ WEATHERINFO winfo;
+
+ // display the menu
+ button = GetDlgItem(hdlg, LOWORD(wParam));
+ GetWindowRect(button, &pos);
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+ switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL)) {
+ case ID_MPREVIEW:
+ // show the preview in a message box, using the weather data from the default station
+ winfo = LoadWeatherInfo(opt.DefStn);
+ GetDisplay(&winfo, *var[LOWORD(wParam)-IDC_TM1], str);
+ MessageBox(NULL, str, TranslateT("Weather Protocol Text Preview"), MB_OK|MB_TOPMOST);
+ break;
+
+ case ID_MRESET:
+ {
+ unsigned varo = LOWORD(wParam) - IDC_TM1;
+ // remove the old setting from db and free memory
+ TCHAR* vartmp = *var[varo];
+ wfree(&vartmp);
+ SetTextDefault(varname[varo]);
+ SetDlgItemText(hdlg, cname[varo], *var[varo]);
+ }
+ break;
+ }
+ DestroyMenu(hMenu);
+ break;
+ }
+
+ case IDC_RESET:
+ // left click action selection menu
+ button = GetDlgItem(hdlg, IDC_RESET);
+ GetWindowRect(button, &pos);
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+ switch(TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL))
+ {
+ case ID_T1:
+ // reset to the strings in memory, discard all changes
+ LoadTextSettings(hdlg);
+ break;
+
+ case ID_T2:
+ // reset to the default setting
+ FreeTextVar();
+ SetTextDefault("CbBENHX");
+ LoadTextSettings(hdlg);
+ break;
+ }
+ DestroyMenu(hMenu);
+ break;
+ }
+ return TRUE;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ // save the option
+ TCHAR textstr[MAX_TEXT_SIZE];
+ // free memory for old settings
+ FreeTextVar();
+ // save new settings to memory
+ GetDlgItemText(hdlg, IDC_CTEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.cText, textstr);
+ GetDlgItemText(hdlg, IDC_BTEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.bText, textstr);
+ GetDlgItemText(hdlg, IDC_BTITLE, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.bTitle, textstr);
+ GetDlgItemText(hdlg, IDC_ETEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.eText, textstr);
+ GetDlgItemText(hdlg, IDC_NTEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.nText, textstr);
+ GetDlgItemText(hdlg, IDC_HTEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.hText, textstr);
+ GetDlgItemText(hdlg, IDC_XTEXT, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.xText, textstr);
+ GetDlgItemText(hdlg, IDC_BTITLE2, textstr, MAX_TEXT_SIZE);
+ wSetData(&opt.sText, textstr);
+ SaveOptions();
+ UpdateAllInfo(0, 0);
+ break;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
diff --git a/plugins/Weather/src/weather_popup.cpp b/plugins/Weather/src/weather_popup.cpp
new file mode 100644
index 0000000000..2a3e3580e5
--- /dev/null
+++ b/plugins/Weather/src/weather_popup.cpp
@@ -0,0 +1,438 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG Team
+Copyright (c) 2005-2009 Boris Krasnovskiy All Rights Reserved
+Copyright (c) 2002-2005 Calvin Che
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This file contain the source related to weather popups, including popup
+ options, popup display, and the code for popup process.
+*/
+
+#include "weather.h"
+
+// variables for weather_popup.c
+static HANDLE hPopupContact;
+
+//============ SHOW WEATHER POPUPS ============
+
+// display weather popups
+// wParam = the contact to display popup
+// lParam = whether the weather data is changed or not
+int WeatherPopup(WPARAM wParam, LPARAM lParam)
+{
+ // determine if the popup should display or not
+ if (opt.UsePopup && opt.UpdatePopup && (!opt.PopupOnChange || (BOOL)lParam) &&
+ !db_get_b((HANDLE)wParam, WEATHERPROTONAME, "DPopUp", 0))
+ {
+ POPUPDATAT ppd = {0};
+ WEATHERINFO winfo;
+
+ // setup the popup
+ ppd.lchContact = (HANDLE)wParam;
+// if ((HANDLE)wParam != NULL) { // for actual contact
+ winfo = LoadWeatherInfo((HANDLE)wParam);
+ ppd.PluginData = ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, winfo.status);
+ GetDisplay(&winfo, opt.pTitle, ppd.lptzContactName);
+ GetDisplay(&winfo, opt.pText, ppd.lptzText);
+ ppd.PluginWindowProc = PopupDlgProc;
+// }
+// else { // for preview
+// ppd.lchIcon = LoadSkinnedProtoIcon(WEATHERPROTONAME, ONLINE);
+// strcpy(ppd.lpzContactName, Translate("This is the name of the city"));
+// strcpy(ppd.lpzText, Translate("Here is a short weather description"));
+// ppd.PluginWindowProc = NULL;
+// }
+ ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour;
+ ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour;
+ ppd.iSeconds = opt.pDelay;
+ PUAddPopUpT( &ppd );
+ }
+ return 0;
+}
+
+//============ WEATHER ERROR POPUPS ============
+
+// display weather error or notices (not threaded)
+// wParam = error text
+// lParam = display type
+// Type can either be SM_WARNING, SM_NOTIFY, or SM_WEATHERALERT
+
+int WeatherError(WPARAM wParam, LPARAM lParam)
+{
+ if ( !opt.UsePopup)
+ return 0;
+
+ TCHAR* tszMsg = ( TCHAR* )wParam;
+
+ if ((DWORD)lParam == SM_WARNING)
+ PUShowMessageT( tszMsg, SM_WARNING );
+ else if ((DWORD)lParam == SM_NOTIFY)
+ PUShowMessageT( tszMsg, SM_NOTIFY);
+ else if ((DWORD)lParam == SM_WEATHERALERT)
+ {
+ POPUPDATAT ppd = {0};
+ TCHAR *chop, str1[512], str2[512];
+
+ // get the 2 strings
+ _tcscpy(str1, tszMsg);
+ _tcscpy(str2, tszMsg);
+ chop = _tcschr(str1, 255);
+ if (chop != NULL) *chop = '\0';
+ else str1[0] = 0;
+ chop = _tcschr(str2, 255);
+ if (chop != NULL) _tcscpy(str2, chop+1);
+ else str2[0] = 0;
+
+ // setup the popup
+ ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_BANG), IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
+ _tcscpy(ppd.lptzContactName, str1);
+ _tcscpy(ppd.lptzText, str2);
+ ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour;
+ ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour;
+ ppd.iSeconds = opt.pDelay;
+ PUAddPopUpT( &ppd );
+ }
+ 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(TCHAR* lpzText, WORD kind)
+{
+ NotifyEventHooks(hHookWeatherError, (WPARAM)lpzText, (LPARAM)kind);
+ return 0;
+}
+
+//============ WEATHER POPUP PROCESSES ============
+
+// popup dialog pocess
+// for selecting actions when click on the popup window
+// use for displaying contact menu
+LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ DWORD ID = 0;
+ HANDLE hContact;
+ hContact = PUGetContact(hWnd);
+
+ switch(message) {
+ case WM_COMMAND:
+ ID = opt.LeftClickAction;
+ if (ID != IDM_M7) PUDeletePopUp(hWnd);
+ SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0);
+ return TRUE;
+
+ case WM_CONTEXTMENU:
+ ID = opt.RightClickAction;
+ if (ID != IDM_M7) PUDeletePopUp(hWnd);
+ SendMessage(hPopupWindow, ID, (WPARAM)hContact, 0);
+ return TRUE;
+
+ case UM_FREEPLUGINDATA:
+ Skin_ReleaseIcon((HICON)PUGetPluginData(hWnd));
+ return FALSE;
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+// process for the popup window
+// containing the code for popup actions
+LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ HMENU hMenu;
+ switch (uMsg) {
+ case IDM_M2: // brief info
+ BriefInfo(wParam, 0);
+ break;
+
+ case IDM_M3: // read complete forecast
+ LoadForecast(wParam, 0);
+ break;
+
+ case IDM_M4: // display weather map
+ WeatherMap(wParam, 0);
+ break;
+
+ case IDM_M5: // open history window
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, wParam, 0);
+ break;
+
+ case IDM_M6: // open external log
+ ViewLog(wParam, 0);
+ break;
+
+ case IDM_M7: // display contact menu
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,wParam,0);
+ GetCursorPos(&pt);
+ hPopupContact = (HANDLE)wParam;
+ TrackPopupMenu(hMenu,TPM_LEFTALIGN,pt.x,pt.y,0,hWnd,NULL);
+ DestroyMenu(hMenu);
+ break;
+
+ case IDM_M8: // display contact detail
+ CallService(MS_USERINFO_SHOWDIALOG, wParam, 0);
+
+ case WM_COMMAND: //Needed by the contact's context menu
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU), (LPARAM)hPopupContact))
+ break;
+ return FALSE;
+
+ case WM_MEASUREITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+ case WM_DRAWITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);//FALSE;
+}
+
+//============ POPUP OPTIONS ============
+
+// used to select the menu item for popup action menu
+static void SelectMenuItem(HMENU hMenu, int Check)
+{
+ for (int i=0; i <= GetMenuItemCount(hMenu)-1; i++)
+ 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)
+{
+ TCHAR text[MAX_TEXT_SIZE];
+ int num;
+ TCHAR str[512];
+
+ // popup colour
+ opt.TextColour = SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_GETCOLOUR,0,0);
+ opt.BGColour = SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_GETCOLOUR,0,0);
+
+ // get delay time
+ GetDlgItemText(hdlg, IDC_DELAY, str, sizeof(str));
+ num = _ttoi(str);
+ opt.pDelay = num;
+
+ // other options
+ opt.UseWinColors = (BYTE)IsDlgButtonChecked(hdlg, IDC_USEWINCOLORS);
+ opt.UsePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_E);
+ opt.UpdatePopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP1);
+ opt.AlertPopup = (BYTE)IsDlgButtonChecked(hdlg, IDC_POP2);
+ opt.PopupOnChange = (BYTE)IsDlgButtonChecked(hdlg, IDC_CH);
+ opt.ShowWarnings = (BYTE)IsDlgButtonChecked(hdlg, IDC_W);
+
+ // popup texts
+ wfree(&opt.pText);
+ wfree(&opt.pTitle);
+ GetDlgItemText(hdlg, IDC_PText, text, MAX_TEXT_SIZE);
+ wSetData(&opt.pText, text);
+ GetDlgItemText(hdlg, IDC_PTitle, text, MAX_TEXT_SIZE);
+ wSetData(&opt.pTitle, text);
+}
+
+// copied and modified from NewStatusNotify
+INT_PTR CALLBACK DlgPopUpOpts(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int ID;
+ TCHAR str[512];
+ HMENU hMenu, hMenu1;
+ RECT pos;
+ HWND button;
+ HANDLE hContact;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hdlg);
+ SaveOptions();
+
+ // click actions
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND);
+ SetDlgItemText(hdlg, IDC_LeftClick, TranslateTS(str));
+ GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND);
+ SetDlgItemText(hdlg, IDC_RightClick, TranslateTS(str));
+ DestroyMenu(hMenu);
+
+ // other options
+ CheckDlgButton(hdlg, IDC_E, opt.UsePopup);
+ CheckDlgButton(hdlg, IDC_POP2, opt.AlertPopup);
+ CheckDlgButton(hdlg, IDC_POP1, opt.UpdatePopup);
+ CheckDlgButton(hdlg, IDC_CH, opt.PopupOnChange);
+ CheckDlgButton(hdlg, IDC_W, opt.ShowWarnings);
+ SetDlgItemText(hdlg,IDC_PText, opt.pText);
+ SetDlgItemText(hdlg,IDC_PTitle, opt.pTitle);
+ // setting popup delay option
+ _ltot(opt.pDelay, str, 10);
+ SetDlgItemText(hdlg,IDC_DELAY, str);
+ if (opt.pDelay == -1)
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2);
+ else if (opt.pDelay == 0)
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1);
+ else
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3);
+ //Colours. First step is configuring the colours.
+ SendDlgItemMessage(hdlg,IDC_BGCOLOUR,CPM_SETCOLOUR,0,opt.BGColour);
+ SendDlgItemMessage(hdlg,IDC_TEXTCOLOUR,CPM_SETCOLOUR,0,opt.TextColour);
+ //Second step is disabling them if we want to use default Windows ones.
+ CheckDlgButton(hdlg, IDC_USEWINCOLORS,opt.UseWinColors?BST_CHECKED:BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !opt.UseWinColors);
+ EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !opt.UseWinColors);
+
+ // buttons
+ SendMessage(GetDlgItem(hdlg,IDC_PREVIEW), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_PDEF), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_LeftClick), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,IDC_RightClick), BUTTONSETASFLATBTN, TRUE, 0);
+ SendMessage(GetDlgItem(hdlg,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;
+
+ case IDC_USEWINCOLORS:
+ // use window color - enable/disable color selection controls
+ EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOUR), !(opt.UseWinColors));
+ EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOUR), !(opt.UseWinColors));
+ SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_E:
+ case IDC_CH:
+ SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_RightClick:
+ // right click action selection menu
+ button = GetDlgItem(hdlg, IDC_RightClick);
+ GetWindowRect(button, &pos);
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+ SelectMenuItem(hMenu1, opt.RightClickAction);
+ ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL);
+ if (ID) opt.RightClickAction = ID;
+ DestroyMenu(hMenu);
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ GetMenuString(hMenu1, opt.RightClickAction, str, sizeof(str), MF_BYCOMMAND);
+ SetDlgItemText(hdlg, IDC_RightClick, TranslateTS(str));
+ DestroyMenu(hMenu);
+ break;
+
+ case IDC_LeftClick:
+ // left click action selection menu
+ button = GetDlgItem(hdlg, IDC_LeftClick);
+ GetWindowRect(button, &pos);
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ TranslateMenu(hMenu1);
+ SelectMenuItem(hMenu1, opt.LeftClickAction);
+ ID = TrackPopupMenu(hMenu1, TPM_LEFTBUTTON|TPM_RETURNCMD, pos.left, pos.bottom, 0, hdlg, NULL);
+ if (ID) opt.LeftClickAction = ID;
+ DestroyMenu(hMenu);
+
+ hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PMENU));
+ hMenu1 = GetSubMenu(hMenu, 0);
+ GetMenuString(hMenu1, opt.LeftClickAction, str, sizeof(str), MF_BYCOMMAND);
+ SetDlgItemText(hdlg, IDC_LeftClick, TranslateTS(str));
+ DestroyMenu(hMenu);
+ break;
+
+ case IDC_PD1:
+ // Popup delay setting from PopUp plugin
+ SetDlgItemText(hdlg, IDC_DELAY, _T("0"));
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD1);
+ break;
+
+ case IDC_PD2:
+ // Popup delay = permanent
+ SetDlgItemText(hdlg, IDC_DELAY, _T("-1"));
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD2);
+ break;
+
+ case IDC_DELAY:
+ // if text is edited
+ CheckRadioButton(hdlg, IDC_PD1, IDC_PD3, IDC_PD3);
+ break;
+
+ case IDC_PDEF:
+ // set the default value for popup texts
+ SetTextDefault("Pp");
+ SetDlgItemText(hdlg,IDC_PText, opt.pText);
+ SetDlgItemText(hdlg,IDC_PTitle, opt.pTitle);
+ wfree(&opt.pText);
+ wfree(&opt.pTitle);
+ break;
+
+ case IDC_VAR3:
+ // display variable list
+ _tcscpy(str, _T(" \n")); // to make the message box wider
+ _tcscat(str, 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"));
+ _tcscat(str, _T("\n"));
+ _tcscat(str, TranslateT("%[..]\tcustom variables"));
+ MessageBox(NULL, str, TranslateT("Variable List"), MB_OK|MB_ICONASTERISK|MB_TOPMOST);
+ break;
+
+ case IDC_PREVIEW:
+ // popup preview
+ hContact = opt.DefStn;
+ ReadPopupOpt(hdlg); // read new options to memory
+ WeatherPopup((WPARAM)opt.DefStn, (BOOL)TRUE); // display popup using new opt
+ DestroyOptions();
+ LoadOptions(); // restore old option in memory
+ opt.DefStn = hContact;
+ break;
+ }
+ break;
+
+ case WM_NOTIFY: //Here we have pressed either the OK or the APPLY button.
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ ReadPopupOpt(hdlg);
+
+ // save the options, and update main menu
+ SaveOptions();
+ UpdatePopupMenu(opt.UsePopup);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/plugins/Weather/src/weather_svcs.cpp b/plugins/Weather/src/weather_svcs.cpp
new file mode 100644
index 0000000000..3872760fc6
--- /dev/null
+++ b/plugins/Weather/src/weather_svcs.cpp
@@ -0,0 +1,386 @@
+/*
+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 weather protocol services
+as required for a Miranda protocol. Also, it contains functions for
+building/changing the weather menu items.
+*/
+
+#include "weather.h"
+
+static HGENMENU hEnableDisablePopupMenu;
+static HGENMENU hEnableDisableMenu;
+
+//============ MIRANDA PROTOCOL SERVICES ============
+
+// protocol service function for setting weather protocol status
+INT_PTR WeatherSetStatus(WPARAM new_status, LPARAM lParam)
+{
+ new_status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE;
+
+ // if we don't want to show status for default station
+ if (opt.NoProtoCondition && status != new_status) {
+ old_status = status;
+ status = new_status != ID_STATUS_OFFLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status);
+
+ UpdateMenu(new_status != ID_STATUS_OFFLINE);
+ if (new_status != ID_STATUS_OFFLINE)
+ UpdateAll(FALSE, FALSE);
+ }
+
+ return 0;
+}
+
+// get capabilities protocol service function
+INT_PTR WeatherGetCaps(WPARAM wParam, LPARAM lParam)
+{
+ INT_PTR ret = 0;
+
+ switch(wParam) {
+ case PFLAGNUM_1:
+ // support search and visible list
+ ret = PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_EXTSEARCH | PF1_VISLIST | PF1_MODEMSGRECV;
+ break;
+
+ case PFLAGNUM_2:
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND |
+ PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+
+ case PFLAGNUM_4:
+ ret = PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_FORCEADDED |
+ PF4_FORCEAUTH;
+ break;
+
+ case PFLAGNUM_5: /* this is PFLAGNUM_5 change when alpha SDK is released */
+ ret = PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND |
+ PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+
+ case PFLAG_UNIQUEIDTEXT:
+ ret = (INT_PTR)Translate("Station ID");
+ break;
+
+ case PFLAG_UNIQUEIDSETTING:
+ ret = (INT_PTR)"ID";
+ break;
+ }
+ return ret;
+}
+
+// protocol service function to get weather protocol name
+INT_PTR WeatherGetName(WPARAM wParam,LPARAM lParam)
+{
+ strncpy((char*)lParam,WEATHERPROTOTEXT,wParam-1);
+ *((char*)lParam + wParam-1) = 0;
+ return 0;
+}
+
+// protocol service function to get the current status of the protocol
+INT_PTR WeatherGetStatus(WPARAM wParam,LPARAM lParam)
+{
+ return status;
+}
+
+// protocol service function to get the icon of the protocol
+INT_PTR WeatherLoadIcon(WPARAM wParam,LPARAM lParam)
+{
+ return (LOWORD(wParam) == PLI_PROTOCOL) ? (INT_PTR)CopyIcon(LoadIconEx("main", FALSE)) : 0;
+}
+
+static void __cdecl AckThreadProc(HANDLE param)
+{
+ Sleep(100);
+ ProtoBroadcastAck(WEATHERPROTONAME, param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+}
+
+// nothing to do here because weather proto do not need to retrieve contact info form network
+// so just return a 0
+INT_PTR WeatherGetInfo(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ mir_forkthread(AckThreadProc, ccs->hContact);
+ return 0;
+}
+
+// avatars
+static const TCHAR *statusStr[] = { _T("Light"), _T("Fog"), _T("SShower"), _T("Snow"), _T("RShower"), _T("Rain"), _T("PCloudy"), _T("Cloudy"), _T("Sunny"), _T("NA") };
+static const WORD statusValue[] = { LIGHT, FOG, SSHOWER, SNOW, RSHOWER, RAIN, PCLOUDY, CLOUDY, SUNNY, NA };
+
+INT_PTR WeatherGetAvatarInfo(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR szSearchPath[MAX_PATH], *chop;
+ WORD status;
+ unsigned i;
+ PROTO_AVATAR_INFORMATIONT* ai = ( PROTO_AVATAR_INFORMATIONT* )lParam;
+
+ GetModuleFileName(GetModuleHandle(NULL), szSearchPath, sizeof(szSearchPath));
+ chop = _tcsrchr(szSearchPath, '\\');
+
+ if (chop) *chop = '\0';
+ else szSearchPath[0] = 0;
+
+ status = (WORD)db_get_w(ai->hContact, WEATHERPROTONAME, "StatusIcon",0);
+ for (i=0; i<10; i++)
+ if (statusValue[i] == status)
+ break;
+
+ if (i >= 10)
+ return GAIR_NOAVATAR;
+
+ ai->format = PA_FORMAT_PNG;
+ wsprintf(ai->filename, _T("%s\\Plugins\\Weather\\%s.png"), szSearchPath, statusStr[i]);
+ if ( _taccess(ai->filename, 4) == 0)
+ return GAIR_SUCCESS;
+
+ ai->format = PA_FORMAT_GIF;
+ wsprintf(ai->filename, _T("%s\\Plugins\\Weather\\%s.gif"), szSearchPath, statusStr[i]);
+ if ( _taccess(ai->filename, 4) == 0)
+ return GAIR_SUCCESS;
+
+ ai->format = PA_FORMAT_UNKNOWN;
+ ai->filename[0] = 0;
+ return GAIR_NOAVATAR;
+}
+
+
+void AvatarDownloaded(HANDLE hContact)
+{
+ PROTO_AVATAR_INFORMATIONT AI = {0};
+ AI.cbSize = sizeof(AI);
+ AI.hContact = hContact;
+
+ if (WeatherGetAvatarInfo(GAIF_FORCE, (LPARAM)&AI) == GAIR_SUCCESS)
+ ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &AI, 0);
+ else
+ ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
+}
+
+
+static void __cdecl WeatherGetAwayMsgThread(HANDLE hContact)
+{
+ Sleep(100);
+
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(hContact, "CList", "StatusMsg", &dbv)) {
+ ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal);
+ db_free( &dbv );
+ }
+ else ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, 0);
+}
+
+static INT_PTR WeatherGetAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA* ccs = (CCSDATA*)lParam;
+ if (ccs == NULL)
+ return 0;
+
+ mir_forkthread(WeatherGetAwayMsgThread, ccs->hContact);
+ return 1;
+}
+
+//============ PROTOCOL INITIALIZATION ============
+// protocol services
+void InitServices(void)
+{
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETCAPS, WeatherGetCaps);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETNAME, WeatherGetName);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_LOADICON, WeatherLoadIcon);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_SETSTATUS, WeatherSetStatus);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETSTATUS, WeatherGetStatus);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_BASICSEARCHT, WeatherBasicSearch);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYEMAILT, WeatherBasicSearch);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_ADDTOLIST, WeatherAddToList);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETINFO, WeatherGetInfo);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_GETAVATARINFOT, WeatherGetAvatarInfo);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PSS_GETAWAYMSG, WeatherGetAwayMsg);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_CREATEADVSEARCHUI, WeatherCreateAdvancedSearchUI);
+ CreateProtoServiceFunction(WEATHERPROTONAME, PS_SEARCHBYADVANCED, WeatherAdvancedSearch);
+
+ CreateProtoServiceFunction(WEATHERPROTONAME, MS_WEATHER_GETDISPLAY, GetDisplaySvcFunc);
+}
+
+//============ MENU INITIALIZATION ============
+
+void UpdateMenu(BOOL State)
+{
+ // update option setting
+ opt.CAutoUpdate = State;
+ db_set_b(NULL, WEATHERPROTONAME, "AutoUpdate", (BYTE)opt.AutoUpdate);
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+
+ if (State) { // to enable auto-update
+ mi.pszName = LPGEN("Auto Update Enabled");
+ mi.icolibItem = GetIconHandle("main");
+ }
+ else { // to disable auto-update
+ mi.pszName = LPGEN("Auto Update Disabled");
+ mi.icolibItem = GetIconHandle("disabled");
+ }
+
+ mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hEnableDisableMenu, (LPARAM)&mi);
+}
+
+void UpdatePopupMenu(BOOL State)
+{
+ // update option setting
+ opt.UsePopup = State;
+ db_set_b(NULL, WEATHERPROTONAME, "UsePopUp", (BYTE)opt.UsePopup);
+
+ CLISTMENUITEM mi = { sizeof(mi) };
+ if (State)
+ { // to enable popup
+ mi.pszName = LPGEN("Disable &weather notification");
+ mi.icolibItem = GetIconHandle("popup");
+ }
+ else
+ { // to disable popup
+ mi.pszName = LPGEN("Enable &weather notification");
+ mi.icolibItem = GetIconHandle("nopopup");
+ }
+
+ mi.flags = CMIM_ICON | CMIM_NAME | CMIF_ICONFROMICOLIB;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hEnableDisablePopupMenu, (LPARAM)&mi);
+}
+
+// update the weather auto-update menu item when click on it
+INT_PTR EnableDisableCmd(WPARAM wParam,LPARAM lParam)
+{
+ UpdateMenu(wParam == TRUE ? (BOOL)lParam : !opt.CAutoUpdate);
+ return 0;
+}
+
+// update the weather popup menu item when click on it
+INT_PTR MenuitemNotifyCmd(WPARAM wParam,LPARAM lParam)
+{
+ UpdatePopupMenu(!opt.UsePopup);
+ return 0;
+}
+
+// adding weather contact menus
+// copied and modified form "modified MSN Protocol"
+void AddMenuItems(void)
+{
+ CLISTMENUITEM mi = { sizeof(mi) };
+ mi.pszContactOwner = WEATHERPROTONAME;
+ mi.flags = CMIF_ICONFROMICOLIB;
+
+ // contact menu
+ CreateServiceFunction(MS_WEATHER_UPDATE, UpdateSingleStation);
+ mi.position = -0x7FFFFFFA;
+ mi.icolibItem = GetIconHandle("update");
+ mi.pszName = LPGEN("Update Weather");
+ mi.pszService = MS_WEATHER_UPDATE;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_REFRESH, UpdateSingleRemove);
+ mi.position = -0x7FFFFFF9;
+ mi.icolibItem = GetIconHandle("update2");
+ mi.pszName = LPGEN("Remove Old Data then Update");
+ mi.pszService = MS_WEATHER_REFRESH;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_BRIEF, BriefInfoSvc);
+ mi.position = -0x7FFFFFF8;
+ mi.icolibItem = GetIconHandle("brief");
+ mi.pszName = LPGEN("Brief Information");
+ mi.pszService = MS_WEATHER_BRIEF;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_COMPLETE, LoadForecast);
+ mi.position = -0x7FFFFFF7;
+ mi.icolibItem = GetIconHandle("read");
+ mi.pszName = LPGEN("Read Complete Forecast");
+ mi.pszService = MS_WEATHER_COMPLETE;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_MAP, WeatherMap);
+ mi.position = -0x7FFFFFF6;
+ mi.icolibItem = GetIconHandle("map");
+ mi.pszName = LPGEN("Weather Map");
+ mi.pszService = MS_WEATHER_MAP;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_LOG, ViewLog);
+ mi.position = -0x7FFFFFF5;
+ mi.icolibItem = GetIconHandle("log");
+ mi.pszName = LPGEN("View Log");
+ mi.pszService = MS_WEATHER_LOG;
+ Menu_AddContactMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_EDIT, EditSettings);
+ mi.position = -0x7FFFFFF4;
+ mi.icolibItem = GetIconHandle("edit");
+ mi.pszName = LPGEN("Edit Settings");
+ mi.pszService = MS_WEATHER_EDIT;
+ Menu_AddContactMenuItem(&mi);
+
+ // adding main menu items
+ mi.pszPopupName = LPGEN("Weather");
+ mi.popupPosition = 500099000;
+
+ CreateServiceFunction(MS_WEATHER_ENABLED, EnableDisableCmd);
+ mi.pszName = LPGEN("Enable/Disable Weather Update");
+ mi.icolibItem = GetIconHandle("main");
+ mi.position = 10100001;
+ mi.pszService = MS_WEATHER_ENABLED;
+ hEnableDisableMenu = Menu_AddMainMenuItem(&mi);
+ UpdateMenu(opt.AutoUpdate);
+
+ CreateServiceFunction(MS_WEATHER_UPDATEALL, UpdateAllInfo);
+ mi.position = 20100001;
+ mi.icolibItem = GetIconHandle("update");
+ mi.pszName = LPGEN("Update All Weather");
+ mi.pszService = MS_WEATHER_UPDATEALL;
+ Menu_AddMainMenuItem(&mi);
+
+ CreateServiceFunction(MS_WEATHER_REFRESHALL, UpdateAllRemove);
+ mi.position = 20100002;
+ mi.icolibItem = GetIconHandle("update2");
+ mi.pszName = LPGEN("Remove Old Data then Update All");
+ mi.pszService = MS_WEATHER_REFRESHALL;
+ Menu_AddMainMenuItem(&mi);
+
+ // only run if popup service exists
+ if ( ServiceExists(MS_POPUP_ADDPOPUPT)) {
+ CreateServiceFunction(WEATHERPROTONAME "/PopupMenu", MenuitemNotifyCmd);
+ mi.pszName = LPGEN("Weather Notification");
+ mi.icolibItem = GetIconHandle("popup");
+ mi.position = 0;
+ mi.pszPopupName = LPGEN("PopUps");
+ mi.pszService = WEATHERPROTONAME "/PopupMenu";
+ hEnableDisablePopupMenu = Menu_AddMainMenuItem(&mi);
+ UpdatePopupMenu(opt.UsePopup);
+ }
+
+ if ( ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ CreateServiceFunction("Weather/mwin_menu", Mwin_MenuClicked);
+ mi.position = -0x7FFFFFF0;
+ mi.hIcon = NULL;
+ mi.flags = 0;
+ mi.pszName = LPGEN("Display in a frame");
+ mi.pszService = "Weather/mwin_menu";
+ hMwinMenu = Menu_AddContactMenuItem(&mi);
+ }
+}
diff --git a/plugins/Weather/src/weather_update.cpp b/plugins/Weather/src/weather_update.cpp
new file mode 100644
index 0000000000..d07af7865b
--- /dev/null
+++ b/plugins/Weather/src/weather_update.cpp
@@ -0,0 +1,615 @@
+/*
+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 updating new weather
+information, both automatic (by timer) and manually (by selecting
+menu items).
+*/
+
+#include "weather.h"
+
+UPDATELIST *UpdateListHead;
+UPDATELIST *UpdateListTail;
+
+extern HANDLE hUpdateMutex;
+
+//============ RETRIEVE NEW WEATHER ============
+
+// retrieve weather info and display / log them
+// hContact = current contact
+int UpdateWeather(HANDLE hContact)
+{
+ TCHAR str[256], str2[MAX_TEXT_SIZE];
+ DBVARIANT dbv;
+ BOOL Ch = FALSE;
+
+ if (hContact == NULL) return 1; // some error prevention
+
+ dbv.pszVal = "";
+
+ // log to netlib log for debug purpose
+ Netlib_LogfT(hNetlibUser, _T("************************************************************************"));
+ int dbres = DBGetContactSettingTString(hContact, WEATHERPROTONAME, "Nick", &dbv);
+
+ Netlib_LogfT(hNetlibUser, _T("<-- Start update for station -->"));
+
+ // download the info and parse it
+ // result are stored in database
+ int code = GetWeatherData(hContact);
+ if (code != 0)
+ {
+ // error occurs if the return value is not equals to 0
+ if (opt.ShowWarnings)
+ { // show warnings by popup
+ mir_sntprintf(str, SIZEOF(str)-105,
+ TranslateT("Unable to retrieve weather information for %s"), dbv.ptszVal);
+ _tcscat(str, _T("\n"));
+ _tcscat(str, GetError(code));
+ WPShowMessage(str, SM_WARNING);
+ }
+ // log to netlib
+ Netlib_LogfT(hNetlibUser, _T("Error! Update cannot continue... Start to free memory"));
+ Netlib_LogfT(hNetlibUser, _T("<-- Error occurs while updating station: %s -->"), dbv.ptszVal);
+ if ( !dbres) db_free(&dbv);
+ return 1;
+ }
+ if ( !dbres) db_free(&dbv);
+
+ // initialize, load new weather Data
+ WEATHERINFO winfo = LoadWeatherInfo(hContact);
+
+ // translate weather condition
+ _tcscpy(winfo.cond, TranslateTS(winfo.cond));
+
+ // compare the old condition and determine if the weather had changed
+ if (opt.UpdateOnlyConditionChanged) { // consider condition change
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "LastCondition", &dbv)) {
+ if (_tcsicmp(winfo.cond, dbv.ptszVal)) Ch = TRUE; // the weather condition is changed
+ db_free(&dbv);
+ }
+ else Ch = TRUE;
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "LastTemperature", &dbv)) {
+ if (_tcsicmp(winfo.temp, dbv.ptszVal)) Ch = TRUE; // the temperature is changed
+ db_free(&dbv);
+ }
+ else Ch = TRUE;
+ }
+ else { // consider update time change
+ if ( !DBGetContactSettingTString(hContact, WEATHERPROTONAME, "LastUpdate", &dbv)) {
+ if (_tcsicmp(winfo.update, dbv.ptszVal)) Ch = TRUE; // the update time is changed
+ db_free(&dbv);
+ }
+ else Ch = TRUE;
+ }
+
+ // have weather alert issued?
+ dbres = DBGetContactSettingTString(hContact, WEATHERCONDITION, "Alert", &dbv);
+ if ( !dbres && dbv.ptszVal[0] != 0) {
+ if (opt.AlertPopup && !db_get_b(hContact, WEATHERPROTONAME, "DPopUp", 0) && Ch) {
+ // display alert popup
+ wsprintf(str, _T("Alert for %s%c%s"), winfo.city, 255, dbv.ptszVal);
+ WPShowMessage(str, SM_WEATHERALERT);
+ }
+ // alert issued, set display to italic
+ if (opt.MakeItalic)
+ db_set_w(hContact, WEATHERPROTONAME, "ApparentMode", ID_STATUS_OFFLINE);
+ SkinPlaySound("weatheralert");
+ }
+ // alert dropped, set the display back to normal
+ else db_unset(hContact, WEATHERPROTONAME, "ApparentMode");
+ if ( !dbres) db_free(&dbv);
+
+ // backup current condition for checking if the weather is changed or not
+ db_set_ts(hContact, WEATHERPROTONAME, "LastLog", winfo.update);
+ db_set_ts(hContact, WEATHERPROTONAME, "LastCondition", winfo.cond);
+ db_set_ts(hContact, WEATHERPROTONAME, "LastTemperature", winfo.temp);
+ db_set_ts(hContact, WEATHERPROTONAME, "LastUpdate", winfo.update);
+
+ // display condition on contact list
+ if (opt.DisCondIcon && winfo.status != ID_STATUS_OFFLINE)
+ db_set_w(hContact, WEATHERPROTONAME, "Status", ID_STATUS_ONLINE);
+ else
+ db_set_w(hContact, WEATHERPROTONAME, "Status", winfo.status);
+ AvatarDownloaded(hContact);
+
+ GetDisplay(&winfo, opt.cText, str2);
+ db_set_ts(hContact, "CList", "MyHandle", str2);
+
+ GetDisplay(&winfo, opt.sText, str2);
+ if (str2[0])
+ db_set_ts(hContact, "CList", "StatusMsg", str2);
+ else
+ db_unset(hContact, "CList", "StatusMsg");
+
+ ProtoBroadcastAck(WEATHERPROTONAME, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, NULL, (LPARAM)(str2[0] ? str2 : 0));
+
+ // save descriptions in MyNotes
+ GetDisplay(&winfo, opt.nText, str2);
+ db_set_ts(hContact, "UserInfo", "MyNotes", str2);
+ GetDisplay(&winfo, opt.xText, str2);
+ db_set_ts(hContact, WEATHERCONDITION, "WeatherInfo", str2);
+
+ // set the update tag
+ db_set_b(hContact, WEATHERPROTONAME, "IsUpdated", TRUE);
+
+ // save info for default weather condition
+ if ( !_tcscmp(winfo.id, opt.Default) && !opt.NoProtoCondition) {
+ // save current condition for default station to be displayed after the update
+ old_status = status;
+ status = winfo.status;
+ // a workaround for a default station that currently have an n/a icon assigned
+ if (status == ID_STATUS_OFFLINE) status = NOSTATUSDATA;
+ ProtoBroadcastAck(WEATHERPROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, status);
+ }
+
+ // logging
+ if (Ch) {
+ // play the sound event
+ SkinPlaySound("weatherupdated");
+
+ if (db_get_b(hContact, WEATHERPROTONAME, "File", 0)) {
+ // external log
+ if ( !DBGetContactSettingTString(hContact,WEATHERPROTONAME, "Log",&dbv)) {
+ // for the option for overwriting the file, delete old file first
+ if (db_get_b(hContact,WEATHERPROTONAME, "Overwrite",0))
+ DeleteFile(dbv.ptszVal);
+ // open the file and set point to the end of file
+ FILE *file = _tfopen( dbv.ptszVal, _T("a"));
+ db_free(&dbv);
+ if (file != NULL) {
+ // write data to the file and close
+ GetDisplay(&winfo, opt.eText, str2);
+ _fputts(str2, file);
+ fclose(file);
+ } } }
+
+ if (db_get_b(hContact, WEATHERPROTONAME, "History", 0)) {
+ DBEVENTINFO dbei = {0};
+ // internal log using history
+ GetDisplay(&winfo, opt.hText, str2);
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = WEATHERPROTONAME;
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.flags = DBEF_READ|DBEF_UTF;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.pBlob = (PBYTE)mir_utf8encodeT(str2);
+ dbei.cbBlob = (DWORD)strlen((char*)dbei.pBlob)+1;
+
+ // add the history event
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ }
+
+ // show the popup
+ NotifyEventHooks(hHookWeatherUpdated, (WPARAM)hContact, (LPARAM)Ch);
+ }
+
+ Netlib_LogfT(hNetlibUser, _T("Update Completed - Start to free memory"));
+ Netlib_LogfT(hNetlibUser, _T("<-- Update successful for station -->"));
+
+ // Update frame data
+ UpdateMwinData(hContact);
+
+ // update brief info if its opened
+ HWND hMoreDataDlg = WindowList_Find(hDataWindowList, hContact);
+ if (hMoreDataDlg != NULL) PostMessage(hMoreDataDlg, WM_UPDATEDATA, 0, 0);
+ return 0;
+}
+
+//============ UPDATE LIST ============
+
+// a linked list queue for updating weather station
+// this function add a weather contact to the end of queue for update
+// hContact = current contact
+void UpdateListAdd(HANDLE hContact)
+{
+ UPDATELIST *newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST));
+ newItem->hContact = hContact;
+ newItem->next = NULL;
+
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ if (UpdateListTail == NULL) UpdateListHead = newItem;
+ else UpdateListTail->next = newItem;
+ UpdateListTail = newItem;
+
+ ReleaseMutex(hUpdateMutex);
+}
+
+// get the first item from the update queue and remove it from the queue
+// return value = the contact for next update
+HANDLE UpdateGetFirst()
+{
+ HANDLE hContact = NULL;
+
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ if (UpdateListHead != NULL)
+ {
+ UPDATELIST* Item = UpdateListHead;
+
+ hContact = Item->hContact;
+ UpdateListHead = Item->next;
+ mir_free(Item);
+
+ if (UpdateListHead == NULL) UpdateListTail = NULL;
+ }
+
+ ReleaseMutex(hUpdateMutex);
+
+ return hContact;
+}
+
+void DestroyUpdateList(void)
+{
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ UPDATELIST *temp = UpdateListHead;
+
+ // free the list one by one
+ while (temp != NULL)
+ {
+ UpdateListHead = temp->next;
+ mir_free(temp);
+ temp = UpdateListHead;
+ }
+ // make sure the entire list is clear
+ UpdateListTail = NULL;
+
+ ReleaseMutex(hUpdateMutex);
+}
+
+
+//============ UPDATE WEATHER ============
+
+// update all weather station
+// AutoUpdate = true if it is from automatic update using timer
+// false if it is from update by clicking the main menu
+void UpdateAll(BOOL AutoUpdate, BOOL RemoveData)
+{
+ // add all weather contact to the update queue list
+ HANDLE hContact = db_find_first();
+ while (hContact != NULL)
+ {
+ if (IsMyContact(hContact))
+ {
+ if ( !db_get_b(hContact,WEATHERPROTONAME, "AutoUpdate",FALSE) || !AutoUpdate)
+ {
+ if (RemoveData) DBDataManage((HANDLE)hContact, WDBM_REMOVE, 0, 0);
+ UpdateListAdd(hContact);
+ }
+ }
+ hContact = db_find_next(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, NULL);
+}
+
+// update a single station
+// wParam = handle for the weather station that is going to be updated
+INT_PTR UpdateSingleStation(WPARAM wParam, LPARAM lParam)
+{
+ if (IsMyContact((HANDLE)wParam))
+ {
+ // add the station to the end of the update queue
+ UpdateListAdd((HANDLE)wParam);
+
+ // if it is not updating, then start the update thread process
+ // if it is updating, the stations just added to the queue will get
+ // updated by the already-running process
+ if ( !ThreadRunning)
+ mir_forkthread(UpdateThreadProc, NULL);
+ }
+
+ return 0;
+}
+
+// update a single station with removing the old data
+// wParam = handle for the weather station that is going to be updated
+INT_PTR UpdateSingleRemove(WPARAM wParam, LPARAM lParam)
+{
+ if (IsMyContact((HANDLE)wParam))
+ {
+ // add the station to the end of the update queue, and also remove old data
+ DBDataManage((HANDLE)wParam, WDBM_REMOVE, 0, 0);
+ UpdateListAdd((HANDLE)wParam);
+
+ // if it is not updating, then start the update thread process
+ // if it is updating, the stations just added to the queue will get updated by the already-running process
+ if ( !ThreadRunning)
+ mir_forkthread(UpdateThreadProc, NULL);
+ }
+
+ return 0;
+}
+
+// update all weather thread
+// this thread update each weather station from the queue
+void UpdateThreadProc(LPVOID hWnd)
+{
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+ if (ThreadRunning)
+ {
+ ReleaseMutex(hUpdateMutex);
+ return;
+ }
+ ThreadRunning = TRUE; // prevent 2 instance of this thread running
+ ReleaseMutex(hUpdateMutex);
+
+ // update weather by getting the first station from the queue until the queue is empty
+ while (UpdateListHead != NULL && !Miranda_Terminated())
+ UpdateWeather(UpdateGetFirst());
+
+ NetlibHttpDisconnect();
+
+ // exit the update thread
+ ThreadRunning = FALSE;
+}
+
+// the "Update All" menu item in main menu
+INT_PTR UpdateAllInfo(WPARAM wParam,LPARAM lParam)
+{
+ if ( !ThreadRunning) UpdateAll(FALSE, FALSE);
+ return 0;
+}
+
+// the "Update All" menu item in main menu and remove the old data
+INT_PTR UpdateAllRemove(WPARAM wParam,LPARAM lParam) {
+ if ( !ThreadRunning) UpdateAll(FALSE, TRUE);
+ return 0;
+}
+
+//============ GETTING WEATHER DATA ============
+
+// getting weather data and save them into the database
+// hContact = the contact to get the data
+int GetWeatherData(HANDLE hContact)
+{
+ // get eacnh part of the id's
+ TCHAR id[256];
+ GetStationID(hContact, id, SIZEOF(id));
+
+ // test ID format
+ TCHAR* szInfo = _tcschr(id, '/');
+ if (szInfo == NULL)
+ return INVALID_ID_FORMAT;
+
+ GetID(id);
+
+ TCHAR Svc[256];
+ GetStationID(hContact, Svc, SIZEOF(Svc));
+ GetSvc(Svc);
+
+ // check for invalid station
+ if (id[0] == 0) return INVALID_ID;
+ if (Svc[0] == 0) return INVALID_SVC;
+
+ // get the update strings (loaded to memory from ini files)
+ WIDATA *Data = GetWIData(Svc);
+ if (Data == NULL)
+ return SVC_NOT_FOUND; // the ini for the station cannot be found
+
+ WIDATAITEMLIST* Item;
+ WORD cond = NA;
+ char loc[256];
+ char* szId = mir_t2a( id );
+ for ( int i=0; i<4; ++i) {
+ // generate update URL
+ switch(i) {
+ case 0:
+ _snprintf(loc, SIZEOF(loc), Data->UpdateURL, szId);
+ break;
+
+ case 1:
+ _snprintf(loc, SIZEOF(loc), Data->UpdateURL2, szId);
+ break;
+
+ case 2:
+ _snprintf(loc, SIZEOF(loc), Data->UpdateURL3, szId);
+ break;
+
+ case 3:
+ _snprintf(loc, SIZEOF(loc), Data->UpdateURL4, szId);
+ break;
+ }
+
+ if ( loc[0] == 0 )
+ continue;
+
+ // download the html file from the internet
+ TCHAR* szData = NULL;
+ int retval = InternetDownloadFile(loc, Data->Cookie, &szData);
+ if (retval != 0) {
+ mir_free(szData);
+ return retval;
+ }
+ if ( _tcsstr(szData, _T("Document Not Found")) != NULL) {
+ mir_free(szData);
+ return DOC_NOT_FOUND;
+ }
+
+ szInfo = szData;
+ Item = Data->UpdateData;
+
+ // begin parsing item by item
+ while (Item != NULL) {
+ if (Item->Item.Url[0] != 0 && Item->Item.Url[0] != (i + '1')) {
+ Item = Item->Next;
+ continue;
+ }
+
+ TCHAR 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 ( _tcscmp(Item->Item.Name, _T("Condition")) && _tcsicmp(Item->Item.Unit, _T("Cond")))
+ _tcscpy(DataValue, TranslateTS(DataValue));
+ break;
+
+ case WID_SET:
+ {
+ // for the "Set Data=" operation
+ DBVARIANT dbv;
+ TCHAR *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 = _tcsstr(str, _T(" & "));
+ if (chop == NULL)
+ chop = _tcschr(str, '\0');
+
+ stl = min(sizeof(str2)-1, (unsigned)(chop-str-2));
+ _tcsncpy(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)) {
+ _tcsncat(DataValue, dbv.ptszVal, SIZEOF(DataValue) - _tcslen(DataValue));
+ DataValue[SIZEOF(DataValue)-1] = 0;
+ db_free(&dbv);
+ }
+ break;
+
+ case'\"': // constant, add it to the result string
+ _tcsncat(DataValue, TranslateTS(str2), SIZEOF(DataValue) - _tcslen(DataValue));
+ DataValue[SIZEOF(DataValue)-1] = 0;
+ break;
+ }
+
+ // remove the front part of the string that is done and continue parsing
+ str = chop + 3;
+ } while (chop[0] && str[0]);
+
+ if ( !hasvar) ConvertDataValue(&Item->Item, DataValue);
+ break;
+ }
+ case WID_BREAK:
+ {
+ // for the "Break Data=" operation
+ DBVARIANT dbv;
+ if ( !DBGetData(hContact, _T2A(Item->Item.Start), &dbv)) {
+ _tcsncpy(DataValue, dbv.ptszVal, SIZEOF(DataValue));
+ DataValue[SIZEOF(DataValue)-1] = 0;
+ db_free(&dbv);
+ }
+ else {
+ DataValue[0] = 0;
+ break; // do not continue if the source is invalid
+ }
+
+ // generate the strings
+ TCHAR* end = _tcsstr(DataValue, Item->Item.Break);
+ if (end == NULL) {
+ DataValue[0] = 0;
+ break; // exit if break string is not found
+ }
+ *end = '\0';
+ end += _tcslen(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_ts(hContact, WEATHERCONDITION, _T2A(Item->Item.End), end);
+ break;
+ } }
+
+ // don't store data if it is not available
+ if ((DataValue[0] != 0 && _tcscmp(DataValue, NODATA) &&
+ _tcscmp(DataValue, TranslateTS(NODATA)) && _tcscmp(Item->Item.Name, _T("Ignore"))) ||
+ ( !_tcscmp(Item->Item.Name, _T("Alert")) && i == 0))
+ {
+ // temporary workaround for mToolTip to show feel-like temperature
+ if ( !_tcscmp(Item->Item.Name, _T("Feel")))
+ db_set_ts(hContact, WEATHERCONDITION, "Heat Index", DataValue);
+ GetStationID(hContact, Svc, SIZEOF(Svc));
+ if ( !_tcscmp(Svc, opt.Default))
+ db_set_ts(NULL, DEFCURRENTWEATHER, _T2A(Item->Item.Name), DataValue);
+ if ( !_tcscmp(Item->Item.Name, _T("Condition"))) {
+ TCHAR buf[128], *cbuf;
+ mir_sntprintf(buf, SIZEOF(buf), _T("#%s Weather"), DataValue);
+ cbuf = TranslateTS(buf);
+ if (cbuf[0] == '#')
+ cbuf = TranslateTS(DataValue);
+ db_set_ts(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), cbuf);
+ CharLowerBuff(DataValue, (DWORD)_tcslen(DataValue));
+ cond = GetIcon(DataValue, Data);
+ }
+ else if ( _tcsicmp(Item->Item.Unit, _T("Cond")) == 0) {
+ TCHAR buf[128], *cbuf;
+ mir_sntprintf(buf, SIZEOF(buf), _T("#%s Weather"), DataValue);
+ cbuf = TranslateTS(buf);
+ if (cbuf[0] == '#')
+ cbuf = TranslateTS(DataValue);
+ db_set_ts(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), cbuf);
+ }
+ else db_set_ts(hContact, WEATHERCONDITION, _T2A(Item->Item.Name), DataValue);
+ }
+ Item = Item->Next;
+ }
+ mir_free(szData);
+ }
+
+ // assign condition icon
+ db_set_w(hContact, WEATHERPROTONAME, "StatusIcon", cond);
+ db_set_ts(hContact, WEATHERPROTONAME, "MirVer", Data->DisplayName);
+ return 0;
+}
+
+//============ UPDATE TIMERS ============
+
+// main auto-update timer
+void CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ // only run if it is not current updating and the auto update option is enabled
+ if ( !ThreadRunning && opt.CAutoUpdate && !Miranda_Terminated() &&
+ (!opt.NoProtoCondition || status == ID_STATUS_ONLINE))
+ UpdateAll(TRUE, FALSE);
+}
+
+// temporary timer for first run
+// when this is run, it kill the old startup timer and create the permenant one above
+void CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ KillTimer(NULL, timerId);
+ ThreadRunning = FALSE;
+
+ if ( !Miranda_Terminated()) {
+ if (opt.StartupUpdate && !opt.NoProtoCondition)
+ UpdateAll(FALSE, FALSE);
+ timerId = SetTimer(NULL, 0, ((int)opt.UpdateTime)*60000, (TIMERPROC)timerProc);
+ }
+}
+
diff --git a/plugins/Weather/src/weather_userinfo.cpp b/plugins/Weather/src/weather_userinfo.cpp
new file mode 100644
index 0000000000..1d716a58ef
--- /dev/null
+++ b/plugins/Weather/src/weather_userinfo.cpp
@@ -0,0 +1,402 @@
+/*
+Weather Protocol plugin for Miranda IM
+Copyright (c) 2012 Miranda NG Team
+Copyright (c) 2005-2011 Boris Krasnovskiy All Rights Reserved
+Copyright (c) 2002-2005 Calvin Che
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+/*
+This file contain the source that is related to display contact
+information, including the one shows in user detail and the brief
+information
+*/
+
+#include "weather.h"
+
+extern INT_PTR CALLBACK DlgProcINIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//============ CONTACT INFORMATION ============
+
+// initialize user info
+// lParam = current contact
+int UserInfoInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.position = 100000000;
+ odp.ptszTitle = _T(WEATHERPROTONAME);
+
+ if (lParam == 0)
+ {
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO);
+ odp.pfnDlgProc = DlgProcINIPage;
+ odp.flags = ODPF_TCHAR;
+ UserInfo_AddPage(wParam, &odp);
+ }
+ else
+ {
+ // check if it is a weather contact
+ if (IsMyContact((HANDLE)lParam))
+ {
+ // register the contact info page
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_USERINFO);
+ odp.pfnDlgProc = DlgProcUIPage;
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ UserInfo_AddPage(wParam, &odp);
+ }
+ }
+
+ return 0;
+}
+
+// dialog process for the weather tab under user info
+// lParam = current contact
+INT_PTR CALLBACK DlgProcUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WEATHERINFO w;
+ TCHAR str[MAX_TEXT_SIZE];
+
+ HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SendMessage(GetDlgItem(hwndDlg,IDC_MOREDETAIL), BUTTONSETASFLATBTN, TRUE, 0);
+ // save the contact handle for later use
+ hContact = (HANDLE)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact);
+ // load weather info for the contact
+ w = LoadWeatherInfo((HANDLE)lParam);
+ SetDlgItemText(hwndDlg, IDC_INFO1, GetDisplay(&w, TranslateT("Current condition for %n"), str));
+
+ SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON,
+ (WPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME,
+ db_get_w(hContact, WEATHERPROTONAME, "StatusIcon",0)), 0);
+
+ { // bold and enlarge the current condition
+ LOGFONT lf;
+ HFONT hNormalFont = (HFONT)SendDlgItemMessage(hwndDlg,IDC_INFO2,WM_GETFONT,0,0);
+ GetObject(hNormalFont,sizeof(lf),&lf);
+ lf.lfWeight = FW_BOLD;
+ lf.lfWidth = 7;
+ lf.lfHeight = 15;
+ SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_SETFONT, (WPARAM)CreateFontIndirect(&lf), 0);
+ }
+ // set the text for displaying other current weather conditions data
+ GetDisplay(&w, _T("%c %t"), str);
+ SetDlgItemText(hwndDlg, IDC_INFO2, str);
+ SetDlgItemText(hwndDlg, IDC_INFO3, w.feel);
+ SetDlgItemText(hwndDlg, IDC_INFO4, w.pressure);
+ GetDisplay(&w, _T("%i %w"), str);
+ SetDlgItemText(hwndDlg, IDC_INFO5, str);
+ SetDlgItemText(hwndDlg, IDC_INFO6, w.dewpoint);
+ SetDlgItemText(hwndDlg, IDC_INFO7, w.sunrise);
+ SetDlgItemText(hwndDlg, IDC_INFO8, w.sunset);
+ SetDlgItemText(hwndDlg, IDC_INFO9, w.high);
+ SetDlgItemText(hwndDlg, IDC_INFO10, w.low);
+ GetDisplay(&w, TranslateT("Last update on: %u"), str);
+ SetDlgItemText(hwndDlg, IDC_INFO11, str);
+ SetDlgItemText(hwndDlg, IDC_INFO12, w.humid);
+ SetDlgItemText(hwndDlg, IDC_INFO13, w.vis);
+ break;
+
+ case WM_DESTROY:
+ Skin_ReleaseIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_INFOICON, STM_SETICON, 0, 0));
+ DeleteObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_INFO2, WM_GETFONT, 0, 0));
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_MOREDETAIL:
+ {
+ HWND hMoreDataDlg = WindowList_Find(hDataWindowList, hContact);
+ if (hMoreDataDlg == NULL)
+ hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL,
+ DlgProcMoreData, (LPARAM)hContact);
+ else
+ {
+ SetForegroundWindow(hMoreDataDlg);
+ SetFocus(hMoreDataDlg);
+ }
+ ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 0);
+ ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 1);
+ break;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+//============ BRIEF INFORMATION ============
+
+static int BriefDlgResizer(HWND hwnd, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ switch(urc->wId)
+ {
+ case IDC_HEADERBAR:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH;
+
+ case IDC_MTEXT:
+ case IDC_DATALIST:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+ case IDC_MUPDATE:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+
+ case IDC_MTOGGLE:
+ case IDC_MWEBPAGE:
+ case IDCANCEL:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+ }
+ return RD_ANCHORX_LEFT|RD_ANCHORY_TOP;
+}
+
+
+
+// dialog process for more data in the user info window
+// lParam = contact handle
+INT_PTR CALLBACK DlgProcMoreData(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static const unsigned tabstops = 48;
+ HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ // save the contact handle for later use
+ hContact = (HANDLE)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact);
+
+ SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_AUTOURLDETECT, (WPARAM) TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETEVENTMASK, 0, ENM_LINK);
+ SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETMARGINS, EC_LEFTMARGIN, 5);
+ SendDlgItemMessage(hwndDlg, IDC_MTEXT, EM_SETTABSTOPS, 1, (LPARAM)&tabstops);
+
+ // get the list to display
+ {
+ LV_COLUMN lvc = { 0 };
+ HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST);
+ RECT aRect = { 0 };
+ GetClientRect(hList, &aRect);
+
+ // managing styles
+ lvc.mask = LVCF_WIDTH | LVCF_TEXT;
+ ListView_SetExtendedListViewStyleEx(hList,
+ LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP,
+ LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
+
+ // inserting columns
+ lvc.cx = LIST_COLUMN;
+ lvc.pszText = TranslateT("Variable");
+ ListView_InsertColumn(hList, 0, &lvc);
+
+ lvc.cx = aRect.right - LIST_COLUMN - GetSystemMetrics(SM_CXVSCROLL) - 3;
+ lvc.pszText = TranslateT("Information");
+ ListView_InsertColumn(hList, 1, &lvc);
+
+ // inserting data
+ SendMessage(hwndDlg, WM_UPDATEDATA, 0, 0);
+ }
+ TranslateDialogDefault(hwndDlg);
+
+ // prevent dups of the window
+ WindowList_Add(hDataWindowList, hwndDlg, hContact);
+
+ // restore window position
+ Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_");
+ return TRUE;
+
+ case WM_UPDATEDATA:
+ ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_DATALIST));
+ LoadBriefInfoText(hwndDlg, hContact);
+ DBDataManage(hContact, WDBM_DETAILDISPLAY, (WPARAM)hwndDlg, 0);
+
+ // set icons
+ {
+ WORD statusIcon = db_get_w(hContact, WEATHERPROTONAME, "StatusIcon", 0);
+
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIconBig(WEATHERPROTONAME, statusIcon)));
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(WEATHERPROTONAME, statusIcon)));
+ }
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_HEADERBAR), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ break;
+
+ case WM_SIZE:
+ {
+ RECT rc;
+ HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST);
+ GetWindowRect(hList, &rc);
+ ListView_SetColumnWidth(hList, 1, ListView_GetColumnWidth(hList, 1) +
+ (int)LOWORD(lParam) - (rc.right - rc.left));
+ }
+ {
+ UTILRESIZEDIALOG urd = {0};
+ urd.cbSize = sizeof(urd);
+ urd.hwndDlg = hwndDlg;
+ urd.hInstance = hInst;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_BRIEF);
+ urd.pfnResizer = BriefDlgResizer;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;
+
+ // The minimum width in points
+ mmi->ptMinTrackSize.x = 350;
+ // The minimum height in points
+ mmi->ptMinTrackSize.y = 300;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ // close the info window
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_MUPDATE:
+ {
+ LV_ITEM lvi = {0};
+ HWND hList = GetDlgItem(hwndDlg, IDC_DATALIST);
+
+ // update current data
+ // set the text to "updating"
+ SetDlgItemText(hwndDlg, IDC_MTEXT, TranslateT("Retrieving new data, please wait..."));
+ ListView_DeleteAllItems(hList);
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.lParam = 1;
+ lvi.pszText = _T("");
+ lvi.iItem = ListView_InsertItem(hList, &lvi);
+ lvi.pszText = TranslateT("Retrieving new data, please wait...");
+ ListView_SetItemText(hList, lvi.iItem, 1, lvi.pszText);
+ UpdateSingleStation((WPARAM)hContact, 0);
+ break;
+ }
+
+ case IDC_MWEBPAGE:
+ LoadForecast((WPARAM)hContact, 0); // read complete forecast
+ break;
+
+ case IDC_MTOGGLE:
+ if (IsWindowVisible(GetDlgItem(hwndDlg,IDC_DATALIST)))
+ 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;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNmhdr = (LPNMHDR)lParam;
+ if (pNmhdr->idFrom == IDC_MTEXT && pNmhdr->code == EN_LINK)
+ {
+ ENLINK *enlink = (ENLINK *) lParam;
+ TEXTRANGE tr;
+ switch (enlink->msg)
+ {
+ case WM_LBUTTONUP:
+ tr.chrg = enlink->chrg;
+ tr.lpstrText = ( LPTSTR )mir_alloc( sizeof(TCHAR)*(tr.chrg.cpMax - tr.chrg.cpMin + 8));
+ SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW | OUF_TCHAR, (LPARAM) tr.lpstrText);
+ mir_free(tr.lpstrText);
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
+
+ Utils_SaveWindowPosition(hwndDlg, NULL, WEATHERPROTONAME, "BriefInfo_");
+ WindowList_Remove(hDataWindowList, hwndDlg);
+ break;
+ }
+
+ return FALSE;
+}
+
+// set the title of the dialog and on the which rectangle
+// also load brief info into message box
+void LoadBriefInfoText(HWND hwndDlg, HANDLE hContact)
+{
+ WEATHERINFO winfo;
+ TCHAR str[4096], str2[4096];
+
+ // load weather information from the contact into the WEATHERINFO struct
+ winfo = LoadWeatherInfo(hContact);
+ // check if data exist. If not, display error message box
+ if ( !(BOOL)db_get_b(hContact, WEATHERPROTONAME, "IsUpdated", FALSE))
+ _tcscpy(str, TranslateT("No information available.\r\nPlease update weather condition first."));
+ else
+ // set the display text and show the message box
+ GetDisplay(&winfo, opt.bText, str);
+ SetDlgItemText(hwndDlg, IDC_MTEXT, str);
+
+ GetDisplay(&winfo, opt.bTitle, str);
+ SetWindowText(hwndDlg, str);
+ GetDisplay(&winfo, _T("%c, %t"), str);
+ mir_sntprintf(str2, SIZEOF(str2), _T("%s\n%s"), winfo.city, str);
+ SetDlgItemText(hwndDlg, IDC_HEADERBAR, str2);
+}
+
+// show brief information dialog
+// wParam = current contact
+int BriefInfo(WPARAM wParam, LPARAM lParam)
+{
+ // make sure that the contact is actually a weather one
+ if (IsMyContact((HANDLE)wParam))
+ {
+ HWND hMoreDataDlg = WindowList_Find(hDataWindowList,(HANDLE)wParam);
+ if (hMoreDataDlg != NULL)
+ {
+ SetForegroundWindow(hMoreDataDlg);
+ SetFocus(hMoreDataDlg);
+ }
+ else
+ {
+ hMoreDataDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_BRIEF), NULL, DlgProcMoreData,
+ (LPARAM)wParam);
+ }
+ ShowWindow(GetDlgItem(hMoreDataDlg, IDC_DATALIST), 0);
+ ShowWindow(GetDlgItem(hMoreDataDlg, IDC_MTEXT), 1);
+ SetDlgItemText(hMoreDataDlg, IDC_MTOGGLE, TranslateT("More Info"));
+ return 1;
+ }
+ return 0;
+}
+
+INT_PTR BriefInfoSvc(WPARAM wParam, LPARAM lParam)
+{
+ return BriefInfo(wParam, lParam);
+}
diff --git a/plugins/Weather/weather_10.vcxproj b/plugins/Weather/weather_10.vcxproj
new file mode 100644
index 0000000000..d09c5d1cb1
--- /dev/null
+++ b/plugins/Weather/weather_10.vcxproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>Weather</ProjectName>
+ <ProjectGuid>{6BFE3E13-BD5D-4C1C-BB29-A82FB51A16CE}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>weather.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x72030000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeaderFile>weather.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x72030000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeaderFile>weather.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x72030000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeaderFile>weather.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x72030000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\weather.cpp" />
+ <ClCompile Include="src\stdafx.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\weather_addstn.cpp" />
+ <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_icons.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_svcs.cpp" />
+ <ClCompile Include="src\weather_update.cpp" />
+ <ClCompile Include="src\weather_userinfo.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\version.h" />
+ <ClInclude Include="src\weather.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Weather/weather_10.vcxproj.filters b/plugins/Weather/weather_10.vcxproj.filters
new file mode 100644
index 0000000000..385b06f839
--- /dev/null
+++ b/plugins/Weather/weather_10.vcxproj.filters
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{ae98b833-66fd-4d03-8883-da86b699da8e}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{229b056a-ba07-4698-ad86-26548bd87e32}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Documentations">
+ <UniqueIdentifier>{3433a4a3-b1af-4761-ab98-0d4ada361b3a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{4be16e1a-70ca-4330-b259-db32ec58dcc0}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\weather.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_addstn.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_contacts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_conv.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <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_icons.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>
+ <ClCompile Include="src\weather_opt.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_popup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_svcs.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_update.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\weather_userinfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\weather.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file