summaryrefslogtreecommitdiff
path: root/plugins/SRMM
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
commitf3d44bc057201407373012b7f682881bda7b3d98 (patch)
treeddf031a82529c84e13222131cf184ecf176d3954 /plugins/SRMM
parentc2d827972a16f1710406d15e58304aecc4e1c9b5 (diff)
some includes restored, mir_full.sln updated, some renaming of folders and projects
git-svn-id: http://svn.miranda-ng.org/main/trunk@140 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/SRMM')
-rw-r--r--plugins/SRMM/Docs/srmm-license.txt340
-rw-r--r--plugins/SRMM/Docs/srmm-readme.txt130
-rw-r--r--plugins/SRMM/Docs/srmm-translation.txt94
-rw-r--r--plugins/SRMM/cmdlist.c168
-rw-r--r--plugins/SRMM/cmdlist.h51
-rw-r--r--plugins/SRMM/commonheaders.h80
-rw-r--r--plugins/SRMM/globals.c188
-rw-r--r--plugins/SRMM/globals.h62
-rw-r--r--plugins/SRMM/msgdialog.c2042
-rw-r--r--plugins/SRMM/msglog.c649
-rw-r--r--plugins/SRMM/msgoptions.c725
-rw-r--r--plugins/SRMM/msgs.c595
-rw-r--r--plugins/SRMM/msgs.h217
-rw-r--r--plugins/SRMM/msgtimedout.c112
-rw-r--r--plugins/SRMM/res/dragcopy.curbin0 -> 326 bytes
-rw-r--r--plugins/SRMM/res/dropuser.curbin0 -> 1086 bytes
-rw-r--r--plugins/SRMM/res/hyperlin.curbin0 -> 326 bytes
-rw-r--r--plugins/SRMM/res/incoming.icobin0 -> 1246 bytes
-rw-r--r--plugins/SRMM/res/notice.icobin0 -> 1246 bytes
-rw-r--r--plugins/SRMM/res/outgoing.icobin0 -> 1246 bytes
-rw-r--r--plugins/SRMM/resource.h98
-rw-r--r--plugins/SRMM/resource.rc361
-rw-r--r--plugins/SRMM/richutil.c269
-rw-r--r--plugins/SRMM/richutil.h34
-rw-r--r--plugins/SRMM/srmm.c88
-rw-r--r--plugins/SRMM/srmm_10.vcxproj341
-rw-r--r--plugins/SRMM/srmm_10.vcxproj.filters178
-rw-r--r--plugins/SRMM/statusicon.c221
-rw-r--r--plugins/SRMM/statusicon.h14
-rw-r--r--plugins/SRMM/version.h5
30 files changed, 7062 insertions, 0 deletions
diff --git a/plugins/SRMM/Docs/srmm-license.txt b/plugins/SRMM/Docs/srmm-license.txt
new file mode 100644
index 0000000000..ca3fe8d547
--- /dev/null
+++ b/plugins/SRMM/Docs/srmm-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) 19yy <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) 19yy 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/SRMM/Docs/srmm-readme.txt b/plugins/SRMM/Docs/srmm-readme.txt
new file mode 100644
index 0000000000..d53888eb88
--- /dev/null
+++ b/plugins/SRMM/Docs/srmm-readme.txt
@@ -0,0 +1,130 @@
+
+ SRMM Plugin for Miranda IM
+ __________________________
+
+
+About
+-----
+This Miranda IM plugin allows you to send and receive instant messages.
+
+
+Installation
+------------
+Simply copy "srmm.dll" into your Miranda IM plugin directory (usually
+"C:\Program Files\Miranda IM\Plugins\") and restart Miranda IM.
+
+
+Changes
+-------
+2.6.0.0
+ - Improved RTL support
+ - Removed offline from autopopup options
+
+2.5.0.0
+ - RTL support added
+ - Updated icons
+
+2.4.0.0
+ - Message API fix (MS_MSG_GETWINDOWDATA)
+
+2.3.0.0
+ - Drag/drop didn't always work from message control
+
+2.2.0.0
+ - Log window didn't scroll correctly when avatar was loaded
+ - Added show seconds option to log window timestamp
+ - Drag and drop file transfer support
+ - Updated internal API to 0.0.0.3
+ - Fix some possible buffer overflow issues
+ - Hide typing notification when user goes offline
+ - Auto popup option is now set per status
+
+2.1.0.0
+ - Show avatars for protocols that support them
+ - Show user menu by clicking user name
+ - Copy user name by shift clicking username
+ - Log window is drawn using XP theme if possible
+
+2.0.0.0
+ - Remove send to multiple "feature"
+ - Remove single message mode
+ - Remove file and url events from message log
+ - Cache database reads when showing messages in the log
+ - Show separate incoming/outgoing icons for messages with "Show Icons" option
+ - Show status changes in the message window
+ - Message area supports Ctrl+Up/Down to scroll through past messages
+ - Close message dialog with Ctrl+w
+ - Fixed some focus/flash issues
+ - Added option to delete temporary contacts on window close
+ - Support window api v0.0.0.1
+ - Retry dialog caused crash
+
+1.0.4.2
+ - Typing Notify options didn't enable/disable correctly
+
+1.0.4.1
+ - Really fix new line issue
+
+1.0.4.0
+ - Minor log changes and url detection cleanup
+
+1.0.3.0
+ - Added option to see user is typing notifications with no window open
+ - Send to multiple list respects the contact list "Hide Empty Groups" setting
+ - Send to multiple list in single mode was cut off
+ - Minor new line issue
+
+1.0.2.0
+ - Possible memory corruption
+
+1.0.1.0
+ - Initial release
+
+Todo:
+ - Font size fixes (muldiv, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_1wmq.asp)
+ - Cache fonts
+ - Add "old" event fonts
+
+
+Thanks
+------
+Thanks to Matrix and Valkyre who designed and created the icons.
+
+
+Support and bug reporting
+-------------------------
+We cannot give support on e-mail or ICQ. Please visit the Miranda IM help page at
+http://www.miranda-im.org/help/ if you need help with this plugin.
+
+If the help page does answer your question, visit the Miranda IM support forum at:
+http://forums.miranda-im.org and we will try to assist you.
+
+If you want to report a bug, please do so in the official bugtracker at:
+http://bugs.miranda-im.org/
+
+
+
+Contact
+-------
+Current maintainer is Robert Rainwater.
+E-mail: rainwater at miranda-im.org
+
+
+
+License and Copyright
+---------------------
+Copyright (C) 2001-2005 Robert Rainwater, Martin Öberg, Richard Hughes
+
+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.
diff --git a/plugins/SRMM/Docs/srmm-translation.txt b/plugins/SRMM/Docs/srmm-translation.txt
new file mode 100644
index 0000000000..782bb9dcda
--- /dev/null
+++ b/plugins/SRMM/Docs/srmm-translation.txt
@@ -0,0 +1,94 @@
+Miranda Language Pack Version 1
+Locale: 0809
+Authors: Miranda IM Development Team
+Author-email: project-info@miranda-im.org
+Last-Modified-Using: Miranda IM 0.6.1
+Plugins-included:
+
+; Generated by lpgen on Thu Jan 11 20:52:59 2007
+; Translations: 74
+
+; msgdialog.c
+;[Add Contact Permanently to List]
+;[User Menu]
+;[View User's Details]
+;[View User's History]
+;[The message send timed out.]
+
+; msgoptions.c
+;[Show balloon popup (unsupported system)]
+
+; msgs.c
+;[%s is typing a message]
+;[Typing Notification]
+;[Message from %s]
+;[&Message]
+;[Miranda could not load the built-in message module, riched20.dll is missing. If you are using Windows 95 or WINE please make sure you have riched20.dll installed. Press 'Yes' to continue loading Miranda.]
+;[Information]
+;[Messages]
+;[Incoming (Focused Window)]
+;[Incoming (Unfocused Window)]
+;[Incoming (New Session)]
+;[Outgoing]
+
+; msgtimedout.c
+;[An unknown error has occured.]
+
+; resource.rc
+;[Close the message window on send]
+;[Minimize the message window on send]
+;[Use the contact's status icon as the window icon]
+;[Save the window size and location individually for each contact]
+;[Cascade new windows]
+;[Show 'Send' button]
+;[Show username on top row]
+;[Show toolbar buttons on top row]
+;[Send message on double 'Enter']
+;[Send message on 'Enter']
+;[Show character count]
+;[Support control up/down in message area to show previously sent messages]
+;[Delete temporary contacts when closing message window]
+;[Enable avatar support in the message window]
+;[Limit avatar height to ]
+;[&D]
+;[&H]
+;[Show icons]
+;[Show names]
+;[Show timestamp]
+;[Show dates]
+;[Load unread events only]
+;[Load number of previous events]
+;[Spin1]
+;[Load previous events less than]
+;[Show status changes]
+;[Show seconds]
+;[Show typing notifications when a user is typing a message]
+;[Update inactive message window icons when a user is typing]
+;[Show typing notification when no message dialog is open]
+;[Flash in the system tray and in the contact list]
+;[Show balloon popup]
+;[Try again]
+;[&Send]
+;[Cancel]
+;[Close]
+;[Show warning when message has not been received after]
+;[seconds.]
+;[pixels.]
+;[Automatically popup window when:]
+;[An error has occured. The protocol reported the following error:]
+;[minutes old]
+;[Send typing notifications to the following users when you are typing a message to them:]
+;[Message Window Options]
+;[Message Window Event Log]
+;[Load History Events]
+;[Typing Notification Options]
+;[Send Error]
+;[Message Session]
+;[C&lear Log]
+;[&Copy]
+;[Co&py All]
+;[Select &All]
+;[Open in &new window]
+;[&Open in existing window]
+;[&Copy link]
+
diff --git a/plugins/SRMM/cmdlist.c b/plugins/SRMM/cmdlist.c
new file mode 100644
index 0000000000..88b1055ca2
--- /dev/null
+++ b/plugins/SRMM/cmdlist.c
@@ -0,0 +1,168 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+
+int tcmdlist_append(SortedList *list, TCHAR *data)
+{
+ TCmdList *new_list;
+
+ if (!data)
+ return list->realCount - 1;
+
+ if (list->realCount >= 20)
+ {
+ TCmdList* n = (TCmdList*)list->items[0];
+ mir_free(n->szCmd);
+ mir_free(n);
+ li.List_Remove(list, 0);
+ }
+
+ new_list = mir_alloc(sizeof(TCmdList));
+ new_list->szCmd = mir_tstrdup(data);
+
+ li.List_InsertPtr(list, new_list);
+
+ return list->realCount - 1;
+}
+
+void tcmdlist_free(SortedList *list)
+{
+ int i;
+ TCmdList** n = (TCmdList**)list->items;
+
+ for (i = 0; i < list->realCount; ++i)
+ {
+ mir_free(n[i]->szCmd);
+ mir_free(n[i]);
+ }
+ li.List_Destroy(list);
+ mir_free(list);
+}
+
+static SortedList msgQueue = { NULL, 0, 0, 5, NULL };
+static CRITICAL_SECTION csMsgQueue;
+static UINT_PTR timerId;
+
+void MessageFailureProcess(TMsgQueue *item, const char* err);
+
+static VOID CALLBACK MsgTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ int i, ntl = 0;
+ TMsgQueue **tmlst = NULL;
+
+ EnterCriticalSection(&csMsgQueue);
+
+ for (i = 0; i < msgQueue.realCount; ++i)
+ {
+ TMsgQueue *item = (TMsgQueue*)msgQueue.items[i];
+ if (dwTime - item->ts > g_dat->msgTimeout)
+ {
+ if (!ntl)
+ tmlst = (TMsgQueue**)alloca((msgQueue.realCount - i) * sizeof(TMsgQueue*));
+ tmlst[ntl++] = item;
+
+ li.List_Remove(&msgQueue, i--);
+ }
+ }
+ LeaveCriticalSection(&csMsgQueue);
+
+ for (i = 0; i < ntl; ++i)
+ MessageFailureProcess(tmlst[i], LPGEN("The message send timed out."));
+}
+
+void msgQueue_add(HANDLE hContact, HANDLE id, const TCHAR* szMsg, HANDLE hDbEvent)
+{
+ TMsgQueue *item;
+
+ item = mir_alloc(sizeof(TMsgQueue));
+ item->hContact = hContact;
+ item->id = id;
+ item->szMsg = mir_tstrdup(szMsg);
+ item->hDbEvent = hDbEvent;
+ item->ts = GetTickCount();
+
+ EnterCriticalSection(&csMsgQueue);
+ if (!msgQueue.realCount && !timerId)
+ timerId = SetTimer(NULL, 0, 5000, MsgTimer);
+ li.List_InsertPtr(&msgQueue, item);
+ LeaveCriticalSection(&csMsgQueue);
+
+}
+
+void msgQueue_processack(HANDLE hContact, HANDLE id, BOOL success, const char* szErr)
+{
+ int i;
+ TMsgQueue* item = NULL;;
+
+ EnterCriticalSection(&csMsgQueue);
+
+ for (i = 0; i < msgQueue.realCount; ++i)
+ {
+ item = (TMsgQueue*)msgQueue.items[i];
+ if (item->hContact == hContact && item->id == id)
+ {
+ li.List_Remove(&msgQueue, i);
+
+ if (!msgQueue.realCount && timerId)
+ {
+ KillTimer(NULL, timerId);
+ timerId = 0;
+ }
+ break;
+ }
+ item = NULL;
+ }
+ LeaveCriticalSection(&csMsgQueue);
+
+ if (item)
+ {
+ if (success)
+ {
+ mir_free(item->szMsg);
+ mir_free(item);
+ }
+ else
+ MessageFailureProcess(item, szErr);
+ }
+}
+
+void msgQueue_init(void)
+{
+ InitializeCriticalSection(&csMsgQueue);
+}
+
+void msgQueue_destroy(void)
+{
+ int i;
+
+ EnterCriticalSection(&csMsgQueue);
+
+ for (i = 0; i < msgQueue.realCount; ++i)
+ {
+ TMsgQueue* item = (TMsgQueue*)msgQueue.items[i];
+ mir_free(item->szMsg);
+ mir_free(item);
+ }
+ li.List_Destroy(&msgQueue);
+
+ LeaveCriticalSection(&csMsgQueue);
+
+ DeleteCriticalSection(&csMsgQueue);
+}
diff --git a/plugins/SRMM/cmdlist.h b/plugins/SRMM/cmdlist.h
new file mode 100644
index 0000000000..add3d4987b
--- /dev/null
+++ b/plugins/SRMM/cmdlist.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#ifndef SRMM_CMDLIST_H
+#define SRMM_CMDLIST_H
+
+typedef struct _TCmdList
+{
+ TCHAR *szCmd;
+}
+TCmdList;
+
+int tcmdlist_append(SortedList *list, TCHAR *data);
+void tcmdlist_free(SortedList *list);
+
+__inline TCHAR* tcmdlist_getitem(SortedList *list, int ind)
+{ return ((TCmdList*)list->items[ind])->szCmd; }
+
+
+typedef struct _TMsgQueue
+{
+ HANDLE id;
+ HANDLE hContact;
+ TCHAR* szMsg;
+ HANDLE hDbEvent;
+ unsigned ts;
+}
+TMsgQueue;
+
+void msgQueue_add(HANDLE hContact, HANDLE id, const TCHAR* szMsg, HANDLE hDbEvent);
+void msgQueue_processack(HANDLE hContact, HANDLE id, BOOL success, const char* szErr);
+void msgQueue_init(void);
+void msgQueue_destroy(void);
+
+#endif
diff --git a/plugins/SRMM/commonheaders.h b/plugins/SRMM/commonheaders.h
new file mode 100644
index 0000000000..fec878afd7
--- /dev/null
+++ b/plugins/SRMM/commonheaders.h
@@ -0,0 +1,80 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#define MIRANDA_VER 0x0A00
+
+#define _WIN32_WINNT 0x0501
+#define _WIN32_IE 0x0501
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <m_stdhdr.h>
+
+#include <windows.h>
+#include <windowsx.h>
+#include <ole2.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <vssym32.h>
+
+#include <time.h>
+
+#include "resource.h"
+
+#include <win2k.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_icolib.h>
+#include <m_fontservice.h>
+#include <m_timezones.h>
+#include <m_avatars.h>
+
+#include "cmdlist.h"
+#include "msgs.h"
+#include "globals.h"
+#include "richutil.h"
+#include "version.h"
+
+#if _MSC_VER >= 1500
+ #define wEffects wReserved
+#endif
+
+extern struct LIST_INTERFACE li;
+extern HINSTANCE g_hInst;
+
+
diff --git a/plugins/SRMM/globals.c b/plugins/SRMM/globals.c
new file mode 100644
index 0000000000..11e7606158
--- /dev/null
+++ b/plugins/SRMM/globals.c
@@ -0,0 +1,188 @@
+/*
+Copyright 2000-2012 Miranda /IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+
+struct GlobalMessageData *g_dat;
+static HANDLE g_hooks[4];
+
+static int dbaddedevent(WPARAM wParam, LPARAM lParam);
+static int ackevent(WPARAM wParam, LPARAM lParam);
+static int AvatarChanged(WPARAM wParam, LPARAM lParam);
+
+typedef struct IconDefStruct
+{
+ const char *szName;
+ const char *szDescr;
+ int defIconID;
+} IconList;
+
+static const IconList iconList[] =
+{
+ { "INCOMING", LPGEN("Incoming message (10x10)"), IDI_INCOMING },
+ { "OUTGOING", LPGEN("Outgoing message (10x10)"), IDI_OUTGOING },
+ { "NOTICE", LPGEN("Notice (10x10)"), IDI_NOTICE },
+};
+
+
+HANDLE hIconLibItem[SIZEOF(iconList)];
+
+static void InitIcons(void)
+{
+ TCHAR szFile[MAX_PATH];
+ char szSettingName[100];
+ SKINICONDESC sid = {0};
+ unsigned i;
+
+ GetModuleFileName(g_hInst, szFile, SIZEOF(szFile));
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszDefaultFile = szFile;
+ sid.pszName = szSettingName;
+ sid.pszSection = LPGEN("Messaging");
+ sid.flags = SIDF_PATH_TCHAR;
+ sid.cx = 10; sid.cy = 10;
+
+ for (i = 0; i < SIZEOF(iconList); i++)
+ {
+ mir_snprintf(szSettingName, sizeof(szSettingName), "SRMM_%s", iconList[i].szName);
+ sid.pszDescription = (char*)iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ hIconLibItem[i] = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+}
+
+static int IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ FreeMsgLogIcons();
+ LoadMsgLogIcons();
+
+ return 0;
+}
+
+void InitGlobals()
+{
+ g_dat = (struct GlobalMessageData *)mir_alloc(sizeof(struct GlobalMessageData));
+ g_dat->hMessageWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ g_hooks[0] = HookEvent(ME_DB_EVENT_ADDED, dbaddedevent);
+ g_hooks[1] = HookEvent(ME_PROTO_ACK, ackevent);
+ g_hooks[2] = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged);
+ g_hooks[3] = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged);
+
+ ReloadGlobals();
+ InitIcons();
+}
+
+void FreeGlobals()
+{
+ int i;
+ mir_free(g_dat);
+
+ for (i=0; i < SIZEOF(g_hooks); ++i)
+ if (g_hooks[i])
+ UnhookEvent(g_hooks[i]);
+}
+
+void ReloadGlobals()
+{
+ g_dat->flags = 0;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, SRMSGDEFSET_SHOWINFOLINE))
+ g_dat->flags |= SMF_SHOWINFO;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, SRMSGDEFSET_SHOWBUTTONLINE))
+ g_dat->flags |= SMF_SHOWBTNS;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, SRMSGDEFSET_SENDBUTTON))
+ g_dat->flags |= SMF_SENDBTN;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING))
+ g_dat->flags |= SMF_SHOWTYPING;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN))
+ g_dat->flags |= SMF_SHOWTYPINGWIN;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN))
+ g_dat->flags |= SMF_SHOWTYPINGTRAY;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST))
+ g_dat->flags |= SMF_SHOWTYPINGCLIST;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS))
+ g_dat->flags |= SMF_SHOWICONS;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME))
+ g_dat->flags |= SMF_SHOWTIME;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, SRMSGDEFSET_AVATARENABLE))
+ g_dat->flags |= SMF_AVATAR;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE))
+ g_dat->flags |= SMF_SHOWDATE;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS))
+ g_dat->flags |= SMF_SHOWSECS;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES))
+ g_dat->flags |= SMF_HIDENAMES;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT))
+ g_dat->flags |= SMF_SHOWREADCHAR;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER))
+ g_dat->flags |= SMF_SENDONENTER;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER))
+ g_dat->flags |= SMF_SENDONDBLENTER;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE))
+ g_dat->flags |= SMF_AUTOCLOSE;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN))
+ g_dat->flags |= SMF_AUTOMIN;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN))
+ g_dat->flags |= SMF_TYPINGUNKNOWN;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT))
+ g_dat->flags |= SMF_CTRLSUPPORT;
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT))
+ g_dat->flags |= SMF_SHOWFORMAT;
+
+ g_dat->openFlags = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS);
+ g_dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT);
+
+ g_dat->msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT);
+ if (g_dat->msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) g_dat->msgTimeout = SRMSGDEFSET_MSGTIMEOUT;
+}
+
+static int dbaddedevent(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if (hContact)
+ {
+ HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact);
+ if (h) SendMessage(h, HM_DBEVENTADDED, (WPARAM)hContact, lParam);
+ }
+ return 0;
+}
+
+static int ackevent(WPARAM wParam, LPARAM lParam)
+{
+ ACKDATA *pAck = (ACKDATA *)lParam;
+
+ if (!pAck) return 0;
+ if (pAck->type == ACKTYPE_MESSAGE)
+ {
+ msgQueue_processack(pAck->hContact, pAck->hProcess, pAck->result == ACKRESULT_SUCCESS, (char*)pAck->lParam);
+
+ if (pAck->result == ACKRESULT_SUCCESS)
+ SkinPlaySound("SendMsg");
+ }
+ return 0;
+}
+
+int AvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact);
+ if (h) SendMessage(h, HM_AVATARACK, wParam, lParam);
+ return 0;
+}
+
diff --git a/plugins/SRMM/globals.h b/plugins/SRMM/globals.h
new file mode 100644
index 0000000000..05ae138f7d
--- /dev/null
+++ b/plugins/SRMM/globals.h
@@ -0,0 +1,62 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#ifndef SRMM_GLOBALS_H
+#define SRMM_GLOBALS_H
+
+#define SMF_SHOWINFO 0x00000001
+#define SMF_SHOWBTNS 0x00000002
+#define SMF_SENDBTN 0x00000004
+#define SMF_SHOWTYPING 0x00000008
+#define SMF_SHOWTYPINGWIN 0x00000010
+#define SMF_SHOWTYPINGTRAY 0x00000020
+#define SMF_SHOWTYPINGCLIST 0x00000040
+#define SMF_SHOWICONS 0x00000080
+#define SMF_SHOWTIME 0x00000100
+#define SMF_AVATAR 0x00000200
+#define SMF_SHOWDATE 0x00000400
+#define SMF_HIDENAMES 0x00000800
+#define SMF_SHOWSECS 0x00001000
+#define SMF_SHOWREADCHAR 0x00002000
+#define SMF_SENDONENTER 0x00004000
+#define SMF_SENDONDBLENTER 0x00008000
+#define SMF_AUTOCLOSE 0x00010000
+#define SMF_AUTOMIN 0x00020000
+#define SMF_TYPINGUNKNOWN 0x00040000
+#define SMF_CTRLSUPPORT 0x00080000
+#define SMF_SHOWFORMAT 0x00100000
+
+#define SMF_ICON_TYPING 0
+
+struct GlobalMessageData
+{
+ unsigned int flags;
+ HANDLE hMessageWindowList;
+ DWORD openFlags;
+ DWORD msgTimeout;
+ DWORD nFlashMax;
+};
+
+void InitGlobals();
+void FreeGlobals();
+void ReloadGlobals();
+
+extern struct GlobalMessageData *g_dat;
+
+#endif
diff --git a/plugins/SRMM/msgdialog.c b/plugins/SRMM/msgdialog.c
new file mode 100644
index 0000000000..1a90a861c6
--- /dev/null
+++ b/plugins/SRMM/msgdialog.c
@@ -0,0 +1,2042 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#include "commonheaders.h"
+#include "statusicon.h"
+
+#define TIMERID_FLASHWND 1
+#define TIMERID_TYPE 2
+#define TIMEOUT_FLASHWND 900
+#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity
+#define SB_CHAR_WIDTH 45
+#define SB_TIME_WIDTH 60
+#define SB_GRIP_WIDTH 20 // pixels - buffer used to prevent sizegrip from overwriting statusbar icons
+#define VALID_AVATAR(x) (x==PA_FORMAT_PNG||x==PA_FORMAT_JPEG||x==PA_FORMAT_ICON||x==PA_FORMAT_BMP||x==PA_FORMAT_GIF)
+
+extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
+extern HANDLE hHookWinEvt, hHookWinPopup;
+extern struct CREOleCallback reOleCallback;
+
+static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus);
+
+static const UINT infoLineControls[] = { IDC_PROTOCOL, IDC_NAME };
+static const UINT buttonLineControls[] = { IDC_ADD, IDC_USERMENU, IDC_DETAILS, IDC_HISTORY };
+static const UINT sendControls[] = { IDC_MESSAGE };
+
+static void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) {
+ MessageWindowEventData mwe = { 0 };
+
+ if (hContact==NULL || hwnd==NULL) return;
+ mwe.cbSize = sizeof(mwe);
+ mwe.hContact = hContact;
+ mwe.hwndWindow = hwnd;
+ mwe.szModule = SRMMMOD;
+ mwe.uType = type;
+ mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+ mwe.hwndInput = GetDlgItem(hwnd, IDC_MESSAGE);
+ mwe.hwndLog = GetDlgItem(hwnd, IDC_LOG);
+ NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe);
+}
+
+static char *MsgServiceName(HANDLE hContact)
+{
+#ifdef _UNICODE
+ char szServiceName[100];
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL)
+ return PSS_MESSAGE;
+
+ mir_snprintf(szServiceName, SIZEOF(szServiceName), "%s%sW", szProto, PSS_MESSAGE);
+ if (ServiceExists(szServiceName))
+ return PSS_MESSAGE "W";
+#endif
+ return PSS_MESSAGE;
+}
+
+static BOOL IsUtfSendAvailable(HANDLE hContact)
+{
+ char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( szProto == NULL )
+ return FALSE;
+
+ return ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF ) ? TRUE : FALSE;
+}
+
+static int RTL_Detect(const TCHAR *ptszText)
+{
+ WORD *infoTypeC2;
+ int i;
+ int iLen = (int)_tcslen(ptszText);
+
+ infoTypeC2 = (WORD*)alloca(sizeof(WORD) * (iLen + 2));
+ GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE2, ptszText, iLen, infoTypeC2);
+
+ for(i = 0; i < iLen; i++) {
+ if(infoTypeC2[i] == C2_RIGHTTOLEFT)
+ return 1;
+ }
+ return 0;
+}
+
+HANDLE SendMessageDirect(const TCHAR *szMsg, HANDLE hContact, char *szProto)
+{
+ int flags = 0;
+ int bufSize = 0;
+ char *sendBuffer = NULL;
+
+ if (RTL_Detect(szMsg)) flags |= PREF_RTL;
+
+ if (IsUtfSendAvailable(hContact))
+ {
+ flags |= PREF_UTF;
+ sendBuffer = mir_utf8encodeT(szMsg);
+ if (!sendBuffer || !sendBuffer[0])
+ {
+ mir_free(sendBuffer);
+ return NULL;
+ }
+ bufSize = (int)strlen(sendBuffer) + 1;
+ }
+ else
+ {
+ flags |= PREF_TCHAR;
+ sendBuffer = mir_t2a(szMsg);
+ if (!sendBuffer || !sendBuffer[0])
+ {
+ mir_free(sendBuffer);
+ return NULL;
+ }
+ bufSize = (int)strlen(sendBuffer) + 1;
+#ifdef _UNICODE
+ {
+ size_t bufSizeT = (_tcslen(szMsg) + 1) * sizeof(TCHAR) ;
+
+ sendBuffer = (char*)mir_realloc(sendBuffer, bufSizeT + bufSize);
+ memcpy((TCHAR*)&sendBuffer[bufSize], szMsg, bufSizeT);
+ bufSize += (int)bufSizeT;
+ }
+#endif
+ }
+
+ if (hContact == NULL)
+ {
+ mir_free(sendBuffer);
+ return NULL;
+ }
+
+ if (sendBuffer)
+ {
+ HANDLE hNewEvent, hSendId;
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_SENT | (flags & PREF_UTF ? DBEF_UTF : 0) | (flags & PREF_RTL ? DBEF_RTL : 0);
+ dbei.szModule = szProto;
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.cbBlob = (DWORD)bufSize;
+ dbei.pBlob = (PBYTE)sendBuffer;
+
+ hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ hSendId = (HANDLE) CallContactService(hContact, MsgServiceName(hContact), flags, (LPARAM) sendBuffer);
+ msgQueue_add(hContact, hSendId, szMsg, hNewEvent);
+ mir_free(sendBuffer);
+
+ return hNewEvent;
+ }
+ return NULL;
+}
+
+
+static void AddToFileList(TCHAR ***pppFiles,int *totalCount,const TCHAR* szFilename)
+{
+ *pppFiles=(TCHAR**)mir_realloc(*pppFiles,(++*totalCount+1)*sizeof(TCHAR*));
+ (*pppFiles)[*totalCount] = NULL;
+ (*pppFiles)[*totalCount-1] = mir_tstrdup( szFilename );
+
+ if ( GetFileAttributes(szFilename) & FILE_ATTRIBUTE_DIRECTORY ) {
+ WIN32_FIND_DATA fd;
+ HANDLE hFind;
+ TCHAR szPath[MAX_PATH];
+ mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\*"), szFilename);
+ if (( hFind = FindFirstFile( szPath, &fd )) != INVALID_HANDLE_VALUE ) {
+ do {
+ if ( !_tcscmp(fd.cFileName,_T(".")) || !_tcscmp(fd.cFileName,_T(".."))) continue;
+ mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\%s"), szFilename, fd.cFileName);
+ AddToFileList(pppFiles,totalCount,szPath);
+ }
+ while( FindNextFile( hFind,&fd ));
+ FindClose( hFind );
+ } } }
+
+static void ShowMultipleControls(HWND hwndDlg, const UINT * controls, int cControls, int state)
+{
+ int i;
+ for (i = 0; i < cControls; i++)
+ ShowWindow(GetDlgItem(hwndDlg, controls[i]), state);
+}
+
+static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus)
+{
+ if (hwndStatus && (g_dat->flags & SMF_SHOWREADCHAR))
+ {
+ TCHAR buf[32];
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+
+ mir_sntprintf(buf, SIZEOF(buf), _T("%d"), len);
+ SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM) buf);
+ }
+}
+
+static void ShowTime(struct MessageWindowData *dat)
+{
+ if (dat->hwndStatus && dat->hTimeZone)
+ {
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ if (dat->wMinute != st.wMinute)
+ {
+ TCHAR buf[32];
+ unsigned i = (g_dat->flags & SMF_SHOWREADCHAR) ? 2 : 1;
+
+ tmi.printDateTime(dat->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ SendMessage(dat->hwndStatus, SB_SETTEXT, i, (LPARAM) buf);
+ dat->wMinute = st.wMinute;
+ }
+ }
+}
+
+static void SetupStatusBar(HWND hwndDlg, struct MessageWindowData *dat)
+{
+ int icons_width, cx, i = 0, statwidths[4];
+ RECT rc;
+
+ icons_width = GetStatusIconsCount(dat->hContact) * (GetSystemMetrics(SM_CXSMICON) + 2) + SB_GRIP_WIDTH;
+ GetWindowRect(dat->hwndStatus, &rc);
+ cx = rc.right - rc.left;
+
+ if (dat->hTimeZone)
+ {
+ if (g_dat->flags & SMF_SHOWREADCHAR)
+ statwidths[i++] = cx - SB_TIME_WIDTH - SB_CHAR_WIDTH - icons_width;
+ statwidths[i++] = cx - SB_TIME_WIDTH - icons_width;
+ }
+ else if (g_dat->flags & SMF_SHOWREADCHAR)
+ statwidths[i++] = cx - SB_CHAR_WIDTH - icons_width;
+
+ statwidths[i++] = cx - icons_width;
+ statwidths[i++] = -1;
+ SendMessage(dat->hwndStatus, SB_SETPARTS, i, (LPARAM) statwidths);
+
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ ShowTime(dat);
+ SendMessage(hwndDlg, DM_STATUSICONCHANGE, 0, 0);
+}
+
+static void SetDialogToType(HWND hwndDlg)
+{
+ struct MessageWindowData *dat;
+
+ dat = (struct MessageWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (dat->hContact)
+ ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), (g_dat->flags&SMF_SHOWINFO) ? SW_SHOW : SW_HIDE);
+ else
+ ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), SW_HIDE);
+
+ if (dat->hContact) {
+ ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), (g_dat->flags&SMF_SHOWBTNS) ? SW_SHOW : SW_HIDE);
+ if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
+ }
+ else ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), SW_HIDE);
+
+ ShowMultipleControls(hwndDlg, sendControls, SIZEOF(sendControls), SW_SHOW);
+ if (!dat->hwndStatus) {
+ int grip = (GetWindowLongPtr(hwndDlg, GWL_STYLE) & WS_THICKFRAME) ? SBARS_SIZEGRIP : 0;
+ dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | grip, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL);
+ SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0);
+ }
+
+ ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDOK), (g_dat->flags & SMF_SENDBTN) ? SW_SHOW : SW_HIDE);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0);
+ if (dat->avatarPic == NULL || !(g_dat->flags & SMF_AVATAR))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE);
+ SendMessage(hwndDlg, DM_UPDATETITLE, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+}
+
+struct MsgEditSubclassData
+{
+ DWORD lastEnterTime;
+};
+
+static void SetEditorText(HWND hwnd, const TCHAR* txt)
+{
+ SetWindowText(hwnd, txt);
+ SendMessage(hwnd, EM_SETSEL, -1, -1);
+}
+
+#define EM_SUBCLASSED (WM_USER+0x101)
+#define EM_UNSUBCLASSED (WM_USER+0x102)
+#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send
+
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct MessageWindowData *pdat = (struct MessageWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+ struct MsgEditSubclassData *dat = (struct MsgEditSubclassData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_DROPFILES:
+ SendMessage(GetParent(hwnd), WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam);
+ break;
+
+ case EM_SUBCLASSED:
+ dat = (struct MsgEditSubclassData *) mir_alloc(sizeof(struct MsgEditSubclassData));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat);
+ dat->lastEnterTime = 0;
+ return 0;
+
+ case WM_CHAR:
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
+ break;
+
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if (wParam == VK_RETURN)
+ {
+ if (!(GetKeyState(VK_SHIFT) & 0x8000) &&
+ ((GetKeyState(VK_CONTROL) & 0x8000) != 0) != ((g_dat->flags & SMF_SENDONENTER) != 0))
+ {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (g_dat->flags & SMF_SENDONDBLENTER)
+ {
+ if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount())
+ dat->lastEnterTime = GetTickCount();
+ else
+ {
+ SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0);
+ SendMessage(hwnd, WM_KEYUP, VK_BACK, 0);
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ }
+ }
+ else
+ dat->lastEnterTime = 0;
+
+ if (((wParam == VK_INSERT && (GetKeyState(VK_SHIFT) & 0x8000)) || (wParam == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))) &&
+ !(GetKeyState(VK_MENU) & 0x8000)) // ctrl-v (paste clean text)
+ {
+ SendMessage(hwnd, WM_PASTE, 0, 0);
+ return 0;
+ }
+
+ if (wParam == VK_UP && (GetKeyState(VK_CONTROL) & 0x8000) &&
+ ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT))
+ {
+ if (pdat->cmdList->realCount)
+ {
+ if (pdat->cmdListInd < 0)
+ {
+ pdat->cmdListInd = pdat->cmdList->realCount - 1;
+ SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdListInd));
+ }
+ else if (pdat->cmdListInd > 0)
+ {
+ SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, --pdat->cmdListInd));
+ }
+ }
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0);
+ UpdateReadChars(GetParent(hwnd), pdat->hwndStatus);
+ return 0;
+ }
+ else if (wParam == VK_DOWN && (GetKeyState(VK_CONTROL) & 0x8000) &&
+ ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT))
+ {
+ if (pdat->cmdList->realCount && pdat->cmdListInd >= 0)
+ {
+ if (pdat->cmdListInd < (pdat->cmdList->realCount - 1))
+ {
+ SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, ++pdat->cmdListInd));
+ }
+ else
+ {
+ pdat->cmdListInd = -1;
+ SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdList->realCount - 1));
+ }
+ }
+
+ EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0);
+ UpdateReadChars(GetParent(hwnd), pdat->hwndStatus);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_MOUSEWHEEL:
+ case WM_KILLFOCUS:
+ dat->lastEnterTime = 0;
+ break;
+
+ case WM_SYSCHAR:
+ dat->lastEnterTime = 0;
+ if ((wParam == 's' || wParam == 'S') && GetKeyState(VK_MENU) & 0x8000)
+ {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ HMENU hMenu;
+ CHARRANGE sel;
+ static const CHARRANGE all = {0, -1};
+
+ MessageWindowPopupData mwpd = {0};
+ mwpd.cbSize = sizeof(mwpd);
+ mwpd.uType = MSG_WINDOWPOPUP_SHOWING;
+ mwpd.uFlags = MSG_WINDOWPOPUP_INPUT;
+ mwpd.hContact = pdat->hContact;
+ mwpd.hwnd = hwnd;
+
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+
+ mwpd.hMenu = GetSubMenu(hMenu, 2);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)mwpd.hMenu, 0);
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);
+ if (sel.cpMin == sel.cpMax)
+ {
+ EnableMenuItem(mwpd.hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(mwpd.hMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(mwpd.hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED);
+ }
+ if (!SendMessage(hwnd, EM_CANUNDO, 0, 0))
+ {
+ EnableMenuItem(mwpd.hMenu, IDM_UNDO, MF_BYCOMMAND | MF_GRAYED);
+ }
+ if (!SendMessage(hwnd, EM_CANREDO, 0, 0))
+ {
+ EnableMenuItem(mwpd.hMenu, IDM_REDO, MF_BYCOMMAND | MF_GRAYED);
+ }
+ if (!SendMessage(hwnd, EM_CANPASTE, 0, 0))
+ {
+ if (!IsClipboardFormatAvailable(CF_HDROP))
+ EnableMenuItem(mwpd.hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(mwpd.hMenu, IDM_PASTESEND, MF_BYCOMMAND | MF_GRAYED);
+ }
+ if (lParam == 0xFFFFFFFF)
+ {
+ SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&mwpd.pt, (LPARAM)sel.cpMax);
+ ClientToScreen(hwnd, &mwpd.pt);
+ }
+ else
+ {
+ mwpd.pt.x = GET_X_LPARAM(lParam);
+ mwpd.pt.y = GET_Y_LPARAM(lParam);
+ }
+
+
+ // First notification
+ NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd);
+
+ // Someone added items?
+ if (GetMenuItemCount(mwpd.hMenu) > 0)
+ {
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ mwpd.selection = TrackPopupMenu(mwpd.hMenu, TPM_RETURNCMD, mwpd.pt.x, mwpd.pt.y, 0, hwnd, NULL);
+ }
+
+ // Second notification
+ mwpd.uType = MSG_WINDOWPOPUP_SELECTED;
+ NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd);
+
+ switch (mwpd.selection)
+ {
+ case IDM_UNDO:
+ SendMessage(hwnd, WM_UNDO, 0, 0);
+ break;
+
+ case IDM_REDO:
+ SendMessage(hwnd, EM_REDO, 0, 0);
+ break;
+
+ case IDM_CUT:
+ SendMessage(hwnd, WM_CUT, 0, 0);
+ break;
+
+ case IDM_COPY:
+ SendMessage(hwnd, WM_COPY, 0, 0);
+ break;
+
+ case IDM_PASTE:
+ SendMessage(hwnd, WM_PASTE, 0, 0);
+ break;
+
+ case IDM_PASTESEND:
+ SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0);
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ break;
+
+ case IDM_DELETE:
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, 0);
+ break;
+
+ case IDM_SELECTALL:
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all);
+ break;
+
+ case IDM_CLEAR:
+ SetWindowText(hwnd, _T( "" ));
+ break;
+ }
+ DestroyMenu(hMenu);
+ return 0;
+ }
+
+ case WM_PASTE:
+ if (IsClipboardFormatAvailable(CF_HDROP))
+ {
+ if (OpenClipboard(hwnd))
+ {
+ HANDLE hDrop = GetClipboardData(CF_HDROP);
+ if (hDrop)
+ SendMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0);
+ CloseClipboard();
+ }
+ }
+ else
+ SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0);
+ return 0;
+
+ case EM_UNSUBCLASSED:
+ mir_free(dat);
+ return 0;
+ }
+ return CallWindowProc(pdat->OldMessageEditProc, hwnd, msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct MessageWindowData *pdat = (struct MessageWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE);
+ return TRUE;
+ }
+
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd) {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, rc.right > rc.bottom ? (short) HIWORD(GetMessagePos()) + rc.bottom / 2 : (short) LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM) hwnd);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ return 0;
+ }
+ return CallWindowProc(pdat->OldSplitterProc, hwnd, msg, wParam, lParam);
+}
+
+static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc)
+{
+ struct MessageWindowData *dat = (struct MessageWindowData *) lParam;
+
+ if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) {
+ int i;
+ for (i = 0; i < SIZEOF(buttonLineControls); i++)
+ if (buttonLineControls[i] == urc->wId)
+ OffsetRect(&urc->rcItem, 0, -dat->lineHeight);
+ }
+
+ switch (urc->wId) {
+ case IDC_NAME:
+ {
+ int len;
+ HWND h;
+
+ h = GetDlgItem(hwndDlg, IDC_NAME);
+ len = GetWindowTextLength(h);
+ if (len > 0) {
+ HDC hdc;
+ SIZE textSize;
+ TCHAR buf[256];
+ HFONT hFont;
+
+ GetWindowText(h, buf, SIZEOF(buf));
+
+ hdc = GetDC(h);
+ hFont = SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0));
+ GetTextExtentPoint32(hdc, buf, lstrlen(buf), &textSize);
+ urc->rcItem.right = urc->rcItem.left + textSize.cx + 10;
+ if ((g_dat->flags&SMF_SHOWBTNS) && urc->rcItem.right > urc->dlgNewSize.cx - dat->nLabelRight)
+ urc->rcItem.right = urc->dlgNewSize.cx - dat->nLabelRight;
+ SelectObject(hdc, hFont);
+ ReleaseDC(h, hdc);
+ }
+ }
+ case IDC_PROTOCOL:
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+
+ case IDC_ADD:
+ case IDC_USERMENU:
+ case IDC_DETAILS:
+ case IDC_HISTORY:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP;
+
+ case IDC_LOG:
+ if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS))
+ urc->rcItem.top -= dat->lineHeight;
+ urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+ case IDC_SPLITTER:
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+
+ case IDC_MESSAGE:
+ {
+ if (!(g_dat->flags & SMF_SENDBTN))
+ urc->rcItem.right = urc->dlgNewSize.cx - urc->rcItem.left;
+ if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic) {
+ urc->rcItem.left = dat->avatarWidth+4;
+ }
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ if (!(g_dat->flags & SMF_SENDBTN))
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+ }
+
+ case IDCANCEL:
+ case IDOK:
+ urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos;
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+
+ case IDC_AVATAR:
+ urc->rcItem.top=urc->rcItem.bottom-(dat->avatarHeight + 2);
+ urc->rcItem.right=urc->rcItem.left+(dat->avatarWidth + 2);
+ return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+void ShowAvatar(HWND hwndDlg, struct MessageWindowData *dat)
+{
+ if (g_dat->flags & SMF_AVATAR)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)dat->hContact, 0);
+ if (ace && (INT_PTR)ace != CALLSERVICE_NOTFOUND && (ace->dwFlags & AVS_BITMAP_VALID) && !(ace->dwFlags & AVS_HIDEONCLIST))
+ dat->avatarPic = ace->hbmPic;
+ else
+ dat->avatarPic = NULL;
+ }
+ else
+ dat->avatarPic = NULL;
+
+ SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0);
+ SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0);
+}
+
+static void NotifyTyping(struct MessageWindowData *dat, int mode)
+{
+ DWORD protoStatus;
+ DWORD protoCaps;
+ DWORD typeCaps;
+
+ if (!dat->hContact)
+ return;
+ // Don't send to protocols who don't support typing
+ // Don't send to users who are unchecked in the typing notification options
+ // Don't send to protocols that are offline
+ // Don't send to users who are not visible and
+ // Don't send to users who are not on the visible list when you are in invisible mode.
+
+ if (!DBGetContactSettingByte(dat->hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)))
+ return;
+
+ if (!dat->szProto)
+ return;
+
+ protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0);
+ protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+ typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+
+ if (!(typeCaps & PF4_SUPPORTTYPING))
+ return;
+
+ if (protoStatus < ID_STATUS_ONLINE)
+ return;
+
+ if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ return;
+
+ if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE)
+ return;
+
+ if (!(g_dat->flags & SMF_TYPINGUNKNOWN) && DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0))
+ return;
+
+ // End user check
+ dat->nTypeMode = mode;
+ CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->hContact, dat->nTypeMode);
+}
+
+void Button_SetIcon_IcoLib(HWND hwndDlg, int itemId, int iconId, const char* tooltip)
+{
+ HWND hWnd = GetDlgItem( hwndDlg, itemId );
+ SendMessage( hWnd, BM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadSkinnedIcon( iconId ));
+ SendMessage( hWnd, BUTTONSETASFLATBTN, 0, 0 );
+ SendMessage( hWnd, BUTTONADDTOOLTIP, (WPARAM)tooltip, 0);
+}
+
+void Button_FreeIcon_IcoLib(HWND hwndDlg, int itemId)
+{
+ HICON hIcon = ( HICON )SendDlgItemMessage(hwndDlg, itemId, BM_SETIMAGE, IMAGE_ICON, 0 );
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+}
+
+void Window_FreeIcon_IcoLib(HWND hwndDlg)
+{
+ HICON hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+
+ hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+}
+
+INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct MessageWindowData *dat;
+
+ dat = (struct MessageWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam;
+ TranslateDialogDefault(hwndDlg);
+ dat = (struct MessageWindowData *) mir_calloc(sizeof(struct MessageWindowData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dat);
+
+ dat->hContact = newData->hContact;
+ dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY);
+ dat->wMinute = 61;
+
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING);
+ if (newData->szInitialText)
+ {
+ int len;
+#ifdef _UNICODE
+ if(newData->isWchar)
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText);
+ else
+#endif
+ SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText);
+ len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len);
+ }
+
+ dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0);
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG));
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_MESSAGE));
+
+ // avatar stuff
+ dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0;
+
+ if (dat->hContact && dat->szProto != NULL)
+ dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ else
+ dat->wStatus = ID_STATUS_OFFLINE;
+ dat->wOldStatus = dat->wStatus;
+ dat->splitterPos = (int) DBGetContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", (DWORD) - 1);
+ dat->cmdList = li.List_Create(0, 20);
+ dat->cmdListInd = -1;
+ dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF;
+ SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL);
+ {
+ RECT rc, rc2;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc);
+ GetWindowRect(hwndDlg, &rc2);
+ dat->nLabelRight = rc2.right - rc.left;
+ }
+ {
+ RECT rc;
+ POINT pt;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc);
+ pt.y = (rc.top + rc.bottom) / 2;
+ pt.x = 0;
+ ScreenToClient(hwndDlg, &pt);
+ dat->originalSplitterPos = pt.y;
+ if (dat->splitterPos == -1)
+ dat->splitterPos = dat->originalSplitterPos;// + 60;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rc);
+ dat->lineHeight = rc.bottom - rc.top + 3;
+ }
+ WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->hContact);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &dat->minEditInit);
+ SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0);
+ dat->hwndStatus = NULL;
+ Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, "Add Contact Permanently to List" );
+ Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, "View User's Details" );
+ Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, "View User's History" );
+ Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, "User Menu" );
+ SendDlgItemMessage(hwndDlg, IDC_NAME, BUTTONSETASFLATBTN, 0, 0 );
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AVATAR), FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL);
+ /* duh, how come we didnt use this from the start? */
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0);
+ if (dat->hContact && dat->szProto) {
+ int nMax;
+ nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->hContact);
+ if (nMax)
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_LIMITTEXT, (WPARAM) nMax, 0);
+ /* get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF */
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM) sizeof(TCHAR) * 0x7FFFFFFF, 0);
+ }
+
+ dat->OldMessageEditProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) MessageEditSubclassProc);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0);
+ dat->OldSplitterProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) SplitterSubclassProc);
+
+ if (dat->hContact)
+ {
+ int historyMode = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY);
+ // This finds the first message to display, it works like shit
+ dat->hDbEventFirst = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) dat->hContact, 0);
+ switch (historyMode)
+ {
+ case LOADHISTORY_COUNT:
+ {
+ int i;
+ HANDLE hPrevEvent;
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ for (i = DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); i--; )
+ {
+ if (dat->hDbEventFirst == NULL)
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ else
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0);
+ if (hPrevEvent == NULL)
+ break;
+
+ dbei.cbBlob = 0;
+ dat->hDbEventFirst = hPrevEvent;
+ CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) &dbei);
+ if (!DbEventIsShown(&dbei, dat))
+ i++;
+ }
+ break;
+ }
+ case LOADHISTORY_TIME:
+ {
+ HANDLE hPrevEvent;
+ DBEVENTINFO dbei = { 0 };
+ DWORD firstTime;
+
+ dbei.cbSize = sizeof(dbei);
+ if (dat->hDbEventFirst == NULL)
+ dbei.timestamp = (DWORD)time(NULL);
+ else
+ CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei);
+ firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME);
+ for (;;)
+ {
+ if (dat->hDbEventFirst == NULL)
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ else
+ hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0);
+ if (hPrevEvent == NULL)
+ break;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei);
+ if (dbei.timestamp < firstTime)
+ break;
+ dat->hDbEventFirst = hPrevEvent;
+ }
+ break;
+ }
+ }
+ }
+
+ {
+ DBEVENTINFO dbei = { 0 };
+ HANDLE hdbEvent;
+
+ dbei.cbSize = sizeof(dbei);
+ hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0);
+ if (hdbEvent)
+ {
+ do {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, (WPARAM) hdbEvent, (LPARAM) & dbei);
+ if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei) ) && !(dbei.flags & DBEF_SENT)) {
+ dat->lastMessage = dbei.timestamp;
+ PostMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ break;
+ }
+ }
+ while (hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0));
+ }
+ }
+
+ SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 1, 0);
+
+ //restore saved msg if any...
+ if (dat->hContact)
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, &dbv))
+ {
+ if (dbv.ptszVal[0])
+ {
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, dbv.ptszVal);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, -1, -1);
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_CHANGE);
+
+ {
+ int flag = newData->noActivate ? RWPF_HIDDEN : 0;
+ int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT);
+ if (Utils_RestoreWindowPositionEx(hwndDlg, flag, savePerContact ? dat->hContact : NULL, SRMMMOD, "")) {
+ if (savePerContact) {
+ if (Utils_RestoreWindowPositionEx(hwndDlg, flag | RWPF_NOMOVE, NULL, SRMMMOD, ""))
+ SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
+ }
+ else
+ SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
+ }
+ if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE))
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded);
+ }
+ if (newData->noActivate)
+ {
+ SetWindowPos(hwndDlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ else
+ {
+ SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+ SetForegroundWindow(hwndDlg);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+
+ SendMessage(hwndDlg, DM_GETAVATAR, 0, 0);
+
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN);
+ return FALSE;
+ }
+
+ case WM_CONTEXTMENU:
+ if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) {
+ POINT pt, pt2;
+ HMENU hMenu;
+ RECT rc;
+
+ GetCursorPos(&pt);
+ pt2.x = pt.x; pt2.y = pt.y;
+ ScreenToClient(dat->hwndStatus, &pt);
+
+ // no popup menu for status icons - this is handled via NM_RCLICK notification and the plugins that added the icons
+ SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
+ if (pt.x >= rc.left) break;
+
+ hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0);
+
+ TrackPopupMenu(hMenu, 0, pt2.x, pt2.y, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ // Mod from tabsrmm
+ case WM_DROPFILES:
+ if (dat->szProto==NULL) break;
+ if (!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1,0)&PF1_FILESEND)) break;
+ if (dat->wStatus==ID_STATUS_OFFLINE) break;
+ if (dat->hContact!=NULL) {
+ TCHAR szFilename[MAX_PATH];
+ HDROP hDrop = (HDROP)wParam;
+ int fileCount = DragQueryFile(hDrop,-1,NULL,0), totalCount = 0, i;
+ TCHAR** ppFiles = NULL;
+ for ( i=0; i < fileCount; i++ ) {
+ DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename));
+ AddToFileList(&ppFiles, &totalCount, szFilename);
+ }
+ CallServiceSync(MS_FILE_SENDSPECIFICFILEST, (WPARAM)dat->hContact, (LPARAM)ppFiles);
+ for(i=0;ppFiles[i];i++) mir_free(ppFiles[i]);
+ mir_free(ppFiles);
+ }
+ break;
+
+ case HM_AVATARACK:
+ ShowAvatar(hwndDlg, dat);
+ break;
+
+ case DM_AVATARCALCSIZE:
+ {
+ BITMAP bminfo;
+
+ if (dat->avatarPic == NULL || !(g_dat->flags&SMF_AVATAR))
+ {
+ dat->avatarWidth=50;
+ dat->avatarHeight=50;
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE);
+ return 0;
+ }
+ GetObject(dat->avatarPic, sizeof(bminfo), &bminfo);
+ dat->avatarWidth=bminfo.bmWidth+2;
+ dat->avatarHeight=bminfo.bmHeight+2;
+ if (dat->limitAvatarH&&dat->avatarHeight>dat->limitAvatarH) {
+ dat->avatarWidth = bminfo.bmWidth * dat->limitAvatarH / bminfo.bmHeight + 2;
+ dat->avatarHeight = dat->limitAvatarH + 2;
+ }
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_SHOW);
+ }
+ break;
+
+ case DM_UPDATESIZEBAR:
+ dat->minEditBoxSize.cx = dat->minEditInit.right - dat->minEditInit.left;
+ dat->minEditBoxSize.cy = dat->minEditInit.bottom - dat->minEditInit.top;
+ if(g_dat->flags&SMF_AVATAR) {
+ SendMessage(hwndDlg, DM_AVATARCALCSIZE, 0, 0);
+ if(dat->avatarPic && dat->minEditBoxSize.cy <= dat->avatarHeight)
+ dat->minEditBoxSize.cy = dat->avatarHeight;
+ }
+ break;
+
+ case DM_AVATARSIZECHANGE:
+ {
+ RECT rc;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ if (rc.bottom-rc.top<dat->minEditBoxSize.cy) {
+ SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER));
+ }
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ break;
+
+ case DM_GETAVATAR:
+ {
+ PROTO_AVATAR_INFORMATION ai = { sizeof(ai), dat->hContact };
+ CallProtoService(dat->szProto, PS_GETAVATARINFO, GAIF_FORCE, (LPARAM)&ai);
+
+ ShowAvatar(hwndDlg, dat);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
+ }
+ break;
+
+ case DM_TYPING:
+ dat->nTypeSecs = (INT_PTR)lParam > 0 ? (int)lParam : 0;
+ break;
+
+ case DM_UPDATEWINICON:
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) {
+ WORD wStatus;
+
+ Window_FreeIcon_IcoLib(hwndDlg);
+
+ if (dat->szProto) {
+ wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedProtoIconBig(dat->szProto, wStatus));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedProtoIcon(dat->szProto, wStatus));
+ break;
+ }
+ }
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedIconBig(SKINICON_EVENT_MESSAGE));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ break;
+
+ case DM_USERNAMETOCLIP:
+ if (dat->hContact)
+ {
+ TCHAR buf[128] = _T("");
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = dat->szProto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci))
+ {
+ switch (ci.type)
+ {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(buf, SIZEOF(buf), _T("%s"), ci.pszVal);
+ mir_free(ci.pszVal);
+ break;
+
+ case CNFT_DWORD:
+ mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal);
+ break;
+ }
+ }
+ if (buf[0] && OpenClipboard(hwndDlg))
+ {
+ HGLOBAL hData;
+
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, _tcslen(buf) * sizeof(TCHAR) + 1);
+ _tcscpy(GlobalLock(hData), buf);
+ GlobalUnlock(hData);
+#ifdef _UNICODE
+ SetClipboardData(CF_UNICODETEXT, hData);
+#else
+ SetClipboardData(CF_TEXT, hData);
+#endif
+ CloseClipboard();
+ }
+ }
+ break;
+
+ case DM_UPDATELASTMESSAGE:
+ if (!dat->hwndStatus || dat->nTypeSecs)
+ break;
+
+ if (dat->lastMessage)
+ {
+ TCHAR date[64], time[64], fmt[128];
+
+ tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0);
+ tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0);
+ mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time);
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt);
+ }
+ else {
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) _T(""));
+ }
+ SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL);
+ break;
+
+ case DM_OPTIONSAPPLIED:
+ SetDialogToType(hwndDlg);
+ if (dat->hBkgBrush)
+ DeleteObject(dat->hBkgBrush);
+ {
+ COLORREF colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
+ dat->hBkgBrush = CreateSolidBrush(colour);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETBKGNDCOLOR, 0, colour);
+ }
+ { // avatar stuff
+ dat->avatarPic = NULL;
+ dat->limitAvatarH = 0;
+ if (CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_AVATARS)
+ {
+ dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT) ?
+ DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT) : 0;
+ }
+ if (!wParam) SendMessage(hwndDlg, DM_GETAVATAR, 0, 0);
+ }
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE);
+ {
+ HFONT hFont;
+ LOGFONT lf;
+ CHARFORMAT cf = {0};
+ hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0);
+ if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0))
+ DeleteObject(hFont);
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, &cf.crTextColor);
+ hFont = CreateFontIndirect(&lf);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0));
+
+ cf.cbSize = sizeof(CHARFORMAT);
+ cf.dwMask = CFM_COLOR;
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (WPARAM) &cf);
+ }
+
+ /*
+ * configure message history for proper RTL formatting
+ */
+
+ {
+ PARAFORMAT2 pf2;
+ ZeroMemory((void *)&pf2, sizeof(pf2));
+ pf2.cbSize = sizeof(pf2);
+
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask = PFM_RTLPARA;
+ SetDlgItemText(hwndDlg, IDC_LOG, _T(""));
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ pf2.wEffects = 0;
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ }
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ break;
+
+ case DM_UPDATETITLE:
+ {
+ TCHAR newtitle[256], oldtitle[256], *szStatus;
+ TCHAR *contactName, *pszNewTitleEnd;
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) wParam;
+
+ pszNewTitleEnd = _T("Message Session");
+ if (dat->hContact)
+ {
+ if (dat->szProto)
+ {
+ TCHAR buf[128] = _T("");
+ int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON);
+
+ dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ contactName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR);
+
+ if (strcmp(dat->szProto, "MetaContacts"))
+ {
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = dat->hContact;
+ ci.szProto = dat->szProto;
+ ci.dwFlag = CNF_DISPLAYUID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ switch (ci.type) {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(buf, SIZEOF(buf), _T("%s"), (TCHAR*)ci.pszVal);
+ mir_free(ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal);
+ break;
+ }
+ }
+ }
+ if (buf[0])
+ SetDlgItemText(hwndDlg, IDC_NAME, buf);
+ else
+ SetDlgItemText(hwndDlg, IDC_NAME, contactName);
+
+ szStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE), GSMDF_TCHAR);
+ if (statusIcon)
+ mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s - %s"), contactName, TranslateTS(pszNewTitleEnd));
+ else
+ mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s (%s): %s"), contactName, szStatus, TranslateTS(pszNewTitleEnd));
+
+ if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status")))
+ {
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), NULL, TRUE);
+ if (statusIcon)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ }
+
+ // log
+ if ((dat->wStatus != dat->wOldStatus || lParam != 0) &&
+ DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH))
+ {
+ DBEVENTINFO dbei;
+ TCHAR buffer[200];
+ HANDLE hNewEvent;
+ int iLen;
+
+ TCHAR *szOldStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wOldStatus, GSMDF_TCHAR);
+ TCHAR *szNewStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GSMDF_TCHAR);
+
+ if (dat->wStatus == ID_STATUS_OFFLINE)
+ {
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed off (was %s)"), szOldStatus);
+ SendMessage(hwndDlg, DM_TYPING, 0, 0);
+ }
+ else if (dat->wOldStatus == ID_STATUS_OFFLINE)
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed on (%s)"), szNewStatus);
+ else
+ iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("is now %s (was %s)"), szNewStatus, szOldStatus);
+
+ {
+ char* blob = ( char* )alloca(1000);
+#if defined( _UNICODE )
+ int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, 1000, 0, 0);
+ memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1));
+ dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1);
+#else
+ int wLen = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0 );
+ memcpy( blob, buffer, iLen+1 );
+ MultiByteToWideChar(CP_ACP, 0, buffer, -1, (WCHAR*)&blob[iLen+1], wLen+1 );
+ dbei.cbBlob = iLen+1 + sizeof(WCHAR)*wLen;
+#endif
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = (PBYTE) blob;
+ dbei.eventType = EVENTTYPE_STATUSCHANGE;
+ dbei.flags = 0;
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.szModule = dat->szProto;
+ hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei);
+ if (dat->hDbEventFirst == NULL)
+ {
+ dat->hDbEventFirst = hNewEvent;
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ }
+ }
+ }
+ dat->wOldStatus = dat->wStatus;
+ }
+ }
+ else lstrcpyn(newtitle, pszNewTitleEnd, SIZEOF(newtitle));
+
+ GetWindowText(hwndDlg, oldtitle, SIZEOF(oldtitle));
+ if ( _tcscmp(newtitle, oldtitle )) { //swt() flickers even if the title hasn't actually changed
+ SetWindowText(hwndDlg, newtitle);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ break;
+ }
+
+ case DM_NEWTIMEZONE:
+ dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY);
+ dat->wMinute = 61;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_GETWINDOWSTATE:
+ {
+ UINT state = 0;
+
+ state |= MSG_WINDOW_STATE_EXISTS;
+ if (IsWindowVisible(hwndDlg))
+ state |= MSG_WINDOW_STATE_VISIBLE;
+ if (GetForegroundWindow()==hwndDlg)
+ state |= MSG_WINDOW_STATE_FOCUS;
+ if (IsIconic(hwndDlg))
+ state |= MSG_WINDOW_STATE_ICONIC;
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state);
+ return TRUE;
+
+ }
+
+ case DM_CASCADENEWWINDOW:
+ if ((HWND) wParam == hwndDlg)
+ break;
+ {
+ RECT rcThis, rcNew;
+ GetWindowRect(hwndDlg, &rcThis);
+ GetWindowRect((HWND) wParam, &rcNew);
+ if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) {
+ int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
+ SetWindowPos((HWND) wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+ *(int *) lParam = 1;
+ }
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE)
+ break;
+
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ //fall through
+
+ case WM_MOUSEACTIVATE:
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND))
+ FlashWindow(hwndDlg, FALSE);
+ break;
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO* mmi = (MINMAXINFO *) lParam;
+ RECT rcWindow, rcLog;
+ GetWindowRect(hwndDlg, &rcWindow);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog);
+ mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcLog.right - rcLog.left) - dat->minEditBoxSize.cx);
+ mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcLog.bottom - rcLog.top) - dat->minEditBoxSize.cy);
+ return 0;
+ }
+
+ case WM_SIZE:
+ {
+ UTILRESIZEDIALOG urd = {0};
+ BOOL bottomScroll = TRUE;
+
+ if (IsIconic(hwndDlg))
+ break;
+
+ if (dat->hwndStatus)
+ {
+ SendMessage(dat->hwndStatus, WM_SIZE, 0, 0);
+ SetupStatusBar(hwndDlg, dat);
+ }
+
+ if (GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL)
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+ GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si);
+ bottomScroll = (si.nPos + (int)si.nPage + 5) >= si.nMax;
+ }
+
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = g_hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = (LPARAM) dat;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSG);
+ urd.pfnResizer = MessageDialogResize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd);
+
+ // The statusbar sometimes draws over these 2 controls so
+ // redraw them
+ if (dat->hwndStatus)
+ {
+ RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE);
+ }
+ if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic)
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE);
+
+ if (bottomScroll)
+ PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0);
+ break;
+ }
+
+ case DM_SPLITTERMOVED:
+ {
+ if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER))
+ {
+ POINT pt;
+ RECT rc;
+ RECT rcLog;
+ int oldSplitterY;
+ HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG);
+
+ GetClientRect(hwndDlg, &rc);
+ GetWindowRect(hwndLog, &rcLog);
+
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+
+ oldSplitterY = dat->splitterPos;
+ dat->splitterPos = rc.bottom - pt.y + 23;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ if (rc.bottom - rc.top + (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy)
+ dat->splitterPos = oldSplitterY + dat->minEditBoxSize.cy - (rc.bottom - rc.top);
+ if (rcLog.bottom - rcLog.top - (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy)
+ dat->splitterPos = oldSplitterY - dat->minEditBoxSize.cy + (rcLog.bottom - rcLog.top);
+
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ }
+ break;
+
+ case DM_REMAKELOG:
+ StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0);
+ break;
+
+ case DM_APPENDTOLOG: //takes wParam=hDbEvent
+ StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1);
+ break;
+
+ case DM_SCROLLLOGTOBOTTOM:
+ {
+ HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG);
+ if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE;
+ GetScrollInfo(hwndLog, SB_VERT, &si);
+ si.fMask = SIF_POS;
+ si.nPos = si.nMax - si.nPage;
+ SetScrollInfo(hwndLog, SB_VERT, &si, TRUE);
+ SendMessage(hwndLog, WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
+ }
+ }
+ break;
+
+ case HM_DBEVENTADDED:
+ if ((HANDLE) wParam != dat->hContact)
+ break;
+ {
+ DBEVENTINFO dbei = { 0 };
+
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei);
+ if (dat->hDbEventFirst == NULL)
+ dat->hDbEventFirst = (HANDLE) lParam;
+ if (DbEventIsShown(&dbei, dat) && !(dbei.flags & DBEF_READ))
+ {
+ if ((dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && !(dbei.flags & DBEF_SENT))
+ {
+ if (GetForegroundWindow() == hwndDlg)
+ SkinPlaySound("RecvMsgActive");
+ else
+ SkinPlaySound("RecvMsgInactive");
+ }
+ if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei) ) && dat->hwndStatus && !(dbei.flags & DBEF_SENT))
+ {
+ dat->lastMessage = dbei.timestamp;
+ SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ }
+ if ((HANDLE) lParam != dat->hDbEventFirst && (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0) == NULL)
+ SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0);
+ else
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+
+ if (!(dbei.flags & DBEF_SENT) && dbei.eventType != EVENTTYPE_STATUSCHANGE)
+ {
+ if (GetActiveWindow() == hwndDlg && GetForegroundWindow() == hwndDlg)
+ {
+ HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG);
+ if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+ GetScrollInfo(hwndLog, SB_VERT, &si);
+ if ((si.nPos + (int)si.nPage + 5) < si.nMax)
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ else
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ }
+ break;
+
+ case WM_TIMECHANGE:
+ PostMessage(hwndDlg, DM_NEWTIMEZONE, 0, 0);
+ PostMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ break;
+
+ case WM_TIMER:
+ if (wParam == TIMERID_FLASHWND)
+ {
+ FlashWindow(hwndDlg, TRUE);
+ if (dat->nFlash > 2 * g_dat->nFlashMax)
+ {
+ KillTimer(hwndDlg, TIMERID_FLASHWND);
+ FlashWindow(hwndDlg, FALSE);
+ dat->nFlash = 0;
+ }
+ dat->nFlash++;
+ }
+ else if (wParam == TIMERID_TYPE)
+ {
+ ShowTime(dat);
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF)
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+
+ if (dat->showTyping)
+ {
+ if (dat->nTypeSecs)
+ {
+ dat->nTypeSecs--;
+ if (GetForegroundWindow() == hwndDlg)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ }
+ else
+ {
+ SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ if (g_dat->flags & SMF_SHOWTYPINGWIN)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ dat->showTyping = 0;
+ }
+ }
+ else
+ {
+ if (dat->nTypeSecs)
+ {
+ TCHAR szBuf[256];
+ TCHAR* szContactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR);
+ HICON hTyping = LoadSkinnedIcon(SKINICON_OTHER_TYPING);
+
+ mir_sntprintf(szBuf, SIZEOF(szBuf), TranslateT("%s is typing a message..."), szContactName);
+ dat->nTypeSecs--;
+
+ SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf);
+ SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) hTyping);
+ if ((g_dat->flags & SMF_SHOWTYPINGWIN) && GetForegroundWindow() != hwndDlg)
+ {
+ HICON hIcon = (HICON)SendMessage(hwndDlg, WM_GETICON, ICON_SMALL, 0);
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hTyping );
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ }
+ dat->showTyping = 1;
+ }
+ }
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT) lParam;
+ if (mis->CtlType == ODT_MENU)
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ }
+ break;
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+ if (dis->CtlType == ODT_MENU)
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ else if (dis->hwndItem == dat->hwndStatus)
+ {
+ DrawStatusIcons(dat->hContact, dis->hDC, dis->rcItem, 2);
+ return TRUE;
+ }
+ else if (dis->CtlID == IDC_PROTOCOL)
+ {
+ if (dat->szProto)
+ {
+ HICON hIcon;
+ int dwStatus;
+
+ dwStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ hIcon = LoadSkinnedProtoIcon(dat->szProto, dwStatus);
+ if (hIcon)
+ {
+ if (DBGetContactSettingDword(dat->hContact, dat->szProto, "IdleTS", 0))
+ {
+ HIMAGELIST hImageList;
+
+ hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0);
+ ImageList_AddIcon(hImageList, hIcon);
+ ImageList_DrawEx(hImageList, 0, dis->hDC, dis->rcItem.left, dis->rcItem.top, 0, 0, CLR_NONE, CLR_NONE, ILD_SELECTED);
+ ImageList_Destroy(hImageList);
+ }
+ else
+ DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon, 0);
+ return TRUE;
+ }
+ }
+ }
+ else if (dis->CtlID == IDC_AVATAR && dat->avatarPic && (g_dat->flags & SMF_AVATAR))
+ {
+ BITMAP bminfo;
+ HPEN hPen, hOldPen;
+
+ hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0));
+ hOldPen = SelectObject(dis->hDC, hPen);
+ Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight);
+ SelectObject(dis->hDC,hOldPen);
+ DeleteObject(hPen);
+ GetObject(dat->avatarPic, sizeof(bminfo), &bminfo);
+ {
+ HDC hdcMem = CreateCompatibleDC(dis->hDC);
+ HBITMAP hbmMem = (HBITMAP)SelectObject(hdcMem, dat->avatarPic);
+ {
+ SetStretchBltMode(dis->hDC, HALFTONE);
+ StretchBlt(dis->hDC, 1, 1, dat->avatarWidth-2, dat->avatarHeight-2, hdcMem, 0, 0,
+ bminfo.bmWidth, bminfo.bmHeight, SRCCOPY);
+ }
+ SelectObject(hdcMem,hbmMem);
+ DeleteDC(hdcMem);
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->hContact))
+ break;
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK)))
+ break;
+ {
+ HANDLE hNewEvent;
+
+ int bufSize = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1;
+ TCHAR* temp = (TCHAR*)alloca(bufSize * sizeof(TCHAR));
+ GetDlgItemText(hwndDlg, IDC_MESSAGE, temp, bufSize);
+ if (!temp[0]) break;
+
+ hNewEvent = SendMessageDirect(temp, dat->hContact, dat->szProto);
+ if (hNewEvent)
+ {
+ tcmdlist_append(dat->cmdList, temp);
+
+ dat->cmdListInd = -1;
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+
+ if (dat->hDbEventFirst == NULL)
+ {
+ dat->hDbEventFirst = hNewEvent;
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, _T(""));
+
+ if (g_dat->flags & SMF_AUTOCLOSE)
+ DestroyWindow(hwndDlg);
+ else if (g_dat->flags & SMF_AUTOMIN)
+ ShowWindow(hwndDlg, SW_MINIMIZE);
+ }
+ }
+ return TRUE;
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case IDC_USERMENU:
+ case IDC_NAME:
+ if (GetKeyState(VK_SHIFT) & 0x8000) // copy user name
+ SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0);
+ else {
+ RECT rc;
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0);
+ GetWindowRect(GetDlgItem(hwndDlg, LOWORD(wParam)), &rc);
+ TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case IDC_HISTORY:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0);
+ break;
+
+ case IDC_DETAILS:
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->hContact, 0);
+ break;
+
+ case IDC_ADD:
+ {
+ ADDCONTACTSTRUCT acs = { 0 };
+
+ acs.handle = dat->hContact;
+ acs.handleType = HANDLE_CONTACT;
+ acs.szProto = 0;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs);
+ }
+ if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE);
+ break;
+
+ case IDC_MESSAGE:
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ UpdateReadChars(hwndDlg, dat->hwndStatus);
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0);
+ if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000))
+ {
+ dat->nLastTyping = GetTickCount();
+ if (len)
+ {
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF)
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON);
+ }
+ else if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (dat && ((LPNMHDR) lParam)->hwndFrom == dat->hwndStatus)
+ {
+ if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == NM_RCLICK)
+ {
+ NMMOUSE *nm = (NMMOUSE *) lParam;
+ RECT rc;
+
+ SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc);
+ if (nm->pt.x >= rc.left)
+ CheckIconClick(dat->hContact, dat->hwndStatus, nm->pt, rc, 2, ((LPNMHDR) lParam)->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0);
+ return TRUE;
+ }
+ }
+
+ switch (((LPNMHDR) lParam)->idFrom)
+ {
+ case IDC_LOG:
+ switch (((LPNMHDR) lParam)->code)
+ {
+ case EN_MSGFILTER:
+ switch (((MSGFILTER *) lParam)->msg)
+ {
+ case WM_LBUTTONDOWN:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE))
+ {
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+ case WM_MOUSEMOVE:
+ {
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE))
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ break;
+ }
+ case WM_RBUTTONUP:
+ {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+ CHARRANGE sel, all = { 0, -1 };
+
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin == sel.cpMax)
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL))
+ {
+ case IDM_COPY:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ break;
+ case IDM_COPYALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0);
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel);
+ break;
+ case IDM_SELECTALL:
+ SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ break;
+ case IDM_CLEAR:
+ SetDlgItemText(hwndDlg, IDC_LOG, _T(""));
+ dat->hDbEventFirst = NULL;
+ break;
+ }
+ DestroyMenu(hSubMenu);
+ DestroyMenu(hMenu);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ break;
+
+ case EN_VSCROLL:
+ if (LOWORD(wParam) == IDC_LOG && GetWindowLongPtr((HWND)lParam, GWL_STYLE) & WS_VSCROLL)
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+ GetScrollInfo((HWND)lParam, SB_VERT, &si);
+ if ((si.nPos + (int)si.nPage + 5) >= si.nMax)
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND))
+ FlashWindow(hwndDlg, FALSE);
+ }
+ break;
+
+ case EN_LINK:
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_SETCURSOR:
+ SetCursor(hCurHyperlinkHand);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ {
+ TEXTRANGE tr;
+ CHARRANGE sel;
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ break;
+ tr.chrg = ((ENLINK *) lParam)->chrg;
+ tr.lpstrText = _alloca((tr.chrg.cpMax - tr.chrg.cpMin + 8) * sizeof(TCHAR));
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+ if (_tcschr(tr.lpstrText, '@') != NULL && _tcschr(tr.lpstrText, ':') == NULL && _tcschr(tr.lpstrText, '/') == NULL)
+ {
+ memmove(tr.lpstrText + 7, tr.lpstrText, (tr.chrg.cpMax - tr.chrg.cpMin + 1) * sizeof(TCHAR));
+ memcpy(tr.lpstrText, _T("mailto:"), 7 * sizeof(TCHAR));
+ }
+ if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN)
+ {
+ HMENU hMenu, hSubMenu;
+ POINT pt;
+
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 1);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL))
+ {
+ case IDM_OPENLINK:
+ ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW);
+ break;
+
+ case IDM_COPYLINK:
+ if (OpenClipboard(hwndDlg))
+ {
+ HGLOBAL hData;
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(tr.lpstrText) + 1) * sizeof(TCHAR));
+ _tcscpy(GlobalLock(hData), tr.lpstrText);
+ GlobalUnlock(hData);
+#ifdef _UNICODE
+ SetClipboardData(CF_UNICODETEXT, hData);
+#else
+ SetClipboardData(CF_TEXT, hData);
+#endif
+ CloseClipboard();
+ }
+ break;
+ }
+
+ DestroyMenu(hMenu);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ else
+ {
+ ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case DM_STATUSICONCHANGE:
+ SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW | (SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1)), (LPARAM)0);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (!dat) return 0;
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING);
+ //save string from the editor
+ if(dat->hContact)
+ {
+ TCHAR* msg;
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1;
+ msg = (TCHAR*)alloca(sizeof(TCHAR) * len);
+ GetDlgItemText(hwndDlg, IDC_MESSAGE, msg, len);
+ if (msg[0])
+ DBWriteContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, msg);
+ else
+ DBDeleteContactSetting(dat->hContact, SRMSGMOD, DBSAVEDMSG);
+ }
+ KillTimer(hwndDlg, TIMERID_TYPE);
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+
+ if (dat->hBkgBrush)
+ DeleteObject(dat->hBkgBrush);
+ if (dat->hwndStatus)
+ DestroyWindow(dat->hwndStatus);
+ tcmdlist_free(dat->cmdList);
+ WindowList_Remove(g_dat->hMessageWindowList, hwndDlg);
+ DBWriteContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", dat->splitterPos);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) dat->OldSplitterProc);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) dat->OldMessageEditProc);
+ {
+ HFONT hFont;
+ hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0);
+ if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0))
+ DeleteObject(hFont);
+ }
+ {
+ WINDOWPLACEMENT wp = { 0 };
+ HANDLE hContact;
+
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT))
+ hContact = dat->hContact;
+ else
+ hContact = NULL;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwndDlg, &wp);
+ if (!dat->windowWasCascaded)
+ {
+ DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left);
+ DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top);
+ }
+ DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
+ DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
+ }
+
+ NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE);
+ if (dat->hContact&&DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP))
+ if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0))
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->hContact, 0);
+
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD);
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS);
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY);
+ Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU);
+ Window_FreeIcon_IcoLib(hwndDlg);
+ mir_free(dat);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break;
+ }
+ return FALSE;
+}
diff --git a/plugins/SRMM/msglog.c b/plugins/SRMM/msglog.c
new file mode 100644
index 0000000000..00a8b682e4
--- /dev/null
+++ b/plugins/SRMM/msglog.c
@@ -0,0 +1,649 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+
+extern HANDLE hIconLibItem[];
+
+static int logPixelSY;
+#define LOGICON_MSG_IN 0
+#define LOGICON_MSG_OUT 1
+#define LOGICON_MSG_NOTICE 2
+static PBYTE pLogIconBmpBits[3];
+static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ];
+
+#define STREAMSTAGE_HEADER 0
+#define STREAMSTAGE_EVENTS 1
+#define STREAMSTAGE_TAIL 2
+#define STREAMSTAGE_STOP 3
+struct LogStreamData
+{
+ int stage;
+ HANDLE hContact;
+ HANDLE hDbEvent, hDbEventLast;
+ char *buffer;
+ int bufferOffset, bufferLen;
+ int eventsToInsert;
+ int isEmpty;
+ struct MessageWindowData *dlgDat;
+};
+
+static char szSep2[40], szSep2_RTL[50];
+
+static void AppendToBuffer(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...)
+{
+ va_list va;
+ int charsDone;
+
+ va_start(va, fmt);
+ for (;;) {
+ charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va);
+ if (charsDone >= 0)
+ break;
+ *cbBufferAlloced += 1024;
+ *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced);
+ }
+ va_end(va);
+ *cbBufferEnd += charsDone;
+}
+
+static const TCHAR *bbcodes[] = { _T("[b]"), _T("[i]"), _T("[u]"), _T("[s]"), _T("[/b]"), _T("[/i]"), _T("[/u]"), _T("[/s]") };
+static const char *bbcodefmt[] = { "\\b ", "\\i ", "\\ul ", "\\strike ", "\\b0 ", "\\i0 ", "\\ul0 ", "\\strike0 " };
+
+static int AppendToBufferWithRTF(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, TCHAR* line)
+{
+ DWORD textCharsCount = 0;
+ char *d;
+ int lineLen;
+
+ if (line == NULL)
+ return 0;
+
+ lineLen = (int)_tcslen(line) * 9 + 8;
+ if (*cbBufferEnd + lineLen > *cbBufferAlloced)
+ {
+ cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024);
+ *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced);
+ }
+
+ d = *buffer + *cbBufferEnd;
+ strcpy(d, "{\\uc1 ");
+ d += 6;
+
+ for (; *line; line++, textCharsCount++)
+ {
+ if (*line == '\r' && line[1] == '\n')
+ {
+ memcpy(d, "\\par ", 5);
+ line++;
+ d += 5;
+ }
+ else if (*line == '\n') {
+ memcpy(d, "\\par ", 5);
+ d += 5;
+ }
+ else if (*line == '\t')
+ {
+ memcpy(d, "\\tab ", 5);
+ d += 5;
+ }
+ else if (*line == '\\' || *line == '{' || *line == '}')
+ {
+ *d++ = '\\';
+ *d++ = (char) *line;
+ }
+ else if (*line == '[' && (g_dat->flags & SMF_SHOWFORMAT))
+ {
+ int i, found = 0;
+ for (i = 0; i < SIZEOF(bbcodes); ++i)
+ {
+ if (line[1] == bbcodes[i][1])
+ {
+ size_t lenb = _tcslen(bbcodes[i]);
+ if (!_tcsnicmp(line, bbcodes[i], lenb))
+ {
+ size_t len = strlen(bbcodefmt[i]);
+ memcpy(d, bbcodefmt[i], len);
+ d += len;
+ line += lenb - 1;
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ if (!_tcsnicmp(line, _T("[url"), 4))
+ {
+ TCHAR* tag = _tcschr(line + 4, ']');
+ if (tag)
+ {
+ TCHAR *tagu = (line[4] == '=') ? line + 5 : tag + 1;
+ TCHAR *tage = _tcsstr(tag, _T("[/url]"));
+ if (!tage) tage = _tcsstr(tag, _T("[/URL]"));
+ if (tage)
+ {
+ *tag = 0;
+ *tage = 0;
+ d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt %s}}", mir_t2a(tagu), mir_t2a(tag + 1));
+// d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt \\ul\\cf%d %s}}", mir_t2a(tagu), msgDlgFontCount, mir_t2a(tag + 1));
+ line = tage + 5;
+ found = 1;
+ }
+ }
+ }
+ else if (!_tcsnicmp(line, _T("[color="), 7))
+ {
+ TCHAR* tag = _tcschr(line + 7, ']');
+ if (tag)
+ {
+ line = tag;
+ found = 1;
+ }
+ }
+ else if (!_tcsnicmp(line, _T("[/color]"), 8))
+ {
+ line += 7;
+ found = 1;
+ }
+ }
+ if (!found)
+ {
+ if (*line < 128) *d++ = (char) *line;
+ else d += sprintf(d, "\\u%d ?", *line);
+ }
+ }
+ else if (*line < 128) *d++ = (char) *line;
+ else d += sprintf(d, "\\u%d ?", *line);
+ }
+
+ *(d++) = '}';
+ *d = 0;
+
+ *cbBufferEnd = (int) (d - *buffer);
+ return textCharsCount;
+}
+
+#ifdef _UNICODE
+ #define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}"
+#else
+ #define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %s;}"
+#endif
+
+static char *CreateRTFHeader(struct MessageWindowData *dat)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd;
+ int i;
+ LOGFONT lf;
+ COLORREF colour;
+ HDC hdc;
+
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+ bufferEnd = 0;
+ bufferAlloced = 1024;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+
+ for (i = 0; i < msgDlgFontCount; i++) {
+ LoadMsgDlgFont(i, &lf, NULL);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName);
+ }
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl ");
+ for (i = 0; i < msgDlgFontCount; i++) {
+ LoadMsgDlgFont(i, NULL, &colour);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour));
+ }
+ if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL)
+ colour = RGB(0, 0, 255);
+ else
+ colour = GetSysColor(COLOR_HOTLIGHT);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour));
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}");
+ //AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard");
+ return buffer;
+}
+
+//mir_free() the return value
+static char *CreateRTFTail(struct MessageWindowData *dat)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd;
+
+ bufferEnd = 0;
+ bufferAlloced = 1024;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}");
+ return buffer;
+}
+
+//return value is static
+static char *SetToStyle(int style)
+{
+ static char szStyle[128];
+ LOGFONT lf;
+
+ LoadMsgDlgFont(style, &lf, NULL);
+ wsprintfA(szStyle, "\\f%u\\cf%u\\b%d\\i%d\\fs%u", style, style, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / logPixelSY);
+ return szStyle;
+}
+
+int DbEventIsForMsgWindow(DBEVENTINFO *dbei)
+{
+ DBEVENTTYPEDESCR* et = ( DBEVENTTYPEDESCR* )CallService( MS_DB_EVENT_GETTYPE, ( WPARAM )dbei->szModule, ( LPARAM )dbei->eventType );
+ return et && ( et->flags & DETF_MSGWINDOW );
+}
+
+int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat)
+{
+ switch (dbei->eventType) {
+ case EVENTTYPE_MESSAGE:
+ return 1;
+ case EVENTTYPE_JABBER_CHATSTATES:
+ case EVENTTYPE_JABBER_PRESENCE:
+ case EVENTTYPE_STATUSCHANGE:
+ case EVENTTYPE_FILE:
+ return (dbei->flags & DBEF_READ) == 0;
+ }
+ return DbEventIsForMsgWindow(dbei);
+}
+
+//mir_free() the return value
+static char *CreateRTFFromDbEvent(struct MessageWindowData *dat, HANDLE hContact, HANDLE hDbEvent, struct LogStreamData *streamData)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd;
+ DBEVENTINFO dbei = { 0 };
+ int showColon = 0;
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) hDbEvent, 0);
+ if (dbei.cbBlob == -1)
+ return NULL;
+ dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob);
+ CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei);
+ if (!DbEventIsShown(&dbei, dat)) {
+ mir_free(dbei.pBlob);
+ return NULL;
+ }
+ if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)))
+ {
+ CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent);
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) hDbEvent);
+ }
+ else if (dbei.eventType == EVENTTYPE_STATUSCHANGE || dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) {
+ CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent);
+ }
+ bufferEnd = 0;
+ bufferAlloced = 1024;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+
+ if (!dat->bIsAutoRTL && !streamData->isEmpty)
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par");
+
+ if (dbei.flags & DBEF_RTL) {
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlpar");
+ dat->bIsAutoRTL = TRUE;
+ }
+ else
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrpar");
+
+ streamData->isEmpty = 0;
+
+ if (dat->bIsAutoRTL) {
+ if(dbei.flags & DBEF_RTL) {
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrch\\rtlch");
+ }else{
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlch\\ltrch");
+ }
+ }
+
+ if (g_dat->flags&SMF_SHOWICONS) {
+ int i;
+
+ switch (dbei.eventType) {
+ case EVENTTYPE_MESSAGE:
+ if (dbei.flags & DBEF_SENT) {
+ i = LOGICON_MSG_OUT;
+ }
+ else {
+ i = LOGICON_MSG_IN;
+ }
+ break;
+ case EVENTTYPE_JABBER_CHATSTATES:
+ case EVENTTYPE_JABBER_PRESENCE:
+ case EVENTTYPE_STATUSCHANGE:
+ case EVENTTYPE_FILE:
+ default:
+ i = LOGICON_MSG_NOTICE;
+ break;
+ }
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14");
+ while (bufferAlloced - bufferEnd < logIconBmpSize[i])
+ bufferAlloced += 1024;
+ buffer = (char *) mir_realloc(buffer, bufferAlloced);
+ CopyMemory(buffer + bufferEnd, pLogIconBmpBits[i], logIconBmpSize[i]);
+ bufferEnd += logIconBmpSize[i];
+ }
+ if (g_dat->flags & SMF_SHOWTIME)
+ {
+ const TCHAR* szFormat;
+ TCHAR str[64];
+
+ if (g_dat->flags & SMF_SHOWSECS)
+ szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d s") : _T("s");
+ else
+ szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d t") : _T("t");
+
+ tmi.printTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0);
+
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME));
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, str);
+ showColon = 1;
+ }
+ if (!(g_dat->flags&SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_STATUSCHANGE && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) {
+ TCHAR* szName;
+ CONTACTINFO ci = {0};
+
+ if (dbei.flags & DBEF_SENT) {
+ ci.cbSize = sizeof(ci);
+ ci.szProto = dbei.szModule;
+ ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ // CNF_DISPLAY always returns a string type
+ szName = ci.pszVal;
+ }
+ }
+ else szName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR);
+
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME));
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName);
+ showColon = 1;
+ if (ci.pszVal)
+ mir_free(ci.pszVal);
+ }
+
+ if (showColon)
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON));
+
+ switch (dbei.eventType) {
+ default:
+ case EVENTTYPE_MESSAGE:
+ {
+ TCHAR* msg = DbGetEventTextT( &dbei, CP_ACP );
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG));
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg);
+
+ mir_free(msg);
+ break;
+ }
+ case EVENTTYPE_JABBER_CHATSTATES:
+ case EVENTTYPE_JABBER_PRESENCE:
+ case EVENTTYPE_STATUSCHANGE:
+ {
+ TCHAR *msg, *szName;
+ CONTACTINFO ci = {0};
+
+ if (dbei.flags & DBEF_SENT) {
+ ci.cbSize = sizeof(ci);
+ ci.hContact = NULL;
+ ci.szProto = dbei.szModule;
+ ci.dwFlag = CNF_DISPLAY | CNF_TCHAR;
+
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
+ // CNF_DISPLAY always returns a string type
+ szName = ci.pszVal;
+ }
+ }
+ else szName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR);
+
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE));
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName);
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, _T(" "));
+
+ msg = DbGetEventTextT( &dbei, CP_ACP );
+ if ( msg ) {
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg);
+ mir_free( msg );
+ }
+ mir_free(ci.pszVal);
+ break;
+ }
+ case EVENTTYPE_FILE:
+ {
+ char* filename = dbei.pBlob + sizeof(DWORD);
+ char* descr = filename + strlen( filename ) + 1;
+ TCHAR* ptszFileName = DbGetEventStringT( &dbei, filename );
+
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE));
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced,
+ (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received"));
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, ": ");
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszFileName);
+ mir_free( ptszFileName );
+
+ if ( *descr != 0 ) {
+ TCHAR* ptszDescr = DbGetEventStringT( &dbei, descr );
+ AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, " (" );
+ AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszDescr);
+ AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, ")" );
+ mir_free( ptszDescr );
+ }
+ break;
+ } }
+
+ if(dat->bIsAutoRTL)
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par");
+
+ mir_free(dbei.pBlob);
+ return buffer;
+}
+
+static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
+{
+ struct LogStreamData *dat = (struct LogStreamData *) dwCookie;
+
+ if (dat->buffer == NULL)
+ {
+ dat->bufferOffset = 0;
+ switch (dat->stage)
+ {
+ case STREAMSTAGE_HEADER:
+ dat->buffer = CreateRTFHeader(dat->dlgDat);
+ dat->stage = STREAMSTAGE_EVENTS;
+ break;
+
+ case STREAMSTAGE_EVENTS:
+ if (dat->eventsToInsert)
+ {
+ do
+ {
+ dat->buffer = CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, dat);
+ if (dat->buffer)
+ dat->hDbEventLast = dat->hDbEvent;
+ dat->hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) dat->hDbEvent, 0);
+ if (--dat->eventsToInsert == 0)
+ break;
+ } while (dat->buffer == NULL && dat->hDbEvent);
+ if (dat->buffer)
+ {
+ dat->isEmpty = 0;
+ break;
+ }
+ }
+ dat->stage = STREAMSTAGE_TAIL;
+ //fall through
+ case STREAMSTAGE_TAIL:
+ dat->buffer = CreateRTFTail(dat->dlgDat);
+ dat->stage = STREAMSTAGE_STOP;
+ break;
+ case STREAMSTAGE_STOP:
+ *pcb = 0;
+ return 0;
+ }
+ dat->bufferLen = (int)strlen(dat->buffer);
+ }
+ *pcb = min(cb, dat->bufferLen - dat->bufferOffset);
+ CopyMemory(pbBuff, dat->buffer + dat->bufferOffset, *pcb);
+ dat->bufferOffset += *pcb;
+ if (dat->bufferOffset == dat->bufferLen)
+ {
+ mir_free(dat->buffer);
+ dat->buffer = NULL;
+ }
+ return 0;
+}
+
+void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend)
+{
+ EDITSTREAM stream = {0};
+ struct LogStreamData streamData = {0};
+ struct MessageWindowData *dat = (struct MessageWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ CHARRANGE oldSel, sel;
+ POINT scrollPos;
+ BOOL bottomScroll = TRUE;
+
+ HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG);
+
+ SendMessage(hwndLog, WM_SETREDRAW, FALSE, 0);
+ SendMessage(hwndLog, EM_EXGETSEL, 0, (LPARAM) & oldSel);
+ streamData.hContact = dat->hContact;
+ streamData.hDbEvent = hDbEventFirst;
+ streamData.dlgDat = dat;
+ streamData.eventsToInsert = count;
+ streamData.isEmpty = !fAppend || GetWindowTextLength(hwndLog) == 0;
+ stream.pfnCallback = LogStreamInEvents;
+ stream.dwCookie = (DWORD_PTR)&streamData;
+
+ if (!streamData.isEmpty)
+ {
+ bottomScroll = (GetFocus() != hwndLog);
+ if (bottomScroll && (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL))
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
+ GetScrollInfo(hwndLog, SB_VERT, &si);
+ bottomScroll = (si.nPos + (int)si.nPage) >= si.nMax;
+ }
+ if (!bottomScroll)
+ SendMessage(hwndLog, EM_GETSCROLLPOS, 0, (LPARAM) & scrollPos);
+ }
+ if (fAppend)
+ {
+ sel.cpMin = sel.cpMax = -1;
+ SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel);
+ }
+
+ strcpy(szSep2, fAppend ? "\\par\\sl0" : "\\sl1000");
+ strcpy(szSep2_RTL, fAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000");
+
+ SendMessage(hwndLog, EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM) & stream);
+ if (bottomScroll)
+ {
+ sel.cpMin = sel.cpMax = -1;
+ SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel);
+ if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)
+ {
+ SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0);
+ PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0);
+ }
+ }
+ else
+ {
+ SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & oldSel);
+ SendMessage(hwndLog, EM_SETSCROLLPOS, 0, (LPARAM) & scrollPos);
+ }
+
+ SendMessage(hwndLog, WM_SETREDRAW, TRUE, 0);
+ if (bottomScroll)
+ RedrawWindow(hwndLog, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+
+ dat->hDbEventLast = streamData.hDbEventLast;
+}
+
+#define RTFPICTHEADERMAXSIZE 78
+void LoadMsgLogIcons(void)
+{
+ HICON hIcon;
+ HBITMAP hBmp, hoBmp;
+ HDC hdc, hdcMem;
+ BITMAPINFOHEADER bih = { 0 };
+ int widthBytes, i;
+ RECT rc;
+ HBRUSH hBkgBrush;
+ int rtfHeaderSize;
+ PBYTE pBmpBits;
+
+ hBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = 10;
+ bih.biPlanes = 1;
+ bih.biWidth = 10;
+ widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+ rc.top = rc.left = 0;
+ rc.right = bih.biWidth;
+ rc.bottom = bih.biHeight;
+ hdc = GetDC(NULL);
+ hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ hdcMem = CreateCompatibleDC(hdc);
+ pBmpBits = (PBYTE) mir_alloc(widthBytes * bih.biHeight);
+
+ for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) {
+ hIcon = (HANDLE)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)hIconLibItem[i]);
+ pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2);
+ //I can't seem to get binary mode working. No matter.
+ rtfHeaderSize = sprintf(pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+
+ SelectObject(hdcMem, hoBmp);
+ GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS);
+ {
+ int n;
+ for (n = 0; n < sizeof(BITMAPINFOHEADER); n++)
+ sprintf(pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]);
+ for (n = 0; n < widthBytes * bih.biHeight; n += 4)
+ sprintf(pLogIconBmpBits[i] + rtfHeaderSize + (bih.biSize + n) * 2, "%02X%02X%02X%02X", pBmpBits[n], pBmpBits[n + 1], pBmpBits[n + 2], pBmpBits[n + 3]);
+ }
+ logIconBmpSize[i] = rtfHeaderSize + (bih.biSize + widthBytes * bih.biHeight) * 2 + 1;
+ pLogIconBmpBits[i][logIconBmpSize[i] - 1] = '}';
+ }
+ mir_free(pBmpBits);
+ DeleteDC(hdcMem);
+ DeleteObject(hBmp);
+ ReleaseDC(NULL, hdc);
+ DeleteObject(hBkgBrush);
+}
+
+void FreeMsgLogIcons(void)
+{
+ int i;
+ for (i = 0; i < SIZEOF(pLogIconBmpBits); i++)
+ mir_free(pLogIconBmpBits[i]);
+}
diff --git a/plugins/SRMM/msgoptions.c b/plugins/SRMM/msgoptions.c
new file mode 100644
index 0000000000..0cdfca4562
--- /dev/null
+++ b/plugins/SRMM/msgoptions.c
@@ -0,0 +1,725 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+
+#include "m_fontservice.h"
+#include "m_modernopt.h"
+
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+struct FontOptionsList
+{
+ const TCHAR* szDescr;
+ COLORREF defColour;
+ const TCHAR* szDefFace;
+ BYTE defStyle;
+ char defSize;
+}
+static const fontOptionsList[] =
+{
+ { LPGENT("Outgoing messages"), RGB(106, 106, 106), _T("Arial"), 0, -12},
+ { LPGENT("Incoming messages"), RGB(0, 0, 0), _T("Arial"), 0, -12},
+ { LPGENT("Outgoing name"), RGB(89, 89, 89), _T("Arial"), FONTF_BOLD, -12},
+ { LPGENT("Outgoing time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9},
+ { LPGENT("Outgoing colon"), RGB(89, 89, 89), _T("Arial"), 0, -11},
+ { LPGENT("Incoming name"), RGB(215, 0, 0), _T("Arial"), FONTF_BOLD, -12},
+ { LPGENT("Incoming time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9},
+ { LPGENT("Incoming colon"), RGB(215, 0, 0), _T("Arial"), 0, -11},
+ { LPGENT("Message area"), RGB(0, 0, 0), _T("Arial"), 0, -12},
+ { LPGENT("Notices"), RGB(90, 90, 160), _T("Arial"), 0, -12},
+};
+
+const int msgDlgFontCount = SIZEOF(fontOptionsList);
+
+#if defined( _UNICODE )
+static BYTE MsgDlgGetFontDefaultCharset(const TCHAR* szFont)
+{
+ return DEFAULT_CHARSET;
+}
+#else
+// get font charset according to current CP
+static BYTE MsgDlgGetCPDefaultCharset()
+{
+ switch (GetACP()) {
+ case 1250:
+ return EASTEUROPE_CHARSET;
+ case 1251:
+ return RUSSIAN_CHARSET;
+ case 1252:
+ return ANSI_CHARSET;
+ case 1253:
+ return GREEK_CHARSET;
+ case 1254:
+ return TURKISH_CHARSET;
+ case 1255:
+ return HEBREW_CHARSET;
+ case 1256:
+ return ARABIC_CHARSET;
+ case 1257:
+ return BALTIC_CHARSET;
+ case 1361:
+ return JOHAB_CHARSET;
+ case 874:
+ return THAI_CHARSET;
+ case 932:
+ return SHIFTJIS_CHARSET;
+ case 936:
+ return GB2312_CHARSET;
+ case 949:
+ return HANGEUL_CHARSET;
+ case 950:
+ return CHINESEBIG5_CHARSET;
+ default:
+ return DEFAULT_CHARSET;
+ }
+}
+
+static int CALLBACK EnumFontFamExProc(const LOGFONT *lpelfe, const TEXTMETRIC *lpntme, DWORD FontType, LPARAM lParam)
+{
+ *(int*)lParam = 1;
+ return 0;
+}
+
+// get font charset according to current CP, if available for specified font
+static BYTE MsgDlgGetFontDefaultCharset(const TCHAR* szFont)
+{
+ HDC hdc;
+ LOGFONT lf = {0};
+ int found = 0;
+
+ _tcscpy(lf.lfFaceName, szFont);
+ lf.lfCharSet = MsgDlgGetCPDefaultCharset();
+
+ // check if the font supports specified charset
+ hdc = GetDC(0);
+ EnumFontFamiliesEx(hdc, &lf, &EnumFontFamExProc, (LPARAM)&found, 0);
+ ReleaseDC(0, hdc);
+
+ if (found)
+ return lf.lfCharSet;
+ else // no, give default
+ return DEFAULT_CHARSET;
+}
+#endif
+
+void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF * colour)
+{
+ char str[32];
+ int style;
+ DBVARIANT dbv;
+
+ if ( colour ) {
+ mir_snprintf(str, SIZEOF(str), "SRMFont%dCol", i);
+ *colour = DBGetContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].defColour);
+ }
+ if ( lf ) {
+ mir_snprintf(str, SIZEOF(str), "SRMFont%dSize", i);
+ lf->lfHeight = (char) DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defSize);
+ lf->lfWidth = 0;
+ lf->lfEscapement = 0;
+ lf->lfOrientation = 0;
+ mir_snprintf(str, SIZEOF(str), "SRMFont%dSty", i);
+ style = DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defStyle);
+ lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL;
+ lf->lfItalic = style & FONTF_ITALIC ? 1 : 0;
+ lf->lfUnderline = 0;
+ lf->lfStrikeOut = 0;
+ lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf->lfQuality = DEFAULT_QUALITY;
+ lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ mir_snprintf(str, SIZEOF(str), "SRMFont%d", i);
+ if (DBGetContactSettingTString(NULL, SRMMMOD, str, &dbv))
+ _tcscpy(lf->lfFaceName, fontOptionsList[i].szDefFace);
+ else {
+ lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName));
+ DBFreeVariant(&dbv);
+ }
+ mir_snprintf(str, SIZEOF(str), "SRMFont%dSet", i);
+ lf->lfCharSet = DBGetContactSettingByte(NULL, SRMMMOD, str, MsgDlgGetFontDefaultCharset(lf->lfFaceName));
+} }
+
+void RegisterSRMMFonts( void )
+{
+ FontIDT fontid = {0};
+ ColourIDT colourid = {0};
+ char idstr[10];
+ int i, index = 0;
+
+ fontid.cbSize = sizeof(FontID);
+ fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID;
+ for ( i = 0; i < msgDlgFontCount; i++, index++ ) {
+ strcpy(fontid.dbSettingsGroup, SRMMMOD);
+ _tcscpy(fontid.group, LPGENT("Message Log"));
+ _tcscpy(fontid.name, fontOptionsList[i].szDescr);
+ mir_snprintf(idstr, SIZEOF(idstr), "SRMFont%d", index);
+ strcpy(fontid.prefix, idstr);
+ fontid.order = index;
+
+ fontid.flags &= ~FIDF_CLASSMASK;
+ fontid.flags |= (fontOptionsList[i].defStyle == FONTF_BOLD) ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL;
+
+ fontid.deffontsettings.colour = fontOptionsList[i].defColour;
+ fontid.deffontsettings.size = fontOptionsList[i].defSize;
+ fontid.deffontsettings.style = fontOptionsList[i].defStyle;
+ _tcscpy(fontid.deffontsettings.szFace, fontOptionsList[i].szDefFace);
+ fontid.deffontsettings.charset = MsgDlgGetFontDefaultCharset(fontOptionsList[i].szDefFace);
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0);
+ }
+
+ colourid.cbSize = sizeof(ColourID);
+ strcpy(colourid.dbSettingsGroup, SRMMMOD);
+ strcpy(colourid.setting, SRMSGSET_BKGCOLOUR);
+ colourid.defcolour = SRMSGDEFSET_BKGCOLOUR;
+ _tcscpy(colourid.name, LPGENT("Background"));
+ _tcscpy(colourid.group, LPGENT("Message Log"));
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&colourid, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct CheckBoxValues_t
+{
+ DWORD style;
+ TCHAR* szDescr;
+}
+static const statusValues[] =
+{
+ { MODEF_OFFLINE, LPGENT("Offline") },
+ { PF2_ONLINE, LPGENT("Online") },
+ { PF2_SHORTAWAY, LPGENT("Away") },
+ { PF2_LONGAWAY, LPGENT("NA") },
+ { PF2_LIGHTDND, LPGENT("Occupied") },
+ { PF2_HEAVYDND, LPGENT("DND") },
+ { PF2_FREECHAT, LPGENT("Free for chat") },
+ { PF2_INVISIBLE, LPGENT("Invisible") },
+ { PF2_OUTTOLUNCH, LPGENT("Out to lunch") },
+ { PF2_ONTHEPHONE, LPGENT("On the phone") }
+};
+
+static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style)
+{
+ TVINSERTSTRUCT tvis;
+ int i;
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
+ for (i = 0; i < nValues; i++) {
+ tvis.item.lParam = values[i].style;
+ tvis.item.pszText = TranslateTS(values[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1);
+ TreeView_InsertItem( hwndTree, &tvis );
+} }
+
+static DWORD MakeCheckBoxTreeFlags(HWND hwndTree)
+{
+ DWORD flags = 0;
+ TVITEM tvi;
+
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+ tvi.hItem = TreeView_GetRoot(hwndTree);
+ while (tvi.hItem) {
+ TreeView_GetItem(hwndTree, &tvi);
+ if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2))
+ flags |= tvi.lParam;
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+ return flags;
+}
+
+static INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ DWORD avatarHeight, msgTimeout;
+
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES);
+ FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_POPLIST), statusValues, SIZEOF(statusValues), DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS));
+ CheckDlgButton(hwndDlg, IDC_DONOTSTEALFOCUS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS));
+ SetDlgItemInt(hwndDlg, IDC_NFLASHES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT), FALSE);
+ CheckDlgButton(hwndDlg, IDC_SHOWBUTTONLINE, g_dat->flags&SMF_SHOWBTNS);
+ CheckDlgButton(hwndDlg, IDC_SHOWINFOLINE, g_dat->flags&SMF_SHOWINFO);
+ CheckDlgButton(hwndDlg, IDC_AUTOMIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN));
+ CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE));
+ CheckDlgButton(hwndDlg, IDC_SAVEPERCONTACT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT));
+ CheckDlgButton(hwndDlg, IDC_CASCADE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE));
+ CheckDlgButton(hwndDlg, IDC_SENDONENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER));
+ CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER));
+ CheckDlgButton(hwndDlg, IDC_STATUSWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON));
+
+ CheckDlgButton(hwndDlg, IDC_AVATARSUPPORT, g_dat->flags&SMF_AVATAR);
+ CheckDlgButton(hwndDlg, IDC_LIMITAVATARH, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT));
+ avatarHeight = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT);
+ SetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, avatarHeight, FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT));
+ if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE);
+ else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH));
+ CheckDlgButton(hwndDlg, IDC_SHOWSENDBTN, g_dat->flags&SMF_SENDBTN);
+ CheckDlgButton(hwndDlg, IDC_CHARCOUNT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT));
+ CheckDlgButton(hwndDlg, IDC_CTRLSUPPORT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT));
+ CheckDlgButton(hwndDlg, IDC_DELTEMP, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP));
+ msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT);
+ SetDlgItemInt(hwndDlg, IDC_SECONDS, msgTimeout >= SRMSGSET_MSGTIMEOUT_MIN ? msgTimeout / 1000 : SRMSGDEFSET_MSGTIMEOUT / 1000, FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_AUTOMIN:
+ CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, BST_UNCHECKED);
+ break;
+ case IDC_AUTOCLOSE:
+ CheckDlgButton(hwndDlg, IDC_AUTOMIN, BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE));
+ break;
+ case IDC_SENDONENTER:
+ CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, BST_UNCHECKED);
+ break;
+ case IDC_SENDONDBLENTER:
+ CheckDlgButton(hwndDlg, IDC_SENDONENTER, BST_UNCHECKED);
+ break;
+ case IDC_SAVEPERCONTACT:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT));
+ break;
+ case IDC_SECONDS:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
+ return 0;
+ break;
+ case IDC_AVATARSUPPORT:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT));
+ if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT))
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE);
+ else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH));
+ break;
+ case IDC_LIMITAVATARH:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH));
+ break;
+ case IDC_AVATARHEIGHT:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
+ return 0;
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case IDC_POPLIST:
+ if (((LPNMHDR) lParam)->code == NM_CLICK) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short) LOWORD(GetMessagePos());
+ hti.pt.y = (short) HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt);
+ if (TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti))
+ if (hti.flags & TVHT_ONITEMSTATEICON) {
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1;
+ TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ DWORD avatarHeight, msgTimeout;
+
+ DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_POPLIST)));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DONOTSTEALFOCUS));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWBUTTONLINE));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWINFOLINE));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOMIN));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CASCADE));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONENTER));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONDBLENTER));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_STATUSWIN));
+
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH));
+ avatarHeight = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, NULL, TRUE);
+ DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, avatarHeight<=0?SRMSGDEFSET_AVHEIGHT:avatarHeight);
+
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSENDBTN));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CHARCOUNT));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CTRLSUPPORT));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DELTEMP));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, (BYTE) GetDlgItemInt(hwndDlg, IDC_NFLASHES, NULL, TRUE));
+
+ msgTimeout = GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, TRUE) * 1000;
+ if (msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) msgTimeout = SRMSGDEFSET_MSGTIMEOUT;
+ DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, msgTimeout);
+
+ ReloadGlobals();
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcLogOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HBRUSH hBkgColourBrush;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ switch (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY)) {
+ case LOADHISTORY_UNREAD:
+ CheckDlgButton(hwndDlg, IDC_LOADUNREAD, BST_CHECKED);
+ break;
+ case LOADHISTORY_COUNT:
+ CheckDlgButton(hwndDlg, IDC_LOADCOUNT, BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), TRUE);
+ break;
+ case LOADHISTORY_TIME:
+ CheckDlgButton(hwndDlg, IDC_LOADTIME, BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), TRUE);
+ break;
+ }
+ SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
+ SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT));
+ SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETRANGE, 0, MAKELONG(12 * 60, 0));
+ SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME));
+
+ CheckDlgButton(hwndDlg, IDC_SHOWLOGICONS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS));
+ CheckDlgButton(hwndDlg, IDC_SHOWNAMES, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES));
+ CheckDlgButton(hwndDlg, IDC_SHOWTIMES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES));
+ CheckDlgButton(hwndDlg, IDC_SHOWSECS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES));
+ CheckDlgButton(hwndDlg, IDC_SHOWDATES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE));
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUSCHANGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH));
+ CheckDlgButton(hwndDlg, IDC_SHOWFORMATTING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT));
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_LOADUNREAD:
+ case IDC_LOADCOUNT:
+ case IDC_LOADTIME:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME));
+ break;
+
+ case IDC_SHOWTIMES:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES));
+ break;
+
+ case IDC_LOADCOUNTN:
+ case IDC_LOADTIMEN:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
+ return TRUE;
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ if (IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT))
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_COUNT);
+ else if (IsDlgButtonChecked(hwndDlg, IDC_LOADTIME))
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_TIME);
+ else
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_UNREAD);
+ DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_GETPOS, 0, 0));
+ DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_GETPOS, 0, 0));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWLOGICONS));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSECS));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSCHANGES));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWFORMATTING));
+
+ FreeMsgLogIcons();
+ LoadMsgLogIcons();
+ ReloadGlobals();
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0);
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ DeleteObject(hBkgColourBrush);
+ break;
+ }
+ return FALSE;
+}
+
+static ResetCList(HWND hwndDlg)
+{
+ int i;
+
+ if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS && !DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT))
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) FALSE, 0);
+ else
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN, 2, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP, 0, (LPARAM) (HBITMAP) NULL);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT, 10, 0);
+ for (i = 0; i <= FONTID_MAX; i++)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+}
+
+static void RebuildList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown)
+{
+ HANDLE hContact, hItem;
+ BYTE defType = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW);
+
+ if (hItemNew && defType) {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemNew, 1);
+ }
+ if (hItemUnknown && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemUnknown, 1);
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do {
+ hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0);
+ if (hItem && DBGetContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, defType)) {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItem, 1);
+ }
+ } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0));
+}
+
+static void SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown)
+{
+ HANDLE hContact, hItem;
+
+ if (hItemNew) {
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemNew, 0) ? 1 : 0));
+ }
+ if (hItemUnknown) {
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemUnknown, 0) ? 1 : 0));
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do {
+ hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0);
+ if (hItem) {
+ DBWriteContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0) ? 1 : 0));
+ }
+ } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0));
+}
+
+static INT_PTR CALLBACK DlgProcTypeOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hItemNew, hItemUnknown;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ CLCINFOITEM cii = { 0 };
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX;
+ cii.pszText = TranslateT("** New contacts **");
+ hItemNew = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii);
+ cii.pszText = TranslateT("** Unknown contacts **");
+ hItemUnknown = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii);
+ }
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE) | (CLS_SHOWHIDDEN) | (CLS_NOHIDEOFFLINE));
+ ResetCList(hwndDlg);
+ RebuildList(hwndDlg, hItemNew, hItemUnknown);
+ CheckDlgButton(hwndDlg, IDC_SHOWNOTIFY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING));
+ CheckDlgButton(hwndDlg, IDC_TYPEWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN));
+ CheckDlgButton(hwndDlg, IDC_TYPETRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN));
+ CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST));
+ CheckDlgButton(hwndDlg, IDC_NOTIFYBALLOON, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY));
+ if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE);
+ CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, BST_CHECKED);
+ SetWindowText(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TranslateT("Show balloon popup (unsupported system)"));
+ }
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_TYPETRAY:
+ if (IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)) {
+ if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE);
+ }
+ else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TRUE);
+ }
+ }
+ else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE);
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case IDC_SHOWNOTIFY:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)
+ && ServiceExists(MS_CLIST_SYSTRAY_NOTIFY));
+ //fall-thru
+ case IDC_TYPEWIN:
+ case IDC_NOTIFYTRAY:
+ case IDC_NOTIFYBALLOON:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (((NMHDR *) lParam)->idFrom) {
+ case IDC_CLIST:
+ switch (((NMHDR *) lParam)->code) {
+ case CLN_OPTIONSCHANGED:
+ ResetCList(hwndDlg);
+ break;
+ case CLN_CHECKCHANGED:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY:
+ {
+ SaveList(hwndDlg, hItemNew, hItemUnknown);
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPEWIN));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY));
+ DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NOTIFYTRAY));
+ ReloadGlobals();
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int OptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ odp.cbSize = sizeof(odp);
+ odp.position = 910000000;
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGDLG);
+ odp.pszTab = LPGEN("Messaging");
+ odp.pszTitle = LPGEN("Message Sessions");
+ odp.pfnDlgProc = DlgProcOptions;
+ odp.flags = ODPF_BOLDGROUPS;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGLOG);
+ odp.pszTab = LPGEN("Messaging Log");
+ odp.pfnDlgProc = DlgProcLogOptions;
+ odp.nIDBottomSimpleControl = IDC_STMSGLOGGROUP;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGTYPE);
+ odp.pszTab = LPGEN("Typing Notify");
+ odp.pfnDlgProc = DlgProcTypeOptions;
+ odp.nIDBottomSimpleControl = 0;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp);
+ return 0;
+}
+
+static int ModernOptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ static int iBoldControls[] =
+ {
+ IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_TXT_TITLE3,
+ MODERNOPT_CTRL_LAST
+ };
+
+ MODERNOPTOBJECT obj = {0};
+
+ obj.cbSize = sizeof(obj);
+ obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE;
+ obj.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ obj.hInstance = g_hInst;
+ obj.iSection = MODERNOPT_PAGE_MSGS;
+ obj.iType = MODERNOPT_TYPE_SECTIONPAGE;
+ obj.iBoldControls = iBoldControls;
+ obj.lpzClassicGroup = NULL;
+ obj.lpzClassicPage = "Message Sessions";
+ obj.lpzClassicTab = "Messaging";
+ obj.lpzHelpUrl = "http://wiki.miranda-im.org/";
+
+ obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGDLG);
+ obj.pfnDlgProc = DlgProcOptions;
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+
+ obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGLOG);
+ obj.pfnDlgProc = DlgProcLogOptions;
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+
+ return 0;
+}
+
+static HANDLE oHooks[2];
+
+void InitOptions(void)
+{
+ oHooks[0] = HookEvent(ME_OPT_INITIALISE, OptInitialise);
+ oHooks[1] = HookEvent(ME_MODERNOPT_INITIALIZE, ModernOptInitialise);
+}
+
+void UnloadOptions(void)
+{
+ int i;
+ for (i=0; i < SIZEOF(oHooks); ++i)
+ if (oHooks[i])
+ UnhookEvent(oHooks[i]);
+}
diff --git a/plugins/SRMM/msgs.c b/plugins/SRMM/msgs.c
new file mode 100644
index 0000000000..bfba1b6299
--- /dev/null
+++ b/plugins/SRMM/msgs.c
@@ -0,0 +1,595 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+#include "statusicon.h"
+
+/* Missing MinGW GUIDs */
+#ifdef __MINGW32__
+const CLSID IID_IRichEditOle = { 0x00020D00, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
+const CLSID IID_IRichEditOleCallback = { 0x00020D03, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
+#endif
+
+static void InitREOleCallback(void);
+
+HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
+HANDLE hHookWinEvt, hHookWinPopup, hMsgMenuItem;
+static HANDLE hServices[7];
+static HANDLE hHooks[8];
+
+static int SRMMStatusToPf2(int status)
+{
+ switch (status) {
+ case ID_STATUS_ONLINE: return PF2_ONLINE;
+ case ID_STATUS_AWAY: return PF2_SHORTAWAY;
+ case ID_STATUS_DND: return PF2_HEAVYDND;
+ case ID_STATUS_NA: return PF2_LONGAWAY;
+ case ID_STATUS_OCCUPIED: return PF2_LIGHTDND;
+ case ID_STATUS_FREECHAT: return PF2_FREECHAT;
+ case ID_STATUS_INVISIBLE: return PF2_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE;
+ case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH;
+ case ID_STATUS_OFFLINE: return MODEF_OFFLINE;
+ }
+ return 0;
+}
+
+static int MessageEventAdded(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei = {0};
+ HWND hwnd;
+
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei);
+
+ if (dbei.flags & (DBEF_SENT | DBEF_READ) || !(dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)))
+ return 0;
+
+ CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1);
+ /* does a window for the contact exist? */
+ hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam);
+ if (hwnd)
+ {
+ if (!DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS))
+ {
+ ShowWindow(hwnd, SW_RESTORE);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+ SetForegroundWindow(hwnd);
+ SkinPlaySound("RecvMsgActive");
+ }
+ else
+ {
+ if (GetForegroundWindow() == hwnd)
+ SkinPlaySound("RecvMsgActive");
+ else
+ SkinPlaySound("RecvMsgInactive");
+ }
+ return 0;
+ }
+ /* new message */
+ SkinPlaySound("AlertMsg");
+ {
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0);
+ if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0))))
+ {
+ struct NewMessageWindowLParam newData = { 0 };
+ newData.hContact = (HANDLE) wParam;
+ newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS);
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData);
+ return 0;
+ }
+ }
+ {
+ TCHAR toolTip[256], *contactName;
+ CLISTEVENT cle = {0};
+ cle.cbSize = sizeof(cle);
+ cle.hContact = (HANDLE) wParam;
+ cle.hDbEvent = (HANDLE) lParam;
+ cle.flags = CLEF_TCHAR;
+ cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ cle.pszService = "SRMsg/ReadMessage";
+ contactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR);
+ mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), contactName);
+ cle.ptszTooltip = toolTip;
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle);
+ }
+ return 0;
+}
+
+INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar)
+{
+ char *szProto;
+ HWND hwnd;
+
+ /* does the HCONTACT's protocol support IM messages? */
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (!szProto || (!CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND))
+ return 1;
+
+ if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact))
+ {
+ if (msg)
+ {
+ HWND hEdit;
+ hEdit = GetDlgItem(hwnd, IDC_MESSAGE);
+ SendMessage(hEdit, EM_SETSEL, -1, SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0));
+ if (isWchar)
+ SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg);
+ else
+ SendMessageA(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg);
+ }
+ ShowWindow(hwnd, SW_RESTORE);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+ SetForegroundWindow(hwnd);
+ }
+ else
+ {
+ struct NewMessageWindowLParam newData = { 0 };
+ newData.hContact = hContact;
+ newData.szInitialText = msg;
+ newData.isWchar = isWchar;
+ hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM)&newData);
+ }
+ return 0;
+}
+
+#if defined(_UNICODE)
+static INT_PTR SendMessageCommand_W(WPARAM wParam, LPARAM lParam)
+{
+ return SendMessageCmd((HANDLE)wParam, (char*)lParam, TRUE);
+}
+#endif
+
+static INT_PTR SendMessageCommand(WPARAM wParam, LPARAM lParam)
+{
+ return SendMessageCmd((HANDLE)wParam, (char*)lParam, FALSE);
+}
+
+static INT_PTR ReadMessageCommand(WPARAM wParam, LPARAM lParam)
+{
+ CLISTEVENT *cle = (CLISTEVENT *) lParam;
+
+ if (cle)
+ SendMessageCmd(cle->hContact, NULL, 0);
+
+ return 0;
+}
+
+static int TypingMessage(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+ int foundWin = 0;
+
+ if (!(g_dat->flags&SMF_SHOWTYPING))
+ return 0;
+ if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) {
+ SendMessage(hwnd, DM_TYPING, 0, lParam);
+ foundWin = 1;
+ }
+ if (lParam && !foundWin && (g_dat->flags&SMF_SHOWTYPINGTRAY)) {
+ TCHAR szTip[256];
+ mir_sntprintf(szTip, SIZEOF(szTip), TranslateT("%s is typing a message"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR));
+
+ if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY) && !(g_dat->flags&SMF_SHOWTYPINGCLIST)) {
+ MIRANDASYSTRAYNOTIFY tn = {0};
+ tn.cbSize = sizeof(tn);
+ tn.tszInfoTitle = TranslateT("Typing Notification");
+ tn.tszInfo = szTip;
+ tn.dwInfoFlags = NIIF_INFO;
+#ifdef _UNICODE
+ tn.dwInfoFlags |= NIIF_INTERN_UNICODE;
+#endif
+ tn.uTimeout = 1000 * 4;
+ CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM) & tn);
+ }
+ else {
+ CLISTEVENT cle = {0};
+
+ cle.cbSize = sizeof(cle);
+ cle.hContact = (HANDLE) wParam;
+ cle.hDbEvent = (HANDLE) 1;
+ cle.flags = CLEF_ONLYAFEW | CLEF_TCHAR;
+ cle.hIcon = LoadSkinnedIcon( SKINICON_OTHER_TYPING );
+ cle.pszService = "SRMsg/ReadMessage";
+ cle.ptszTooltip = szTip;
+ CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1);
+ CallServiceSync(MS_CLIST_ADDEVENT, wParam, (LPARAM) & cle);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)cle.hIcon, 0);
+ }
+ }
+ return 0;
+}
+
+static int MessageSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (cws->szModule == NULL) return 0;
+
+ if (!strcmp(cws->szModule, "CList"))
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0);
+ else if (hContact)
+ {
+ if (cws->szSetting && !strcmp(cws->szSetting, "Timezone"))
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_NEWTIMEZONE, (WPARAM) cws, 0);
+ else
+ {
+ char * szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto && !strcmp(cws->szModule, szProto))
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0);
+ }
+ }
+ return 0;
+}
+
+static int ContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+ if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam))
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+
+ return 0;
+}
+
+static void RestoreUnreadMessageAlerts(void)
+{
+ CLISTEVENT cle = {0};
+ DBEVENTINFO dbei = {0};
+ TCHAR toolTip[256];
+ int windowAlreadyExists;
+ HANDLE hDbEvent, hContact;
+ int autoPopup;
+
+ dbei.cbSize = sizeof(dbei);
+ cle.cbSize = sizeof(cle);
+ cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ cle.pszService = "SRMsg/ReadMessage";
+ cle.flags = CLEF_TCHAR;
+ cle.ptszTooltip = toolTip;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0);
+ while (hDbEvent)
+ {
+ autoPopup = 0;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei);
+ if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && ( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)))
+ {
+ windowAlreadyExists = WindowList_Find(g_dat->hMessageWindowList, hContact) != NULL;
+ if (windowAlreadyExists)
+ continue;
+ {
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0))))
+ {
+ autoPopup = 1;
+ }
+ }
+ if (autoPopup && !windowAlreadyExists)
+ {
+ struct NewMessageWindowLParam newData = {0};
+ newData.hContact = hContact;
+ newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS);
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData);
+ }
+ else
+ {
+ cle.hContact = hContact;
+ cle.hDbEvent = hDbEvent;
+ mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR));
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle);
+ }
+ }
+ hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0);
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+}
+
+void RegisterSRMMFonts( void );
+
+static int FontsChanged(WPARAM wParam,LPARAM lParam)
+{
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0);
+ return 0;
+}
+
+static int SplitmsgModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ RegisterSRMMFonts();
+ LoadMsgLogIcons();
+ {
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000090000;
+ mi.flags = CMIF_ICONFROMICOLIB | CMIF_DEFAULT;
+ mi.icolibItem = LoadSkinnedIconHandle( SKINICON_EVENT_MESSAGE );
+ mi.pszName = LPGEN("&Message");
+ mi.pszService = MS_MSG_SENDMESSAGE;
+ hMsgMenuItem = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+ }
+ HookEvent(ME_FONT_RELOAD, FontsChanged);
+
+ RestoreUnreadMessageAlerts();
+ return 0;
+}
+
+int PreshutdownSendRecv(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_BroadcastAsync(g_dat->hMessageWindowList, WM_CLOSE, 0, 0);
+ DeinitStatusIcons();
+ return 0;
+}
+
+int SplitmsgShutdown(void)
+{
+ int i;
+
+ DestroyCursor(hCurSplitNS);
+ DestroyCursor(hCurHyperlinkHand);
+ DestroyCursor(hCurSplitWE);
+
+ for (i=0; i < SIZEOF(hHooks); ++i)
+ if (hHooks[i])
+ UnhookEvent(hHooks[i]);
+
+ for ( i=0; i < SIZEOF(hServices); ++i)
+ if (hServices[i])
+ DestroyServiceFunction(hServices[i]);
+
+ FreeMsgLogIcons();
+ FreeLibrary(GetModuleHandleA("riched20"));
+ OleUninitialize();
+ RichUtil_Unload();
+ msgQueue_destroy();
+ FreeGlobals();
+ return 0;
+}
+
+static int IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ FreeMsgLogIcons();
+ LoadMsgLogIcons();
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_REMAKELOG, 0, 0);
+ // change all the icons
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATEWINICON, 0, 0);
+ return 0;
+}
+
+static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof( CLISTMENUITEM );
+ clmi.flags = CMIM_FLAGS | CMIF_DEFAULT | CMIF_HIDDEN;
+
+ if ( szProto ) {
+ // leave this menu item hidden for chats
+ if ( !DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0 ))
+ if ( CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND )
+ clmi.flags &= ~CMIF_HIDDEN;
+ }
+
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMsgMenuItem, ( LPARAM )&clmi );
+ }
+ return 0;
+}
+
+static INT_PTR GetWindowAPI(WPARAM wParam, LPARAM lParam)
+{
+ return PLUGIN_MAKE_VERSION(0,0,0,4);
+}
+
+static INT_PTR GetWindowClass(WPARAM wParam, LPARAM lParam)
+{
+ char *szBuf = (char*)wParam;
+ int size = (int)lParam;
+ mir_snprintf(szBuf, size, SRMMMOD);
+ return 0;
+}
+
+static INT_PTR GetWindowData(WPARAM wParam, LPARAM lParam)
+{
+ MessageWindowInputData *mwid = (MessageWindowInputData*)wParam;
+ MessageWindowData *mwd = (MessageWindowData*)lParam;
+ HWND hwnd;
+
+ if (mwid==NULL||mwd==NULL) return 1;
+ if (mwid->cbSize!=sizeof(MessageWindowInputData)||mwd->cbSize!=sizeof(MessageWindowData)) return 1;
+ if (mwid->hContact==NULL) return 1;
+ if (mwid->uFlags!=MSG_WINDOW_UFLAG_MSG_BOTH) return 1;
+ hwnd = WindowList_Find(g_dat->hMessageWindowList, mwid->hContact);
+ mwd->uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+ mwd->hwndWindow = hwnd;
+ mwd->local = 0;
+ mwd->uState = SendMessage(hwnd, DM_GETWINDOWSTATE, 0, 0);
+ return 0;
+}
+
+int LoadSendRecvMessageModule(void)
+{
+ if (LoadLibraryA("riched20.dll") == NULL) {
+ if (IDYES !=
+ MessageBox(0,
+ TranslateT
+ ("Miranda could not load the built-in message module, riched20.dll is missing. If you are using Windows 95 or WINE please make sure you have riched20.dll installed. Press 'Yes' to continue loading Miranda."),
+ TranslateT("Information"), MB_YESNO | MB_ICONINFORMATION))
+ return 1;
+ return 0;
+ }
+
+ InitGlobals();
+ RichUtil_Load();
+ OleInitialize(NULL);
+ InitREOleCallback();
+ InitOptions();
+ msgQueue_init();
+
+ hHooks[0] = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded);
+ hHooks[1] = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, MessageSettingChanged);
+ hHooks[2] = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted);
+ hHooks[3] = HookEvent(ME_SYSTEM_MODULESLOADED, SplitmsgModulesLoaded);
+ hHooks[4] = HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged);
+ hHooks[5] = HookEvent(ME_PROTO_CONTACTISTYPING, TypingMessage);
+ hHooks[6] = HookEvent(ME_SYSTEM_PRESHUTDOWN, PreshutdownSendRecv);
+ hHooks[7] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu);
+
+ hServices[0] = CreateServiceFunction(MS_MSG_SENDMESSAGE, SendMessageCommand);
+#ifdef _UNICODE
+ hServices[1] = CreateServiceFunction(MS_MSG_SENDMESSAGEW, SendMessageCommand_W);
+#endif
+ hServices[2] = CreateServiceFunction(MS_MSG_GETWINDOWAPI, GetWindowAPI);
+ hServices[3] = CreateServiceFunction(MS_MSG_GETWINDOWCLASS, GetWindowClass);
+ hServices[4] = CreateServiceFunction(MS_MSG_GETWINDOWDATA, GetWindowData);
+ hServices[5] = CreateServiceFunction("SRMsg/ReadMessage", ReadMessageCommand);
+
+ hHookWinEvt = CreateHookableEvent(ME_MSG_WINDOWEVENT);
+ hHookWinPopup = CreateHookableEvent(ME_MSG_WINDOWPOPUP);
+
+ SkinAddNewSoundEx("RecvMsgActive", LPGEN("Instant messages"), LPGEN("Incoming (Focused Window)"));
+ SkinAddNewSoundEx("RecvMsgInactive", LPGEN("Instant messages"), LPGEN("Incoming (Unfocused Window)"));
+ SkinAddNewSoundEx("AlertMsg", LPGEN("Instant messages"), LPGEN("Incoming (New Session)"));
+ SkinAddNewSoundEx("SendMsg", LPGEN("Instant messages"), LPGEN("Outgoing"));
+ SkinAddNewSoundEx("SendError", LPGEN("Instant messages"), LPGEN("Message send error"));
+
+ hCurSplitNS = LoadCursor(NULL, IDC_SIZENS);
+ hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE);
+ hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND);
+ if (hCurHyperlinkHand == NULL)
+ hCurHyperlinkHand = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_HYPERLINKHAND));
+
+ InitStatusIcons();
+ return 0;
+}
+
+static IRichEditOleCallbackVtbl reOleCallbackVtbl;
+struct CREOleCallback reOleCallback;
+
+static STDMETHODIMP_(ULONG) CREOleCallback_QueryInterface(struct CREOleCallback *lpThis, REFIID riid, LPVOID * ppvObj)
+{
+ if (IsEqualIID(riid, &IID_IRichEditOleCallback)) {
+ *ppvObj = lpThis;
+ lpThis->lpVtbl->AddRef((IRichEditOleCallback *) lpThis);
+ return S_OK;
+ }
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+}
+
+static STDMETHODIMP_(ULONG) CREOleCallback_AddRef(struct CREOleCallback *lpThis)
+{
+ if (lpThis->refCount == 0) {
+ if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &lpThis->pictStg))
+ lpThis->pictStg = NULL;
+ lpThis->nextStgId = 0;
+ }
+ return ++lpThis->refCount;
+}
+
+static STDMETHODIMP_(ULONG) CREOleCallback_Release(struct CREOleCallback *lpThis)
+{
+ if (--lpThis->refCount == 0) {
+ if (lpThis->pictStg)
+ lpThis->pictStg->lpVtbl->Release(lpThis->pictStg);
+ }
+ return lpThis->refCount;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_ContextSensitiveHelp(struct CREOleCallback *lpThis, BOOL fEnterMode)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_DeleteObject(struct CREOleCallback *lpThis, LPOLEOBJECT lpoleobj)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_GetClipboardData(struct CREOleCallback *lpThis, CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj)
+{
+ return E_NOTIMPL;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_GetContextMenu(struct CREOleCallback *lpThis, WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu)
+{
+ return E_INVALIDARG;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_GetDragDropEffect(struct CREOleCallback *lpThis, BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_GetInPlaceContext(struct CREOleCallback *lpThis, LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ return E_INVALIDARG;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_GetNewStorage(struct CREOleCallback *lpThis, LPSTORAGE * lplpstg)
+{
+ WCHAR szwName[64];
+ char szName[64];
+ wsprintfA(szName, "s%u", lpThis->nextStgId++);
+ MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName));
+ if (lpThis->pictStg == NULL)
+ return STG_E_MEDIUMFULL;
+ return lpThis->pictStg->lpVtbl->CreateStorage(lpThis->pictStg, szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg);
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_QueryAcceptData(struct CREOleCallback *lpThis, LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_QueryInsertObject(struct CREOleCallback *lpThis, LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP_(HRESULT) CREOleCallback_ShowContainerUI(struct CREOleCallback *lpThis, BOOL fShow)
+{
+ return S_OK;
+}
+
+static void InitREOleCallback(void)
+{
+ reOleCallback.lpVtbl = &reOleCallbackVtbl;
+ reOleCallback.lpVtbl->AddRef = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_AddRef;
+ reOleCallback.lpVtbl->Release = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_Release;
+ reOleCallback.lpVtbl->QueryInterface = (ULONG(__stdcall *) (IRichEditOleCallback *, REFIID, PVOID *)) CREOleCallback_QueryInterface;
+ reOleCallback.lpVtbl->ContextSensitiveHelp = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ContextSensitiveHelp;
+ reOleCallback.lpVtbl->DeleteObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEOBJECT)) CREOleCallback_DeleteObject;
+ reOleCallback.lpVtbl->GetClipboardData = (HRESULT(__stdcall *) (IRichEditOleCallback *, CHARRANGE *, DWORD, LPDATAOBJECT *)) CREOleCallback_GetClipboardData;
+ reOleCallback.lpVtbl->GetContextMenu = (HRESULT(__stdcall *) (IRichEditOleCallback *, WORD, LPOLEOBJECT, CHARRANGE *, HMENU *)) CREOleCallback_GetContextMenu;
+ reOleCallback.lpVtbl->GetDragDropEffect = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL, DWORD, LPDWORD)) CREOleCallback_GetDragDropEffect;
+ reOleCallback.lpVtbl->GetInPlaceContext = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEINPLACEFRAME *, LPOLEINPLACEUIWINDOW *, LPOLEINPLACEFRAMEINFO))
+ CREOleCallback_GetInPlaceContext;
+ reOleCallback.lpVtbl->GetNewStorage = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPSTORAGE *)) CREOleCallback_GetNewStorage;
+ reOleCallback.lpVtbl->QueryAcceptData = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPDATAOBJECT, CLIPFORMAT *, DWORD, BOOL, HGLOBAL)) CREOleCallback_QueryAcceptData;
+ reOleCallback.lpVtbl->QueryInsertObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPCLSID, LPSTORAGE, LONG)) CREOleCallback_QueryInsertObject;
+ reOleCallback.lpVtbl->ShowContainerUI = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ShowContainerUI;
+ reOleCallback.refCount = 0;
+}
diff --git a/plugins/SRMM/msgs.h b/plugins/SRMM/msgs.h
new file mode 100644
index 0000000000..842b291a08
--- /dev/null
+++ b/plugins/SRMM/msgs.h
@@ -0,0 +1,217 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#ifndef SRMM_MSGS_H
+#define SRMM_MSGS_H
+
+#include <richedit.h>
+#include <richole.h>
+
+struct NewMessageWindowLParam
+{
+ HANDLE hContact;
+ const char *szInitialText;
+ int isWchar;
+ int noActivate;
+};
+
+struct MessageWindowData
+{
+ HANDLE hContact;
+ HANDLE hDbEventFirst, hDbEventLast;
+ HBRUSH hBkgBrush;
+ WNDPROC OldMessageEditProc, OldSplitterProc;
+ int splitterPos, originalSplitterPos;
+ SIZE minEditBoxSize;
+ RECT minEditInit;
+ int lineHeight;
+ int windowWasCascaded;
+ DWORD nFlash;
+ int nLabelRight;
+ int nTypeSecs;
+ int nTypeMode;
+ int avatarWidth;
+ int avatarHeight;
+ int limitAvatarH;
+ HBITMAP avatarPic;
+ DWORD nLastTyping;
+ int showTyping;
+ DWORD lastMessage;
+ HWND hwndStatus;
+ HANDLE hTimeZone;
+ char *szProto;
+ WORD wStatus;
+ WORD wOldStatus;
+ int cmdListInd;
+ SortedList *cmdList;
+ int bIsAutoRTL;
+ WORD wMinute;
+};
+
+#define DM_REMAKELOG (WM_USER+11)
+#define HM_DBEVENTADDED (WM_USER+12)
+#define DM_CASCADENEWWINDOW (WM_USER+13)
+#define DM_OPTIONSAPPLIED (WM_USER+14)
+#define DM_SPLITTERMOVED (WM_USER+15)
+#define DM_UPDATETITLE (WM_USER+16)
+#define DM_APPENDTOLOG (WM_USER+17)
+#define DM_NEWTIMEZONE (WM_USER+18)
+#define DM_SCROLLLOGTOBOTTOM (WM_USER+19)
+#define DM_TYPING (WM_USER+20)
+#define DM_UPDATEWINICON (WM_USER+21)
+#define DM_UPDATELASTMESSAGE (WM_USER+22)
+#define DM_USERNAMETOCLIP (WM_USER+23)
+#define DM_AVATARSIZECHANGE (WM_USER+24)
+#define DM_AVATARCALCSIZE (WM_USER+25)
+#define DM_GETAVATAR (WM_USER+26)
+#define DM_UPDATESIZEBAR (WM_USER+27)
+#define HM_AVATARACK (WM_USER+28)
+#define DM_GETWINDOWSTATE (WM_USER+30)
+#define DM_STATUSICONCHANGE (WM_USER+31)
+
+#define EVENTTYPE_JABBER_CHATSTATES 2000
+#define EVENTTYPE_JABBER_PRESENCE 2001
+#define EVENTTYPE_STATUSCHANGE 25368
+
+struct CREOleCallback
+{
+ IRichEditOleCallbackVtbl *lpVtbl;
+ unsigned refCount;
+ IStorage *pictStg;
+ int nextStgId;
+};
+
+INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+int DbEventIsForMsgWindow(DBEVENTINFO *dbei);
+int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat);
+void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend);
+HANDLE SendMessageDirect(const TCHAR *szMsg, HANDLE hContact, char *szProto);
+
+void LoadMsgLogIcons(void);
+void FreeMsgLogIcons(void);
+
+void InitOptions(void);
+void UnloadOptions(void);
+
+#define MSGFONTID_MYMSG 0
+#define MSGFONTID_YOURMSG 1
+#define MSGFONTID_MYNAME 2
+#define MSGFONTID_MYTIME 3
+#define MSGFONTID_MYCOLON 4
+#define MSGFONTID_YOURNAME 5
+#define MSGFONTID_YOURTIME 6
+#define MSGFONTID_YOURCOLON 7
+#define MSGFONTID_MESSAGEAREA 8
+#define MSGFONTID_NOTICE 9
+
+void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF* colour);
+extern const int msgDlgFontCount;
+
+#define LOADHISTORY_UNREAD 0
+#define LOADHISTORY_COUNT 1
+#define LOADHISTORY_TIME 2
+
+#define SRMMMOD "SRMM"
+#define SRMSGMOD "SRMsg"
+#define DBSAVEDMSG "SavedMsg"
+
+#define SRMSGSET_DONOTSTEALFOCUS "DoNotStealFocus"
+#define SRMSGDEFSET_DONOTSTEALFOCUS 0
+#define SRMSGSET_POPFLAGS "PopupFlags"
+#define SRMSGDEFSET_POPFLAGS 0
+#define SRMSGSET_SHOWBUTTONLINE "ShowButtonLine"
+#define SRMSGDEFSET_SHOWBUTTONLINE 1
+#define SRMSGSET_SHOWINFOLINE "ShowInfoLine"
+#define SRMSGDEFSET_SHOWINFOLINE 1
+#define SRMSGSET_AUTOMIN "AutoMin"
+#define SRMSGDEFSET_AUTOMIN 0
+#define SRMSGSET_AUTOCLOSE "AutoClose"
+#define SRMSGDEFSET_AUTOCLOSE 0
+#define SRMSGSET_SAVEPERCONTACT "SavePerContact"
+#define SRMSGDEFSET_SAVEPERCONTACT 0
+#define SRMSGSET_CASCADE "Cascade"
+#define SRMSGDEFSET_CASCADE 1
+#define SRMSGSET_SENDONENTER "SendOnEnter"
+#define SRMSGDEFSET_SENDONENTER 1
+#define SRMSGSET_SENDONDBLENTER "SendOnDblEnter"
+#define SRMSGDEFSET_SENDONDBLENTER 0
+#define SRMSGSET_STATUSICON "UseStatusWinIcon"
+#define SRMSGDEFSET_STATUSICON 0
+#define SRMSGSET_SENDBUTTON "UseSendButton"
+#define SRMSGDEFSET_SENDBUTTON 0
+#define SRMSGSET_CHARCOUNT "ShowCharCount"
+#define SRMSGDEFSET_CHARCOUNT 0
+#define SRMSGSET_CTRLSUPPORT "SupportCtrlUpDn"
+#define SRMSGDEFSET_CTRLSUPPORT 1
+#define SRMSGSET_DELTEMP "DeleteTempCont"
+#define SRMSGDEFSET_DELTEMP 0
+#define SRMSGSET_MSGTIMEOUT "MessageTimeout"
+#define SRMSGDEFSET_MSGTIMEOUT 65000
+#define SRMSGSET_MSGTIMEOUT_MIN 5000 // minimum value (5 seconds)
+#define SRMSGSET_FLASHCOUNT "FlashMax"
+#define SRMSGDEFSET_FLASHCOUNT 5
+
+#define SRMSGSET_LOADHISTORY "LoadHistory"
+#define SRMSGDEFSET_LOADHISTORY LOADHISTORY_UNREAD
+#define SRMSGSET_LOADCOUNT "LoadCount"
+#define SRMSGDEFSET_LOADCOUNT 10
+#define SRMSGSET_LOADTIME "LoadTime"
+#define SRMSGDEFSET_LOADTIME 10
+
+#define SRMSGSET_SHOWLOGICONS "ShowLogIcon"
+#define SRMSGDEFSET_SHOWLOGICONS 1
+#define SRMSGSET_HIDENAMES "HideNames"
+#define SRMSGDEFSET_HIDENAMES 1
+#define SRMSGSET_SHOWTIME "ShowTime"
+#define SRMSGDEFSET_SHOWTIME 1
+#define SRMSGSET_SHOWSECS "ShowSeconds"
+#define SRMSGDEFSET_SHOWSECS 1
+#define SRMSGSET_SHOWDATE "ShowDate"
+#define SRMSGDEFSET_SHOWDATE 0
+#define SRMSGSET_SHOWSTATUSCH "ShowStatusChanges"
+#define SRMSGDEFSET_SHOWSTATUSCH 1
+#define SRMSGSET_SHOWFORMAT "ShowFormatting"
+#define SRMSGDEFSET_SHOWFORMAT 1
+#define SRMSGSET_BKGCOLOUR "BkgColour"
+#define SRMSGDEFSET_BKGCOLOUR GetSysColor(COLOR_WINDOW)
+
+#define SRMSGSET_TYPING "SupportTyping"
+#define SRMSGSET_TYPINGNEW "DefaultTyping"
+#define SRMSGDEFSET_TYPINGNEW 1
+#define SRMSGSET_TYPINGUNKNOWN "UnknownTyping"
+#define SRMSGDEFSET_TYPINGUNKNOWN 0
+#define SRMSGSET_SHOWTYPING "ShowTyping"
+#define SRMSGDEFSET_SHOWTYPING 1
+#define SRMSGSET_SHOWTYPINGWIN "ShowTypingWin"
+#define SRMSGDEFSET_SHOWTYPINGWIN 1
+#define SRMSGSET_SHOWTYPINGNOWIN "ShowTypingTray"
+#define SRMSGDEFSET_SHOWTYPINGNOWIN 0
+#define SRMSGSET_SHOWTYPINGCLIST "ShowTypingClist"
+#define SRMSGDEFSET_SHOWTYPINGCLIST 1
+
+
+#define SRMSGSET_AVATARENABLE "AvatarEnable"
+#define SRMSGDEFSET_AVATARENABLE 1
+#define SRMSGSET_LIMITAVHEIGHT "AvatarLimitHeight"
+#define SRMSGDEFSET_LIMITAVHEIGHT 1
+#define SRMSGSET_AVHEIGHT "AvatarHeight"
+#define SRMSGDEFSET_AVHEIGHT 60
+
+#endif
diff --git a/plugins/SRMM/msgtimedout.c b/plugins/SRMM/msgtimedout.c
new file mode 100644
index 0000000000..1b1773aa8e
--- /dev/null
+++ b/plugins/SRMM/msgtimedout.c
@@ -0,0 +1,112 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#include "commonheaders.h"
+#include "msgs.h"
+
+typedef struct
+{
+ const char *szMsg;
+ TMsgQueue *item;
+} ErrorDlgParam;
+
+INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar);
+
+INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TMsgQueue *item = (TMsgQueue*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ RECT rc, rcParent;
+ ErrorDlgParam *param = (ErrorDlgParam *) lParam;
+ item = param->item;
+
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)item);
+
+ if (!param->szMsg || !param->szMsg[0])
+ SetDlgItemText(hwndDlg, IDC_ERRORTEXT, TranslateT("An unknown error has occured."));
+ else
+ {
+ TCHAR* ptszError = (TCHAR*)CallService(MS_LANGPACK_PCHARTOTCHAR, 0, (LPARAM)param->szMsg);
+ SetDlgItemText(hwndDlg, IDC_ERRORTEXT, ptszError);
+ mir_free(ptszError);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_MSGTEXT, item->szMsg);
+
+ GetWindowRect(hwndDlg, &rc);
+ GetWindowRect(GetParent(hwndDlg), &rcParent);
+ SetWindowPos(hwndDlg, 0, (rcParent.left + rcParent.right - (rc.right - rc.left)) / 2,
+ (rcParent.top + rcParent.bottom - (rc.bottom - rc.top)) / 2,
+ 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ mir_free(item->szMsg);
+ mir_free(item);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) item->hContact, 0);
+ SendMessageDirect(item->szMsg, item->hContact, szProto);
+ }
+
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void MessageFailureProcess(TMsgQueue *item, const char* err)
+{
+ HWND hwnd;
+ ErrorDlgParam param = { err, item };
+
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)item->hContact, (LPARAM)item->hDbEvent);
+
+ hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact);
+ if (hwnd == NULL)
+ {
+ SendMessageCmd(item->hContact, NULL, 0);
+ hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact);
+ }
+ else
+ SendMessage(hwnd, DM_REMAKELOG, 0, 0);
+
+ SkinPlaySound("SendError");
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwnd, ErrorDlgProc, (LPARAM) &param);
+}
+
diff --git a/plugins/SRMM/res/dragcopy.cur b/plugins/SRMM/res/dragcopy.cur
new file mode 100644
index 0000000000..89c7c960d5
--- /dev/null
+++ b/plugins/SRMM/res/dragcopy.cur
Binary files differ
diff --git a/plugins/SRMM/res/dropuser.cur b/plugins/SRMM/res/dropuser.cur
new file mode 100644
index 0000000000..a84b19e28b
--- /dev/null
+++ b/plugins/SRMM/res/dropuser.cur
Binary files differ
diff --git a/plugins/SRMM/res/hyperlin.cur b/plugins/SRMM/res/hyperlin.cur
new file mode 100644
index 0000000000..f0f548c828
--- /dev/null
+++ b/plugins/SRMM/res/hyperlin.cur
Binary files differ
diff --git a/plugins/SRMM/res/incoming.ico b/plugins/SRMM/res/incoming.ico
new file mode 100644
index 0000000000..fabbf979cc
--- /dev/null
+++ b/plugins/SRMM/res/incoming.ico
Binary files differ
diff --git a/plugins/SRMM/res/notice.ico b/plugins/SRMM/res/notice.ico
new file mode 100644
index 0000000000..23527a94d8
--- /dev/null
+++ b/plugins/SRMM/res/notice.ico
Binary files differ
diff --git a/plugins/SRMM/res/outgoing.ico b/plugins/SRMM/res/outgoing.ico
new file mode 100644
index 0000000000..f772ab3f8d
--- /dev/null
+++ b/plugins/SRMM/res/outgoing.ico
Binary files differ
diff --git a/plugins/SRMM/resource.h b/plugins/SRMM/resource.h
new file mode 100644
index 0000000000..715d83656b
--- /dev/null
+++ b/plugins/SRMM/resource.h
@@ -0,0 +1,98 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDD_MSGSENDERROR 102
+#define IDR_CONTEXT 180
+#define IDC_DROP 183
+#define IDC_HYPERLINKHAND 214
+#define IDC_DROPUSER 215
+#define IDD_OPT_MSGDLG 243
+#define IDD_MSG 244
+#define IDD_OPT_MSGLOG 245
+#define IDD_OPT_MSGTYPE 275
+#define IDI_INCOMING 276
+#define IDI_OUTGOING 277
+#define IDI_NOTICE 282
+#define IDD_MODERNOPT_MSGDLG 288
+#define IDD_MODERNOPT_MSGLOG 289
+#define IDC_LOG 1001
+#define IDC_MESSAGE 1002
+#define IDC_AUTOCLOSE 1004
+#define IDC_AUTOMIN 1005
+#define IDC_DONOTSTEALFOCUS 1006
+#define IDC_NAME 1009
+#define IDC_SPLITTER 1017
+#define IDC_SHOWNAMES 1024
+#define IDC_SHOWSENDBTN 1029
+#define IDC_SHOWLOGICONS 1032
+#define IDC_SHOWTIMES 1033
+#define IDC_SHOWDATES 1034
+#define IDC_CLIST 1035
+#define IDC_SHOWSTATUSCHANGES 1035
+#define IDC_SHOWFORMATTING 1036
+#define IDC_SAVEPERCONTACT 1037
+#define IDC_LOADCOUNTN 1039
+#define IDC_LOADCOUNTSPIN 1040
+#define IDC_SHOWINFOLINE 1041
+#define IDC_SHOWBUTTONLINE 1042
+#define IDC_LOADUNREAD 1043
+#define IDC_SENDONENTER 1043
+#define IDC_LOADCOUNT 1044
+#define IDC_SENDONDBLENTER 1044
+#define IDC_LOADTIMEN 1045
+#define IDC_LOADTIMESPIN 1046
+#define IDC_LOADTIME 1047
+#define IDC_STMINSOLD 1051
+#define IDC_DETAILS 1069
+#define IDC_ADD 1070
+#define IDC_USERMENU 1071
+#define IDC_HISTORY 1080
+#define IDC_STMSGLOGGROUP 1442
+#define IDC_PROTOCOL 1580
+#define IDC_ERRORTEXT 1596
+#define IDC_MSGTEXT 1597
+#define IDC_SHOWNOTIFY 1600
+#define IDC_STATUSWIN 1601
+#define IDC_TYPEWIN 1602
+#define IDC_CHARCOUNT 1603
+#define IDC_TYPETRAY 1603
+#define IDC_CASCADE 1604
+#define IDC_SECONDS 1605
+#define IDC_NOTIFYTRAY 1606
+#define IDC_NFLASHES 1606
+#define IDC_NOTIFYBALLOON 1607
+#define IDC_CTRLSUPPORT 1608
+#define IDC_DELTEMP 1609
+#define IDC_AVATAR 1610
+#define IDC_AVATARSUPPORT 1611
+#define IDC_LIMITAVATARH 1612
+#define IDC_AVATARHEIGHT 1613
+#define IDC_SHOWSECS 1614
+#define IDC_POPLIST 1616
+#define IDC_TXT_TITLE1 1617
+#define IDC_TXT_TITLE2 1618
+#define IDC_TXT_TITLE3 1619
+#define IDM_CUT 40000
+#define IDM_COPY 40001
+#define IDM_PASTE 40002
+#define IDM_UNDO 40003
+#define IDM_DELETE 40004
+#define IDM_REDO 40005
+#define IDM_PASTESEND 40006
+#define IDM_COPYALL 40011
+#define IDM_SELECTALL 40012
+#define IDM_CLEAR 40013
+#define IDM_OPENLINK 40014
+#define IDM_COPYLINK 40016
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 290
+#define _APS_NEXT_COMMAND_VALUE 40019
+#define _APS_NEXT_CONTROL_VALUE 1620
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/SRMM/resource.rc b/plugins/SRMM/resource.rc
new file mode 100644
index 0000000000..fbcfe77156
--- /dev/null
+++ b/plugins/SRMM/resource.rc
@@ -0,0 +1,361 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <winres.h>
+#include <richedit.h>
+#include "../../include/statusmodes.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_MSGDLG DIALOGEX 0, 0, 304, 234
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Automatically popup window when:",IDC_STATIC,7,7,141,13
+ CONTROL "Tree1",IDC_POPLIST,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,199,6,98,42
+ CONTROL "In background",IDC_DONOTSTEALFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,21,130,10
+ CONTROL "Close the message window on send",IDC_AUTOCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,50,289,10
+ CONTROL "Minimize the message window on send",IDC_AUTOMIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,62,289,10
+ CONTROL "Use the contact's status icon as the window icon",IDC_STATUSWIN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,74,289,10
+ CONTROL "Save the window size and location individually for each contact",IDC_SAVEPERCONTACT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,86,289,10
+ CONTROL "Cascade new windows",IDC_CASCADE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,98,289,10
+ CONTROL "Show 'Send' button",IDC_SHOWSENDBTN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,166,135,10
+ CONTROL "Show username on top row",IDC_SHOWINFOLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,179,138,10
+ CONTROL "Show toolbar buttons on top row",IDC_SHOWBUTTONLINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,192,137,10
+ CONTROL "Send message on double 'Enter'",IDC_SENDONDBLENTER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,148,166,149,10
+ CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,148,179,152,10
+ CONTROL "Show character count",IDC_CHARCOUNT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,148,192,149,10
+ LTEXT "Show warning when message has not been received after",IDC_STATIC,8,208,211,8
+ EDITTEXT IDC_SECONDS,223,206,25,12,ES_AUTOHSCROLL
+ LTEXT "seconds.",IDC_STATIC,253,208,44,8
+ CONTROL "Support control up/down in message area to show previously sent messages",IDC_CTRLSUPPORT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,110,289,10
+ CONTROL "Delete temporary contacts when closing message window",IDC_DELTEMP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,122,287,10
+ CONTROL "Enable avatar support in the message window",IDC_AVATARSUPPORT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,135,289,10
+ CONTROL "Limit avatar height to ",IDC_LIMITAVATARH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,149,126,10
+ EDITTEXT IDC_AVATARHEIGHT,148,148,28,13,ES_AUTOHSCROLL
+ LTEXT "pixels.",IDC_STATIC,181,150,35,8
+ LTEXT "Max Number of Flashes",IDC_STATIC,7,35,141,8
+ EDITTEXT IDC_NFLASHES,148,33,25,12,ES_AUTOHSCROLL | ES_NUMBER
+END
+
+IDD_MSGSENDERROR DIALOGEX 0, 0, 187, 110
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Send Error"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "An error has occured. The protocol reported the following error:",IDC_STATIC,5,4,177,20
+ EDITTEXT IDC_ERRORTEXT,5,24,177,21,ES_MULTILINE | ES_READONLY
+ LTEXT "while sending the following message:",IDC_STATIC,6,48,175,8
+ CONTROL "",IDC_MSGTEXT,RICHEDIT_CLASS,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_CLIPSIBLINGS | WS_VSCROLL | WS_TABSTOP,5,60,177,26,WS_EX_STATICEDGE
+ DEFPUSHBUTTON "Try again",IDOK,22,91,63,14
+ PUSHBUTTON "Cancel",IDCANCEL,104,91,61,14
+END
+
+IDD_MSG DIALOGEX 0, 0, 185, 79
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_ACCEPTFILES | WS_EX_CONTROLPARENT
+CAPTION "Message Session"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW,2,5,12,12
+ CONTROL "",IDC_NAME,"MButtonClass",WS_TABSTOP,15,2,95,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "",IDC_ADD,"MButtonClass",WS_TABSTOP,110,2,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "",IDC_USERMENU,"MButtonClass",WS_TABSTOP,128,2,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&D",IDC_DETAILS,"MButtonClass",WS_TABSTOP,146,2,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "&H",IDC_HISTORY,"MButtonClass",WS_TABSTOP,164,2,16,14,WS_EX_NOACTIVATE | 0x10000000L
+ CONTROL "",IDC_MESSAGE,RICHEDIT_CLASS,ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN | WS_VSCROLL | WS_TABSTOP,1,49,141,13,WS_EX_ACCEPTFILES | WS_EX_STATICEDGE
+ DEFPUSHBUTTON "&Send",IDOK,143,48,39,15
+ PUSHBUTTON "Close",IDCANCEL,129,0,54,15,NOT WS_VISIBLE
+ CONTROL "",IDC_LOG,RICHEDIT_CLASS,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL | WS_TABSTOP,1,18,183,26,WS_EX_STATICEDGE
+ CONTROL "",IDC_SPLITTER,"Static",SS_ENHMETAFILE,0,45,183,2
+ CONTROL "",IDC_AVATAR,"Button",BS_OWNERDRAW | NOT WS_VISIBLE,1,50,1,13
+END
+
+IDD_OPT_MSGLOG DIALOGEX 0, 0, 306, 183
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Message Window Event Log",IDC_STMSGLOGGROUP,5,5,295,109
+ CONTROL "Show icons",IDC_SHOWLOGICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,17,154,10
+ CONTROL "Show names",IDC_SHOWNAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,33,154,10
+ CONTROL "Show timestamp",IDC_SHOWTIMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,49,154,10
+ CONTROL "Show dates",IDC_SHOWDATES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,80,143,10
+ CONTROL "Load unread events only",IDC_LOADUNREAD,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,15,133,138,10
+ CONTROL "Load number of previous events",IDC_LOADCOUNT,"Button",BS_AUTORADIOBUTTON,15,149,138,10
+ EDITTEXT IDC_LOADCOUNTN,158,147,33,12,ES_RIGHT | ES_NUMBER | WS_DISABLED
+ CONTROL "Spin1",IDC_LOADCOUNTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | WS_DISABLED,181,147,11,14
+ CONTROL "Load previous events less than",IDC_LOADTIME,"Button",BS_AUTORADIOBUTTON,15,165,141,10
+ EDITTEXT IDC_LOADTIMEN,158,163,33,12,ES_RIGHT | ES_NUMBER | WS_DISABLED
+ CONTROL "Spin1",IDC_LOADTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | WS_DISABLED,181,163,11,14
+ LTEXT "minutes old",IDC_STMINSOLD,196,165,82,8,WS_DISABLED
+ CONTROL "Show status changes",IDC_SHOWSTATUSCHANGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,97,154,10
+ CONTROL "Show seconds",IDC_SHOWSECS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,64,143,10
+ GROUPBOX "Load History Events",IDC_STATIC,5,117,295,65
+ CONTROL "Show Formatting",IDC_SHOWFORMATTING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,169,10,126,10
+END
+
+IDD_OPT_MSGTYPE DIALOGEX 0, 0, 283, 252
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x348,18,30,248,131,WS_EX_CLIENTEDGE
+ LTEXT "Send typing notifications to the following users when you are typing a message to them:",IDC_STATIC,19,6,245,19
+ CONTROL "Show typing notifications when a user is typing a message",IDC_SHOWNOTIFY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,166,233,13
+ CONTROL "Update inactive message window icons when a user is typing",IDC_TYPEWIN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,181,230,10
+ CONTROL "Show typing notification when no message dialog is open",IDC_TYPETRAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,194,230,10
+ CONTROL "Flash in the system tray and in the contact list",IDC_NOTIFYTRAY,
+ "Button",BS_AUTORADIOBUTTON,44,207,206,10
+ CONTROL "Show balloon popup",IDC_NOTIFYBALLOON,"Button",BS_AUTORADIOBUTTON,44,219,206,10
+END
+
+IDD_MODERNOPT_MSGDLG DIALOGEX 0, 0, 369, 106
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ CONTROL "Close the message window on send",IDC_AUTOCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,174,10
+ CONTROL "Minimize the message window on send",IDC_AUTOMIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,174,10
+ CONTROL "Use the contact's status icon as the window icon",IDC_STATUSWIN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,37,174,10
+ CONTROL "Save the window position for each contact",IDC_SAVEPERCONTACT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,49,174,10
+ CONTROL "Cascade new windows",IDC_CASCADE,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,216,119,22,10
+ CONTROL "",IDC_POPLIST,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,194,13,175,46
+ LTEXT "Automatically popup window when:",IDC_TXT_TITLE2,184,0,185,8
+ CONTROL "Show 'Send' button",IDC_SHOWSENDBTN,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,10,137,25,10
+ CONTROL "Show username on top row",IDC_SHOWINFOLINE,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,11,161,26,10
+ CONTROL "Show toolbar buttons on top row",IDC_SHOWBUTTONLINE,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,11,174,28,10
+ CONTROL "Send message on double 'Enter'",IDC_SENDONDBLENTER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,79,174,10
+ CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,79,175,10
+ CONTROL "Show character count",IDC_CHARCOUNT,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,59,142,22,10
+ LTEXT "Show warning when message has not been received after",IDC_STATIC,10,93,211,8
+ EDITTEXT IDC_SECONDS,226,91,25,12,ES_AUTOHSCROLL
+ LTEXT "seconds.",IDC_STATIC,256,93,44,8
+ CONTROL "Support control up/down in message area to show previously sent messages",IDC_CTRLSUPPORT,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,240,131,20,10
+ CONTROL "Delete temporary contacts when closing message window",IDC_DELTEMP,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,240,143,22,10
+ CONTROL "Enable avatar support in the message window",IDC_AVATARSUPPORT,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,239,155,23,10
+ CONTROL "Limit avatar height to ",IDC_LIMITAVATARH,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,236,166,26,10
+ EDITTEXT IDC_AVATARHEIGHT,242,178,12,13,ES_AUTOHSCROLL | NOT WS_VISIBLE
+ LTEXT "pixels.",IDC_STATIC,271,177,8,8,NOT WS_VISIBLE
+ LTEXT "Message window behaviour:",IDC_TXT_TITLE1,1,0,183,8
+ LTEXT "Messaging:",IDC_TXT_TITLE3,1,64,368,8
+END
+
+IDD_MODERNOPT_MSGLOG DIALOGEX 0, 0, 369, 103
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ CONTROL "Show icons",IDC_SHOWLOGICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,146,10
+ CONTROL "Show names",IDC_SHOWNAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,146,10
+ CONTROL "Show timestamp",IDC_SHOWTIMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,13,146,10
+ CONTROL "Show dates",IDC_SHOWDATES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,206,37,135,10
+ CONTROL "Load unread events only",IDC_LOADUNREAD,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,10,65,138,10
+ CONTROL "Load number of previous events",IDC_LOADCOUNT,"Button",BS_AUTORADIOBUTTON,10,78,138,10
+ EDITTEXT IDC_LOADCOUNTN,153,76,33,12,ES_RIGHT | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_LOADCOUNTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | WS_DISABLED,176,76,11,14
+ CONTROL "Load previous events less than",IDC_LOADTIME,"Button",BS_AUTORADIOBUTTON,10,91,138,10
+ EDITTEXT IDC_LOADTIMEN,153,89,33,12,ES_RIGHT | ES_NUMBER | WS_DISABLED
+ CONTROL "",IDC_LOADTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | WS_DISABLED,176,89,11,14
+ LTEXT "minutes old",IDC_STMINSOLD,191,91,82,8,WS_DISABLED
+ CONTROL "Show status changes",IDC_SHOWSTATUSCHANGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,37,146,10
+ CONTROL "Show seconds",IDC_SHOWSECS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,206,25,127,10
+ LTEXT "Message Window Event Log",IDC_TXT_TITLE1,0,0,369,8
+ LTEXT "Load History Events",IDC_TXT_TITLE2,0,52,369,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_MSGDLG, DIALOG
+ BEGIN
+ VERTGUIDE, 7
+ VERTGUIDE, 22
+ VERTGUIDE, 51
+ VERTGUIDE, 148
+ VERTGUIDE, 297
+ VERTGUIDE, 300
+ BOTTOMMARGIN, 231
+ END
+
+ IDD_MSGSENDERROR, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 182
+ TOPMARGIN, 5
+ END
+
+ IDD_MSG, DIALOG
+ BEGIN
+ RIGHTMARGIN, 183
+ TOPMARGIN, 5
+ HORZGUIDE, 16
+ HORZGUIDE, 53
+ END
+
+ IDD_OPT_MSGLOG, DIALOG
+ BEGIN
+ VERTGUIDE, 10
+ VERTGUIDE, 148
+ VERTGUIDE, 156
+ VERTGUIDE, 169
+ VERTGUIDE, 300
+ BOTTOMMARGIN, 178
+ END
+
+ IDD_OPT_MSGTYPE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 245
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <winres.h>\r\n"
+ "#include <richedit.h>\r\n"
+ "#include ""../../include/statusmodes.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_INCOMING ICON "res/incoming.ico"
+IDI_OUTGOING ICON "res/outgoing.ico"
+IDI_NOTICE ICON "res/notice.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_HYPERLINKHAND CURSOR "res/hyperlin.cur"
+IDC_DROP CURSOR "res/dragcopy.cur"
+IDC_DROPUSER CURSOR "res/dropuser.cur"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_CONTEXT MENU
+BEGIN
+ POPUP "Log"
+ BEGIN
+ MENUITEM "C&lear Log", IDM_CLEAR
+ MENUITEM SEPARATOR
+ MENUITEM "&Copy", IDM_COPY
+ MENUITEM "Co&py All", IDM_COPYALL
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_SELECTALL
+ END
+ POPUP "LogLink"
+ BEGIN
+ MENUITEM "&Open link", IDM_OPENLINK
+ MENUITEM "&Copy link", IDM_COPYLINK
+ END
+ POPUP "Message"
+ BEGIN
+ MENUITEM "Undo", IDM_UNDO
+ MENUITEM "Redo", IDM_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cut", IDM_CUT
+ MENUITEM "Copy", IDM_COPY
+ MENUITEM "Paste", IDM_PASTE
+ MENUITEM "Paste && Send", IDM_PASTESEND
+ MENUITEM "Delete", IDM_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_SELECTALL
+ MENUITEM SEPARATOR
+ MENUITEM "Clear", IDM_CLEAR
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/SRMM/richutil.c b/plugins/SRMM/richutil.c
new file mode 100644
index 0000000000..14296717f7
--- /dev/null
+++ b/plugins/SRMM/richutil.c
@@ -0,0 +1,269 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+#include "richutil.h"
+
+/*
+ To initialize this library, call:
+ RichUtil_Load();
+ Before the application exits, call:
+ RichUtil_Unload();
+
+ Then to use the library (it draws the xp border around it), you need
+ to make sure you control has the WS_EX_CLIENTEDGE flag. Then you just
+ subclass it with:
+ RichUtil_SubClass(hwndEdit);
+
+ If no xptheme is present, the window isn't subclassed the SubClass function
+ just returns. And if WS_EX_CLIENTEDGE isn't present, the subclass does nothing.
+ Otherwise it removes the border and draws it by itself.
+*/
+
+static SortedList sListInt;
+
+static int RichUtil_CmpVal(void *p1, void *p2)
+{
+ TRichUtil *tp1 = (TRichUtil*)p1;
+ TRichUtil *tp2 = (TRichUtil*)p2;
+ return (int)((INT_PTR)tp1->hwnd - (INT_PTR)tp2->hwnd);
+}
+
+// UxTheme Stuff
+static HMODULE mTheme;
+
+static HANDLE (WINAPI *MyOpenThemeData)(HWND, LPCWSTR);
+static HRESULT (WINAPI *MyCloseThemeData)(HANDLE);
+static BOOL (WINAPI *MyIsThemeActive)(VOID);
+static HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE, HDC, int, int, LPCRECT, LPCRECT);
+static HRESULT (WINAPI *MyGetThemeBackgroundContentRect)(HANDLE, HDC, int, int, LPCRECT, LPRECT);
+static HRESULT (WINAPI *MyDrawThemeParentBackground)(HWND, HDC, LPRECT);
+static BOOL (WINAPI *MyIsThemeBackgroundPartiallyTransparent)(HANDLE, int, int);
+
+static CRITICAL_SECTION csRich;
+
+static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+static void RichUtil_ClearUglyBorder(TRichUtil *ru);
+
+void RichUtil_Load(void)
+{
+ sListInt.increment = 10;
+ sListInt.sortFunc = RichUtil_CmpVal;
+
+ mTheme = IsWinVerXPPlus() ? GetModuleHandleA("uxtheme") : 0;
+
+ InitializeCriticalSection(&csRich);
+ if (!mTheme) return;
+
+ MyOpenThemeData = (HANDLE (WINAPI *)(HWND, LPCWSTR))GetProcAddress(mTheme, "OpenThemeData");
+ MyCloseThemeData = (HRESULT (WINAPI *)(HANDLE))GetProcAddress(mTheme, "CloseThemeData");
+ MyIsThemeActive = (BOOL (WINAPI *)(VOID))GetProcAddress(mTheme, "IsThemeActive");
+ MyDrawThemeBackground = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT*, const RECT *))GetProcAddress(mTheme, "DrawThemeBackground");
+ MyGetThemeBackgroundContentRect = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT *, RECT *))GetProcAddress(mTheme, "GetThemeBackgroundContentRect");
+ MyDrawThemeParentBackground = (HRESULT (WINAPI *)(HWND, HDC, RECT*))GetProcAddress(mTheme, "DrawThemeParentBackground");
+ MyIsThemeBackgroundPartiallyTransparent = (BOOL (WINAPI *)(HANDLE, int, int))GetProcAddress(mTheme, "IsThemeBackgroundPartiallyTransparent");
+
+ if (!MyOpenThemeData ||
+ !MyCloseThemeData ||
+ !MyIsThemeActive ||
+ !MyDrawThemeBackground ||
+ !MyGetThemeBackgroundContentRect ||
+ !MyDrawThemeParentBackground ||
+ !MyIsThemeBackgroundPartiallyTransparent)
+ {
+ FreeLibrary(mTheme);
+ mTheme = NULL;
+ }
+}
+
+void RichUtil_Unload(void)
+{
+ li.List_Destroy(&sListInt);
+ DeleteCriticalSection(&csRich);
+ if (mTheme)
+ FreeLibrary(mTheme);
+}
+
+int RichUtil_SubClass(HWND hwndEdit)
+{
+ if (IsWindow(hwndEdit))
+ {
+ int idx;
+
+ TRichUtil *ru = (TRichUtil*)mir_calloc(sizeof(TRichUtil));
+
+ ru->hwnd = hwndEdit;
+ ru->hasUglyBorder = 0;
+
+ EnterCriticalSection(&csRich);
+ if (!li.List_GetIndex(&sListInt, ru, &idx))
+ li.List_Insert(&sListInt, ru, idx);
+ LeaveCriticalSection(&csRich);
+
+ ru->origProc = (WNDPROC)SetWindowLongPtr(ru->hwnd, GWLP_WNDPROC, (LONG_PTR)&RichUtil_Proc);
+ RichUtil_ClearUglyBorder(ru);
+ return 1;
+ }
+ return 0;
+}
+
+static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TRichUtil *ru;
+
+ EnterCriticalSection(&csRich);
+ ru = li.List_Find(&sListInt, (TRichUtil*)&hwnd);
+ LeaveCriticalSection(&csRich);
+
+ if (ru == NULL) return 0;
+
+ switch(msg)
+ {
+ case WM_CHAR:
+ {
+ HWND hwndMsg = GetDlgItem(GetParent(hwnd), IDC_MESSAGE);
+ if (hwndMsg != hwnd)
+ {
+ SetFocus(hwndMsg);
+ SendMessage(hwndMsg, WM_CHAR, wParam, lParam);
+ }
+ break;
+ }
+
+ case WM_THEMECHANGED:
+ case WM_STYLECHANGED:
+ {
+ RichUtil_ClearUglyBorder(ru);
+ break;
+ }
+
+ case WM_NCPAINT:
+ {
+ LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam);
+ if (ru->hasUglyBorder && MyIsThemeActive())
+ {
+ HANDLE hTheme = MyOpenThemeData(ru->hwnd, L"EDIT");
+ if (hTheme)
+ {
+ RECT rcBorder;
+ RECT rcClient;
+ int nState;
+ HDC hdc = GetWindowDC(ru->hwnd);
+ LONG style = GetWindowLong(hwnd, GWL_STYLE);
+
+ GetWindowRect(hwnd, &rcBorder);
+ rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top;
+ rcBorder.left = rcBorder.top = 0;
+ CopyRect(&rcClient, &rcBorder);
+ rcClient.left += ru->rect.left;
+ rcClient.top += ru->rect.top;
+ rcClient.right -= ru->rect.right;
+ rcClient.bottom -= ru->rect.bottom;
+ ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+ if (MyIsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL))
+ MyDrawThemeParentBackground(hwnd, hdc, &rcBorder);
+
+ if (style & WS_DISABLED)
+ nState = ETS_DISABLED;
+ else if (style & ES_READONLY)
+ nState = ETS_READONLY;
+ else
+ nState = ETS_NORMAL;
+
+ MyDrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL);
+ MyCloseThemeData(hTheme);
+ ReleaseDC(hwnd, hdc);
+ return 0;
+ }
+ }
+ return ret;
+ }
+ case WM_NCCALCSIZE:
+ {
+ LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam);
+ NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS*)lParam;
+
+ if (ru->hasUglyBorder && MyIsThemeActive())
+ {
+ HANDLE hTheme = MyOpenThemeData(hwnd, L"EDIT");
+
+ if (hTheme)
+ {
+ RECT rcClient ={0};
+ HDC hdc = GetDC(GetParent(hwnd));
+
+ if (MyGetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK)
+ {
+ ru->rect.left = rcClient.left-ncsParam->rgrc[0].left;
+ ru->rect.top = rcClient.top-ncsParam->rgrc[0].top;
+ ru->rect.right = ncsParam->rgrc[0].right-rcClient.right;
+ ru->rect.bottom = ncsParam->rgrc[0].bottom-rcClient.bottom;
+ ncsParam->rgrc[0] = rcClient;
+
+ MyCloseThemeData(hTheme);
+ ReleaseDC(GetParent(hwnd), hdc);
+ return WVR_REDRAW;
+ }
+ ReleaseDC(GetParent(hwnd), hdc);
+ MyCloseThemeData(hTheme);
+ }
+ }
+ return ret;
+ }
+
+ case WM_ENABLE:
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME);
+ break;
+
+ case WM_GETDLGCODE:
+ return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam) & ~DLGC_HASSETSEL;
+
+ case WM_NCDESTROY:
+ {
+ LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam);
+
+ if (IsWindow(hwnd))
+ {
+ if((WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC) == &RichUtil_Proc)
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ru->origProc);
+ }
+
+ EnterCriticalSection(&csRich);
+ li.List_RemovePtr(&sListInt, ru);
+ LeaveCriticalSection(&csRich);
+
+ mir_free(ru);
+ return ret;
+ }
+ }
+ return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam);
+}
+
+static void RichUtil_ClearUglyBorder(TRichUtil *ru)
+{
+ if (mTheme && MyIsThemeActive() && GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ {
+ ru->hasUglyBorder = 1;
+ SetWindowLongPtr(ru->hwnd, GWL_EXSTYLE, GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) ^ WS_EX_CLIENTEDGE);
+ }
+ // Redraw window since the style may have changed
+ SetWindowPos(ru->hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
+ RedrawWindow(ru->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME);
+}
diff --git a/plugins/SRMM/richutil.h b/plugins/SRMM/richutil.h
new file mode 100644
index 0000000000..68e9f37c5b
--- /dev/null
+++ b/plugins/SRMM/richutil.h
@@ -0,0 +1,34 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#ifndef SRMM_RICHUTIL_H
+#define SRMM_RICHUTIL_H
+
+typedef struct {
+ HWND hwnd;
+ RECT rect;
+ int hasUglyBorder;
+ WNDPROC origProc;
+} TRichUtil;
+
+void RichUtil_Load();
+void RichUtil_Unload();
+int RichUtil_SubClass(HWND hwndEdit);
+
+#endif
diff --git a/plugins/SRMM/srmm.c b/plugins/SRMM/srmm.c
new file mode 100644
index 0000000000..a8e3949040
--- /dev/null
+++ b/plugins/SRMM/srmm.c
@@ -0,0 +1,88 @@
+/*
+Copyright 2000-2012 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+
+#include "commonheaders.h"
+
+int LoadSendRecvMessageModule(void);
+int SplitmsgShutdown(void);
+
+PLUGINLINK* pluginLink;
+HINSTANCE g_hInst;
+int hLangpack;
+
+struct MM_INTERFACE mmi;
+struct UTF8_INTERFACE utfi;
+struct LIST_INTERFACE li;
+TIME_API tmi;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Send/Receive Messages",
+ __VERSION_DWORD,
+ "Send and receive instant messages",
+ "Miranda IM Development Team",
+ "rainwater@miranda-im.org",
+ "Copyright 2000-2012 Miranda IM project",
+ "http://www.miranda-im.org",
+ UNICODE_AWARE,
+ DEFMOD_SRMESSAGE, // replace internal version (if any)
+#ifdef _UNICODE
+ {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0xc }} //{657FE89B-D121-40c2-8AC9-B9FA5755B30C}
+#else
+ {0xd53dd778, 0x16d2, 0x49ac, { 0x8f, 0xb3, 0x6f, 0x9a, 0x96, 0x1c, 0x9f, 0xd2 }} //{D53DD778-16D2-49ac-8FB3-6F9A961C9FD2}
+#endif
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+__declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if (mirandaVersion < MIRANDA_VERSION_CORE )
+ return NULL;
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_SRMM, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int __declspec(dllexport) Load(PLUGINLINK * link)
+{
+ pluginLink = link;
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+ mir_getLI(&li);
+ mir_getTMI(&tmi);
+ mir_getLP(&pluginInfo);
+
+ return LoadSendRecvMessageModule();
+}
+
+int __declspec(dllexport) Unload(void)
+{
+ UnloadOptions();
+ return SplitmsgShutdown();
+}
diff --git a/plugins/SRMM/srmm_10.vcxproj b/plugins/SRMM/srmm_10.vcxproj
new file mode 100644
index 0000000000..fc87e7d352
--- /dev/null
+++ b/plugins/SRMM/srmm_10.vcxproj
@@ -0,0 +1,341 @@
+<?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>SRMM</ProjectName>
+ <ProjectGuid>{F47EAB99-C78F-4A92-87D5-B0E16FE5A133}</ProjectGuid>
+ <RootNamespace>srmm</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </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.30128.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release_Unicode/srmm.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SRMM_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../../include/msapi/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Release_Unicode/srmm.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SRMM_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../../include/msapi/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug_Unicode/srmm.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SRMM_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../../include/msapi/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Debug_Unicode/srmm.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SRMM_EXPORTS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>Default</CompileAs>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../../include/msapi/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="cmdlist.c" />
+ <ClCompile Include="globals.c">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="msgdialog.c" />
+ <ClCompile Include="msglog.c" />
+ <ClCompile Include="msgoptions.c" />
+ <ClCompile Include="msgs.c" />
+ <ClCompile Include="msgtimedout.c" />
+ <ClCompile Include="richutil.c" />
+ <ClCompile Include="srmm.c">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="statusicon.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="cmdlist.h" />
+ <ClInclude Include="commonheaders.h" />
+ <ClInclude Include="globals.h" />
+ <ClInclude Include="msgs.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="richutil.h" />
+ <ClInclude Include="statusicon.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\Miranda-IM\res\addcontact.ico" />
+ <None Include="..\..\src\res\addcontact.ico" />
+ <None Include="res\Clock32.ico" />
+ <None Include="res\Clock8.ico" />
+ <None Include="res\Details32.ico" />
+ <None Include="res\Details8.ico" />
+ <None Include="..\..\Miranda-IM\res\downarrow.ico" />
+ <None Include="res\Downarrow32.ico" />
+ <None Include="res\Downarrow8.ico" />
+ <None Include="..\..\Miranda-IM\res\dragcopy.cur" />
+ <None Include="res\dragcopy.cur" />
+ <None Include="..\..\src\res\dragcopy.cur" />
+ <None Include="..\..\Miranda-IM\res\dropuser.cur" />
+ <None Include="..\..\src\res\dropuser.cur" />
+ <None Include="res\dropuser.cur" />
+ <None Include="..\..\Miranda-IM\res\history.ico" />
+ <None Include="res\History32.ico" />
+ <None Include="res\History8.ico" />
+ <None Include="..\..\src\res\hyperlin.cur" />
+ <None Include="res\hyperlin.cur" />
+ <None Include="..\..\Miranda-IM\res\hyperlin.cur" />
+ <None Include="res\incoming.ico" />
+ <None Include="..\..\Miranda-IM\res\multisend.ico" />
+ <None Include="res\Multisend32.ico" />
+ <None Include="res\Multisend8.ico" />
+ <None Include="res\notice.ico" />
+ <None Include="res\outgoing.ico" />
+ <None Include="..\..\Miranda-IM\res\rename.ico" />
+ <None Include="..\..\Miranda-IM\res\timestamp.ico" />
+ <None Include="..\..\Miranda-IM\res\typing.ico" />
+ <None Include="res\Typing32.ico" />
+ <None Include="res\Typing8.ico" />
+ <None Include="..\..\Miranda-IM\res\viewdetails.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/SRMM/srmm_10.vcxproj.filters b/plugins/SRMM/srmm_10.vcxproj.filters
new file mode 100644
index 0000000000..30f6186a20
--- /dev/null
+++ b/plugins/SRMM/srmm_10.vcxproj.filters
@@ -0,0 +1,178 @@
+<?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>{8927e967-671b-4c16-8208-54dec5f31489}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{6ae44719-2dc0-4659-bb57-b80bc11f0eb2}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{ed6d6a77-6f3c-4512-afc9-7c872bee5ded}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="cmdlist.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="globals.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="msgdialog.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="msglog.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="msgoptions.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="msgs.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="msgtimedout.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="richutil.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="srmm.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="statusicon.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="cmdlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="commonheaders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="globals.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="msgs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="richutil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="statusicon.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\Miranda-IM\res\addcontact.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\src\res\addcontact.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Clock32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Clock8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Details32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Details8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\downarrow.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Downarrow32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Downarrow8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\dragcopy.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\dragcopy.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\src\res\dragcopy.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\dropuser.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\src\res\dropuser.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\dropuser.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\history.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\History32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\History8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\src\res\hyperlin.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\hyperlin.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\hyperlin.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\incoming.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\multisend.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Multisend32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Multisend8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\notice.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\outgoing.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\rename.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\timestamp.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\typing.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Typing32.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\Typing8.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\..\Miranda-IM\res\viewdetails.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/SRMM/statusicon.c b/plugins/SRMM/statusicon.c
new file mode 100644
index 0000000000..d8c5a5d87a
--- /dev/null
+++ b/plugins/SRMM/statusicon.c
@@ -0,0 +1,221 @@
+/*
+Copyright 2000-2010 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+*/
+#include "commonheaders.h"
+#include "statusicon.h"
+
+struct StatusIconListNode {
+ StatusIconData sid;
+ struct StatusIconListNode *next;
+};
+
+HANDLE hHookIconPressedEvt;
+struct StatusIconListNode *status_icon_list = 0;
+int status_icon_list_size = 0;
+
+INT_PTR AddStatusIcon(WPARAM wParam, LPARAM lParam) {
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct StatusIconListNode *siln = (struct StatusIconListNode *)mir_calloc(sizeof(struct StatusIconListNode));
+
+ siln->sid.cbSize = sid->cbSize;
+ siln->sid.szModule = mir_strdup(sid->szModule);
+ siln->sid.dwId = sid->dwId;
+ siln->sid.hIcon = sid->hIcon;
+ siln->sid.hIconDisabled = sid->hIconDisabled;
+ siln->sid.flags = sid->flags;
+ if(sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip);
+ else siln->sid.szTooltip = 0;
+
+ siln->next = status_icon_list;
+ status_icon_list = siln;
+ status_icon_list_size++;
+
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0);
+ return 0;
+}
+
+INT_PTR RemoveStatusIcon(WPARAM wParam, LPARAM lParam) {
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct StatusIconListNode *current = status_icon_list, *prev = 0;
+
+ while(current) {
+ if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) {
+ if(prev) prev->next = current->next;
+ else status_icon_list = current->next;
+
+ status_icon_list_size--;
+
+ mir_free(current->sid.szModule);
+ DestroyIcon(current->sid.hIcon);
+ if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled);
+ mir_free(current->sid.szTooltip);
+ mir_free(current);
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0);
+ return 0;
+ }
+
+ prev = current;
+ current = current->next;
+ }
+
+ return 1;
+}
+
+void RemoveAllStatusIcons(void) {
+ struct StatusIconListNode *current;
+
+ while(status_icon_list) {
+ current = status_icon_list;
+ status_icon_list = status_icon_list->next;
+ status_icon_list_size--;
+
+ mir_free(current->sid.szModule);
+ DestroyIcon(current->sid.hIcon);
+ if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled);
+ if(current->sid.szTooltip) mir_free(current->sid.szTooltip);
+ mir_free(current);
+ }
+
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0);
+}
+
+INT_PTR ModifyStatusIcon(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct StatusIconListNode *current = status_icon_list, *prev = 0;
+
+ while(current) {
+ if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) {
+ if(!hContact) {
+ current->sid.flags = sid->flags;
+ if(sid->hIcon) {
+ DestroyIcon(current->sid.hIcon);
+ current->sid.hIcon = sid->hIcon;
+ }
+ if(sid->hIconDisabled) {
+ DestroyIcon(current->sid.hIconDisabled);
+ current->sid.hIconDisabled = sid->hIconDisabled;
+ }
+ if(sid->szTooltip) {
+ mir_free(current->sid.szTooltip);
+ current->sid.szTooltip = mir_strdup(sid->szTooltip);
+ }
+
+ WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0);
+ } else {
+ char buff[256];
+ HWND hwnd;
+ sprintf(buff, "SRMMStatusIconFlags%d", sid->dwId);
+ DBWriteContactSettingByte(hContact, sid->szModule, buff, (BYTE)sid->flags);
+ if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact)) {
+ PostMessage(hwnd, DM_STATUSICONCHANGE, 0, 0);
+ }
+ }
+ return 0;
+ }
+
+ current = current->next;
+ }
+
+ return 1;
+}
+
+void DrawStatusIcons(HANDLE hContact, HDC hDC, RECT r, int gap) {
+ struct StatusIconListNode *current = status_icon_list;
+ HICON hIcon;
+ char buff[256];
+ int flags;
+ int x = r.left;
+ while(current && x < r.right) {
+ sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId);
+ flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags);
+ if(!(flags & MBF_HIDDEN)) {
+ if((flags & MBF_DISABLED) && current->sid.hIconDisabled) hIcon = current->sid.hIconDisabled;
+ else hIcon = current->sid.hIcon;
+
+ SetBkMode(hDC, TRANSPARENT);
+ DrawIconEx(hDC, x, (r.top + r.bottom - GetSystemMetrics(SM_CYSMICON)) >> 1, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
+
+ x += GetSystemMetrics(SM_CYSMICON) + gap;
+ }
+ current = current->next;
+ }
+}
+
+void CheckIconClick(HANDLE hContact, HWND hwndFrom, POINT pt, RECT r, int gap, int click_flags) {
+ StatusIconClickData sicd;
+ struct StatusIconListNode *current = status_icon_list;
+ int iconNum = (pt.x - r.left) / (GetSystemMetrics(SM_CXSMICON) + gap);
+ char buff[256];
+ int flags;
+
+ while(current && iconNum >= 0) {
+ sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId);
+ flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags);
+ if(!(flags & MBF_HIDDEN)) iconNum--;
+ if(iconNum >= 0)
+ current = current->next;
+ }
+
+ if(current) {
+ sicd.cbSize = sizeof(StatusIconClickData);
+ ClientToScreen(hwndFrom, &pt);
+ sicd.clickLocation = pt;
+ sicd.dwId = current->sid.dwId;
+ sicd.szModule = current->sid.szModule;
+ sicd.flags = click_flags;
+
+ NotifyEventHooks(hHookIconPressedEvt, (WPARAM)hContact, (LPARAM)&sicd);
+ }
+}
+
+HANDLE hServiceIcon[3];
+int InitStatusIcons() {
+ hServiceIcon[0] = CreateServiceFunction(MS_MSG_ADDICON, AddStatusIcon);
+ hServiceIcon[1] = CreateServiceFunction(MS_MSG_REMOVEICON, RemoveStatusIcon);
+ hServiceIcon[2] = CreateServiceFunction(MS_MSG_MODIFYICON, ModifyStatusIcon);
+ hHookIconPressedEvt = CreateHookableEvent(ME_MSG_ICONPRESSED);
+
+ return 0;
+}
+
+int DeinitStatusIcons() {
+ int i;
+ DestroyHookableEvent(hHookIconPressedEvt);
+ for(i = 0; i < 3; i++) DestroyServiceFunction(hServiceIcon[i]);
+ RemoveAllStatusIcons();
+ return 0;
+}
+
+int GetStatusIconsCount(HANDLE hContact) {
+ char buff[256];
+ int count = 0;
+ int flags;
+ struct StatusIconListNode *current = status_icon_list;
+ while(current) {
+ sprintf(buff, "SRMMStatusIconFlags%d", (int)current->sid.dwId);
+ flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags);
+ if(!(flags & MBF_HIDDEN)) {
+ count ++;
+ }
+ current = current->next;
+ }
+ return count;
+}
diff --git a/plugins/SRMM/statusicon.h b/plugins/SRMM/statusicon.h
new file mode 100644
index 0000000000..314ac9ec1e
--- /dev/null
+++ b/plugins/SRMM/statusicon.h
@@ -0,0 +1,14 @@
+#ifndef _STATUS_ICON_INC
+#define _STATUS_ICON_INC
+
+extern HANDLE hHookIconPressedEvt;
+extern int status_icon_list_size;
+
+int InitStatusIcons();
+int DeinitStatusIcons();
+
+int GetStatusIconsCount(HANDLE hContact);
+void DrawStatusIcons(HANDLE hContact, HDC hdc, RECT r, int gap);
+void CheckIconClick(HANDLE hContact, HWND hwndFrom, POINT pt, RECT r, int gap, int flags);
+
+#endif
diff --git a/plugins/SRMM/version.h b/plugins/SRMM/version.h
new file mode 100644
index 0000000000..58f9cf348c
--- /dev/null
+++ b/plugins/SRMM/version.h
@@ -0,0 +1,5 @@
+#include <m_version.h>
+
+#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION
+#define __VERSION_STRING MIRANDA_VERSION_STRING
+#define __VERSION_DWORD MIRANDA_VERSION_DWORD