From 21549db08d22a6e41443799b917525da1dbf9853 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 10 Aug 2012 10:35:58 +0000 Subject: - SRMM, Chat & Clist_Classic made standard git-svn-id: http://svn.miranda-ng.org/main/trunk@1422 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/modules.cpp | 13 +- src/core/stdauth/version.h | 4 +- src/core/stdautoaway/version.h | 4 +- src/core/stdaway/version.h | 4 +- src/core/stdchat/chat_10.vcxproj | 235 ++ src/core/stdchat/chat_10.vcxproj.filters | 86 + src/core/stdchat/docs/Chat_Readme.txt | 82 + src/core/stdchat/docs/Chat_license.txt | 340 +++ src/core/stdchat/docs/chat-translation.txt | 300 +++ src/core/stdchat/res/1.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/2.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/3.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/4.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/5.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/6.ico | Bin 0 -> 1742 bytes src/core/stdchat/res/action.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/addmode.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/bkgcolor.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/blank.ico | Bin 0 -> 318 bytes src/core/stdchat/res/bold.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/chat.rc | 455 ++++ src/core/stdchat/res/close.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/color.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/filter.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/filter2.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/highlight.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/history.ico | Bin 0 -> 6830 bytes src/core/stdchat/res/info.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/italics.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/join.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/kick.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/message.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/messageout.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/nick.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/nicklist.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/nicklist2.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/notice.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/overlay.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/part.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/quit.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/removestatus.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/smiley.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/smileyc.ico | Bin 0 -> 2038 bytes src/core/stdchat/res/tag1.ico | Bin 0 -> 1590 bytes src/core/stdchat/res/tag2.ico | Bin 0 -> 4726 bytes src/core/stdchat/res/topic.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/topicbut.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/underline.ico | Bin 0 -> 2550 bytes src/core/stdchat/res/version.rc | 56 + src/core/stdchat/res/window.ico | Bin 0 -> 10086 bytes src/core/stdchat/src/chat.h | 552 ++++ src/core/stdchat/src/clist.cpp | 360 +++ src/core/stdchat/src/colorchooser.cpp | 266 ++ src/core/stdchat/src/log.cpp | 712 +++++ src/core/stdchat/src/main.cpp | 288 +++ src/core/stdchat/src/manager.cpp | 1611 ++++++++++++ src/core/stdchat/src/message.cpp | 356 +++ src/core/stdchat/src/options.cpp | 1123 ++++++++ src/core/stdchat/src/resource.h | 141 + src/core/stdchat/src/richutil.cpp | 293 +++ src/core/stdchat/src/richutil.h | 55 + src/core/stdchat/src/services.cpp | 874 +++++++ src/core/stdchat/src/tools.cpp | 917 +++++++ src/core/stdchat/src/version.h | 14 + src/core/stdchat/src/window.cpp | 2725 ++++++++++++++++++++ src/core/stdclist/clist_10.vcxproj | 226 ++ src/core/stdclist/clist_10.vcxproj.filters | 73 + src/core/stdclist/docs/clist-license.txt | 340 +++ src/core/stdclist/docs/clist-readme.txt | 38 + src/core/stdclist/docs/clist-translation.txt | 166 ++ .../stdclist/docs/clist_classic-translation.txt | 166 ++ src/core/stdclist/res/blank.ico | Bin 0 -> 318 bytes src/core/stdclist/res/dragcopy.cur | Bin 0 -> 326 bytes src/core/stdclist/res/dropuser.cur | Bin 0 -> 1086 bytes src/core/stdclist/res/hyperlin.cur | Bin 0 -> 326 bytes src/core/stdclist/res/resource.rc | 532 ++++ src/core/stdclist/res/version.rc | 56 + src/core/stdclist/src/clc.h | 32 + src/core/stdclist/src/clcfonts.cpp | 137 + src/core/stdclist/src/clcopts.cpp | 479 ++++ src/core/stdclist/src/clcpaint.cpp | 596 +++++ src/core/stdclist/src/clistmenus.cpp | 36 + src/core/stdclist/src/clistopts.cpp | 279 ++ src/core/stdclist/src/cluiopts.cpp | 394 +++ src/core/stdclist/src/commonheaders.h | 77 + src/core/stdclist/src/init.cpp | 176 ++ src/core/stdclist/src/resource.h | 163 ++ src/core/stdclist/src/version.h | 14 + src/core/stdemail/version.h | 4 +- src/core/stdfile/version.h | 4 +- src/core/stdhelp/version.h | 4 +- src/core/stdidle/version.h | 4 +- src/core/stdmsg/docs/srmm-license.txt | 340 +++ src/core/stdmsg/docs/srmm-readme.txt | 130 + src/core/stdmsg/docs/srmm-translation.txt | 141 + src/core/stdmsg/res/dragcopy.cur | Bin 0 -> 326 bytes src/core/stdmsg/res/dropuser.cur | Bin 0 -> 1086 bytes src/core/stdmsg/res/hyperlin.cur | Bin 0 -> 326 bytes src/core/stdmsg/res/incoming.ico | Bin 0 -> 1246 bytes src/core/stdmsg/res/notice.ico | Bin 0 -> 1246 bytes src/core/stdmsg/res/outgoing.ico | Bin 0 -> 1246 bytes src/core/stdmsg/res/resource.rc | 361 +++ src/core/stdmsg/res/version.rc | 54 + src/core/stdmsg/src/cmdlist.cpp | 166 ++ src/core/stdmsg/src/cmdlist.h | 51 + src/core/stdmsg/src/commonheaders.h | 75 + src/core/stdmsg/src/globals.cpp | 186 ++ src/core/stdmsg/src/globals.h | 62 + src/core/stdmsg/src/msgdialog.cpp | 2014 +++++++++++++++ src/core/stdmsg/src/msglog.cpp | 645 +++++ src/core/stdmsg/src/msgoptions.cpp | 656 +++++ src/core/stdmsg/src/msgs.cpp | 567 ++++ src/core/stdmsg/src/msgs.h | 232 ++ src/core/stdmsg/src/msgtimedout.cpp | 112 + src/core/stdmsg/src/resource.h | 98 + src/core/stdmsg/src/richutil.cpp | 269 ++ src/core/stdmsg/src/richutil.h | 34 + src/core/stdmsg/src/srmm.cpp | 70 + src/core/stdmsg/src/statusicon.cpp | 221 ++ src/core/stdmsg/src/statusicon.h | 14 + src/core/stdmsg/src/version.h | 14 + src/core/stdmsg/srmm_10.vcxproj | 221 ++ src/core/stdmsg/srmm_10.vcxproj.filters | 80 + src/core/stduihist/version.h | 4 +- src/core/stdurl/version.h | 4 +- src/core/stduserinfo/version.h | 4 +- src/core/stduseronline/version.h | 4 +- src/modules/plugins/newplugins.cpp | 53 +- src/modules/plugins/plugins.h | 2 - 129 files changed, 22692 insertions(+), 54 deletions(-) create mode 100644 src/core/stdchat/chat_10.vcxproj create mode 100644 src/core/stdchat/chat_10.vcxproj.filters create mode 100644 src/core/stdchat/docs/Chat_Readme.txt create mode 100644 src/core/stdchat/docs/Chat_license.txt create mode 100644 src/core/stdchat/docs/chat-translation.txt create mode 100644 src/core/stdchat/res/1.ico create mode 100644 src/core/stdchat/res/2.ico create mode 100644 src/core/stdchat/res/3.ico create mode 100644 src/core/stdchat/res/4.ico create mode 100644 src/core/stdchat/res/5.ico create mode 100644 src/core/stdchat/res/6.ico create mode 100644 src/core/stdchat/res/action.ico create mode 100644 src/core/stdchat/res/addmode.ico create mode 100644 src/core/stdchat/res/bkgcolor.ico create mode 100644 src/core/stdchat/res/blank.ico create mode 100644 src/core/stdchat/res/bold.ico create mode 100644 src/core/stdchat/res/chat.rc create mode 100644 src/core/stdchat/res/close.ico create mode 100644 src/core/stdchat/res/color.ico create mode 100644 src/core/stdchat/res/filter.ico create mode 100644 src/core/stdchat/res/filter2.ico create mode 100644 src/core/stdchat/res/highlight.ico create mode 100644 src/core/stdchat/res/history.ico create mode 100644 src/core/stdchat/res/info.ico create mode 100644 src/core/stdchat/res/italics.ico create mode 100644 src/core/stdchat/res/join.ico create mode 100644 src/core/stdchat/res/kick.ico create mode 100644 src/core/stdchat/res/message.ico create mode 100644 src/core/stdchat/res/messageout.ico create mode 100644 src/core/stdchat/res/nick.ico create mode 100644 src/core/stdchat/res/nicklist.ico create mode 100644 src/core/stdchat/res/nicklist2.ico create mode 100644 src/core/stdchat/res/notice.ico create mode 100644 src/core/stdchat/res/overlay.ico create mode 100644 src/core/stdchat/res/part.ico create mode 100644 src/core/stdchat/res/quit.ico create mode 100644 src/core/stdchat/res/removestatus.ico create mode 100644 src/core/stdchat/res/smiley.ico create mode 100644 src/core/stdchat/res/smileyc.ico create mode 100644 src/core/stdchat/res/tag1.ico create mode 100644 src/core/stdchat/res/tag2.ico create mode 100644 src/core/stdchat/res/topic.ico create mode 100644 src/core/stdchat/res/topicbut.ico create mode 100644 src/core/stdchat/res/underline.ico create mode 100644 src/core/stdchat/res/version.rc create mode 100644 src/core/stdchat/res/window.ico create mode 100644 src/core/stdchat/src/chat.h create mode 100644 src/core/stdchat/src/clist.cpp create mode 100644 src/core/stdchat/src/colorchooser.cpp create mode 100644 src/core/stdchat/src/log.cpp create mode 100644 src/core/stdchat/src/main.cpp create mode 100644 src/core/stdchat/src/manager.cpp create mode 100644 src/core/stdchat/src/message.cpp create mode 100644 src/core/stdchat/src/options.cpp create mode 100644 src/core/stdchat/src/resource.h create mode 100644 src/core/stdchat/src/richutil.cpp create mode 100644 src/core/stdchat/src/richutil.h create mode 100644 src/core/stdchat/src/services.cpp create mode 100644 src/core/stdchat/src/tools.cpp create mode 100644 src/core/stdchat/src/version.h create mode 100644 src/core/stdchat/src/window.cpp create mode 100644 src/core/stdclist/clist_10.vcxproj create mode 100644 src/core/stdclist/clist_10.vcxproj.filters create mode 100644 src/core/stdclist/docs/clist-license.txt create mode 100644 src/core/stdclist/docs/clist-readme.txt create mode 100644 src/core/stdclist/docs/clist-translation.txt create mode 100644 src/core/stdclist/docs/clist_classic-translation.txt create mode 100644 src/core/stdclist/res/blank.ico create mode 100644 src/core/stdclist/res/dragcopy.cur create mode 100644 src/core/stdclist/res/dropuser.cur create mode 100644 src/core/stdclist/res/hyperlin.cur create mode 100644 src/core/stdclist/res/resource.rc create mode 100644 src/core/stdclist/res/version.rc create mode 100644 src/core/stdclist/src/clc.h create mode 100644 src/core/stdclist/src/clcfonts.cpp create mode 100644 src/core/stdclist/src/clcopts.cpp create mode 100644 src/core/stdclist/src/clcpaint.cpp create mode 100644 src/core/stdclist/src/clistmenus.cpp create mode 100644 src/core/stdclist/src/clistopts.cpp create mode 100644 src/core/stdclist/src/cluiopts.cpp create mode 100644 src/core/stdclist/src/commonheaders.h create mode 100644 src/core/stdclist/src/init.cpp create mode 100644 src/core/stdclist/src/resource.h create mode 100644 src/core/stdclist/src/version.h create mode 100644 src/core/stdmsg/docs/srmm-license.txt create mode 100644 src/core/stdmsg/docs/srmm-readme.txt create mode 100644 src/core/stdmsg/docs/srmm-translation.txt create mode 100644 src/core/stdmsg/res/dragcopy.cur create mode 100644 src/core/stdmsg/res/dropuser.cur create mode 100644 src/core/stdmsg/res/hyperlin.cur create mode 100644 src/core/stdmsg/res/incoming.ico create mode 100644 src/core/stdmsg/res/notice.ico create mode 100644 src/core/stdmsg/res/outgoing.ico create mode 100644 src/core/stdmsg/res/resource.rc create mode 100644 src/core/stdmsg/res/version.rc create mode 100644 src/core/stdmsg/src/cmdlist.cpp create mode 100644 src/core/stdmsg/src/cmdlist.h create mode 100644 src/core/stdmsg/src/commonheaders.h create mode 100644 src/core/stdmsg/src/globals.cpp create mode 100644 src/core/stdmsg/src/globals.h create mode 100644 src/core/stdmsg/src/msgdialog.cpp create mode 100644 src/core/stdmsg/src/msglog.cpp create mode 100644 src/core/stdmsg/src/msgoptions.cpp create mode 100644 src/core/stdmsg/src/msgs.cpp create mode 100644 src/core/stdmsg/src/msgs.h create mode 100644 src/core/stdmsg/src/msgtimedout.cpp create mode 100644 src/core/stdmsg/src/resource.h create mode 100644 src/core/stdmsg/src/richutil.cpp create mode 100644 src/core/stdmsg/src/richutil.h create mode 100644 src/core/stdmsg/src/srmm.cpp create mode 100644 src/core/stdmsg/src/statusicon.cpp create mode 100644 src/core/stdmsg/src/statusicon.h create mode 100644 src/core/stdmsg/src/version.h create mode 100644 src/core/stdmsg/srmm_10.vcxproj create mode 100644 src/core/stdmsg/srmm_10.vcxproj.filters (limited to 'src') diff --git a/src/core/modules.cpp b/src/core/modules.cpp index 5969fdcd0e..645f238872 100644 --- a/src/core/modules.cpp +++ b/src/core/modules.cpp @@ -64,7 +64,8 @@ int LoadFontserviceModule(void); // ui: font manager int LoadIcoLibModule(void); // ui: icons manager int LoadServiceModePlugin(void); int LoadDefaultServiceModePlugin(void); -int LoadErrorsModule(); +int LoadErrorsModule(void); +int LoadStdPlugins(void); void UnloadUtilsModule(void); void UnloadButtonModule(void); @@ -156,15 +157,7 @@ int LoadDefaultModules(void) if ( LoadFindAddModule()) return 1; if ( LoadIgnoreModule()) return 1; if ( LoadVisibilityModule()) return 1; - - for (int i=0; i < 11; i++) { - if ( pluginDefault[i].pImpl ) - continue; - - if ( !LoadCorePlugin(pluginDefault[i])) - return 1; - } - + if ( LoadStdPlugins()) return 1; return 0; } diff --git a/src/core/stdauth/version.h b/src/core/stdauth/version.h index ecaa3daa78..6cde63bca4 100644 --- a/src/core/stdauth/version.h +++ b/src/core/stdauth/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdauth" #define __FILENAME "stdauth.dll" #define __DESCRIPTION "Core module for sending/receiving auth requests." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdautoaway/version.h b/src/core/stdautoaway/version.h index 903c7bbbac..187cd1fe13 100644 --- a/src/core/stdautoaway/version.h +++ b/src/core/stdautoaway/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdautoaway" #define __FILENAME "stdautoaway.dll" #define __DESCRIPTION "Core module for away state processing." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdaway/version.h b/src/core/stdaway/version.h index 4cf976b665..675a9844fb 100644 --- a/src/core/stdaway/version.h +++ b/src/core/stdaway/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdaway" #define __FILENAME "stdaway.dll" #define __DESCRIPTION "Core module for the away messages processing." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdchat/chat_10.vcxproj b/src/core/stdchat/chat_10.vcxproj new file mode 100644 index 0000000000..f87dbffec7 --- /dev/null +++ b/src/core/stdchat/chat_10.vcxproj @@ -0,0 +1,235 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + stdchat + {268BD296-8DD3-4715-A386-CF120398EC98} + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Disabled + ..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + Use + chat.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + /DLL %(AdditionalOptions) + Version.lib;%(AdditionalDependencies) + type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27 + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Disabled + ..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + 4996;%(DisableSpecificWarnings) + Use + chat.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + /DLL %(AdditionalOptions) + Version.lib;%(AdditionalDependencies) + 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) + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Full + OnlyExplicitInline + true + Size + ..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions) + true + false + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + Use + chat.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + /PDBALTPATH:%_PDB% + Version.lib;%(AdditionalDependencies) + type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27 + true + true + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Full + OnlyExplicitInline + true + Size + ..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions) + true + false + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + Use + chat.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + /PDBALTPATH:%_PDB% + Version.lib;%(AdditionalDependencies) + 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) + true + true + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + + + + Create + + + + + + NotUsing + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/stdchat/chat_10.vcxproj.filters b/src/core/stdchat/chat_10.vcxproj.filters new file mode 100644 index 0000000000..f0744d306e --- /dev/null +++ b/src/core/stdchat/chat_10.vcxproj.filters @@ -0,0 +1,86 @@ + + + + + {ce9c3130-07ac-478e-8752-265c31f3bc8f} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {b87dc5b7-8e8e-49a1-8291-b27797a443b7} + h;hpp;hxx;hm;inl + + + {ac500f7b-22cc-423c-a5e9-35da455c5e6a} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {6f7bae66-5f17-4ccb-8721-25f55e5c4e64} + .txt + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Documentation + + + Documentation + + + Documentation + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/src/core/stdchat/docs/Chat_Readme.txt b/src/core/stdchat/docs/Chat_Readme.txt new file mode 100644 index 0000000000..331fc555fc --- /dev/null +++ b/src/core/stdchat/docs/Chat_Readme.txt @@ -0,0 +1,82 @@ +----------------------------oOo---------------------------- + + Chat v 0.3.1.6 + + Released 2004-05-26, last updated 2005-08-19 + +------------------------------------------------------------ + +Important information +---------- + +#1 This plugin provides a groupchat interface for any protocol that wish to use it. + +#2 End users need not worry about anything more than setting your preferences in + +#3 Developers can take a look at the included m_chat.h for + an introduction on how to use it. Feel free to contact me if you need more + information on how to get it working. + + + +Change log +---------- + +Please go to: +http://www.miranda-im.org/download/details.php?action=viewlog&id=1309 + + + +Author +--------- + +My name is Jörgen Persson, also known as Matrix, I have been using +Miranda IM since 2001 and so far I have been responsible for the IRC part and +I am nowadays considered to be a 'core guy'. If you wish to contact me you can e-mail +me at: i_am_matrix at users dot sourceforge dot net. You can also join #miranda +on the FreeNode network, where you can talk to me and other fans of Miranda IM. + + + +How to install +---------- + +Use an unzipper of choice (I use WinZip) and extract the files to the 'Plugins' +directory of your Miranda IM installation. Please note that you must restart +Miranda IM for the installation to complete. If you are upgrading to another +version you will have to shut down Miranda before extracting the files +or the process will fail. + + + +Credits +---------- + +Egodust, "The coding encyclopedia". Thanks! We miss You!!! +Valkyre, Thanks for the bold, italics and underline icons + + +Base Address +---------- + +0x54 110000 (matrix) + + + +Copyright and license +--------------------- +Copyright (C) 2005 Jörgen Persson + +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. \ No newline at end of file diff --git a/src/core/stdchat/docs/Chat_license.txt b/src/core/stdchat/docs/Chat_license.txt new file mode 100644 index 0000000000..7f1161073d --- /dev/null +++ b/src/core/stdchat/docs/Chat_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. + + + Copyright (C) 19yy + + 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. + + , 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/src/core/stdchat/docs/chat-translation.txt b/src/core/stdchat/docs/chat-translation.txt new file mode 100644 index 0000000000..24c8d5c97a --- /dev/null +++ b/src/core/stdchat/docs/chat-translation.txt @@ -0,0 +1,300 @@ +; Common strings that belong to many files +;[%s disables \'%s\' status for %s] +;[%s enables \'%s\' status for %s] +;[%s has disconnected] +;[%s has joined] +;[%s has left] +;[%s is now known as %s] +;[%s kicked %s] +;[&Message] +;[Background] +;[Background colour] +;[Information] +;[Text colour] +;[Timestamp] + +; ../../plugins/Chat/chat.rc +;[&Close tab] +;[&Copy link] +;[&Open at this position] +;[&Open in current browser window] +;[&Send] +;[(The timeout require at least PopUp plugin v 1.0.1.9. Setting it to 0 means default setting and -1 means indefinite time)] +;[Actions] +;[Add new rooms to group:] +;[C&lose other tabs] +;[Clear] +;[Clear lo&g] +;[Co&py all] +;[Copy] +;[Custom1] +;[Custom2] +;[Cut] +;[Disconnects] +;[Enable highlighting] +;[Enable logging to disk] +;[Google] +;[Limit log text to (events):] +;[Link] +;[List] +;[Log] +;[Log Options] +;[Log directory] +;[Log timestamp] +;[Message] +;[Messages] +;[Nick changes] +;[Notices] +;[OK] +;[Open a &new browser window] +;[Options] +;[Other] +;[Other name] +;[Paste] +;[Popups for the Chat plugin] +;[Redo] +;[Select All] +;[Show these events only:] +;[Spin1] +;[Status changes] +;[Tab1] +;[Tabs] +;[Text] +;[Timeout (s)] +;[Topic changes] +;[Trim to (kB)] +;[Undo ] +;[Use custom colours] +;[Use default colours] +;[Use same style as in the message log] +;[User kicks] +;[Userlist row distance (pixels):] +;[Users joining] +;[Users leaving] +;[Wikipedia] +;[Word lookup] +;[Words to highlight (wildcards allowed)] +;[Your name] + +; ../../plugins/Chat/clist.cpp +;[Join chat] +;[Open chat window] + +; ../../plugins/Chat/log.cpp +;[ (set by %s on %s)] +;[ (set by %s)] +;[Notice from %s: ] +;[The topic is \'%s%s\'] +;[You are now known as %s] +;[You have joined %s] + +; ../../plugins/Chat/main.cpp +;[Miranda could not load the Chat plugin because Microsoft Rich Edit v 3 is missing.\nIf you are using Windows 95/98/NT or WINE please upgrade your Rich Edit control.\n\nDo you want to download an update now?.] + +; ../../plugins/Chat/options.cpp +;[Action (10x10)] +;[Action message] +;[Add Status (10x10)] +;[Add \':\' to auto-completed user names] +;[Appearance and functionality of chat room windows] +;[Appearance of the message log] +;[Bold] +;[Chat] +;[Chat Log] +;[Chat Module] +;[Close] +;[Close tab on doubleclick] +;[Default events to show in new chat rooms if the \'event filter\' is enabled] +;[Display contact status icon before user role icon] +;[Do not play sounds when the chat room is focused] +;[Do not pop up the window when joining a chat room] +;[Enable the \'event filter\' for new rooms] +;[Event filter disabled] +;[Event filter enabled] +;[Flash window when a word is highlighted] +;[Flash window when someone speaks] +;[General] +;[Group Chats] +;[Group Chats Log] +;[Group chats] +;[Hide userlist] +;[Highlight (10x10)] +;[Highlighted message] +;[Icon overlay] +;[Icons to display in the message log] +;[Icons to display in the tray] +;[Incoming message] +;[Indent the second line of a message] +;[Information (10x10)] +;[Information messages] +;[Italics] +;[Join (10x10)] +;[Kick (10x10)] +;[Leave (10x10)] +;[Limit user names in the message log to 20 characters] +;[Message Background] +;[Message Sessions] +;[Message in (10x10)] +;[Message is highlighted] +;[Message out (10x10)] +;[Message typing area] +;[Messaging] +;[Nickchange (10x10)] +;[Notice (10x10)] +;[Notice from user] +;[Only prefix with timestamp if it has changed] +;[Options for using a tabbed interface] +;[Others nicknames] +;[Outgoing message] +;[Pop-ups to display] +;[Popups] +;[Prefix all events with a timestamp] +;[Quit (10x10)] +;[Remove status (10x10)] +;[Restore previously open tabs when showing the window] +;[Room history] +;[Room settings] +;[Save the size and position of chat rooms] +;[Select Folder] +;[Send message by pressing the Enter key] +;[Send message by pressing the Enter key twice] +;[Show actions] +;[Show button for sending messages] +;[Show button menus when right clicking the buttons] +;[Show buttons for controlling the chat room] +;[Show buttons for formatting the text you are typing] +;[Show contact statuses if protocol supports them] +;[Show icon for actions] +;[Show icon for highlights] +;[Show icon for information messages] +;[Show icon for messages] +;[Show icon for name changes] +;[Show icon for notices ] +;[Show icon for status changes] +;[Show icon for topic changes] +;[Show icon for users disconnecting] +;[Show icon for users joining] +;[Show icon for users kicking other user] +;[Show icon for users leaving] +;[Show icon in tray for actions] +;[Show icon in tray for highlights] +;[Show icon in tray for information messages] +;[Show icon in tray for messages] +;[Show icon in tray for name changes] +;[Show icon in tray for notices ] +;[Show icon in tray for status changes] +;[Show icon in tray for topic changes] +;[Show icon in tray for users disconnecting] +;[Show icon in tray for users joining] +;[Show icon in tray for users kicking other user] +;[Show icon in tray for users leaving] +;[Show icons in tray only when the chat room is not active] +;[Show information messages] +;[Show list of users in the chat room] +;[Show messages] +;[Show new windows cascaded] +;[Show notices] +;[Show pop-up for actions] +;[Show pop-up for highlights] +;[Show pop-up for information messages] +;[Show pop-up for messages] +;[Show pop-up for name changes] +;[Show pop-up for notices ] +;[Show pop-up for status changes] +;[Show pop-up for topic changes] +;[Show pop-up for users disconnecting] +;[Show pop-up for users joining] +;[Show pop-up for users kicking other user] +;[Show pop-up for users leaving] +;[Show pop-ups only when the chat room is not active] +;[Show status changes of users] +;[Show tabs at the bottom] +;[Show the topic of the room on your contact list (if supported)] +;[Show topic changes] +;[Show userlist] +;[Show users being kicked] +;[Show users changing name] +;[Show users disconnecting] +;[Show users joining] +;[Show users leaving] +;[Smiley button] +;[Status 1 (10x10)] +;[Status 2 (10x10)] +;[Status 3 (10x10)] +;[Status 4 (10x10)] +;[Status 5 (10x10)] +;[Status 6 (10x10)] +;[Strip colors from messages in the log] +;[The topic has been changed] +;[The topic is ...] +;[Timestamp has same colour as the event] +;[Toggle the visible state when double clicking in the contact list] +;[Topic (10x10)] +;[Underlined] +;[Use a tabbed interface] +;[User disables status for ...] +;[User enables status for ...] +;[User has changed name] +;[User has disconnected] +;[User has joined] +;[User has kicked some other user] +;[User has left] +;[User has performed an action] +;[User has sent a notice] +;[User is now known as ...] +;[User kicked ...] +;[User list members (Online)] +;[User list members (away)] +;[User's status was changed] +;[Userlist Background] +;[Userlist Background (selected)] +;[Userlist Lines] +;[Window Icon] +;[Your nickname] + +; ../../plugins/Chat/services.cpp +;[&Join] +;[&Leave] + +; ../../plugins/Chat/tools.cpp +;[%s %c %s\n] +;[%s %s\n] +;[%s disables \'%s\' status for %s in %s] +;[%s enables \'%s\' status for %s in %s] +;[%s has disconnected (%s)] +;[%s has joined %s] +;[%s has left %s] +;[%s has left (%s)] +;[%s kicked %s (%s)] +;[%s kicked %s from %s] +;[%s says: %s] +;[%s speaks in %s] +;[%s wants your attention in %s] +;[Information in %s] +;[Look up \'%s\':] +;[No word to look up] +;[Notice from %s] +;[Notice from %s: %s] +;[The topic is \'%s\'] +;[The topic is \'%s\' (set by %s)] +;[Topic change in %s] + +; ../../plugins/Chat/window.cpp +;[%s: Chat Room (%u user)] +;[%s: Chat Room (%u users)] +;[%s: Message Session] +;[%s: Message Session (%u users)] +;[Close current tab (CTRL+F4)] +;[Control this room (CTRL+O)] +;[Enable/disable the event filter (CTRL+F)] +;[Insert a smiley] +;[Make the text bold (CTRL+B)] +;[Make the text italicized (CTRL+I)] +;[Make the text underlined (CTRL+U)] +;[Nick name] +;[Select a background color for the text (CTRL+L)] +;[Select a foreground color for the text (CTRL+K)] +;[Show the history (CTRL+H)] +;[Show/hide the nicklist (CTRL+N)] +;[Status] +;[Unique id] diff --git a/src/core/stdchat/res/1.ico b/src/core/stdchat/res/1.ico new file mode 100644 index 0000000000..51dcdc4648 Binary files /dev/null and b/src/core/stdchat/res/1.ico differ diff --git a/src/core/stdchat/res/2.ico b/src/core/stdchat/res/2.ico new file mode 100644 index 0000000000..819ecc1d7a Binary files /dev/null and b/src/core/stdchat/res/2.ico differ diff --git a/src/core/stdchat/res/3.ico b/src/core/stdchat/res/3.ico new file mode 100644 index 0000000000..0928e257fe Binary files /dev/null and b/src/core/stdchat/res/3.ico differ diff --git a/src/core/stdchat/res/4.ico b/src/core/stdchat/res/4.ico new file mode 100644 index 0000000000..5dcea114fa Binary files /dev/null and b/src/core/stdchat/res/4.ico differ diff --git a/src/core/stdchat/res/5.ico b/src/core/stdchat/res/5.ico new file mode 100644 index 0000000000..6aa5806c53 Binary files /dev/null and b/src/core/stdchat/res/5.ico differ diff --git a/src/core/stdchat/res/6.ico b/src/core/stdchat/res/6.ico new file mode 100644 index 0000000000..c35cc39ebc Binary files /dev/null and b/src/core/stdchat/res/6.ico differ diff --git a/src/core/stdchat/res/action.ico b/src/core/stdchat/res/action.ico new file mode 100644 index 0000000000..44816c42d7 Binary files /dev/null and b/src/core/stdchat/res/action.ico differ diff --git a/src/core/stdchat/res/addmode.ico b/src/core/stdchat/res/addmode.ico new file mode 100644 index 0000000000..a6a7e6f38c Binary files /dev/null and b/src/core/stdchat/res/addmode.ico differ diff --git a/src/core/stdchat/res/bkgcolor.ico b/src/core/stdchat/res/bkgcolor.ico new file mode 100644 index 0000000000..e3322ef34b Binary files /dev/null and b/src/core/stdchat/res/bkgcolor.ico differ diff --git a/src/core/stdchat/res/blank.ico b/src/core/stdchat/res/blank.ico new file mode 100644 index 0000000000..7845f62fed Binary files /dev/null and b/src/core/stdchat/res/blank.ico differ diff --git a/src/core/stdchat/res/bold.ico b/src/core/stdchat/res/bold.ico new file mode 100644 index 0000000000..fc34113b6b Binary files /dev/null and b/src/core/stdchat/res/bold.ico differ diff --git a/src/core/stdchat/res/chat.rc b/src/core/stdchat/res/chat.rc new file mode 100644 index 0000000000..fc81743d84 --- /dev/null +++ b/src/core/stdchat/res/chat.rc @@ -0,0 +1,455 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" +#include "richedit.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CHANNEL DIALOGEX 0, 0, 252, 140 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_MESSAGE,RICHEDIT_CLASS,ES_MULTILINE | + ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN | + ES_NUMBER | WS_VSCROLL | WS_TABSTOP,0,128,127,12, + WS_EX_STATICEDGE + PUSHBUTTON "&Send",IDOK,136,126,115,14,WS_DISABLED + CONTROL "",IDC_SMILEY,"MButtonClass",WS_DISABLED | WS_TABSTOP,112,108,15,13,0x18000000L + CONTROL "",IDC_BOLD,"MButtonClass",WS_DISABLED | WS_TABSTOP,8,108,15,13,0x18000000L + CONTROL "",IDC_ITALICS,"MButtonClass",WS_DISABLED | WS_TABSTOP,24,108,15,13,0x18000000L + CONTROL "",IDC_UNDERLINE,"MButtonClass",WS_DISABLED | WS_TABSTOP,40,108,15,13,0x18000000L + CONTROL "",IDC_COLOR,"MButtonClass",WS_DISABLED | WS_TABSTOP,68,108,15,13,0x18000000L + CONTROL "",IDC_BKGCOLOR,"MButtonClass",WS_DISABLED | WS_TABSTOP,84,108,15,13,0x18000000L + CONTROL "",IDC_HISTORY,"MButtonClass",WS_TABSTOP,188,108,15,13,0x18000000L + CONTROL "",IDC_FILTER,"MButtonClass",WS_TABSTOP,220,108,15,13,0x18000000L + CONTROL "",IDC_CHANMGR,"MButtonClass",WS_DISABLED | WS_TABSTOP,204,108,15,13,0x18000000L + CONTROL "",IDC_SHOWNICKLIST,"MButtonClass",WS_TABSTOP,236,108,15,13,0x18000000L + CONTROL "",IDC_LOG,RICHEDIT_CLASS,ES_MULTILINE | ES_AUTOVSCROLL | + ES_READONLY | ES_NUMBER | WS_VSCROLL | WS_TABSTOP,8,23, + 164,73,WS_EX_STATICEDGE + CONTROL "",IDC_SPLITTERX,"Static",SS_ENHMETAFILE,172,23,10,73 + CONTROL "",IDC_SPLITTERY,"Static",SS_ENHMETAFILE,0,102,251,6 + LISTBOX IDC_LIST,182,23,69,73,LBS_OWNERDRAWFIXED | + LBS_NOINTEGRALHEIGHT | LBS_NODATA | NOT WS_BORDER | + WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE + CONTROL "Tab1",IDC_TAB,"SysTabControl32",TCS_MULTILINE,0,0,231,102 + CONTROL "",IDC_CLOSE,"MButtonClass",WS_TABSTOP,236,2,15,13,0x18000000L +END + +IDD_FILTER DIALOGEX 0, 0, 83, 125 +STYLE DS_FIXEDSYS | DS_SETFONT | WS_POPUP | WS_BORDER +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CTEXT "Show these events only:",IDC_TEXTO,0,0,83,13, + SS_CENTERIMAGE + LTEXT "",IDC_STATIC,0,13,83,112 + CONTROL "Actions",IDC_1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,13,73,10 + CONTROL "Messages",IDC_2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,23,73,10 + CONTROL "Nick changes",IDC_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,33,73,10 + CONTROL "Users joining",IDC_4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,43,73,10 + CONTROL "Users leaving",IDC_5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,53,73,10 + CONTROL "Topic changes",IDC_6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,63,73,10 + CONTROL "Status changes",IDC_7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,73,73,10 + CONTROL "Information",IDC_8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,83,73,10 + CONTROL "Disconnects",IDC_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,93,73,10 + CONTROL "User kicks",IDC_10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,103,73,10 + CONTROL "Notices",IDC_11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,113,73,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CHANNEL, DIALOG + BEGIN + RIGHTMARGIN, 251 + VERTGUIDE, 8 + VERTGUIDE, 172 + VERTGUIDE, 182 + VERTGUIDE, 237 + HORZGUIDE, 8 + HORZGUIDE, 23 + HORZGUIDE, 70 + HORZGUIDE, 96 + HORZGUIDE, 102 + HORZGUIDE, 108 + HORZGUIDE, 121 + END + + IDD_FILTER, DIALOG + BEGIN + VERTGUIDE, 5 + VERTGUIDE, 78 + HORZGUIDE, 13 + HORZGUIDE, 117 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPTIONS1 DIALOGEX 0, 0, 300, 230 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Tree1",IDC_CHECKBOXES,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | + TVS_FULLROWSELECT | WS_BORDER | WS_TABSTOP,10,12,280,205 + GROUPBOX "Options",IDC_STATIC,0,0,300,227 +END + +IDD_OPTIONS2 DIALOGEX 0, 0, 300, 200 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Log Options",IDC_STATIC,1,1,294,134 + EDITTEXT IDC_OUTSTAMP,10,19,35,14,ES_AUTOHSCROLL + EDITTEXT IDC_INSTAMP,60,19,35,14,ES_AUTOHSCROLL + LTEXT "Log timestamp",IDC_STATIC,205,11,81,8 + EDITTEXT IDC_LOGTIMESTAMP,205,19,81,14,ES_AUTOHSCROLL + LTEXT "Timestamp",IDC_STATIC,119,11,78,8 + EDITTEXT IDC_TIMESTAMP,118,19,81,14,ES_AUTOHSCROLL + LTEXT "Other name",IDC_STATIC,60,11,57,8 + LTEXT "Your name",IDC_STATIC,10,11,50,8 + CONTROL "Enable highlighting",IDC_HIGHLIGHT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,46,118,10 + LTEXT "Limit log text to (events):",IDC_STATIC,133,46,112,8 + LTEXT "Trim to (kB)",IDC_STATIC,248,104,38,8 + EDITTEXT IDC_LOGLIMIT,248,44,38,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + CONTROL "Spin1",IDC_SPIN2,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | + UDS_NOTHOUSANDS | UDS_HOTTRACK,275,43,11,14 + LTEXT "Words to highlight (wildcards allowed)",IDC_STATIC,10, + 58,240,8 + EDITTEXT IDC_HIGHLIGHTWORDS,10,67,276,14,ES_AUTOHSCROLL + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,10,86,275,1 + CONTROL "Enable logging to disk",IDC_LOGGING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,94,211,10 + LTEXT "Log directory",IDC_STATIC,10,106,211,8 + EDITTEXT IDC_LOGDIRECTORY,10,114,211,14,ES_AUTOHSCROLL | + ES_READONLY + PUSHBUTTON "...",IDC_FONTCHOOSE,221,114,19,14 + EDITTEXT IDC_LIMIT,248,114,38,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + CONTROL "Spin1",IDC_SPIN3,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | + UDS_NOTHOUSANDS | UDS_HOTTRACK,275,112,11,14 + GROUPBOX "Other",IDC_STATIC,1,145,294,53 + LTEXT "Add new rooms to group:",IDC_STATIC,11,159,132,8 + EDITTEXT IDC_GROUP,158,158,49,14,ES_AUTOHSCROLL + LTEXT "Userlist row distance (pixels):",IDC_STATIC,11,180,132, + 8 + EDITTEXT IDC_NICKROW2,158,178,29,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + CONTROL "",IDC_SPIN4,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | + UDS_NOTHOUSANDS | UDS_HOTTRACK,183,178,11,14 +END + +IDD_OPTIONSPOPUP DIALOGEX 0, 0, 277, 177 +STYLE DS_FIXEDSYS | DS_SETFONT | WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Use same style as in the message log",IDC_RADIO1,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,33,29,225,10 + CONTROL "Use default colours",IDC_RADIO2,"Button", + BS_AUTORADIOBUTTON,33,62,217,10 + CONTROL "Use custom colours",IDC_RADIO3,"Button", + BS_AUTORADIOBUTTON,33,95,105,10 + CONTROL "Custom1",IDC_TEXT,"ColourPicker",WS_TABSTOP,141,93,50, + 14,0x18000000L + CONTROL "Custom2",IDC_BKG,"ColourPicker",WS_TABSTOP,201,93,50,14, + 0x18000000L + EDITTEXT IDC_TIMEOUT,132,134,38,14,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | + UDS_NOTHOUSANDS | UDS_HOTTRACK,169,135,11,14 + GROUPBOX "Popups for the Chat plugin",IDC_STATIC,0,0,277,174 + LTEXT "Timeout (s)",IDC_STATIC,33,138,92,8 + LTEXT "Text",IDC_STATIC,141,83,49,8 + LTEXT "Background",IDC_STATIC,201,83,67,8 + LTEXT "(The timeout require at least PopUp plugin v 1.0.1.9. Setting it to 0 means default setting and -1 means indefinite time)", + IDC_STATIC,33,151,207,17 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPTIONS1, DIALOG + BEGIN + VERTGUIDE, 10 + VERTGUIDE, 153 + VERTGUIDE, 181 + VERTGUIDE, 202 + VERTGUIDE, 290 + HORZGUIDE, 12 + HORZGUIDE, 174 + HORZGUIDE, 192 + HORZGUIDE, 213 + END + + IDD_OPTIONS2, DIALOG + BEGIN + LEFTMARGIN, 1 + RIGHTMARGIN, 295 + VERTGUIDE, 10 + VERTGUIDE, 60 + VERTGUIDE, 144 + VERTGUIDE, 158 + VERTGUIDE, 183 + VERTGUIDE, 221 + VERTGUIDE, 286 + TOPMARGIN, 1 + BOTTOMMARGIN, 198 + HORZGUIDE, 108 + HORZGUIDE, 126 + HORZGUIDE, 146 + HORZGUIDE, 158 + HORZGUIDE, 174 + END + + IDD_OPTIONSPOPUP, DIALOG + BEGIN + VERTGUIDE, 33 + VERTGUIDE, 157 + VERTGUIDE, 201 + HORZGUIDE, 49 + HORZGUIDE, 81 + HORZGUIDE, 174 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_TAG1 ICON "tag1.ico" +IDI_TAG2 ICON "tag2.ico" +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Swedish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) +#ifdef _WIN32 +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_COLORCHOOSER DIALOGEX 0, 0, 198, 150 +STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | + WS_VISIBLE | WS_BORDER +EXSTYLE WS_EX_TOPMOST +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,172,136,26,14,NOT WS_TABSTOP + CTEXT "",IDC_COLORTEXT,0,0,197,12,SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_BUNDERLINE ICON "underline.ico" +IDI_BBOLD ICON "bold.ico" +IDI_BITALICS ICON "italics.ico" +IDI_BSMILEY ICON "smiley.ico" +IDI_JOIN ICON "join.ico" +IDI_TOPIC ICON "topic.ico" +IDI_ADDSTATUS ICON "addmode.ico" +IDI_INFO ICON "info.ico" +IDI_KICK ICON "kick.ico" +IDI_MESSAGE ICON "message.ico" +IDI_NICK ICON "nick.ico" +IDI_NOTICE ICON "notice.ico" +IDI_PART ICON "part.ico" +IDI_QUIT ICON "quit.ico" +IDI_REMSTATUS ICON "removestatus.ico" +IDI_HIGHLIGHT ICON "highlight.ico" +IDI_MESSAGEOUT ICON "messageout.ico" +IDI_ACTION ICON "action.ico" +IDI_TOPICBUT ICON "topicbut.ico" +IDI_BKGCOLOR ICON "bkgcolor.ico" +IDI_CHANMGR ICON "window.ico" +IDI_COLOR ICON "color.ico" +IDI_FILTER ICON "filter.ico" +IDI_HISTORY ICON "history.ico" +IDI_NICKLIST ICON "nicklist.ico" +IDI_BLANK ICON "blank.ico" +IDI_STATUS3 ICON "4.ico" +IDI_STATUS2 ICON "3.ico" +IDI_STATUS4 ICON "5.ico" +IDI_STATUS1 ICON "2.ico" +IDI_STATUS0 ICON "1.ico" +IDI_STATUS5 ICON "6.ico" +IDI_CLOSE ICON "close.ico" +IDI_OVERLAY ICON "overlay.ico" +IDI_NICKLIST2 ICON "nicklist2.ico" +IDI_FILTER2 ICON "filter2.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "#include ""richedit.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU +BEGIN + POPUP "List" + BEGIN + MENUITEM "&Message", ID_MESS + END + POPUP "Log" + BEGIN + MENUITEM "Clear lo&g", ID_CLEARLOG + MENUITEM SEPARATOR + MENUITEM "Co&py all", ID_COPYALL + MENUITEM SEPARATOR + POPUP "Word lookup", GRAYED + BEGIN + MENUITEM "Google", ID_SEARCH_GOOGLE + MENUITEM "Wikipedia", ID_SEARCH_WIKIPEDIA + END + END + POPUP "Link" + BEGIN + MENUITEM "Open a &new browser window", ID_NEW + MENUITEM "&Open in current browser window", ID_CURR + MENUITEM "&Copy link", ID_COPY + END + MENUITEM "", 65535 + POPUP "Message" + BEGIN + MENUITEM "Undo ", ID_MESSAGE_UNDO, GRAYED + MENUITEM "Redo", ID_MESSAGE_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Copy", ID_MESSAGE_COPY, GRAYED + MENUITEM "Cut", ID_MESSAGE_CUT, GRAYED + MENUITEM "Paste", ID_MESSAGE_PASTE + MENUITEM "Select All", ID_MESSAGE_SELECTALL + MENUITEM SEPARATOR + MENUITEM "Clear", ID_MESSAGE_CLEAR + END + POPUP "Tabs" + BEGIN + MENUITEM "&Close tab", ID_CLOSE + MENUITEM "C&lose other tabs", ID_CLOSEOTHER + MENUITEM SEPARATOR + MENUITEM "&Open at this position", ID_LOCKPOSITION + END +END + +#endif // Swedish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/core/stdchat/res/close.ico b/src/core/stdchat/res/close.ico new file mode 100644 index 0000000000..20f12dd61f Binary files /dev/null and b/src/core/stdchat/res/close.ico differ diff --git a/src/core/stdchat/res/color.ico b/src/core/stdchat/res/color.ico new file mode 100644 index 0000000000..689762edbb Binary files /dev/null and b/src/core/stdchat/res/color.ico differ diff --git a/src/core/stdchat/res/filter.ico b/src/core/stdchat/res/filter.ico new file mode 100644 index 0000000000..7c99edb58c Binary files /dev/null and b/src/core/stdchat/res/filter.ico differ diff --git a/src/core/stdchat/res/filter2.ico b/src/core/stdchat/res/filter2.ico new file mode 100644 index 0000000000..701890522b Binary files /dev/null and b/src/core/stdchat/res/filter2.ico differ diff --git a/src/core/stdchat/res/highlight.ico b/src/core/stdchat/res/highlight.ico new file mode 100644 index 0000000000..552c912eaa Binary files /dev/null and b/src/core/stdchat/res/highlight.ico differ diff --git a/src/core/stdchat/res/history.ico b/src/core/stdchat/res/history.ico new file mode 100644 index 0000000000..e757b93e54 Binary files /dev/null and b/src/core/stdchat/res/history.ico differ diff --git a/src/core/stdchat/res/info.ico b/src/core/stdchat/res/info.ico new file mode 100644 index 0000000000..1acdb7190b Binary files /dev/null and b/src/core/stdchat/res/info.ico differ diff --git a/src/core/stdchat/res/italics.ico b/src/core/stdchat/res/italics.ico new file mode 100644 index 0000000000..5c61422a71 Binary files /dev/null and b/src/core/stdchat/res/italics.ico differ diff --git a/src/core/stdchat/res/join.ico b/src/core/stdchat/res/join.ico new file mode 100644 index 0000000000..151cd93211 Binary files /dev/null and b/src/core/stdchat/res/join.ico differ diff --git a/src/core/stdchat/res/kick.ico b/src/core/stdchat/res/kick.ico new file mode 100644 index 0000000000..c93e92dd77 Binary files /dev/null and b/src/core/stdchat/res/kick.ico differ diff --git a/src/core/stdchat/res/message.ico b/src/core/stdchat/res/message.ico new file mode 100644 index 0000000000..19957e4ac8 Binary files /dev/null and b/src/core/stdchat/res/message.ico differ diff --git a/src/core/stdchat/res/messageout.ico b/src/core/stdchat/res/messageout.ico new file mode 100644 index 0000000000..637196b745 Binary files /dev/null and b/src/core/stdchat/res/messageout.ico differ diff --git a/src/core/stdchat/res/nick.ico b/src/core/stdchat/res/nick.ico new file mode 100644 index 0000000000..3f199ffd50 Binary files /dev/null and b/src/core/stdchat/res/nick.ico differ diff --git a/src/core/stdchat/res/nicklist.ico b/src/core/stdchat/res/nicklist.ico new file mode 100644 index 0000000000..f2f611d6a4 Binary files /dev/null and b/src/core/stdchat/res/nicklist.ico differ diff --git a/src/core/stdchat/res/nicklist2.ico b/src/core/stdchat/res/nicklist2.ico new file mode 100644 index 0000000000..cba204fe5e Binary files /dev/null and b/src/core/stdchat/res/nicklist2.ico differ diff --git a/src/core/stdchat/res/notice.ico b/src/core/stdchat/res/notice.ico new file mode 100644 index 0000000000..1ba34d7244 Binary files /dev/null and b/src/core/stdchat/res/notice.ico differ diff --git a/src/core/stdchat/res/overlay.ico b/src/core/stdchat/res/overlay.ico new file mode 100644 index 0000000000..28742d898d Binary files /dev/null and b/src/core/stdchat/res/overlay.ico differ diff --git a/src/core/stdchat/res/part.ico b/src/core/stdchat/res/part.ico new file mode 100644 index 0000000000..39c24868aa Binary files /dev/null and b/src/core/stdchat/res/part.ico differ diff --git a/src/core/stdchat/res/quit.ico b/src/core/stdchat/res/quit.ico new file mode 100644 index 0000000000..d7fbdaf4b7 Binary files /dev/null and b/src/core/stdchat/res/quit.ico differ diff --git a/src/core/stdchat/res/removestatus.ico b/src/core/stdchat/res/removestatus.ico new file mode 100644 index 0000000000..ea3cef3fef Binary files /dev/null and b/src/core/stdchat/res/removestatus.ico differ diff --git a/src/core/stdchat/res/smiley.ico b/src/core/stdchat/res/smiley.ico new file mode 100644 index 0000000000..e0d066ce33 Binary files /dev/null and b/src/core/stdchat/res/smiley.ico differ diff --git a/src/core/stdchat/res/smileyc.ico b/src/core/stdchat/res/smileyc.ico new file mode 100644 index 0000000000..d5b8ab0d28 Binary files /dev/null and b/src/core/stdchat/res/smileyc.ico differ diff --git a/src/core/stdchat/res/tag1.ico b/src/core/stdchat/res/tag1.ico new file mode 100644 index 0000000000..1dc687becd Binary files /dev/null and b/src/core/stdchat/res/tag1.ico differ diff --git a/src/core/stdchat/res/tag2.ico b/src/core/stdchat/res/tag2.ico new file mode 100644 index 0000000000..4fac50a4c8 Binary files /dev/null and b/src/core/stdchat/res/tag2.ico differ diff --git a/src/core/stdchat/res/topic.ico b/src/core/stdchat/res/topic.ico new file mode 100644 index 0000000000..e4bb7da7e0 Binary files /dev/null and b/src/core/stdchat/res/topic.ico differ diff --git a/src/core/stdchat/res/topicbut.ico b/src/core/stdchat/res/topicbut.ico new file mode 100644 index 0000000000..ddb72fb8ca Binary files /dev/null and b/src/core/stdchat/res/topicbut.ico differ diff --git a/src/core/stdchat/res/underline.ico b/src/core/stdchat/res/underline.ico new file mode 100644 index 0000000000..01cf64a36a Binary files /dev/null and b/src/core/stdchat/res/underline.ico differ diff --git a/src/core/stdchat/res/version.rc b/src/core/stdchat/res/version.rc new file mode 100644 index 0000000000..c415fe9f91 --- /dev/null +++ b/src/core/stdchat/res/version.rc @@ -0,0 +1,56 @@ +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include +#include "..\src\version.h" + +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page( 1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Miranda\0" + VALUE "FileDescription", "Group chats\0" + VALUE "FileVersion", __VERSION_STRING "\0" + VALUE "InternalName", "chat\0" + VALUE "LegalCopyright", "Copyright ( c) 2002-12 Miranda team\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "chat.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Chat plugin\0" + VALUE "ProductVersion", __VERSION_STRING "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC diff --git a/src/core/stdchat/res/window.ico b/src/core/stdchat/res/window.ico new file mode 100644 index 0000000000..b2c9e0f7b1 Binary files /dev/null and b/src/core/stdchat/res/window.ico differ diff --git a/src/core/stdchat/src/chat.h b/src/core/stdchat/src/chat.h new file mode 100644 index 0000000000..f8130358aa --- /dev/null +++ b/src/core/stdchat/src/chat.h @@ -0,0 +1,552 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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 _CHAT_H_ +#define _CHAT_H_ + +#define MIRANDA_VER 0x0A00 + +//#pragma warning( disable : 4786 ) // limitation in MSVC's debugger. +//#pragma warning( disable : 4996 ) // limitation in MSVC's debugger. + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0501 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" +#include "version.h" +#include "m_ieview.h" +#include "m_smileyadd.h" + +#ifndef NDEBUG +#define new new(_NORMAL_BLOCK, __FILE__, __LINE__) +#endif + +//defines +#define OPTIONS_FONTCOUNT 17 +#define GC_UPDATETITLE (WM_USER+100) +#define GC_SPLITTERMOVED (WM_USER+101) +#define GC_CLOSEWINDOW (WM_USER+103) +#define GC_GETITEMDATA (WM_USER+104) +#define GC_SETITEMDATA (WM_USER+105) +#define GC_UPDATESTATUSBAR (WM_USER+106) +#define GC_SETVISIBILITY (WM_USER+107) +#define GC_SETWNDPROPS (WM_USER+108) +#define GC_REDRAWLOG (WM_USER+109) +#define GC_FIREHOOK (WM_USER+110) +#define GC_FILTERFIX (WM_USER+111) +#define GC_CHANGEFILTERFLAG (WM_USER+112) +#define GC_SHOWFILTERMENU (WM_USER+113) +#define GC_SETWINDOWPOS (WM_USER+114) +#define GC_SAVEWNDPOS (WM_USER+115) +//#define GC_NICKLISTCLEAR (WM_USER+117) +#define GC_REDRAWWINDOW (WM_USER+118) +#define GC_SHOWCOLORCHOOSER (WM_USER+119) +#define GC_ADDLOG (WM_USER+120) +#define GC_ACKMESSAGE (WM_USER+121) +//#define GC_ADDUSER (WM_USER+122) +//#define GC_REMOVEUSER (WM_USER+123) +//#define GC_NICKCHANGE (WM_USER+124) +#define GC_UPDATENICKLIST (WM_USER+125) +//#define GC_MODECHANGE (WM_USER+126) +#define GC_TABCHANGE (WM_USER+127) +#define GC_ADDTAB (WM_USER+128) +#define GC_SCROLLTOBOTTOM (WM_USER+129) +#define GC_REMOVETAB (WM_USER+130) +#define GC_SESSIONNAMECHANGE (WM_USER+131) +#define GC_FIXTABICONS (WM_USER+132) +#define GC_DROPPEDTAB (WM_USER+133) +#define GC_TABCLICKED (WM_USER+134) +#define GC_SWITCHNEXTTAB (WM_USER+135) +#define GC_SWITCHPREVTAB (WM_USER+136) +#define GC_SWITCHTAB (WM_USER+137) +#define GC_SETTABHIGHLIGHT (WM_USER+138) +#define GC_SETMESSAGEHIGHLIGHT (WM_USER+139) +#define GC_REDRAWLOG2 (WM_USER+140) +#define GC_REDRAWLOG3 (WM_USER+141) + +#define EM_SUBCLASSED (WM_USER+200) +#define EM_UNSUBCLASSED (WM_USER+201) +#define EM_ACTIVATE (WM_USER+202) + +#define TIMERID_FLASHWND 205 + +#define GCW_TABROOM 10 +#define GCW_TABPRIVMSG 11 + +#define GC_EVENT_HIGHLIGHT 0x1000 +#define STATE_TALK 0x0001 + +#define ICON_ACTION 0 +#define ICON_ADDSTATUS 1 +#define ICON_HIGHLIGHT 2 +#define ICON_INFO 3 +#define ICON_JOIN 4 +#define ICON_KICK 5 +#define ICON_MESSAGE 6 +#define ICON_MESSAGEOUT 7 +#define ICON_NICK 8 +#define ICON_NOTICE 9 +#define ICON_PART 10 +#define ICON_QUIT 11 +#define ICON_REMSTATUS 12 +#define ICON_TOPIC 13 + +#define ICON_STATUS1 14 +#define ICON_STATUS2 15 +#define ICON_STATUS3 16 +#define ICON_STATUS4 17 +#define ICON_STATUS0 18 +#define ICON_STATUS5 19 + +// special service for tweaking performance +#define MS_GC_GETEVENTPTR "GChat/GetNewEventPtr" +typedef INT_PTR (*GETEVENTFUNC)(WPARAM wParam, LPARAM lParam); +typedef struct { + GETEVENTFUNC pfnAddEvent; +}GCPTRS; + +extern HINSTANCE g_hInst; + +//structs + +typedef struct MODULE_INFO_TYPE +{ + char* pszModule; + TCHAR* ptszModDispName; + char* pszHeader; + BOOL bBold; + BOOL bUnderline; + BOOL bItalics; + BOOL bColor; + BOOL bBkgColor; + BOOL bChanMgr; + BOOL bAckMsg; + int nColorCount; + COLORREF* crColors; + HICON hOnlineIcon; + HICON hOfflineIcon; + HICON hOnlineTalkIcon; + HICON hOfflineTalkIcon; + int OnlineIconIndex; + int OfflineIconIndex; + int iMaxText; + struct MODULE_INFO_TYPE *next; +} + MODULEINFO; + +typedef struct COMMAND_INFO_TYPE +{ + char* lpCommand; + struct COMMAND_INFO_TYPE *last, *next; +} + COMMAND_INFO; + +typedef struct +{ + LOGFONT lf; + COLORREF color; +} + FONTINFO; + +typedef struct LOG_INFO_TYPE +{ + TCHAR* ptszText; + TCHAR* ptszNick; + TCHAR* ptszUID; + TCHAR* ptszStatus; + TCHAR* ptszUserInfo; + BOOL bIsMe; + BOOL bIsHighlighted; + time_t time; + int iType; + struct LOG_INFO_TYPE *next; + struct LOG_INFO_TYPE *prev; +} + LOGINFO; + +typedef struct STATUSINFO_TYPE +{ + TCHAR* pszGroup; + HICON hIcon; + WORD Status; + struct STATUSINFO_TYPE *next; +} + STATUSINFO; + +typedef struct USERINFO_TYPE +{ + TCHAR* pszNick; + TCHAR* pszUID; + WORD Status; + int iStatusEx; + WORD ContactStatus; + struct USERINFO_TYPE *next; +} + USERINFO; + +typedef struct TABLIST_TYPE +{ + TCHAR* pszID; + char* pszModule; + struct TABLIST_TYPE *next; +} + TABLIST; + +typedef struct SESSION_INFO_TYPE +{ + HWND hWnd; + + BOOL bFGSet; + BOOL bBGSet; + BOOL bFilterEnabled; + BOOL bNicklistEnabled; + BOOL bInitDone; + + char* pszModule; + TCHAR* ptszID; + TCHAR* ptszName; + TCHAR* ptszStatusbarText; + TCHAR* ptszTopic; + + // I hate m3x, Unicode, IRC, chats etc... + char* pszID; // ugly fix for returning static ANSI strings in GC_INFO + char* pszName; // just to fix a bug quickly, should die after porting IRC to Unicode + + int iType; + int iFG; + int iBG; + int iSplitterY; + int iSplitterX; + int iLogFilterFlags; + int nUsersInNicklist; + int iEventCount; + int iX; + int iY; + int iWidth; + int iHeight; + int iStatusCount; + + WORD wStatus; + WORD wState; + WORD wCommandsNum; + DWORD dwItemData; + DWORD dwFlags; + HANDLE hContact; + HWND hwndStatus; + time_t LastTime; + + COMMAND_INFO* lpCommands; + COMMAND_INFO* lpCurrentCommand; + LOGINFO* pLog; + LOGINFO* pLogEnd; + USERINFO* pUsers; + USERINFO* pMe; + STATUSINFO* pStatuses; + + HWND hwndTooltip; + int iOldItemID; + + IAccPropServices* pAccPropServicesForNickList; + struct SESSION_INFO_TYPE *next; +} + SESSION_INFO; + +typedef struct +{ + char* buffer; + int bufferOffset, bufferLen; + HWND hwnd; + LOGINFO* lin; + BOOL bStripFormat; + BOOL bRedraw; + SESSION_INFO* si; +} + LOGSTREAMDATA; + +struct CREOleCallback : public IRichEditOleCallback +{ + CREOleCallback() : refCount(0) {} + unsigned refCount; + IStorage *pictStg; + int nextStgId; + + STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * lplpObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode); + STDMETHOD(GetNewStorage) (LPSTORAGE FAR * lplpstg); + STDMETHOD(GetInPlaceContext) (LPOLEINPLACEFRAME FAR * lplpFrame, LPOLEINPLACEUIWINDOW FAR * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo); + STDMETHOD(ShowContainerUI) (BOOL fShow); + STDMETHOD(QueryInsertObject) (LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp); + STDMETHOD(DeleteObject) (LPOLEOBJECT lpoleobj); + STDMETHOD(QueryAcceptData) (LPDATAOBJECT lpdataobj, CLIPFORMAT FAR * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict); + STDMETHOD(GetClipboardData) (CHARRANGE FAR * lpchrg, DWORD reco, LPDATAOBJECT FAR * lplpdataobj); + STDMETHOD(GetDragDropEffect) (BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect); + STDMETHOD(GetContextMenu) (WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE FAR * lpchrg, HMENU FAR * lphmenu) ; +}; + +struct GlobalLogSettings_t { + BOOL ShowTime; + BOOL ShowTimeIfChanged; + BOOL LoggingEnabled; + BOOL FlashWindow; + BOOL HighlightEnabled; + BOOL LogIndentEnabled; + BOOL StripFormat; + BOOL SoundsFocus; + BOOL PopUpInactiveOnly; + BOOL TrayIconInactiveOnly; + BOOL AddColonToAutoComplete; + BOOL TabsEnable; + BOOL TabCloseOnDblClick; + BOOL TabRestore; + BOOL LogLimitNames; + BOOL TabsAtBottom; + BOOL TimeStampEventColour; + DWORD dwIconFlags; + DWORD dwTrayIconFlags; + DWORD dwPopupFlags; + int LogTextIndent; + int LoggingLimit; + int iEventLimit; + int iPopupStyle; + int iPopupTimeout; + int iSplitterX; + int iSplitterY; + int iX; + int iY; + int iWidth; + int iHeight; + TCHAR* pszTimeStamp; + TCHAR* pszTimeStampLog; + TCHAR* pszIncomingNick; + TCHAR* pszOutgoingNick; + TCHAR* pszHighlightWords; + TCHAR* pszLogDir; + HFONT UserListFont; + HFONT UserListHeadingsFont; + HFONT MessageBoxFont; + HFONT NameFont; + COLORREF crLogBackground; + COLORREF crUserListColor; + COLORREF crUserListBGColor; + COLORREF crUserListSelectedBGColor; + COLORREF crUserListHeadingsColor; + COLORREF crPUTextColour; + COLORREF crPUBkgColour; + BOOL ShowContactStatus; + BOOL ContactStatusFirst; +}; +extern struct GlobalLogSettings_t g_Settings; + +typedef struct{ + MODULEINFO* pModule; + int xPosition; + int yPosition; + HWND hWndTarget; + BOOL bForeground; + SESSION_INFO* si; +} + COLORCHOOSER; + +//main.c +void LoadIcons(void); +void LoadLogIcons(void); +void FreeIcons(void); +void UpgradeCheck(void); + +//colorchooser.c +INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//log.c +void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO* si, BOOL bRedraw, BOOL bPhaseTwo); +void LoadMsgLogBitmaps(void); +void FreeMsgLogBitmaps(void); +void ValidateFilename (TCHAR * filename); +TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time); +char* Log_CreateRtfHeader(MODULEINFO * mi); + +//window.c +INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam); +int GetTextPixelSize( TCHAR* pszText, HFONT hFont, BOOL bWidth); + +//options.c +int OptionsInit(void); +int OptionsUnInit(void); +void LoadMsgDlgFont(int i, LOGFONT * lf, COLORREF * colour); +void LoadGlobalSettings(void); +void AddIcons(void); +HICON LoadIconEx(char* pszIcoLibName, BOOL big); +void LoadLogFonts(void); + +//services.c +void HookEvents(void); +void UnhookEvents(void); +void CreateServiceFunctions(void); +void DestroyServiceFunctions(void); +void CreateHookableEvents(void); +void DestroyHookableEvents(void); +void TabsInit(void); +void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground); + +//manager.c +void SetActiveSession(const TCHAR* pszID, const char* pszModule); +void SetActiveSessionEx(SESSION_INFO* si); +SESSION_INFO* GetActiveSession(void); +SESSION_INFO* SM_AddSession(const TCHAR* pszID, const char* pszModule); +int SM_RemoveSession(const TCHAR* pszID, const char* pszModule, BOOL removeContact); +SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule); +USERINFO* SM_AddUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus); +BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID); +BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce); +BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID); +BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule); +BOOL SM_SetTabbedWindowHwnd(SESSION_INFO* si, HWND hwnd); +HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO * ui); +BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus); +BOOL SM_SetStatusEx(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags ); +BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText); +STATUSINFO* SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus); +SESSION_INFO* SM_GetNextWindow(SESSION_INFO* si); +SESSION_INFO* SM_GetPrevWindow(SESSION_INFO* si); +BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce); +BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted); +LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync); +BOOL SM_RemoveAll (void); +BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus); +BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD pszStatus); +BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus); +BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID); +void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand); +char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule); +char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule); +int SM_GetCount(const char* pszModule); +SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem); +char* SM_GetUsers(SESSION_INFO* si); +USERINFO* SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index); +MODULEINFO* MM_AddModule(const char* pszModule); +MODULEINFO* MM_FindModule(const char* pszModule); +void MM_FixColors(); +void MM_FontsChanged(void); +void MM_IconsChanged(void); +BOOL MM_RemoveAll (void); +BOOL TabM_AddTab(const TCHAR* pszID, const char* pszModule); +BOOL TabM_RemoveAll (void); +STATUSINFO* TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount); +STATUSINFO* TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus); +WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus); +TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status); +BOOL TM_RemoveAll (STATUSINFO** pStatusList); +BOOL UM_SetStatusEx(USERINFO* pUserList,const TCHAR* pszText, int onlyMe ); +USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** pUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus); +USERINFO* UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID); +USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID); +USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index); +USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status); +USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status); +USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status); +TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent); +BOOL UM_RemoveUser(USERINFO** pUserList, const TCHAR* pszUID); +BOOL UM_RemoveAll (USERINFO** ppUserList); +LOGINFO* LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd); +BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount); +BOOL LM_RemoveAll (LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd); + +//clist.c +HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType); +BOOL CList_SetOffline(HANDLE hContact, BOOL bHide); +BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule); +int CList_RoomDoubleclicked(WPARAM wParam,LPARAM lParam); +INT_PTR CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam); +INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam); +INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam); +int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam); +INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam); +void CList_CreateGroup(TCHAR* group); +BOOL CList_AddEvent(HANDLE hContact, HICON hIcon, HANDLE hEvent, int type, TCHAR* fmt, ... ) ; +HANDLE CList_FindRoom (const char* pszModule, const TCHAR* pszRoom) ; +int WCCmp(TCHAR* wild, TCHAR*string); + +//tools.c +TCHAR* RemoveFormatting(const TCHAR* pszText); +BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix); +int GetColorIndex(const char* pszModule, COLORREF cr); +void CheckColorsInModule(const char* pszModule); +const TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) ; +int GetRichTextLength(HWND hwnd); +BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText); +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText); +void DestroyGCMenu(HMENU *hMenu, int iIndex); +BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem); +BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem); +BOOL IsEventSupported(int eventType); +BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce); + +// message.c +char* Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si); +TCHAR* DoRtfToTags( char* pszRtfText, SESSION_INFO* si); + +#pragma comment(lib,"comctl32.lib") + +////////////////////////////////////////////////////////////////////////////////// + +TCHAR* a2tf( const TCHAR* str, int flags ); +TCHAR* replaceStr( TCHAR** dest, const TCHAR* src ); +char* replaceStrA( char** dest, const char* src ); + +#endif diff --git a/src/core/stdchat/src/clist.cpp b/src/core/stdchat/src/clist.cpp new file mode 100644 index 0000000000..df60f1de3a --- /dev/null +++ b/src/core/stdchat/src/clist.cpp @@ -0,0 +1,360 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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 "chat.h" + +extern HANDLE hJoinMenuItem, hLeaveMenuItem; + +HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType) +{ + HANDLE hContact = CList_FindRoom(pszModule, pszRoom); + DBVARIANT dbv; + TCHAR pszGroup[50]; + + *pszGroup = '\0'; + if ( !DBGetContactSettingTString( NULL, "Chat", "AddToGroup", &dbv )) { + if ( lstrlen( dbv.ptszVal ) > 0 ) + lstrcpyn( pszGroup, dbv.ptszVal, 50); + DBFreeVariant(&dbv); + } + else lstrcpyn( pszGroup, _T("Chat rooms"), 50); + + if ( pszGroup[0] ) + CList_CreateGroup( pszGroup ); + + if ( hContact ) { //contact exist, make sure it is in the right group + DBVARIANT dbv; + DBVARIANT dbv2; + char str[50]; + int i; + + if ( pszGroup[0] ) { + for (i = 0;; i++) { + _itoa( i, str, 10 ); + if ( DBGetContactSettingTString( NULL, "CListGroups", str, &dbv )) { + DBWriteContactSettingTString(hContact, "CList", "Group", pszGroup); + goto END_GROUPLOOP; + } + + if ( !DBGetContactSettingTString( hContact, "CList", "Group", &dbv2 )) { + if ( dbv.ptszVal[0] != '\0' && dbv2.ptszVal[0] != '\0' && !lstrcmpi( dbv.ptszVal + 1, dbv2.ptszVal )) { + DBFreeVariant( &dbv ); + DBFreeVariant( &dbv2 ); + goto END_GROUPLOOP; + } + DBFreeVariant(&dbv2); + } + DBFreeVariant(&dbv); + } } + +END_GROUPLOOP: + DBWriteContactSettingWord( hContact, pszModule, "Status", ID_STATUS_OFFLINE ); + DBWriteContactSettingTString(hContact, pszModule, "Nick", pszDisplayName ); +/* if ( iType != GCW_SERVER ) + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/ + return hContact; + } + + // here we create a new one since no one is to be found + if (( hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0)) == NULL ) + return NULL; + + CallService( MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) pszModule ); + if ( pszGroup && lstrlen( pszGroup ) > 0 ) + DBWriteContactSettingTString(hContact, "CList", "Group", pszGroup ); + else + DBDeleteContactSetting( hContact, "CList", "Group" ); + DBWriteContactSettingTString( hContact, pszModule, "Nick", pszDisplayName ); + DBWriteContactSettingTString( hContact, pszModule, "ChatRoomID", pszRoom ); + DBWriteContactSettingByte( hContact, pszModule, "ChatRoom", (BYTE)iType ); + DBWriteContactSettingWord( hContact, pszModule, "Status", ID_STATUS_OFFLINE ); +// if (iType == GCW_SERVER) + // DBWriteContactSettingByte(hContact, "CList", "Hidden", 1); + return hContact; +} + +BOOL CList_SetOffline(HANDLE hContact, BOOL bHide) +{ + if ( hContact ) { + char* szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + int i = DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0); + DBWriteContactSettingWord(hContact, szProto,"ApparentMode",(LPARAM) 0); + DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); +/* if ( bHide && i != GCW_SERVER ) + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/ + return TRUE; + } + + return FALSE; +} + +BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule) +{ + HANDLE hContact; + char* szProto; + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while ( hContact ) { + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( MM_FindModule( szProto )) { + if ( !pszModule || ( pszModule && !strcmp( pszModule, szProto ))) { + int i = DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0); + if ( i != 0 ) { + DBWriteContactSettingWord(hContact, szProto,"ApparentMode",(LPARAM)(WORD) 0); + DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); + /*0000if (bHide && i == GCW_CHATROOM)d0 + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/ + } } } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + return TRUE; +} + +int CList_RoomDoubleclicked( WPARAM wParam, LPARAM lParam ) +{ + DBVARIANT dbv; + char *szProto; + BOOL bRedrawFlag = FALSE; + + HANDLE hContact = (HANDLE)wParam; + if ( !hContact ) + return 0; + + szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( MM_FindModule(szProto)) { + if ( DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0 ) == 0 ) + return 0; + + if ( !DBGetContactSettingTString( hContact, szProto, "ChatRoomID", &dbv )) { + SESSION_INFO* si = SM_FindSession( dbv.ptszVal, szProto ); + if ( si ) { + // is the "toggle visibility option set, so we need to close the window? + if (si->hWnd != NULL + && DBGetContactSettingByte(NULL, "Chat", "ToggleVisibility", 0)==1 + && !CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0) + && IsWindowVisible(si->hWnd) + && !IsIconic(si->hWnd)) + { + if (g_Settings.TabsEnable) + SendMessage(si->hWnd, GC_REMOVETAB, 1, (LPARAM) si ); + else + PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0); + DBFreeVariant(&dbv); + return 1; + } + ShowRoom(si, WINDOW_VISIBLE, TRUE); + } + DBFreeVariant(&dbv); + return 1; + } } + + return 0; +} + +INT_PTR CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam) +{ + return CList_RoomDoubleclicked((WPARAM) ((CLISTEVENT*)lParam)->hContact,(LPARAM) 0); +} + +INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + if ( hContact ) { + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( szProto ) { + if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE ) + CallProtoService( szProto, PS_JOINCHAT, wParam, lParam ); + else + CList_RoomDoubleclicked( wParam, 0 ); + } } + + return 0; +} + +INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + if ( hContact ) { + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( szProto ) + CallProtoService( szProto, PS_LEAVECHAT, wParam, lParam ); + } + return 0; +} + +int CList_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 ) { + // display this menu item only for chats + if ( DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0 )) { + // still hide it for offline protos + if ( CallProtoService( szProto, PS_GETSTATUS, 0, 0 ) != ID_STATUS_OFFLINE ) { + clmi.flags &= ~CMIF_HIDDEN; + clmi.flags |= CMIM_NAME; + + if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE ) + clmi.pszName = ( char* )LPGEN("Join chat"); + else + clmi.pszName = ( char* )LPGEN("Open chat window"); + } } } + CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hJoinMenuItem, ( LPARAM )&clmi ); + + clmi.flags &= ~(CMIM_NAME | CMIF_DEFAULT); + clmi.flags |= CMIF_NOTOFFLINE; + CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hLeaveMenuItem, ( LPARAM )&clmi ); + } + return 0; +} + +INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam) +{ + return CList_PrebuildContactMenu(wParam, lParam); +} + + +void CList_CreateGroup(TCHAR* group) +{ + int i; + char str[50]; + TCHAR name[256]; + DBVARIANT dbv; + + if ( !group ) + return; + + for (i = 0;; i++) + { + _itoa(i, str, 10); + if ( DBGetContactSettingTString( NULL, "CListGroups", str, &dbv )) + break; + + if ( dbv.pszVal[0] != '\0' && !lstrcmpi(dbv.ptszVal + 1, group)) { + DBFreeVariant(&dbv); + return; + } + + DBFreeVariant(&dbv); + } + + // CallService(MS_CLIST_GROUPCREATE, (WPARAM)group, 0); + name[0] = 1 | GROUPF_EXPANDED; + _tcsncpy(name + 1, group, SIZEOF(name) - 1); + name[ lstrlen(group) + 1] = '\0'; + DBWriteContactSettingTString(NULL, "CListGroups", str, name); + CallService(MS_CLUI_GROUPADDED, i + 1, 0); +} + +BOOL CList_AddEvent(HANDLE hContact, HICON hIcon, HANDLE hEvent, int type, TCHAR* fmt, ... ) +{ + CLISTEVENT cle = {0}; + va_list marker; + TCHAR szBuf[4096]; + + if (!fmt || !fmt[0] || _tcslen(fmt) > 2000) + return FALSE; + + va_start(marker, fmt); + _vsntprintf(szBuf, SIZEOF(szBuf), fmt, marker); + va_end(marker); + + cle.cbSize = sizeof(cle); + cle.hContact = hContact; + cle.hDbEvent = hEvent; + cle.flags = type | CLEF_TCHAR; + cle.hIcon = hIcon; + cle.pszService = "GChat/DblClickEvent" ; + cle.ptszTooltip = TranslateTS(szBuf); + if (type) { + if (!CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)) + CallService(MS_CLIST_ADDEVENT, (WPARAM) hContact, (LPARAM) &cle); + } + else { + if (CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hEvent); + CallService(MS_CLIST_ADDEVENT, (WPARAM)hContact, (LPARAM)&cle); + } + return TRUE; +} + +HANDLE CList_FindRoom ( const char* pszModule, const TCHAR* pszRoom) +{ + HANDLE hContact = ( HANDLE )CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) { + char* szProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0 ); + if ( szProto && !lstrcmpiA( szProto, pszModule )) { + if ( DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0) != 0 ) { + DBVARIANT dbv; + if ( !DBGetContactSettingTString( hContact, szProto, "ChatRoomID", &dbv )) { + if ( !lstrcmpi(dbv.ptszVal, pszRoom)) { + DBFreeVariant( &dbv ); + return hContact; + } + DBFreeVariant(&dbv); + } } } + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + return 0; +} + +int WCCmp(TCHAR* wild, TCHAR* string) +{ + TCHAR *cp, *mp; + if ( wild == NULL || !wild[0] || string == NULL || !string[0]) + return 0; + + while ((*string) && (*wild != '*')) { + if ((*wild != *string) && (*wild != '?')) + return 0; + + wild++; + string++; + } + + while (*string) { + if (*wild == '*') { + if (!*++wild) + return 1; + + mp = wild; + cp = string+1; + } + else if ((*wild == *string) || (*wild == '?')) { + wild++; + string++; + } + else { + wild = mp; + string = cp++; + } } + + while (*wild == '*') + wild++; + + return !*wild; +} diff --git a/src/core/stdchat/src/colorchooser.cpp b/src/core/stdchat/src/colorchooser.cpp new file mode 100644 index 0000000000..0d2642165f --- /dev/null +++ b/src/core/stdchat/src/colorchooser.cpp @@ -0,0 +1,266 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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. +*/ + + +// this color chooser window is inspired by PeaCow's smiley chooser window for the Smileyadd plugin + +#include "chat.h" +#include + +static int CalculateCoordinatesToButton(COLORCHOOSER * pCC, POINT pt) +{ + int iSquareRoot = (int)sqrt((double)pCC->pModule->nColorCount); + int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount?iSquareRoot+1:iSquareRoot; + + int col = pt.x / 25; + int row = (pt.y-20) / 20; + int pos = nCols * row + col; + + if (pt.y < 20 && pos >= pCC->pModule->nColorCount) + pos = -1; + + return pos; +} + +static RECT CalculateButtonToCoordinates(COLORCHOOSER * pCC, int buttonPosition) +{ + RECT pt; + int iSquareRoot = (int)sqrt((double)pCC->pModule->nColorCount); + int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount?iSquareRoot+1:iSquareRoot; + + int row = buttonPosition / nCols; + int col = buttonPosition % nCols; + + pt.left = col * 25+1; + pt.top = row * 20 + 20; + pt.right = pt.left + 25-1; + pt.bottom = pt.top + 20; + + return pt; +} + +INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static COLORCHOOSER* pCC = NULL; + static int iCurrentHotTrack; + static BOOL bChoosing; + static int iRows; + static int iColumns; + static HWND hPreviousActiveWindow; + + switch(msg) { + case WM_INITDIALOG: + { + RECT rc; + int iSquareRoot; + int width ; + int height; + + TranslateDialogDefault(hwndDlg); + pCC = (COLORCHOOSER*) lParam; + + iCurrentHotTrack = -2; + bChoosing = FALSE; + + iSquareRoot = (int)sqrt((double)pCC->pModule->nColorCount); + + iColumns = iSquareRoot * iSquareRoot == pCC->pModule->nColorCount?iSquareRoot:iSquareRoot+1; + iRows = iSquareRoot; + + rc.top = rc.left = 100; + rc.right = 100 + iColumns * 25 + 1; + rc.bottom = iRows * 20 + 100 + 20; + + AdjustWindowRectEx(&rc, GetWindowLongPtr(hwndDlg, GWL_STYLE), FALSE, GetWindowLongPtr(hwndDlg, GWL_EXSTYLE)); + + width = rc.right - rc.left; + height = rc.bottom - rc.top; + + pCC->yPosition -= height; + + + SetDlgItemText(hwndDlg, IDC_COLORTEXT, pCC->bForeground?TranslateT("Text colour"):TranslateT("Background colour")); + SetWindowPos(GetDlgItem(hwndDlg, IDC_COLORTEXT), NULL, 0, 0, width, 20, 0); + SetWindowPos(hwndDlg, NULL, pCC->xPosition, pCC->yPosition, width, height, SWP_SHOWWINDOW); + } + break; + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + if (( HWND )lParam == GetDlgItem( hwndDlg, IDC_COLORTEXT )) { + SetTextColor((HDC)wParam,RGB(60,60,150)); + SetBkColor((HDC)wParam,GetSysColor(COLOR_WINDOW)); + return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); + } + break; + + case WM_COMMAND: + switch ( LOWORD( wParam )) { + case IDOK: + if (iCurrentHotTrack >= 0) + PostMessage(hwndDlg, WM_LBUTTONUP, 0, 0); + break; + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_LBUTTONUP: + if (iCurrentHotTrack >= 0 && iCurrentHotTrack < pCC->pModule->nColorCount && pCC->hWndTarget != NULL) { + HWND hWindow; + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = 0; + cf.dwEffects = 0; + hWindow = GetParent( pCC->hWndTarget ); + + if ( pCC->bForeground ) { + pCC->si->bFGSet = TRUE; + pCC->si->iFG = iCurrentHotTrack; + if ( IsDlgButtonChecked( hWindow, IDC_COLOR )) { + cf.dwMask = CFM_COLOR; + cf.crTextColor = pCC->pModule->crColors[iCurrentHotTrack]; + SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + else { + pCC->si->bBGSet = TRUE; + pCC->si->iBG = iCurrentHotTrack; + if ( IsDlgButtonChecked( hWindow, IDC_BKGCOLOR )) { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = pCC->pModule->crColors[iCurrentHotTrack]; + SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } } + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + + case WM_ACTIVATE: + if (wParam == WA_INACTIVE) + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + else if ((wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE)) + hPreviousActiveWindow = (HWND)lParam; + break; + + case WM_MOUSEMOVE: + { + HDC hdc = GetDC(hwndDlg); + POINT pt; + RECT rect; + int but; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + if (iCurrentHotTrack == -2) + return 0; // prevent focussing when not drawn yet! + + but = CalculateCoordinatesToButton(pCC, pt); + + // weird stuff + if (but != iCurrentHotTrack) { + if (iCurrentHotTrack >= 0) { + rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack); + DrawFocusRect(hdc, &rect); + iCurrentHotTrack = -1; + } + iCurrentHotTrack = but; + + if (iCurrentHotTrack >= 0) { + rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack); + DrawFocusRect(hdc, &rect); + } } + ReleaseDC(hwndDlg, hdc); + } + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc; + RECT rc; + int i = 0; + int iThisRow = 1; + int iThisColumn = 0; + + GetClientRect(hwndDlg, &rc); + + rc.top += 20; + + hdc = BeginPaint(hwndDlg, &ps); + + // fill background + FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); + + for (i; i < pCC->pModule->nColorCount; i++) { + HBRUSH hbr; + + // decide place to draw the color block in the window + iThisColumn ++; + if (iThisColumn > iColumns) { + iThisColumn = 1; + iThisRow++; + } + + if ( pCC->bForeground && pCC->si->bFGSet && pCC->si->iFG == i || + !pCC->bForeground && pCC->si->bBGSet && pCC->si->iBG == i ) { + rc.top = (iThisRow-1) * 20+ 1 +20 ; + rc.left = (iThisColumn-1) * 25 + 1 + 1 ; + rc.bottom = iThisRow * 20- 1 + 20 ; + rc.right = iThisColumn * 25-1 ; + + DrawEdge(hdc, &rc, EDGE_RAISED, BF_TOP|BF_LEFT|BF_RIGHT|BF_BOTTOM); + } + + rc.top = (iThisRow-1) * 20+ 3 +20 ; + rc.left = (iThisColumn-1) * 25 + 3 + 1 ; + rc.bottom = iThisRow * 20- 3 + 20 ; + rc.right = iThisColumn * 25-3 ; + + FillRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + + hbr = CreateSolidBrush(pCC->pModule->crColors[i]); + + rc.top = (iThisRow-1) * 20+4 +20; + rc.left = (iThisColumn-1) * 25+ 4 + 1; + rc.bottom = iThisRow * 20-4 + 20; + rc.right = iThisColumn * 25-4; + + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + } + + EndPaint(hwndDlg, &ps); + iCurrentHotTrack = -1; + } + break; + + case WM_CLOSE: + SetFocus(pCC->hWndTarget); + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + mir_free( pCC ); + return TRUE; + } + + return FALSE; +} diff --git a/src/core/stdchat/src/log.cpp b/src/core/stdchat/src/log.cpp new file mode 100644 index 0000000000..86b2f41b0a --- /dev/null +++ b/src/core/stdchat/src/log.cpp @@ -0,0 +1,712 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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 "chat.h" + + +// The code for streaming the text is to a large extent copied from +// the srmm module and then modified to fit the chat module. + +extern FONTINFO aFonts[OPTIONS_FONTCOUNT]; +extern HICON hIcons[30]; +extern BOOL SmileyAddInstalled; + +static PBYTE pLogIconBmpBits[14]; +static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ]; + +static int logPixelSY = 0; +static int logPixelSX = 0; + +static int EventToIndex(LOGINFO * lin) +{ + switch (lin->iType) { + case GC_EVENT_MESSAGE: + if (lin->bIsMe) + return 10; + else + return 9; + + case GC_EVENT_JOIN: return 3; + case GC_EVENT_PART: return 4; + case GC_EVENT_QUIT: return 5; + case GC_EVENT_NICK: return 7; + case GC_EVENT_KICK: return 6; + case GC_EVENT_NOTICE: return 8; + case GC_EVENT_TOPIC: return 11; + case GC_EVENT_INFORMATION:return 12; + case GC_EVENT_ADDSTATUS: return 13; + case GC_EVENT_REMOVESTATUS: return 14; + case GC_EVENT_ACTION: return 15; + } + return 0; +} + +static int EventToIcon(LOGINFO * lin) +{ + switch (lin->iType) { + case GC_EVENT_MESSAGE: + if (lin->bIsMe) + return ICON_MESSAGEOUT; + else + return ICON_MESSAGE; + + case GC_EVENT_JOIN: return ICON_JOIN; + case GC_EVENT_PART: return ICON_PART; + case GC_EVENT_QUIT: return ICON_QUIT; + case GC_EVENT_NICK: return ICON_NICK; + case GC_EVENT_KICK: return ICON_KICK; + case GC_EVENT_NOTICE: return ICON_NOTICE; + case GC_EVENT_TOPIC: return ICON_TOPIC; + case GC_EVENT_INFORMATION:return ICON_INFO; + case GC_EVENT_ADDSTATUS: return ICON_ADDSTATUS; + case GC_EVENT_REMOVESTATUS: return ICON_REMSTATUS; + case GC_EVENT_ACTION: return ICON_ACTION; + } + return 0; +} + +static char *Log_SetStyle(int style, int fontindex) +{ + static char szStyle[128]; + mir_snprintf(szStyle, SIZEOF(szStyle), "\\f%u\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", style, style+1, aFonts[fontindex].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[fontindex].lf.lfItalic, 2 * abs(aFonts[fontindex].lf.lfHeight) * 74 / logPixelSY); + return szStyle; +} + +static void Log_Append(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...) +{ + va_list va; + int charsDone = 0; + + va_start(va, fmt); + for (;;) { + charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va); + if (charsDone >= 0) + break; + *cbBufferAlloced += 4096; + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + va_end(va); + *cbBufferEnd += charsDone; +} + +static int Log_AppendRTF(LOGSTREAMDATA* streamData, BOOL simpleMode, char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...) +{ + va_list va; + int lineLen, textCharsCount=0; + TCHAR* line = (TCHAR*)alloca(8001 * sizeof(TCHAR)); + char* d; + + va_start(va, fmt); + lineLen = _vsntprintf( line, 8000, fmt, va); + if (lineLen < 0) lineLen = 8000; + line[lineLen] = 0; + va_end(va); + + lineLen = lineLen*20 + 8; + if (*cbBufferEnd + lineLen > *cbBufferAlloced) { + cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + + d = *buffer + *cbBufferEnd; + + for (; *line; line++, textCharsCount++) { + if (*line == '\r' && line[1] == '\n') { + CopyMemory(d, "\\par ", 5); + line++; + d += 5; + } + else if (*line == '\n') { + CopyMemory(d, "\\line ", 6); + d += 6; + } + else if (*line == '%' && !simpleMode ) { + char szTemp[200]; + + szTemp[0] = '\0'; + switch ( *++line ) { + case '\0': + case '%': + *d++ = '%'; + break; + + case 'c': + case 'f': + if (g_Settings.StripFormat || streamData->bStripFormat) + line += 2; + + else if ( line[1] != '\0' && line[2] != '\0') { + TCHAR szTemp3[3], c = *line; + int col; + szTemp3[0] = line[1]; + szTemp3[1] = line[2]; + szTemp3[2] = '\0'; + line += 2; + + col = _ttoi(szTemp3); + col += (OPTIONS_FONTCOUNT + 1); + mir_snprintf(szTemp, SIZEOF(szTemp), ( c == 'c' ) ? "\\cf%u " : "\\highlight%u ", col); + } + break; + case 'C': + case 'F': + if ( !g_Settings.StripFormat && !streamData->bStripFormat) { + int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); + if ( *line == 'C' ) + mir_snprintf(szTemp, SIZEOF(szTemp), "\\cf%u ", j+1); + else + mir_snprintf(szTemp, SIZEOF(szTemp), "\\highlight0 "); + } + break; + case 'b': + case 'u': + case 'i': + if ( !streamData->bStripFormat ) + mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'u') ? "\\%cl " : "\\%c ", *line ); + break; + + case 'B': + case 'U': + case 'I': + if ( !streamData->bStripFormat ) { + mir_snprintf( szTemp, SIZEOF(szTemp), (*line == 'U') ? "\\%cl0 " : "\\%c0 ", *line ); + CharLowerA( szTemp ); + } + break; + + case 'r': + if ( !streamData->bStripFormat ) { + int index = EventToIndex(streamData->lin); + mir_snprintf(szTemp, SIZEOF(szTemp), "%s ", Log_SetStyle(index, index)); + } + break; + } + + if ( szTemp[0] ) { + int iLen = lstrlenA(szTemp); + memcpy( d, szTemp, iLen ); + d += iLen; + } + } + else if (*line == '\t' && !streamData->bStripFormat) { + CopyMemory(d, "\\tab ", 5); + d += 5; + } + else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) { + *d++ = '\\'; + *d++ = (char) *line; + } + else if (*line > 0 && *line < 128) { + *d++ = (char) *line; + } + else d += sprintf(d, "\\u%u ?", (WORD)*line); + } + + *cbBufferEnd = (int) (d - *buffer); + return textCharsCount; +} + +static void AddEventToBuffer(char **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData) +{ + TCHAR szTemp[512], szTemp2[512]; + TCHAR* pszNick = NULL; + if ( streamData->lin->ptszNick ) { + if ( g_Settings.LogLimitNames && lstrlen( streamData->lin->ptszNick ) > 20 ) { + lstrcpyn( szTemp2, streamData->lin->ptszNick, 20 ); + lstrcpyn( szTemp2+20, _T("..."), 4); + } + else lstrcpyn( szTemp2, streamData->lin->ptszNick, 511 ); + + if ( streamData->lin->ptszUserInfo ) + mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, streamData->lin->ptszUserInfo ); + else + mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%s"), szTemp2 ); + pszNick = szTemp; + } + + if ( streamData && streamData->lin ) { + switch ( streamData->lin->iType ) { + case GC_EVENT_MESSAGE: + if ( streamData->lin->ptszText ) + Log_AppendRTF( streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText ); + break; + case GC_EVENT_ACTION: + if ( streamData->lin->ptszNick && streamData->lin->ptszText) { + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), streamData->lin->ptszNick); + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText); + } + break; + case GC_EVENT_JOIN: + if (pszNick) { + if (!streamData->lin->bIsMe) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has joined"), pszNick); + else + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, TranslateT("You have joined %s"), streamData->si->ptszName); + } + break; + case GC_EVENT_PART: + if (pszNick) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has left"), pszNick); + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText); + break; + case GC_EVENT_QUIT: + if (pszNick) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has disconnected"), pszNick); + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText); + break; + case GC_EVENT_NICK: + if (pszNick && streamData->lin->ptszText) { + if (!streamData->lin->bIsMe) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText); + else + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You are now known as %s"), streamData->lin->ptszText); + } + break; + case GC_EVENT_KICK: + if (streamData->lin->ptszNick && streamData->lin->ptszStatus) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s kicked %s"), streamData->lin->ptszStatus, streamData->lin->ptszNick); + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText); + break; + case GC_EVENT_NOTICE: + if (pszNick && streamData->lin->ptszText) { + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("Notice from %s: "), pszNick ); + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText); + } + break; + case GC_EVENT_TOPIC: + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, TranslateT("The topic is \'%s%s\'"), streamData->lin->ptszText, _T("%r")); + if (streamData->lin->ptszNick) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, + streamData->lin->ptszUserInfo ? TranslateT(" (set by %s on %s)"): TranslateT(" (set by %s)"), + streamData->lin->ptszNick, streamData->lin->ptszUserInfo); + break; + case GC_EVENT_INFORMATION: + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, (streamData->lin->bIsMe) ? _T("--> %s") : _T("%s"), streamData->lin->ptszText); + break; + case GC_EVENT_ADDSTATUS: + if (streamData->lin->ptszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s enables \'%s\' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + if (streamData->lin->ptszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) + Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s disables \'%s\' status for %s"), streamData->lin->ptszText , streamData->lin->ptszStatus, streamData->lin->ptszNick); + break; +} } } + +TCHAR* MakeTimeStamp( TCHAR* pszStamp, time_t time) +{ + static TCHAR szTime[30]; + _tcsftime(szTime, 29, pszStamp, localtime(&time)); + return szTime; +} + +static char* Log_CreateRTF(LOGSTREAMDATA *streamData) +{ + char *buffer, *header; + int bufferAlloced, bufferEnd, i, me = 0; + LOGINFO * lin = streamData->lin; + MODULEINFO *mi = MM_FindModule(streamData->si->pszModule); + + // guesstimate amount of memory for the RTF + bufferEnd = 0; + bufferAlloced = streamData->bRedraw ? 1024 * (streamData->si->iEventCount+2) : 2048; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + + // ### RTF HEADER + header = mi->pszHeader; + + if (header) + Log_Append(&buffer, &bufferEnd, &bufferAlloced, header); + + + // ### RTF BODY (one iteration per event that should be streamed in) + while ( lin ) + { + // filter + if (streamData->si->iType != GCW_CHATROOM || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags&lin->iType) != 0) + { + // create new line, and set font and color + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\par%s ", Log_SetStyle(0, 0)); + + // Insert icon + if (lin->iType&g_Settings.dwIconFlags || lin->bIsHighlighted&&g_Settings.dwIconFlags&GC_EVENT_HIGHLIGHT) + { + int iIndex = (lin->bIsHighlighted&&g_Settings.dwIconFlags&GC_EVENT_HIGHLIGHT) ? ICON_HIGHLIGHT : EventToIcon(lin); + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14"); + while (bufferAlloced - bufferEnd < logIconBmpSize[0]) + bufferAlloced += 4096; + buffer = (char *) mir_realloc(buffer, bufferAlloced); + CopyMemory(buffer + bufferEnd, pLogIconBmpBits[iIndex], logIconBmpSize[iIndex]); + bufferEnd += logIconBmpSize[iIndex]; + } + + if (g_Settings.TimeStampEventColour) + { + // colored timestamps + static char szStyle[256]; + int iii; + if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) + { + iii = lin->bIsHighlighted?16:(lin->bIsMe ? 2 : 1); + mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii+1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic, 2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY); + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle); + } + else + { + iii = lin->bIsHighlighted?16:EventToIndex(lin); + mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii+1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic, 2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY); + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle); + } + } + else + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(0, 0 )); + // insert a TAB if necessary to put the timestamp in the right position + if (g_Settings.dwIconFlags) + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab "); + + //insert timestamp + if (g_Settings.ShowTime) + { + TCHAR szTimeStamp[30], szOldTimeStamp[30]; + + lstrcpyn( szTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), 30); + lstrcpyn( szOldTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), 30); + if ( !g_Settings.ShowTimeIfChanged || streamData->si->LastTime == 0 || lstrcmp(szTimeStamp, szOldTimeStamp )) { + streamData->si->LastTime = lin->time; + Log_AppendRTF( streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, _T("%s"), szTimeStamp ); + } + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab "); + } + + // Insert the nick + if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) + { + TCHAR pszTemp[300], *p1; + + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(lin->bIsMe ? 2 : 1, lin->bIsMe ? 2 : 1)); + lstrcpyn(pszTemp, lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick, 299); + p1 = _tcsstr(pszTemp, _T("%n")); + if (p1) + p1[1] = 's'; + + Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, pszTemp, lin->ptszNick); + Log_Append(&buffer, &bufferEnd, &bufferAlloced, " "); + } + + // Insert the message + { + i = lin->bIsHighlighted?16:EventToIndex(lin); + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(i, i)); + streamData->lin = lin; + AddEventToBuffer(&buffer, &bufferEnd, &bufferAlloced, streamData); + } + + } + lin = lin->prev; + } + + // ### RTF END + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}"); + return buffer; +} + +static DWORD CALLBACK Log_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + LOGSTREAMDATA *lstrdat = (LOGSTREAMDATA *) dwCookie; + + if (lstrdat) + { + // create the RTF + if (lstrdat->buffer == NULL) + { + lstrdat->bufferOffset = 0; + lstrdat->buffer = Log_CreateRTF(lstrdat); + lstrdat->bufferLen = lstrlenA(lstrdat->buffer); + } + + // give the RTF to the RE control + *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset); + CopyMemory(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb); + lstrdat->bufferOffset += *pcb; + + // free stuff if the streaming operation is complete + if (lstrdat->bufferOffset == lstrdat->bufferLen) + { + mir_free(lstrdat->buffer); + lstrdat->buffer = NULL; + } + } + + return 0; +} + +void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO* si, BOOL bRedraw, BOOL bPhaseTwo) +{ + EDITSTREAM stream; + LOGSTREAMDATA streamData; + CHARRANGE oldsel, sel, newsel; + POINT point ={0}; + SCROLLINFO scroll; + WPARAM wp; + HWND hwndRich; + + if (hwndDlg == 0 || lin == 0 || si == 0) + return; + + hwndRich = GetDlgItem(hwndDlg, IDC_LOG); + ZeroMemory(&streamData, sizeof(LOGSTREAMDATA)); + streamData.hwnd = hwndRich; + streamData.si = si; + streamData.lin = lin; + streamData.bStripFormat = FALSE; + + // bPhaseTwo = bRedraw && bPhaseTwo; + + if (bRedraw || si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&lin->iType) != 0) + { + BOOL bFlag = FALSE; + + ZeroMemory(&stream, sizeof(stream)); + stream.pfnCallback = Log_StreamCallback; + stream.dwCookie = (DWORD_PTR) & streamData; + scroll.cbSize= sizeof(SCROLLINFO); + scroll.fMask= SIF_RANGE | SIF_POS|SIF_PAGE; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &scroll); + SendMessage(hwndRich, EM_GETSCROLLPOS, 0, (LPARAM) &point); + + // do not scroll to bottom if there is a selection + SendMessage(hwndRich, EM_EXGETSEL, 0, (LPARAM) &oldsel); + if (oldsel.cpMax != oldsel.cpMin) + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + + //set the insertion point at the bottom + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & sel); + + // fix for the indent... must be a M$ bug + if (sel.cpMax == 0) + bRedraw = TRUE; + + // should the event(s) be appended to the current log + wp = bRedraw?SF_RTF:SFF_SELECTION|SF_RTF; + + //get the number of pixels per logical inch + if (bRedraw) + { + HDC hdc; + hdc = GetDC(NULL); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC (NULL, hdc); + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + bFlag = TRUE; + // SetCursor(LoadCursor(NULL, IDC_ARROW)); + } + + // stream in the event(s) + streamData.lin = lin; + streamData.bRedraw = bRedraw; + SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM) & stream); + + // do smileys + if (SmileyAddInstalled && (bRedraw + || (lin->ptszText + && lin->iType != GC_EVENT_JOIN + && lin->iType != GC_EVENT_NICK + && lin->iType != GC_EVENT_ADDSTATUS + && lin->iType != GC_EVENT_REMOVESTATUS ))) + { + SMADD_RICHEDIT3 sm = {0}; + + newsel.cpMax = -1; + newsel.cpMin = sel.cpMin; + if (newsel.cpMin < 0) + newsel.cpMin = 0; + ZeroMemory(&sm, sizeof(sm)); + sm.cbSize = sizeof(sm); + sm.hwndRichEditControl = hwndRich; + sm.Protocolname = si->pszModule; + sm.rangeToReplace = bRedraw?NULL:&newsel; + sm.disableRedraw = TRUE; + sm.hContact = si->hContact; + CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm); + } + + // scroll log to bottom if the log was previously scrolled to bottom, else restore old position + if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax-scroll.nPage-5 || scroll.nMax-scroll.nMin-scroll.nPage < 50) + { + SendMessage(GetParent(hwndRich), GC_SCROLLTOBOTTOM, 0, 0); + } + else + SendMessage(hwndRich, EM_SETSCROLLPOS, 0, (LPARAM) &point); + + // do we need to restore the selection + if (oldsel.cpMax != oldsel.cpMin) + { + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & oldsel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); + } + + // need to invalidate the window + if (bFlag) + { + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & sel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); +} } } + +char * Log_CreateRtfHeader(MODULEINFO * mi) +{ + char *buffer; + int bufferAlloced, bufferEnd, i = 0; + + // guesstimate amount of memory for the RTF header + bufferEnd = 0; + bufferAlloced = 4096; + buffer = (char *) mir_realloc(mi->pszHeader, bufferAlloced); + buffer[0] = '\0'; + + + //get the number of pixels per logical inch + { + HDC hdc; + hdc = GetDC(NULL); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + } + + // ### RTF HEADER + + // font table + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl"); + for (i = 0; i < OPTIONS_FONTCOUNT; i++) + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\f%u\\fnil\\fcharset%u" TCHAR_STR_PARAM ";}", i, aFonts[i].lf.lfCharSet, aFonts[i].lf.lfFaceName); + + // colour table + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl ;"); + + for (i = 0; i < OPTIONS_FONTCOUNT; i++) + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(aFonts[i].color), GetGValue(aFonts[i].color), GetBValue(aFonts[i].color)); + + for(i = 0; i < mi->nColorCount; i++) + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i])); + + // new paragraph + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}\\pard"); + + // set tabs and indents + { + int iIndent = 0; + + if (g_Settings.dwIconFlags) + { + iIndent += (14*1440)/logPixelSX; + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent); + } + if (g_Settings.ShowTime) + { + int iSize = (g_Settings.LogTextIndent*1440)/logPixelSX; + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent + iSize ); + if (g_Settings.LogIndentEnabled) + iIndent += iSize; + } + /* + { // text indent + int iSize = (135*1440)/logPixelSX; + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent + iSize ); + if (g_Settings.LogIndentEnabled) + iIndent += iSize; + + } + */ + Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\fi-%u\\li%u", iIndent, iIndent); + } + return buffer; +} + +#define RTFPICTHEADERMAXSIZE 78 +void LoadMsgLogBitmaps(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, "Chat", "ColorLogBG", GetSysColor(COLOR_WINDOW))); + bih.biSize = sizeof(bih); + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biHeight = 10; //GetSystemMetrics(SM_CYSMICON); + bih.biPlanes = 1; + bih.biWidth = 10; //GetSystemMetrics(SM_CXSMICON); + 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 = hIcons[i]; + pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2); + rtfHeaderSize = sprintf((char *)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); + 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((char *)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]); + for (n = 0; n < widthBytes * bih.biHeight; n += 4) + sprintf((char *)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 FreeMsgLogBitmaps(void) +{ + int i; + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) + mir_free(pLogIconBmpBits[i]); +} diff --git a/src/core/stdchat/src/main.cpp b/src/core/stdchat/src/main.cpp new file mode 100644 index 0000000000..e9927f4442 --- /dev/null +++ b/src/core/stdchat/src/main.cpp @@ -0,0 +1,288 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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 "chat.h" + +//globals +HINSTANCE g_hInst; +HANDLE g_hWindowList; +HMENU g_hMenu = NULL; +int hLangpack; + +FONTINFO aFonts[OPTIONS_FONTCOUNT]; +HICON hIcons[30]; +BOOL IEviewInstalled = FALSE; +HBRUSH hListBkgBrush = NULL; +BOOL SmileyAddInstalled = FALSE; +BOOL PopUpInstalled = FALSE; +HBRUSH hEditBkgBrush = NULL; +HBRUSH hListSelectedBkgBrush = NULL; + +HIMAGELIST hImageList = NULL; + +HIMAGELIST hIconsList = NULL; + +TCHAR* pszActiveWndID = 0; +char* pszActiveWndModule = 0; + +/* 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 + +struct GlobalLogSettings_t g_Settings; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + MIRANDA_VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + {0x9d6c3213, 0x2b4, 0x4fe1, { 0x92, 0xe6, 0x52, 0x6d, 0xe2, 0x4f, 0x8d, 0x65 }} //{9D6C3213-02B4-4fe1-92E6-526DE24F8D65} +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + g_hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_CHAT, MIID_LAST}; + +extern "C" __declspec(dllexport) int Load(void) +{ + // set the memory & utf8 managers + mir_getLP( &pluginInfo ); + + UpgradeCheck(); + + g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU)); + HookEvents(); + CreateServiceFunctions(); + CreateHookableEvents(); + OptionsInit(); + TabsInit(); + return 0; +} + +extern "C" __declspec(dllexport) int Unload(void) +{ + DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX); + DBWriteContactSettingWord(NULL, "Chat", "SplitterY", (WORD)g_Settings.iSplitterY); + DBWriteContactSettingDword(NULL, "Chat", "roomx", g_Settings.iX); + DBWriteContactSettingDword(NULL, "Chat", "roomy", g_Settings.iY); + DBWriteContactSettingDword(NULL, "Chat", "roomwidth" , g_Settings.iWidth); + DBWriteContactSettingDword(NULL, "Chat", "roomheight", g_Settings.iHeight); + + CList_SetAllOffline(TRUE, NULL); + + mir_free( pszActiveWndID ); + mir_free( pszActiveWndModule ); + + DestroyMenu(g_hMenu); + DestroyServiceFunctions(); + DestroyHookableEvents(); + FreeIcons(); + OptionsUnInit(); + FreeLibrary(GetModuleHandle(_T("riched20.dll"))); + UnhookEvents(); + return 0; +} + +void UpgradeCheck(void) +{ + DWORD dwVersion = DBGetContactSettingDword(NULL, "Chat", "OldVersion", PLUGIN_MAKE_VERSION(0,2,9,9)); + if ( pluginInfo.version > dwVersion) + { + if (dwVersion < PLUGIN_MAKE_VERSION(0,3,0,0)) + { + DBDeleteContactSetting(NULL, "ChatFonts", "Font18"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font18Col"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font18Set"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font18Size"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font18Sty"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font19"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font19Col"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font19Set"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font19Size"); + DBDeleteContactSetting(NULL, "ChatFonts", "Font19Sty"); + DBDeleteContactSetting(NULL, "Chat", "ColorNicklistLines"); + DBDeleteContactSetting(NULL, "Chat", "NicklistIndent"); + DBDeleteContactSetting(NULL, "Chat", "NicklistRowDist"); + DBDeleteContactSetting(NULL, "Chat", "ShowFormatButtons"); + DBDeleteContactSetting(NULL, "Chat", "ShowLines"); + DBDeleteContactSetting(NULL, "Chat", "ShowName"); + DBDeleteContactSetting(NULL, "Chat", "ShowTopButtons"); + DBDeleteContactSetting(NULL, "Chat", "SplitterX"); + DBDeleteContactSetting(NULL, "Chat", "SplitterY"); + DBDeleteContactSetting(NULL, "Chat", "IconFlags"); + DBDeleteContactSetting(NULL, "Chat", "LogIndentEnabled"); + } } + + DBWriteContactSettingDword(NULL, "Chat", "OldVersion", pluginInfo.version); +} + +void LoadLogIcons(void) +{ + hIcons[ICON_ACTION] = LoadIconEx( "log_action", FALSE ); + hIcons[ICON_ADDSTATUS] = LoadIconEx( "log_addstatus", FALSE ); + hIcons[ICON_HIGHLIGHT] = LoadIconEx( "log_highlight", FALSE ); + hIcons[ICON_INFO] = LoadIconEx( "log_info", FALSE ); + hIcons[ICON_JOIN] = LoadIconEx( "log_join", FALSE ); + hIcons[ICON_KICK] = LoadIconEx( "log_kick", FALSE ); + hIcons[ICON_MESSAGE] = LoadIconEx( "log_message_in", FALSE ); + hIcons[ICON_MESSAGEOUT] = LoadIconEx( "log_message_out", FALSE ); + hIcons[ICON_NICK] = LoadIconEx( "log_nick", FALSE ); + hIcons[ICON_NOTICE] = LoadIconEx( "log_notice", FALSE ); + hIcons[ICON_PART] = LoadIconEx( "log_part", FALSE ); + hIcons[ICON_QUIT] = LoadIconEx( "log_quit", FALSE ); + hIcons[ICON_REMSTATUS] = LoadIconEx( "log_removestatus", FALSE ); + hIcons[ICON_TOPIC] = LoadIconEx( "log_topic", FALSE ); + hIcons[ICON_STATUS1] = LoadIconEx( "status1", FALSE ); + hIcons[ICON_STATUS2] = LoadIconEx( "status2", FALSE ); + hIcons[ICON_STATUS3] = LoadIconEx( "status3", FALSE ); + hIcons[ICON_STATUS4] = LoadIconEx( "status4", FALSE ); + hIcons[ICON_STATUS0] = LoadIconEx( "status0", FALSE ); + hIcons[ICON_STATUS5] = LoadIconEx( "status5", FALSE ); +} + +void LoadIcons(void) +{ + int i; + + for(i = 0; i < 20; i++) + hIcons[i] = NULL; + + LoadLogIcons(); + LoadMsgLogBitmaps(); + + hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK,0,3); + hIconsList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK,0,100); + ImageList_AddIcon(hIconsList,LoadSkinnedIcon( SKINICON_EVENT_MESSAGE)); + ImageList_AddIcon(hIconsList,LoadIconEx( "overlay", FALSE )); + ImageList_SetOverlayImage(hIconsList, 1, 1); + ImageList_AddIcon(hImageList, (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 0, 0, 0)); + ImageList_AddIcon(hImageList, (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 0, 0, 0)); +} + +void FreeIcons(void) +{ + FreeMsgLogBitmaps(); + ImageList_Destroy(hImageList); + ImageList_Destroy(hIconsList); +} + +CREOleCallback reOleCallback; + +STDMETHODIMP CREOleCallback::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if (IsEqualIID(riid, IID_IRichEditOleCallback)) { + *ppvObj = this; + AddRef(); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CREOleCallback::AddRef() +{ + if (refCount == 0) { + if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &pictStg)) + pictStg = NULL; + nextStgId = 0; + } + return ++refCount; +} + +STDMETHODIMP_(ULONG) CREOleCallback::Release() +{ + if (--refCount == 0) { + if (pictStg) + pictStg->Release(); + } + return refCount; +} + +STDMETHODIMP CREOleCallback::ContextSensitiveHelp(BOOL fEnterMode) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::DeleteObject(LPOLEOBJECT lpoleobj) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetClipboardData(CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CREOleCallback::GetContextMenu(WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetInPlaceContext(LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetNewStorage(LPSTORAGE * lplpstg) +{ + WCHAR szwName[64]; + char szName[64]; + wsprintfA(szName, "s%u", nextStgId++); + MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName)); + if (pictStg == NULL) + return STG_E_MEDIUMFULL; + return pictStg->CreateStorage(szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg); +} + +STDMETHODIMP CREOleCallback::QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::ShowContainerUI(BOOL fShow) +{ + return S_OK; +} \ No newline at end of file diff --git a/src/core/stdchat/src/manager.cpp b/src/core/stdchat/src/manager.cpp new file mode 100644 index 0000000000..02a0f76a59 --- /dev/null +++ b/src/core/stdchat/src/manager.cpp @@ -0,0 +1,1611 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-2010 Miranda ICQ/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 "chat.h" + +extern TCHAR* pszActiveWndID ; +extern char* pszActiveWndModule ; +extern SESSION_INFO g_TabSession; +extern HICON hIcons[30]; +extern HIMAGELIST hIconsList; + +#define WINDOWS_COMMANDS_MAX 30 +#define STATUSICONCOUNT 6 + +SESSION_INFO* m_WndList = 0; +TABLIST * g_TabList = 0; +MODULEINFO *m_ModList = 0; + +void SetActiveSession(const TCHAR* pszID, const char* pszModule) +{ + SESSION_INFO* si = SM_FindSession(pszID, pszModule); + if ( si ) + SetActiveSessionEx(si); +} + +void SetActiveSessionEx(SESSION_INFO* si) +{ + if ( si ) { + replaceStr( &pszActiveWndID, si->ptszID ); + replaceStrA( &pszActiveWndModule, si->pszModule ); +} } + +SESSION_INFO* GetActiveSession( void ) +{ + SESSION_INFO* si = SM_FindSession( pszActiveWndID, pszActiveWndModule ); + if ( si ) + return si; + + return m_WndList; +} + +//--------------------------------------------------- +// Session Manager functions +// +// Keeps track of all sessions and its windows +//--------------------------------------------------- + +SESSION_INFO* SM_AddSession( const TCHAR* pszID, const char* pszModule) +{ + if ( !pszID || !pszModule ) + return NULL; + + if ( !SM_FindSession(pszID, pszModule)) { + SESSION_INFO*node = (SESSION_INFO*) mir_alloc(sizeof(SESSION_INFO)); + ZeroMemory(node, sizeof(SESSION_INFO)); + node->ptszID = mir_tstrdup( pszID ); + node->pszModule = mir_strdup( pszModule ); + + if (m_WndList == NULL) { // list is empty + m_WndList = node; + node->next = NULL; + } + else { + node->next = m_WndList; + m_WndList = node; + } + return node; + } + return NULL; +} + +int SM_RemoveSession(const TCHAR* pszID, const char* pszModule, BOOL removeContact) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while (pTemp != NULL) + { + if ((!pszID && pTemp->iType != GCW_SERVER || !lstrcmpi(pTemp->ptszID,pszID)) && !lstrcmpiA(pTemp->pszModule,pszModule)) // match + { + COMMAND_INFO *pCurComm; + DWORD dw = pTemp->dwItemData; + + if (!g_Settings.TabsEnable) + { + if (pTemp->hWnd ) + SendMessage(pTemp->hWnd, GC_EVENT_CONTROL+WM_USER+500, SESSION_TERMINATE, 0); + } + else + { + if (g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_REMOVETAB, 1, (LPARAM)pTemp); + } + + if (pTemp->hWnd) + g_TabSession.nUsersInNicklist = 0; + + DoEventHook(pTemp->ptszID, pTemp->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)pTemp->dwItemData); + + if (pLast == NULL) + m_WndList = pTemp->next; + else + pLast->next = pTemp->next; + + UM_RemoveAll(&pTemp->pUsers); + TM_RemoveAll(&pTemp->pStatuses); + LM_RemoveAll(&pTemp->pLog, &pTemp->pLogEnd); + pTemp->iStatusCount = 0; + pTemp->nUsersInNicklist = 0; + + // contact may have been deleted here already, since function may be called after deleting + // contact so the handle may be invalid, therefore DBGetContactSettingByte shall return 0 + if (pTemp->hContact && DBGetContactSettingByte( pTemp->hContact, pTemp->pszModule, "ChatRoom", 0 ) != 0) + { + CList_SetOffline(pTemp->hContact, pTemp->iType == GCW_CHATROOM?TRUE:FALSE); +/* if (pTemp->iType != GCW_SERVER) + DBWriteContactSettingByte(pTemp->hContact, "CList", "Hidden", 1);*/ + DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule, "Topic", ""); + DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule, "StatusBar", ""); + DBDeleteContactSetting(pTemp->hContact, "CList", "StatusMsg"); + + if (removeContact) + CallService(MS_DB_CONTACT_DELETE, (WPARAM)pTemp->hContact, 0); + } + + mir_free( pTemp->pszModule ); + mir_free( pTemp->ptszID ); + mir_free( pTemp->ptszName ); + mir_free( pTemp->ptszStatusbarText ); + mir_free( pTemp->ptszTopic ); + mir_free( pTemp->pszID ); + mir_free( pTemp->pszName ); + + // delete commands + pCurComm = pTemp->lpCommands; + while (pCurComm != NULL) + { + COMMAND_INFO *pNext = pCurComm->next; + mir_free(pCurComm->lpCommand); + mir_free(pCurComm); + pCurComm = pNext; + } + + mir_free(pTemp); + if (pszID) + return (int)dw; + if (pLast) + pTemp = pLast->next; + else + pTemp = m_WndList; + } + else + { + pLast = pTemp; + pTemp = pTemp->next; + } + } + return FALSE; +} + +SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if ( !pszID || !pszModule ) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA(pTemp->pszModule,pszModule)) + return pTemp; + + pLast = pTemp; + pTemp = pTemp->next; + } + return NULL; +} + +BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while (pTemp != NULL) + { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA(pTemp->pszModule,pszModule)) + { + UM_RemoveAll(&pTemp->pUsers); + pTemp->nUsersInNicklist = 0; + if (pTemp->hWnd) + g_TabSession.nUsersInNicklist = 0; + if (pTemp->iType != GCW_SERVER) + pTemp->bInitDone = FALSE; + if (g_Settings.TabsEnable && pTemp->hWnd) + g_TabSession.pUsers = 0; + + if (pszID) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +BOOL SM_SetStatusEx( const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags ) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA(pTemp->pszModule,pszModule)) { + UM_SetStatusEx(pTemp->pUsers, pszText, flags); + if (pTemp->hWnd) + RedrawWindow(GetDlgItem(pTemp->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + if (pszID) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO * ui) +{ + STATUSINFO * ti; + if (!ui || !si) + return NULL; + + ti = TM_FindStatus(si->pStatuses, TM_WordToString(si->pStatuses, ui->Status)); + if (ti) + { + if ((int)ti->hIcon < STATUSICONCOUNT) + { + int id = si->iStatusCount - (int)ti->hIcon - 1; + if (id == 0) + return hIcons[ICON_STATUS0]; + if (id == 1) + return hIcons[ICON_STATUS1]; + if (id == 2) + return hIcons[ICON_STATUS2]; + if (id == 3) + return hIcons[ICON_STATUS3]; + if (id == 4) + return hIcons[ICON_STATUS4]; + if (id == 5) + return hIcons[ICON_STATUS5]; + } + else + return ti->hIcon; + } + return hIcons[ICON_STATUS0]; +} + +BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + int bManyFix = 0; + + while (pTemp != NULL) { + if ( !lstrcmpiA( pTemp->pszModule, gce->pDest->pszModule )) { + if ( UM_FindUser( pTemp->pUsers, gce->ptszUID )) { + if ( pTemp->bInitDone ) { + if ( SM_AddEvent(pTemp->ptszID, pTemp->pszModule, gce, FALSE ) && pTemp->hWnd && pTemp->bInitDone) { + g_TabSession.pLog = pTemp->pLog; + g_TabSession.pLogEnd = pTemp->pLogEnd; + SendMessage(pTemp->hWnd, GC_ADDLOG, 0, 0); + } + else if (pTemp->hWnd && pTemp->bInitDone) { + g_TabSession.pLog = pTemp->pLog; + g_TabSession.pLogEnd = pTemp->pLogEnd; + SendMessage(pTemp->hWnd, GC_REDRAWLOG2, 0, 0); + } + DoSoundsFlashPopupTrayStuff(pTemp, gce, FALSE, bManyFix); + bManyFix ++; + if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled) + LogToFile(pTemp, gce); + } } } + + pLast = pTemp; + pTemp = pTemp->next; + } + + return 0; +} + +BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszID || !pszModule) + return TRUE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA(pTemp->pszModule,pszModule)) { + LOGINFO * li = LM_AddEvent(&pTemp->pLog, &pTemp->pLogEnd); + pTemp->iEventCount += 1; + + li->iType = gce->pDest->iType; + li->ptszNick = mir_tstrdup( gce->ptszNick ); + li->ptszText = mir_tstrdup( gce->ptszText ); + li->ptszStatus = mir_tstrdup( gce->ptszStatus ); + li->ptszUserInfo = mir_tstrdup( gce->ptszUserInfo ); + + li->bIsMe = gce->bIsMe; + li->time = gce->time; + li->bIsHighlighted = bIsHighlighted; + + if (g_Settings.iEventLimit > 0 && pTemp->iEventCount > g_Settings.iEventLimit + 20) { + LM_TrimLog(&pTemp->pLog, &pTemp->pLogEnd, pTemp->iEventCount - g_Settings.iEventLimit); + pTemp->iEventCount = g_Settings.iEventLimit; + return FALSE; + } + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +USERINFO * SM_AddUser( const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszID || !pszModule) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO * p = UM_AddUser( pTemp->pStatuses, &pTemp->pUsers, pszUID, pszNick, wStatus); + pTemp->nUsersInNicklist++; + if (pTemp->hWnd) + g_TabSession.nUsersInNicklist ++; + return p; + } + pLast = pTemp; + pTemp = pTemp->next; + } + + return 0; +} + +BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID) +{ + SESSION_INFO *pTemp = m_WndList; + + if (!pszID || !pszModule || !pszUID) + return FALSE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + UM_SortUser( &pTemp->pUsers, pszUID ); + return TRUE; + } + pTemp = pTemp->next; + } + + return FALSE; +} + +BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule || !pszUID) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + DWORD dw; + USERINFO * ui = UM_FindUser(pTemp->pUsers, pszUID); + if ( ui ) { + pTemp->nUsersInNicklist--; + if (pTemp->hWnd) { + g_TabSession.pUsers = pTemp->pUsers; + g_TabSession.nUsersInNicklist --; + } + + dw = UM_RemoveUser(&pTemp->pUsers, pszUID); + + if (pTemp->hWnd) + SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); + + if (pszID) + return TRUE; + } } + + pLast = pTemp; + pTemp = pTemp->next; + } + + return 0; +} + +USERINFO * SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index) +{ + SESSION_INFO *pTemp = m_WndList; + + if (!pszModule) + return FALSE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) + return UM_FindUserFromIndex( pTemp->pUsers, index ); + pTemp = pTemp->next; + } + + return NULL; +} + + +STATUSINFO * SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszID || !pszModule ) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + STATUSINFO* ti = TM_AddStatus( &pTemp->pStatuses, pszStatus, &pTemp->iStatusCount ); + if ( ti ) + pTemp->iStatusCount++; + if ( g_Settings.TabsEnable && pTemp->hWnd ) + g_TabSession.pStatuses = pTemp->pStatuses; + return ti; + } + pLast = pTemp; + pTemp = pTemp->next; + } + + return 0; +} + +BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if ( !pszID || !pszModule ) + return FALSE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO * ui = UM_GiveStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus)); + if (ui) { + SM_MoveUser( pTemp->ptszID, pTemp->pszModule, ui->pszUID ); + if ( pTemp->hWnd ) + SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); + } + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + + return FALSE; +} + +BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD wStatus) +{ + SESSION_INFO* pTemp = m_WndList, *pLast = NULL; + + if ( !pszID || !pszModule ) + return FALSE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO * ui = UM_SetContactStatus(pTemp->pUsers, pszUID, wStatus); + if (ui) { + SM_MoveUser( pTemp->ptszID, pTemp->pszModule, ui->pszUID ); + if ( pTemp->hWnd ) + SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); + } + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + + return FALSE; +} + +BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszID || !pszModule ) + return FALSE; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO* ui = UM_TakeStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus)); + if ( ui ) { + SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID); + if ( pTemp->hWnd ) + SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); + } + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + + return FALSE; +} +LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + while ( pTemp && pszModule ) { + if (( !pszID ||!lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + if ( pTemp->hWnd ) { + LRESULT i = SendMessage(pTemp->hWnd, msg, wParam, lParam); + if ( pszID ) + return i; + } + if ( pszID ) + return 0; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszID || !pszModule) + return 0; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + if ( pTemp->hWnd ) + return PostMessage(pTemp->hWnd, msg, wParam, lParam); + + return FALSE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return FALSE; +} + +BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + while (pTemp != NULL) + { + if (!pszModule || !lstrcmpiA(pTemp->pszModule, pszModule)) + { + if (pTemp->hWnd) + { + if (bAsync) + PostMessage(pTemp->hWnd, msg, wParam, lParam); + else + SendMessage(pTemp->hWnd, msg, wParam, lParam); + } + + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + pTemp->wStatus = wStatus; + if (pTemp->hWnd && g_Settings.TabsEnable) + g_TabSession.wStatus = wStatus; + + if ( pTemp->hContact ) { + if ( pTemp->iType != GCW_SERVER && wStatus != ID_STATUS_OFFLINE ) + DBDeleteContactSetting(pTemp->hContact, "CList", "Hidden"); + + DBWriteContactSettingWord(pTemp->hContact, pTemp->pszModule, "Status", (WORD)wStatus); + } + + if ( g_Settings.TabsEnable && g_TabSession.hWnd ) + PostMessage( g_TabSession.hWnd, GC_FIXTABICONS, 0, (LPARAM) pTemp ); + + if (pszID) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if ( !pszModule || !pszText ) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + if ( pTemp->iType == GCW_CHATROOM ) + DoEventHook( pTemp->ptszID, pTemp->pszModule, GC_USER_MESSAGE, NULL, pszText, (LPARAM)NULL); + if (pszID) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +SESSION_INFO* SM_GetPrevWindow(SESSION_INFO* si) +{ + BOOL bFound = FALSE; + SESSION_INFO* pTemp = m_WndList; + + if ( !si ) + return NULL; + + while (pTemp != NULL) + { + if (si == pTemp) + { + if (bFound) + return NULL; + else + bFound = TRUE; + } + else if (bFound == TRUE && pTemp->hWnd) + return pTemp; + pTemp = pTemp->next; + if (pTemp == NULL && bFound) + pTemp = m_WndList; + } + return NULL; +} + +SESSION_INFO* SM_GetNextWindow(SESSION_INFO* si) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!si) + return NULL; + + while (pTemp != NULL) + { + if (si == pTemp) + { + if (pLast) + { + if (pLast != pTemp) + return pLast; + else + return NULL; + } + } + if (pTemp->hWnd) + pLast = pTemp; + pTemp = pTemp->next; + if (pTemp == NULL) + pTemp = m_WndList; + } + return NULL; +} + +BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO* ui = UM_FindUser( pTemp->pUsers, pszUID ); + if ( ui ) + replaceStr( &ui->pszUID, pszNewUID ); + + if ( pszID ) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + + +BOOL SM_SetTabbedWindowHwnd(SESSION_INFO* si, HWND hwnd) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + while (pTemp != NULL) + { + if (si && si == pTemp) + { + pTemp->hWnd = hwnd; + } + else + pTemp->hWnd = NULL; + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} +BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce) +{ + SESSION_INFO *pTemp = m_WndList, *pLast = NULL; + + if (!pszModule) + return FALSE; + + while ( pTemp != NULL ) { + if (( !pszID || !lstrcmpi( pTemp->ptszID, pszID )) && !lstrcmpiA( pTemp->pszModule, pszModule )) { + USERINFO* ui = UM_FindUser(pTemp->pUsers, gce->ptszUID ); + if ( ui ) { + replaceStr( &ui->pszNick, gce->ptszText); + SM_MoveUser( pTemp->ptszID, pTemp->pszModule, ui->pszUID ); + if ( pTemp->hWnd ) + SendMessage( pTemp->hWnd, GC_UPDATENICKLIST, 0, 0 ); + } + + if (pszID) + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} +BOOL SM_RemoveAll (void) +{ + while (m_WndList) + { + SESSION_INFO*pLast = m_WndList->next; + + if (m_WndList->hWnd) + SendMessage(m_WndList->hWnd, GC_EVENT_CONTROL+WM_USER+500, SESSION_TERMINATE, 0); + DoEventHook(m_WndList->ptszID, m_WndList->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)m_WndList->dwItemData); + if (m_WndList->hContact) + CList_SetOffline(m_WndList->hContact, m_WndList->iType == GCW_CHATROOM?TRUE:FALSE); + DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule , "Topic", ""); + DBDeleteContactSetting(m_WndList->hContact, "CList", "StatusMsg"); + DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule, "StatusBar", ""); + + UM_RemoveAll(&m_WndList->pUsers); + TM_RemoveAll(&m_WndList->pStatuses); + LM_RemoveAll(&m_WndList->pLog, &m_WndList->pLogEnd); + m_WndList->iStatusCount = 0; + m_WndList->nUsersInNicklist = 0; + + mir_free( m_WndList->pszModule ); + mir_free( m_WndList->ptszID ); + mir_free( m_WndList->ptszName ); + mir_free( m_WndList->ptszStatusbarText ); + mir_free( m_WndList->ptszTopic ); + mir_free( m_WndList->pszID ); + mir_free( m_WndList->pszName ); + + while (m_WndList->lpCommands != NULL) { + COMMAND_INFO *pNext = m_WndList->lpCommands->next; + mir_free(m_WndList->lpCommands->lpCommand); + mir_free(m_WndList->lpCommands); + m_WndList->lpCommands = pNext; + } + + mir_free(m_WndList); + m_WndList = pLast; + } + m_WndList = NULL; + return TRUE; +} + +void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand) +{ + SESSION_INFO* pTemp = m_WndList; + while ( pTemp != NULL ) { + if ( lstrcmpi( pTemp->ptszID, pszID ) == 0 && lstrcmpiA( pTemp->pszModule, pszModule ) == 0) { // match + COMMAND_INFO *node = (COMMAND_INFO *)mir_alloc(sizeof(COMMAND_INFO)); + node->lpCommand = mir_strdup( lpNewCommand ); + node->last = NULL; // always added at beginning! + + // new commands are added at start + if (pTemp->lpCommands == NULL) { + node->next = NULL; + pTemp->lpCommands = node; + } + else { + node->next = pTemp->lpCommands; + pTemp->lpCommands->last = node; // hmm, weird + pTemp->lpCommands = node; + } + pTemp->lpCurrentCommand = NULL; // current command + pTemp->wCommandsNum++; + + if (pTemp->wCommandsNum > WINDOWS_COMMANDS_MAX) { + COMMAND_INFO *pCurComm = pTemp->lpCommands; + COMMAND_INFO *pLast; + while (pCurComm->next != NULL) { pCurComm = pCurComm->next; } + pLast = pCurComm->last; + mir_free(pCurComm->lpCommand); + mir_free(pCurComm); + pLast->next = NULL; + // done + pTemp->wCommandsNum--; + } } + pTemp = pTemp->next; +} } + +char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule) // get previous command. returns NULL if previous command does not exist. current command remains as it was. +{ + SESSION_INFO* pTemp = m_WndList; + while ( pTemp != NULL ) { + if ( lstrcmpi( pTemp->ptszID, pszID ) == 0 && lstrcmpiA( pTemp->pszModule, pszModule ) == 0) { // match + COMMAND_INFO *pPrevCmd = NULL; + if (pTemp->lpCurrentCommand != NULL) { + if (pTemp->lpCurrentCommand->next != NULL) // not NULL + pPrevCmd = pTemp->lpCurrentCommand->next; // next command (newest at beginning) + else + pPrevCmd = pTemp->lpCurrentCommand; + } + else pPrevCmd = pTemp->lpCommands; + + pTemp->lpCurrentCommand = pPrevCmd; // make it the new command + return(((pPrevCmd) ? (pPrevCmd->lpCommand) : (NULL))); + } + pTemp = pTemp->next; + } + return(NULL); +} + +char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule) // get next command. returns NULL if next command does not exist. current command becomes NULL (a prev command after this one will get you the last command) +{ + SESSION_INFO* pTemp = m_WndList; + while ( pTemp != NULL ) { + if ( lstrcmpi( pTemp->ptszID, pszID ) == 0 && lstrcmpiA( pTemp->pszModule, pszModule ) == 0) { // match + COMMAND_INFO *pNextCmd = NULL; + if (pTemp->lpCurrentCommand != NULL) + pNextCmd = pTemp->lpCurrentCommand->last; // last command (newest at beginning) + + pTemp->lpCurrentCommand = pNextCmd; // make it the new command + return(((pNextCmd) ? (pNextCmd->lpCommand) : (NULL))); + } + pTemp = pTemp->next; + } + return(NULL); +} + +int SM_GetCount(const char* pszModule) +{ + SESSION_INFO* pTemp = m_WndList; + int count = 0; + + while (pTemp != NULL) + { + if (!lstrcmpiA(pszModule, pTemp->pszModule)) + count++; + + pTemp = pTemp->next; + } + return count; +} + +SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem) +{ + SESSION_INFO* pTemp = m_WndList; + int count = 0; + while (pTemp != NULL) + { + if (!lstrcmpiA(pszModule, pTemp->pszModule)) + { + if (iItem ==count) + return pTemp; + else + count++; + } + + pTemp = pTemp->next; + } + return NULL; + +} + +char* SM_GetUsers(SESSION_INFO* si) +{ + SESSION_INFO* pTemp = m_WndList; + USERINFO* utemp = NULL; + char* p = NULL; + int alloced = 0; + + if ( si == NULL ) + return NULL; + + while (pTemp != NULL) { + if ( si == pTemp ) { + if (( utemp = pTemp->pUsers ) == NULL ) + return NULL; + + break; + } + pTemp = pTemp->next; + } + + do { + int pLen = lstrlenA(p), nameLen = lstrlen(utemp->pszUID); + if ( pLen + nameLen + 2 > alloced ) + p = (char *)mir_realloc( p, alloced += 4096 ); + + WideCharToMultiByte( CP_ACP, 0, utemp->pszUID, -1, p + pLen, nameLen+1, 0, 0 ); + lstrcpyA( p + pLen + nameLen, " " ); + utemp = utemp->next; + } + while ( utemp != NULL ); + return p; +} + + + + + + +//--------------------------------------------------- +// Module Manager functions +// +// Necessary to keep track of all modules +// that has registered with the plugin +//--------------------------------------------------- + +MODULEINFO* MM_AddModule(const char* pszModule) +{ + if (!pszModule) + return NULL; + if (!MM_FindModule(pszModule)) + { + MODULEINFO *node = (MODULEINFO*) mir_alloc(sizeof(MODULEINFO)); + ZeroMemory(node, sizeof(MODULEINFO)); + + node->pszModule = (char*)mir_alloc(lstrlenA(pszModule) + 1); + lstrcpyA(node->pszModule, pszModule); + + if (m_ModList == NULL) // list is empty + { + m_ModList = node; + node->next = NULL; + } + else + { + node->next = m_ModList; + m_ModList = node; + } + return node; + } + return FALSE; +} + +void MM_IconsChanged(void) +{ + MODULEINFO *pTemp = m_ModList, *pLast = NULL; + ImageList_ReplaceIcon(hIconsList, 0, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE)); + ImageList_ReplaceIcon(hIconsList, 1, LoadIconEx( "overlay", FALSE )); + while (pTemp != NULL) + { + pTemp->OnlineIconIndex = ImageList_ReplaceIcon(hIconsList, pTemp->OnlineIconIndex, LoadSkinnedProtoIcon(pTemp->pszModule, ID_STATUS_ONLINE)); + pTemp->OfflineIconIndex = ImageList_ReplaceIcon(hIconsList, pTemp->OfflineIconIndex, LoadSkinnedProtoIcon(pTemp->pszModule, ID_STATUS_OFFLINE)); + + if (pTemp->hOfflineIcon) + DestroyIcon(pTemp->hOfflineIcon); + if (pTemp->hOnlineIcon) + DestroyIcon(pTemp->hOnlineIcon); + if (pTemp->hOnlineTalkIcon) + DestroyIcon(pTemp->hOnlineTalkIcon); + if (pTemp->hOfflineTalkIcon) + DestroyIcon(pTemp->hOfflineTalkIcon); + pTemp->hOfflineIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT); + pTemp->hOnlineIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT); + + pTemp->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1)); + ImageList_ReplaceIcon(hIconsList, pTemp->OnlineIconIndex+1, pTemp->hOnlineTalkIcon); + + pTemp->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1)); + ImageList_ReplaceIcon(hIconsList, pTemp->OfflineIconIndex+1, pTemp->hOfflineTalkIcon); + + pLast = pTemp; + pTemp = pTemp->next; + } + return; +} +void MM_FontsChanged(void) +{ + MODULEINFO *pTemp = m_ModList; + while (pTemp != NULL) + { + pTemp->pszHeader = Log_CreateRtfHeader(pTemp); + pTemp = pTemp->next; + } + return; +} +MODULEINFO* MM_FindModule(const char* pszModule) +{ + MODULEINFO *pTemp = m_ModList, *pLast = NULL; + + if (!pszModule) + return NULL; + + while (pTemp != NULL) { + if (lstrcmpiA(pTemp->pszModule,pszModule) == 0) + return pTemp; + + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +// stupid thing.. +void MM_FixColors() +{ + MODULEINFO *pTemp = m_ModList; + + while (pTemp != NULL) + { + CheckColorsInModule(pTemp->pszModule); + pTemp = pTemp->next; + } + return; +} + +BOOL MM_RemoveAll (void) +{ + while (m_ModList != NULL) + { + MODULEINFO *pLast = m_ModList->next; + mir_free(m_ModList->pszModule); + mir_free(m_ModList->ptszModDispName); + mir_free(m_ModList->pszHeader); + mir_free(m_ModList->crColors); + + if (m_ModList->hOfflineIcon) + DestroyIcon(m_ModList->hOfflineIcon); + if (m_ModList->hOnlineIcon) + DestroyIcon(m_ModList->hOnlineIcon); + if (m_ModList->hOnlineTalkIcon) + DestroyIcon(m_ModList->hOnlineTalkIcon); + if (m_ModList->hOfflineTalkIcon) + DestroyIcon(m_ModList->hOfflineTalkIcon); + + mir_free(m_ModList); + m_ModList = pLast; + } + m_ModList = NULL; + return TRUE; +} + + + +//--------------------------------------------------- +// Tab list manager functions +// +// Necessary to keep track of what tabs should +// be restored +//--------------------------------------------------- + +BOOL TabM_AddTab(const TCHAR* pszID, const char* pszModule) +{ + TABLIST *node = NULL; + if (!pszID || !pszModule) + return FALSE; + + node = (TABLIST*) mir_alloc(sizeof(TABLIST)); + ZeroMemory( node, sizeof( TABLIST )); + node->pszID = mir_tstrdup( pszID ); + node->pszModule = mir_strdup( pszModule ); + + if ( g_TabList == NULL ) { // list is empty + g_TabList = node; + node->next = NULL; + } + else { + node->next = g_TabList; + g_TabList = node; + } + return TRUE; +} + +BOOL TabM_RemoveAll (void) +{ + while (g_TabList != NULL) + { + TABLIST * pLast = g_TabList->next; + mir_free(g_TabList->pszModule); + mir_free(g_TabList->pszID); + mir_free(g_TabList); + g_TabList = pLast; + } + g_TabList = NULL; + return TRUE; +} + +//--------------------------------------------------- +// Status manager functions +// +// Necessary to keep track of what user statuses +// per window nicklist that is available +//--------------------------------------------------- + +STATUSINFO * TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount) +{ + if (!ppStatusList || !pszStatus) + return NULL; + + if ( !TM_FindStatus(*ppStatusList, pszStatus)) { + STATUSINFO *node = (STATUSINFO*) mir_alloc(sizeof(STATUSINFO)); + ZeroMemory(node, sizeof(STATUSINFO)); + replaceStr( &node->pszGroup, pszStatus ); + node->hIcon = (HICON)(*iCount); + while ((int)node->hIcon > STATUSICONCOUNT - 1) + node->hIcon--; + + if (*ppStatusList == NULL) // list is empty + { + node->Status = 1; + *ppStatusList = node; + node->next = NULL; + } + else + { + node->Status = ppStatusList[0]->Status*2; + node->next = *ppStatusList; + *ppStatusList = node; + } + return node; + + } + return FALSE; +} + +STATUSINFO * TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus) +{ + STATUSINFO *pTemp = pStatusList, *pLast = NULL; + + if (!pStatusList || !pszStatus) + return NULL; + + while ( pTemp != NULL ) { + if ( lstrcmpi(pTemp->pszGroup, pszStatus) == 0 ) + return pTemp; + + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus) +{ + STATUSINFO *pTemp = pStatusList, *pLast = NULL; + + if (!pStatusList || !pszStatus) + return 0; + + while (pTemp != NULL) { + if ( lstrcmpi( pTemp->pszGroup, pszStatus ) == 0 ) + return pTemp->Status; + + if ( pTemp->next == NULL ) + return pStatusList->Status; + + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status) +{ + STATUSINFO *pTemp = pStatusList, *pLast = NULL; + + if (!pStatusList) + return NULL; + + while (pTemp != NULL) { + if (pTemp->Status&Status) { + Status -= pTemp->Status; + if (Status == 0) + return pTemp->pszGroup; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +BOOL TM_RemoveAll (STATUSINFO** ppStatusList) +{ + + if (!ppStatusList) + return FALSE; + + while (*ppStatusList != NULL) + { + STATUSINFO *pLast = ppStatusList[0]->next; + mir_free(ppStatusList[0]->pszGroup); + if ((int)ppStatusList[0]->hIcon > 10) + DestroyIcon(ppStatusList[0]->hIcon); + mir_free(*ppStatusList); + *ppStatusList = pLast; + } + *ppStatusList = NULL; + return TRUE; +} + +//--------------------------------------------------- +// User manager functions +// +// Necessary to keep track of the users +// in a window nicklist +//--------------------------------------------------- + + +static int UM_CompareItem(USERINFO * u1, const TCHAR* pszNick, WORD wStatus) +{ + int i; + + WORD dw1 = u1->Status; + WORD dw2 = wStatus; + + for (i=0; i<8; i++ ) + { + if (( dw1 & 1 ) && !( dw2 & 1 )) + return -1; + if (( dw2 & 1 ) && !( dw1 & 1 )) + return 1; + if (( dw1 & 1 ) && ( dw2 & 1 )) + return lstrcmp( u1->pszNick, pszNick ); + + dw1 = dw1 >> 1; + dw2 = dw2 >> 1; + } + return lstrcmp( u1->pszNick, pszNick ); + +} + +USERINFO * UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID) +{ + USERINFO * pTemp = *ppUserList, *pLast = NULL; + USERINFO * node = NULL; + + if (!pTemp || !pszUID) + return NULL; + + while(pTemp && lstrcmpi( pTemp->pszUID, pszUID)) { + pLast = pTemp; + pTemp = pTemp->next; + } + + if ( pTemp ) { + node = pTemp; + if (pLast) + pLast->next = pTemp->next; + else + *ppUserList = pTemp->next; + pTemp = *ppUserList; + + pLast = NULL; + + while ( pTemp && UM_CompareItem(pTemp, node->pszNick, node->Status ) <= 0) { + pLast = pTemp; + pTemp = pTemp->next; + } + + if (*ppUserList == NULL) { // list is empty + *ppUserList = node; + node->next = NULL; + } + else { + if ( pLast ) { + node->next = pTemp; + pLast->next = node; + } + else { + node->next = *ppUserList; + *ppUserList = node; + } } + + return node; + } + return NULL; +} + +USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** ppUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus) +{ + USERINFO * pTemp = *ppUserList, *pLast = NULL; + + if (!pStatusList || !ppUserList || !ppUserList) + return NULL; + + while(pTemp && UM_CompareItem(pTemp, pszNick, wStatus) <= 0) + { + pLast = pTemp; + pTemp = pTemp->next; + } + + // if (!UM_FindUser(*ppUserList, pszUI, wStatus) + { + USERINFO *node = (USERINFO*) mir_alloc(sizeof(USERINFO)); + ZeroMemory(node, sizeof(USERINFO)); + replaceStr( &node->pszUID, pszUID ); + + if (*ppUserList == NULL) { // list is empty + *ppUserList = node; + node->next = NULL; + } + else { + if ( pLast ) { + node->next = pTemp; + pLast->next = node; + } + else { + node->next = *ppUserList; + *ppUserList = node; + } } + + return node; + } + return NULL; +} + +USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID) +{ + USERINFO *pTemp = pUserList, *pLast = NULL; + + if (!pUserList || !pszUID) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->pszUID, pszUID )) + return pTemp; + + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index) +{ + int i = 0; + USERINFO *pTemp = pUserList; + + if (!pUserList) + return NULL; + + while (pTemp != NULL) + { + if (i == index) + { + return pTemp; + } + pTemp = pTemp->next; + i++; + } + return NULL; +} + +USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status) +{ + USERINFO *pTemp = pUserList, *pLast = NULL; + + if (!pUserList || !pszUID) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->pszUID, pszUID )) { + pTemp->Status |= status; + return pTemp; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status) +{ + USERINFO *pTemp = pUserList, *pLast = NULL; + + if (!pUserList || !pszUID) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->pszUID, pszUID )) { + pTemp->ContactStatus = status; + return pTemp; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +BOOL UM_SetStatusEx(USERINFO* pUserList, const TCHAR* pszText, int flags ) +{ + USERINFO *pTemp = pUserList, *pLast = NULL; + int bOnlyMe = ( flags & GC_SSE_ONLYLISTED ) != 0, bSetStatus = ( flags & GC_SSE_ONLINE ) != 0; + char cDelimiter = ( flags & GC_SSE_TABDELIMITED ) ? '\t' : ' '; + + while (pTemp != NULL) + { + if ( !bOnlyMe ) + pTemp->iStatusEx = 0; + + if ( pszText != NULL ) { + TCHAR* s = (TCHAR *)_tcsstr(pszText, pTemp->pszUID); + if ( s ) { + pTemp->iStatusEx = 0; + if ( s == pszText || s[-1] == cDelimiter ) { + int len = lstrlen( pTemp->pszUID ); + if ( s[len] == cDelimiter || s[len] == '\0' ) + pTemp->iStatusEx = ( !bOnlyMe || bSetStatus ) ? 1 : 0; + } } } + + pLast = pTemp; + pTemp = pTemp->next; + } + return TRUE; +} + +USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status) +{ + USERINFO *pTemp = pUserList, *pLast = NULL; + + if (!pUserList || !pszUID) + return NULL; + + while ( pTemp != NULL ) { + if ( !lstrcmpi( pTemp->pszUID, pszUID )) { + pTemp->Status &= ~status; + return pTemp; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return 0; +} + +TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent) +{ + TCHAR* pszName = NULL; + USERINFO *pTemp = pUserList; + + if (!pUserList || !pszOriginal || !pszCurrent) + return NULL; + + while ( pTemp != NULL ) { + if ( pTemp->pszNick && my_strstri( pTemp->pszNick, pszOriginal) == pTemp->pszNick ) + if ( lstrcmpi( pTemp->pszNick, pszCurrent ) > 0 && ( !pszName || lstrcmpi( pTemp->pszNick, pszName ) < 0)) + pszName = pTemp->pszNick; + + pTemp = pTemp->next; + } + return pszName; +} + +BOOL UM_RemoveUser(USERINFO** ppUserList, const TCHAR* pszUID) +{ + USERINFO *pTemp = *ppUserList, *pLast = NULL; + + if (!ppUserList || !pszUID) + return FALSE; + + while (pTemp != NULL) { + if (!lstrcmpi( pTemp->pszUID, pszUID )) { + if (pLast == NULL) + *ppUserList = pTemp->next; + else + pLast->next = pTemp->next; + mir_free(pTemp->pszNick); + mir_free(pTemp->pszUID); + mir_free(pTemp); + return TRUE; + } + pLast = pTemp; + pTemp = pTemp->next; + } + return FALSE; +} + +BOOL UM_RemoveAll (USERINFO** ppUserList) +{ + if (!ppUserList) + return FALSE; + + while (*ppUserList != NULL) + { + USERINFO *pLast = ppUserList[0]->next; + mir_free( ppUserList[0]->pszUID ); + mir_free( ppUserList[0]->pszNick ); + mir_free( *ppUserList ); + *ppUserList = pLast; + } + *ppUserList = NULL; + return TRUE; +} + +//--------------------------------------------------- +// Log manager functions +// +// Necessary to keep track of events +// in a window log +//--------------------------------------------------- + +LOGINFO * LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd) +{ + + LOGINFO *node = NULL; + + if (!ppLogListStart || !ppLogListEnd) + return NULL; + + node = (LOGINFO*) mir_alloc(sizeof(LOGINFO)); + ZeroMemory(node, sizeof(LOGINFO)); + + + if (*ppLogListStart == NULL) // list is empty + { + *ppLogListStart = node; + *ppLogListEnd = node; + node->next = NULL; + node->prev = NULL; + } + else + { + ppLogListStart[0]->prev = node; + node->next = *ppLogListStart; + *ppLogListStart = node; + ppLogListStart[0]->prev=NULL; + } + + return node; +} + +BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount) +{ + LOGINFO *pTemp = *ppLogListEnd; + while (pTemp != NULL && iCount > 0) { + *ppLogListEnd = pTemp->prev; + if (*ppLogListEnd == NULL) + *ppLogListStart = NULL; + + mir_free(pTemp->ptszNick); + mir_free(pTemp->ptszUserInfo); + mir_free(pTemp->ptszText); + mir_free(pTemp->ptszStatus); + mir_free(pTemp); + pTemp = *ppLogListEnd; + iCount--; + } + ppLogListEnd[0]->next = NULL; + + return TRUE; +} + +BOOL LM_RemoveAll (LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd) +{ + while ( *ppLogListStart != NULL ) { + LOGINFO *pLast = ppLogListStart[0]->next; + mir_free( ppLogListStart[0]->ptszText ); + mir_free( ppLogListStart[0]->ptszNick ); + mir_free( ppLogListStart[0]->ptszStatus ); + mir_free( ppLogListStart[0]->ptszUserInfo ); + mir_free( *ppLogListStart ); + *ppLogListStart = pLast; + } + *ppLogListStart = NULL; + *ppLogListEnd = NULL; + return TRUE; +} diff --git a/src/core/stdchat/src/message.cpp b/src/core/stdchat/src/message.cpp new file mode 100644 index 0000000000..ce76bfc6f5 --- /dev/null +++ b/src/core/stdchat/src/message.cpp @@ -0,0 +1,356 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson +Copyright 2003-2009 Miranda ICQ/IM project, + +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 "chat.h" +#include + +static int RTFColorToIndex(int *pIndex, int iCol, SESSION_INFO* si) +{ + int i; + MODULEINFO * pMod = MM_FindModule(si->pszModule); + + for (i = 0; i < pMod->nColorCount ; i++) + if ( pIndex[i] == iCol ) + return i; + + return -1; +} + +static void CreateColorMap( char* Text, int *pIndex, SESSION_INFO* si) +{ + char *p1, *p2, *pEnd; + int iIndex = 1; + + static const char* lpszFmt = "\\red%[^ \x5b\\]\\green%[^ \x5b\\]\\blue%[^ \x5b;];"; + char szRed[10], szGreen[10], szBlue[10]; + + p1 = strstr(Text, "\\colortbl" ); + if ( !p1 ) + return; + + pEnd = strchr(p1, '}'); + p2 = strstr(p1, "\\red" ); + + while (p2 && p2 < pEnd) { + if ( sscanf( p2, lpszFmt, &szRed, &szGreen, &szBlue) > 0 ) { + int i; + MODULEINFO * pMod = MM_FindModule(si->pszModule); + for (i = 0; i < pMod->nColorCount ; i ++) + if (pMod->crColors[i] == RGB( atoi(szRed), atoi(szGreen), atoi(szBlue))) + pIndex[i] = iIndex; + } + iIndex++; + p1 = p2; + p1 ++; + p2 = strstr(p1, "\\red" ); +} } + +static int ReadInteger( const char* p, int* result ) +{ + char temp[10]; + int i=0; + while ( isdigit( *p )) + temp[i++] = *p++; + temp[i] = 0; + + if ( result != NULL ) + *result = atoi( temp ); + + return i; +} + +TCHAR* DoRtfToTags( char* pszText, SESSION_INFO* si) +{ + char *p1; + int* pIndex; + int i, iRemoveChars, cp = CP_ACP; + char InsertThis[50]; + BOOL bJustRemovedRTF = TRUE; + BOOL bTextHasStarted = FALSE; + int iUcMode = 0; + + if ( !pszText ) + return FALSE; + + // create an index of colors in the module and map them to + // corresponding colors in the RTF color table + pIndex = (int *)mir_alloc(sizeof(int) * MM_FindModule(si->pszModule)->nColorCount); + for(i = 0; i < MM_FindModule(si->pszModule)->nColorCount ; i++) + pIndex[i] = -1; + + CreateColorMap( pszText, pIndex, si ); + + // scan the file for rtf commands and remove or parse them + p1 = strstr( pszText, "\\pard" ); + if ( p1 == NULL ) { + mir_free(pIndex); + return FALSE; + } + + p1 += 5; + + memmove(pszText, p1, strlen(p1) + 1); + p1 = pszText; + + // iterate through all characters, if rtf control character found then take action + while ( *p1 != '\0' ) { + InsertThis[0] = 0; + iRemoveChars = 0; + + switch (*p1) { + case '\\': + if ( !memcmp(p1, "\\cf", 3 )) { // foreground color + int iCol, iInd; + iRemoveChars = 3 + ReadInteger(p1+3, &iCol); + iInd = RTFColorToIndex(pIndex, iCol, si); + bJustRemovedRTF = TRUE; + + if (bTextHasStarted || iInd >= 0) + mir_snprintf( InsertThis, SIZEOF(InsertThis), ( iInd >= 0 ) ? "%%c%02u" : "%%C", iInd); + } + else if ( !memcmp(p1, "\\highlight", 10 )) { //background color + int iCol, iInd; + iRemoveChars = 10 + ReadInteger(p1+10, &iCol); + iInd = RTFColorToIndex(pIndex, iCol, si); + bJustRemovedRTF = TRUE; + + if (bTextHasStarted || iInd >= 0) + mir_snprintf( InsertThis, SIZEOF(InsertThis), ( iInd >= 0 ) ? "%%f%02u" : "%%F", iInd); + } + else if ( !memcmp(p1, "\\lang", 5 )) { // language id + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = 5 + ReadInteger( p1+5, NULL ); + } + else if ( !memcmp(p1, "\\par", 4 )) { // newline + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = 4; + strcpy(InsertThis, "\n" ); + } + else if ( !memcmp(p1, "\\line", 5 )) { // newline + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = 5; + strcpy(InsertThis, "\n" ); + } + else if (!memcmp(p1, "\\bullet", 7)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 7; + strcpy(InsertThis, "\xE2\x80\xA2"); + } + else if ( !memcmp(p1, "\\b", 2 )) { //bold + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = (p1[2] != '0')?2:3; + mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[2] != '0') ? "%%b": "%%B" ); + } + else if ( !memcmp(p1, "\\i", 2 )) { // italics + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = (p1[2] != '0')?2:3; + mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[2] != '0') ? "%%i" : "%%I" ); + } + else if ( !memcmp(p1, "\\uc", 3 )) { // number of Unicode chars + bTextHasStarted = bJustRemovedRTF = TRUE; + iUcMode = p1[3] - '0'; + iRemoveChars = 4; + } + else if ( !memcmp(p1, "\\ul", 3 )) { // underlined + bTextHasStarted = bJustRemovedRTF = TRUE; + if (p1[3] == 'n') + iRemoveChars = 7; + else if (p1[3] == '0') + iRemoveChars = 4; + else + iRemoveChars = 3; + mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[3] != '0' && p1[3] != 'n') ? "%%u" : "%%U" ); + } + else if ( p1[1] == 'f' && isdigit( p1[2] )) { // unicode char + bTextHasStarted = bJustRemovedRTF = TRUE; + iRemoveChars = 2 + ReadInteger( p1+2, NULL ); + } + else if ( !memcmp(p1, "\\tab", 4 )) { // tab + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 4; + strcpy(InsertThis, " " ); + } + else if (!memcmp(p1, "\\endash", 7)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 7; + strcpy(InsertThis, "\xE2\x80\x93"); + } + else if (!memcmp(p1, "\\emdash", 7)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 7; + strcpy(InsertThis, "\xE2\x80\x94"); + } + else if (!memcmp(p1, "\\lquote",7)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 7; + strcpy(InsertThis, "\xE2\x80\x98"); + } + else if (!memcmp(p1, "\\rquote",7)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 7; + strcpy(InsertThis, "\xE2\x80\x99"); + } + else if (!memcmp(p1, "\\ldblquote",10)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 10; + strcpy(InsertThis, "\xe2\x80\x9c"); + } + else if (!memcmp(p1, "\\rdblquote",10)) { + bTextHasStarted = TRUE; + bJustRemovedRTF = TRUE; + iRemoveChars = 10; + strcpy(InsertThis, "\xe2\x80\x9d"); + } + else if ( p1[1] == '\\' || p1[1] == '{' || p1[1] == '}' ) { // escaped characters + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + iRemoveChars = 2; + mir_snprintf(InsertThis, SIZEOF(InsertThis), "%c", p1[1]); + } + else if ( p1[1] == '~' ) { // non-breaking space + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + iRemoveChars = 2; + strcpy(InsertThis, "\xC2\xA0"); + } + else if ( p1[1] == '\'' ) { // special character + char tmp[4], *p3 = tmp; + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + if (p1[2] != ' ' && p1[2] != '\\') { + *p3++ = p1[2]; + iRemoveChars = 3; + if ( p1[3] != ' ' && p1[3] != '\\') { + *p3++ = p1[3]; + iRemoveChars++; + } + *p3 = 0; + sscanf( tmp, "%x", InsertThis ); + + InsertThis[1] = 0; + } + else iRemoveChars = 2; + } + else if ( bJustRemovedRTF ) { // remove unknown RTF command + int j = 1; + bJustRemovedRTF = TRUE; + while(p1[j] != ' ' && p1[j] != '\\' && p1[j] != '\0') + j++; + iRemoveChars = j; + } + break; + + case '{': // other RTF control characters + case '}': + iRemoveChars = 1; + break; + + case '\r': case '\n': + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + iRemoveChars = 1; + break; + + case '%': // escape chat -> protocol control character + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + iRemoveChars = 1; + strcpy(InsertThis, "%%"); + break; + case ' ': // remove spaces following a RTF command + if (bJustRemovedRTF) + iRemoveChars = 1; + bJustRemovedRTF = FALSE; + bTextHasStarted = TRUE; + break; + + default: // other text that should not be touched + bTextHasStarted = TRUE; + bJustRemovedRTF = FALSE; + break; + } + + // move the memory and paste in new commands instead of the old RTF + if (InsertThis[0] || iRemoveChars) + { + size_t len = strlen(InsertThis); + memmove(p1 + len , p1 + iRemoveChars, strlen(p1) - iRemoveChars + 1); + memcpy(p1, InsertThis, len); + p1 += len; + } + else p1++; + } + + mir_free(pIndex); + + return mir_utf8decodeW(pszText); +} + +static DWORD CALLBACK Message_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + static DWORD dwRead; + char ** ppText = (char **) dwCookie; + + if (*ppText == NULL) { + *ppText = (char *)mir_alloc(cb + 1); + memcpy(*ppText, pbBuff, cb); + (*ppText)[cb] = 0; + *pcb = cb; + dwRead = cb; + } + else { + char *p = (char *)mir_alloc(dwRead + cb + 1); + memcpy(p, *ppText, dwRead); + memcpy(p+dwRead, pbBuff, cb); + p[dwRead + cb] = 0; + mir_free(*ppText); + *ppText = p; + *pcb = cb; + dwRead += cb; + } + + return 0; +} + +char* Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si) +{ + EDITSTREAM stream; + char* pszText = NULL; + DWORD dwFlags; + + if (hwndDlg == 0 || si == 0) + return NULL; + + ZeroMemory(&stream, sizeof(stream)); + stream.pfnCallback = Message_StreamCallback; + stream.dwCookie = (DWORD_PTR) &pszText; // pass pointer to pointer + + dwFlags = SF_RTFNOOBJS | SFF_PLAINRTF | SF_USECODEPAGE | (CP_UTF8 << 16); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_STREAMOUT, dwFlags, (LPARAM) & stream); + return pszText; // pszText contains the text +} diff --git a/src/core/stdchat/src/options.cpp b/src/core/stdchat/src/options.cpp new file mode 100644 index 0000000000..89d39d7f47 --- /dev/null +++ b/src/core/stdchat/src/options.cpp @@ -0,0 +1,1123 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +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 "resource.h" +#include "chat.h" + +#include + +extern HBRUSH hEditBkgBrush; +extern HBRUSH hListBkgBrush; +extern HBRUSH hListSelectedBkgBrush; +extern HICON hIcons[30]; +extern FONTINFO aFonts[OPTIONS_FONTCOUNT]; +extern BOOL PopUpInstalled; +extern SESSION_INFO g_TabSession; + +HANDLE g_hOptions = NULL; + +#define FONTF_BOLD 1 +#define FONTF_ITALIC 2 +struct FontOptionsList +{ + const TCHAR* szDescr; + COLORREF defColour; + const TCHAR* szDefFace; + BYTE defCharset, defStyle; + char defSize; + COLORREF colour; + const TCHAR* szFace; + BYTE charset, style; + char size; +} + +//remeber to put these in the Translate( ) template file too +static const fontOptionsList[] = { + { LPGENT("Timestamp"), RGB(50, 50, 240), _T("Terminal"), DEFAULT_CHARSET, 0, -8}, + { LPGENT("Others nicknames"), RGB(0, 0, 0), _T("Verdana"), DEFAULT_CHARSET, FONTF_BOLD, -12}, + { LPGENT("Your nickname"), RGB(0, 0, 0), _T("Verdana"), DEFAULT_CHARSET, FONTF_BOLD, -12}, + { LPGENT("User has joined"), RGB(90, 160, 90), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User has left"), RGB(160, 160, 90), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User has disconnected"), RGB(160, 90, 90), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User kicked ..."), RGB(100, 100, 100), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User is now known as ..."), RGB(90, 90, 160), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Notice from user"), RGB(160, 130, 60), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Incoming message"), RGB(90, 90, 90), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Outgoing message"), RGB(90, 90, 90), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("The topic is ..."), RGB(70, 70, 160), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Information messages"), RGB(130, 130, 195), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User enables status for ..."), RGB(70, 150, 70), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User disables status for ..."), RGB(150, 70, 70), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Action message"), RGB(160, 90, 160), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Highlighted message"), RGB(180, 150, 80), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("Message typing area"), RGB(0, 0, 40), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User list members (Online)"), RGB(0,0, 0), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, + { LPGENT("User list members (away)"), RGB(170, 170, 170), _T("Verdana"), DEFAULT_CHARSET, 0, -12}, +}; + +const int msgDlgFontCount = SIZEOF(fontOptionsList); + +struct branch_t +{ + const TCHAR* szDescr; + const char* szDBName; + int iMode; + BYTE bDefault; +}; + +static const struct branch_t branch0[] = { + { LPGENT("Use a tabbed interface"), "Tabs", 0, 1}, + { LPGENT("Close tab on doubleclick"), "TabCloseOnDblClick", 0, 0}, + { LPGENT("Restore previously open tabs when showing the window"), "TabRestore", 0, 0}, + { LPGENT("Show tabs at the bottom"), "TabBottom", 0, 0}, +}; + +static const struct branch_t branch1[] = { + { LPGENT("Send message by pressing the Enter key"), "SendOnEnter", 0, 1}, + { LPGENT("Send message by pressing the Enter key twice"), "SendOnDblEnter", 0,0}, + { LPGENT("Flash window when someone speaks"), "FlashWindow", 0,0}, + { LPGENT("Flash window when a word is highlighted"), "FlashWindowHighlight", 0,1}, + { LPGENT("Show list of users in the chat room"), "ShowNicklist", 0,1}, + { LPGENT("Show button for sending messages"), "ShowSend", 0, 0}, + { LPGENT("Show buttons for controlling the chat room"), "ShowTopButtons", 0,1}, + { LPGENT("Show buttons for formatting the text you are typing"), "ShowFormatButtons", 0,1}, + { LPGENT("Show button menus when right clicking the buttons"), "RightClickFilter", 0,0}, + { LPGENT("Show new windows cascaded"), "CascadeWindows", 0,1}, + { LPGENT("Save the size and position of chat rooms"), "SavePosition", 0,0}, + { LPGENT("Show the topic of the room on your contact list (if supported)"), "TopicOnClist", 0, 0}, + { LPGENT("Do not play sounds when the chat room is focused"), "SoundsFocus", 0, 0}, + { LPGENT("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0,0}, + { LPGENT("Toggle the visible state when double clicking in the contact list"), "ToggleVisibility", 0,0}, + {LPGENT("Show contact statuses if protocol supports them"), "ShowContactStatus", 0,0}, + {LPGENT("Display contact status icon before user role icon"), "ContactStatusFirst", 0,0}, +}; + +static const struct branch_t branch2[] = { + { LPGENT("Prefix all events with a timestamp"), "ShowTimeStamp", 0,1}, + { LPGENT("Only prefix with timestamp if it has changed"), "ShowTimeStampIfChanged", 0,0}, + { LPGENT("Timestamp has same colour as the event"), "TimeStampEventColour", 0,0}, + { LPGENT("Indent the second line of a message"), "LogIndentEnabled", 0,1}, + { LPGENT("Limit user names in the message log to 20 characters"), "LogLimitNames", 0,1}, + { LPGENT("Add \':\' to auto-completed user names"), "AddColonToAutoComplete", 0, 1}, + { LPGENT("Strip colors from messages in the log"), "StripFormatting", 0, 0}, + { LPGENT("Enable the \'event filter\' for new rooms"), "FilterEnabled", 0,0} +}; + +static const struct branch_t branch3[] = { + { LPGENT("Show topic changes"), "FilterFlags", GC_EVENT_TOPIC, 0}, + { LPGENT("Show users joining"), "FilterFlags", GC_EVENT_JOIN, 0}, + { LPGENT("Show users disconnecting"), "FilterFlags", GC_EVENT_QUIT, 0}, + { LPGENT("Show messages"), "FilterFlags", GC_EVENT_MESSAGE, 1}, + { LPGENT("Show actions"), "FilterFlags", GC_EVENT_ACTION, 1}, + { LPGENT("Show users leaving"), "FilterFlags", GC_EVENT_PART, 0}, + { LPGENT("Show users being kicked"), "FilterFlags", GC_EVENT_KICK, 1}, + { LPGENT("Show notices"), "FilterFlags", GC_EVENT_NOTICE, 1}, + { LPGENT("Show users changing name"), "FilterFlags", GC_EVENT_NICK, 0}, + { LPGENT("Show information messages"), "FilterFlags", GC_EVENT_INFORMATION, 1}, + { LPGENT("Show status changes of users"), "FilterFlags", GC_EVENT_ADDSTATUS, 0}, +}; + +static const struct branch_t branch4[] = { + { LPGENT("Show icon for topic changes"), "IconFlags", GC_EVENT_TOPIC, 0}, + { LPGENT("Show icon for users joining"), "IconFlags", GC_EVENT_JOIN, 1}, + { LPGENT("Show icon for users disconnecting"), "IconFlags", GC_EVENT_QUIT, 0}, + { LPGENT("Show icon for messages"), "IconFlags", GC_EVENT_MESSAGE, 0}, + { LPGENT("Show icon for actions"), "IconFlags", GC_EVENT_ACTION, 0}, + { LPGENT("Show icon for highlights"), "IconFlags", GC_EVENT_HIGHLIGHT, 0}, + { LPGENT("Show icon for users leaving"), "IconFlags", GC_EVENT_PART, 0}, + { LPGENT("Show icon for users kicking other user"), "IconFlags", GC_EVENT_KICK, 0}, + { LPGENT("Show icon for notices "), "IconFlags", GC_EVENT_NOTICE, 0}, + { LPGENT("Show icon for name changes"), "IconFlags", GC_EVENT_NICK, 0}, + { LPGENT("Show icon for information messages"), "IconFlags", GC_EVENT_INFORMATION, 0}, + { LPGENT("Show icon for status changes"), "IconFlags", GC_EVENT_ADDSTATUS, 0}, +}; + +static const struct branch_t branch5[] = { + { LPGENT("Show icons in tray only when the chat room is not active"), "TrayIconInactiveOnly", 0, 1}, + { LPGENT("Show icon in tray for topic changes"), "TrayIconFlags", GC_EVENT_TOPIC, 0}, + { LPGENT("Show icon in tray for users joining"), "TrayIconFlags", GC_EVENT_JOIN, 0}, + { LPGENT("Show icon in tray for users disconnecting"), "TrayIconFlags", GC_EVENT_QUIT, 0}, + { LPGENT("Show icon in tray for messages"), "TrayIconFlags", GC_EVENT_MESSAGE, 0}, + { LPGENT("Show icon in tray for actions"), "TrayIconFlags", GC_EVENT_ACTION, 0}, + { LPGENT("Show icon in tray for highlights"), "TrayIconFlags", GC_EVENT_HIGHLIGHT, 1}, + { LPGENT("Show icon in tray for users leaving"), "TrayIconFlags", GC_EVENT_PART, 0}, + { LPGENT("Show icon in tray for users kicking other user"), "TrayIconFlags", GC_EVENT_KICK, 0}, + { LPGENT("Show icon in tray for notices "), "TrayIconFlags", GC_EVENT_NOTICE, 0}, + { LPGENT("Show icon in tray for name changes"), "TrayIconFlags", GC_EVENT_NICK, 0}, + { LPGENT("Show icon in tray for information messages"), "TrayIconFlags", GC_EVENT_INFORMATION, 0}, + { LPGENT("Show icon in tray for status changes"), "TrayIconFlags", GC_EVENT_ADDSTATUS, 0}, +}; + +static const struct branch_t branch6[] = { + { LPGENT("Show pop-ups only when the chat room is not active"), "PopUpInactiveOnly", 0, 1}, + { LPGENT("Show pop-up for topic changes"), "PopupFlags", GC_EVENT_TOPIC, 0}, + { LPGENT("Show pop-up for users joining"), "PopupFlags", GC_EVENT_JOIN, 0}, + { LPGENT("Show pop-up for users disconnecting"), "PopupFlags", GC_EVENT_QUIT, 0}, + { LPGENT("Show pop-up for messages"), "PopupFlags", GC_EVENT_MESSAGE, 0}, + { LPGENT("Show pop-up for actions"), "PopupFlags", GC_EVENT_ACTION, 0}, + { LPGENT("Show pop-up for highlights"), "PopupFlags", GC_EVENT_HIGHLIGHT, 0}, + { LPGENT("Show pop-up for users leaving"), "PopupFlags", GC_EVENT_PART, 0}, + { LPGENT("Show pop-up for users kicking other user"), "PopupFlags", GC_EVENT_KICK, 0}, + { LPGENT("Show pop-up for notices "), "PopupFlags", GC_EVENT_NOTICE, 0}, + { LPGENT("Show pop-up for name changes"), "PopupFlags", GC_EVENT_NICK, 0}, + { LPGENT("Show pop-up for information messages"), "PopupFlags", GC_EVENT_INFORMATION, 0}, + { LPGENT("Show pop-up for status changes"), "PopupFlags", GC_EVENT_ADDSTATUS, 0}, +}; + +HTREEITEM hItemB0[SIZEOF(branch0)]; +HTREEITEM hItemB1[SIZEOF(branch1)]; +HTREEITEM hItemB2[SIZEOF(branch2)]; +HTREEITEM hItemB3[SIZEOF(branch3)]; +HTREEITEM hItemB4[SIZEOF(branch4)]; +HTREEITEM hItemB5[SIZEOF(branch5)]; +HTREEITEM hItemB6[SIZEOF(branch6)]; + +static HTREEITEM InsertBranch(HWND hwndTree, char* pszDescr, BOOL bExpanded) +{ + HTREEITEM res; + TVINSERTSTRUCT tvis = {0}; + + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT|TVIF_STATE; + tvis.item.pszText = (TCHAR*)CallService(MS_LANGPACK_PCHARTOTCHAR, 0, (LPARAM)pszDescr); + tvis.item.stateMask = bExpanded ? TVIS_STATEIMAGEMASK | TVIS_EXPANDED : TVIS_STATEIMAGEMASK; + tvis.item.state = bExpanded ? INDEXTOSTATEIMAGEMASK(1) | TVIS_EXPANDED : INDEXTOSTATEIMAGEMASK(1); + res = TreeView_InsertItem(hwndTree, &tvis); + mir_free(tvis.item.pszText); + return res; +} + +static void FillBranch(HWND hwndTree, HTREEITEM hParent, const struct branch_t *branch, HTREEITEM *hItemB, int nValues, DWORD defaultval) +{ + TVINSERTSTRUCT tvis; + int i; + int iState; + + if (hParent == 0) + return; + + tvis.hParent=hParent; + tvis.hInsertAfter=TVI_LAST; + tvis.item.mask=TVIF_TEXT|TVIF_STATE; + for (i=0;i>12==1)?0:1; + if(branch[i].iMode) { + if (bChecked) + iState |= branch[i].iMode; + if (iState&GC_EVENT_ADDSTATUS) + iState |= GC_EVENT_REMOVESTATUS; + DBWriteContactSettingDword(NULL, "Chat", branch[i].szDBName, (DWORD)iState); + } + else DBWriteContactSettingByte(NULL, "Chat", branch[i].szDBName, bChecked); +} } + +static void CheckHeading(HWND hwndTree, HTREEITEM hHeading) +{ + BOOL bChecked = TRUE; + TVITEM tvi; + + if (hHeading == 0) + return; + + tvi.mask=TVIF_HANDLE|TVIF_STATE; + tvi.hItem=TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD); + while(tvi.hItem && bChecked) { + if (tvi.hItem != hItemB1[0] && tvi.hItem != hItemB1[1] ) { + TreeView_GetItem(hwndTree,&tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK)>>12 == 1)) + bChecked = FALSE; + } + tvi.hItem=TreeView_GetNextSibling(hwndTree,tvi.hItem); + } + tvi.stateMask = TVIS_STATEIMAGEMASK; + tvi.state = INDEXTOSTATEIMAGEMASK(bChecked?2:1); + tvi.hItem = hHeading; + TreeView_SetItem(hwndTree,&tvi); +} + +static void CheckBranches(HWND hwndTree, HTREEITEM hHeading) +{ + BOOL bChecked = TRUE; + TVITEM tvi; + + if (hHeading == 0) + return; + + tvi.mask=TVIF_HANDLE|TVIF_STATE; + tvi.hItem = hHeading; + TreeView_GetItem(hwndTree,&tvi); + if (((tvi.state&TVIS_STATEIMAGEMASK)>>12==2)) + bChecked = FALSE; + tvi.hItem=TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD); + tvi.stateMask = TVIS_STATEIMAGEMASK; + while(tvi.hItem) { + tvi.state=INDEXTOSTATEIMAGEMASK(bChecked?2:1); + if (tvi.hItem !=hItemB1[0] && tvi.hItem != hItemB1[1] ) + TreeView_SetItem(hwndTree,&tvi); + tvi.hItem=TreeView_GetNextSibling(hwndTree,tvi.hItem); +} } + +static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) +{ + TCHAR szDir[MAX_PATH]; + switch(uMsg) { + case BFFM_INITIALIZED: + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + + case BFFM_SELCHANGED: + if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) + SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); + break; + } + return 0; +} + +void LoadLogFonts(void) +{ + int i; + + for ( i = 0; ilfHeight = (char) DBGetContactSettingByte(NULL, "ChatFonts", str, fontOptionsList[i].defSize); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + wsprintfA(str, "Font%dSty", i); + style = DBGetContactSettingByte(NULL, "ChatFonts", 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; + wsprintfA(str, "Font%dSet", i); + lf->lfCharSet = DBGetContactSettingByte(NULL, "ChatFonts", str, fontOptionsList[i].defCharset); + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + wsprintfA(str, "Font%d", i); + if (DBGetContactSettingTString(NULL, "ChatFonts", str, &dbv)) + lstrcpy(lf->lfFaceName, fontOptionsList[i].szDefFace); + else { + lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName)); + DBFreeVariant(&dbv); +} } } + +void RegisterFonts( void ) +{ + FontIDT fontid = {0}; + ColourIDT colourid; + char idstr[10]; + int index = 0, i; + + fontid.cbSize = sizeof(FontIDT); + fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID | FIDF_NEEDRESTART; + for (i = 0; i < msgDlgFontCount; i++, index++) { + strncpy(fontid.dbSettingsGroup, "ChatFonts", sizeof(fontid.dbSettingsGroup)); + _tcsncpy(fontid.group, _T("Chat Module"), SIZEOF(fontid.group)); + _tcsncpy(fontid.name, fontOptionsList[i].szDescr, SIZEOF(fontid.name)); + sprintf(idstr, "Font%d", index); + strncpy(fontid.prefix, idstr, sizeof(fontid.prefix)); + fontid.order = index; + + fontid.deffontsettings.charset = fontOptionsList[i].defCharset; + fontid.deffontsettings.colour = fontOptionsList[i].defColour; + fontid.deffontsettings.size = fontOptionsList[i].defSize; + fontid.deffontsettings.style = fontOptionsList[i].defStyle; + _tcsncpy(fontid.deffontsettings.szFace, fontOptionsList[i].szDefFace, SIZEOF(fontid.deffontsettings.szFace)); + _tcsncpy(fontid.backgroundGroup, _T("Chat Module"), SIZEOF(fontid.backgroundGroup)); + switch (i) { + case 17: + _tcsncpy(fontid.backgroundName, _T("Message Background"), SIZEOF(fontid.backgroundName)); + break; + case 18: + case 19: + _tcsncpy(fontid.backgroundName, _T("Userlist Background"), SIZEOF(fontid.backgroundName)); + break; + default: + _tcsncpy(fontid.backgroundName, _T("Background"), SIZEOF(fontid.backgroundName)); + break; + } + FontRegisterT(&fontid); + } + + colourid.cbSize = sizeof(ColourIDT); + colourid.order = 0; + strncpy(colourid.dbSettingsGroup, "Chat", sizeof(colourid.dbSettingsGroup)); + + strncpy(colourid.setting, "ColorLogBG", SIZEOF(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Background"), SIZEOF(colourid.name)); + _tcsncpy(colourid.group, LPGENT("Chat Module"), SIZEOF(colourid.group)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "ColorMessageBG", SIZEOF(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Message Background"), SIZEOF(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "ColorNicklistBG", SIZEOF(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Userlist Background"), SIZEOF(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "ColorNicklistLines", SIZEOF(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Userlist Lines"), SIZEOF(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_INACTIVEBORDER); + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "ColorNicklistSelectedBG", SIZEOF(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Userlist Background (selected)"), SIZEOF(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT); + ColourRegisterT(&colourid); +} + +// add icons to the skinning module + +struct +{ + int size; + char* szSection; + char* szDescr; + char* szName; + int defIconID; +} +static const iconList[] = +{ + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Window Icon"), "chat_window", IDI_CHANMGR }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Text colour"), "chat_fgcol", IDI_COLOR }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Background colour"), "chat_bkgcol", IDI_BKGCOLOR }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Bold"), "chat_bold", IDI_BBOLD }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Italics"), "chat_italics", IDI_BITALICS }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Underlined"), "chat_underline", IDI_BUNDERLINE }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Smiley button"), "chat_smiley", IDI_BSMILEY }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Room history"), "chat_history", IDI_HISTORY }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Room settings"), "chat_settings", IDI_TOPICBUT }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Event filter disabled"), "chat_filter", IDI_FILTER }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Event filter enabled"), "chat_filter2", IDI_FILTER2 }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Hide userlist"), "chat_nicklist", IDI_NICKLIST }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Show userlist"), "chat_nicklist2", IDI_NICKLIST2 }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY }, + { 0, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Close"), "chat_close", IDI_CLOSE }, + + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0 }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1 }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2 }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3 }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4 }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats"), LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5 }, + + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Add Status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Remove status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Nickchange (10x10)"), "chat_log_nick", IDI_NICK }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT }, + { 10, LPGEN("Messaging") "/" LPGEN("Group Chats Log"), LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO } +}; + +void AddIcons(void) +{ + TCHAR szFile[MAX_PATH]; + GetModuleFileName(g_hInst, szFile, MAX_PATH); + + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.ptszDefaultFile = szFile; + sid.flags = SIDF_PATH_TCHAR; + + for (int i = 0; i < SIZEOF(iconList); i++ ) { + sid.cx = sid.cy = iconList[i].size; + sid.pszSection = iconList[i].szSection; + sid.pszDescription = iconList[i].szDescr; + sid.pszName = iconList[i].szName; + sid.iDefaultIndex = -iconList[i].defIconID; + Skin_AddIcon(&sid); +} } + +// load icons from the skinning module if available +HICON LoadIconEx( char* pszIcoLibName, BOOL big ) +{ + char szTemp[256]; + mir_snprintf(szTemp, SIZEOF(szTemp), "chat_%s", pszIcoLibName); + return (HICON) CallService(MS_SKIN2_GETICON, big, (LPARAM)szTemp); +} + +static void InitSetting(TCHAR** ppPointer, char* pszSetting, TCHAR* pszDefault) +{ + DBVARIANT dbv; + if ( !DBGetContactSettingTString(NULL, "Chat", pszSetting, &dbv )) { + replaceStr( ppPointer, dbv.ptszVal ); + DBFreeVariant(&dbv); + } + else replaceStr( ppPointer, pszDefault ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// General options + +#define OPT_FIXHEADINGS (WM_USER+1) + +static INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + static HTREEITEM hListHeading1 = 0; + static HTREEITEM hListHeading2= 0; + static HTREEITEM hListHeading3= 0; + static HTREEITEM hListHeading4= 0; + static HTREEITEM hListHeading5= 0; + static HTREEITEM hListHeading6= 0; + static HTREEITEM hListHeading0= 0; + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHECKBOXES),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHECKBOXES),GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES); + hListHeading0 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Options for using a tabbed interface"), DBGetContactSettingByte(NULL, "Chat", "Branch0Exp", 0)?TRUE:FALSE); + hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Appearance and functionality of chat room windows"), DBGetContactSettingByte(NULL, "Chat", "Branch1Exp", 0)?TRUE:FALSE); + hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Appearance of the message log"), DBGetContactSettingByte(NULL, "Chat", "Branch2Exp", 0)?TRUE:FALSE); + hListHeading3 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Default events to show in new chat rooms if the \'event filter\' is enabled"), DBGetContactSettingByte(NULL, "Chat", "Branch3Exp", 0)?TRUE:FALSE); + hListHeading4 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Icons to display in the message log"), DBGetContactSettingByte(NULL, "Chat", "Branch4Exp", 0)?TRUE:FALSE); + hListHeading5 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Icons to display in the tray"), DBGetContactSettingByte(NULL, "Chat", "Branch5Exp", 0)?TRUE:FALSE); + if (PopUpInstalled) + hListHeading6 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Pop-ups to display"), DBGetContactSettingByte(NULL, "Chat", "Branch6Exp", 0)?TRUE:FALSE); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0, branch0, hItemB0, SIZEOF(branch0), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, branch1, hItemB1, SIZEOF(branch1), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, hItemB2, SIZEOF(branch2), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3, branch3, hItemB3, SIZEOF(branch3), 0x03E0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4, branch4, hItemB4, SIZEOF(branch4), 0x0000); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5, branch5, hItemB5, SIZEOF(branch5), 0x1000); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6, branch6, hItemB6, SIZEOF(branch6), 0x0000); + SendMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0); + break; + + case OPT_FIXHEADINGS: + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6); + break; + + case WM_COMMAND: + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) { + case IDC_CHECKBOXES: + 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 = {0}; + tvi.mask=TVIF_HANDLE|TVIF_STATE; + tvi.hItem=hti.hItem; + TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom,&tvi); + if (tvi.hItem == hItemB1[0] && INDEXTOSTATEIMAGEMASK(1)==tvi.state) + TreeView_SetItemState(((LPNMHDR)lParam)->hwndFrom, hItemB1[1], INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK); + if (tvi.hItem == hItemB1[1] && INDEXTOSTATEIMAGEMASK(1)==tvi.state) + TreeView_SetItemState(((LPNMHDR)lParam)->hwndFrom, hItemB1[0], INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK); + + if (tvi.hItem == hListHeading0) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0); + else if (tvi.hItem == hListHeading1) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1); + else if (tvi.hItem == hListHeading2) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2); + else if (tvi.hItem == hListHeading3) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3); + else if (tvi.hItem == hListHeading4) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4); + else if (tvi.hItem == hListHeading5) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5); + else if (tvi.hItem == hListHeading6) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6); + else + PostMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } } } + break; + + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + BYTE b = DBGetContactSettingByte(NULL, "Chat", "Tabs", 1); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch0, hItemB0, SIZEOF(branch0)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, hItemB1, SIZEOF(branch1)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, hItemB2, SIZEOF(branch2)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch3, hItemB3, SIZEOF(branch3)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch4, hItemB4, SIZEOF(branch4)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch5, hItemB5, SIZEOF(branch5)); + if (PopUpInstalled) + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch6, hItemB6, SIZEOF(branch6)); + g_Settings.dwIconFlags = DBGetContactSettingDword(NULL, "Chat", "IconFlags", 0x0000); + g_Settings.dwTrayIconFlags = DBGetContactSettingDword(NULL, "Chat", "TrayIconFlags", 0x1000); + g_Settings.dwPopupFlags = DBGetContactSettingDword(NULL, "Chat", "PopupFlags", 0x0000); + g_Settings.StripFormat = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrimFormatting", 0); + g_Settings.TrayIconInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrayIconInactiveOnly", 1); + g_Settings.PopUpInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "PopUpInactiveOnly", 1); + g_Settings.LogIndentEnabled = (DBGetContactSettingByte(NULL, "Chat", "LogIndentEnabled", 1) != 0)?TRUE:FALSE; + + if (b != DBGetContactSettingByte(NULL, "Chat", "Tabs", 1)) { + SM_BroadcastMessage(NULL, GC_CLOSEWINDOW, 0, 1, FALSE); + g_Settings.TabsEnable = DBGetContactSettingByte(NULL, "Chat", "Tabs", 1); + } + else SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + } + return TRUE; + } } } + break; + + case WM_DESTROY: + { + BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch1Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch2Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch3Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch4Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch5Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch0Exp", b); + if (PopUpInstalled) { + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6, TVIS_EXPANDED)&TVIS_EXPANDED?1:0; + DBWriteContactSettingByte(NULL, "Chat", "Branch6Exp", b); + } } + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Log & other options + +static INT_PTR CALLBACK DlgProcOptions2(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_SETRANGE,0,MAKELONG(5000,0)); + SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_SETPOS,0,MAKELONG(DBGetContactSettingWord(NULL,"Chat","LogLimit",100),0)); + SendDlgItemMessage(hwndDlg,IDC_SPIN3,UDM_SETRANGE,0,MAKELONG(10000,0)); + SendDlgItemMessage(hwndDlg,IDC_SPIN3,UDM_SETPOS,0,MAKELONG(DBGetContactSettingWord(NULL,"Chat","LoggingLimit",100),0)); + SendDlgItemMessage(hwndDlg,IDC_SPIN4,UDM_SETRANGE,0,MAKELONG(255,10)); + SendDlgItemMessage(hwndDlg,IDC_SPIN4,UDM_SETPOS,0,MAKELONG(DBGetContactSettingByte(NULL,"Chat","NicklistRowDist",12),0)); + { + TCHAR* pszGroup = NULL; + InitSetting(&pszGroup, "AddToGroup", _T("Chat rooms")); + SetWindowText(GetDlgItem(hwndDlg, IDC_GROUP), pszGroup); + mir_free(pszGroup); + } + { + TCHAR szTemp[MAX_PATH]; + CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)g_Settings.pszLogDir, (LPARAM)szTemp ); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, szTemp); + } + SetDlgItemText(hwndDlg, IDC_HIGHLIGHTWORDS, g_Settings.pszHighlightWords); + SetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, g_Settings.pszTimeStampLog); + SetDlgItemText(hwndDlg, IDC_TIMESTAMP, g_Settings.pszTimeStamp); + SetDlgItemText(hwndDlg, IDC_OUTSTAMP, g_Settings.pszOutgoingNick); + SetDlgItemText(hwndDlg, IDC_INSTAMP, g_Settings.pszIncomingNick); + CheckDlgButton(hwndDlg, IDC_HIGHLIGHT, g_Settings.HighlightEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS), g_Settings.HighlightEnabled?TRUE:FALSE); + CheckDlgButton(hwndDlg, IDC_LOGGING, g_Settings.LoggingEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), g_Settings.LoggingEnabled?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTCHOOSE), g_Settings.LoggingEnabled?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), g_Settings.LoggingEnabled?TRUE:FALSE); + break; + + case WM_COMMAND: + if (( LOWORD(wParam) == IDC_INSTAMP + || LOWORD(wParam) == IDC_OUTSTAMP + || LOWORD(wParam) == IDC_TIMESTAMP + || LOWORD(wParam) == IDC_LOGLIMIT + || LOWORD(wParam) == IDC_HIGHLIGHTWORDS + || LOWORD(wParam) == IDC_LOGDIRECTORY + || LOWORD(wParam) == IDC_LOGTIMESTAMP + || LOWORD(wParam) == IDC_NICKROW2 + || LOWORD(wParam) == IDC_GROUP + || LOWORD(wParam) == IDC_LIMIT) + && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return 0; + + switch (LOWORD(wParam)) { + case IDC_LOGGING: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTCHOOSE), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED?TRUE:FALSE); + break; + + case IDC_FONTCHOOSE: + { + LPITEMIDLIST idList; + BROWSEINFO bi = {0}; + TCHAR szDirectory[MAX_PATH]; + TCHAR szTemp[MAX_PATH]; + + bi.hwndOwner=hwndDlg; + bi.pszDisplayName=szDirectory; + bi.lpszTitle=TranslateT("Select Folder"); + bi.ulFlags=BIF_NEWDIALOGSTYLE|BIF_EDITBOX|BIF_RETURNONLYFSDIRS; + bi.lpfn=BrowseCallbackProc; + bi.lParam=(LPARAM)szDirectory; + idList = SHBrowseForFolder(&bi); + if ( idList ) { + SHGetPathFromIDList(idList,szDirectory); + lstrcat(szDirectory, _T("\\")); + CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)szDirectory, (LPARAM)szTemp); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, lstrlen(szTemp) > 1 ? szTemp : _T("Logs\\")); + CoTaskMemFree(idList); + } + break; + } + case IDC_HIGHLIGHT: + EnableWindow(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS), IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHT) == BST_CHECKED?TRUE:FALSE); + break; + } + + if (lParam != (LPARAM)NULL) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY ) { + int iLen; + TCHAR * pszText = NULL; + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS)); + if ( iLen > 0 ) { + TCHAR *ptszText = (TCHAR *)mir_alloc((iLen+2) * sizeof(TCHAR)); + TCHAR *p2 = NULL; + + if(ptszText) { + GetDlgItemText(hwndDlg, IDC_HIGHLIGHTWORDS, ptszText, iLen + 1); + p2 = _tcschr(ptszText, ','); + while ( p2 ) { + *p2 = ' '; + p2 = _tcschr(ptszText, ','); + } + DBWriteContactSettingTString(NULL, "Chat", "HighlightWords", ptszText); + mir_free(ptszText); + } + } + else DBDeleteContactSetting(NULL, "Chat", "HighlightWords"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY)); + if ( iLen > 0 ) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText,iLen + 1); + DBWriteContactSettingTString(NULL, "Chat", "LogDirectory", pszText); + } + else DBDeleteContactSetting(NULL, "Chat", "LogDirectory"); + + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)pszText, (LPARAM)g_Settings.pszLogDir); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP)); + if ( iLen > 0 ) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen+1); + DBWriteContactSettingTString(NULL, "Chat", "LogTimestamp", pszText); + } + else DBDeleteContactSetting(NULL, "Chat", "LogTimestamp"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP)); + if ( iLen > 0 ) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_TIMESTAMP, pszText, iLen+1); + DBWriteContactSettingTString(NULL, "Chat", "HeaderTime", pszText); + } + else DBDeleteContactSetting(NULL, "Chat", "HeaderTime"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP)); + if ( iLen > 0 ) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_INSTAMP, pszText,iLen+1); + DBWriteContactSettingTString(NULL, "Chat", "HeaderIncoming", pszText); + } + else DBDeleteContactSetting(NULL, "Chat", "HeaderIncoming"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP)); + if ( iLen > 0 ) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_OUTSTAMP, pszText,iLen+1); + DBWriteContactSettingTString(NULL, "Chat", "HeaderOutgoing", pszText); + } + else DBDeleteContactSetting(NULL, "Chat", "HeaderOutgoing"); + + g_Settings.HighlightEnabled = IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHT) == BST_CHECKED?TRUE:FALSE; + DBWriteContactSettingByte(NULL, "Chat", "HighlightEnabled", (BYTE)g_Settings.HighlightEnabled); + + g_Settings.LoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED?TRUE:FALSE; + DBWriteContactSettingByte(NULL, "Chat", "LoggingEnabled", (BYTE)g_Settings.LoggingEnabled); + if ( g_Settings.LoggingEnabled ) + CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)g_Settings.pszLogDir); + + iLen = SendDlgItemMessage(hwndDlg,IDC_SPIN2,UDM_GETPOS,0,0); + DBWriteContactSettingWord(NULL, "Chat", "LogLimit", (WORD)iLen); + iLen = SendDlgItemMessage(hwndDlg,IDC_SPIN3,UDM_GETPOS,0,0); + DBWriteContactSettingWord(NULL, "Chat", "LoggingLimit", (WORD)iLen); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP)); + if (iLen > 0) { + pszText = (TCHAR *)mir_realloc(pszText, (iLen + 1) * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen+1); + DBWriteContactSettingTString(NULL, "Chat", "AddToGroup", pszText); + } + else DBWriteContactSettingString(NULL, "Chat", "AddToGroup", ""); + mir_free(pszText); + + iLen = SendDlgItemMessage(hwndDlg,IDC_SPIN4,UDM_GETPOS,0,0); + if (iLen > 0) + DBWriteContactSettingByte(NULL, "Chat", "NicklistRowDist", (BYTE)iLen); + else + DBDeleteContactSetting(NULL, "Chat", "NicklistRowDist"); + + FreeMsgLogBitmaps(); + LoadMsgLogBitmaps(); + SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + return TRUE; + } + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Popup options + +static INT_PTR CALLBACK DlgProcOptionsPopup(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_BKG, CPM_SETCOLOUR,0,g_Settings.crPUBkgColour); + SendDlgItemMessage(hwndDlg, IDC_TEXT, CPM_SETCOLOUR,0,g_Settings.crPUTextColour); + + if (g_Settings.iPopupStyle ==2) + CheckDlgButton(hwndDlg, IDC_RADIO2, BST_CHECKED); + else if (g_Settings.iPopupStyle ==3) + CheckDlgButton(hwndDlg, IDC_RADIO3, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_RADIO1, BST_CHECKED); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) ==BST_CHECKED?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) ==BST_CHECKED?TRUE:FALSE); + + SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_SETRANGE,0,MAKELONG(100,-1)); + SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_SETPOS,0,MAKELONG(g_Settings.iPopupTimeout,0)); + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_TIMEOUT) && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam != GetFocus())) + return 0; + + if (lParam != (LPARAM)NULL) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + switch (LOWORD(wParam)) { + + case IDC_RADIO1: + case IDC_RADIO2: + case IDC_RADIO3: + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) ==BST_CHECKED?TRUE:FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) ==BST_CHECKED?TRUE:FALSE); + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY ) { + int iLen; + + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2) == BST_CHECKED) + iLen = 2; + else if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED) + iLen = 3; + else + iLen = 1; + + g_Settings.iPopupStyle = iLen; + DBWriteContactSettingByte(NULL, "Chat", "PopupStyle", (BYTE)iLen); + + iLen = SendDlgItemMessage(hwndDlg,IDC_SPIN1,UDM_GETPOS,0,0); + g_Settings.iPopupTimeout = iLen; + DBWriteContactSettingWord(NULL, "Chat", "PopupTimeout", (WORD)iLen); + + g_Settings.crPUBkgColour = SendDlgItemMessage(hwndDlg,IDC_BKG,CPM_GETCOLOUR,0,0); + DBWriteContactSettingDword(NULL, "Chat", "PopupColorBG", (DWORD)SendDlgItemMessage(hwndDlg,IDC_BKG,CPM_GETCOLOUR,0,0)); + g_Settings.crPUTextColour = SendDlgItemMessage(hwndDlg,IDC_TEXT,CPM_GETCOLOUR,0,0); + DBWriteContactSettingDword(NULL, "Chat", "PopupColorText", (DWORD)SendDlgItemMessage(hwndDlg,IDC_TEXT,CPM_GETCOLOUR,0,0)); + return TRUE; + } + break; + } + return FALSE; +} + +static int OptionsInitialize(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = {0}; + + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS1); + odp.pszGroup = LPGEN("Message Sessions"); + odp.pszTitle = LPGEN("Group chats"); + odp.pszTab = LPGEN("General"); + odp.pfnDlgProc = DlgProcOptions1; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + odp.position = 910000001; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS2); + odp.pszTab = LPGEN("Chat Log"); + odp.pfnDlgProc = DlgProcOptions2; + Options_AddPage(wParam, &odp); + + if (PopUpInstalled) { + odp.position = 910000002; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONSPOPUP); + odp.pszTitle = LPGEN("Chat"); + odp.pszGroup = LPGEN("Popups"); + odp.pszTab = NULL; + odp.pfnDlgProc = DlgProcOptionsPopup; + Options_AddPage(wParam, &odp); + } + return 0; +} + +void LoadGlobalSettings(void) +{ + LOGFONT lf; + + g_Settings.LogLimitNames = DBGetContactSettingByte(NULL, "Chat", "LogLimitNames", 1); + g_Settings.ShowTime = DBGetContactSettingByte(NULL, "Chat", "ShowTimeStamp", 1); + g_Settings.TabsEnable = DBGetContactSettingByte(NULL, "Chat", "Tabs", 1); + g_Settings.TabsAtBottom = DBGetContactSettingByte(NULL, "Chat", "TabBottom", 0); + g_Settings.TabCloseOnDblClick = DBGetContactSettingByte(NULL, "Chat", "TabCloseOnDblClick", 0); + g_Settings.TabRestore = DBGetContactSettingByte(NULL, "Chat", "TabRestore", 0); + g_Settings.SoundsFocus = DBGetContactSettingByte(NULL, "Chat", "SoundsFocus", 0); + g_Settings.ShowTimeIfChanged = (BOOL)DBGetContactSettingByte(NULL, "Chat", "ShowTimeStampIfChanged", 0); + g_Settings.TimeStampEventColour = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TimeStampEventColour", 0); + g_Settings.iEventLimit = DBGetContactSettingWord(NULL, "Chat", "LogLimit", 100); + g_Settings.dwIconFlags = DBGetContactSettingDword(NULL, "Chat", "IconFlags", 0x0000); + g_Settings.dwTrayIconFlags = DBGetContactSettingDword(NULL, "Chat", "TrayIconFlags", 0x1000); + g_Settings.dwPopupFlags = DBGetContactSettingDword(NULL, "Chat", "PopupFlags", 0x0000); + g_Settings.LoggingLimit = DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100); + g_Settings.LoggingEnabled = (BOOL)DBGetContactSettingByte(NULL, "Chat", "LoggingEnabled", 0); + g_Settings.FlashWindow = (BOOL)DBGetContactSettingByte(NULL, "Chat", "FlashWindow", 0); + g_Settings.HighlightEnabled = (BOOL)DBGetContactSettingByte(NULL, "Chat", "HighlightEnabled", 1); + g_Settings.crUserListColor = DBGetContactSettingDword(NULL, "ChatFonts", "Font18Col", RGB(0,0,0)); + g_Settings.crUserListBGColor = DBGetContactSettingDword(NULL, "Chat", "ColorNicklistBG", GetSysColor(COLOR_WINDOW)); + g_Settings.crUserListSelectedBGColor = DBGetContactSettingDword(NULL, "Chat", "ColorNicklistSelectedBG", GetSysColor(COLOR_HIGHLIGHT)); + g_Settings.crUserListHeadingsColor = DBGetContactSettingDword(NULL, "ChatFonts", "Font19Col", RGB(170,170,170)); + g_Settings.crLogBackground = DBGetContactSettingDword(NULL, "Chat", "ColorLogBG", GetSysColor(COLOR_WINDOW)); + g_Settings.StripFormat = (BOOL)DBGetContactSettingByte(NULL, "Chat", "StripFormatting", 0); + g_Settings.TrayIconInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrayIconInactiveOnly", 1); + g_Settings.PopUpInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "PopUpInactiveOnly", 1); + g_Settings.AddColonToAutoComplete = (BOOL)DBGetContactSettingByte(NULL, "Chat", "AddColonToAutoComplete", 1); + g_Settings.iPopupStyle = DBGetContactSettingByte(NULL, "Chat", "PopupStyle", 1); + g_Settings.iPopupTimeout = DBGetContactSettingWord(NULL, "Chat", "PopupTimeout", 3); + g_Settings.crPUBkgColour = DBGetContactSettingDword(NULL, "Chat", "PopupColorBG", GetSysColor(COLOR_WINDOW)); + g_Settings.crPUTextColour = DBGetContactSettingDword(NULL, "Chat", "PopupColorText", 0); + g_Settings.ShowContactStatus = DBGetContactSettingByte(NULL, "Chat", "ShowContactStatus", 0); + g_Settings.ContactStatusFirst = DBGetContactSettingByte(NULL, "Chat", "ContactStatusFirst", 0); + + InitSetting( &g_Settings.pszTimeStamp, "HeaderTime", _T("[%H:%M]")); + InitSetting( &g_Settings.pszTimeStampLog, "LogTimestamp", _T("[%d %b %y %H:%M]")); + InitSetting( &g_Settings.pszIncomingNick, "HeaderIncoming", _T("%n:")); + InitSetting( &g_Settings.pszOutgoingNick, "HeaderOutgoing", _T("%n:")); + InitSetting( &g_Settings.pszHighlightWords, "HighlightWords", _T("%m")); + + { + TCHAR pszTemp[MAX_PATH]; + DBVARIANT dbv; + g_Settings.pszLogDir = (TCHAR *)mir_realloc(g_Settings.pszLogDir, MAX_PATH*sizeof(TCHAR)); + if (!DBGetContactSettingTString(NULL, "Chat", "LogDirectory", &dbv)) { + lstrcpyn(pszTemp, dbv.ptszVal, MAX_PATH); + DBFreeVariant(&dbv); + } + else { + TCHAR *tmpPath = Utils_ReplaceVarsT(_T("%miranda_logpath%\\Chat")); + lstrcpyn(pszTemp, tmpPath, SIZEOF(pszTemp)-1); + mir_free(tmpPath); + } + + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)pszTemp, (LPARAM)g_Settings.pszLogDir); + } + + g_Settings.LogIndentEnabled = (DBGetContactSettingByte(NULL, "Chat", "LogIndentEnabled", 1) != 0)?TRUE:FALSE; + + if ( g_Settings.MessageBoxFont ) + DeleteObject( g_Settings.MessageBoxFont ); + LoadMsgDlgFont( 17, &lf, NULL ); + g_Settings.MessageBoxFont = CreateFontIndirect(&lf); + + if ( g_Settings.UserListFont ) + DeleteObject(g_Settings.UserListFont); + LoadMsgDlgFont(18, &lf, NULL); + g_Settings.UserListFont = CreateFontIndirect(&lf); + + if (g_Settings.UserListHeadingsFont) + DeleteObject(g_Settings.UserListHeadingsFont); + LoadMsgDlgFont(19, &lf, NULL); + g_Settings.UserListHeadingsFont = CreateFontIndirect(&lf); + if (hListBkgBrush != NULL) { + DeleteObject(hListBkgBrush); + } + hListBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, "Chat", "ColorNicklistBG", GetSysColor(COLOR_WINDOW))); + if (hListSelectedBkgBrush != NULL) { + DeleteObject(hListSelectedBkgBrush); + } + hListSelectedBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, "Chat", "ColorNicklistSelectedBG", GetSysColor(COLOR_HIGHLIGHT))); +} + +static void FreeGlobalSettings(void) +{ + mir_free(g_Settings.pszTimeStamp); + mir_free(g_Settings.pszTimeStampLog); + mir_free(g_Settings.pszIncomingNick); + mir_free(g_Settings.pszOutgoingNick); + mir_free(g_Settings.pszHighlightWords); + mir_free(g_Settings.pszLogDir); + if ( g_Settings.MessageBoxFont ) + DeleteObject( g_Settings.MessageBoxFont ); + if ( g_Settings.UserListFont ) + DeleteObject( g_Settings.UserListFont ); + if ( g_Settings.UserListHeadingsFont ) + DeleteObject( g_Settings.UserListHeadingsFont ); +} + +int OptionsInit(void) +{ + LOGFONT lf; + + g_hOptions = HookEvent(ME_OPT_INITIALISE, OptionsInitialize); + + LoadLogFonts(); + LoadMsgDlgFont(18, &lf, NULL); + lstrcpy(lf.lfFaceName, _T("MS Shell Dlg")); + lf.lfUnderline = lf.lfItalic = lf.lfStrikeOut = 0; + lf.lfHeight = -17; + lf.lfWeight = FW_BOLD; + g_Settings.NameFont = CreateFontIndirect(&lf); + g_Settings.UserListFont = NULL; + g_Settings.UserListHeadingsFont = NULL; + g_Settings.MessageBoxFont = NULL; + g_Settings.iSplitterX = DBGetContactSettingWord(NULL, "Chat", "SplitterX", 105); + g_Settings.iSplitterY = DBGetContactSettingWord(NULL, "Chat", "SplitterY", 90); + g_Settings.iX = DBGetContactSettingDword(NULL, "Chat", "roomx", -1); + g_Settings.iY = DBGetContactSettingDword(NULL, "Chat", "roomy", -1); + g_Settings.iWidth = DBGetContactSettingDword(NULL, "Chat", "roomwidth", -1); + g_Settings.iHeight = DBGetContactSettingDword(NULL, "Chat", "roomheight", -1); + LoadGlobalSettings(); + + SkinAddNewSoundEx("ChatMessage", LPGEN("Group chats"), LPGEN("Incoming message")); + SkinAddNewSoundEx("ChatHighlight", LPGEN("Group chats"), LPGEN("Message is highlighted")); + SkinAddNewSoundEx("ChatAction", LPGEN("Group chats"), LPGEN("User has performed an action")); + SkinAddNewSoundEx("ChatJoin", LPGEN("Group chats"), LPGEN("User has joined")); + SkinAddNewSoundEx("ChatPart", LPGEN("Group chats"), LPGEN("User has left")); + SkinAddNewSoundEx("ChatKick", LPGEN("Group chats"), LPGEN("User has kicked some other user")); + SkinAddNewSoundEx("ChatMode", LPGEN("Group chats"), LPGEN("User's status was changed")); + SkinAddNewSoundEx("ChatNick", LPGEN("Group chats"), LPGEN("User has changed name")); + SkinAddNewSoundEx("ChatNotice", LPGEN("Group chats"), LPGEN("User has sent a notice")); + SkinAddNewSoundEx("ChatQuit", LPGEN("Group chats"), LPGEN("User has disconnected")); + SkinAddNewSoundEx("ChatTopic", LPGEN("Group chats"), LPGEN("The topic has been changed")); + + if ( g_Settings.LoggingEnabled ) + CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)g_Settings.pszLogDir); + { + LOGFONT lf; + HFONT hFont; + int iText; + + LoadMsgDlgFont(0, &lf, NULL); + hFont = CreateFontIndirect(&lf); + iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)),hFont, TRUE); + DeleteObject(hFont); + g_Settings.LogTextIndent = iText; + g_Settings.LogTextIndent = g_Settings.LogTextIndent*12/10; + } + + return 0; +} + +int OptionsUnInit(void) +{ + FreeGlobalSettings(); + UnhookEvent(g_hOptions); + DeleteObject(hEditBkgBrush); + DeleteObject(hListBkgBrush); + DeleteObject(hListSelectedBkgBrush); + DeleteObject(g_Settings.NameFont); + return 0; +} diff --git a/src/core/stdchat/src/resource.h b/src/core/stdchat/src/resource.h new file mode 100644 index 0000000000..f95fa7dd01 --- /dev/null +++ b/src/core/stdchat/src/resource.h @@ -0,0 +1,141 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by chat.rc +// +#define IDD_CHANNEL 101 +#define IDD_OPTIONS1 102 +#define IDD_OPTIONS2 103 +#define IDD_FILTER 105 +#define IDD_OPTIONSPOPUP 106 +#define IDI_BUNDERLINE 120 +#define IDI_BBOLD 121 +#define IDI_BITALICS 122 +#define IDI_BSMILEY 123 +#define IDI_TOPICBUT 124 +#define IDI_BKGCOLOR 125 +#define IDI_CHANMGR 126 +#define IDI_COLOR 127 +#define IDI_FILTER 128 +#define IDI_HISTORY 129 +#define IDI_NICKLIST 130 +#define IDI_JOIN 131 +#define IDI_PART 132 +#define IDI_QUIT 133 +#define IDI_KICK 134 +#define IDI_NICK 135 +#define IDI_NOTICE 136 +#define IDI_MESSAGE 137 +#define IDI_MESSAGEOUT 138 +#define IDI_TOPIC 139 +#define IDI_INFO 140 +#define IDI_ADDSTATUS 141 +#define IDI_REMSTATUS 142 +#define IDI_ACTION 143 +#define IDI_HIGHLIGHT 144 +#define IDI_BLANK 146 +#define IDI_TAG1 149 +#define IDI_TAG2 150 +#define IDR_MENU 151 +#define IDD_COLORCHOOSER 152 +#define IDI_STATUS3 153 +#define IDI_STATUS2 154 +#define IDI_STATUS4 155 +#define IDI_STATUS1 156 +#define IDI_STATUS0 157 +#define IDI_STATUS5 158 +#define IDI_CLOSE 159 +#define IDI_OVERLAY 160 +#define IDI_NICKLIST2 161 +#define IDI_FILTER2 162 +#define IDC_LOG 1005 +#define IDC_SPLITTERX 1006 +#define IDC_SMILEY 1007 +#define IDC_SPLITTERY 1008 +#define IDC_MESSAGE 1009 +#define IDC_BOLD 1010 +#define IDC_ITALICS 1011 +#define IDC_UNDERLINE 1012 +#define IDC_FILTER 1013 +#define IDC_CHANMGR 1014 +#define IDC_SHOWNICKLIST 1016 +#define IDC_COLOR 1017 +#define IDC_BKGCOLOR 1019 +#define IDC_CHECKBOXES 1021 +#define IDC_NICKLISTBKG 1021 +#define IDC_HISTORY 1022 +#define IDC_CLOSE 1023 +#define IDC_NICKROW 1024 +#define IDC_LOGLIMIT 1024 +#define IDC_NICKROW2 1025 +#define IDC_SPIN1 1028 +#define IDC_SPIN2 1029 +#define IDC_SPIN3 1030 +#define IDC_SPIN4 1031 +#define IDC_FONTLIST 1032 +#define IDC_CHOOSEFONT 1034 +#define IDC_FONTCOLOR 1035 +#define IDC_MESSAGEBKG 1036 +#define IDC_LOGBKG 1037 +#define IDC_HIGHLIGHTWORDS 1040 +#define IDC_INSTAMP 1041 +#define IDC_OUTSTAMP 1043 +#define IDC_TIMESTAMP 1046 +#define IDC_FONTCHOOSE 1047 +#define IDC_LOGDIRECTORY 1048 +#define IDC_LIMIT 1050 +#define IDC_LOGTIMESTAMP 1051 +#define IDC_GROUP 1057 +#define IDC_RADIO1 1061 +#define IDC_RADIO2 1062 +#define IDC_RADIO3 1063 +#define IDC_TEXT 1064 +#define IDC_BKG 1065 +#define IDC_TIMEOUT 1067 +#define IDC_HIGHLIGHT 1068 +#define IDC_TEXTO 1069 +#define IDC_LOGGING 1069 +#define IDC_COLORTEXT 1070 +#define IDC_LIST 1072 +#define IDC_TAB 1074 +#define IDC_1 1075 +#define IDC_2 1076 +#define IDC_3 1077 +#define IDC_4 1078 +#define IDC_5 1079 +#define IDC_6 1080 +#define IDC_7 1081 +#define IDC_8 1082 +#define IDC_9 1083 +#define IDC_10 1084 +#define IDC_11 1085 +#define ID_MESS 40001 +#define ID_NEW 40002 +#define ID_CURR 40003 +#define ID_COPY 40004 +#define ID_COPYALL 40006 +#define ID_CLEARLOG 40009 +#define ID_MESSAGE_UNDO 40013 +#define ID_MESSAGE_COPY 40014 +#define ID_MESSAGE_CUT 40015 +#define ID_MESSAGE_CLEAR 40017 +#define ID_MESSAGE_SELECTALL 40018 +#define ID_MESSAGE_REDO 40019 +#define ID_MESSAGE_PASTE 40020 +#define ID_CLOSE 40022 +#define ID_CLOSEOTHER 40023 +#define ID_LOCKPOSITION 40024 +#define ID_Menu 40026 +#define ID_SEARCH_GOOGLE 40027 +#define ID_SEARCH_WIKIPEDIA 40028 +#define ID_WIKIPEDIA_ 40029 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 163 +#define _APS_NEXT_COMMAND_VALUE 40030 +#define _APS_NEXT_CONTROL_VALUE 1076 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/core/stdchat/src/richutil.cpp b/src/core/stdchat/src/richutil.cpp new file mode 100644 index 0000000000..1c5143b17c --- /dev/null +++ b/src/core/stdchat/src/richutil.cpp @@ -0,0 +1,293 @@ +/* +SRMM + +Copyright 2000-2005 Miranda ICQ/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 +#include +#include +#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. +*/ +// list crap +typedef struct _RList { + struct _RList *next; + struct _RList *prev; + TRichUtil *data; +} RList; + +TRichUtil *rlist_find(RList *list, HWND hwnd); +RList *rlist_append(RList *list, TRichUtil *data); +RList *rlist_remove_link(RList *list, const RList *link); +RList *rlist_remove(RList * list, TRichUtil *data); +void rlist_free(RList * list); + +TRichUtil *rlist_find(RList *list, HWND hwnd) { + RList *n; + + if (hwnd==NULL) return NULL; + for (n=list; n!=NULL; n=n->next) { + if (n->data&&n->data->hwnd==hwnd) return n->data; + } + return NULL; +} + +RList *rlist_append(RList *list, TRichUtil *data) { + RList *n; + RList *new_list = (RList *)malloc(sizeof(RList)); + RList *attach_to = NULL; + + new_list->next = NULL; + new_list->data = data; + for (n=list; n!=NULL; n=n->next) { + attach_to = n; + } + if (attach_to==NULL) { + new_list->prev = NULL; + return new_list; + } + else { + new_list->prev = attach_to; + attach_to->next = new_list; + return list; + } +} + +RList *rlist_remove_link(RList *list, const RList *link) { + if (!link) + return list; + + if (link->next) + link->next->prev = link->prev; + if (link->prev) + link->prev->next = link->next; + if (link==list) + list = link->next; + return list; +} + +RList *rlist_remove(RList *list, TRichUtil *data) { + RList *n; + + for (n=list; n!=NULL; n=n->next) { + if (n->data==data) { + RList *newlist = rlist_remove_link(list, n); + free(n); + return newlist; + } + } + return list; +} + +void rlist_free(RList *list) { + RList *n = list; + + while (n!=NULL) { + RList *next = n->next; + free(n); + n = next; + } +} + +// UxTheme Stuff +static HMODULE mTheme = 0; +static HANDLE (WINAPI *MyOpenThemeData)(HWND,LPCWSTR) = 0; +static HRESULT (WINAPI *MyCloseThemeData)(HANDLE) = 0; +static BOOL (WINAPI *MyIsThemeActive)() = 0; +static HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE,HDC,int,int,const RECT*,const RECT *) = 0; +static HRESULT (WINAPI *MyGetThemeBackgroundContentRect)(HANDLE,HDC,int,int,const RECT *,RECT *) = 0; +static HRESULT (WINAPI *MyDrawThemeParentBackground)(HWND,HDC,RECT*) = 0; +static BOOL (WINAPI *MyIsThemeBackgroundPartiallyTransparent)(HANDLE,int,int) = 0; + +static RList *slist = NULL; +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() { + mTheme = RIsWinVerXPPlus()?LoadLibraryA("uxtheme.dll"):0; + InitializeCriticalSection(&csRich); + if (!mTheme) return; + MyOpenThemeData = (HANDLE (WINAPI *)(HWND, LPCWSTR))GetProcAddress(mTheme, "OpenThemeData"); + MyCloseThemeData = (HRESULT (WINAPI *)(HANDLE))GetProcAddress(mTheme, "CloseThemeData"); + MyIsThemeActive = (BOOL (WINAPI *)())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() { + DeleteCriticalSection(&csRich); + if (mTheme) { + FreeLibrary(mTheme); + } +} + +int RichUtil_SubClass(HWND hwndEdit) { + if (IsWindow(hwndEdit)) { + TRichUtil *ru = (TRichUtil*)malloc(sizeof(TRichUtil)); + + ZeroMemory(ru, sizeof(TRichUtil)); + ru->hwnd = hwndEdit; + ru->hasUglyBorder = 0; + EnterCriticalSection(&csRich); + slist = rlist_append(slist, ru); + LeaveCriticalSection(&csRich); + SetWindowLongPtr(ru->hwnd, GWLP_USERDATA, (LONG_PTR)ru); // Ugly hack + 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 = rlist_find(slist, hwnd); + LeaveCriticalSection(&csRich); + switch(msg) { + 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); + + 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 (!IsWindowEnabled(hwnd)) + nState = ETS_DISABLED; + else if(SendMessage(hwnd, EM_GETOPTIONS, 0, 0) & ECO_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; + HDC hdc = GetDC(GetParent(hwnd)); + + ZeroMemory(&rcClient, sizeof(RECT)); + 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; + CopyRect(&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_DESTROY: + { + 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); + slist = rlist_remove(slist, ru); + LeaveCriticalSection(&csRich); + if (ru) 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/src/core/stdchat/src/richutil.h b/src/core/stdchat/src/richutil.h new file mode 100644 index 0000000000..dff6a53915 --- /dev/null +++ b/src/core/stdchat/src/richutil.h @@ -0,0 +1,55 @@ +/* +SRMM + +Copyright 2000-2005 Miranda ICQ/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 + +#define RWinVerMajor() LOBYTE(LOWORD(GetVersion())) +#define RIsWinVerXPPlus() (RWinVerMajor()>=5 && LOWORD(GetVersion())!=5) + +#ifndef WM_THEMECHANGED +#define WM_THEMECHANGED 0x031A +#endif +#ifndef EP_EDITTEXT +#define EP_EDITTEXT 1 +#endif +#ifndef ETS_NORMAL +#define ETS_NORMAL 1 +#endif +#ifndef ETS_DISABLED +#define ETS_DISABLED 4 +#endif +#ifndef ETS_READONLY +#define ETS_READONLY 6 +#endif + +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/src/core/stdchat/src/services.cpp b/src/core/stdchat/src/services.cpp new file mode 100644 index 0000000000..06e4f20cc8 --- /dev/null +++ b/src/core/stdchat/src/services.cpp @@ -0,0 +1,874 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-2010 Miranda ICQ/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 "chat.h" + +#include "m_fontservice.h" + +extern HICON hIcons[30]; +extern HIMAGELIST hImageList; +extern HIMAGELIST hIconsList; +extern BOOL SmileyAddInstalled; +extern BOOL PopUpInstalled; +extern BOOL IEviewInstalled; + +HANDLE hSendEvent; +HANDLE hBuildMenuEvent ; +HANDLE g_hModulesLoaded; +HANDLE g_hSystemPreShutdown; +HANDLE hJoinMenuItem, hLeaveMenuItem; +HANDLE g_hHookPrebuildMenu; +HANDLE g_hIconsChanged, g_hFontsChanged; +HANDLE g_hSmileyOptionsChanged = NULL; +HANDLE g_hIconsChanged2; +SESSION_INFO g_TabSession; +CRITICAL_SECTION cs; + +void RegisterFonts( void ); + +static HANDLE + hServiceRegister = NULL, + hServiceNewChat = NULL, + hServiceAddEvent = NULL, + hServiceGetAddEventPtr = NULL, + hServiceGetInfo = NULL, + hServiceGetCount = NULL, + hEventPrebuildMenu = NULL, + hEventDoubleclicked = NULL, + hEventJoinChat = NULL, + hEventLeaveChat = NULL; + +#ifdef _WIN64 + +#define SIZEOF_STRUCT_GCREGISTER_V1 40 +#define SIZEOF_STRUCT_GCWINDOW_V1 48 +#define SIZEOF_STRUCT_GCEVENT_V1 76 +#define SIZEOF_STRUCT_GCEVENT_V2 80 + +#else + +#define SIZEOF_STRUCT_GCREGISTER_V1 28 +#define SIZEOF_STRUCT_GCWINDOW_V1 32 +#define SIZEOF_STRUCT_GCEVENT_V1 44 +#define SIZEOF_STRUCT_GCEVENT_V2 48 + +#endif + +void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground) +{ + if (!si) + return; + + if ( g_Settings.TabsEnable) { + // the session is not the current tab, so we copy the necessary + // details into the SESSION_INFO for the tabbed window + if (!si->hWnd) { + g_TabSession.iEventCount = si->iEventCount; + g_TabSession.iStatusCount = si->iStatusCount; + g_TabSession.iType = si->iType; + g_TabSession.nUsersInNicklist = si->nUsersInNicklist; + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + g_TabSession.pMe = si->pMe; + g_TabSession.dwFlags = si->dwFlags; + g_TabSession.pStatuses = si->pStatuses; + g_TabSession.ptszID = si->ptszID; + g_TabSession.pszModule = si->pszModule; + g_TabSession.ptszName = si->ptszName; + g_TabSession.ptszStatusbarText = si->ptszStatusbarText; + g_TabSession.ptszTopic = si->ptszTopic; + g_TabSession.pUsers = si->pUsers; + g_TabSession.hContact = si->hContact; + g_TabSession.wStatus = si->wStatus; + g_TabSession.lpCommands = si->lpCommands; + g_TabSession.lpCurrentCommand = NULL; + } + + //Do we need to create a tabbed window? + if (g_TabSession.hWnd == NULL) + g_TabSession.hWnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), NULL, RoomWndProc, (LPARAM)&g_TabSession); + + SetWindowLongPtr(g_TabSession.hWnd, GWL_EXSTYLE, GetWindowLongPtr(g_TabSession.hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); + + // if the session was not the current tab we need to tell the window to + // redraw to show the contents of the current SESSION_INFO + if (!si->hWnd) { + SM_SetTabbedWindowHwnd(si, g_TabSession.hWnd); + SendMessage(g_TabSession.hWnd, GC_ADDTAB, -1, (LPARAM)si); + SendMessage(g_TabSession.hWnd, GC_TABCHANGE, 0, (LPARAM)&g_TabSession); + } + + SetActiveSession(si->ptszID, si->pszModule); + + if (!IsWindowVisible(g_TabSession.hWnd) || wp == WINDOW_HIDDEN) + SendMessage(g_TabSession.hWnd, GC_EVENT_CONTROL + WM_USER + 500, wp, 0); + else { + if (IsIconic(g_TabSession.hWnd)) + ShowWindow(g_TabSession.hWnd, SW_NORMAL); + + PostMessage(g_TabSession.hWnd, WM_SIZE, 0, 0); + if (si->iType != GCW_SERVER) + SendMessage(g_TabSession.hWnd, GC_UPDATENICKLIST, 0, 0); + else + SendMessage(g_TabSession.hWnd, GC_UPDATETITLE, 0, 0); + SendMessage(g_TabSession.hWnd, GC_REDRAWLOG, 0, 0); + SendMessage(g_TabSession.hWnd, GC_UPDATESTATUSBAR, 0, 0); + ShowWindow(g_TabSession.hWnd, SW_SHOW); + if (bSetForeground) + SetForegroundWindow(g_TabSession.hWnd); + } + SendMessage(g_TabSession.hWnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(GetDlgItem(g_TabSession.hWnd, IDC_MESSAGE)); + return; + } + + //Do we need to create a window? + if (si->hWnd == NULL) + si->hWnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), NULL, RoomWndProc, (LPARAM)si); + + SetWindowLongPtr(si->hWnd, GWL_EXSTYLE, GetWindowLongPtr(si->hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); + if (!IsWindowVisible(si->hWnd) || wp == WINDOW_HIDDEN) + SendMessage(si->hWnd, GC_EVENT_CONTROL + WM_USER + 500, wp, 0); + else { + if (IsIconic(si->hWnd)) + ShowWindow(si->hWnd, SW_NORMAL); + ShowWindow(si->hWnd, SW_SHOW); + SetForegroundWindow(si->hWnd); + } + + SendMessage(si->hWnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(GetDlgItem(si->hWnd, IDC_MESSAGE)); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Post-load event hooks + +static int FontsChanged(WPARAM wParam,LPARAM lParam) +{ + LoadLogFonts(); + { + LOGFONT lf; + HFONT hFont; + int iText; + + LoadMsgDlgFont(0, &lf, NULL); + hFont = CreateFontIndirect(&lf); + iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)),hFont, TRUE); + DeleteObject(hFont); + g_Settings.LogTextIndent = iText; + g_Settings.LogTextIndent = g_Settings.LogTextIndent*12/10; + g_Settings.LogIndentEnabled = (DBGetContactSettingByte(NULL, "Chat", "LogIndentEnabled", 1) != 0)?TRUE:FALSE; + } + MM_FontsChanged(); + MM_FixColors(); + SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + return 0; +} + +static int IconsChanged(WPARAM wParam,LPARAM lParam) +{ + FreeMsgLogBitmaps(); + + LoadLogIcons(); + LoadMsgLogBitmaps(); + MM_IconsChanged(); + SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, FALSE); + return 0; +} + +static int PreShutdown(WPARAM wParam,LPARAM lParam) +{ + SM_BroadcastMessage(NULL, GC_CLOSEWINDOW, 0, 1, FALSE); + + SM_RemoveAll(); + MM_RemoveAll(); + TabM_RemoveAll(); + return 0; +} + +static int SmileyOptionsChanged(WPARAM wParam,LPARAM lParam) +{ + SM_BroadcastMessage(NULL, GC_REDRAWLOG, 0, 1, FALSE); + return 0; +} + +static int ModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char* mods[3] = { "Chat", "ChatFonts" }; + CallService( "DBEditorpp/RegisterModule", (WPARAM)mods, 2 ); + + RegisterFonts(); + AddIcons(); + LoadIcons(); + { + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.position = -2000090001; + mi.flags = CMIF_DEFAULT | CMIF_ICONFROMICOLIB; + mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_JOIN ); + mi.pszName = LPGEN("&Join"); + mi.pszService = "GChat/JoinChat"; + hJoinMenuItem = Menu_AddContactMenuItem(&mi); + + mi.position = -2000090000; + mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_LEAVE ); + mi.flags = CMIF_NOTOFFLINE | CMIF_ICONFROMICOLIB; + mi.pszName = LPGEN("&Leave"); + mi.pszService = "GChat/LeaveChat"; + hLeaveMenuItem = Menu_AddContactMenuItem(&mi); + } + + g_hFontsChanged = HookEvent(ME_FONT_RELOAD, FontsChanged); + g_hIconsChanged2 = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged); + + if ( ServiceExists( MS_SMILEYADD_SHOWSELECTION )) { + SmileyAddInstalled = TRUE; + g_hSmileyOptionsChanged = HookEvent(ME_SMILEYADD_OPTIONSCHANGED, SmileyOptionsChanged); + } + if ( ServiceExists( MS_POPUP_ADDPOPUPEX )) + PopUpInstalled = TRUE; + + if ( ServiceExists( MS_IEVIEW_WINDOW )) + IEviewInstalled = TRUE; + + CList_SetAllOffline(TRUE, NULL); + return 0; +} + +static INT_PTR Service_GetCount(WPARAM wParam,LPARAM lParam) +{ + int i; + + if (!lParam) + return -1; + + EnterCriticalSection(&cs); + + i = SM_GetCount((char *)lParam); + + LeaveCriticalSection(&cs); + return i; +} + +static INT_PTR Service_GetInfo(WPARAM wParam,LPARAM lParam) +{ + GC_INFO * gci = (GC_INFO *) lParam; + SESSION_INFO* si = NULL; + + if (!gci || !gci->pszModule) + return 1; + + EnterCriticalSection(&cs); + + if ( gci->Flags&BYINDEX) + si = SM_FindSessionByIndex( gci->pszModule, gci->iItem ); + else + si = SM_FindSession( gci->pszID, gci->pszModule ); + + if ( si ) { + if ( gci->Flags & DATA ) gci->dwItemData = si->dwItemData; + if ( gci->Flags & HCONTACT ) gci->hContact = si->hContact; + if ( gci->Flags & TYPE ) gci->iType = si->iType; + if ( gci->Flags & COUNT ) gci->iCount = si->nUsersInNicklist; + if ( gci->Flags & USERS ) gci->pszUsers = SM_GetUsers(si); + + if ( si->dwFlags & GC_UNICODE ) { + if ( gci->Flags & ID ) gci->pszID = si->ptszID; + if ( gci->Flags & NAME ) gci->pszName = si->ptszName; + } + else { + if ( gci->Flags & ID ) gci->pszID = ( TCHAR* )si->pszID; + if ( gci->Flags & NAME ) gci->pszName = ( TCHAR* )si->pszName; + } + + LeaveCriticalSection(&cs); + return 0; + } + + LeaveCriticalSection(&cs); + return 1; +} + +static INT_PTR Service_Register(WPARAM wParam, LPARAM lParam) +{ + + GCREGISTER *gcr = (GCREGISTER *)lParam; + MODULEINFO * mi = NULL; + if ( gcr == NULL) + return GC_REGISTER_ERROR; + + if (gcr->cbSize != SIZEOF_STRUCT_GCREGISTER_V1) + return GC_REGISTER_WRONGVER; + + EnterCriticalSection(&cs); + + mi = MM_AddModule( gcr->pszModule ); + if ( mi ) { + mi->ptszModDispName = a2tf( gcr->ptszModuleDispName, gcr->dwFlags ); + mi->bBold = gcr->dwFlags&GC_BOLD; + mi->bUnderline = gcr->dwFlags&GC_UNDERLINE ; + mi->bItalics = gcr->dwFlags&GC_ITALICS ; + mi->bColor = gcr->dwFlags&GC_COLOR ; + mi->bBkgColor = gcr->dwFlags&GC_BKGCOLOR ; + mi->bAckMsg = gcr->dwFlags&GC_ACKMSG ; + mi->bChanMgr = gcr->dwFlags&GC_CHANMGR ; + mi->iMaxText= gcr->iMaxText; + mi->nColorCount = gcr->nColors; + if ( gcr->nColors > 0) { + mi->crColors = (COLORREF *)mir_alloc(sizeof(COLORREF) * gcr->nColors); + memcpy(mi->crColors, gcr->pColors, sizeof(COLORREF) * gcr->nColors); + } + + mi->OnlineIconIndex = ImageList_AddIcon(hIconsList, LoadSkinnedProtoIcon(gcr->pszModule, ID_STATUS_ONLINE)); + mi->hOnlineIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT); + + mi->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1)); + ImageList_AddIcon(hIconsList, mi->hOnlineTalkIcon); + + mi->OfflineIconIndex = ImageList_AddIcon(hIconsList, LoadSkinnedProtoIcon(gcr->pszModule, ID_STATUS_OFFLINE)); + mi->hOfflineIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT); + + mi->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1)); + ImageList_AddIcon(hIconsList, mi->hOfflineTalkIcon); + + mi->pszHeader = Log_CreateRtfHeader(mi); + + CheckColorsInModule((char*)gcr->pszModule); + CList_SetAllOffline(TRUE, gcr->pszModule); + + LeaveCriticalSection(&cs); + return 0; + } + + LeaveCriticalSection(&cs); + return GC_REGISTER_ERROR; +} + +static INT_PTR Service_NewChat(WPARAM wParam, LPARAM lParam) +{ + MODULEINFO* mi; + GCSESSION *gcw =(GCSESSION *)lParam; + if (gcw== NULL) + return GC_NEWSESSION_ERROR; + + if (gcw->cbSize != SIZEOF_STRUCT_GCWINDOW_V1) + return GC_NEWSESSION_WRONGVER; + + EnterCriticalSection(&cs); + + if (( mi = MM_FindModule( gcw->pszModule )) != NULL ) { + TCHAR* ptszID = a2tf( gcw->ptszID, gcw->dwFlags ); + SESSION_INFO* si = SM_AddSession( ptszID, gcw->pszModule); + + // create a new session and set the defaults + if ( si != NULL ) { + TCHAR szTemp[256]; + + si->dwItemData = gcw->dwItemData; + if ( gcw->iType != GCW_SERVER ) + si->wStatus = ID_STATUS_ONLINE; + si->iType = gcw->iType; + si->dwFlags = gcw->dwFlags; + si->ptszName = a2tf( gcw->ptszName, gcw->dwFlags ); + si->ptszStatusbarText = a2tf( gcw->ptszStatusbarText, gcw->dwFlags ); + si->iSplitterX = g_Settings.iSplitterX; + si->iSplitterY = g_Settings.iSplitterY; + si->iLogFilterFlags = (int)DBGetContactSettingDword(NULL, "Chat", "FilterFlags", 0x03E0); + si->bFilterEnabled = DBGetContactSettingByte(NULL, "Chat", "FilterEnabled", 0); + si->bNicklistEnabled = DBGetContactSettingByte(NULL, "Chat", "ShowNicklist", 1); + if ( !( gcw->dwFlags & GC_UNICODE )) { + si->pszID = mir_strdup( gcw->pszID ); + si->pszName = mir_strdup( gcw->pszName ); + } + + if ( mi->bColor ) { + si->iFG = 4; + si->bFGSet = TRUE; + } + if ( mi->bBkgColor ) { + si->iBG = 2; + si->bBGSet = TRUE; + } + if (si->iType == GCW_SERVER) + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("Server: %s"), si->ptszName); + else + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), si->ptszName); + si->hContact = CList_AddRoom( gcw->pszModule, ptszID, szTemp, si->iType); + DBWriteContactSettingString(si->hContact, si->pszModule , "Topic", ""); + DBDeleteContactSetting(si->hContact, "CList", "StatusMsg"); + if (si->ptszStatusbarText) + DBWriteContactSettingTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText); + else + DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", ""); + } + else { + SESSION_INFO* si2 = SM_FindSession( ptszID, gcw->pszModule ); + if ( si2 ) { + if (si2->hWnd) + g_TabSession.nUsersInNicklist = 0; + + UM_RemoveAll(&si2->pUsers); + TM_RemoveAll(&si2->pStatuses); + + si2->iStatusCount = 0; + si2->nUsersInNicklist = 0; + + if ( !g_Settings.TabsEnable ) { + if (si2->hWnd ) + RedrawWindow(GetDlgItem(si2->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + } + else if (g_TabSession.hWnd) + RedrawWindow(GetDlgItem(g_TabSession.hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + } } + + LeaveCriticalSection(&cs); + mir_free( ptszID ); + return 0; + } + + LeaveCriticalSection(&cs); + return GC_NEWSESSION_ERROR; +} + +static int DoControl(GCEVENT * gce, WPARAM wp) +{ + if ( gce->pDest->iType == GC_EVENT_CONTROL ) { + switch (wp) { + case WINDOW_HIDDEN: + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if (si) { + si->bInitDone = TRUE; + SetActiveSession(si->ptszID, si->pszModule); + if (si->hWnd) + ShowRoom(si, wp, FALSE); + } + } + return 0; + + case WINDOW_MINIMIZE: + case WINDOW_MAXIMIZE: + case WINDOW_VISIBLE: + case SESSION_INITDONE: + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if (si) { + si->bInitDone = TRUE; + if (wp != SESSION_INITDONE || DBGetContactSettingByte(NULL, "Chat", "PopupOnJoin", 0) == 0) + ShowRoom(si, wp, TRUE); + return 0; + } } + break; + + case SESSION_OFFLINE: + SM_SetOffline(gce->pDest->ptszID, gce->pDest->pszModule); + // fall through + + case SESSION_ONLINE: + SM_SetStatus( gce->pDest->ptszID, gce->pDest->pszModule, wp==SESSION_ONLINE?ID_STATUS_ONLINE:ID_STATUS_OFFLINE); + break; + + case WINDOW_CLEARLOG: + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if ( si ) { + LM_RemoveAll(&si->pLog, &si->pLogEnd); + if ( si->hWnd ) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + } + si->iEventCount = 0; + si->LastTime = 0; + } + break; + } + case SESSION_TERMINATE: + return SM_RemoveSession(gce->pDest->ptszID, gce->pDest->pszModule, (gce->dwFlags & GCEF_REMOVECONTACT) != 0); + } + SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_EVENT_CONTROL + WM_USER + 500, wp, 0); + } + + else if (gce->pDest->iType == GC_EVENT_CHUID && gce->pszText) + { + SM_ChangeUID( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszNick, gce->ptszText); + } + + else if (gce->pDest->iType == GC_EVENT_CHANGESESSIONAME && gce->pszText) + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if ( si ) { + replaceStr( &si->ptszName, gce->ptszText ); + if ( si->hWnd ) + SendMessage(si->hWnd, GC_UPDATETITLE, 0, 0); + + if ( g_TabSession.hWnd && g_Settings.TabsEnable ) { + g_TabSession.ptszName = si->ptszName; + SendMessage(g_TabSession.hWnd, GC_SESSIONNAMECHANGE, 0, (LPARAM)si); + } } } + + else if (gce->pDest->iType == GC_EVENT_SETITEMDATA) { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if (si) + si->dwItemData = gce->dwItemData; + } + + else if (gce->pDest->iType ==GC_EVENT_GETITEMDATA) { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if (si) { + gce->dwItemData = si->dwItemData; + return si->dwItemData; + } + return 0; + } + else if (gce->pDest->iType == GC_EVENT_SETSBTEXT) + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if (si) { + replaceStr( &si->ptszStatusbarText, gce->ptszText ); + if ( si->ptszStatusbarText ) + DBWriteContactSettingTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText); + else + DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", ""); + if ( si->hWnd ) { + g_TabSession.ptszStatusbarText = si->ptszStatusbarText; + SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0); + } } + } + else if (gce->pDest->iType == GC_EVENT_ACK) + { + SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_ACKMESSAGE, 0, 0); + } + else if (gce->pDest->iType == GC_EVENT_SENDMESSAGE && gce->pszText) + { + SM_SendUserMessage( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText); + } + else if (gce->pDest->iType == GC_EVENT_SETSTATUSEX) + { + SM_SetStatusEx( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText, gce->dwItemData); + } + else return 1; + + return 0; +} + +static void AddUser(GCEVENT * gce) +{ + SESSION_INFO* si = SM_FindSession( gce->pDest->ptszID, gce->pDest->pszModule); + if ( si ) { + WORD status = TM_StringToWord( si->pStatuses, gce->ptszStatus ); + USERINFO * ui = SM_AddUser( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszNick, status); + if (ui) { + ui->pszNick = mir_tstrdup( gce->ptszNick ); + + if (gce->bIsMe) + si->pMe = ui; + + ui->Status = status; + ui->Status |= si->pStatuses->Status; + + if (si->hWnd) { + g_TabSession.pUsers = si->pUsers; + SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); +} } } } + +static INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam) +{ + GCEVENT *gce = (GCEVENT*)lParam, save_gce; + GCDEST *gcd = NULL, save_gcd; + TCHAR* pWnd = NULL; + char* pMod = NULL; + BOOL bIsHighlighted = FALSE; + BOOL bRemoveFlag = FALSE; + int iRetVal = GC_EVENT_ERROR; + + if ( gce == NULL ) + return GC_EVENT_ERROR; + + gcd = gce->pDest; + if ( gcd == NULL ) + return GC_EVENT_ERROR; + + if ( gce->cbSize != SIZEOF_STRUCT_GCEVENT_V1 && gce->cbSize != SIZEOF_STRUCT_GCEVENT_V2 ) + return GC_EVENT_WRONGVER; + + if ( !IsEventSupported( gcd->iType )) + return GC_EVENT_ERROR; + + EnterCriticalSection(&cs); + + if ( !( gce->dwFlags & GC_UNICODE )) { + save_gce = *gce; + save_gcd = *gce->pDest; + gce->pDest->ptszID = a2tf( gce->pDest->ptszID, gce->dwFlags ); + gce->ptszUID = a2tf( gce->ptszUID, gce->dwFlags ); + gce->ptszNick = a2tf( gce->ptszNick, gce->dwFlags ); + gce->ptszStatus = a2tf( gce->ptszStatus, gce->dwFlags ); + gce->ptszText = a2tf( gce->ptszText, gce->dwFlags ); + gce->ptszUserInfo = a2tf( gce->ptszUserInfo, gce->dwFlags ); + } + + // Do different things according to type of event + switch(gcd->iType) { + case GC_EVENT_ADDGROUP: + { + STATUSINFO* si = SM_AddStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszStatus); + if ( si && gce->dwItemData) + si->hIcon = CopyIcon((HICON)gce->dwItemData); + } + iRetVal = 0; + goto LBL_Exit; + + case GC_EVENT_CHUID: + case GC_EVENT_CHANGESESSIONAME: + case GC_EVENT_SETITEMDATA: + case GC_EVENT_GETITEMDATA: + case GC_EVENT_CONTROL: + case GC_EVENT_SETSBTEXT: + case GC_EVENT_ACK: + case GC_EVENT_SENDMESSAGE : + case GC_EVENT_SETSTATUSEX : + iRetVal = DoControl(gce, wParam); + goto LBL_Exit; + + case GC_EVENT_SETCONTACTSTATUS: + iRetVal = SM_SetContactStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, (WORD)gce->dwItemData ); + goto LBL_Exit; + + case GC_EVENT_TOPIC: + { + SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule); + if ( si ) { + if ( gce->pszText ) { + replaceStr( &si->ptszTopic, gce->ptszText); + if ( si->hWnd ) + g_TabSession.ptszTopic = si->ptszTopic; + DBWriteContactSettingTString( si->hContact, si->pszModule , "Topic", RemoveFormatting( si->ptszTopic )); + if ( DBGetContactSettingByte( NULL, "Chat", "TopicOnClist", 0 )) + DBWriteContactSettingTString( si->hContact, "CList" , "StatusMsg", RemoveFormatting( si->ptszTopic )); + } } + break; + } + case GC_EVENT_ADDSTATUS: + SM_GiveStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus ); + break; + + case GC_EVENT_REMOVESTATUS: + SM_TakeStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus); + break; + + case GC_EVENT_MESSAGE: + case GC_EVENT_ACTION: + if ( !gce->bIsMe && gce->pDest->pszID && gce->pszText ) { + SESSION_INFO* si = SM_FindSession( gce->pDest->ptszID, gce->pDest->pszModule ); + if ( si ) + if ( IsHighlighted( si, gce->ptszText )) + bIsHighlighted = TRUE; + } + break; + + case GC_EVENT_NICK: + SM_ChangeNick( gce->pDest->ptszID, gce->pDest->pszModule, gce); + break; + + case GC_EVENT_JOIN: + AddUser(gce); + break; + + case GC_EVENT_PART: + case GC_EVENT_QUIT: + case GC_EVENT_KICK: + bRemoveFlag = TRUE; + break; + } + + // Decide which window (log) should have the event + if ( gcd->pszID ) { + pWnd = gcd->ptszID; + pMod = gcd->pszModule; + } + else if ( gcd->iType == GC_EVENT_NOTICE || gcd->iType == GC_EVENT_INFORMATION ) { + SESSION_INFO* si = GetActiveSession(); + if ( si && !lstrcmpA( si->pszModule, gcd->pszModule )) { + pWnd = si->ptszID; + pMod = si->pszModule; + } + else { + iRetVal = 0; + goto LBL_Exit; + } + } + else { + // Send the event to all windows with a user pszUID. Used for broadcasting QUIT etc + SM_AddEventToAllMatchingUID( gce ); + if ( !bRemoveFlag ) { + iRetVal = 0; + goto LBL_Exit; + } } + + // add to log + if ( pWnd ) { + SESSION_INFO* si = SM_FindSession(pWnd, pMod); + + // fix for IRC's old stuyle mode notifications. Should not affect any other protocol + if ((gce->pDest->iType == GC_EVENT_ADDSTATUS || gce->pDest->iType == GC_EVENT_REMOVESTATUS) && !( gce->dwFlags & GCEF_ADDTOLOG )) { + iRetVal = 0; + goto LBL_Exit; + } + + if (gce && gce->pDest->iType == GC_EVENT_JOIN && gce->time == 0) { + iRetVal = 0; + goto LBL_Exit; + } + + if (si && (si->bInitDone || gce->pDest->iType == GC_EVENT_TOPIC || (gce->pDest->iType == GC_EVENT_JOIN && gce->bIsMe))) { + if (SM_AddEvent(pWnd, pMod, gce, bIsHighlighted) && si->hWnd) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_ADDLOG, 0, 0); + } + else if (si->hWnd) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_REDRAWLOG2, 0, 0); + } + DoSoundsFlashPopupTrayStuff(si, gce, bIsHighlighted, 0); + if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled) + LogToFile(si, gce); + } + + if ( !bRemoveFlag ) { + iRetVal = 0; + goto LBL_Exit; + } } + + if ( bRemoveFlag ) + iRetVal = ( SM_RemoveUser( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID ) == 0 ) ? 1 : 0; + +LBL_Exit: + LeaveCriticalSection(&cs); + + if ( !( gce->dwFlags & GC_UNICODE )) { + mir_free((void*)gce->ptszText ); + mir_free((void*)gce->ptszNick ); + mir_free((void*)gce->ptszUID ); + mir_free((void*)gce->ptszStatus ); + mir_free((void*)gce->ptszUserInfo ); + mir_free((void*)gce->pDest->ptszID ); + *gce = save_gce; + *gce->pDest = save_gcd; + } + + return iRetVal; +} + +static INT_PTR Service_GetAddEventPtr(WPARAM wParam, LPARAM lParam) +{ + GCPTRS * gp = (GCPTRS *) lParam; + + EnterCriticalSection(&cs); + + gp->pfnAddEvent = Service_AddEvent; + LeaveCriticalSection(&cs); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Service creation + +void HookEvents(void) +{ + InitializeCriticalSection(&cs); + g_hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + g_hHookPrebuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CList_PrebuildContactMenu); + g_hSystemPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown); + g_hIconsChanged = HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged); +} + +void UnhookEvents(void) +{ + UnhookEvent(g_hModulesLoaded); + UnhookEvent(g_hSystemPreShutdown); + UnhookEvent(g_hHookPrebuildMenu); + UnhookEvent(g_hIconsChanged); + UnhookEvent(g_hIconsChanged2); + UnhookEvent(g_hFontsChanged); + if (g_hSmileyOptionsChanged) + UnhookEvent(g_hSmileyOptionsChanged); + DeleteCriticalSection(&cs); +} + +void CreateServiceFunctions(void) +{ + hServiceRegister = CreateServiceFunction(MS_GC_REGISTER, Service_Register); + hServiceNewChat = CreateServiceFunction(MS_GC_NEWSESSION, Service_NewChat); + hServiceAddEvent = CreateServiceFunction(MS_GC_EVENT, Service_AddEvent); + hServiceGetAddEventPtr = CreateServiceFunction(MS_GC_GETEVENTPTR, Service_GetAddEventPtr); + hServiceGetInfo = CreateServiceFunction(MS_GC_GETINFO, Service_GetInfo); + hServiceGetCount = CreateServiceFunction(MS_GC_GETSESSIONCOUNT, Service_GetCount); + + hEventDoubleclicked = CreateServiceFunction("GChat/DblClickEvent", CList_EventDoubleclicked); + hEventPrebuildMenu = CreateServiceFunction("GChat/PrebuildMenuEvent", CList_PrebuildContactMenuSvc); + hEventJoinChat = CreateServiceFunction("GChat/JoinChat", CList_JoinChat); + hEventLeaveChat = CreateServiceFunction("GChat/LeaveChat", CList_LeaveChat); +} + +void DestroyServiceFunctions(void) +{ + DestroyServiceFunction( hServiceRegister ); + DestroyServiceFunction( hServiceNewChat ); + DestroyServiceFunction( hServiceAddEvent ); + DestroyServiceFunction( hServiceGetAddEventPtr ); + DestroyServiceFunction( hServiceGetInfo ); + DestroyServiceFunction( hServiceGetCount ); + + DestroyServiceFunction( hEventDoubleclicked ); + DestroyServiceFunction( hEventPrebuildMenu ); + DestroyServiceFunction( hEventJoinChat ); + DestroyServiceFunction( hEventLeaveChat ); +} + +void CreateHookableEvents(void) +{ + hSendEvent = CreateHookableEvent(ME_GC_EVENT); + hBuildMenuEvent = CreateHookableEvent(ME_GC_BUILDMENU); +} + +void DestroyHookableEvents(void) +{ + DestroyHookableEvent(hSendEvent); + DestroyHookableEvent(hBuildMenuEvent); +} + +void TabsInit(void) +{ + ZeroMemory(&g_TabSession, sizeof(SESSION_INFO)); + + g_TabSession.iType = GCW_TABROOM; + g_TabSession.iSplitterX = g_Settings.iSplitterX; + g_TabSession.iSplitterY = g_Settings.iSplitterY; + g_TabSession.iLogFilterFlags = (int)DBGetContactSettingDword(NULL, "Chat", "FilterFlags", 0x03E0); + g_TabSession.bFilterEnabled = DBGetContactSettingByte(NULL, "Chat", "FilterEnabled", 0); + g_TabSession.bNicklistEnabled = DBGetContactSettingByte(NULL, "Chat", "ShowNicklist", 1); + g_TabSession.iFG = 4; + g_TabSession.bFGSet = TRUE; + g_TabSession.iBG = 2; + g_TabSession.bBGSet = TRUE; +} diff --git a/src/core/stdchat/src/tools.cpp b/src/core/stdchat/src/tools.cpp new file mode 100644 index 0000000000..fa8f28ead3 --- /dev/null +++ b/src/core/stdchat/src/tools.cpp @@ -0,0 +1,917 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-2010 Miranda ICQ/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 "chat.h" + +extern HICON hIcons[30]; +extern BOOL PopUpInstalled; +extern FONTINFO aFonts[OPTIONS_FONTCOUNT]; +extern HMENU g_hMenu; +extern HANDLE hBuildMenuEvent ; +extern HANDLE hSendEvent; +extern SESSION_INFO g_TabSession; + +int GetRichTextLength(HWND hwnd) +{ + GETTEXTLENGTHEX gtl; + + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP ; + return (int) SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); +} + +TCHAR* RemoveFormatting(const TCHAR* pszWord) +{ + static TCHAR szTemp[10000]; + int i = 0; + int j = 0; + + if ( pszWord == 0 || lstrlen(pszWord) == 0 ) + return NULL; + + while(j < 9999 && i <= lstrlen( pszWord )) { + if (pszWord[i] == '%') { + switch ( pszWord[i+1] ) { + case '%': + szTemp[j] = '%'; + j++; + i++; i++; + break; + case 'b': + case 'u': + case 'i': + case 'B': + case 'U': + case 'I': + case 'r': + case 'C': + case 'F': + i++; i++; + break; + + case 'c': + case 'f': + i += 4; + break; + + default: + szTemp[j] = pszWord[i]; + j++; + i++; + break; + } } + else { + szTemp[j] = pszWord[i]; + j++; + i++; + } } + + return (TCHAR*) &szTemp; +} + +static void __stdcall ShowRoomFromPopup(void * pi) +{ + SESSION_INFO* si = (SESSION_INFO*) pi; + ShowRoom(si, WINDOW_VISIBLE, TRUE); +} + +static INT_PTR CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) { + case WM_COMMAND: + if (HIWORD(wParam) == STN_CLICKED) { + SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)0);; + + CallFunctionAsync(ShowRoomFromPopup, si); + + PUDeletePopUp(hWnd); + return TRUE; + } + break; + case WM_CONTEXTMENU: + { + SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)0); + if (si->hContact) + if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)"chaticon"); + + if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND)) + FlashWindow(si->hWnd, FALSE); + + PUDeletePopUp( hWnd ); + } + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static int ShowPopup (HANDLE hContact, SESSION_INFO* si, HICON hIcon, char* pszProtoName, TCHAR* pszRoomName, COLORREF crBkg, const TCHAR* fmt, ...) +{ + POPUPDATAT pd = {0}; + va_list marker; + static TCHAR szBuf[4*1024]; + + if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000) + return 0; + + va_start(marker, fmt); + _vsntprintf(szBuf, 4096, fmt, marker); + va_end(marker); + + pd.lchContact = hContact; + + if ( hIcon ) + pd.lchIcon = hIcon ; + else + pd.lchIcon = LoadIconEx( "window", FALSE ); + + mir_sntprintf(pd.lptzContactName, MAX_CONTACTNAME-1, _T(TCHAR_STR_PARAM) _T(" - %s"), + pszProtoName, CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR )); + lstrcpyn( pd.lptzText, TranslateTS(szBuf), MAX_SECONDLINE-1); + pd.iSeconds = g_Settings.iPopupTimeout; + + if (g_Settings.iPopupStyle == 2) { + pd.colorBack = 0; + pd.colorText = 0; + } + else if (g_Settings.iPopupStyle == 3) { + pd.colorBack = g_Settings.crPUBkgColour; + pd.colorText = g_Settings.crPUTextColour; + } + else { + pd.colorBack = g_Settings.crLogBackground; + pd.colorText = crBkg; + } + + pd.PluginWindowProc = (WNDPROC)PopupDlgProc; + pd.PluginData = si; + return PUAddPopUpT(&pd); +} + +static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce) +{ + int iEvent = gce->pDest->iType; + + if ( iEvent&g_Settings.dwTrayIconFlags ) { + switch ( iEvent ) { + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT : + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT : + CList_AddEvent(si->hContact, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), "chaticon", 0, TranslateT("%s wants your attention in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_MESSAGE : + CList_AddEvent(si->hContact, hIcons[ICON_MESSAGE], "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_ACTION: + CList_AddEvent(si->hContact, hIcons[ICON_ACTION], "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_JOIN: + CList_AddEvent(si->hContact, hIcons[ICON_JOIN], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has joined %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_PART: + CList_AddEvent(si->hContact, hIcons[ICON_PART], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has left %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_QUIT: + CList_AddEvent(si->hContact, hIcons[ICON_QUIT], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has disconnected"), gce->ptszNick); + break; + case GC_EVENT_NICK: + CList_AddEvent(si->hContact, hIcons[ICON_NICK], "chaticon", CLEF_ONLYAFEW, TranslateT("%s is now known as %s"), gce->ptszNick, gce->pszText); + break; + case GC_EVENT_KICK: + CList_AddEvent(si->hContact, hIcons[ICON_KICK], "chaticon", CLEF_ONLYAFEW, TranslateT("%s kicked %s from %s"), gce->pszStatus, gce->ptszNick, si->ptszName); + break; + case GC_EVENT_NOTICE: + CList_AddEvent(si->hContact, hIcons[ICON_NOTICE], "chaticon", CLEF_ONLYAFEW, TranslateT("Notice from %s"), gce->ptszNick); + break; + case GC_EVENT_TOPIC: + CList_AddEvent(si->hContact, hIcons[ICON_TOPIC], "chaticon", CLEF_ONLYAFEW, TranslateT("Topic change in %s"), si->ptszName); + break; + case GC_EVENT_INFORMATION: + CList_AddEvent(si->hContact, hIcons[ICON_INFO], "chaticon", CLEF_ONLYAFEW, TranslateT("Information in %s"), si->ptszName); + break; + case GC_EVENT_ADDSTATUS: + CList_AddEvent(si->hContact, hIcons[ICON_ADDSTATUS], "chaticon", CLEF_ONLYAFEW, TranslateT("%s enables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName); + break; + case GC_EVENT_REMOVESTATUS: + CList_AddEvent(si->hContact, hIcons[ICON_REMSTATUS], "chaticon", CLEF_ONLYAFEW, TranslateT("%s disables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName); + break; + } } + + return TRUE; +} + +static BOOL DoPopup(SESSION_INFO* si, GCEVENT * gce) +{ + int iEvent = gce->pDest->iType; + + if ( iEvent & g_Settings.dwPopupFlags ) { + switch (iEvent) { + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT : + ShowPopup(si->hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText )); + break; + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT : + ShowPopup(si->hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_MESSAGE : + ShowPopup(si->hContact, si, hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, aFonts[9].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText)); + break; + case GC_EVENT_ACTION: + ShowPopup(si->hContact, si, hIcons[ICON_ACTION], si->pszModule, si->ptszName, aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_JOIN: + ShowPopup(si->hContact, si, hIcons[ICON_JOIN], si->pszModule, si->ptszName, aFonts[3].color, TranslateT("%s has joined"), gce->ptszNick); + break; + case GC_EVENT_PART: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left"), gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left (%s)"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_QUIT: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected"), gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected (%s)"), gce->ptszNick,RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NICK: + ShowPopup(si->hContact, si, hIcons[ICON_NICK], si->pszModule, si->ptszName, aFonts[7].color, TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText); + break; + case GC_EVENT_KICK: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NOTICE: + ShowPopup(si->hContact, si, hIcons[ICON_NOTICE], si->pszModule, si->ptszName, aFonts[8].color, TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_TOPIC: + if (!gce->ptszNick) + ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText)); + else + ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick); + break; + case GC_EVENT_INFORMATION: + ShowPopup(si->hContact, si, hIcons[ICON_INFO], si->pszModule, si->ptszName, aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ADDSTATUS: + ShowPopup(si->hContact, si, hIcons[ICON_ADDSTATUS], si->pszModule, si->ptszName, aFonts[13].color, TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + ShowPopup(si->hContact, si, hIcons[ICON_REMSTATUS], si->pszModule, si->ptszName, aFonts[14].color, TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + } } + + return TRUE; +} + +BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix) +{ + BOOL bInactive; + int iEvent; + + if (!gce || !si || gce->bIsMe || si->iType == GCW_SERVER) + return FALSE; + + bInactive = si->hWnd == NULL || GetForegroundWindow() != si->hWnd; + // bInactive |= GetActiveWindow() != si->hWnd; // Removed this, because it seemed to be FALSE, even when window was focused, causing incorrect notifications + + iEvent = gce->pDest->iType; + + if ( bHighlight ) { + gce->pDest->iType |= GC_EVENT_HIGHLIGHT; + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatHighlight"); + if (!g_Settings.TabsEnable && bInactive && si->hWnd && DBGetContactSettingByte(NULL, "Chat", "FlashWindowHighlight", 0) != 0) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + if (DBGetContactSettingByte(si->hContact, "CList", "Hidden", 0) != 0) + DBDeleteContactSetting(si->hContact, "CList", "Hidden"); + if (bInactive) + DoTrayIcon(si, gce); + if (bInactive || !g_Settings.PopUpInactiveOnly) + DoPopup(si, gce); + if (g_Settings.TabsEnable && bInactive && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM) si); + return TRUE; + } + + // do blinking icons in tray + if (bInactive || !g_Settings.TrayIconInactiveOnly) + DoTrayIcon(si, gce); + + // stupid thing to not create multiple popups for a QUIT event for instance + if (bManyFix == 0) { + // do popups + if (bInactive || !g_Settings.PopUpInactiveOnly) + DoPopup(si, gce); + + // do sounds and flashing + switch (iEvent) { + case GC_EVENT_JOIN: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatJoin"); + break; + case GC_EVENT_PART: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatPart"); + break; + case GC_EVENT_QUIT: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatQuit"); + break; + case GC_EVENT_ADDSTATUS: + case GC_EVENT_REMOVESTATUS: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatMode"); + break; + case GC_EVENT_KICK: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatKick"); + break; + case GC_EVENT_MESSAGE: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatMessage"); + if (!g_Settings.TabsEnable && bInactive && g_Settings.FlashWindow && si->hWnd) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + + if (bInactive && !( si->wState & STATE_TALK )) { + si->wState |= STATE_TALK; + DBWriteContactSettingWord(si->hContact, si->pszModule,"ApparentMode",(LPARAM)(WORD) 40071); + } + if (g_Settings.TabsEnable && bInactive && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETTABHIGHLIGHT, 0, (LPARAM) si); + break; + case GC_EVENT_ACTION: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatAction"); + break; + case GC_EVENT_NICK: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatNick"); + break; + case GC_EVENT_NOTICE: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatNotice"); + break; + case GC_EVENT_TOPIC: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatTopic"); + break; + } } + + return TRUE; +} + +int GetColorIndex(const char* pszModule, COLORREF cr) +{ + MODULEINFO * pMod = MM_FindModule(pszModule); + int i = 0; + + if (!pMod || pMod->nColorCount == 0) + return -1; + + for (i = 0; i < pMod->nColorCount; i++) + if (pMod->crColors[i] == cr) + return i; + + return -1; +} + +// obscure function that is used to make sure that any of the colors +// passed by the protocol is used as fore- or background color +// in the messagebox. THis is to vvercome limitations in the richedit +// that I do not know currently how to fix + +void CheckColorsInModule(const char* pszModule) +{ + MODULEINFO * pMod = MM_FindModule( pszModule ); + int i = 0; + COLORREF crFG; + COLORREF crBG = (COLORREF)DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + + LoadMsgDlgFont(17, NULL, &crFG); + + if ( !pMod ) + return; + + for (i = 0; i < pMod->nColorCount; i++) { + if (pMod->crColors[i] == crFG || pMod->crColors[i] == crBG) { + if (pMod->crColors[i] == RGB(255,255,255)) + pMod->crColors[i]--; + else + pMod->crColors[i]++; +} } } + +const TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) +{ + int i,j,k; + for(i=0; s1[i]; i++) + for(j=i, k=0; _totlower(s1[j]) == _totlower(s2[k]); j++, k++) + if (!s2[k+1]) + return s1 + i; + + return NULL; +} + +BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText) +{ + if ( g_Settings.HighlightEnabled && g_Settings.pszHighlightWords && pszText && si->pMe ) { + TCHAR* p1 = g_Settings.pszHighlightWords; + TCHAR* p2 = NULL; + const TCHAR* p3 = pszText; + static TCHAR szWord1[1000]; + static TCHAR szWord2[1000]; + static TCHAR szTrimString[] = _T(":,.!?;\'>)"); + + // compare word for word + while (*p1 != '\0') { + // find the next/first word in the highlight word string + // skip 'spaces' be4 the word + while(*p1 == ' ' && *p1 != '\0') + p1 += 1; + + //find the end of the word + p2 = _tcschr(p1, ' '); + if (!p2) + p2 = _tcschr(p1, '\0'); + if (p1 == p2) + return FALSE; + + // copy the word into szWord1 + lstrcpyn(szWord1, p1, p2 - p1 > 998 ? 999 : p2 - p1 + 1); + p1 = p2; + + // replace %m with the users nickname + p2 = _tcschr(szWord1, '%'); + if (p2 && p2[1] == 'm') { + TCHAR szTemp[50]; + + p2[1] = 's'; + lstrcpyn(szTemp, szWord1, 999); + mir_sntprintf(szWord1, SIZEOF(szWord1), szTemp, si->pMe->pszNick); + } + + // time to get the next/first word in the incoming text string + while(*p3 != '\0') + { + // skip 'spaces' be4 the word + while(*p3 == ' ' && *p3 != '\0') + p3 += 1; + + //find the end of the word + p2 = (TCHAR *)_tcschr(p3, ' '); + if (!p2) + p2 = (TCHAR *)_tcschr(p3, '\0'); + + + if (p3 != p2) { + // eliminate ending character if needed + if (p2-p3 > 1 && _tcschr(szTrimString, p2[-1])) + p2 -= 1; + + // copy the word into szWord2 and remove formatting + lstrcpyn(szWord2, p3, p2-p3>998?999:p2-p3+1); + + // reset the pointer if it was touched because of an ending character + if (*p2 != '\0' && *p2 != ' ') + p2 += 1; + p3 = p2; + + CharLower(szWord1); + CharLower(szWord2); + + // compare the words, using wildcards + if (WCCmp(szWord1, RemoveFormatting(szWord2))) + return TRUE; + } } + + p3 = pszText; + } } + + return FALSE; +} + +BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce) +{ + MODULEINFO * mi = NULL; + TCHAR szBuffer[4096]; + TCHAR szLine[4096]; + TCHAR szTime[100]; + FILE *hFile = NULL; + TCHAR szFile[MAX_PATH]; + TCHAR szName[MAX_PATH]; + TCHAR szFolder[MAX_PATH]; + char p = '\0'; + TCHAR *szModName = NULL; + szBuffer[0] = '\0'; + + if (!si || !gce) + return FALSE; + + mi = MM_FindModule(si->pszModule); + if ( !mi ) + return FALSE; + + szModName = mir_a2t(si->pszModule); + mir_sntprintf(szName, MAX_PATH, _T("%s"), mi->ptszModDispName ? mi->ptszModDispName : (szModName = mir_a2t(si->pszModule))); + mir_free(szModName); + ValidateFilename(szName); + mir_sntprintf(szFolder, MAX_PATH, _T("%s\\%s"), g_Settings.pszLogDir, szName ); + + CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szFolder); + + mir_sntprintf( szName, MAX_PATH, _T("%s.log"), si->ptszID ); + ValidateFilename(szName); + + mir_sntprintf(szFile, MAX_PATH, _T("%s\\%s"), szFolder, szName ); + lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99); + + hFile = _tfopen(szFile, _T("at+")); + if (hFile) + { + TCHAR szTemp[512], szTemp2[512]; + TCHAR* pszNick = NULL; + if ( gce->ptszNick ) { + if ( g_Settings.LogLimitNames && lstrlen(gce->ptszNick) > 20 ) { + lstrcpyn(szTemp2, gce->ptszNick, 20); + lstrcpyn(szTemp2+20, _T("..."), 4); + } + else lstrcpyn(szTemp2, gce->ptszNick, 511); + + if (gce->pszUserInfo) + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, gce->pszUserInfo); + else + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2); + pszNick = szTemp; + } + switch (gce->pDest->iType) { + case GC_EVENT_MESSAGE: + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT: + p = '*'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s * %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ACTION: + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT: + p = '*'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_JOIN: + p = '>'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has joined"), (char *)pszNick); + break; + case GC_EVENT_PART: + p = '<'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left"), (char *)pszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left (%s)"), (char *)pszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_QUIT: + p = '<'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected"), (char *)pszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected (%s)"), (char *)pszNick,RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NICK: + p = '^'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText); + break; + case GC_EVENT_KICK: + p = '~'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NOTICE: + p = '¤'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_TOPIC: + p = '#'; + if (!gce->pszNick) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText)); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick); + break; + case GC_EVENT_INFORMATION: + p = '!'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s"), RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ADDSTATUS: + p = '+'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + p = '-'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + } + if (p) + mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%s %c %s\n"), szTime, p, szBuffer); + else + mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%s %s\n"), szTime, szBuffer); + + if ( szLine[0] ) { + char* p = mir_t2a( szLine ); + fputs(p, hFile); + mir_free( p ); + + if ( g_Settings.LoggingLimit > 0 ) { + DWORD dwSize; + DWORD trimlimit; + + fseek(hFile,0,SEEK_END); + dwSize = ftell(hFile); + rewind (hFile); + trimlimit = g_Settings.LoggingLimit*1024+ 1024*10; + if (dwSize > trimlimit) { + BYTE * pBuffer = 0; + BYTE * pBufferTemp = 0; + int read = 0; + + pBuffer = (BYTE *)mir_alloc(g_Settings.LoggingLimit*1024+1); + pBuffer[g_Settings.LoggingLimit*1024] = '\0'; + fseek(hFile,-g_Settings.LoggingLimit*1024,SEEK_END); + read = (int)fread(pBuffer, 1, g_Settings.LoggingLimit*1024, hFile); + fclose(hFile); + hFile = NULL; + + // trim to whole lines, should help with broken log files I hope. + pBufferTemp = (BYTE *)strchr((char *)pBuffer, '\n'); + if ( pBufferTemp ) { + pBufferTemp++; + read -= pBufferTemp - pBuffer; + } + else pBufferTemp = pBuffer; + + if (read > 0) { + hFile = _tfopen(szFile, _T("wt")); + if (hFile ) { + fwrite(pBufferTemp, 1, read, hFile); + fclose(hFile); hFile = NULL; + } } + + mir_free(pBuffer); + } } } + + if (hFile) + fclose(hFile); hFile = NULL; + return TRUE; + } + + return FALSE; +} + +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText) +{ + GCMENUITEMS gcmi = {0}; + int i; + HMENU hSubMenu = 0; + + *hMenu = GetSubMenu(g_hMenu, iIndex); + TranslateMenu(*hMenu); + gcmi.pszID = si->ptszID; + gcmi.pszModule = si->pszModule; + gcmi.pszUID = pszUID; + + if (iIndex == 1) { + int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_ENABLED); + EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED); + ModifyMenu(*hMenu, 4, MF_GRAYED|MF_BYPOSITION, 4, NULL); + if (!i) { + EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_BYCOMMAND | MF_GRAYED); + if (pszWordText && pszWordText[0]) + ModifyMenu(*hMenu, 4, MF_ENABLED|MF_BYPOSITION, 4, NULL); + } + + if ( pszWordText && pszWordText[0] ) { + TCHAR szMenuText[4096]; + mir_sntprintf( szMenuText, 4096, TranslateT("Look up \'%s\':"), pszWordText ); + ModifyMenu( *hMenu, 4, MF_STRING|MF_BYPOSITION, 4, szMenuText ); + } + else ModifyMenu( *hMenu, 4, MF_STRING|MF_GRAYED|MF_BYPOSITION, 4, TranslateT( "No word to look up" )); + gcmi.Type = MENU_ON_LOG; + } + else if (iIndex == 0) + { + TCHAR szTemp[30], szTemp2[30]; + lstrcpyn(szTemp, TranslateT("&Message"), 24); + if ( pszUID ) + mir_sntprintf( szTemp2, SIZEOF(szTemp2), _T("%s %s"), szTemp, pszUID); + else + lstrcpyn(szTemp2, szTemp, 24); + + if ( lstrlen(szTemp2) > 22 ) + lstrcpyn( szTemp2+22, _T("..."), 4 ); + ModifyMenu( *hMenu, ID_MESS, MF_STRING|MF_BYCOMMAND, ID_MESS, szTemp2 ); + gcmi.Type = MENU_ON_NICKLIST; + } + + NotifyEventHooks(hBuildMenuEvent, 0, (WPARAM)&gcmi); + + if (gcmi.nItems > 0) + AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); + + for (i = 0; i < gcmi.nItems; i++) { + TCHAR* ptszDescr = a2tf(gcmi.Item[i].pszDesc, si->dwFlags); + TCHAR* ptszText = TranslateTS(ptszDescr); + DWORD dwState = gcmi.Item[i].bDisabled ? MF_GRAYED : 0; + + if (gcmi.Item[i].uType == MENU_NEWPOPUP) { + hSubMenu = CreateMenu(); + AppendMenu(*hMenu, dwState | MF_POPUP, (UINT_PTR)hSubMenu, ptszText); + } + else if (gcmi.Item[i].uType == MENU_POPUPHMENU) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPITEM) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPCHECK) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_SEPARATOR) + AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_HMENU) + AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_ITEM) + AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_CHECK) + AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + + mir_free( ptszDescr ); + } + return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); +} + +void DestroyGCMenu(HMENU *hMenu, int iIndex) +{ + MENUITEMINFO mi; + mi.cbSize = sizeof(mi); + mi.fMask = MIIM_SUBMENU; + while(GetMenuItemInfo(*hMenu, iIndex, TRUE, &mi)) + { + if (mi.hSubMenu != NULL) + DestroyMenu(mi.hSubMenu); + RemoveMenu(*hMenu, iIndex, MF_BYPOSITION); + } +} + +BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem) +{ + GCHOOK* gch = (GCHOOK*)mir_calloc( sizeof( GCHOOK )); + GCDEST* gcd = (GCDEST*)mir_calloc( sizeof( GCDEST )); + + gcd->pszModule = mir_strdup( pszModule ); + + { + SESSION_INFO* si; + if (( si = SM_FindSession(pszID, pszModule)) == NULL ) + return FALSE; + + if ( !( si->dwFlags & GC_UNICODE )) { + gcd->pszID = mir_t2a( pszID ); + gch->pszUID = mir_t2a( pszUID ); + gch->pszText = mir_t2a( pszText ); + } + else { + gcd->ptszID = mir_tstrdup( pszID ); + gch->ptszUID = mir_tstrdup( pszUID ); + gch->ptszText = mir_tstrdup( pszText ); + } + } + + gcd->iType = iType; + gch->dwData = dwItem; + gch->pDest = gcd; + PostMessage(hwnd, GC_FIREHOOK, 0, (LPARAM) gch); + return TRUE; +} + +BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem) +{ + GCHOOK gch = {0}; + GCDEST gcd = {0}; + + gcd.pszModule = (char*)pszModule; + + { + SESSION_INFO* si; + if (( si = SM_FindSession(pszID, pszModule)) == NULL ) + return FALSE; + + if ( !( si->dwFlags & GC_UNICODE )) { + gcd.pszID = mir_t2a( pszID ); + gch.pszUID = mir_t2a( pszUID ); + gch.pszText = mir_t2a( pszText ); + } + else { + gcd.ptszID = mir_tstrdup( pszID ); + gch.ptszUID = mir_tstrdup( pszUID ); + gch.ptszText = mir_tstrdup( pszText ); + } + } + + gcd.iType = iType; + gch.dwData = dwItem; + gch.pDest = &gcd; + NotifyEventHooks(hSendEvent,0,(WPARAM)&gch); + + mir_free( gcd.pszID ); + mir_free( gch.ptszUID ); + mir_free( gch.ptszText ); + + return TRUE; +} + +BOOL IsEventSupported(int eventType) +{ + switch (eventType) + { + // Supported events + case GC_EVENT_JOIN: + case GC_EVENT_PART: + case GC_EVENT_QUIT: + case GC_EVENT_KICK: + case GC_EVENT_NICK: + case GC_EVENT_NOTICE: + case GC_EVENT_MESSAGE: + case GC_EVENT_TOPIC: + case GC_EVENT_INFORMATION: + case GC_EVENT_ACTION: + case GC_EVENT_ADDSTATUS: + case GC_EVENT_REMOVESTATUS: + case GC_EVENT_CHUID: + case GC_EVENT_CHANGESESSIONAME: + case GC_EVENT_ADDGROUP: + case GC_EVENT_SETITEMDATA: + case GC_EVENT_GETITEMDATA: + case GC_EVENT_SETSBTEXT: + case GC_EVENT_ACK: + case GC_EVENT_SENDMESSAGE: + case GC_EVENT_SETSTATUSEX: + case GC_EVENT_CONTROL: + case GC_EVENT_SETCONTACTSTATUS: + return TRUE; + } + + // Other events + return FALSE; +} + +void ValidateFilename (TCHAR * filename) +{ + TCHAR *p1 = filename; + TCHAR szForbidden[] = _T("\\/:*?\"<>|"); + while(*p1 != '\0') + { + if (_tcschr(szForbidden, *p1)) + *p1 = '_'; + p1 +=1; +} } + +TCHAR* a2tf( const TCHAR* str, int flags ) +{ + if ( str == NULL ) + return NULL; + + if ( flags & GC_UNICODE ) + return mir_tstrdup( str ); + else + return mir_a2u((char*)str); +} + +TCHAR* replaceStr( TCHAR** dest, const TCHAR* src ) +{ + mir_free( *dest ); + *dest = mir_tstrdup( src ); + return *dest; +} + +char* replaceStrA( char** dest, const char* src ) +{ + mir_free( *dest ); + *dest = mir_strdup( src ); + return *dest; +} diff --git a/src/core/stdchat/src/version.h b/src/core/stdchat/src/version.h new file mode 100644 index 0000000000..c553761412 --- /dev/null +++ b/src/core/stdchat/src/version.h @@ -0,0 +1,14 @@ + +#include + +#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION +#define __VERSION_STRING MIRANDA_VERSION_STRING + +#define __PLUGIN_NAME "Standard Chat" +#define __INTERNAL_NAME "stdchat" +#define __FILENAME "stdchat.dll" +#define __DESCRIPTION "Core module for providing chat rooms support." +#define __AUTHOR "Miranda NG Development Team" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdchat/src/window.cpp b/src/core/stdchat/src/window.cpp new file mode 100644 index 0000000000..ccddae051b --- /dev/null +++ b/src/core/stdchat/src/window.cpp @@ -0,0 +1,2725 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-2010 Miranda ICQ/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 "chat.h" + +extern HBRUSH hEditBkgBrush; +extern HBRUSH hListBkgBrush; +extern HBRUSH hListSelectedBkgBrush; +extern HANDLE hSendEvent; +extern HICON hIcons[30]; +extern struct CREOleCallback reOleCallback; +extern HIMAGELIST hImageList; +extern HMENU g_hMenu; +extern BOOL SmileyAddInstalled; +extern TABLIST * g_TabList; +extern HIMAGELIST hIconsList; + +static WNDPROC OldSplitterProc; +static WNDPROC OldMessageProc; +static WNDPROC OldNicklistProc; +static WNDPROC OldTabProc; +static WNDPROC OldFilterButtonProc; +static WNDPROC OldLogProc; +static HKL hkl = NULL; + +typedef struct +{ + time_t lastEnterTime; + TCHAR szTabSave[20]; +} MESSAGESUBDATA; + + +static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_NCHITTEST: + return HTCLIENT; + + case WM_SETCURSOR: + { RECT rc; + GetClientRect(hwnd,&rc); + SetCursor(rc.right>rc.bottom?LoadCursor(NULL, IDC_SIZENS):LoadCursor(NULL, IDC_SIZEWE)); + return TRUE; + } + case WM_LBUTTONDOWN: + SetCapture(hwnd); + return 0; + + case WM_MOUSEMOVE: + if (GetCapture()==hwnd) { + RECT rc; + GetClientRect(hwnd,&rc); + SendMessage(GetParent(hwnd),GC_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(); + PostMessage(GetParent(hwnd),WM_SIZE, 0, 0); + return 0; + } + return CallWindowProc(OldSplitterProc,hwnd,msg,wParam,lParam); +} + +static void InitButtons(HWND hwndDlg, SESSION_INFO* si) +{ + MODULEINFO * pInfo = MM_FindModule(si->pszModule); + + SendDlgItemMessage( hwndDlg, IDC_SMILEY, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "smiley", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_BOLD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "bold", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_ITALICS, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "italics", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_UNDERLINE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "underline", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_COLOR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "fgcol", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_BKGCOLOR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "bkgcol", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_HISTORY, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "history", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_CHANMGR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "settings", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( "close", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_SHOWNICKLIST, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( si->bNicklistEnabled ? "nicklist" : "nicklist2", FALSE )); + SendDlgItemMessage( hwndDlg, IDC_FILTER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx( si->bFilterEnabled ? "filter" : "filter2", FALSE )); + + SendDlgItemMessage( hwndDlg, IDC_SMILEY, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_BOLD, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_ITALICS, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_UNDERLINE, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_BKGCOLOR, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_COLOR, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_HISTORY, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_SHOWNICKLIST, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_CHANMGR, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_FILTER, BUTTONSETASFLATBTN, TRUE, 0 ); + SendDlgItemMessage( hwndDlg, IDC_CLOSE, BUTTONSETASFLATBTN, TRUE, 0 ); + + SendMessage(GetDlgItem(hwndDlg,IDC_SMILEY), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Insert a smiley"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_BOLD), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text bold (CTRL+B)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_ITALICS), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text italicized (CTRL+I)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_UNDERLINE), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text underlined (CTRL+U)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_BKGCOLOR), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Select a background color for the text (CTRL+L)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_COLOR), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Select a foreground color for the text (CTRL+K)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_HISTORY), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Show the history (CTRL+H)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_SHOWNICKLIST), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Show/hide the nicklist (CTRL+N)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_CHANMGR), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Control this room (CTRL+O)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_FILTER), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Enable/disable the event filter (CTRL+F)"), 0); + SendMessage(GetDlgItem(hwndDlg,IDC_CLOSE), BUTTONADDTOOLTIP, (WPARAM)LPGEN("Close current tab (CTRL+F4)"), 0); + SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_ITALICS, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_COLOR, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOR, BUTTONSETASPUSHBTN, TRUE, 0); + + if (pInfo) { + EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), pInfo->bBold); + EnableWindow(GetDlgItem(hwndDlg, IDC_ITALICS), pInfo->bItalics); + EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), pInfo->bUnderline); + EnableWindow(GetDlgItem(hwndDlg, IDC_COLOR), pInfo->bColor); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOR), pInfo->bBkgColor); + if (si->iType == GCW_CHATROOM) + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), pInfo->bChanMgr); +} } + +static int RoomWndResize(HWND hwndDlg,LPARAM lParam,UTILRESIZECONTROL *urc) +{ + RECT rc, rcTabs; + SESSION_INFO* si = (SESSION_INFO*)lParam; + int TabHeight; + BOOL bControl = (BOOL)DBGetContactSettingByte(NULL, "Chat", "ShowTopButtons", 1); + BOOL bFormat = (BOOL)DBGetContactSettingByte(NULL, "Chat", "ShowFormatButtons", 1); + BOOL bToolbar = bFormat || bControl; + BOOL bSend = (BOOL)DBGetContactSettingByte(NULL, "Chat", "ShowSend", 0); + BOOL bNick = si->iType!=GCW_SERVER && si->bNicklistEnabled; + BOOL bTabs = g_Settings.TabsEnable; + BOOL bTabBottom = g_Settings.TabsAtBottom; + + GetClientRect(GetDlgItem(hwndDlg, IDC_TAB), &rcTabs); + TabHeight = rcTabs.bottom - rcTabs.top; + TabCtrl_AdjustRect(GetDlgItem(hwndDlg, IDC_TAB), FALSE, &rcTabs); + TabHeight -= (rcTabs.bottom - rcTabs.top); + ShowWindow(GetDlgItem(hwndDlg, IDC_SMILEY), SmileyAddInstalled&&bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BOLD), bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_ITALICS), bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_COLOR), bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOR), bFormat?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HISTORY), bControl?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), bControl?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_FILTER), bControl?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), bControl?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDOK), bSend?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTERX), bNick?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_CLOSE), g_Settings.TabsEnable?SW_SHOW:SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_TAB), g_Settings.TabsEnable?SW_SHOW:SW_HIDE); + if (si->iType != GCW_SERVER) + ShowWindow(GetDlgItem(hwndDlg, IDC_LIST), si->bNicklistEnabled?SW_SHOW:SW_HIDE); + else + ShowWindow(GetDlgItem(hwndDlg, IDC_LIST), SW_HIDE); + + if (si->iType == GCW_SERVER) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), FALSE); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER), TRUE); + if (si->iType == GCW_CHATROOM) + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), MM_FindModule(si->pszModule)->bChanMgr); + } + + switch(urc->wId) { + case IDOK: + GetWindowRect(si->hwndStatus, &rc); + urc->rcItem.left = bSend?315:urc->dlgNewSize.cx ; + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY+23; + urc->rcItem.bottom = urc->dlgNewSize.cy - (rc.bottom-rc.top)-1; + return RD_ANCHORX_RIGHT|RD_ANCHORY_CUSTOM; + + case IDC_TAB: + urc->rcItem.top = 1; + urc->rcItem.left = 0; + urc->rcItem.right = urc->dlgNewSize.cx- 24; + urc->rcItem.bottom = bToolbar?(urc->dlgNewSize.cy - si->iSplitterY):(urc->dlgNewSize.cy - si->iSplitterY+20); + return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM; + + case IDC_LOG: + urc->rcItem.top = bTabs?(bTabBottom?0:rcTabs.top-1):0; + urc->rcItem.left = 0; + urc->rcItem.right = bNick?urc->dlgNewSize.cx - si->iSplitterX:urc->dlgNewSize.cx; + urc->rcItem.bottom = bToolbar?(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight + 6:urc->dlgNewSize.cy - si->iSplitterY):(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight+26:urc->dlgNewSize.cy - si->iSplitterY+20); + return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM; + + case IDC_LIST: + urc->rcItem.top = bTabs?(bTabBottom?0:rcTabs.top-1):0; + urc->rcItem.right = urc->dlgNewSize.cx ; + urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX + 2; + urc->rcItem.bottom = bToolbar?(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight + 6:urc->dlgNewSize.cy - si->iSplitterY):(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight+26:urc->dlgNewSize.cy - si->iSplitterY+20); + return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM; + + case IDC_SPLITTERX: + urc->rcItem.right = urc->dlgNewSize.cx - si->iSplitterX+2; + urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX; + urc->rcItem.bottom = bToolbar?(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight + 6:urc->dlgNewSize.cy - si->iSplitterY):(bTabs&&bTabBottom?urc->dlgNewSize.cy - si->iSplitterY-TabHeight+26:urc->dlgNewSize.cy - si->iSplitterY+20); + urc->rcItem.top = bTabs ?rcTabs.top:1; + return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM; + + case IDC_SPLITTERY: + urc->rcItem.top = bToolbar?urc->dlgNewSize.cy - si->iSplitterY:urc->dlgNewSize.cy - si->iSplitterY+20; + urc->rcItem.bottom = bToolbar?(urc->dlgNewSize.cy - si->iSplitterY+2):(urc->dlgNewSize.cy - si->iSplitterY+22); + return RD_ANCHORX_WIDTH|RD_ANCHORY_CUSTOM; + + case IDC_MESSAGE: + GetWindowRect(si->hwndStatus, &rc); + urc->rcItem.right = bSend?urc->dlgNewSize.cx - 64:urc->dlgNewSize.cx ; + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY+22; + urc->rcItem.bottom = urc->dlgNewSize.cy - (rc.bottom-rc.top)-1 ; + return RD_ANCHORX_LEFT|RD_ANCHORY_CUSTOM; + + case IDC_SMILEY: + case IDC_ITALICS: + case IDC_BOLD: + case IDC_UNDERLINE: + case IDC_COLOR: + case IDC_BKGCOLOR: + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY+3; + urc->rcItem.bottom = urc->dlgNewSize.cy - si->iSplitterY+19; + return RD_ANCHORX_LEFT|RD_ANCHORY_CUSTOM; + + case IDC_HISTORY: + case IDC_CHANMGR: + case IDC_SHOWNICKLIST: + case IDC_FILTER: + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY+3; + urc->rcItem.bottom = urc->dlgNewSize.cy - si->iSplitterY+19; + return RD_ANCHORX_RIGHT|RD_ANCHORY_CUSTOM; + + case IDC_CLOSE: + urc->rcItem.right = urc->dlgNewSize.cx-3; + urc->rcItem.left = urc->dlgNewSize.cx - 19; + urc->rcItem.bottom = bTabBottom?(bToolbar?urc->dlgNewSize.cy - si->iSplitterY-2:urc->dlgNewSize.cy - si->iSplitterY-2+20):19; + urc->rcItem.top = bTabBottom?(bToolbar?urc->dlgNewSize.cy - si->iSplitterY-18:urc->dlgNewSize.cy - si->iSplitterY-18+20):3; + return RD_ANCHORX_CUSTOM|RD_ANCHORY_CUSTOM; + } + return RD_ANCHORX_LEFT|RD_ANCHORY_TOP; +} + +static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + MESSAGESUBDATA *dat; + SESSION_INFO* Parentsi; + + Parentsi=(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + dat = (MESSAGESUBDATA *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + switch (msg) { + case EM_SUBCLASSED: + dat = (MESSAGESUBDATA *) mir_alloc(sizeof(MESSAGESUBDATA)); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat); + dat->szTabSave[0] = '\0'; + dat->lastEnterTime = 0; + return 0; + + case WM_MOUSEWHEEL: + SendMessage(GetDlgItem(GetParent(hwnd), IDC_LOG), WM_MOUSEWHEEL, wParam, lParam); + dat->lastEnterTime = 0; + return TRUE; + + case EM_REPLACESEL: + PostMessage(hwnd, EM_ACTIVATE, 0, 0); + break; + + case EM_ACTIVATE: + SetActiveWindow(GetParent(hwnd)); + break; + + case WM_CHAR: + { + BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) + break; + + if (wParam == 9 && isCtrl && !isAlt) // ctrl-i (italics) + return TRUE; + + if (wParam == VK_SPACE && isCtrl && !isAlt) // ctrl-space (paste clean text) + return TRUE; + + if (wParam == '\n' || wParam == '\r') { + if ((isCtrl != 0) ^ (0 != DBGetContactSettingByte(NULL, "Chat", "SendOnEnter", 1))) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (DBGetContactSettingByte(NULL, "Chat", "SendOnDblEnter", 0)) { + if (dat->lastEnterTime + 2 < time(NULL)) + dat->lastEnterTime = time(NULL); + 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 == 1 && isCtrl && !isAlt) { //ctrl-a + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } } + break; + + case WM_KEYDOWN: + { + static int start, end; + BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + if (wParam == VK_RETURN) { + dat->szTabSave[0] = '\0'; + if ((isCtrl != 0) ^ (0 != DBGetContactSettingByte(NULL, "Chat", "SendOnEnter", 1))) + return 0; + + if (DBGetContactSettingByte(NULL, "Chat", "SendOnDblEnter", 0)) + if (dat->lastEnterTime + 2 >= time(NULL)) + return 0; + + break; + } + + if (wParam == VK_TAB && isShift && !isCtrl) { // SHIFT-TAB (go to nick list) + SetFocus(GetDlgItem(GetParent(hwnd), IDC_LIST)); + return TRUE; + } + + if (wParam == VK_TAB && isCtrl && !isShift) { // CTRL-TAB (switch tab/window) + if (g_Settings.TabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHNEXTTAB, 0, 0); + else + ShowRoom(SM_GetNextWindow(Parentsi), WINDOW_VISIBLE, TRUE); + return TRUE; + } + + if (wParam == VK_TAB && isCtrl && isShift) { // CTRL_SHIFT-TAB (switch tab/window) + if (g_Settings.TabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHPREVTAB, 0, 0); + else + ShowRoom(SM_GetPrevWindow(Parentsi), WINDOW_VISIBLE, TRUE); + return TRUE; + } + + if (wParam <= '9' && wParam >= '1' && isCtrl && !isAlt) { // CTRL + 1 -> 9 (switch tab) + if (g_Settings.TabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHTAB, 0, (LPARAM)((int)wParam - (int)'1')); + } + + if (wParam <= VK_NUMPAD9 && wParam >= VK_NUMPAD1 && isCtrl && !isAlt) // CTRL + 1 -> 9 (switch tab) + if (g_Settings.TabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHTAB, 0, (LPARAM)((int)wParam - (int)VK_NUMPAD1)); + + if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete + TCHAR* pszText = NULL; + int iLen; + GETTEXTLENGTHEX gtl = {0}; + GETTEXTEX gt = {0}; + LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL); + + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + start = LOWORD(lResult); + end = HIWORD(lResult); + SendMessage(hwnd, EM_SETSEL, end, end); + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, (LPARAM)NULL); + if (iLen >0) { + TCHAR *pszName = NULL; + TCHAR *pszSelName = NULL; + pszText = (TCHAR *)mir_alloc(sizeof(TCHAR)*(iLen+100)); + + gt.cb = iLen+99; + gt.flags = GT_DEFAULT; + gt.codepage = 1200; + + SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)>, (LPARAM)pszText); + while ( start >0 && pszText[start-1] != ' ' && pszText[start-1] != 13 && pszText[start-1] != VK_TAB) + start--; + while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end-1] != VK_TAB) + end ++; + + if ( dat->szTabSave[0] =='\0') + lstrcpyn( dat->szTabSave, pszText+start, end-start+1 ); + + pszSelName = (TCHAR *)mir_alloc( sizeof(TCHAR)*( end-start+1 )); + lstrcpyn( pszSelName, pszText+start, end-start+1); + pszName = UM_FindUserAutoComplete(Parentsi->pUsers, dat->szTabSave, pszSelName); + if (pszName == NULL) { + pszName = dat->szTabSave; + SendMessage(hwnd, EM_SETSEL, start, end); + if (end !=start) + SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) pszName); + dat->szTabSave[0] = '\0'; + } + else { + SendMessage(hwnd, EM_SETSEL, start, end); + if (end !=start) + SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) pszName); + } + mir_free(pszText); + mir_free(pszSelName); + } + + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + return 0; + } + + if (dat->szTabSave[0] != '\0' && wParam != VK_RIGHT && wParam != VK_LEFT + && wParam != VK_SPACE && wParam != VK_RETURN && wParam != VK_BACK + && wParam != VK_DELETE ) { + if (g_Settings.AddColonToAutoComplete && start == 0) + SendMessageA(hwnd, EM_REPLACESEL, FALSE, (LPARAM) ": "); + + dat->szTabSave[0] = '\0'; + } + + if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + return TRUE; + } + + if (wParam == 0x49 && isCtrl && !isAlt) { // ctrl-i (italics) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, IsDlgButtonChecked(GetParent(hwnd), IDC_ITALICS) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + return TRUE; + } + + if (wParam == 0x42 && isCtrl && !isAlt) { // ctrl-b (bold) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, IsDlgButtonChecked(GetParent(hwnd), IDC_BOLD) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + return TRUE; + } + + if (wParam == 0x55 && isCtrl && !isAlt) { // ctrl-u (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, IsDlgButtonChecked(GetParent(hwnd), IDC_UNDERLINE) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + return TRUE; + } + + if (wParam == 0x4b && isCtrl && !isAlt) { // ctrl-k (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + return TRUE; + } + + if (wParam == VK_SPACE && isCtrl && !isAlt) { // ctrl-space (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + return TRUE; + } + + if (wParam == 0x4c && isCtrl && !isAlt) { // ctrl-l (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_BKGCOLOR) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + return TRUE; + } + + if (wParam == 0x46 && isCtrl && !isAlt) { // ctrl-f (paste clean text) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_FILTER))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_FILTER, 0), 0); + return TRUE; + } + + if (wParam == 0x4e && isCtrl && !isAlt) { // ctrl-n (nicklist) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_SHOWNICKLIST))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_SHOWNICKLIST, 0), 0); + return TRUE; + } + + if (wParam == 0x48 && isCtrl && !isAlt) { // ctrl-h (history) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_HISTORY, 0), 0); + return TRUE; + } + + if (wParam == 0x4f && isCtrl && !isAlt) { // ctrl-o (options) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_CHANMGR))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHANMGR, 0), 0); + return TRUE; + } + + if ((wParam == 45 && isShift || wParam == 0x56 && isCtrl )&& !isAlt) { // ctrl-v (paste clean text) + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + return TRUE; + } + + if (wParam == 0x57 && isCtrl && !isAlt) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + + if (wParam == VK_NEXT || wParam == VK_PRIOR) { + HWND htemp = GetParent(hwnd); + SendDlgItemMessage(htemp, IDC_LOG, msg, wParam, lParam); + dat->lastEnterTime = 0; + return TRUE; + } + + if (wParam == VK_UP && isCtrl && !isAlt) { + int iLen; + GETTEXTLENGTHEX gtl = {0}; + SETTEXTEX ste; + LOGFONT lf; + char* lpPrevCmd = SM_GetPrevCommand(Parentsi->ptszID, Parentsi->pszModule); + + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + LoadMsgDlgFont(17, &lf, NULL); + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + if (lpPrevCmd) + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); + else + SetWindowText(hwnd, _T("")); + + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, (LPARAM)NULL); + SendMessage(hwnd, EM_SCROLLCARET, 0,0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL,iLen,iLen); + dat->lastEnterTime = 0; + return TRUE; + } + + if (wParam == VK_DOWN && isCtrl && !isAlt) { + int iLen; + GETTEXTLENGTHEX gtl = {0}; + SETTEXTEX ste; + + char* lpPrevCmd = SM_GetNextCommand(Parentsi->ptszID, Parentsi->pszModule); + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + if (lpPrevCmd) + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM) lpPrevCmd); + else + SetWindowText(hwnd, _T("")); + + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, (LPARAM)NULL); + SendMessage(hwnd, EM_SCROLLCARET, 0,0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL,iLen,iLen); + dat->lastEnterTime = 0; + return TRUE; + } + + if (wParam == VK_RETURN) + break; + } + //fall through + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + + case WM_RBUTTONDOWN: + { + CHARRANGE sel, all = { 0, -1 }; + POINT pt; + UINT uID = 0; + HMENU hSubMenu; + + hSubMenu = GetSubMenu(g_hMenu, 4); + TranslateMenu(hSubMenu); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel); + + EnableMenuItem(hSubMenu, ID_MESSAGE_UNDO, SendMessage(hwnd, EM_CANUNDO, 0,0)?MF_ENABLED:MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_REDO, SendMessage(hwnd, EM_CANREDO, 0,0)?MF_ENABLED:MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_COPY, sel.cpMax!=sel.cpMin?MF_ENABLED:MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_CUT, sel.cpMax!=sel.cpMin?MF_ENABLED:MF_GRAYED); + + dat->lastEnterTime = 0; + + pt.x = (short) LOWORD(lParam); + pt.y = (short) HIWORD(lParam); + ClientToScreen(hwnd, &pt); + + uID = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); + switch (uID) { + case 0: + break; + + case ID_MESSAGE_UNDO: + SendMessage(hwnd, EM_UNDO, 0, 0); + break; + + case ID_MESSAGE_REDO: + SendMessage(hwnd, EM_REDO, 0, 0); + break; + + case ID_MESSAGE_COPY: + SendMessage(hwnd, WM_COPY, 0, 0); + break; + + case ID_MESSAGE_CUT: + SendMessage(hwnd, WM_CUT, 0, 0); + break; + + case ID_MESSAGE_PASTE: + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + break; + + case ID_MESSAGE_SELECTALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all); + break; + + case ID_MESSAGE_CLEAR: + SetWindowText(hwnd, _T( "" )); + break; + } + PostMessage(hwnd, WM_KEYUP, 0, 0 ); + } + break; + + case WM_KEYUP: + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + { + CHARFORMAT2 cf; + UINT u = 0; + UINT u2 = 0; + COLORREF cr; + + LoadMsgDlgFont(17, NULL, &cr); + + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_BACKCOLOR|CFM_COLOR; + SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + + if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bColor) { + int index = GetColorIndex(Parentsi->pszModule, cf.crTextColor); + u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR); + + if (index >= 0) { + Parentsi->bFGSet = TRUE; + Parentsi->iFG = index; + } + + if (u == BST_UNCHECKED && cf.crTextColor != cr) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crTextColor == cr) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_UNCHECKED); + } + + if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bBkgColor) { + int index = GetColorIndex(Parentsi->pszModule, cf.crBackColor); + COLORREF crB = (COLORREF)DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + u = IsDlgButtonChecked(GetParent(hwnd), IDC_BKGCOLOR); + + if (index >= 0) { + Parentsi->bBGSet = TRUE; + Parentsi->iBG = index; + } + if (u == BST_UNCHECKED && cf.crBackColor != crB) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crBackColor == crB) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_UNCHECKED); + } + + if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bBold) { + u = IsDlgButtonChecked(GetParent(hwnd), IDC_BOLD); + u2 = cf.dwEffects; + u2 &= CFE_BOLD; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_UNCHECKED); + } + + if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bItalics) { + u = IsDlgButtonChecked(GetParent(hwnd), IDC_ITALICS); + u2 = cf.dwEffects; + u2 &= CFE_ITALIC; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_UNCHECKED); + } + + if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bUnderline) { + u = IsDlgButtonChecked(GetParent(hwnd), IDC_UNDERLINE); + u2 = cf.dwEffects; + u2 &= CFE_UNDERLINE; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_UNCHECKED); + } } + break; + + case EM_UNSUBCLASSED: + mir_free(dat); + return 0; + } + + return CallWindowProc(OldMessageProc, hwnd, msg, wParam, lParam); +} + +static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + static SESSION_INFO* si = NULL; + switch (uMsg) { + case WM_INITDIALOG: + si = (SESSION_INFO*)lParam; + CheckDlgButton(hwndDlg, IDC_1, si->iLogFilterFlags&GC_EVENT_ACTION); + CheckDlgButton(hwndDlg, IDC_2, si->iLogFilterFlags&GC_EVENT_MESSAGE); + CheckDlgButton(hwndDlg, IDC_3, si->iLogFilterFlags&GC_EVENT_NICK); + CheckDlgButton(hwndDlg, IDC_4, si->iLogFilterFlags&GC_EVENT_JOIN); + CheckDlgButton(hwndDlg, IDC_5, si->iLogFilterFlags&GC_EVENT_PART); + CheckDlgButton(hwndDlg, IDC_6, si->iLogFilterFlags&GC_EVENT_TOPIC); + CheckDlgButton(hwndDlg, IDC_7, si->iLogFilterFlags&GC_EVENT_ADDSTATUS); + CheckDlgButton(hwndDlg, IDC_8, si->iLogFilterFlags&GC_EVENT_INFORMATION); + CheckDlgButton(hwndDlg, IDC_9, si->iLogFilterFlags&GC_EVENT_QUIT); + CheckDlgButton(hwndDlg, IDC_10, si->iLogFilterFlags&GC_EVENT_KICK); + CheckDlgButton(hwndDlg, IDC_11, si->iLogFilterFlags&GC_EVENT_NOTICE); + break; + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + SetTextColor((HDC)wParam,RGB(60,60,150)); + SetBkColor((HDC)wParam,GetSysColor(COLOR_WINDOW)); + return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + int iFlags = 0; + + if (IsDlgButtonChecked(hwndDlg, IDC_1) == BST_CHECKED) + iFlags |= GC_EVENT_ACTION; + if (IsDlgButtonChecked(hwndDlg, IDC_2) == BST_CHECKED) + iFlags |= GC_EVENT_MESSAGE; + if (IsDlgButtonChecked(hwndDlg, IDC_3) == BST_CHECKED) + iFlags |= GC_EVENT_NICK; + if (IsDlgButtonChecked(hwndDlg, IDC_4) == BST_CHECKED) + iFlags |= GC_EVENT_JOIN; + if (IsDlgButtonChecked(hwndDlg, IDC_5) == BST_CHECKED) + iFlags |= GC_EVENT_PART; + if (IsDlgButtonChecked(hwndDlg, IDC_6) == BST_CHECKED) + iFlags |= GC_EVENT_TOPIC; + if (IsDlgButtonChecked(hwndDlg, IDC_7) == BST_CHECKED) + iFlags |= GC_EVENT_ADDSTATUS; + if (IsDlgButtonChecked(hwndDlg, IDC_8) == BST_CHECKED) + iFlags |= GC_EVENT_INFORMATION; + if (IsDlgButtonChecked(hwndDlg, IDC_9) == BST_CHECKED) + iFlags |= GC_EVENT_QUIT; + if (IsDlgButtonChecked(hwndDlg, IDC_10) == BST_CHECKED) + iFlags |= GC_EVENT_KICK; + if (IsDlgButtonChecked(hwndDlg, IDC_11) == BST_CHECKED) + iFlags |= GC_EVENT_NOTICE; + + if (iFlags&GC_EVENT_ADDSTATUS) + iFlags |= GC_EVENT_REMOVESTATUS; + + SendMessage(GetParent(hwndDlg), GC_CHANGEFILTERFLAG, 0, (LPARAM)iFlags); + if (si->bFilterEnabled) + SendMessage(GetParent(hwndDlg), GC_REDRAWLOG, 0, 0); + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + } + + return(FALSE); +} + +static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_RBUTTONUP: + { + HWND hFilter = GetDlgItem(GetParent(hwnd), IDC_FILTER); + HWND hColor = GetDlgItem(GetParent(hwnd), IDC_COLOR); + HWND hBGColor = GetDlgItem(GetParent(hwnd), IDC_BKGCOLOR); + + if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) != 0) { + if (hFilter == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWFILTERMENU, 0, 0); + if (hColor == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR); + if (hBGColor == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR); + } } + break; + } + + return CallWindowProc(OldFilterButtonProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_LBUTTONUP: + { + CHARRANGE sel; + + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) &sel); + if (sel.cpMin != sel.cpMax) + { + SendMessage(hwnd, WM_COPY, 0, 0); + sel.cpMin = sel.cpMax ; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel); + } + SetFocus(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)); + break; + } + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + CHARRANGE sel; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) &sel); + if (sel.cpMin != sel.cpMax) { + sel.cpMin = sel.cpMax ; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel); + } } + break; + + case WM_CHAR: + SetFocus(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)); + SendMessage(GetDlgItem(GetParent(hwnd), IDC_MESSAGE), WM_CHAR, wParam, lParam); + break; + } + + return CallWindowProc(OldLogProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK TabSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL bDragging = FALSE; + static int iBeginIndex = 0; + switch (msg) { + case WM_LBUTTONDOWN: + { + TCHITTESTINFO tci = {0}; + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1 ) { + int i; + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + i= TabCtrl_HitTest(hwnd, &tci); + if (i != -1) { + TCITEM tc; + SESSION_INFO* s = NULL; + + tc.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, i, &tc); + s = (SESSION_INFO* ) tc.lParam; + if (s) + { + BOOL bOnline = DBGetContactSettingWord(s->hContact, s->pszModule, "Status", ID_STATUS_OFFLINE) == ID_STATUS_ONLINE?TRUE:FALSE; + bDragging = TRUE; + iBeginIndex = i; + ImageList_BeginDrag(hIconsList, bOnline?(MM_FindModule(s->pszModule))->OnlineIconIndex:(MM_FindModule(s->pszModule))->OfflineIconIndex, 8, 8); + ImageList_DragEnter(hwnd,tci.pt.x, tci.pt.y); + SetCapture(hwnd); + } + return TRUE; + } } + else PostMessage(GetParent(hwnd), GC_TABCLICKED, 0, 0 ); + } + break; + case WM_CAPTURECHANGED: + bDragging = FALSE; + ImageList_DragLeave(hwnd); + ImageList_EndDrag(); + break; + + case WM_MOUSEMOVE: + if (bDragging) { + TCHITTESTINFO tci = {0}; + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(hwnd, &tci.pt); + ImageList_DragMove(tci.pt.x, tci.pt.y); + } + break; + + case WM_LBUTTONUP: + if (bDragging && ReleaseCapture()) { + TCHITTESTINFO tci = {0}; + int i; + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + bDragging = FALSE; + ImageList_DragLeave(hwnd); + ImageList_EndDrag(); + + ScreenToClient(hwnd, &tci.pt); + i= TabCtrl_HitTest(hwnd, &tci); + if (i != -1 && i != iBeginIndex) + SendMessage(GetParent(hwnd), GC_DROPPEDTAB, (WPARAM)i, (LPARAM)iBeginIndex); + } + break; + + case WM_LBUTTONDBLCLK: + { + TCHITTESTINFO tci = {0}; + int i = 0; + + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1 && g_Settings.TabCloseOnDblClick) + PostMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + } + break; + + case WM_MBUTTONUP: + { + TCHITTESTINFO tci = {0}; + int i = 0; + + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1 ) { + TCITEM tc; + SESSION_INFO* si ; + + tc.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, i, &tc); + si = (SESSION_INFO* ) tc.lParam; + if (si) + SendMessage(GetParent(hwnd), GC_REMOVETAB, 1, (LPARAM) si ); + } } + break; + } + + return CallWindowProc(OldTabProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_ERASEBKGND: + { + HDC dc = (HDC)wParam; + SESSION_INFO* parentdat =(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + if (dc) { + int height, index, items = 0; + + index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + if (index == LB_ERR || parentdat->nUsersInNicklist <= 0) + return 0; + + items = parentdat->nUsersInNicklist - index; + height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + + if (height != LB_ERR) { + RECT rc = {0}; + GetClientRect(hwnd, &rc); + + if (rc.bottom-rc.top > items * height) { + rc.top = items*height; + FillRect(dc, &rc, hListBkgBrush); + } } } } + return 1; + + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + break; + + case WM_RBUTTONDOWN: + SendMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam); + break; + + case WM_RBUTTONUP: + SendMessage(hwnd, WM_LBUTTONUP, wParam, lParam); + break; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam; + if (mis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + return FALSE; + } + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam; + if (dis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + return FALSE; + } + case WM_CONTEXTMENU: + { + TVHITTESTINFO hti; + int item; + int height; + USERINFO * ui; + SESSION_INFO* parentdat =(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + + hti.pt.x = (short) LOWORD(lParam); + hti.pt.y = (short) HIWORD(lParam); + if (hti.pt.x == -1 && hti.pt.y == -1) { + int index = SendMessage(hwnd, LB_GETCURSEL, 0, 0); + int top = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + hti.pt.x = 4; + hti.pt.y = (index - top)*height + 1; + } + else ScreenToClient(hwnd,&hti.pt); + + item = LOWORD(SendMessage(GetDlgItem(GetParent(hwnd), IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + ui = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item); + // ui = (USERINFO *)SendMessage(GetDlgItem(GetParent(hwnd), IDC_LIST), LB_GETITEMDATA, item, 0); + if (ui) { + HMENU hMenu = 0; + UINT uID; + USERINFO uinew; + + memcpy(&uinew, ui, sizeof(USERINFO)); + if (hti.pt.x == -1 && hti.pt.y == -1) + hti.pt.y += height - 4; + ClientToScreen(hwnd, &hti.pt); + uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, parentdat, uinew.pszUID, NULL); + + switch (uID) { + case 0: + break; + + case ID_MESS: + DoEventHookAsync(GetParent(hwnd), parentdat->ptszID, parentdat->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL); + break; + + default: + DoEventHookAsync(GetParent(hwnd), parentdat->ptszID, parentdat->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID); + break; + } + DestroyGCMenu(&hMenu, 1); + return TRUE; + } } + break; + + case WM_MOUSEMOVE: + { + SESSION_INFO* parentdat =(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + if ( parentdat ) { + POINT p; + GetCursorPos(&p); + SendMessage( parentdat->hwndTooltip,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(p.x + 15,p.y + 15)); +// SendMessage( parentdat->hwndTooltip, TTM_ACTIVATE, TRUE, 0 ); + } } + break; + + } + + return CallWindowProc(OldNicklistProc, hwnd, msg, wParam, lParam); +} + +static int RestoreWindowPosition(HWND hwnd, HANDLE hContact, char * szModule, char * szNamePrefix, UINT showCmd) +{ + WINDOWPLACEMENT wp; + char szSettingName[64]; + int x,y, width, height;; + + wp.length=sizeof(wp); + GetWindowPlacement(hwnd,&wp); + wsprintfA(szSettingName,"%sx",szNamePrefix); + x=DBGetContactSettingDword(hContact,szModule,szSettingName,-1); + wsprintfA(szSettingName,"%sy",szNamePrefix); + y=(int)DBGetContactSettingDword(hContact,szModule,szSettingName,-1); + wsprintfA(szSettingName,"%swidth",szNamePrefix); + width=DBGetContactSettingDword(hContact,szModule,szSettingName,-1); + wsprintfA(szSettingName,"%sheight",szNamePrefix); + height=DBGetContactSettingDword(hContact,szModule,szSettingName,-1); + + if (x==-1) + return 0; + wp.rcNormalPosition.left=x; + wp.rcNormalPosition.top=y; + wp.rcNormalPosition.right=wp.rcNormalPosition.left+width; + wp.rcNormalPosition.bottom=wp.rcNormalPosition.top+height; + wp.showCmd = showCmd; + SetWindowPlacement(hwnd,&wp); + return 1; +} + +int GetTextPixelSize( TCHAR* pszText, HFONT hFont, BOOL bWidth) +{ + HDC hdc; + HFONT hOldFont; + RECT rc = {0}; + int i; + + if (!pszText || !hFont) + return 0; + + hdc = GetDC(NULL); + hOldFont = (HFONT)SelectObject(hdc, hFont); + i = DrawText(hdc, pszText , -1, &rc, DT_CALCRECT); + SelectObject(hdc, hOldFont); + ReleaseDC(NULL,hdc); + return bWidth ? rc.right - rc.left : rc.bottom - rc.top; +} + +static void __cdecl phase2(void * lParam) +{ + SESSION_INFO* si = (SESSION_INFO*) lParam; + Sleep(30); + if (si && si->hWnd) + PostMessage(si->hWnd, GC_REDRAWLOG3, 0, 0); +} + +INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + SESSION_INFO* si; + + si = (SESSION_INFO*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (uMsg) { + case WM_INITDIALOG: + { + int mask; + HWND hNickList = GetDlgItem(hwndDlg,IDC_LIST); + si = (SESSION_INFO*)lParam; + si->pAccPropServicesForNickList = NULL; + CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER, IID_IAccPropServices, (LPVOID *)si->pAccPropServicesForNickList); + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si); + OldSplitterProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_SPLITTERX),GWLP_WNDPROC,(LONG_PTR)SplitterSubclassProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_SPLITTERY),GWLP_WNDPROC,(LONG_PTR)SplitterSubclassProc); + OldNicklistProc=(WNDPROC)SetWindowLongPtr(hNickList,GWLP_WNDPROC,(LONG_PTR)NicklistSubclassProc); + OldTabProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_TAB),GWLP_WNDPROC,(LONG_PTR)TabSubclassProc); + OldLogProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_LOG),GWLP_WNDPROC,(LONG_PTR)LogSubclassProc); + OldFilterButtonProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_FILTER),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_COLOR),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_BKGCOLOR),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc); + OldMessageProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC,(LONG_PTR)MessageSubclassProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, 1, 0); + mask = (int)SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETEVENTMASK, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, mask | ENM_LINK | ENM_MOUSEEVENTS); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM)sizeof(TCHAR)*0x7FFFFFFF, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback); + + // RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_MESSAGE)); + // RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG)); + + si->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP| SBT_TOOLTIPS , 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); + SendMessage(si->hwndStatus,SB_SETMINHEIGHT,GetSystemMetrics(SM_CYSMICON),0); + TabCtrl_SetMinTabWidth(GetDlgItem(hwndDlg, IDC_TAB), 80); + TabCtrl_SetImageList(GetDlgItem(hwndDlg, IDC_TAB), hIconsList); + + // enable tooltips + si->iOldItemID = -1; + si->hwndTooltip = CreateWindow(TOOLTIPS_CLASS,NULL,TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hNickList,(HMENU)NULL,g_hInst,NULL); + SetWindowPos(si->hwndTooltip, HWND_TOPMOST,0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + { + TOOLINFO ti = {0}; + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRANSPARENT; + ti.hwnd = hwndDlg; + ti.hinst = g_hInst; + ti.uId = (UINT_PTR)hNickList; + ti.lpszText = LPSTR_TEXTCALLBACK; + //GetClientRect( hNickList, &ti.rect ); + SendMessage( si->hwndTooltip, TTM_ADDTOOL, 0, ( LPARAM )&ti ); + SendMessage( si->hwndTooltip, TTM_SETDELAYTIME, TTDT_AUTOPOP, 20000 ); + SendMessage( si->hwndTooltip, TTM_SETMAXTIPWIDTH, 0, 300); + + //SendMessage( psi->hwndTooltip, TTM_TRACKACTIVATE, TRUE, ( LPARAM )&ti ); + } + + // restore previous tabs + if (g_Settings.TabsEnable && DBGetContactSettingByte(NULL, "Chat", "TabRestore", 0)) { + TABLIST * node = g_TabList; + while (node) { + SESSION_INFO* s = SM_FindSession(node->pszID, node->pszModule); + if (s) + SendMessage(hwndDlg, GC_ADDTAB, -1, (LPARAM)s); + + node = node->next; + } } + + TabM_RemoveAll(); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SMILEY), TRUE); + + SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_HIDESELECTION, TRUE, 0); + + SendMessage(hwndDlg, GC_SETWNDPROPS, 0, 0); + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0); + SendMessage(hwndDlg, GC_SETWINDOWPOS, 0, 0); + } + break; + + case GC_SETWNDPROPS: + { + HICON hIcon; + LoadGlobalSettings(); + InitButtons(hwndDlg, si); + + hIcon = si->wStatus==ID_STATUS_ONLINE?MM_FindModule(si->pszModule)->hOnlineIcon:MM_FindModule(si->pszModule)->hOfflineIcon; + // stupid hack to make icons show. I dunno why this is needed currently + if (!hIcon) { + MM_IconsChanged(); + hIcon = si->wStatus==ID_STATUS_ONLINE?MM_FindModule(si->pszModule)->hOnlineIcon:MM_FindModule(si->pszModule)->hOfflineIcon; + } + + SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0); + SendMessage(si->hwndStatus, SB_SETICON, 0,(LPARAM)hIcon); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx( "window", TRUE )); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx( "window", FALSE )); + + SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_SETBKGNDCOLOR , 0, g_Settings.crLogBackground); + + if (g_Settings.TabsEnable) { + int mask = (int)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TAB), GWL_STYLE); + if (g_Settings.TabsAtBottom) + mask |= TCS_BOTTOM; + else + mask &= ~TCS_BOTTOM; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TAB), GWL_STYLE, (LONG_PTR)mask); + } + + { //messagebox + COLORREF crFore; + + CHARFORMAT2 cf; + LoadMsgDlgFont(17, NULL, &crFore); + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_COLOR|CFM_BOLD|CFM_UNDERLINE|CFM_BACKCOLOR; + cf.dwEffects = 0; + cf.crTextColor = crFore; + cf.crBackColor = (COLORREF)DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETBKGNDCOLOR , 0, DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW))); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) g_Settings.MessageBoxFont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, (WPARAM)SCF_ALL , (LPARAM)&cf); + } + { // nicklist + int ih; + int ih2; + int font; + int height; + + ih = GetTextPixelSize( _T("AQGglo"), g_Settings.UserListFont,FALSE); + ih2 = GetTextPixelSize( _T("AQGglo"), g_Settings.UserListHeadingsFont,FALSE); + height = DBGetContactSettingByte(NULL, "Chat", "NicklistRowDist", 12); + font = ih > ih2?ih:ih2; + + // make sure we have space for icon! + if (g_Settings.ShowContactStatus) + font = font > 16 ? font : 16; + + SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETITEMHEIGHT, 0, (LPARAM)height > font ? height : font); + InvalidateRect(GetDlgItem(hwndDlg, IDC_LIST), NULL, TRUE); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0); + } + break; + + case GC_UPDATETITLE: + { + TCHAR szTemp [100]; + switch(si->iType) { + case GCW_CHATROOM: + mir_sntprintf(szTemp, SIZEOF(szTemp), + (si->nUsersInNicklist ==1) ? TranslateT("%s: Chat Room (%u user)") : TranslateT("%s: Chat Room (%u users)"), + si->ptszName, si->nUsersInNicklist); + break; + case GCW_PRIVMESS: + mir_sntprintf(szTemp, SIZEOF(szTemp), + (si->nUsersInNicklist ==1) ? TranslateT("%s: Message Session") : TranslateT("%s: Message Session (%u users)"), + si->ptszName, si->nUsersInNicklist); + break; + case GCW_SERVER: + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s: Server"), si->ptszName); + break; + } + SetWindowText(hwndDlg, szTemp); + } + break; + + case GC_UPDATESTATUSBAR: + { + HICON hIcon; + int iStatusbarParts[2]; + TCHAR* ptszDispName = MM_FindModule(si->pszModule)->ptszModDispName; + int x = 12; + + x += GetTextPixelSize(ptszDispName, (HFONT)SendMessage(si->hwndStatus,WM_GETFONT,0,0), TRUE); + x += GetSystemMetrics(SM_CXSMICON); + iStatusbarParts[0] = x; iStatusbarParts[1] = -1; + SendMessage(si->hwndStatus,SB_SETPARTS,2 ,(LPARAM)&iStatusbarParts); + + hIcon = si->wStatus==ID_STATUS_ONLINE?MM_FindModule(si->pszModule)->hOnlineIcon:MM_FindModule(si->pszModule)->hOfflineIcon; + + // stupid hack to make icons show. I dunno why this is needed currently + if (!hIcon) { + MM_IconsChanged(); + hIcon = si->wStatus==ID_STATUS_ONLINE?MM_FindModule(si->pszModule)->hOnlineIcon:MM_FindModule(si->pszModule)->hOfflineIcon; + } + + SendMessage(si->hwndStatus, SB_SETICON, 0,(LPARAM)hIcon); + SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0); + + SendMessage(si->hwndStatus, SB_SETTEXT,0,(LPARAM)ptszDispName); + + SendMessage(si->hwndStatus, SB_SETTEXT,1,(LPARAM)(si->ptszStatusbarText ? si->ptszStatusbarText : _T(""))); + SendMessage(si->hwndStatus, SB_SETTIPTEXT,1,(LPARAM)(si->ptszStatusbarText ? si->ptszStatusbarText : _T(""))); + return TRUE; + } + break; + + case GC_SETWINDOWPOS: + { + SESSION_INFO* pActive = GetActiveSession(); + WINDOWPLACEMENT wp; + RECT screen; + int savePerContact = DBGetContactSettingByte(NULL, "Chat", "SavePosition", 0); + + wp.length=sizeof(wp); + GetWindowPlacement(hwndDlg,&wp); + SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0); + + if (si->iX) { + wp.rcNormalPosition.left = si->iX; + wp.rcNormalPosition.top = si->iY; + wp.rcNormalPosition.right = wp.rcNormalPosition.left + si->iWidth; + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + si->iHeight; + wp.showCmd = SW_HIDE; + SetWindowPlacement(hwndDlg,&wp); + // SetWindowPos(hwndDlg, 0, si->iX,si->iY, si->iWidth, si->iHeight, SWP_NOZORDER |SWP_HIDEWINDOW|SWP_NOACTIVATE); + break; + } + if (savePerContact) { + if (RestoreWindowPosition(hwndDlg, g_Settings.TabsEnable?NULL:si->hContact, "Chat", "room", SW_HIDE)) + break; + SetWindowPos(hwndDlg, 0, (screen.right-screen.left)/2- (550)/2,(screen.bottom-screen.top)/2- (400)/2, (550), (400), SWP_NOZORDER |SWP_HIDEWINDOW|SWP_NOACTIVATE); + } + else SetWindowPos(hwndDlg, 0, (screen.right-screen.left)/2- (550)/2,(screen.bottom-screen.top)/2- (400)/2, (550), (400), SWP_NOZORDER |SWP_HIDEWINDOW|SWP_NOACTIVATE); + + if (!g_Settings.TabsEnable && pActive && pActive->hWnd && DBGetContactSettingByte(NULL, "Chat", "CascadeWindows", 1)) { + RECT rcThis, rcNew; + int dwFlag = SWP_NOZORDER|SWP_NOACTIVATE; + if (!IsWindowVisible ((HWND)wParam)) + dwFlag |= SWP_HIDEWINDOW; + + GetWindowRect(hwndDlg, &rcThis); + GetWindowRect(pActive->hWnd, &rcNew); + + { + int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); + SetWindowPos((HWND) hwndDlg, 0, rcNew.left + offset, rcNew.top + offset, rcNew.right-rcNew.left, rcNew.bottom-rcNew.top, dwFlag); + } } } + break; + + case GC_SAVEWNDPOS: + { + WINDOWPLACEMENT wp = { 0 }; + + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + g_Settings.iX = wp.rcNormalPosition.left; + g_Settings.iY = wp.rcNormalPosition.top; + g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + + if (!lParam) { + si->iX = g_Settings.iX; + si->iY = g_Settings.iY; + si->iWidth = g_Settings.iWidth; + si->iHeight = g_Settings.iHeight; + } } + break; + + case WM_SIZE: + { + UTILRESIZEDIALOG urd; + + if (wParam == SIZE_MAXIMIZED) + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + + if (IsIconic(hwndDlg)) break; + SendMessage(si->hwndStatus, WM_SIZE, 0, 0); + ZeroMemory(&urd,sizeof(urd)); + urd.cbSize=sizeof(urd); + urd.hInstance=g_hInst; + urd.hwndDlg=hwndDlg; + urd.lParam=(LPARAM)si; + urd.lpTemplate=MAKEINTRESOURCEA(IDD_CHANNEL); + urd.pfnResizer=RoomWndResize; + CallService(MS_UTILS_RESIZEDIALOG,0,(LPARAM)&urd); + + InvalidateRect(si->hwndStatus, NULL, TRUE); + RedrawWindow(GetDlgItem(hwndDlg,IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); + RedrawWindow(GetDlgItem(hwndDlg,IDOK), NULL, NULL, RDW_INVALIDATE); + SendMessage(hwndDlg,GC_SAVEWNDPOS,0,1); + } + break; + + case GC_REDRAWWINDOW: + InvalidateRect(hwndDlg, NULL, TRUE); + break; + + case GC_REDRAWLOG: + si->LastTime = 0; + if (si->pLog) { + LOGINFO * pLog = si->pLog; + if (si->iEventCount > 60) { + int index = 0; + while ( index < 59) { + if (pLog->next == NULL) + break; + + pLog = pLog->next; + if (si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&pLog->iType) != 0) + index++; + } + Log_StreamInEvent(hwndDlg, pLog, si, TRUE, FALSE); + mir_forkthread(phase2, si); + } + else Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE); + } + else SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER+500, WINDOW_CLEARLOG, 0); + break; + + case GC_REDRAWLOG2: + si->LastTime = 0; + if (si->pLog) + Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE); + break; + + case GC_REDRAWLOG3: + si->LastTime = 0; + if (si->pLog) + Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, TRUE); + break; + + case GC_ADDLOG: + if (si->pLogEnd) + Log_StreamInEvent(hwndDlg, si->pLog, si, FALSE, FALSE); + else + SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER+500, WINDOW_CLEARLOG, 0); + break; + + case GC_SWITCHNEXTTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1) { + if (i < total -1) + i++; + else + i=0; + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), i); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0 ); + } } + break; + + case GC_SWITCHPREVTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1) { + if (i > 0) + i--; + else + i=total-1; + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), i); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0 ); + } } + break; + + case GC_SWITCHTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1 && i != lParam && total > lParam) { + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), lParam); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0 ); + } } + break; + + case GC_REMOVETAB: + { + SESSION_INFO* s2; + int i = -1; + int tabId = 0; + SESSION_INFO* s1 = (SESSION_INFO*) lParam; + + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + + if (s1) { + if (tabId) { + for (i = 0; i < tabId; i++) { + int ii; + TCITEM tci = {0}; + tci.mask = TCIF_PARAM ; + ii = TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + if (ii != -1) { + s2 = (SESSION_INFO*)tci.lParam; + if (s1 == s2) + goto END_REMOVETAB; + } } } + } + else i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + +END_REMOVETAB: + if (i != -1 && i < tabId) { + TCITEM id = {0}; + SESSION_INFO* s; + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), i); + id.mask = TCIF_PARAM; + if (!TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id)) { + if (!TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i-1, &id)) { + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + } } + + s = (SESSION_INFO*)id.lParam; + if (s) + ShowRoom(s, (WPARAM)WINDOW_VISIBLE, wParam == 1?FALSE:TRUE); + } } + break; + + case GC_ADDTAB: + { + TCITEM tci; + int tabId; + WORD w = 0; + int i = 0; + int indexfound = -1; + int lastlocked = -1; + BOOL bFound = FALSE; + SESSION_INFO* s2; + SESSION_INFO* s1 = (SESSION_INFO*) lParam; + + tci.mask = TCIF_PARAM ; + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + + // does the tab already exist? + for (i = 0; i < tabId; i++) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s2 = (SESSION_INFO*)tci.lParam; + if (s2) { + if (s1 == s2 && !bFound) { + if (!bFound) { + bFound = TRUE; + indexfound = i; + } } + + w = DBGetContactSettingWord(s2->hContact, s2->pszModule, "TabPosition", 0); + if (w) + lastlocked = (int)w; + } } + + w = 0; + + if (!bFound) { // create a new tab + int insertat; + TCHAR szTemp [30]; + + lstrcpyn(szTemp, s1->ptszName, 21); + if (lstrlen(s1->ptszName) >20) + lstrcpyn(szTemp+20, _T("..."), 4); + + tci.mask = TCIF_TEXT|TCIF_PARAM ; + tci.pszText = szTemp; + tci.lParam = lParam; + + // determine insert position + w = DBGetContactSettingWord(s1->hContact, s1->pszModule, "TabPosition", 0); + if (wParam == -1) + insertat = w == 0?tabId:(int)w-1; + else + insertat = (int)wParam; + + w = TabCtrl_InsertItem( GetDlgItem(hwndDlg, IDC_TAB), insertat, &tci ); + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s1); + } + + if (wParam == -1) { + if (bFound) + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), indexfound); + else + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), w); + } } + break; + + case GC_FIXTABICONS: + { + SESSION_INFO* s = (SESSION_INFO*) lParam; + SESSION_INFO* s2; + int i; + if (s) { + TCITEM tci; + int tabId; + + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (i = 0; i < tabId; i++) { + tci.mask = TCIF_PARAM|TCIF_IMAGE ; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { + int image = 0; + if (!(s2->wState&GC_EVENT_HIGHLIGHT)) { + image = s2->wStatus==ID_STATUS_ONLINE?MM_FindModule(s2->pszModule)->OnlineIconIndex:MM_FindModule(s2->pszModule)->OfflineIconIndex; + if (s2->wState&STATE_TALK) + image++; + } + + if (tci.iImage != image) { + tci.mask = TCIF_IMAGE ; + tci.iImage = image; + TabCtrl_SetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + } } } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_SETMESSAGEHIGHLIGHT: + { + SESSION_INFO* s = (SESSION_INFO*) lParam; + SESSION_INFO* s2; + int i; + if (s) { + TCITEM tci; + int tabId; + + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (i = 0; i < tabId; i++) { + tci.mask = TCIF_PARAM ; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { // highlight + s2->wState |= GC_EVENT_HIGHLIGHT; + if (SM_FindSession(si->ptszID, si->pszModule) == s2) + si->wState = s2->wState; + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s2); + if (DBGetContactSettingByte(NULL, "Chat", "FlashWindowHighlight", 0) != 0 && GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) + SetTimer(hwndDlg, TIMERID_FLASHWND, 900, NULL); + break; + } } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_SETTABHIGHLIGHT: + { + SESSION_INFO* s = (SESSION_INFO*) lParam; + SESSION_INFO* s2; + int i; + if (s) { + TCITEM tci; + int tabId; + + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (i = 0; i < tabId; i++) { + tci.mask = TCIF_PARAM ; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { // highlight + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s2); + if (g_Settings.FlashWindow && GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) + SetTimer(hwndDlg, TIMERID_FLASHWND, 900, NULL); + break; + } } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_TABCHANGE: + SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)lParam); + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + break; + + case GC_TABCLICKED: + { + int i; + i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1) { + SESSION_INFO* s; + TCITEM id = {0}; + + id.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + s = (SESSION_INFO*)id.lParam; + if (s) { + if (s->wState&STATE_TALK) { + s->wState &= ~STATE_TALK; + DBWriteContactSettingWord(s->hContact, s->pszModule ,"ApparentMode",(LPARAM) 0); + } + + if (s->wState&GC_EVENT_HIGHLIGHT) { + s->wState &= ~GC_EVENT_HIGHLIGHT; + + if (CallService(MS_CLIST_GETEVENT, (WPARAM)s->hContact, (LPARAM)0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)s->hContact, (LPARAM)"chaticon"); + } + + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s); + if (!s->hWnd) { + ShowRoom(s, (WPARAM)WINDOW_VISIBLE, TRUE); + SendMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + } } } } + break; + + case GC_DROPPEDTAB: + { + TCITEM tci; + SESSION_INFO* s; + int begin = (int)lParam; + int end = (int) wParam; + int i, tabId; + if (begin == end) + break; + + tci.mask = TCIF_PARAM ; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB),begin, &tci); + s = (SESSION_INFO*)tci.lParam; + if (s) { + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), begin); + + SendMessage(hwndDlg, GC_ADDTAB, end, (LPARAM)s); + + // fix the "fixed" positions + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (i = 0; i< tabId ; i++) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB),i, &tci); + s = (SESSION_INFO*)tci.lParam; + if (s && s->hContact && DBGetContactSettingWord(s->hContact, s->pszModule, "TabPosition", 0) != 0) + DBWriteContactSettingWord(s->hContact, s->pszModule, "TabPosition", (WORD)(i + 1)); + } } } + break; + + case GC_SESSIONNAMECHANGE: + { + TCITEM tci; + int i; + int tabId; + SESSION_INFO* s2; + SESSION_INFO* s1 = (SESSION_INFO* ) lParam; + + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (i = 0; i < tabId; i++) { + int j; + tci.mask = TCIF_PARAM ; + j = TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + if (j != -1) { + s2 = (SESSION_INFO*)tci.lParam; + if (s1 == s2) { + tci.mask = TCIF_TEXT ; + tci.pszText = s1->ptszName; + TabCtrl_SetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + } } } } + break; + + case GC_ACKMESSAGE: + SendDlgItemMessage(hwndDlg,IDC_MESSAGE,EM_SETREADONLY,FALSE,0); + SendDlgItemMessage(hwndDlg,IDC_MESSAGE,WM_SETTEXT,0, (LPARAM)""); + return TRUE; + + case WM_CTLCOLORLISTBOX: + SetBkColor((HDC) wParam, g_Settings.crUserListBGColor); + return (INT_PTR) hListBkgBrush; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam; + if (mis->CtlType == ODT_MENU) + { + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + } else + { + int ih = GetTextPixelSize( _T("AQGgl'"), g_Settings.UserListFont,FALSE); + int ih2 = GetTextPixelSize( _T("AQGg'"), g_Settings.UserListHeadingsFont,FALSE); + int font = ih > ih2?ih:ih2; + int height = DBGetContactSettingByte(NULL, "Chat", "NicklistRowDist", 12); + + // make sure we have space for icon! + if (g_Settings.ShowContactStatus) + font = font > 16 ? font : 16; + + mis->itemHeight = height > font?height:font; + } + return TRUE; + } + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam; + if (dis->CtlType == ODT_MENU) + { + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + } else + if (dis->CtlID == IDC_LIST) { + HFONT hFont, hOldFont; + HICON hIcon; + int offset; + int height; + int index = dis->itemID; + USERINFO * ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, index); + if (ui) { + int x_offset = 2; + + height = dis->rcItem.bottom - dis->rcItem.top; + + if (height&1) + height++; + if (height == 10) + offset = 0; + else + offset = height/2 - 4; + hIcon = SM_GetStatusIcon(si, ui); + hFont = (ui->iStatusEx == 0) ? g_Settings.UserListFont : g_Settings.UserListHeadingsFont; + hOldFont = (HFONT) SelectObject(dis->hDC, hFont); + SetBkMode(dis->hDC, TRANSPARENT); + + if (dis->itemAction == ODA_FOCUS && dis->itemState & ODS_SELECTED) + FillRect(dis->hDC, &dis->rcItem, hListSelectedBkgBrush); + else //if (dis->itemState & ODS_INACTIVE) + FillRect(dis->hDC, &dis->rcItem, hListBkgBrush); + + if (g_Settings.ShowContactStatus && g_Settings.ContactStatusFirst && ui->ContactStatus) { + HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top+offset-3,hIcon,16,16,0,NULL, DI_NORMAL); + x_offset += 18; + } + DrawIconEx(dis->hDC,x_offset, dis->rcItem.top + offset,hIcon,10,10,0,NULL, DI_NORMAL); + x_offset += 12; + if (g_Settings.ShowContactStatus && !g_Settings.ContactStatusFirst && ui->ContactStatus) { + HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top+offset-3,hIcon,16,16,0,NULL, DI_NORMAL); + x_offset += 18; + } + + SetTextColor(dis->hDC, ui->iStatusEx == 0?g_Settings.crUserListColor:g_Settings.crUserListHeadingsColor); + TextOut(dis->hDC, dis->rcItem.left+x_offset, dis->rcItem.top, ui->pszNick, lstrlen(ui->pszNick)); + SelectObject(dis->hDC, hOldFont); + + if (si->pAccPropServicesForNickList) + { + wchar_t *nick = mir_t2u(ui->pszNick); + si->pAccPropServicesForNickList->SetHwndPropStr(GetDlgItem(hwndDlg,IDC_LIST), OBJID_CLIENT, dis->itemID+1, PROPID_ACC_NAME, nick); + mir_free(nick); + } + } + return TRUE; + } } + + case GC_UPDATENICKLIST: + { + int i = SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_GETTOPINDEX, 0, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETCOUNT, si->nUsersInNicklist, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETTOPINDEX, i, 0); + SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0); + } + break; + + case GC_EVENT_CONTROL + WM_USER+500: + { + switch(wParam) { + case SESSION_OFFLINE: + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0); + return TRUE; + + case SESSION_ONLINE: + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + return TRUE; + + case WINDOW_HIDDEN: + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + return TRUE; + + case WINDOW_CLEARLOG: + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + return TRUE; + + case SESSION_TERMINATE: + SendMessage(hwndDlg,GC_SAVEWNDPOS,0,0); + if (DBGetContactSettingByte(NULL, "Chat", "SavePosition", 0)) { + DBWriteContactSettingDword(si->hContact, "Chat", "roomx", si->iX); + DBWriteContactSettingDword(si->hContact, "Chat", "roomy", si->iY); + DBWriteContactSettingDword(si->hContact, "Chat", "roomwidth" , si->iWidth); + DBWriteContactSettingDword(si->hContact, "Chat", "roomheight", si->iHeight); + } + if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)"chaticon"); + si->wState &= ~STATE_TALK; + DBWriteContactSettingWord(si->hContact, si->pszModule ,"ApparentMode",(LPARAM) 0); + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + return TRUE; + + case WINDOW_MINIMIZE: + ShowWindow(hwndDlg, SW_MINIMIZE); + goto LABEL_SHOWWINDOW; + + case WINDOW_MAXIMIZE: + ShowWindow(hwndDlg, SW_MAXIMIZE); + goto LABEL_SHOWWINDOW; + + case SESSION_INITDONE: + if (DBGetContactSettingByte(NULL, "Chat", "PopupOnJoin", 0)!=0) + return TRUE; + // fall through + case WINDOW_VISIBLE: + if (IsIconic(hwndDlg)) + ShowWindow(hwndDlg, SW_NORMAL); +LABEL_SHOWWINDOW: + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0); + SendMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0); + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + ShowWindow(hwndDlg, SW_SHOW); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SetForegroundWindow(hwndDlg); + return TRUE; + } } + break; + + case GC_SPLITTERMOVED: + { POINT pt; + RECT rc; + RECT rcLog; + BOOL bFormat = IsWindowVisible(GetDlgItem(hwndDlg,IDC_SMILEY)); + + static int x = 0; + + GetWindowRect(GetDlgItem(hwndDlg,IDC_LOG),&rcLog); + if ((HWND)lParam==GetDlgItem(hwndDlg,IDC_SPLITTERX)) { + int oldSplitterX; + GetClientRect(hwndDlg,&rc); + pt.x=wParam; pt.y=0; + ScreenToClient(hwndDlg,&pt); + + oldSplitterX=si->iSplitterX; + si->iSplitterX=rc.right-pt.x+1; + if (si->iSplitterX < 35) + si->iSplitterX=35; + if (si->iSplitterX > rc.right-rc.left-35) + si->iSplitterX = rc.right-rc.left-35; + g_Settings.iSplitterX = si->iSplitterX; + } + else if ((HWND)lParam==GetDlgItem(hwndDlg,IDC_SPLITTERY)) { + int oldSplitterY; + GetClientRect(hwndDlg,&rc); + pt.x=0; pt.y=wParam; + ScreenToClient(hwndDlg,&pt); + + oldSplitterY=si->iSplitterY; + si->iSplitterY=bFormat?rc.bottom-pt.y+1:rc.bottom-pt.y+20; + if (si->iSplitterY<63) + si->iSplitterY=63; + if (si->iSplitterY>rc.bottom-rc.top-40) + si->iSplitterY = rc.bottom-rc.top-40; + g_Settings.iSplitterY = si->iSplitterY; + } + if (x==2) { + PostMessage(hwndDlg,WM_SIZE,0,0); + x = 0; + } + else x++; + } + break; + + case GC_FIREHOOK: + if (lParam) { + GCHOOK* gch = (GCHOOK *) lParam; + NotifyEventHooks(hSendEvent,0,(WPARAM)gch); + if ( gch->pDest ) { + mir_free( gch->pDest->pszID ); + mir_free( gch->pDest->pszModule ); + mir_free( gch->pDest ); + } + mir_free( gch->ptszText ); + mir_free( gch->ptszUID ); + mir_free( gch ); + } + break; + + case GC_CHANGEFILTERFLAG: + si->iLogFilterFlags = lParam; + break; + + case GC_SHOWFILTERMENU: + { + RECT rc; + HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), hwndDlg, FilterWndProc, (LPARAM)si); + TranslateDialogDefault(hwnd); + GetWindowRect(GetDlgItem(hwndDlg, IDC_FILTER), &rc); + SetWindowPos(hwnd, HWND_TOP, rc.left-85, (IsWindowVisible(GetDlgItem(hwndDlg, IDC_FILTER))||IsWindowVisible(GetDlgItem(hwndDlg, IDC_BOLD)))?rc.top-206:rc.top-186, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW); + } + break; + + case GC_SHOWCOLORCHOOSER: + { + HWND ColorWindow; + RECT rc; + BOOL bFG = lParam == IDC_COLOR?TRUE:FALSE; + COLORCHOOSER * pCC = (COLORCHOOSER *)mir_alloc(sizeof(COLORCHOOSER)); + + GetWindowRect(GetDlgItem(hwndDlg, bFG?IDC_COLOR:IDC_BKGCOLOR), &rc); + pCC->hWndTarget = GetDlgItem(hwndDlg, IDC_MESSAGE); + pCC->pModule = MM_FindModule(si->pszModule); + pCC->xPosition = rc.left+3; + pCC->yPosition = IsWindowVisible(GetDlgItem(hwndDlg, IDC_COLOR))?rc.top-1:rc.top+20; + pCC->bForeground = bFG; + pCC->si = si; + + ColorWindow= CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_COLORCHOOSER), hwndDlg, DlgProcColorToolWindow, (LPARAM) pCC); + } + break; + + case GC_SCROLLTOBOTTOM: + { + SCROLLINFO si = { 0 }; + if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) != 0) { + CHARRANGE sel; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si); + si.fMask = SIF_POS; + si.nPos = si.nMax - si.nPage + 1; + SetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si, TRUE); + sel.cpMin = sel.cpMax = GetRichTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_EXSETSEL, 0, (LPARAM) & sel); + PostMessage(GetDlgItem(hwndDlg, IDC_LOG), WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); + } } + break; + + case WM_TIMER: + if (wParam == TIMERID_FLASHWND) + FlashWindow(hwndDlg, TRUE); + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) + break; + + //fall through + case WM_MOUSEACTIVATE: + { + WINDOWPLACEMENT wp = { 0 }; + + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + g_Settings.iX = wp.rcNormalPosition.left; + g_Settings.iY = wp.rcNormalPosition.top; + g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + + if (g_Settings.TabsEnable) { + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1) { + SESSION_INFO* s; + TCITEM tci; + + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s = (SESSION_INFO*) tci.lParam; + if (s) { + s->wState &= ~GC_EVENT_HIGHLIGHT; + s->wState &= ~STATE_TALK; + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s); + } } } + + if (uMsg != WM_ACTIVATE) + SetFocus(GetDlgItem(hwndDlg,IDC_MESSAGE)); + + SetActiveSession(si->ptszID, si->pszModule); + + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) + FlashWindow(hwndDlg, FALSE); + if (DBGetContactSettingWord(si->hContact, si->pszModule ,"ApparentMode", 0) != 0) + DBWriteContactSettingWord(si->hContact, si->pszModule ,"ApparentMode",(LPARAM) 0); + if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)"chaticon"); + } + break; + + case WM_NOTIFY: + { + LPNMHDR pNmhdr; + + pNmhdr = (LPNMHDR)lParam; + switch (pNmhdr->code) { + case NM_RCLICK: + if (pNmhdr->idFrom == IDC_TAB ) { + int i = TabCtrl_GetCurSel(pNmhdr->hwndFrom); + + if (i != -1) { + SESSION_INFO* s; + HMENU hSubMenu; + TCHITTESTINFO tci = {0}; + TCITEM id = {0}; + int i = 0; + id.mask = TCIF_PARAM; + + tci.pt.x=(short)LOWORD(GetMessagePos()); + tci.pt.y=(short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + + ScreenToClient(GetDlgItem(hwndDlg, IDC_TAB), &tci.pt); + i = TabCtrl_HitTest(pNmhdr->hwndFrom, &tci); + if (i != -1) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + s = (SESSION_INFO*)id.lParam; + + ClientToScreen(GetDlgItem(hwndDlg, IDC_TAB), &tci.pt); + hSubMenu = GetSubMenu(g_hMenu, 5); + TranslateMenu(hSubMenu); + if (s) { + WORD w = DBGetContactSettingWord(s->hContact, s->pszModule, "TabPosition", 0); + if ( w == 0) + CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND|MF_UNCHECKED); + else + CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND|MF_CHECKED); + } + else CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND|MF_UNCHECKED); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, tci.pt.x, tci.pt.y, 0, hwndDlg, NULL)) { + case ID_CLOSE: + if (TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)) == i) + PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + else + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), i); + break; + + case ID_CLOSEOTHER: + { + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)) - 1; + if (tabId > 0) { + if (TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)) != i) + if (s) + ShowRoom(s, WINDOW_VISIBLE, TRUE); + + for(tabId; tabId >= 0; tabId --) { + if (tabId == i) + continue; + + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), tabId); + } } } + break; + + case ID_LOCKPOSITION: + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + if (!(GetMenuState(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND)&MF_CHECKED)) { + if (s->hContact) + DBWriteContactSettingWord(s->hContact, s->pszModule, "TabPosition", (WORD)(i + 1)); + } + else DBDeleteContactSetting(s->hContact, s->pszModule, "TabPosition"); + break; + } } } } + break; + + case EN_MSGFILTER: + if (pNmhdr->idFrom == IDC_LOG && ((MSGFILTER *) lParam)->msg == WM_RBUTTONUP) { + CHARRANGE sel, all = { 0, -1 }; + POINT pt; + UINT uID = 0; + HMENU hMenu = 0; + TCHAR pszWord[4096]; + + pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam); + pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam); + ClientToScreen(pNmhdr->hwndFrom, &pt); + + { // fixing stuff for searches + long iCharIndex, iLineIndex, iChars, start, end, iRes; + POINTL ptl; + + pszWord[0] = '\0'; + ptl.x = (LONG)pt.x; + ptl.y = (LONG)pt.y; + ScreenToClient(GetDlgItem(hwndDlg, IDC_LOG), (LPPOINT)&ptl); + iCharIndex = SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_CHARFROMPOS, 0, (LPARAM)&ptl); + if (iCharIndex < 0) + break; + iLineIndex = SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_EXLINEFROMCHAR, 0, (LPARAM)iCharIndex); + iChars = SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_LINEINDEX, (WPARAM)iLineIndex, 0 ); + start = SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_FINDWORDBREAK, WB_LEFT, iCharIndex);//-iChars; + end = SendMessage(GetDlgItem(hwndDlg, IDC_LOG), EM_FINDWORDBREAK, WB_RIGHT, iCharIndex);//-iChars; + + if (end - start > 0) { + TEXTRANGE tr; + CHARRANGE cr; + static TCHAR szTrimString[] = _T(":;,.!?\'\"><()[]- \r\n"); + ZeroMemory(&tr, sizeof(TEXTRANGE)); + + cr.cpMin = start; + cr.cpMax = end; + tr.chrg = cr; + tr.lpstrText = pszWord; + iRes = SendMessage( GetDlgItem(hwndDlg, IDC_LOG), EM_GETTEXTRANGE, 0, (LPARAM)&tr); + + if (iRes > 0) { + int iLen = lstrlen(pszWord)-1; + while(iLen >= 0 && _tcschr(szTrimString, pszWord[iLen])) { + pszWord[iLen] = _T('\0'); + iLen--; + } } } } + + uID = CreateGCMenu(hwndDlg, &hMenu, 1, pt, si, NULL, pszWord); + switch (uID) { + case 0: + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + break; + + case ID_COPYALL: + SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel); + SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); + SendMessage(pNmhdr->hwndFrom, WM_COPY, 0, 0); + SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel); + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + break; + + case ID_CLEARLOG: + { + SESSION_INFO* s = SM_FindSession(si->ptszID, si->pszModule); + if (s) + { + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + LM_RemoveAll(&s->pLog, &s->pLogEnd); + s->iEventCount = 0; + s->LastTime = 0; + si->iEventCount = 0; + si->LastTime = 0; + si->pLog = s->pLog; + si->pLogEnd = s->pLogEnd; + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + } } + break; + + case ID_SEARCH_GOOGLE: + { + TCHAR szURL[4096]; + if (pszWord[0]) { + mir_sntprintf( szURL, SIZEOF( szURL ), _T("http://www.google.com/search?q=%s"), pszWord ); + CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) szURL); + } + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + } + break; + + case ID_SEARCH_WIKIPEDIA: + { + TCHAR szURL[4096]; + if (pszWord[0]) { + mir_sntprintf( szURL, SIZEOF( szURL ), _T("http://en.wikipedia.org/wiki/%s"), pszWord ); + CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) szURL); + } + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + } + break; + + default: + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID); + break; + } + DestroyGCMenu(&hMenu, 5); + } + break; + + case EN_LINK: + if (pNmhdr->idFrom == IDC_LOG) { + switch (((ENLINK *) lParam)->msg) { + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + { + TEXTRANGE tr; + CHARRANGE sel; + + SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin != sel.cpMax) + break; + tr.chrg = ((ENLINK *) lParam)->chrg; + tr.lpstrText = (LPTSTR)mir_alloc(sizeof(TCHAR)*(tr.chrg.cpMax - tr.chrg.cpMin + 1)); + SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM) & tr); + + if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) { + HMENU hSubMenu; + POINT pt; + + hSubMenu = GetSubMenu(g_hMenu, 2); + TranslateMenu(hSubMenu); + 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 ID_NEW: + CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) tr.lpstrText); + break; + + case ID_CURR: + CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) tr.lpstrText); + break; + + case ID_COPY: + { + HGLOBAL hData; + if (!OpenClipboard(hwndDlg)) + break; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(lstrlen(tr.lpstrText) + 1)); + lstrcpy(( TCHAR* )GlobalLock(hData), tr.lpstrText); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + CloseClipboard(); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + } } + mir_free(tr.lpstrText); + return TRUE; + } + + CallService(MS_UTILS_OPENURL, OUF_TCHAR|OUF_NEWWINDOW, (LPARAM) tr.lpstrText); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + mir_free(tr.lpstrText); + break; + } } } + break; + + case TTN_NEEDTEXT: + if (pNmhdr->idFrom == (UINT_PTR)GetDlgItem(hwndDlg,IDC_LIST)) + { + LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO)lParam; + POINT p; + int item; + USERINFO * ui; + SESSION_INFO* parentdat =(SESSION_INFO*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA); + + GetCursorPos( &p ); + ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST), &p); + item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(p.x, p.y))); + ui = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item); + if ( ui != NULL ) { + static TCHAR ptszBuf[ 1024 ]; + mir_sntprintf( ptszBuf, SIZEOF(ptszBuf), _T("%s: %s\r\n%s: %s\r\n%s: %s"), + TranslateT( "Nick name" ), ui->pszNick, + TranslateT( "Unique id" ), ui->pszUID, + TranslateT( "Status" ), TM_WordToString( parentdat->pStatuses, ui->Status )); + lpttd->lpszText = ptszBuf; + } } + break; + } } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_LIST: + if (HIWORD(wParam) == LBN_DBLCLK) { + TVHITTESTINFO hti; + int item; + USERINFO * ui; + + hti.pt.x=(short)LOWORD(GetMessagePos()); + hti.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST),&hti.pt); + + item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, item); + if (ui) { + if (GetKeyState(VK_SHIFT) & 0x8000) { + LRESULT lResult = (LRESULT)SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL); + int start = LOWORD(lResult); + TCHAR* pszName = (TCHAR*)alloca(sizeof(TCHAR)*(lstrlen(ui->pszUID) + 3)); + if (start == 0) + mir_sntprintf(pszName, lstrlen(ui->pszUID)+3, _T("%s: "), ui->pszUID); + else + mir_sntprintf(pszName, lstrlen(ui->pszUID)+2, _T("%s "), ui->pszUID); + + SendMessage( GetDlgItem(hwndDlg, IDC_MESSAGE), EM_REPLACESEL, FALSE, (LPARAM) pszName ); + PostMessage( hwndDlg, WM_MOUSEACTIVATE, 0, 0 ); + } + else DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL); + } + + return TRUE; + } + + if ( HIWORD(wParam) == LBN_KILLFOCUS ) + RedrawWindow(GetDlgItem(hwndDlg, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + break; + + case IDOK: + { + char* pszRtf; + TCHAR* ptszText, *p1; + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDOK))) + break; + + pszRtf = Message_GetFromStream(hwndDlg, si); + SM_AddCommand(si->ptszID, si->pszModule, pszRtf); + ptszText = DoRtfToTags(pszRtf, si); + p1 = _tcschr(ptszText, '\0'); + + //remove trailing linebreaks + while ( p1 > ptszText && (*p1 == '\0' || *p1 == '\r' || *p1 == '\n')) { + *p1 = '\0'; + p1--; + } + + if ( MM_FindModule(si->pszModule)->bAckMsg ) { + EnableWindow(GetDlgItem(hwndDlg,IDC_MESSAGE),FALSE); + SendDlgItemMessage(hwndDlg,IDC_MESSAGE,EM_SETREADONLY,TRUE,0); + } + else SendDlgItemMessage(hwndDlg,IDC_MESSAGE,WM_SETTEXT,0,(LPARAM)_T("")); + + EnableWindow(GetDlgItem(hwndDlg,IDOK),FALSE); + + DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, (LPARAM)NULL); + mir_free(pszRtf); + mir_free(ptszText); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + break; + + case IDC_SHOWNICKLIST: + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_SHOWNICKLIST))) + break; + if (si->iType == GCW_SERVER) + break; + + si->bNicklistEnabled = !si->bNicklistEnabled; + + SendDlgItemMessage(hwndDlg,IDC_SHOWNICKLIST,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx( si->bNicklistEnabled ? "nicklist" : "nicklist2", FALSE )); + SendMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case IDC_MESSAGE: + EnableWindow(GetDlgItem(hwndDlg, IDOK), GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0); + break; + + case IDC_SMILEY: + { + SMADD_SHOWSEL3 smaddInfo; + RECT rc; + + GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEY), &rc); + + smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3); + smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_MESSAGE); + smaddInfo.targetMessage = EM_REPLACESEL; + smaddInfo.targetWParam = TRUE; + smaddInfo.Protocolname = si->pszModule; + smaddInfo.Direction = 3; + smaddInfo.xPosition = rc.left+3; + smaddInfo.yPosition = rc.top-1; + smaddInfo.hContact = si->hContact; + smaddInfo.hwndParent = hwndDlg; + + if (SmileyAddInstalled) + CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM) &smaddInfo); + } + break; + + case IDC_HISTORY: + { + TCHAR szFile[MAX_PATH]; + TCHAR szName[MAX_PATH]; + TCHAR szFolder[MAX_PATH]; + MODULEINFO * pInfo = MM_FindModule(si->pszModule); + + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_HISTORY))) + break; + + if ( pInfo ) { + TCHAR *szModName = NULL; + mir_sntprintf(szName, MAX_PATH, _T("%s"), pInfo->ptszModDispName ? pInfo->ptszModDispName : (szModName = mir_a2t(si->pszModule))); + mir_free(szModName); + ValidateFilename(szName); + mir_sntprintf(szFolder, MAX_PATH, _T("%s\\%s"), g_Settings.pszLogDir, szName); + mir_sntprintf(szName, MAX_PATH, _T("%s.log"), si->ptszID); + ValidateFilename(szName); + mir_sntprintf(szFile, MAX_PATH, _T("%s\\%s"), szFolder, szName); + ShellExecute(hwndDlg, _T("open"), szFile, NULL, NULL, SW_SHOW); + } } + break; + + case IDC_CLOSE: + SendMessage(hwndDlg, GC_REMOVETAB, 0, 0); + break; + + case IDC_CHANMGR: + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHANMGR))) + break; + DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, (LPARAM)NULL); + break; + + case IDC_FILTER: + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_FILTER))) + break; + + si->bFilterEnabled = !si->bFilterEnabled; + SendDlgItemMessage(hwndDlg,IDC_FILTER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)LoadIconEx( si->bFilterEnabled ? "filter" : "filter2", FALSE )); + if (si->bFilterEnabled && DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0) { + SendMessage(hwndDlg, GC_SHOWFILTERMENU, 0, 0); + break; + } + SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0); + break; + + case IDC_BKGCOLOR: + { + CHARFORMAT2 cf; + + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_BKGCOLOR))) + break; + + if (IsDlgButtonChecked(hwndDlg, IDC_BKGCOLOR )) { + if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0) + SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR); + else if (si->bBGSet) { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = MM_FindModule(si->pszModule)->crColors[si->iBG]; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } + else { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = (COLORREF)DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } + break; + + case IDC_COLOR: + { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_COLOR))) + break; + + if (IsDlgButtonChecked(hwndDlg, IDC_COLOR )) { + if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0) + SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR); + else if (si->bFGSet) { + cf.dwMask = CFM_COLOR; + cf.crTextColor = MM_FindModule(si->pszModule)->crColors[si->iFG]; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } + else { + COLORREF cr; + + LoadMsgDlgFont(17, NULL, &cr); + cf.dwMask = CFM_COLOR; + cf.crTextColor = cr; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } + break; + + case IDC_BOLD: + case IDC_ITALICS: + case IDC_UNDERLINE: + { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE; + cf.dwEffects = 0; + + if (LOWORD(wParam) == IDC_BOLD && !IsWindowEnabled(GetDlgItem(hwndDlg,IDC_BOLD))) + break; + if (LOWORD(wParam) == IDC_ITALICS && !IsWindowEnabled(GetDlgItem(hwndDlg,IDC_ITALICS))) + break; + if (LOWORD(wParam) == IDC_UNDERLINE && !IsWindowEnabled(GetDlgItem(hwndDlg,IDC_UNDERLINE))) + break; + if (IsDlgButtonChecked(hwndDlg, IDC_BOLD)) + cf.dwEffects |= CFE_BOLD; + if (IsDlgButtonChecked(hwndDlg, IDC_ITALICS)) + cf.dwEffects |= CFE_ITALIC; + if (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE)) + cf.dwEffects |= CFE_UNDERLINE; + + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } } + break; + + case WM_KEYDOWN: + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + + case WM_MOVE: + SendMessage(hwndDlg,GC_SAVEWNDPOS,0,1); + break; + + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = si->iSplitterX + 43; + if (mmi->ptMinTrackSize.x < 350) + mmi->ptMinTrackSize.x = 350; + + mmi->ptMinTrackSize.y = si->iSplitterY + 80; + } + break; + + case WM_LBUTTONDBLCLK: + if (LOWORD(lParam) < 30) + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + break; + + case WM_CLOSE: + if (g_Settings.TabsEnable && g_Settings.TabRestore && lParam != 1) { + SESSION_INFO* s; + TCITEM id = {0}; + int j = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)) - 1; + id.mask = TCIF_PARAM; + for(j; j >= 0; j--) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), j, &id); + s = (SESSION_INFO*)id.lParam; + if (s) + TabM_AddTab(s->ptszID, s->pszModule); + } } + + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + break; + + case GC_CLOSEWINDOW: + if (g_Settings.TabsEnable) + SM_SetTabbedWindowHwnd(0, 0); + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + SendMessage(hwndDlg,GC_SAVEWNDPOS,0,0); + + si->hWnd = NULL; + si->wState &= ~STATE_TALK; + DestroyWindow(si->hwndStatus); + si->hwndStatus = NULL; + + if (si->hwndTooltip != NULL) { + HWND hNickList = GetDlgItem(hwndDlg,IDC_LIST); + TOOLINFO ti = { 0 }; + ti.cbSize = sizeof(TOOLINFO); + ti.uId = (UINT_PTR)hNickList; + ti.hwnd = hNickList; + SendMessage( si->hwndTooltip, TTM_DELTOOL, 0, (LPARAM)(LPTOOLINFO)&ti ); + } + DestroyWindow( si->hwndTooltip ); + si->hwndTooltip = NULL; + if (si->pAccPropServicesForNickList) si->pAccPropServicesForNickList->Release(); + SetWindowLongPtr(hwndDlg,GWLP_USERDATA,0); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_SPLITTERX),GWLP_WNDPROC,(LONG_PTR)OldSplitterProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_SPLITTERY),GWLP_WNDPROC,(LONG_PTR)OldSplitterProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_LIST),GWLP_WNDPROC,(LONG_PTR)OldNicklistProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_TAB),GWLP_WNDPROC,(LONG_PTR)OldTabProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MESSAGE),GWLP_WNDPROC,(LONG_PTR)OldMessageProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_LOG),GWLP_WNDPROC,(LONG_PTR)OldLogProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_FILTER),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_COLOR),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc); + SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_BKGCOLOR),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc); + break; + } + return(FALSE); +} diff --git a/src/core/stdclist/clist_10.vcxproj b/src/core/stdclist/clist_10.vcxproj new file mode 100644 index 0000000000..388e84c57a --- /dev/null +++ b/src/core/stdclist/clist_10.vcxproj @@ -0,0 +1,226 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + StdClist + {E71C1722-A41D-4475-87F4-29961A3654BB} + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Disabled + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + commonheaders.h + Level3 + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + true + 0x6590000 + false + $(IntDir)$(TargetName).lib + Windows + 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) + $(SolutionDir)\lib + + + + + Disabled + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + commonheaders.h + Level3 + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + 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) + true + 0x6590000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions) + true + false + true + Fast + Use + commonheaders.h + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + 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) + true + true + true + 0x6590000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions) + true + false + true + Fast + Use + commonheaders.h + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + 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) + true + true + true + 0x6590000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/stdclist/clist_10.vcxproj.filters b/src/core/stdclist/clist_10.vcxproj.filters new file mode 100644 index 0000000000..fa8001046e --- /dev/null +++ b/src/core/stdclist/clist_10.vcxproj.filters @@ -0,0 +1,73 @@ + + + + + {63109169-73b5-4fd9-b189-bfe8ca62f233} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {952f01d3-995f-456b-98ff-785b549b289d} + h;hpp;hxx;hm;inl + + + {97bb8e2e-2508-4f05-bdcf-376efae7e97c} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/src/core/stdclist/docs/clist-license.txt b/src/core/stdclist/docs/clist-license.txt new file mode 100644 index 0000000000..7f1161073d --- /dev/null +++ b/src/core/stdclist/docs/clist-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. + + + Copyright (C) 19yy + + 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. + + , 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/src/core/stdclist/docs/clist-readme.txt b/src/core/stdclist/docs/clist-readme.txt new file mode 100644 index 0000000000..68b9df24d3 --- /dev/null +++ b/src/core/stdclist/docs/clist-readme.txt @@ -0,0 +1,38 @@ +################################################################ +# Classic Contact List Plugin +################################################################ + +About +----- +The Classic Contact List control is used to view your contacts +in Miranda IM. + + +Requirements +------------ + - Miranda IM 0.4 + + +History +------- +0.4.0.0 + - CList separated from core (initial release) + + +Copyright +--------- +Copyright (C) 2003-2005 Miranda IM Development Team + +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/src/core/stdclist/docs/clist-translation.txt b/src/core/stdclist/docs/clist-translation.txt new file mode 100644 index 0000000000..f213719525 --- /dev/null +++ b/src/core/stdclist/docs/clist-translation.txt @@ -0,0 +1,166 @@ +; Common strings that belong to many files +;[Contact List] +;[Groups] +;[Status Bar] +;[Window] + +; ../../plugins/Clist/clcfonts.c +;[Background] +;[Contacts which are 'not on list'] +;[Dividers] +;[Group member counts] +;[Hottrack Text] +;[Offline contacts] +;[Offline contacts to whom you have a different visibility] +;[Online contacts to whom you have a different visibility] +;[Quicksearch Text] +;[Selected Text] +;[Standard contacts] + +; ../../plugins/Clist/clcopts.c +;[Away] +;[DND] +;[Free for chat] +;[Invisible] +;[List] +;[List Background] +;[NA] +;[Not focused] +;[Occupied] +;[Offline] +;[On the phone] +;[Online] +;[Out to lunch] + +; ../../plugins/Clist/clistopts.c +;[Global] + +; ../../plugins/Clist/resource.rc +;[% of screen] +;[&Away\tCtrl+2] +;[&DND\tCtrl+5] +;[&Delete Group] +;[&Free for chat\tCtrl+6] +;[&Hide Offline Users] +;[&Hide Offline Users in here] +;[&Hide/Show] +;[&Invisible\tCtrl+7] +;[&NA\tCtrl+3] +;[&New Group] +;[&New Subgroup] +;[&Offline\tCtrl+0] +;[&Rename Group] +;[&Status] +;['Hide Offline' means to hide:] +;[Active opacity:] +;[Always on top] +;[Always show status in tooltip] +;[Are you sure you want to delete %s?] +;[Ask before deleting contacts] +;[Automatically resize window to height of list] +;[Background colour] +;[Contact List Background] +;[Contact List Sorting] +;[Contact list background:] +;[Contact list:] +;[Cycle icons every] +;[Delete Contact] +;[Dim idle contacts] +;[Disable &Groups] +;[Disable drag and drop of items] +;[Disable groups] +;[Disable icon blinking] +;[Disable rename of items by clicking twice] +;[Draw a line alongside group names] +;[E&xit] +;[Easy move] +;[Enable docking] +;[Fade contact list in/out] +;[Gamma correction] +;[Grey out entire list when:] +;[Group] +;[Hide &Empty Groups] +;[Hide &Offline Users out here] +;[Hide Miranda] +;[Hide contact list after it has been idle for] +;[Hide empty groups] +;[Hide from list only, in order to keep their history and ignore/visibility settings] +;[Hide group counts when there are none online] +;[Hide offline users] +;[Hide vertical scroll bar] +;[Hot track items as mouse passes over] +;[If window is partially covered, bring iy to front] +;[If window is partially covered, bring to front instead of hiding] +;[Inactive opacity:] +;[Indent groups by:] +;[Items] +;[Left margin:] +;[Make sections equal width] +;[Make selection highlight translucent] +;[Minimize to tray] +;[No] +;[Nowhere] +;[Occ&upied\tCtrl+4] +;[On the &Phone\tCtrl+8] +;[On&line\tCtrl+1] +;[Only when statuses differ] +;[Ordering:] +;[Out to &Lunch\tCtrl+9] +;[Pin to desktop] +;[Quicksearch in open groups only] +;[Right click opens Miranda IM menu] +;[Right click opens status menu] +;[Row height:] +;[Scroll list smoothly] +;[Scroll with text] +;[Selection colour] +;[Show] +;[Show bevels on panels] +;[Show counts of number of contacts in a group] +;[Show divider between online and offline contacts] +;[Show drop shadow (restart required)] +;[Show icons] +;[Show menu bar] +;[Show multiple icons] +;[Show protocol names] +;[Show resize grip indicator] +;[Show selection even when list is not focused] +;[Show status bar] +;[Show status text] +;[Show title bar] +;[Single click interface] +;[Size upwards] +;[Slider2] +;[Sort contacts by name] +;[Sort contacts by protocol] +;[Sort contacts by status] +;[Sort groups alphabetically] +;[Spin1] +;[Spin5] +;[Stretch proportionally] +;[Stretch to height] +;[Stretch to width] +;[System tray icon] +;[System tray icon when using multiple protocols] +;[This will erase all history and settings for this contact!] +;[Tile horizontally] +;[Tile vertically] +;[Time:] +;[Title bar text:] +;[Tool style main window] +;[Translucency options (Windows 2000/XP only)] +;[Transparent contact list] +;[Tray] +;[Use Options->Ignore (expert mode) to unhide contacts.] +;[Use Windows colours] +;[Use background image] +;[Visual] +;[Window:] +;[Yes] +;[icon when statuses differ] +;[maximum] +;[milliseconds] +;[ms delay] +;[pixels] +;[seconds] +;[seconds, when statuses differ] diff --git a/src/core/stdclist/docs/clist_classic-translation.txt b/src/core/stdclist/docs/clist_classic-translation.txt new file mode 100644 index 0000000000..2ccfedb7e5 --- /dev/null +++ b/src/core/stdclist/docs/clist_classic-translation.txt @@ -0,0 +1,166 @@ +; Common strings that belong to many files +;[Contact List] +;[Groups] +;[Status Bar] +;[Window] + +; ../../plugins/Clist_classic/clcfonts.cpp +;[Background] +;[Contacts which are 'not on list'] +;[Dividers] +;[Group member counts] +;[Hottrack Text] +;[Offline contacts] +;[Offline contacts to whom you have a different visibility] +;[Online contacts to whom you have a different visibility] +;[Quicksearch Text] +;[Selected Text] +;[Standard contacts] + +; ../../plugins/Clist_classic/clcopts.cpp +;[Away] +;[DND] +;[Free for chat] +;[Invisible] +;[List] +;[List Background] +;[NA] +;[Not focused] +;[Occupied] +;[Offline] +;[On the phone] +;[Online] +;[Out to lunch] + +; ../../plugins/Clist_classic/clistopts.cpp +;[Global] + +; ../../plugins/Clist_classic/resource.rc +;[% of screen] +;[&Away\tCtrl+2] +;[&DND\tCtrl+5] +;[&Delete Group] +;[&Free for chat\tCtrl+6] +;[&Hide Offline Users] +;[&Hide Offline Users in here] +;[&Hide/Show] +;[&Invisible\tCtrl+7] +;[&NA\tCtrl+3] +;[&New Group] +;[&New Subgroup] +;[&Offline\tCtrl+0] +;[&Rename Group] +;[&Status] +;['Hide Offline' means to hide:] +;[Active opacity:] +;[Always on top] +;[Always show status in tooltip] +;[Are you sure you want to delete %s?] +;[Ask before deleting contacts] +;[Automatically resize window to height of list] +;[Background colour] +;[Contact List Background] +;[Contact List Sorting] +;[Contact list background:] +;[Contact list:] +;[Cycle icons every] +;[Delete Contact] +;[Dim idle contacts] +;[Disable &Groups] +;[Disable drag and drop of items] +;[Disable groups] +;[Disable icon blinking] +;[Disable rename of items by clicking twice] +;[Draw a line alongside group names] +;[E&xit] +;[Easy move] +;[Enable docking] +;[Fade contact list in/out] +;[Gamma correction] +;[Grey out entire list when:] +;[Group] +;[Hide &Empty Groups] +;[Hide &Offline Users out here] +;[Hide Miranda] +;[Hide contact list after it has been idle for] +;[Hide empty groups] +;[Hide from list only, in order to keep their history and ignore/visibility settings] +;[Hide group counts when there are none online] +;[Hide offline users] +;[Hide vertical scroll bar] +;[Hot track items as mouse passes over] +;[If window is partially covered, bring iy to front] +;[If window is partially covered, bring to front instead of hiding] +;[Inactive opacity:] +;[Indent groups by:] +;[Items] +;[Left margin:] +;[Make sections equal width] +;[Make selection highlight translucent] +;[Minimize to tray] +;[No] +;[Nowhere] +;[Occ&upied\tCtrl+4] +;[On the &Phone\tCtrl+8] +;[On&line\tCtrl+1] +;[Only when statuses differ] +;[Ordering:] +;[Out to &Lunch\tCtrl+9] +;[Pin to desktop] +;[Quicksearch in open groups only] +;[Right click opens Miranda IM menu] +;[Right click opens status menu] +;[Row height:] +;[Scroll list smoothly] +;[Scroll with text] +;[Selection colour] +;[Show] +;[Show bevels on panels] +;[Show counts of number of contacts in a group] +;[Show divider between online and offline contacts] +;[Show drop shadow (restart required)] +;[Show icons] +;[Show menu bar] +;[Show multiple icons] +;[Show protocol names] +;[Show resize grip indicator] +;[Show selection even when list is not focused] +;[Show status bar] +;[Show status text] +;[Show title bar] +;[Single click interface] +;[Size upwards] +;[Slider2] +;[Sort contacts by name] +;[Sort contacts by protocol] +;[Sort contacts by status] +;[Sort groups alphabetically] +;[Spin1] +;[Spin5] +;[Stretch proportionally] +;[Stretch to height] +;[Stretch to width] +;[System tray icon] +;[System tray icon when using multiple protocols] +;[This will erase all history and settings for this contact!] +;[Tile horizontally] +;[Tile vertically] +;[Time:] +;[Title bar text:] +;[Tool style main window] +;[Translucency options (Windows 2000/XP only)] +;[Transparent contact list] +;[Tray] +;[Use Options->Ignore (expert mode) to unhide contacts.] +;[Use Windows colours] +;[Use background image] +;[Visual] +;[Window:] +;[Yes] +;[icon when statuses differ] +;[maximum] +;[milliseconds] +;[ms delay] +;[pixels] +;[seconds] +;[seconds, when statuses differ] diff --git a/src/core/stdclist/res/blank.ico b/src/core/stdclist/res/blank.ico new file mode 100644 index 0000000000..7845f62fed Binary files /dev/null and b/src/core/stdclist/res/blank.ico differ diff --git a/src/core/stdclist/res/dragcopy.cur b/src/core/stdclist/res/dragcopy.cur new file mode 100644 index 0000000000..89c7c960d5 Binary files /dev/null and b/src/core/stdclist/res/dragcopy.cur differ diff --git a/src/core/stdclist/res/dropuser.cur b/src/core/stdclist/res/dropuser.cur new file mode 100644 index 0000000000..a84b19e28b Binary files /dev/null and b/src/core/stdclist/res/dropuser.cur differ diff --git a/src/core/stdclist/res/hyperlin.cur b/src/core/stdclist/res/hyperlin.cur new file mode 100644 index 0000000000..f0f548c828 Binary files /dev/null and b/src/core/stdclist/res/hyperlin.cur differ diff --git a/src/core/stdclist/res/resource.rc b/src/core/stdclist/res/resource.rc new file mode 100644 index 0000000000..1db5646b80 --- /dev/null +++ b/src/core/stdclist/res/resource.rc @@ -0,0 +1,532 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DELETECONTACT DIALOGEX 0, 0, 284, 90 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Delete Contact" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "No",IDNO,162,38,65,14 + PUSHBUTTON "Yes",IDYES,54,38,65,14 + CONTROL "Hide from list only, in order to keep their history and ignore/visibility settings",IDC_HIDE, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,65,270,9 + LTEXT "Use Options->Ignore (expert mode) to unhide contacts.",IDC_STATIC,20,78,257,8 + CONTROL "Are you sure you want to delete %s?",IDC_TOPLINE,"Static",SS_SIMPLE | SS_NOPREFIX | WS_GROUP,7,7,270,8 + LTEXT "This will erase all history and settings for this contact!",IDC_STATIC,7,18,239,14 +END + +IDD_OPT_CLIST DIALOGEX 0, 0, 314, 204 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Hide offline users",IDC_HIDEOFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,17,124,10 + CONTROL "Hide empty groups",IDC_HIDEEMPTYGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,33,124,10 + CONTROL "Disable groups",IDC_DISABLEGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,50,124,10 + CONTROL "Ask before deleting contacts",IDC_CONFIRMDELETE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,67,124,10 + CONTROL "Sort contacts by name",IDC_SORTBYNAME,"Button",BS_AUTORADIOBUTTON | WS_GROUP,153,14,144,10 + CONTROL "Sort contacts by status",IDC_SORTBYSTATUS,"Button",BS_AUTORADIOBUTTON,153,26,149,10 + CONTROL "Sort contacts by protocol",IDC_SORTBYPROTO,"Button",BS_AUTORADIOBUTTON,153,38,151,10 + CONTROL "Single click interface",IDC_ONECLK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,68,150,10 + CONTROL "Always show status in tooltip",IDC_ALWAYSSTATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,152,81,151,11 + CONTROL "Disable icon blinking",IDC_DISABLEBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,95,86,9 + EDITTEXT IDC_BLINKTIME,153,109,35,12,ES_NUMBER + LTEXT "ms delay",IDC_STMSDELAY,192,110,113,8 + CONTROL "Show",IDC_DONTCYCLE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,10,143,97,10 + COMBOBOX IDC_PRIMARYSTATUS,107,142,78,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "icon when statuses differ",IDC_STATIC,189,144,116,8,NOT WS_GROUP + CONTROL "Cycle icons every",IDC_CYCLE,"Button",BS_AUTORADIOBUTTON,10,160,97,10 + EDITTEXT IDC_CYCLETIME,107,159,30,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_CYCLETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,127,158,10,14 + LTEXT "seconds, when statuses differ",IDC_STATIC,140,161,165,8,NOT WS_GROUP + CONTROL "Show multiple icons",IDC_MULTITRAY,"Button",BS_AUTORADIOBUTTON,10,177,98,10 + CONTROL "Only when statuses differ",IDC_ALWAYSMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,108,177,198,10 + GROUPBOX "Contact List",IDC_STCLISTGROUP,2,2,135,126 + GROUPBOX "System tray icon",IDC_STATIC,143,57,169,70 + GROUPBOX "System tray icon when using multiple protocols",IDC_STATIC,2,131,310,66 + GROUPBOX "Contact List Sorting",IDC_STATIC,143,2,169,54,WS_GROUP + CONTROL "Spin5",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,173,97,11,21 + CONTROL "Disable icon blinking",IDC_ICONBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,84,97,10 +END + +IDD_OPT_CLUI DIALOGEX 0, 0, 313, 245 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Window",IDC_STWINDOWGROUP,4,4,305,154 + CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,18,128,10 + CONTROL "Tool style main window",IDC_TOOLWND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,32,128,10 + CONTROL "Minimize to tray",IDC_MIN2TRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,46,128,10 + CONTROL "Show menu bar",IDC_SHOWMAINMENU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,60,128,10 + CONTROL "Easy move",IDC_CLIENTDRAG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,74,128,10 + CONTROL "Show title bar",IDC_SHOWCAPTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,88,128,10 + LTEXT "Title bar text:",IDC_STATIC,12,106,51,8 + EDITTEXT IDC_TITLETEXT,63,104,72,12,ES_AUTOHSCROLL + CONTROL "Show drop shadow (restart required)",IDC_DROPSHADOW, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,122,138,10 + CONTROL "Pin to desktop",IDC_ONDESKTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,137,128,10 + CONTROL "Hide contact list after it has been idle for",IDC_AUTOHIDE, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,141,18,162,10 + EDITTEXT IDC_HIDETIME,151,33,30,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_HIDETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,172,32,10,14 + LTEXT "seconds",IDC_STATIC01,186,35,56,8 + CONTROL "Automatically resize window to height of list",IDC_AUTOSIZE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,141,55,162,10 + LTEXT "maximum",IDC_STATIC21,151,71,45,8 + EDITTEXT IDC_MAXSIZEHEIGHT,197,69,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin1",IDC_MAXSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,218,68,10,14 + LTEXT "% of screen",IDC_STATIC22,230,71,69,8 + CONTROL "Size upwards",IDC_AUTOSIZEUPWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,151,86,147,10 + CONTROL "If window is partially covered, bring to front instead of hiding",IDC_BRINGTOFRONT, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,141,102,162,16 + CONTROL "Enable docking",IDC_DISABLEDOCKING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,141,135,136,10 + GROUPBOX "Translucency options (Windows 2000/XP only)",IDC_STATIC,4,161,305,80 + CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,174,163,10 + CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,191,151,9 + LTEXT "Inactive opacity:",IDC_STATIC11,23,206,89,8 + CONTROL "Slider2",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,112,205,130,11 + LTEXT "000%",IDC_INACTIVEPERC,246,206,29,8,SS_NOPREFIX + LTEXT "Active opacity:",IDC_STATIC12,23,221,89,8 + CONTROL "Slider2",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,112,221,130,11 + LTEXT "000%",IDC_ACTIVEPERC,246,222,29,8,SS_NOPREFIX +END + +IDD_OPT_CLC DIALOGEX 0, 0, 314, 251 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Items",IDC_STATIC,2,2,310,108 + CONTROL "Show divider between online and offline contacts",IDC_DIVIDERONOFF, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,13,179,10 + CONTROL "Hot track items as mouse passes over",IDC_TRACKSELECT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,27,179,10 + CONTROL "Disable drag and drop of items",IDC_DISABLEDRAGDROP, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,41,179,10 + CONTROL "Disable rename of items by clicking twice",IDC_NOTEDITLABELS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,55,179,10 + CONTROL "Show selection even when list is not focused",IDC_SHOWSELALWAYS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,69,179,10 + CONTROL "Make selection highlight translucent",IDC_NOTNOTRANSLUCENTSEL, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,83,179,10 + CONTROL "Dim idle contacts",IDC_IDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,96,153,10 + LTEXT "'Hide Offline' means to hide:",IDC_STATIC,191,10,112,8 + CONTROL "Tree1",IDC_HIDEOFFLINEOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,191,20,112,84 + GROUPBOX "Groups",IDC_STATIC,2,112,148,136 + CONTROL "Draw a line alongside group names",IDC_LINEWITHGROUPS, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,129,131,16 + CONTROL "Show counts of number of contacts in a group",IDC_SHOWGROUPCOUNTS, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,147,131,16 + CONTROL "Hide group counts when there are none online",IDC_HIDECOUNTSWHENEMPTY, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,165,131,16 + CONTROL "Sort groups alphabetically",IDC_SORTGROUPSALPHA,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,183,131,16 + CONTROL "Quicksearch in open groups only",IDC_QUICKSEARCHVISONLY, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,201,131,16 + LTEXT "Indent groups by:",IDC_STATIC,11,221,67,8 + EDITTEXT IDC_GROUPINDENT,78,219,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_GROUPINDENTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,95,215,10,14 + LTEXT "pixels",IDC_STATIC,112,221,36,8 + GROUPBOX "Visual",IDC_STATIC,156,112,156,136 + CONTROL "Scroll list smoothly",IDC_NOTNOSMOOTHSCROLLING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,123,139,10 + LTEXT "Time:",IDC_STATIC11,174,137,42,8 + EDITTEXT IDC_SMOOTHTIME,216,135,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_SMOOTHTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,239,134,10,14 + LTEXT "milliseconds",IDC_STATIC12,250,137,56,8,SS_CENTERIMAGE + LTEXT "Left margin:",IDC_STATIC,164,163,51,8 + EDITTEXT IDC_LEFTMARGIN,215,161,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_LEFTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,240,161,10,14 + LTEXT "pixels",IDC_STATIC,250,163,54,8 + CONTROL "Hide vertical scroll bar",IDC_NOSCROLLBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,150,140,10 + LTEXT "Row height:",IDC_STATIC,164,178,51,8 + EDITTEXT IDC_ROWHEIGHT,215,176,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_ROWHEIGHTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,240,176,10,14 + LTEXT "pixels",IDC_STATIC,250,178,54,8 + CONTROL "Gamma correction",IDC_GAMMACORRECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,190,140,10 + CONTROL "Grey out entire list when:",IDC_GREYOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,202,139,10 + CONTROL "Tree1",IDC_GREYOUTOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,164,212,141,32 +END + +IDD_OPT_CLCBKG DIALOGEX 0, 0, 235, 154 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Contact List Background",IDC_STATIC,4,4,227,146 + LTEXT "Background colour",IDC_STATIC,59,35,72,8,NOT WS_GROUP + CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,22,35,32,10 + LTEXT "Selection colour",IDC_STATIC,59,51,72,8 + CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,22,51,32,10 + CONTROL "Use background image",IDC_BITMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,70,161,10 + EDITTEXT IDC_FILENAME,22,88,184,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BROWSE,208,88,15,11 + CONTROL "Stretch to width",IDC_STRETCHH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,105,100,10 + CONTROL "Stretch to height",IDC_STRETCHV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,122,105,101,10 + CONTROL "Tile horizontally",IDC_TILEH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,118,100,10 + CONTROL "Tile vertically",IDC_TILEV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,122,118,101,10 + CONTROL "Scroll with text",IDC_SCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,131,100,10 + CONTROL "Stretch proportionally",IDC_PROPORTIONAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,122,131,101,10 + CONTROL "Use Windows colours",IDC_WINCOLOUR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,20,156,10 +END + +IDD_OPT_SBAR DIALOGEX 0, 0, 203, 212 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Status Bar",IDC_STATIC,4,4,195,204 + CONTROL "Show status bar",IDC_SHOWSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,17,176,10 + CONTROL "Show icons",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,33,166,10 + CONTROL "Show protocol names",IDC_SHOWPROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,48,166,10 + CONTROL "Show status text",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,63,166,10 + CONTROL "Right click opens status menu",IDC_RIGHTSTATUS,"Button",BS_AUTORADIOBUTTON,22,160,166,10 + CONTROL "Right click opens Miranda NG menu",IDC_RIGHTMIRANDA, + "Button",BS_AUTORADIOBUTTON,22,147,166,10 + CONTROL "Make sections equal width",IDC_EQUALSECTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,78,166,10 + CONTROL "Show bevels on panels",IDC_SBPANELBEVEL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,94,166,10 + CONTROL "Show resize grip indicator",IDC_SHOWGRIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,110,166,10 +END + +IDD_MODERNOPT_CLIST DIALOGEX 0, 0, 369, 51 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Hide offline users",IDC_HIDEOFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,124,10 + CONTROL "Hide empty groups",IDC_HIDEEMPTYGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,124,10 + CONTROL "Disable groups",IDC_DISABLEGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,37,124,10 + CONTROL "Sort contacts by name",IDC_SORTBYNAME,"Button",BS_AUTORADIOBUTTON | WS_GROUP,194,13,144,10 + CONTROL "Sort contacts by status",IDC_SORTBYSTATUS,"Button",BS_AUTORADIOBUTTON,194,25,149,10 + CONTROL "Sort contacts by protocol",IDC_SORTBYPROTO,"Button",BS_AUTORADIOBUTTON,194,37,151,10 + LTEXT "Ordering:",IDC_TXT_TITLE2,184,0,185,8 + LTEXT "Contact list:",IDC_TXT_TITLE1,1,0,182,8 + CONTROL "Ask before deleting contacts",IDC_CONFIRMDELETE,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,21,75,124,10 + CONTROL "Single click interface",IDC_ONECLK,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,163,76,150,10 + CONTROL "Always show status in tooltip",IDC_ALWAYSSTATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | NOT WS_VISIBLE | WS_TABSTOP,163,89,151,11 + CONTROL "Disable icon blinking",IDC_DISABLEBLINK,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,163,103,86,9 + EDITTEXT IDC_BLINKTIME,165,117,35,12,ES_NUMBER | NOT WS_VISIBLE + LTEXT "ms delay",IDC_STMSDELAY,203,118,113,8,NOT WS_VISIBLE + CONTROL "Show",IDC_DONTCYCLE,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_GROUP,21,151,97,10 + COMBOBOX IDC_PRIMARYSTATUS,119,150,78,70,CBS_DROPDOWNLIST | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "icon when statuses differ",IDC_STATIC,201,152,116,8,NOT WS_VISIBLE | NOT WS_GROUP + CONTROL "Cycle icons every",IDC_CYCLE,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,21,168,97,10 + EDITTEXT IDC_CYCLETIME,119,167,30,12,ES_RIGHT | ES_NUMBER | NOT WS_VISIBLE + CONTROL "",IDC_CYCLETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | NOT WS_VISIBLE,139,166,11,14 + LTEXT "seconds, when statuses differ",IDC_STATIC,151,169,165,8,NOT WS_VISIBLE | NOT WS_GROUP + CONTROL "Show multiple icons",IDC_MULTITRAY,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,21,185,98,10 + CONTROL "Only when statuses differ",IDC_ALWAYSMULTI,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,119,185,198,10 + CONTROL "",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | NOT WS_VISIBLE,185,105,11,21 + CONTROL "Disable icon blinking",IDC_ICONBLINK,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,21,92,97,10 +END + +IDD_MODERNOPT_CLUI DIALOGEX 0, 0, 369, 100 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,128,10 + CONTROL "Tool style main window",IDC_TOOLWND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,128,10 + CONTROL "Minimize to tray",IDC_MIN2TRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,37,128,10 + CONTROL "Hide contact list after it has been idle for",IDC_AUTOHIDE, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,194,13,162,10 + EDITTEXT IDC_HIDETIME,204,25,30,12,ES_RIGHT | ES_NUMBER + CONTROL "",IDC_HIDETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,224,22,11,14 + LTEXT "seconds",IDC_STATIC01,238,27,56,8 + CONTROL "Automatically resize window to height of list",IDC_AUTOSIZE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,42,162,10 + LTEXT "maximum",IDC_STATIC21,204,57,45,8 + EDITTEXT IDC_MAXSIZEHEIGHT,250,54,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_MAXSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,270,54,11,14 + LTEXT "% of screen",IDC_STATIC22,282,57,69,8 + CONTROL "Size upwards",IDC_AUTOSIZEUPWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,70,147,10 + LTEXT "Title bar text:",IDC_STATIC,37,158,51,8,NOT WS_VISIBLE + CONTROL "Show menu bar",IDC_SHOWMAINMENU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,49,128,10 + CONTROL "Easy move",IDC_CLIENTDRAG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,61,128,10 + CONTROL "Show title bar",IDC_SHOWCAPTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,73,128,10 + CONTROL "If window is partially covered, bring iy to front",IDC_BRINGTOFRONT, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,194,85,175,10 + EDITTEXT IDC_TITLETEXT,91,156,72,12,ES_AUTOHSCROLL | NOT WS_VISIBLE + CONTROL "Show drop shadow (restart required)",IDC_DROPSHADOW, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,41,174,138,10 + CONTROL "Pin to desktop",IDC_ONDESKTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,85,128,10 + LTEXT "Window:",IDC_TXT_TITLE1,1,0,368,8 + CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,13,174,163,10 + CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,13,191,151,9 + LTEXT "Inactive opacity:",IDC_STATIC11,23,206,89,8,NOT WS_VISIBLE + CONTROL "",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | NOT WS_VISIBLE | WS_TABSTOP,112,205,130,11 + LTEXT "Active opacity:",IDC_STATIC12,23,221,89,8,NOT WS_VISIBLE + CONTROL "",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | NOT WS_VISIBLE | WS_TABSTOP,112,221,130,11 + LTEXT "000%",IDC_INACTIVEPERC,246,206,29,8,SS_NOPREFIX | NOT WS_VISIBLE + LTEXT "000%",IDC_ACTIVEPERC,246,222,29,8,SS_NOPREFIX | NOT WS_VISIBLE +END + +IDD_MODERNOPT_SBAR DIALOGEX 0, 0, 369, 53 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Show status bar",IDC_SHOWSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,0,0,369,10 + CONTROL "Show icons",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,15,142,10 + CONTROL "Show protocol names",IDC_SHOWPROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,27,142,10 + CONTROL "Show status text",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,39,142,10 + CONTROL "Make sections equal width",IDC_EQUALSECTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,15,142,10 + CONTROL "Show bevels on panels",IDC_SBPANELBEVEL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,27,107,10 + CONTROL "Show resize grip indicator",IDC_SHOWGRIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,39,96,10 + CONTROL "Right click opens status menu",IDC_RIGHTSTATUS,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,22,160,142,10 + CONTROL "Right click opens Miranda NG menu",IDC_RIGHTMIRANDA, + "Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,22,147,142,10 +END + +IDD_MODERNOPT_CLCBKG DIALOGEX 0, 0, 232, 143 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "Background colour",IDC_STATIC,57,28,72,8,NOT WS_GROUP + CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,20,28,32,10 + LTEXT "Selection colour",IDC_STATIC,57,44,72,8 + CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,20,44,32,10 + CONTROL "Use background image",IDC_BITMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,63,161,10 + EDITTEXT IDC_FILENAME,20,79,184,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BROWSE,206,79,15,12 + CONTROL "Stretch to width",IDC_STRETCHH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,96,100,10 + CONTROL "Stretch to height",IDC_STRETCHV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,96,101,10 + CONTROL "Tile horizontally",IDC_TILEH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,109,100,10 + CONTROL "Tile vertically",IDC_TILEV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,109,101,10 + CONTROL "Scroll with text",IDC_SCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,122,100,10 + CONTROL "Stretch proportionally",IDC_PROPORTIONAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,122,101,10 + CONTROL "Use Windows colours",IDC_WINCOLOUR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,156,10 + LTEXT "Contact list background:",IDC_TXT_TITLE1,1,0,230,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DELETECONTACT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 277 + TOPMARGIN, 7 + BOTTOMMARGIN, 85 + END + + IDD_OPT_CLIST, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 312 + VERTGUIDE, 10 + VERTGUIDE, 107 + TOPMARGIN, 2 + BOTTOMMARGIN, 202 + HORZGUIDE, 179 + HORZGUIDE, 196 + END + + IDD_OPT_CLUI, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 309 + VERTGUIDE, 13 + VERTGUIDE, 23 + VERTGUIDE, 112 + VERTGUIDE, 141 + VERTGUIDE, 151 + VERTGUIDE, 175 + VERTGUIDE, 242 + VERTGUIDE, 246 + TOPMARGIN, 4 + BOTTOMMARGIN, 241 + HORZGUIDE, 18 + HORZGUIDE, 39 + HORZGUIDE, 75 + HORZGUIDE, 180 + HORZGUIDE, 196 + END + + IDD_OPT_CLC, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 312 + VERTGUIDE, 11 + VERTGUIDE, 164 + VERTGUIDE, 216 + TOPMARGIN, 2 + BOTTOMMARGIN, 249 + HORZGUIDE, 145 + HORZGUIDE, 163 + HORZGUIDE, 222 + END + + IDD_OPT_CLCBKG, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 231 + VERTGUIDE, 12 + VERTGUIDE, 22 + VERTGUIDE, 122 + TOPMARGIN, 4 + BOTTOMMARGIN, 150 + HORZGUIDE, 24 + HORZGUIDE, 35 + HORZGUIDE, 73 + HORZGUIDE, 89 + HORZGUIDE, 102 + HORZGUIDE, 115 + END + + IDD_OPT_SBAR, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 199 + VERTGUIDE, 12 + VERTGUIDE, 22 + VERTGUIDE, 188 + TOPMARGIN, 4 + BOTTOMMARGIN, 208 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "#include \r\n" + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_HYPERLINKHAND CURSOR "hyperlin.cur" +IDC_DROP CURSOR "dragcopy.cur" +IDC_DROPUSER CURSOR "dropuser.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CLISTMENU MENU +BEGIN + POPUP "&¤" + BEGIN + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_ICQ_EXIT + END + POPUP "&Status" + BEGIN + MENUITEM "&Offline\tCtrl+0", ID_STATUS_OFFLINE, CHECKED + MENUITEM "On&line\tCtrl+1", ID_STATUS_ONLINE + MENUITEM "&Away\tCtrl+2", ID_STATUS_AWAY + MENUITEM "&NA\tCtrl+3", ID_STATUS_NA + MENUITEM "Occ&upied\tCtrl+4", ID_STATUS_OCCUPIED + MENUITEM "&DND\tCtrl+5", ID_STATUS_DND + MENUITEM "&Free for chat\tCtrl+6", ID_STATUS_FREECHAT + MENUITEM "&Invisible\tCtrl+7", ID_STATUS_INVISIBLE + MENUITEM "On the &Phone\tCtrl+8", ID_STATUS_ONTHEPHONE + MENUITEM "Out to &Lunch\tCtrl+9", ID_STATUS_OUTTOLUNCH + END +END + +IDR_CONTEXT MENU +BEGIN + POPUP "Tray" + BEGIN + MENUITEM "&Hide/Show", ID_TRAY_HIDE + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_TRAY_EXIT + END + POPUP "Nowhere" + BEGIN + MENUITEM "&New Group", POPUP_NEWGROUP + MENUITEM SEPARATOR + MENUITEM "&Hide Offline Users", POPUP_HIDEOFFLINE + MENUITEM "Hide &Offline Users out here", POPUP_HIDEOFFLINEROOT + MENUITEM "Hide &Empty Groups", POPUP_HIDEEMPTYGROUPS + MENUITEM "Disable &Groups", POPUP_DISABLEGROUPS + MENUITEM SEPARATOR + MENUITEM "Hide Miranda", POPUP_HIDEMIRANDA + END + POPUP "Group" + BEGIN + MENUITEM "&New Subgroup", POPUP_NEWSUBGROUP + MENUITEM "&Hide Offline Users in here", POPUP_GROUPHIDEOFFLINE + MENUITEM SEPARATOR + MENUITEM "&Rename Group", POPUP_RENAMEGROUP + MENUITEM "&Delete Group", POPUP_DELETEGROUP + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/core/stdclist/res/version.rc b/src/core/stdclist/res/version.rc new file mode 100644 index 0000000000..73ab32afe8 --- /dev/null +++ b/src/core/stdclist/res/version.rc @@ -0,0 +1,56 @@ +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include "..\src\version.h" +#include "winres.h" + +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page( 1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Miranda\0" + VALUE "FileDescription", "Contact list classic\0" + VALUE "FileVersion", __VERSION_STRING "\0" + VALUE "InternalName", "clist_classic\0" + VALUE "LegalCopyright", "Copyright ( c) 2002-12 Miranda team\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "clist_classic.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Contact list plugin\0" + VALUE "ProductVersion", __VERSION_STRING "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC diff --git a/src/core/stdclist/src/clc.h b/src/core/stdclist/src/clc.h new file mode 100644 index 0000000000..d089a213da --- /dev/null +++ b/src/core/stdclist/src/clc.h @@ -0,0 +1,32 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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 FONTID_LAST 7 + +struct ClcContact : public ClcContactBase +{ +}; + +struct ClcData : public ClcDataBase +{ +}; \ No newline at end of file diff --git a/src/core/stdclist/src/clcfonts.cpp b/src/core/stdclist/src/clcfonts.cpp new file mode 100644 index 0000000000..6a2f3062dc --- /dev/null +++ b/src/core/stdclist/src/clcfonts.cpp @@ -0,0 +1,137 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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" + +#define CLIST_FONTID_CONTACTS 0 +#define CLIST_FONTID_INVIS 1 +#define CLIST_FONTID_OFFLINE 2 +#define CLIST_FONTID_NOTONLIST 3 +#define CLIST_FONTID_GROUPS 4 +#define CLIST_FONTID_GROUPCOUNTS 5 +#define CLIST_FONTID_DIVIDERS 6 +#define CLIST_FONTID_OFFINVIS 7 +#define CLIST_FONTID_MAX 7 + +static const TCHAR* szClistFontIdDescr[CLIST_FONTID_MAX + 1] = +{ + LPGENT( "Standard contacts"), + LPGENT( "Online contacts to whom you have a different visibility"), + LPGENT( "Offline contacts"), + LPGENT( "Contacts which are 'not on list'"), + LPGENT( "Groups"), + LPGENT( "Group member counts"), + LPGENT( "Dividers"), + LPGENT( "Offline contacts to whom you have a different visibility" ) +}; + +static int fontListOrder[CLIST_FONTID_MAX + 1] = +{ + CLIST_FONTID_CONTACTS, + CLIST_FONTID_INVIS, + CLIST_FONTID_OFFLINE, + CLIST_FONTID_OFFINVIS, + CLIST_FONTID_NOTONLIST, + CLIST_FONTID_GROUPS, + CLIST_FONTID_GROUPCOUNTS, + CLIST_FONTID_DIVIDERS +}; + +static int FS_FontsChanged(WPARAM wParam, LPARAM lParam) +{ + pcli->pfnClcOptionsChanged(); + return 0; +} + +void RegisterCListFonts() +{ + FontIDT fontid = {0}; + ColourIDT colourid = {0}; + char idstr[10]; + int i; + + fontid.cbSize = sizeof(FontIDT); + fontid.flags = FIDF_ALLOWREREGISTER | FIDF_APPENDNAME | FIDF_NOAS | FIDF_SAVEPOINTSIZE | FIDF_ALLOWEFFECTS; + + for (i = 0; i <= CLIST_FONTID_MAX; i++) { + + switch (fontListOrder[i]) + { + case FONTID_GROUPS: + case FONTID_GROUPCOUNTS: + fontid.flags &= ~FIDF_CLASSMASK; + fontid.flags |= FIDF_CLASSHEADER; + break; + case FONTID_DIVIDERS: + fontid.flags &= ~FIDF_CLASSMASK; + fontid.flags |= FIDF_CLASSSMALL; + break; + default: + fontid.flags &= ~FIDF_CLASSMASK; + fontid.flags |= FIDF_CLASSGENERAL; + break; + } + + strncpy(fontid.dbSettingsGroup, "CLC", sizeof(fontid.dbSettingsGroup)); + _tcsncpy(fontid.group, _T("Contact List"), SIZEOF(fontid.group)); + _tcsncpy(fontid.name, szClistFontIdDescr[fontListOrder[i]], SIZEOF(fontid.name)); + sprintf(idstr, "Font%d", fontListOrder[i]); + strncpy(fontid.prefix, idstr, SIZEOF(fontid.prefix)); + fontid.order = fontListOrder[i]; + + FontRegisterT(&fontid); + } + + // and colours + colourid.cbSize = sizeof(ColourIDT); + colourid.order = 0; + strncpy(colourid.dbSettingsGroup, "CLC", sizeof(colourid.dbSettingsGroup)); + + strncpy(colourid.setting, "BkColour", sizeof(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Background"), SIZEOF(colourid.name)); + _tcsncpy(colourid.group, LPGENT("Contact List"), SIZEOF(colourid.group)); + colourid.defcolour = CLCDEFAULT_BKCOLOUR; + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "SelTextColour", sizeof(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Selected Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_SELTEXTCOLOUR; + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "HotTextColour", sizeof(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Hottrack Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_HOTTEXTCOLOUR; + ColourRegisterT(&colourid); + + strncpy(colourid.setting, "QuickSearchColour", sizeof(colourid.setting)); + _tcsncpy(colourid.name, LPGENT("Quicksearch Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_QUICKSEARCHCOLOUR; + ColourRegisterT(&colourid); + + HookEvent(ME_FONT_RELOAD, FS_FontsChanged); +} diff --git a/src/core/stdclist/src/clcopts.cpp b/src/core/stdclist/src/clcopts.cpp new file mode 100644 index 0000000000..51f9c8a08b --- /dev/null +++ b/src/core/stdclist/src/clcopts.cpp @@ -0,0 +1,479 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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" + +#define DBFONTF_BOLD 1 +#define DBFONTF_ITALIC 2 +#define DBFONTF_UNDERLINE 4 + +struct CheckBoxToStyleEx_t +{ + int id; + DWORD flag; + int not; +} + +static const checkBoxToStyleEx[] = { + {IDC_DISABLEDRAGDROP, CLS_EX_DISABLEDRAGDROP, 0}, + {IDC_NOTEDITLABELS, CLS_EX_EDITLABELS, 1}, + {IDC_SHOWSELALWAYS, CLS_EX_SHOWSELALWAYS, 0}, + {IDC_TRACKSELECT, CLS_EX_TRACKSELECT, 0}, + {IDC_SHOWGROUPCOUNTS, CLS_EX_SHOWGROUPCOUNTS, 0}, + {IDC_HIDECOUNTSWHENEMPTY, CLS_EX_HIDECOUNTSWHENEMPTY, 0}, + {IDC_DIVIDERONOFF, CLS_EX_DIVIDERONOFF, 0}, + {IDC_NOTNOTRANSLUCENTSEL, CLS_EX_NOTRANSLUCENTSEL, 1}, + {IDC_LINEWITHGROUPS, CLS_EX_LINEWITHGROUPS, 0}, + {IDC_QUICKSEARCHVISONLY, CLS_EX_QUICKSEARCHVISONLY, 0}, + {IDC_SORTGROUPSALPHA, CLS_EX_SORTGROUPSALPHA, 0}, + {IDC_NOTNOSMOOTHSCROLLING, CLS_EX_NOSMOOTHSCROLLING, 1} +}; + +struct CheckBoxValues_t +{ + DWORD style; + TCHAR* szDescr; +}; + +static const struct CheckBoxValues_t greyoutValues[] = { + { GREYF_UNFOCUS, LPGENT("Not focused") }, + { 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 const struct CheckBoxValues_t offlineValues[] = { + { 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 LONG CalcMinRowHeight() +{ + int i; + LONG minHeight = 16; + HDC hdc = GetDC(NULL); + for (i = 0; i < FONTID_LAST; i++) { + HFONT hFont; + LOGFONT lf; + COLORREF color; + SIZE fontSize; + pcli->pfnGetFontSetting(i, &lf, &color); + lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); + hFont = CreateFontIndirect(&lf); + hFont = ( HFONT )SelectObject(hdc, hFont); + GetTextExtentPoint32(hdc, _T("x"), 1, &fontSize); + if (fontSize.cy > minHeight) + minHeight = fontSize.cy; + hFont = ( HFONT )SelectObject(hdc,hFont); + DeleteObject(hFont); + } + ReleaseDC(NULL, hdc); + return minHeight; +} + +static INT_PTR CALLBACK DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE, + GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE, + GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + { + int i; + DWORD exStyle = DBGetContactSettingDword(NULL, "CLC", "ExStyle", pcli->pfnGetDefaultExStyle()); + for (i = 0; i < SIZEOF(checkBoxToStyleEx); i++) + CheckDlgButton(hwndDlg, checkBoxToStyleEx[i].id, + (exStyle & checkBoxToStyleEx[i].flag) ^ (checkBoxToStyleEx[i].flag * + checkBoxToStyleEx[i].not) ? BST_CHECKED : BST_UNCHECKED); + } + { + UDACCEL accel[2] = { {0, 10} , {2, 50} }; + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETRANGE, 0, MAKELONG(999, 0)); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETACCEL, SIZEOF(accel), (LPARAM) & accel); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CLC", "ScrollTime", CLCDEFAULT_SCROLLTIME), 0)); + } + CheckDlgButton(hwndDlg, IDC_IDLE, DBGetContactSettingByte(NULL, "CLC", "ShowIdle", CLCDEFAULT_SHOWIDLE) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0)); + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingByte(NULL, "CLC", "LeftMargin", CLCDEFAULT_LEFTMARGIN), 0)); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETRANGE, 0, MAKELONG(50, 0)); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingByte(NULL, "CLC", "GroupIndent", CLCDEFAULT_GROUPINDENT), 0)); + CheckDlgButton(hwndDlg, IDC_GREYOUT, + DBGetContactSettingDword(NULL, "CLC", "GreyoutFlags", CLCDEFAULT_GREYOUTFLAGS) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SMOOTHTIME), IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + EnableWindow(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), greyoutValues, SIZEOF(greyoutValues), + DBGetContactSettingDword(NULL, "CLC", "FullGreyoutFlags", CLCDEFAULT_FULLGREYOUTFLAGS)); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), offlineValues, SIZEOF(offlineValues), + DBGetContactSettingDword(NULL, "CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES)); + CheckDlgButton(hwndDlg, IDC_NOSCROLLBAR, DBGetContactSettingByte(NULL, "CLC", "NoVScrollBar", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_GAMMACORRECT, DBGetContactSettingByte(NULL, "CLC", "GammaCorrect", CLCDEFAULT_GAMMACORRECT) ? BST_CHECKED : BST_UNCHECKED); + { + LONG minHeight = CalcMinRowHeight(); + LONG rowHeight = DBGetContactSettingByte(NULL, "CLC", "RowHeight", CLCDEFAULT_ROWHEIGHT); + if (rowHeight < minHeight) { + rowHeight = minHeight; + } + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, minHeight)); + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, MAKELONG(rowHeight, 0)); + } + return TRUE; + case WM_SETFOCUS: + { + LONG minHeight = CalcMinRowHeight(); + LONG rowHeight = SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0); + if (rowHeight < minHeight) { + rowHeight = minHeight; + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, MAKELONG(rowHeight, 0)); + } + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, minHeight)); + } + break; + case WM_VSCROLL: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_NOTNOSMOOTHSCROLLING) + EnableWindow(GetDlgItem(hwndDlg, IDC_SMOOTHTIME), IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + if (LOWORD(wParam) == IDC_GREYOUT) + EnableWindow(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + if ((LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_SMOOTHTIME || LOWORD(wParam) == IDC_GROUPINDENT + || LOWORD(wParam) == IDC_ROWHEIGHT) + && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_GREYOUTOPTS: + case IDC_HIDEOFFLINEOPTS: + 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: + if (((LPNMHDR) lParam)->code == PSN_APPLY ) { + int i; + DWORD exStyle = 0; + for (i = 0; i < SIZEOF(checkBoxToStyleEx); i++) + if ((IsDlgButtonChecked(hwndDlg, checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].not) + exStyle |= checkBoxToStyleEx[i].flag; + + DBWriteContactSettingDword(NULL, "CLC", "ExStyle", exStyle); + { + DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS)); + DBWriteContactSettingDword(NULL, "CLC", "FullGreyoutFlags", fullGreyoutFlags); + if (IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)) + DBWriteContactSettingDword(NULL, "CLC", "GreyoutFlags", fullGreyoutFlags); + else + DBWriteContactSettingDword(NULL, "CLC", "GreyoutFlags", 0); + } + DBWriteContactSettingByte(NULL, "CLC", "ShowIdle", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_IDLE) ? 1 : 0)); + DBWriteContactSettingDword(NULL, "CLC", "OfflineModes", MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS))); + DBWriteContactSettingByte(NULL, "CLC", "LeftMargin", + (BYTE) SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, "CLC", "ScrollTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "GroupIndent", + (BYTE) SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "NoVScrollBar", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_NOSCROLLBAR) ? 1 : 0)); + DBWriteContactSettingByte(NULL, "CLC", "RowHeight", (BYTE) SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "GammaCorrect", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_GAMMACORRECT)); + pcli->pfnClcOptionsChanged(); + return TRUE; + } + break; + } + break; + case WM_DESTROY: + ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), TVSIL_NORMAL)); + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BITMAP, + DBGetContactSettingByte(NULL, "CLC", "UseBitmap", CLCDEFAULT_USEBITMAP) ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_BKCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, "CLC", "BkColour", CLCDEFAULT_BKCOLOUR)); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_SELBKCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETCOLOUR, 0, + DBGetContactSettingDword(NULL, "CLC", "SelBkColour", CLCDEFAULT_SELBKCOLOUR)); + CheckDlgButton(hwndDlg, IDC_WINCOLOUR, DBGetContactSettingByte(NULL, "CLC", "UseWinColours", 0)); + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + { + DBVARIANT dbv; + if (!DBGetContactSettingString(NULL, "CLC", "BkBitmap", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_FILENAME, dbv.pszVal); + if (ServiceExists(MS_UTILS_PATHTOABSOLUTE)) { + char szPath[MAX_PATH]; + + if (CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM) dbv.pszVal, (LPARAM) szPath)) + SetDlgItemTextA(hwndDlg, IDC_FILENAME, szPath); + } + DBFreeVariant(&dbv); + } + } + { + WORD bmpUse = DBGetContactSettingWord(NULL, "CLC", "BkBmpUse", CLCDEFAULT_BKBMPUSE); + CheckDlgButton(hwndDlg, IDC_STRETCHH, bmpUse & CLB_STRETCHH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_STRETCHV, bmpUse & CLB_STRETCHV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEH, bmpUse & CLBF_TILEH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEV, bmpUse & CLBF_TILEV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SCROLL, bmpUse & CLBF_SCROLL ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROPORTIONAL, bmpUse & CLBF_PROPORTIONAL ? BST_CHECKED : BST_UNCHECKED); + } + { + HRESULT(STDAPICALLTYPE * MySHAutoComplete) (HWND, DWORD); + MySHAutoComplete = (HRESULT(STDAPICALLTYPE *) (HWND, DWORD)) GetProcAddress(GetModuleHandleA("shlwapi"), "SHAutoComplete"); + if (MySHAutoComplete) + MySHAutoComplete(GetDlgItem(hwndDlg, IDC_FILENAME), 1); + } + return TRUE; + case WM_USER + 10: + EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHH), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHV), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TILEH), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TILEV), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SCROLL), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROPORTIONAL), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + break; + case WM_USER + 11: + { + BOOL b = IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOUR), !b); + EnableWindow(GetDlgItem(hwndDlg, IDC_SELCOLOUR), !b); + break; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDC_BROWSE) { + char str[MAX_PATH]; + OPENFILENAMEA ofn = { 0 }; + char filter[512]; + + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, SIZEOF(str)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, SIZEOF(filter), (LPARAM) filter); + ofn.lpstrFilter = filter; + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = SIZEOF(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + if (!GetOpenFileNameA(&ofn)) + break; + SetDlgItemTextA(hwndDlg, IDC_FILENAME, str); + } + else if (LOWORD(wParam) == IDC_FILENAME && HIWORD(wParam) != EN_CHANGE) + break; + if (LOWORD(wParam) == IDC_BITMAP) + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + if (LOWORD(wParam) == IDC_WINCOLOUR) + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, "CLC", "UseBitmap", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + { + COLORREF col; + col = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_BKCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "BkColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "BkColour", col); + col = SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_SELBKCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "SelBkColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "SelBkColour", col); + DBWriteContactSettingByte(NULL, "CLC", "UseWinColours", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR))); + } + { + char str[MAX_PATH], strrel[MAX_PATH]; + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, SIZEOF(str)); + if (ServiceExists(MS_UTILS_PATHTORELATIVE)) { + if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM) str, (LPARAM) strrel)) + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", strrel); + else + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", str); + } + else + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", str); + } + { + WORD flags = 0; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHH)) + flags |= CLB_STRETCHH; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHV)) + flags |= CLB_STRETCHV; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEH)) + flags |= CLBF_TILEH; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEV)) + flags |= CLBF_TILEV; + if (IsDlgButtonChecked(hwndDlg, IDC_SCROLL)) + flags |= CLBF_SCROLL; + if (IsDlgButtonChecked(hwndDlg, IDC_PROPORTIONAL)) + flags |= CLBF_PROPORTIONAL; + DBWriteContactSettingWord(NULL, "CLC", "BkBmpUse", flags); + } + pcli->pfnClcOptionsChanged(); + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +int ClcOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.pszGroup = LPGEN("Contact List"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLC); + odp.pszTitle = LPGEN("List"); + odp.pfnDlgProc = DlgProcClcMainOpts; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLCBKG); + odp.pszTitle = LPGEN("List Background"); + odp.pfnDlgProc = DlgProcClcBkgOpts; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + return 0; +} + +int ClcModernOptInit(WPARAM wParam, LPARAM lParam) +{ + static int iBoldControls[] = + { + IDC_TXT_TITLE1, IDC_TXT_TITLE2, + MODERNOPT_CTRL_LAST + }; + + MODERNOPTOBJECT obj = {0}; + + obj.cbSize = sizeof(obj); + obj.dwFlags = MODEROPT_FLG_TCHAR; + obj.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + obj.hInstance = g_hInst; + obj.iSection = MODERNOPT_PAGE_SKINS; + obj.iType = MODERNOPT_TYPE_SUBSECTIONPAGE; + obj.lptzSubsection = LPGENT("Contact List"); + obj.iBoldControls = iBoldControls; + obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_CLCBKG); + obj.pfnDlgProc = DlgProcClcBkgOpts; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + return 0; +} diff --git a/src/core/stdclist/src/clcpaint.cpp b/src/core/stdclist/src/clcpaint.cpp new file mode 100644 index 0000000000..dfa4147244 --- /dev/null +++ b/src/core/stdclist/src/clcpaint.cpp @@ -0,0 +1,596 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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 HIMAGELIST himlCListClc; +static BYTE divide3[765] = { 255 }; + +static void ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight) +{ + SelectObject(hdc, dat->fontInfo[id].hFont); + SetTextColor(hdc, dat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = dat->fontInfo[id].fontHeight; +} + +static void __inline SetHotTrackColour(HDC hdc, struct ClcData *dat) +{ + if (dat->gammaCorrection) { + COLORREF oldCol, newCol; + int oldLum, newLum; + + oldCol = GetTextColor(hdc); + oldLum = (GetRValue(oldCol) * 30 + GetGValue(oldCol) * 59 + GetBValue(oldCol) * 11) / 100; + newLum = (GetRValue(dat->hotTextColour) * 30 + GetGValue(dat->hotTextColour) * 59 + GetBValue(dat->hotTextColour) * 11) / 100; + if (newLum == 0) { + SetTextColor(hdc, dat->hotTextColour); + return; + } + if (newLum >= oldLum + 20) { + oldLum += 20; + newCol = + RGB(GetRValue(dat->hotTextColour) * oldLum / newLum, GetGValue(dat->hotTextColour) * oldLum / newLum, + GetBValue(dat->hotTextColour) * oldLum / newLum); + } + else if (newLum <= oldLum) { + int r, g, b; + r = GetRValue(dat->hotTextColour) * oldLum / newLum; + g = GetGValue(dat->hotTextColour) * oldLum / newLum; + b = GetBValue(dat->hotTextColour) * oldLum / newLum; + if (r > 255) { + g += (r - 255) * 3 / 7; + b += (r - 255) * 3 / 7; + r = 255; + } + if (g > 255) { + r += (g - 255) * 59 / 41; + if (r > 255) + r = 255; + b += (g - 255) * 59 / 41; + g = 255; + } + if (b > 255) { + r += (b - 255) * 11 / 89; + if (r > 255) + r = 255; + g += (b - 255) * 11 / 89; + if (g > 255) + g = 255; + b = 255; + } + newCol = RGB(r, g, b); + } + else + newCol = dat->hotTextColour; + SetTextColor(hdc, newCol); + } + else + SetTextColor(hdc, dat->hotTextColour); +} + +static int GetStatusOnlineness(int status) +{ + switch (status) { + case ID_STATUS_FREECHAT: return 110; + case ID_STATUS_ONLINE: return 100; + case ID_STATUS_OCCUPIED: return 60; + case ID_STATUS_ONTHEPHONE: return 50; + case ID_STATUS_DND: return 40; + case ID_STATUS_AWAY: return 30; + case ID_STATUS_OUTTOLUNCH: return 20; + case ID_STATUS_NA: return 10; + case ID_STATUS_INVISIBLE: return 5; + } + return 0; +} + +static int GetGeneralisedStatus(void) +{ + int i, status, thisStatus, statusOnlineness, thisOnlineness; + + status = ID_STATUS_OFFLINE; + statusOnlineness = 0; + + for (i = 0; i < pcli->hClcProtoCount; i++) { + thisStatus = pcli->clcProto[i].dwStatus; + if (thisStatus == ID_STATUS_INVISIBLE) + return ID_STATUS_INVISIBLE; + thisOnlineness = GetStatusOnlineness(thisStatus); + if (thisOnlineness > statusOnlineness) { + status = thisStatus; + statusOnlineness = thisOnlineness; + } + } + return status; +} + +static int GetRealStatus(struct ClcContact *contact, int status) +{ + int i; + char *szProto = contact->proto; + if (!szProto) + return status; + for (i = 0; i < pcli->hClcProtoCount; i++) { + if (!lstrcmpA(pcli->clcProto[i].szProto, szProto)) { + return pcli->clcProto[i].dwStatus; + } + } + return status; +} + +static HMODULE themeAPIHandle = NULL; // handle to uxtheme.dll +static HANDLE(WINAPI * MyOpenThemeData) (HWND, LPCWSTR); +static HRESULT(WINAPI * MyCloseThemeData) (HANDLE); +static HRESULT(WINAPI * MyDrawThemeBackground) (HANDLE, HDC, int, int, const RECT *, const RECT *); + +#define MGPROC(x) GetProcAddress(themeAPIHandle,x) +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint) +{ + HDC hdcMem; + RECT clRect; + int i, y, indent, index, fontHeight; + struct ClcGroup *group; + HBITMAP hBmpOsb, hOldBitmap; + HFONT hOldFont; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + int status = GetGeneralisedStatus(); + int grey = 0, groupCountsFontTopShift; + HBRUSH hBrushAlternateGrey = NULL; + // yes I know about GetSysColorBrush() + COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; + int minHeight = 16; + for (i = 0; i < FONTID_LAST; i++) { + if (minHeight < dat->fontInfo[i].fontHeight) { + minHeight = dat->fontInfo[i].fontHeight; + } + } + if (dat->rowHeight < minHeight) { + dat->rowHeight = minHeight; + } + + if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(status) || style & WS_DISABLED) + grey = 1; + else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) + grey = 1; + GetClientRect(hwnd, &clRect); + if (rcPaint == NULL) + rcPaint = &clRect; + if (IsRectEmpty(rcPaint)) + return; + y = -dat->yScroll; + hdcMem = CreateCompatibleDC(hdc); + hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); + hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBmpOsb); + { + TEXTMETRIC tm; + hOldFont = (HFONT)SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift = tm.tmAscent; + SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift -= tm.tmAscent; + } + if (style & CLS_GREYALTERNATE) + hBrushAlternateGrey = + CreateSolidBrush(GetNearestColor(hdcMem, RGB(GetRValue(tmpbkcolour) - 10, GetGValue(tmpbkcolour) - 10, GetBValue(tmpbkcolour) - 10))); + + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + SetBkMode(hdcMem, TRANSPARENT); + { + HBRUSH hBrush; + + hBrush = CreateSolidBrush(tmpbkcolour); + FillRect(hdcMem, rcPaint, hBrush); + DeleteObject(hBrush); + if (dat->hBmpBackground) { + BITMAP bmp; + HDC hdcBmp; + int x, y; + int maxx, maxy; + int destw, desth; + + // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. + SetStretchBltMode(hdcMem, HALFTONE); + + GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); + hdcBmp = CreateCompatibleDC(hdcMem); + SelectObject(hdcBmp, dat->hBmpBackground); + y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; + maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; + maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; + switch (dat->backgroundBmpUse & CLBM_TYPE) { + case CLB_STRETCH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } + else { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + } + else { + destw = clRect.right; + desth = clRect.bottom; + } + break; + case CLB_STRETCHH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + else { + destw = clRect.right; + desth = bmp.bmHeight; + } + break; + case CLB_STRETCHV: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } + else { + destw = bmp.bmWidth; + desth = clRect.bottom; + } + break; + default: //clb_topleft + destw = bmp.bmWidth; + desth = bmp.bmHeight; + break; + } + for (; y < maxy; y += desth) { + if (y < rcPaint->top - desth) + continue; + for (x = 0; x < maxx; x += destw) + StretchBlt(hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); + } + DeleteDC(hdcBmp); + } + } + group = &dat->list; + group->scanIndex = 0; + indent = 0; + for (index = 0; y < rcPaint->bottom;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + indent--; + if (group == NULL) + break; + group->scanIndex++; + continue; + } + if (y > rcPaint->top - dat->rowHeight) { + int iImage = -1; + int selected = index == dat->selection && (dat->showSelAlways || dat->exStyle & CLS_EX_SHOWSELALWAYS || GetFocus() == hwnd) + && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER; + int hottrack = dat->exStyle & CLS_EX_TRACKSELECT && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER && dat->iHotTrack == index; + SIZE textSize, countsSize, spaceSize; + int width, checkboxWidth; + char *szCounts; + + //alternating grey + if (style & CLS_GREYALTERNATE && index & 1) { + RECT rc; + rc.top = y; + rc.bottom = rc.top + dat->rowHeight; + rc.left = 0; + rc.right = clRect.right; + FillRect(hdcMem, &rc, hBrushAlternateGrey); + } + + //setup + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) { + if (group->cl.items[group->scanIndex]->flags & CLCIIF_GROUPFONT) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) + ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) + ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && + ((group->cl.items[group->scanIndex]->flags & CONTACTF_INVISTO + && GetRealStatus(group->cl.items[group->scanIndex], status) != ID_STATUS_INVISIBLE) + || (group->cl.items[group->scanIndex]->flags & CONTACTF_VISTO + && GetRealStatus(group->cl.items[group->scanIndex], status) == ID_STATUS_INVISIBLE) + ) + ) { + // the contact is in the always visible list and the proto is invisible + // the contact is in the always invisible and the proto is in any other mode + ChangeToFont(hdcMem, dat, group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && !(group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE)) + ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + GetTextExtentPoint32(hdcMem, group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText), &textSize); + width = textSize.cx; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + szCounts = pcli->pfnGetGroupCountsText(dat, group->cl.items[group->scanIndex]); + if (szCounts[0]) { + GetTextExtentPoint32A(hdcMem, " ", 1, &spaceSize); + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); + GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); + width += spaceSize.cx + countsSize.cx; + } + } + + if ((style & CLS_CHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) || + (style & CLS_GROUPCHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_GROUP) || + (group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->flags & CLCIIF_CHECKBOX)) + checkboxWidth = dat->checkboxSize + 2; + else + checkboxWidth = 0; + + //background + if (selected) { + int x = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace - 2; + ImageList_DrawEx(dat->himlHighlight, 0, hdcMem, x, y, min(width + 5, clRect.right - x), dat->rowHeight, CLR_NONE, CLR_NONE, + dat->exStyle & CLS_EX_NOTRANSLUCENTSEL ? ILD_NORMAL : ILD_BLEND25); + SetTextColor(hdcMem, dat->selTextColour); + } + else if (hottrack) + SetHotTrackColour(hdcMem, dat); + + //checkboxes + if (checkboxWidth) { + RECT rc; + HANDLE hTheme = NULL; + + // THEME + if (IsWinVerXPPlus()) { + if (!themeAPIHandle) { + themeAPIHandle = GetModuleHandleA("uxtheme"); + if (themeAPIHandle) { + MyOpenThemeData = (HANDLE(WINAPI *) (HWND, LPCWSTR)) MGPROC("OpenThemeData"); + MyCloseThemeData = (HRESULT(WINAPI *) (HANDLE)) MGPROC("CloseThemeData"); + MyDrawThemeBackground = + (HRESULT(WINAPI *) (HANDLE, HDC, int, int, const RECT *, const RECT *)) MGPROC("DrawThemeBackground"); + } + } + // Make sure all of these methods are valid (i would hope either all or none work) + if (MyOpenThemeData && MyCloseThemeData && MyDrawThemeBackground) { + hTheme = MyOpenThemeData(hwnd, L"BUTTON"); + } + } + rc.left = dat->leftMargin + indent * dat->groupIndent; + rc.right = rc.left + dat->checkboxSize; + rc.top = y + ((dat->rowHeight - dat->checkboxSize) >> 1); + rc.bottom = rc.top + dat->checkboxSize; + if (hTheme) { + MyDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? (hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); + } + else + DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (hottrack ? DFCS_HOT : 0)); + if (hTheme && MyCloseThemeData) { + MyCloseThemeData(hTheme); + hTheme = NULL; + } + } + + //icon + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) + iImage = group->cl.items[group->scanIndex]->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) + iImage = group->cl.items[group->scanIndex]->iImage; + if (iImage != -1) { + /*COLORREF colourFg=dat->selBkColour; + int mode=ILD_NORMAL; + if(selected) mode=ILD_SELECTED; + else if(hottrack) {mode=ILD_FOCUS; colourFg=dat->hotTextColour;} + else if(group->cl.items[group->scanIndex]->type==CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags&CONTACTF_NOTONLIST) {colourFg=dat->fontInfo[FONTID_NOTONLIST].colour; mode=ILD_BLEND50;} + ImageList_DrawEx(himlCListClc,iImage,hdcMem,dat->leftMargin+indent*dat->groupIndent+checkboxWidth,y+((dat->rowHeight-16)>>1),0,0,CLR_NONE,colourFg,mode); + */ + // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (hottrack) { + colourFg = dat->hotTextColour; + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && dat->showIdle + && (group->cl.items[group->scanIndex]->flags & CONTACTF_IDLE) + && GetRealStatus(group->cl.items[group->scanIndex], ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + mode = ILD_SELECTED; + ImageList_DrawEx(himlCListClc, iImage, hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth, + y + ((dat->rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + } + + //text + if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) { + RECT rc; + rc.top = y + (dat->rowHeight >> 1); + rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent; + rc.right = rc.left + ((clRect.right - rc.left - textSize.cx) >> 1) - 3; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + TextOut(hdcMem, rc.right + 3, y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText)); + rc.left = rc.right + 6 + textSize.cx; + rc.right = clRect.right; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + RECT rc; + if (szCounts[0]) { + fontHeight = dat->fontInfo[FONTID_GROUPS].fontHeight; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.right = min(clRect.right - countsSize.cx, rc.left + textSize.cx + spaceSize.cx); + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.bottom = rc.top + textSize.cy; + if (rc.right < rc.left + 4) + rc.right = clRect.right + 1; + else + TextOutA(hdcMem, rc.right, rc.top + groupCountsFontTopShift, szCounts, lstrlenA(szCounts)); + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + if (selected) + SetTextColor(hdcMem, dat->selTextColour); + else if (hottrack) + SetHotTrackColour(hdcMem, dat); + rc.right--; + ExtTextOut(hdcMem, rc.left, rc.top, ETO_CLIPPED, &rc, group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText), NULL); + } + else + TextOut(hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace, + y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText)); + if (dat->exStyle & CLS_EX_LINEWITHGROUPS) { + rc.top = y + (dat->rowHeight >> 1); + rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 3; + rc.right = clRect.right - 1 - dat->extraColumnSpacing * dat->extraColumnsCount; + if (rc.right - rc.left > 1) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + } + else { + TCHAR *szText = group->cl.items[group->scanIndex]->szText; + RECT rc; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.right = (clRect.right - clRect.left); + rc.bottom = rc.top; + DrawText(hdcMem, szText, lstrlen(szText), &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + if (selected) { + if (group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER) { + TCHAR *szText = group->cl.items[group->scanIndex]->szText; + RECT rc; + int qlen = lstrlen(dat->szQuickSearch); + SetTextColor(hdcMem, dat->quickSearchColour); + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.right = (clRect.right - clRect.left); + rc.bottom = rc.top; + if (qlen) + DrawText(hdcMem, szText, qlen, &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + } + + //extra icons + for (iImage = 0; iImage < dat->extraColumnsCount; iImage++) { + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (group->cl.items[group->scanIndex]->iExtraImage[iImage] == 0xFF) + continue; + if (selected) + mode = ILD_SELECTED; + else if (hottrack) { + mode = ILD_FOCUS; + colourFg = dat->hotTextColour; + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + ImageList_DrawEx(dat->himlExtraColumns, group->cl.items[group->scanIndex]->iExtraImage[iImage], hdcMem, + clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - iImage), y + ((dat->rowHeight - 16) >> 1), 0, 0, + CLR_NONE, colourFg, mode); + } + } + index++; + y += dat->rowHeight; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded) { + group = group->cl.items[group->scanIndex]->group; + indent++; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + if (dat->iInsertionMark != -1) { //insertion mark + HBRUSH hBrush; + POINT pts[8]; + HRGN hRgn; + + pts[0].x = dat->leftMargin; + pts[0].y = dat->iInsertionMark * dat->rowHeight - dat->yScroll - 4; + pts[1].x = pts[0].x + 2; + pts[1].y = pts[0].y + 3; + pts[2].x = clRect.right - 4; + pts[2].y = pts[1].y; + pts[3].x = clRect.right - 1; + pts[3].y = pts[0].y - 1; + pts[4].x = pts[3].x; + pts[4].y = pts[0].y + 7; + pts[5].x = pts[2].x + 1; + pts[5].y = pts[1].y + 2; + pts[6].x = pts[1].x; + pts[6].y = pts[5].y; + pts[7].x = pts[0].x; + pts[7].y = pts[4].y; + hRgn = CreatePolygonRgn(pts, SIZEOF(pts), ALTERNATE); + hBrush = CreateSolidBrush(dat->fontInfo[FONTID_CONTACTS].colour); + FillRgn(hdcMem, hRgn, hBrush); + DeleteObject(hBrush); + DeleteObject(hRgn); + } + if (!grey) + BitBlt(hdc, rcPaint->left, rcPaint->top, rcPaint->right - rcPaint->left, rcPaint->bottom - rcPaint->top, hdcMem, rcPaint->left, rcPaint->top, + SRCCOPY); + SelectObject(hdcMem,hOldBitmap); + SelectObject(hdcMem,hOldFont); + DeleteDC(hdcMem); + if (hBrushAlternateGrey) + DeleteObject(hBrushAlternateGrey); + if (grey) { + PBYTE bits; + BITMAPINFOHEADER bmih = { 0 }; + int i; + int greyRed, greyGreen, greyBlue; + COLORREF greyColour; + bmih.biBitCount = 32; + bmih.biSize = sizeof(bmih); + bmih.biCompression = BI_RGB; + bmih.biHeight = -clRect.bottom; + bmih.biPlanes = 1; + bmih.biWidth = clRect.right; + bits = (PBYTE) malloc(4 * bmih.biWidth * -bmih.biHeight); + GetDIBits(hdc, hBmpOsb, 0, clRect.bottom, bits, (BITMAPINFO *) & bmih, DIB_RGB_COLORS); + greyColour = GetSysColor(COLOR_3DFACE); + greyRed = GetRValue(greyColour) * 2; + greyGreen = GetGValue(greyColour) * 2; + greyBlue = GetBValue(greyColour) * 2; + if (divide3[0] == 255) { + for (i = 0; i < SIZEOF(divide3); i++) + divide3[i] = (i + 1) / 3; + } + for (i = 4 * clRect.right * clRect.bottom - 4; i >= 0; i -= 4) { + bits[i] = divide3[bits[i] + greyBlue]; + bits[i + 1] = divide3[bits[i + 1] + greyGreen]; + bits[i + 2] = divide3[bits[i + 2] + greyRed]; + } + SetDIBitsToDevice(hdc, 0, 0, clRect.right, clRect.bottom, 0, 0, 0, clRect.bottom, bits, (BITMAPINFO *) & bmih, DIB_RGB_COLORS); + free(bits); + } + DeleteObject(hBmpOsb); +} diff --git a/src/core/stdclist/src/clistmenus.cpp b/src/core/stdclist/src/clistmenus.cpp new file mode 100644 index 0000000000..76be7e93e4 --- /dev/null +++ b/src/core/stdclist/src/clistmenus.cpp @@ -0,0 +1,36 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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_PTR CloseAction(WPARAM wParam,LPARAM lParam) +{ + if (CallService(MS_SYSTEM_OKTOEXIT,(WPARAM)0,(LPARAM)0)) + DestroyWindow(pcli->hwndContactList); + + return(0); +} + +void InitCustomMenus() +{ + CreateServiceFunction( "CloseAction", CloseAction ); +} diff --git a/src/core/stdclist/src/clistopts.cpp b/src/core/stdclist/src/clistopts.cpp new file mode 100644 index 0000000000..83079d6d75 --- /dev/null +++ b/src/core/stdclist/src/clistopts.cpp @@ -0,0 +1,279 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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" + +static INT_PTR CALLBACK DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_USER + 1: + { + HANDLE hContact = (HANDLE) wParam; + DBCONTACTWRITESETTING *ws = (DBCONTACTWRITESETTING *) lParam; + if (hContact == NULL && ws != NULL && ws->szModule != NULL && ws->szSetting != NULL + && lstrcmpiA(ws->szModule, "CList") == 0 && lstrcmpiA(ws->szSetting, "UseGroups") == 0 && IsWindowVisible(hwndDlg)) { + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, ws->value.bVal == 0); + } + break; + } + case WM_DESTROY: + { + UnhookEvent((HANDLE) GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + break; + } + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED, hwndDlg, WM_USER + 1)); + CheckDlgButton(hwndDlg, IDC_ONTOP, DBGetContactSettingByte(NULL, "CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, + DBGetContactSettingByte(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, + DBGetContactSettingByte(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, + DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYNAME, !DBGetContactSettingByte(NULL, "CList", "SortByStatus", SETTING_SORTBYSTATUS_DEFAULT) + && !DBGetContactSettingByte(NULL, "CList", "SortByProto", SETTING_SORTBYPROTO_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYSTATUS, + DBGetContactSettingByte(NULL, "CList", "SortByStatus", SETTING_SORTBYSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYPROTO, + DBGetContactSettingByte(NULL, "CList", "SortByProto", SETTING_SORTBYPROTO_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, + DBGetContactSettingByte(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHIDE, + DBGetContactSettingByte(NULL, "CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (!(caps & CLUIF_HIDEEMPTYGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDEEMPTYGROUPS), SW_HIDE); + if (!(caps & CLUIF_DISABLEGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_DISABLEGROUPS), SW_HIDE); + if (caps & CLUIF_HASONTOPOPTION) + ShowWindow(GetDlgItem(hwndDlg, IDC_ONTOP), SW_HIDE); + if (caps & CLUIF_HASAUTOHIDEOPTION) { + ShowWindow(GetDlgItem(hwndDlg, IDC_AUTOHIDE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_STAUTOHIDESECS), SW_HIDE); + } + } + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1)); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0)); + CheckDlgButton(hwndDlg, IDC_ONECLK, + DBGetContactSettingByte(NULL, "CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, + DBGetContactSettingByte(NULL, "CList", "AlwaysStatus", SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, + !DBGetContactSettingByte(NULL, "CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DONTCYCLE, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CYCLE, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MULTITRAY, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, + DBGetContactSettingByte(NULL, "CList", "DisableTrayFlash", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKTIME), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMSDELAY), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + CheckDlgButton(hwndDlg, IDC_ICONBLINK, DBGetContactSettingByte(NULL, "CList", "NoIconBlink", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_CYCLE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETRANGE, 0, MAKELONG(120, 1)); + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "CycleTime", SETTING_CYCLETIME_DEFAULT), 0)); + { + int i, count, item; + PROTOACCOUNT **accs; + DBVARIANT dbv = { DBVT_DELETED }; + DBGetContactSetting(NULL, "CList", "PrimaryStatus", &dbv); + CallService( MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&accs); + item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) TranslateT("Global")); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) 0); + for (i = 0; i < count; i++) { + if (!IsAccountEnabled(accs[i]) || CallProtoService( accs[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) == 0) + continue; + item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) accs[i]->tszAccountName); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) accs[i]); + if (dbv.type == DBVT_ASCIIZ && !lstrcmpA(dbv.pszVal, accs[i]->szModuleName)) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, item, 0); + } + DBFreeVariant(&dbv); + } + if (-1 == (int) SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0)) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETBUDDY, (WPARAM) GetDlgItem(hwndDlg, IDC_BLINKTIME), 0); // set buddy + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETRANGE, 0, MAKELONG(0x3FFF, 250)); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "CList", "IconFlashTime", 550), 0)); + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_AUTOHIDE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + } + if (LOWORD(wParam) == IDC_DONTCYCLE || LOWORD(wParam) == IDC_CYCLE || LOWORD(wParam) == IDC_MULTITRAY) { + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)); + } + if (LOWORD(wParam) == IDC_DISABLEBLINK) { + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKTIME), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMSDELAY), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + } + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_CYCLETIME) && HIWORD(wParam) != EN_CHANGE) + break; + if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE) + break; + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_CYCLETIME) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + if (LOWORD(wParam) == IDC_BLINKTIME && HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; // dont make apply enabled during buddy set crap + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, "CList", "HideOffline", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE)); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (caps & CLUIF_HIDEEMPTYGROUPS) + DBWriteContactSettingByte(NULL, "CList", "HideEmptyGroups", + (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEEMPTYGROUPS)); + if (caps & CLUIF_DISABLEGROUPS) + DBWriteContactSettingByte(NULL, "CList", "UseGroups", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_DISABLEGROUPS)); + if (!(caps & CLUIF_HASONTOPOPTION)) { + DBWriteContactSettingByte(NULL, "CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + SetWindowPos( pcli->hwndContactList, + IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); + } + if (!(caps & CLUIF_HASAUTOHIDEOPTION)) { + DBWriteContactSettingByte(NULL, "CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + DBWriteContactSettingWord(NULL, "CList", "HideTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0)); + } + } + DBWriteContactSettingByte(NULL, "CList", "SortByStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SORTBYSTATUS)); + DBWriteContactSettingByte(NULL, "CList", "SortByProto", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SORTBYPROTO)); + DBWriteContactSettingByte(NULL, "CList", "ConfirmDelete", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CONFIRMDELETE)); + DBWriteContactSettingByte(NULL, "CList", "Tray1Click", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONECLK)); + DBWriteContactSettingByte(NULL, "CList", "AlwaysStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ALWAYSSTATUS)); + DBWriteContactSettingByte(NULL, "CList", "AlwaysMulti", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_ALWAYSMULTI)); + DBWriteContactSettingByte(NULL, "CList", "TrayIcon", + (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE) ? SETTING_TRAYICON_SINGLE + : (IsDlgButtonChecked(hwndDlg, IDC_CYCLE) ? SETTING_TRAYICON_CYCLE : + SETTING_TRAYICON_MULTI))); + DBWriteContactSettingWord(NULL, "CList", "CycleTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, "CList", "IconFlashTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "DisableTrayFlash", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + DBWriteContactSettingByte(NULL, "CList", "NoIconBlink", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ICONBLINK)); + { + int cur = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0); + PROTOACCOUNT* pa = ( PROTOACCOUNT* )SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETITEMDATA, cur, 0 ); + if ( pa == NULL ) + DBDeleteContactSetting(NULL, "CList", "PrimaryStatus"); + else + DBWriteContactSettingString(NULL, "CList", "PrimaryStatus", pa->szModuleName ); + } + + pcli->pfnTrayIconIconsChanged(); + pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */ + pcli->pfnInvalidateDisplayNameCacheEntry( INVALID_HANDLE_VALUE ); /* force reshuffle */ + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +static UINT expertOnlyControls[] = { IDC_ALWAYSSTATUS }; + +int CListOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = -1000000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLIST); + odp.pszTitle = LPGEN("Contact List"); + odp.pfnDlgProc = DlgProcGenOpts; + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = IDC_STCLISTGROUP; + odp.expertOnlyControls = expertOnlyControls; + odp.nExpertOnlyControls = SIZEOF(expertOnlyControls); + Options_AddPage(wParam, &odp); + return 0; +} + +int CListModernOptInit(WPARAM wParam, LPARAM lParam) +{ + static int iBoldControls[] = + { + IDC_TXT_TITLE1, IDC_TXT_TITLE2, + MODERNOPT_CTRL_LAST + }; + + MODERNOPTOBJECT obj = {0}; + + obj.cbSize = sizeof(obj); + obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE; + obj.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + obj.hInstance = g_hInst; + obj.iSection = MODERNOPT_PAGE_CLIST; + obj.iType = MODERNOPT_TYPE_SECTIONPAGE; + obj.iBoldControls = iBoldControls; + obj.lpzClassicGroup = "Contact List"; + obj.lpzClassicPage = "List"; + obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_CLIST); + obj.pfnDlgProc = DlgProcGenOpts; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + return 0; +} diff --git a/src/core/stdclist/src/cluiopts.cpp b/src/core/stdclist/src/cluiopts.cpp new file mode 100644 index 0000000000..e0b7bdbdee --- /dev/null +++ b/src/core/stdclist/src/cluiopts.cpp @@ -0,0 +1,394 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/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 BOOL(WINAPI * MySetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD); + +static INT_PTR CALLBACK DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, + DBGetContactSettingByte(NULL, "CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONTOP, DBGetContactSettingByte(NULL, "CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TOOLWND, + DBGetContactSettingByte(NULL, "CList", "ToolWindow", SETTING_TOOLWINDOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MIN2TRAY, + DBGetContactSettingByte(NULL, "CList", "Min2Tray", SETTING_MIN2TRAY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), FALSE); + CheckDlgButton(hwndDlg, IDC_SHOWCAPTION, + DBGetContactSettingByte(NULL, "CLUI", "ShowCaption", SETTING_SHOWCAPTION_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWMAINMENU, + DBGetContactSettingByte(NULL, "CLUI", "ShowMainMenu", SETTING_SHOWMAINMENU_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, + DBGetContactSettingByte(NULL, "CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TOOLWND), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TITLETEXT), FALSE); + } + CheckDlgButton(hwndDlg, IDC_FADEINOUT, DBGetContactSettingByte(NULL, "CLUI", "FadeInOut", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOSIZE, DBGetContactSettingByte(NULL, "CLUI", "AutoSize", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DROPSHADOW, DBGetContactSettingByte(NULL, "CList", "WindowShadow", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONDESKTOP, DBGetContactSettingByte(NULL, "CList", "OnDesktop", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEDOCKING, DBGetContactSettingByte(NULL, "CLUI", "DockToSides", 1) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETPOS, 0, DBGetContactSettingByte(NULL, "CLUI", "MaxSizeHeight", 75)); + CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, DBGetContactSettingByte(NULL, "CLUI", "AutoSizeUpward", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHIDE, + DBGetContactSettingByte(NULL, "CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1)); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC01), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC21), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC22), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZEHEIGHT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_AUTOSIZEUPWARD), FALSE); + } + + { DBVARIANT dbv; + if ( !DBGetContactSettingTString(NULL, "CList", "TitleText", &dbv)) { + SetDlgItemText(hwndDlg, IDC_TITLETEXT, dbv.ptszVal); + DBFreeVariant( &dbv ); + } + else SetDlgItemTextA(hwndDlg, IDC_TITLETEXT, MIRANDANAME); + } + if (!IsWinVer2000Plus()) { + EnableWindow(GetDlgItem(hwndDlg, IDC_FADEINOUT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DROPSHADOW), FALSE); + } + else + CheckDlgButton(hwndDlg, IDC_TRANSPARENT, + DBGetContactSettingByte(NULL, "CList", "Transparent", SETTING_TRANSPARENT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + + if (!IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC11), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC12), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSACTIVE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSINACTIVE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIVEPERC), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INACTIVEPERC), FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETPOS, TRUE, DBGetContactSettingByte(NULL, "CList", "Alpha", SETTING_ALPHA_DEFAULT)); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETPOS, TRUE, + DBGetContactSettingByte(NULL, "CList", "AutoAlpha", SETTING_AUTOALPHA_DEFAULT)); + SendMessage(hwndDlg, WM_HSCROLL, 0x12345678, 0); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_AUTOHIDE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC01), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + } + else if (LOWORD(wParam) == IDC_TRANSPARENT) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC11), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC12), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSACTIVE), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSINACTIVE), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIVEPERC), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_INACTIVEPERC), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + } + else if (LOWORD(wParam) == IDC_AUTOSIZE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC21), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC22), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZEHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_AUTOSIZEUPWARD), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + } + else if (LOWORD(wParam) == IDC_TOOLWND) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)); + } + else if (LOWORD(wParam) == IDC_SHOWCAPTION) { + EnableWindow(GetDlgItem(hwndDlg, IDC_TOOLWND), IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND) + && IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TITLETEXT), IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + } + + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_TITLETEXT || LOWORD(wParam) == IDC_MAXSIZEHEIGHT) && + (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + + // Enable apply button + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_HSCROLL: + { + char str[10]; + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_INACTIVEPERC, str); + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_ACTIVEPERC, str); + } + if (wParam != 0x12345678) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == PSN_APPLY) + { + DBWriteContactSettingByte(NULL, "CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + DBWriteContactSettingByte(NULL, "CList", "ToolWindow", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)); + DBWriteContactSettingByte(NULL, "CList", "BringToFront", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BRINGTOFRONT)); + DBWriteContactSettingByte(NULL, "CLUI", "FadeInOut", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT)); + DBWriteContactSettingByte(NULL, "CLUI", "AutoSize", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + DBWriteContactSettingByte(NULL, "CLUI", "MaxSizeHeight", (BYTE) GetDlgItemInt(hwndDlg, IDC_MAXSIZEHEIGHT, NULL, FALSE)); + DBWriteContactSettingByte(NULL, "CLUI", "AutoSizeUpward", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEUPWARD)); + DBWriteContactSettingByte(NULL, "CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + DBWriteContactSettingWord(NULL, "CList", "HideTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "Transparent", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + DBWriteContactSettingByte(NULL, "CList", "Alpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "AutoAlpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "WindowShadow", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DROPSHADOW)); + DBWriteContactSettingByte(NULL, "CList", "OnDesktop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP)); + DBWriteContactSettingByte(NULL, "CLUI", "DockToSides", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DISABLEDOCKING)); + DBWriteContactSettingByte(NULL, "CLUI", "ShowCaption", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + DBWriteContactSettingByte(NULL, "CLUI", "ShowMainMenu", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)); + DBWriteContactSettingByte(NULL, "CLUI", "ClientAreaDrag", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CLIENTDRAG)); + DBWriteContactSettingByte(NULL, "CList", "Min2Tray", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MIN2TRAY)); + { + TCHAR title[256]; + GetDlgItemText(hwndDlg, IDC_TITLETEXT, title, SIZEOF(title)); + DBWriteContactSettingTString(NULL, "CList", "TitleText", title); + SetWindowText(pcli->hwndContactList, title); + } + + pcli->pfnLoadCluiGlobalOpts(); + SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + if (IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) + { + // Window must be hidden to dynamically remove the taskbar button. + // See http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/taskbar.asp + WINDOWPLACEMENT p; + p.length = sizeof(p); + GetWindowPlacement(pcli->hwndContactList, &p); + ShowWindow(pcli->hwndContactList, SW_HIDE); + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, + GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_APPWINDOW | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE); + SetWindowPlacement(pcli->hwndContactList, &p); + } + else + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW | WS_EX_APPWINDOW); + + if (IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP)) + { + HWND hProgMan = FindWindow(_T("Progman"), NULL); + if (hProgMan) + SetParent(pcli->hwndContactList, hProgMan); + } + else + SetParent(pcli->hwndContactList, NULL); + + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)) + { + int style = GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, style); + } + else + { + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, + GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)); + } + + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)) + SetMenu(pcli->hwndContactList, NULL); + else + SetMenu(pcli->hwndContactList, pcli->hMenuMain); + + SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + + if (IsIconic(pcli->hwndContactList) && !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) + ShowWindow(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_MIN2TRAY) ? SW_HIDE : SW_SHOW); + if (IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) + { + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + if (MySetLayeredWindowAttributes) + MySetLayeredWindowAttributes(pcli->hwndContactList, RGB(0, 0, 0), + (BYTE) DBGetContactSettingByte(NULL, "CList", "AutoAlpha", SETTING_AUTOALPHA_DEFAULT), + LWA_ALPHA); + } + else + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_LAYERED); + + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); //forces it to send a cln_listsizechanged + + return TRUE; + } + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_SHOWSBAR, DBGetContactSettingByte(NULL, "CLUI", "ShowSBar", 1) ? BST_CHECKED : BST_UNCHECKED); + { + BYTE showOpts = DBGetContactSettingByte(NULL, "CLUI", "SBarShow", 1); + CheckDlgButton(hwndDlg, IDC_SHOWICON, showOpts & 1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWPROTO, showOpts & 2 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, showOpts & 4 ? BST_CHECKED : BST_UNCHECKED); + } + CheckDlgButton(hwndDlg, IDC_RIGHTSTATUS, DBGetContactSettingByte(NULL, "CLUI", "SBarRightClk", 0) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg, IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, DBGetContactSettingByte(NULL, "CLUI", "EqualSections", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SBPANELBEVEL, DBGetContactSettingByte(NULL, "CLUI", "SBarBevel", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWGRIP, DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) ? BST_CHECKED : BST_UNCHECKED); + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EQUALSECTIONS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SBPANELBEVEL), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWGRIP), FALSE); + } + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_SHOWSBAR) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_EQUALSECTIONS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SBPANELBEVEL), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWGRIP), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == PSN_APPLY ) { + DBWriteContactSettingByte(NULL, "CLUI", "ShowSBar", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + DBWriteContactSettingByte(NULL, "CLUI", "SBarShow", + (BYTE) ((IsDlgButtonChecked(hwndDlg, IDC_SHOWICON) ? 1 : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO) ? 2 : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS) ? 4 : 0))); + DBWriteContactSettingByte(NULL, "CLUI", "SBarRightClk", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_RIGHTMIRANDA)); + DBWriteContactSettingByte(NULL, "CLUI", "EqualSections", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS)); + DBWriteContactSettingByte(NULL, "CLUI", "SBarBevel", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SBPANELBEVEL)); + pcli->pfnLoadCluiGlobalOpts(); + if (DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) != (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)) { + HWND parent = GetParent(pcli->hwndStatus); + int flags = WS_CHILD | CCS_BOTTOM; + DBWriteContactSettingByte(NULL, "CLUI", "ShowGrip", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)); + ShowWindow(pcli->hwndStatus, SW_HIDE); + DestroyWindow(pcli->hwndStatus); + flags |= DBGetContactSettingByte(NULL, "CLUI", "ShowSBar", 1) ? WS_VISIBLE : 0; + flags |= DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) ? SBARS_SIZEGRIP : 0; + pcli->hwndStatus = CreateWindow(STATUSCLASSNAME, NULL, flags, 0, 0, 0, 0, parent, NULL, g_hInst, NULL); + } + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) + ShowWindow(pcli->hwndStatus, SW_SHOW); + else + ShowWindow(pcli->hwndStatus, SW_HIDE); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + return TRUE; + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +static UINT expertOnlyControls[] = +{ + IDC_BRINGTOFRONT, IDC_AUTOSIZE, IDC_STATIC21, IDC_MAXSIZEHEIGHT, IDC_MAXSIZESPIN, + IDC_STATIC22, IDC_AUTOSIZEUPWARD, IDC_SHOWMAINMENU, IDC_SHOWCAPTION, IDC_CLIENTDRAG +}; + +int CluiOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLUI); + odp.pszTitle = LPGEN("Window"); + odp.pszGroup = LPGEN("Contact List"); + odp.pfnDlgProc = DlgProcCluiOpts; + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = IDC_STWINDOWGROUP; + odp.expertOnlyControls = expertOnlyControls; + odp.nExpertOnlyControls = SIZEOF(expertOnlyControls); + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SBAR); + odp.pszTitle = LPGEN("Status Bar"); + odp.pfnDlgProc = DlgProcSBarOpts; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + odp.nIDBottomSimpleControl = 0; + odp.nExpertOnlyControls = 0; + odp.expertOnlyControls = NULL; + Options_AddPage(wParam, &odp); + return 0; +} + +int CluiModernOptInit(WPARAM wParam, LPARAM lParam) +{ + static int iBoldControls[] = + { + IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_SHOWSBAR, + MODERNOPT_CTRL_LAST + }; + + MODERNOPTOBJECT obj = {0}; + + obj.cbSize = sizeof(obj); + obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE; + obj.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + obj.hInstance = g_hInst; + obj.iSection = MODERNOPT_PAGE_CLIST; + obj.iType = MODERNOPT_TYPE_SECTIONPAGE; + obj.iBoldControls = iBoldControls; + obj.lpzClassicGroup = "Contact List"; + obj.lpzClassicPage = "List"; + obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_CLUI); + obj.pfnDlgProc = DlgProcCluiOpts; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_SBAR); + obj.pfnDlgProc = DlgProcSBarOpts; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + return 0; +} diff --git a/src/core/stdclist/src/commonheaders.h b/src/core/stdclist/src/commonheaders.h new file mode 100644 index 0000000000..11522da792 --- /dev/null +++ b/src/core/stdclist/src/commonheaders.h @@ -0,0 +1,77 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2005 Miranda ICQ/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 _CRT_SECURE_NO_WARNINGS +#define MIRANDA_VER 0x0A00 + +#define _WIN32_WINNT 0x0600 +#define _WIN32_IE 0x0501 + +#include "m_stdhdr.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clc.h" +#include "version.h" +#include "resource.h" + +// shared vars +extern HINSTANCE g_hInst; + +/* most free()'s are invalid when the code is executed from a dll, so this changes + all the bad free()'s to good ones, however it's still incorrect code. The reasons for not + changing them include: + + * DBFreeVariant has a CallService() lookup + * free() is executed in some large loops to do with clist creation of group data + * easy search and replace + +*/ diff --git a/src/core/stdclist/src/init.cpp b/src/core/stdclist/src/init.cpp new file mode 100644 index 0000000000..60b3bae86e --- /dev/null +++ b/src/core/stdclist/src/init.cpp @@ -0,0 +1,176 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2005 Miranda ICQ/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" + +HINSTANCE g_hInst = 0; +CLIST_INTERFACE* pcli = NULL; +HIMAGELIST himlCListClc = NULL; +int hLangpack; + +BOOL(WINAPI * MySetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD) = NULL; + +///////////////////////////////////////////////////////////////////////////////////////// +// external functions + +void RegisterCListFonts( void ); +void InitCustomMenus( void ); +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint); + +int ClcOptInit(WPARAM wParam, LPARAM lParam); +int ClcModernOptInit(WPARAM wParam, LPARAM lParam); +int CluiOptInit(WPARAM wParam, LPARAM lParam); +int CluiModernOptInit(WPARAM wParam, LPARAM lParam); +int CListOptInit(WPARAM wParam, LPARAM lParam); +int CListModernOptInit(WPARAM wParam, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////////////////// +// dll stub + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + g_hInst = hInstDLL; + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// returns the plugin information + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + MIRANDA_VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + //{240A91DC-9464-457a-9787-FF1EA88E77E3} + {0x240a91dc, 0x9464, 0x457a, { 0x97, 0x87, 0xff, 0x1e, 0xa8, 0x8e, 0x77, 0xe3 }} +}; + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// returns plugin's interfaces information + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_CLIST, MIID_LAST}; + +///////////////////////////////////////////////////////////////////////////////////////// +// called when number of accounts has been changed + +static int OnAccountsChanged( WPARAM wParam, LPARAM lParam ) +{ + himlCListClc = (HIMAGELIST) CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// called when all modules got loaded + +static int OnModernOptsInit(WPARAM wParam, LPARAM lParam); +static int OnModulesLoaded( WPARAM wParam, LPARAM lParam ) +{ + HookEvent(ME_MODERNOPT_INITIALIZE, OnModernOptsInit); + RegisterCListFonts(); + himlCListClc = (HIMAGELIST) CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// options iniatialization + +static int OnOptsInit(WPARAM wParam, LPARAM lParam) +{ + ClcOptInit(wParam, lParam); + CluiOptInit(wParam, lParam); + CListOptInit(wParam, lParam); + return 0; +} + +static int OnModernOptsInit(WPARAM wParam, LPARAM lParam) +{ + ClcModernOptInit(wParam, lParam); + CListModernOptInit(wParam, lParam); + CluiModernOptInit(wParam, lParam); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// menu status services + +static INT_PTR GetStatusMode(WPARAM wParam, LPARAM lParam) +{ + return pcli->currentDesiredStatusMode; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// main clist initialization routine + +extern "C" __declspec(dllexport) int CListInitialise() +{ + mir_getLP( &pluginInfo ); + + pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst); + if ( (INT_PTR)pcli == CALLSERVICE_NOTFOUND ) { +LBL_Error: + MessageBoxA( NULL, "This version of plugin requires Miranda IM 0.8.0.9 or later", "Fatal error", MB_OK ); + return 1; + } + if ( pcli->version < 6 ) + goto LBL_Error; + + pcli->pfnPaintClc = PaintClc; + + MySetLayeredWindowAttributes = (BOOL(WINAPI *) (HWND, COLORREF, BYTE, DWORD)) GetProcAddress( + LoadLibraryA("user32.dll"), "SetLayeredWindowAttributes"); + + CreateServiceFunction(MS_CLIST_GETSTATUSMODE, GetStatusMode); + + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + HookEvent(ME_PROTO_ACCLISTCHANGED, OnAccountsChanged); + HookEvent(ME_OPT_INITIALISE, OnOptsInit); + + InitCustomMenus(); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// a plugin loader aware of CList exports will never call this. + +extern "C" __declspec(dllexport) int Load(void) +{ + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// a plugin unloader + +extern "C" __declspec(dllexport) int Unload(void) +{ + return 0; +} \ No newline at end of file diff --git a/src/core/stdclist/src/resource.h b/src/core/stdclist/src/resource.h new file mode 100644 index 0000000000..541c69b212 --- /dev/null +++ b/src/core/stdclist/src/resource.h @@ -0,0 +1,163 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define IDD_OPT_CLIST 126 +#define IDR_CONTEXT 180 +#define IDC_DROP 183 +#define IDD_OPT_HOTKEY 184 +#define IDR_CLISTMENU 199 +#define IDC_HYPERLINKHAND 214 +#define IDC_DROPUSER 215 +#define IDD_OPT_CLUI 218 +#define IDD_OPT_CLC 228 +#define IDD_OPT_CLCBKG 230 +#define IDD_OPT_SBAR 234 +#define IDD_OPT_CLCTEXTSIMPLE 239 +#define IDD_DELETECONTACT 254 +#define IDD_MODERNOPT_CLIST 288 +#define IDD_MODERNOPT_CLUI 289 +#define IDD_MODERNOPT_SBAR 290 +#define IDD_MODERNOPT_CLCBKG 291 +#define IDC_MIN2TRAY 1073 +#define IDC_ONTOP 1074 +#define IDC_SHOWMAINMENU 1075 +#define IDC_CLIENTDRAG 1076 +#define IDC_TOOLWND 1097 +#define IDC_ONECLK 1098 +#define IDC_SHOWCAPTION 1098 +#define IDC_HIDEOFFLINE 1099 +#define IDC_SHOWHIDE 1100 +#define IDC_HIDEEMPTYGROUPS 1100 +#define IDC_SORTBYSTATUS 1101 +#define IDC_FADEINOUT 1101 +#define IDC_READMSG 1102 +#define IDC_AUTOSIZE 1102 +#define IDC_DISABLEGROUPS 1102 +#define IDC_AUTOSIZEUPWARD 1103 +#define IDC_ALWAYSSTATUS 1103 +#define IDC_NETSEARCH 1104 +#define IDC_CONFIRMDELETE 1104 +#define IDC_SORTBYPROTO 1105 +#define IDC_SHOWOPTIONS 1105 +#define IDC_SEARCHURL 1106 +#define IDC_TRANSPARENT 1124 +#define IDC_TRANSINACTIVE 1126 +#define IDC_TRANSACTIVE 1128 +#define IDC_STATIC11 1154 +#define IDC_STATIC12 1155 +#define IDC_STATIC21 1156 +#define IDC_STATIC22 1157 +#define IDC_HKSHOWHIDE 1162 +#define IDC_HKREADMSG 1163 +#define IDC_HKSEARCH 1164 +#define IDC_HKSHOWOPTIONS 1165 +#define IDC_BROWSE 1184 +#define IDC_INACTIVEPERC 1187 +#define IDC_ACTIVEPERC 1188 +#define IDC_SEARCHNEWWND 1188 +#define IDC_TITLETEXT 1196 +#define IDC_AUTOHIDE 1235 +#define IDC_HIDETIME 1236 +#define IDC_MAXSIZEHEIGHT 1254 +#define IDC_MAXSIZESPIN 1255 +#define IDC_BKGCOLOUR 1269 +#define IDC_FILENAME 1271 +#define IDC_SCROLL 1277 +#define IDC_PROPORTIONAL 1278 +#define IDC_SELCOLOUR 1281 +#define IDC_SMOOTHTIME 1283 +#define IDC_SMOOTHTIMESPIN 1284 +#define IDC_GREYOUT 1285 +#define IDC_ROWHEIGHT 1286 +#define IDC_ROWHEIGHTSPIN 1287 +#define IDC_GREYOUTOPTS 1288 +#define IDC_GROUPINDENT 1289 +#define IDC_GROUPINDENTSPIN 1290 +#define IDC_LEFTMARGIN 1291 +#define IDC_SAMPLE 1292 +#define IDC_LEFTMARGINSPIN 1292 +#define IDC_FONTSIZE 1293 +#define IDC_STRETCHH 1298 +#define IDC_STRETCHV 1299 +#define IDC_TILEH 1300 +#define IDC_SCRIPT 1300 +#define IDC_TILEV 1301 +#define IDC_GAMMACORRECT 1302 +#define IDC_HIDEOFFLINEOPTS 1308 +#define IDC_DONTCYCLE 1315 +#define IDC_PRIMARYSTATUS 1316 +#define IDC_CYCLE 1317 +#define IDC_CYCLETIME 1318 +#define IDC_CYCLETIMESPIN 1319 +#define IDC_HIDETIMESPIN 1320 +#define IDC_MULTITRAY 1321 +#define IDC_ALWAYSMULTI 1322 +#define IDC_SHOWICON 1323 +#define IDC_SHOWPROTO 1324 +#define IDC_SHOWSTATUS 1325 +#define IDC_EQUALSECTIONS 1326 +#define IDC_SHOWSBAR 1329 +#define IDC_RIGHTMIRANDA 1330 +#define IDC_RIGHTSTATUS 1331 +#define IDC_SORTBYNAME 1347 +#define IDC_STAUTOHIDESECS 1349 +#define IDC_STCLISTGROUP 1350 +#define IDC_DISABLEDRAGDROP 1351 +#define IDC_NOTEDITLABELS 1352 +#define IDC_SHOWSELALWAYS 1353 +#define IDC_TRACKSELECT 1354 +#define IDC_SHOWGROUPCOUNTS 1355 +#define IDC_HIDECOUNTSWHENEMPTY 1356 +#define IDC_DIVIDERONOFF 1357 +#define IDC_NOTNOTRANSLUCENTSEL 1358 +#define IDC_LINEWITHGROUPS 1359 +#define IDC_QUICKSEARCHVISONLY 1360 +#define IDC_SORTGROUPSALPHA 1361 +#define IDC_NOTNOSMOOTHSCROLLING 1362 +#define IDC_BITMAP 1363 +#define IDC_STWINDOWGROUP 1364 +#define IDC_STATIC01 1365 +#define IDC_HIDE 1534 +#define IDC_TOPLINE 1535 +#define IDC_HOTKEYURLSTR 1567 +#define IDC_BRINGTOFRONT 1579 +#define IDC_BLINKTIME 1607 +#define IDC_BLINKSPIN 1608 +#define IDC_DISABLEBLINK 1609 +#define IDC_IDLE 1610 +#define IDC_SBPANELBEVEL 1611 +#define IDC_DROPSHADOW 1612 +#define IDC_SHOWGRIP 1612 +#define IDC_NOSCROLLBAR 1613 +#define IDC_TXT_TITLE1 1617 +#define IDC_TXT_TITLE2 1618 +#define IDC_ONDESKTOP 1657 +#define IDC_DISABLEDOCKING 1658 +#define IDC_WINCOLOUR 1659 +#define IDC_ICONBLINK 1660 +#define IDC_STMSDELAY 1661 +#define ID_ICQ_EXIT 40001 +#define POPUP_HIDEEMPTYGROUPS 40003 +#define POPUP_NEWSUBGROUP 40004 +#define POPUP_HIDEOFFLINE 40005 +#define POPUP_GROUPHIDEOFFLINE 40006 +#define POPUP_HIDEOFFLINEROOT 40007 +#define POPUP_DISABLEGROUPS 40008 +#define POPUP_HIDEMIRANDA 40017 +#define ID_TRAY_HIDE 40038 +#define ID_TRAY_EXIT 40040 +#define POPUP_NEWGROUP 40050 +#define POPUP_RENAMEGROUP 40052 +#define POPUP_DELETEGROUP 40053 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 292 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1662 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/core/stdclist/src/version.h b/src/core/stdclist/src/version.h new file mode 100644 index 0000000000..e8d5e9b5e7 --- /dev/null +++ b/src/core/stdclist/src/version.h @@ -0,0 +1,14 @@ + +#include + +#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION +#define __VERSION_STRING MIRANDA_VERSION_STRING + +#define __PLUGIN_NAME "Classic contact list" +#define __INTERNAL_NAME "stdclist" +#define __FILENAME "stdclist.dll" +#define __DESCRIPTION "Core module for displaying contacts." +#define __AUTHOR "Miranda NG Development Team" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdemail/version.h b/src/core/stdemail/version.h index c31cb1194e..46b2087c41 100644 --- a/src/core/stdemail/version.h +++ b/src/core/stdemail/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdemail" #define __FILENAME "stdemail.dll" #define __DESCRIPTION "Core module for e-mail urls handling." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdfile/version.h b/src/core/stdfile/version.h index c7b2e9f028..6e47a11cef 100644 --- a/src/core/stdfile/version.h +++ b/src/core/stdfile/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdfile" #define __FILENAME "stdfile.dll" #define __DESCRIPTION "Core module for sending/receiving files." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdhelp/version.h b/src/core/stdhelp/version.h index 93104688aa..1bd1020583 100644 --- a/src/core/stdhelp/version.h +++ b/src/core/stdhelp/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdhelp" #define __FILENAME "stdhelp.dll" #define __DESCRIPTION "Core module for the Help/About dialog." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdidle/version.h b/src/core/stdidle/version.h index e38c89285c..fb382d83db 100644 --- a/src/core/stdidle/version.h +++ b/src/core/stdidle/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdidle" #define __FILENAME "stdidle.dll" #define __DESCRIPTION "Core module for idle state processing." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdmsg/docs/srmm-license.txt b/src/core/stdmsg/docs/srmm-license.txt new file mode 100644 index 0000000000..ca3fe8d547 --- /dev/null +++ b/src/core/stdmsg/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. + + + Copyright (C) 19yy + + 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. + + , 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/src/core/stdmsg/docs/srmm-readme.txt b/src/core/stdmsg/docs/srmm-readme.txt new file mode 100644 index 0000000000..d53888eb88 --- /dev/null +++ b/src/core/stdmsg/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/src/core/stdmsg/docs/srmm-translation.txt b/src/core/stdmsg/docs/srmm-translation.txt new file mode 100644 index 0000000000..95e4acd75e --- /dev/null +++ b/src/core/stdmsg/docs/srmm-translation.txt @@ -0,0 +1,141 @@ +; Common strings that belong to many files +;[Messaging] + +; ../../plugins/SRMM/cmdlist.cpp +;[The message send timed out.] + +; ../../plugins/SRMM/globals.cpp +;[Incoming message (10x10)] +;[Notice (10x10)] +;[Outgoing message (10x10)] + +; ../../plugins/SRMM/msgdialog.cpp +;[%s is typing a message...] +;[Last message received on %s at %s.] +;[is now %s (was %s)] +;[signed off (was %s)] +;[signed on (%s)] + +; ../../plugins/SRMM/msglog.cpp +;[File received] +;[File sent] + +; ../../plugins/SRMM/msgoptions.cpp +;[** New contacts **] +;[** Unknown contacts **] +;[Away] +;[Background] +;[DND] +;[Free for chat] +;[Incoming colon] +;[Incoming messages] +;[Incoming name] +;[Incoming time] +;[Invisible] +;[Message Log] +;[Message Sessions] +;[Message area] +;[Messaging Log] +;[NA] +;[Notices] +;[Occupied] +;[Offline] +;[On the phone] +;[Online] +;[Out to lunch] +;[Outgoing colon] +;[Outgoing messages] +;[Outgoing name] +;[Outgoing time] +;[Show balloon popup (unsupported system)] +;[Typing Notify] + +; ../../plugins/SRMM/msgs.cpp +;[%s is typing a message] +;[&Message] +;[Incoming (Focused Window)] +;[Incoming (New Session)] +;[Incoming (Unfocused Window)] +;[Information] +;[Instant messages] +;[Message from %s] +;[Message send error] +;[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.] +;[Outgoing] +;[Typing Notification] + +; ../../plugins/SRMM/msgtimedout.cpp +;[An unknown error has occured.] + +; ../../plugins/SRMM/resource.rc +;[&Copy] +;[&Copy link] +;[&D] +;[&H] +;[&Open link] +;[&Send] +;[An error has occured. The protocol reported the following error:] +;[Automatically popup window when:] +;[C&lear Log] +;[Cancel] +;[Cascade new windows] +;[Clear] +;[Close] +;[Close the message window on send] +;[Co&py All] +;[Copy] +;[Cut] +;[Delete] +;[Delete temporary contacts when closing message window] +;[Enable avatar support in the message window] +;[Flash in the system tray and in the contact list] +;[In background] +;[Limit avatar height to ] +;[Load History Events] +;[Load number of previous events] +;[Load previous events less than] +;[Load unread events only] +;[Log] +;[LogLink] +;[Max Number of Flashes] +;[Message] +;[Message Session] +;[Message Window Event Log] +;[Message window behaviour:] +;[Messaging:] +;[Minimize the message window on send] +;[Paste] +;[Paste && Send] +;[Redo] +;[Save the window position for each contact] +;[Save the window size and location individually for each contact] +;[Select &All] +;[Send Error] +;[Send message on 'Enter'] +;[Send message on double 'Enter'] +;[Send typing notifications to the following users when you are typing a message to them:] +;[Show 'Send' button] +;[Show Formatting] +;[Show balloon popup] +;[Show character count] +;[Show dates] +;[Show icons] +;[Show names] +;[Show seconds] +;[Show status changes] +;[Show timestamp] +;[Show toolbar buttons on top row] +;[Show typing notification when no message dialog is open] +;[Show typing notifications when a user is typing a message] +;[Show username on top row] +;[Show warning when message has not been received after] +;[Spin1] +;[Support control up/down in message area to show previously sent messages] +;[Try again] +;[Undo] +;[Update inactive message window icons when a user is typing] +;[Use the contact's status icon as the window icon] +;[minutes old] +;[pixels.] +;[seconds.] +;[while sending the following message:] diff --git a/src/core/stdmsg/res/dragcopy.cur b/src/core/stdmsg/res/dragcopy.cur new file mode 100644 index 0000000000..89c7c960d5 Binary files /dev/null and b/src/core/stdmsg/res/dragcopy.cur differ diff --git a/src/core/stdmsg/res/dropuser.cur b/src/core/stdmsg/res/dropuser.cur new file mode 100644 index 0000000000..a84b19e28b Binary files /dev/null and b/src/core/stdmsg/res/dropuser.cur differ diff --git a/src/core/stdmsg/res/hyperlin.cur b/src/core/stdmsg/res/hyperlin.cur new file mode 100644 index 0000000000..f0f548c828 Binary files /dev/null and b/src/core/stdmsg/res/hyperlin.cur differ diff --git a/src/core/stdmsg/res/incoming.ico b/src/core/stdmsg/res/incoming.ico new file mode 100644 index 0000000000..fabbf979cc Binary files /dev/null and b/src/core/stdmsg/res/incoming.ico differ diff --git a/src/core/stdmsg/res/notice.ico b/src/core/stdmsg/res/notice.ico new file mode 100644 index 0000000000..23527a94d8 Binary files /dev/null and b/src/core/stdmsg/res/notice.ico differ diff --git a/src/core/stdmsg/res/outgoing.ico b/src/core/stdmsg/res/outgoing.ico new file mode 100644 index 0000000000..f772ab3f8d Binary files /dev/null and b/src/core/stdmsg/res/outgoing.ico differ diff --git a/src/core/stdmsg/res/resource.rc b/src/core/stdmsg/res/resource.rc new file mode 100644 index 0000000000..2191538b6f --- /dev/null +++ b/src/core/stdmsg/res/resource.rc @@ -0,0 +1,361 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#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 + "..\\sxr\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "#include \r\n" + "#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 "incoming.ico" +IDI_OUTGOING ICON "outgoing.ico" +IDI_NOTICE ICON "notice.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_HYPERLINKHAND CURSOR "hyperlin.cur" +IDC_DROP CURSOR "dragcopy.cur" +IDC_DROPUSER CURSOR "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/src/core/stdmsg/res/version.rc b/src/core/stdmsg/res/version.rc new file mode 100644 index 0000000000..9b4b853e11 --- /dev/null +++ b/src/core/stdmsg/res/version.rc @@ -0,0 +1,54 @@ +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include "..\src\version.h" +#include "winres.h" +#include "richedit.h" + +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page( 1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Miranda\0" + VALUE "FileDescription", "Send and receive instant messages\0" + VALUE "FileVersion", __VERSION_STRING "\0" + VALUE "InternalName", "jabber\0" + VALUE "LegalCopyright", "Copyright ( c) 2002-12 Miranda team\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "srmm.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "SRMM plugin\0" + VALUE "ProductVersion", __VERSION_STRING "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/core/stdmsg/src/cmdlist.cpp b/src/core/stdmsg/src/cmdlist.cpp new file mode 100644 index 0000000000..91d082fc74 --- /dev/null +++ b/src/core/stdmsg/src/cmdlist.cpp @@ -0,0 +1,166 @@ +/* +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); + List_Remove(list, 0); + } + + new_list = (TCmdList*)mir_alloc(sizeof(TCmdList)); + new_list->szCmd = mir_tstrdup(data); + + 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]); + } + 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; + + 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 = (TMsgQueue*)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); + 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) + { + 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); + } + List_Destroy(&msgQueue); + + LeaveCriticalSection(&csMsgQueue); + + DeleteCriticalSection(&csMsgQueue); +} diff --git a/src/core/stdmsg/src/cmdlist.h b/src/core/stdmsg/src/cmdlist.h new file mode 100644 index 0000000000..add3d4987b --- /dev/null +++ b/src/core/stdmsg/src/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/src/core/stdmsg/src/commonheaders.h b/src/core/stdmsg/src/commonheaders.h new file mode 100644 index 0000000000..5ab3a6985d --- /dev/null +++ b/src/core/stdmsg/src/commonheaders.h @@ -0,0 +1,75 @@ +/* +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 + +#define _CRT_SECURE_NO_WARNINGS + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "resource.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdlist.h" +#include "msgs.h" +#include "globals.h" +#include "richutil.h" +#include "version.h" + +extern HINSTANCE g_hInst; diff --git a/src/core/stdmsg/src/globals.cpp b/src/core/stdmsg/src/globals.cpp new file mode 100644 index 0000000000..e6d0175f1c --- /dev/null +++ b/src/core/stdmsg/src/globals.cpp @@ -0,0 +1,186 @@ +/* +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 +{ + char *szName; + 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) +{ + char szSettingName[100]; + + TCHAR szFile[MAX_PATH]; + GetModuleFileName(g_hInst, szFile, SIZEOF(szFile)); + + SKINICONDESC sid = {0}; + 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 (int i=0; i < SIZEOF(iconList); i++) { + mir_snprintf(szSettingName, sizeof(szSettingName), "SRMM_%s", iconList[i].szName); + sid.pszDescription = iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + hIconLibItem[i] = Skin_AddIcon(&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/src/core/stdmsg/src/globals.h b/src/core/stdmsg/src/globals.h new file mode 100644 index 0000000000..05ae138f7d --- /dev/null +++ b/src/core/stdmsg/src/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/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp new file mode 100644 index 0000000000..df25b409e0 --- /dev/null +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -0,0 +1,2014 @@ +/* +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 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) +{ + if (hContact == NULL || hwnd == NULL) + return; + + MessageWindowEventData mwe = { 0 }; + 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) +{ + 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"; + 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; + + size_t bufSizeT = (_tcslen(szMsg) + 1) * sizeof(TCHAR) ; + sendBuffer = (char*)mir_realloc(sendBuffer, bufSizeT + bufSize); + memcpy((TCHAR*)&sendBuffer[bufSize], szMsg, bufSizeT); + bufSize += (int)bufSizeT; + } + + 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 SrmmWindowData *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 SrmmWindowData *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 SrmmWindowData *dat; + + dat = (struct SrmmWindowData *) 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 SrmmWindowData *pdat = (struct SrmmWindowData *)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); + TranslateMenu(mwpd.hMenu); + + 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 SrmmWindowData *pdat = (struct SrmmWindowData *)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 SrmmWindowData *dat = (struct SrmmWindowData *) 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) { + TCHAR buf[256]; + GetWindowText(h, buf, SIZEOF(buf)); + + HDC hdc = GetDC(h); + HFONT hFont = (HFONT)SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0)); + + SIZE textSize; + 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 SrmmWindowData *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 SrmmWindowData *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, TRUE, 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 SrmmWindowData *dat; + + dat = (struct SrmmWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam; + TranslateDialogDefault(hwndDlg); + dat = (struct SrmmWindowData *) mir_calloc(sizeof(struct SrmmWindowData)); + 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; + + if(newData->isWchar) + SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText); + else + + 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 = 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, TRUE, 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.topminEditBoxSize.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_INFORMATIONT ai = { sizeof(ai), dat->hContact }; + CallProtoService(dat->szProto, PS_GETAVATARINFOT, 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((TCHAR*)GlobalLock(hData), buf); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + 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); + 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); + 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)) + { + HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0)); + HPEN hOldPen = (HPEN)SelectObject(dis->hDC, hPen); + Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight); + SelectObject(dis->hDC,hOldPen); + DeleteObject(hPen); + + BITMAP bminfo; + 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); + TranslateMenu(hSubMenu); + 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 = (TCHAR*)_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); + TranslateMenu(hSubMenu); + 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((TCHAR*)GlobalLock(hData), tr.lpstrText); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + 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/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp new file mode 100644 index 0000000000..d24cda4032 --- /dev/null +++ b/src/core/stdmsg/src/msglog.cpp @@ -0,0 +1,645 @@ +/* +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 SrmmWindowData *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; +} + +#define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" + +static char *CreateRTFHeader(struct SrmmWindowData *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 SrmmWindowData *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 SrmmWindowData *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 SrmmWindowData *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 = (char*)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 SrmmWindowData *dat = (struct SrmmWindowData*)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 = Skin_GetIconByHandle(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((char*)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((char*)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]); + for (n = 0; n < widthBytes * bih.biHeight; n += 4) + sprintf((char*)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/src/core/stdmsg/src/msgoptions.cpp b/src/core/stdmsg/src/msgoptions.cpp new file mode 100644 index 0000000000..6eb91e910f --- /dev/null +++ b/src/core/stdmsg/src/msgoptions.cpp @@ -0,0 +1,656 @@ +/* +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); + +static BYTE MsgDlgGetFontDefaultCharset(const TCHAR* szFont) +{ + return DEFAULT_CHARSET; +} + +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); + FontRegisterT(&fontid); + } + + 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")); + ColourRegisterT(&colourid); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +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 void ResetCList(HWND hwndDlg) +{ + 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 (int 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; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGLOG); + odp.pszTab = LPGEN("Messaging Log"); + odp.pfnDlgProc = DlgProcLogOptions; + odp.nIDBottomSimpleControl = IDC_STMSGLOGGROUP; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGTYPE); + odp.pszTab = LPGEN("Typing Notify"); + odp.pfnDlgProc = DlgProcTypeOptions; + odp.nIDBottomSimpleControl = 0; + Options_AddPage(wParam, &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/src/core/stdmsg/src/msgs.cpp b/src/core/stdmsg/src/msgs.cpp new file mode 100644 index 0000000000..9bf26a38cb --- /dev/null +++ b/src/core/stdmsg/src/msgs.cpp @@ -0,0 +1,567 @@ +/* +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 + +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; +} + +static INT_PTR SendMessageCommand_W(WPARAM wParam, LPARAM lParam) +{ + return SendMessageCmd((HANDLE)wParam, (char*)lParam, TRUE); +} + +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; + tn.dwInfoFlags |= NIIF_INTERN_UNICODE; + 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 = Menu_AddContactMenuItem(&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(SrmmWindowData)) 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); + 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); + hServices[1] = CreateServiceFunction(MS_MSG_SENDMESSAGEW, SendMessageCommand_W); + 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; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +CREOleCallback reOleCallback; + +STDMETHODIMP CREOleCallback::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if (IsEqualIID(riid, IID_IRichEditOleCallback)) { + *ppvObj = this; + AddRef(); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CREOleCallback::AddRef() +{ + if (refCount == 0) { + if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &pictStg)) + pictStg = NULL; + nextStgId = 0; + } + return ++refCount; +} + +STDMETHODIMP_(ULONG) CREOleCallback::Release() +{ + if (--refCount == 0) { + if (pictStg) + pictStg->Release(); + } + return refCount; +} + +STDMETHODIMP CREOleCallback::ContextSensitiveHelp(BOOL fEnterMode) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::DeleteObject(LPOLEOBJECT lpoleobj) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetClipboardData(CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CREOleCallback::GetContextMenu(WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetInPlaceContext(LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetNewStorage(LPSTORAGE * lplpstg) +{ + WCHAR szwName[64]; + char szName[64]; + wsprintfA(szName, "s%u", nextStgId++); + MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName)); + if (pictStg == NULL) + return STG_E_MEDIUMFULL; + return pictStg->CreateStorage(szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg); +} + +STDMETHODIMP CREOleCallback::QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::ShowContainerUI(BOOL fShow) +{ + return S_OK; +} diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h new file mode 100644 index 0000000000..4a02e67a32 --- /dev/null +++ b/src/core/stdmsg/src/msgs.h @@ -0,0 +1,232 @@ +/* +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 +#include + +struct NewMessageWindowLParam +{ + HANDLE hContact; + const char *szInitialText; + int isWchar; + int noActivate; +}; + +struct SrmmWindowData +{ + 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 : public IRichEditOleCallback +{ + CREOleCallback() : refCount(0) {} + unsigned refCount; + IStorage *pictStg; + int nextStgId; + + STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * lplpObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode); + STDMETHOD(GetNewStorage) (LPSTORAGE FAR * lplpstg); + STDMETHOD(GetInPlaceContext) (LPOLEINPLACEFRAME FAR * lplpFrame, LPOLEINPLACEUIWINDOW FAR * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo); + STDMETHOD(ShowContainerUI) (BOOL fShow); + STDMETHOD(QueryInsertObject) (LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp); + STDMETHOD(DeleteObject) (LPOLEOBJECT lpoleobj); + STDMETHOD(QueryAcceptData) (LPDATAOBJECT lpdataobj, CLIPFORMAT FAR * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict); + STDMETHOD(GetClipboardData) (CHARRANGE FAR * lpchrg, DWORD reco, LPDATAOBJECT FAR * lplpdataobj); + STDMETHOD(GetDragDropEffect) (BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect); + STDMETHOD(GetContextMenu) (WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE FAR * lpchrg, HMENU FAR * lphmenu) ; +}; + +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 SrmmWindowData *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/src/core/stdmsg/src/msgtimedout.cpp b/src/core/stdmsg/src/msgtimedout.cpp new file mode 100644 index 0000000000..1b1773aa8e --- /dev/null +++ b/src/core/stdmsg/src/msgtimedout.cpp @@ -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) ¶m); +} + diff --git a/src/core/stdmsg/src/resource.h b/src/core/stdmsg/src/resource.h new file mode 100644 index 0000000000..715d83656b --- /dev/null +++ b/src/core/stdmsg/src/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/src/core/stdmsg/src/richutil.cpp b/src/core/stdmsg/src/richutil.cpp new file mode 100644 index 0000000000..7f77c98fa8 --- /dev/null +++ b/src/core/stdmsg/src/richutil.cpp @@ -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) +{ + 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 (!List_GetIndex(&sListInt, ru, &idx)) + 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 = (TRichUtil *)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 = GetWindowLongPtr(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); + 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/src/core/stdmsg/src/richutil.h b/src/core/stdmsg/src/richutil.h new file mode 100644 index 0000000000..68e9f37c5b --- /dev/null +++ b/src/core/stdmsg/src/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/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp new file mode 100644 index 0000000000..dfb4c31579 --- /dev/null +++ b/src/core/stdmsg/src/srmm.cpp @@ -0,0 +1,70 @@ +/* +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); + +HINSTANCE g_hInst; +int hLangpack; + +TIME_API tmi; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + MIRANDA_VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0xc }} //{657FE89B-D121-40c2-8AC9-B9FA5755B30C} +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + g_hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_SRMM, MIID_LAST}; + +extern "C" int __declspec(dllexport) Load(void) +{ + + mir_getTMI(&tmi); + mir_getLP(&pluginInfo); + + return LoadSendRecvMessageModule(); +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + UnloadOptions(); + return SplitmsgShutdown(); +} diff --git a/src/core/stdmsg/src/statusicon.cpp b/src/core/stdmsg/src/statusicon.cpp new file mode 100644 index 0000000000..cd7ac3872e --- /dev/null +++ b/src/core/stdmsg/src/statusicon.cpp @@ -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/src/core/stdmsg/src/statusicon.h b/src/core/stdmsg/src/statusicon.h new file mode 100644 index 0000000000..314ac9ec1e --- /dev/null +++ b/src/core/stdmsg/src/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/src/core/stdmsg/src/version.h b/src/core/stdmsg/src/version.h new file mode 100644 index 0000000000..4001e7f865 --- /dev/null +++ b/src/core/stdmsg/src/version.h @@ -0,0 +1,14 @@ + +#include + +#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION +#define __VERSION_STRING MIRANDA_VERSION_STRING + +#define __PLUGIN_NAME "Send/Receive Messages" +#define __INTERNAL_NAME "stdmsg" +#define __FILENAME "stdmsg.dll" +#define __DESCRIPTION "Core module for send/receive instant messages." +#define __AUTHOR "Miranda NG Development Team" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdmsg/srmm_10.vcxproj b/src/core/stdmsg/srmm_10.vcxproj new file mode 100644 index 0000000000..c985b94a9b --- /dev/null +++ b/src/core/stdmsg/srmm_10.vcxproj @@ -0,0 +1,221 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + StdMsg + {F47EAB99-C78F-4A92-87D5-B0E16FE5A133} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + false + true + Fast + Use + Level3 + commonheaders.h + false + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + true + true + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + false + true + Fast + Use + Level3 + commonheaders.h + false + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + true + true + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + /PDBALTPATH:%_PDB% + + + + + Disabled + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + Level3 + EditAndContinue + commonheaders.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + true + false + $(IntDir)$(TargetName).lib + Windows + comctl32.lib;%(AdditionalDependencies) + $(SolutionDir)\lib + + + + + Disabled + ..\..\..\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + Level3 + commonheaders.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\include\msapi + + + comctl32.lib;%(AdditionalDependencies) + true + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/stdmsg/srmm_10.vcxproj.filters b/src/core/stdmsg/srmm_10.vcxproj.filters new file mode 100644 index 0000000000..751ea7199a --- /dev/null +++ b/src/core/stdmsg/srmm_10.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {8927e967-671b-4c16-8208-54dec5f31489} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {6ae44719-2dc0-4659-bb57-b80bc11f0eb2} + h;hpp;hxx;hm;inl + + + {ed6d6a77-6f3c-4512-afc9-7c872bee5ded} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/src/core/stduihist/version.h b/src/core/stduihist/version.h index 71226e8a50..99ff40c2e8 100644 --- a/src/core/stduihist/version.h +++ b/src/core/stduihist/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stduihist" #define __FILENAME "stduihist.dll" #define __DESCRIPTION "Core module for built-in history viewer." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stdurl/version.h b/src/core/stdurl/version.h index 40d6568a81..990f0452ab 100644 --- a/src/core/stdurl/version.h +++ b/src/core/stdurl/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stdurl" #define __FILENAME "stdurl.dll" #define __DESCRIPTION "Core module for URL handling." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stduserinfo/version.h b/src/core/stduserinfo/version.h index 64130a49e7..ca6347c294 100644 --- a/src/core/stduserinfo/version.h +++ b/src/core/stduserinfo/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stduserinfo" #define __FILENAME "stduserinfo.dll" #define __DESCRIPTION "Core module for providing user information." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/core/stduseronline/version.h b/src/core/stduseronline/version.h index e81e85bd8f..fc0cc14144 100644 --- a/src/core/stduseronline/version.h +++ b/src/core/stduseronline/version.h @@ -8,7 +8,7 @@ #define __INTERNAL_NAME "stduseronline" #define __FILENAME "stduseronline.dll" #define __DESCRIPTION "Core module for user-is-online event processing." -#define __AUTHOR "Myranda team" +#define __AUTHOR "Miranda NG Development Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2012 Myranda team" +#define __COPYRIGHT "© 2012 Miranda NG Development Team" diff --git a/src/modules/plugins/newplugins.cpp b/src/modules/plugins/newplugins.cpp index ad6206eaf4..684db5cb0c 100644 --- a/src/modules/plugins/newplugins.cpp +++ b/src/modules/plugins/newplugins.cpp @@ -40,26 +40,6 @@ LIST #define MAX_MIR_VER ULONG_MAX -MuuidReplacement pluginDefault[] = -{ - { MIID_UIUSERINFO, _T("stduserinfo"), NULL }, // 0 - { MIID_SRURL, _T("stdurl"), NULL }, // 1 - { MIID_SREMAIL, _T("stdemail"), NULL }, // 2 - { MIID_SRAUTH, _T("stdauth"), NULL }, // 3 - { MIID_SRFILE, _T("stdfile"), NULL }, // 4 - { MIID_UIHELP, _T("stdhelp"), NULL }, // 5 - { MIID_UIHISTORY, _T("stduihist"), NULL }, // 6 - { MIID_IDLE, _T("stdidle"), NULL }, // 7 - { MIID_AUTOAWAY, _T("stdautoaway"), NULL }, // 8 - { MIID_USERONLINE, _T("stduseronline"), NULL }, // 9 - { MIID_SRAWAY, _T("stdaway"), NULL }, // 10 - - { MIID_CLIST, NULL, NULL }, // 11 - { MIID_CHAT, NULL, NULL }, // 12 - { MIID_SRMM, NULL, NULL }, // 13 - { MIID_DATABASE, NULL, NULL }, // 14 -}; - static BOOL bModuleInitialized = FALSE; TCHAR mirandabootini[MAX_PATH]; @@ -101,6 +81,27 @@ bool hasMuuid(const BASIC_PLUGIN_INFO& bpi, const MUUID& uuid) return false; } +///////////////////////////////////////////////////////////////////////////////////////// +// default plugins + +static MuuidReplacement pluginDefault[] = +{ + { MIID_UIUSERINFO, _T("stduserinfo"), NULL }, // 0 + { MIID_SRURL, _T("stdurl"), NULL }, // 1 + { MIID_SREMAIL, _T("stdemail"), NULL }, // 2 + { MIID_SRAUTH, _T("stdauth"), NULL }, // 3 + { MIID_SRFILE, _T("stdfile"), NULL }, // 4 + { MIID_UIHELP, _T("stdhelp"), NULL }, // 5 + { MIID_UIHISTORY, _T("stduihist"), NULL }, // 6 + { MIID_IDLE, _T("stdidle"), NULL }, // 7 + { MIID_AUTOAWAY, _T("stdautoaway"), NULL }, // 8 + { MIID_USERONLINE, _T("stduseronline"), NULL }, // 9 + { MIID_SRAWAY, _T("stdaway"), NULL }, // 10 + { MIID_CLIST, _T("stdclist"), NULL }, // 11 + { MIID_CHAT, _T("stdchat"), NULL }, // 12 + { MIID_SRMM, _T("stdmsg"), NULL } // 13 +}; + int getDefaultPluginIdx(const MUUID& muuid) { for (int i=0; i < SIZEOF(pluginDefault); i++) @@ -110,6 +111,18 @@ int getDefaultPluginIdx(const MUUID& muuid) return -1; } +int LoadStdPlugins() +{ + for (int i=0; i < SIZEOF(pluginDefault); i++) { + if ( pluginDefault[i].pImpl ) + continue; + + if ( !LoadCorePlugin(pluginDefault[i])) + return 1; + } + return 0; +} + ///////////////////////////////////////////////////////////////////////////////////////// // global functions diff --git a/src/modules/plugins/plugins.h b/src/modules/plugins/plugins.h index d7b4d9adce..72e3087f4a 100644 --- a/src/modules/plugins/plugins.h +++ b/src/modules/plugins/plugins.h @@ -78,8 +78,6 @@ struct MuuidReplacement pluginEntry* pImpl; // replacement plugin }; -extern MuuidReplacement pluginDefault[]; - bool LoadCorePlugin( MuuidReplacement& ); MUUID* GetPluginInterfaces(const TCHAR* ptszFileName, bool& bIsPlugin); \ No newline at end of file -- cgit v1.2.3