summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-08-10 10:35:58 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-08-10 10:35:58 +0000
commit21549db08d22a6e41443799b917525da1dbf9853 (patch)
treed59e22f8b74510294b9e644719015461a4c5a003 /src/core
parent9bce64a32ea9d903797a27bb06b9919c11bbe596 (diff)
- SRMM, Chat & Clist_Classic made standard
git-svn-id: http://svn.miranda-ng.org/main/trunk@1422 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/core')
-rw-r--r--src/core/modules.cpp13
-rw-r--r--src/core/stdauth/version.h4
-rw-r--r--src/core/stdautoaway/version.h4
-rw-r--r--src/core/stdaway/version.h4
-rw-r--r--src/core/stdchat/chat_10.vcxproj235
-rw-r--r--src/core/stdchat/chat_10.vcxproj.filters86
-rw-r--r--src/core/stdchat/docs/Chat_Readme.txt82
-rw-r--r--src/core/stdchat/docs/Chat_license.txt340
-rw-r--r--src/core/stdchat/docs/chat-translation.txt300
-rw-r--r--src/core/stdchat/res/1.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/2.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/3.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/4.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/5.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/6.icobin0 -> 1742 bytes
-rw-r--r--src/core/stdchat/res/action.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/addmode.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/bkgcolor.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/blank.icobin0 -> 318 bytes
-rw-r--r--src/core/stdchat/res/bold.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/chat.rc455
-rw-r--r--src/core/stdchat/res/close.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/color.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/filter.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/filter2.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/highlight.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/history.icobin0 -> 6830 bytes
-rw-r--r--src/core/stdchat/res/info.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/italics.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/join.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/kick.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/message.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/messageout.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/nick.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/nicklist.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/nicklist2.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/notice.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/overlay.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/part.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/quit.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/removestatus.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/smiley.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/smileyc.icobin0 -> 2038 bytes
-rw-r--r--src/core/stdchat/res/tag1.icobin0 -> 1590 bytes
-rw-r--r--src/core/stdchat/res/tag2.icobin0 -> 4726 bytes
-rw-r--r--src/core/stdchat/res/topic.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/topicbut.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/underline.icobin0 -> 2550 bytes
-rw-r--r--src/core/stdchat/res/version.rc56
-rw-r--r--src/core/stdchat/res/window.icobin0 -> 10086 bytes
-rw-r--r--src/core/stdchat/src/chat.h552
-rw-r--r--src/core/stdchat/src/clist.cpp360
-rw-r--r--src/core/stdchat/src/colorchooser.cpp266
-rw-r--r--src/core/stdchat/src/log.cpp712
-rw-r--r--src/core/stdchat/src/main.cpp288
-rw-r--r--src/core/stdchat/src/manager.cpp1611
-rw-r--r--src/core/stdchat/src/message.cpp356
-rw-r--r--src/core/stdchat/src/options.cpp1123
-rw-r--r--src/core/stdchat/src/resource.h141
-rw-r--r--src/core/stdchat/src/richutil.cpp293
-rw-r--r--src/core/stdchat/src/richutil.h55
-rw-r--r--src/core/stdchat/src/services.cpp874
-rw-r--r--src/core/stdchat/src/tools.cpp917
-rw-r--r--src/core/stdchat/src/version.h14
-rw-r--r--src/core/stdchat/src/window.cpp2725
-rw-r--r--src/core/stdclist/clist_10.vcxproj226
-rw-r--r--src/core/stdclist/clist_10.vcxproj.filters73
-rw-r--r--src/core/stdclist/docs/clist-license.txt340
-rw-r--r--src/core/stdclist/docs/clist-readme.txt38
-rw-r--r--src/core/stdclist/docs/clist-translation.txt166
-rw-r--r--src/core/stdclist/docs/clist_classic-translation.txt166
-rw-r--r--src/core/stdclist/res/blank.icobin0 -> 318 bytes
-rw-r--r--src/core/stdclist/res/dragcopy.curbin0 -> 326 bytes
-rw-r--r--src/core/stdclist/res/dropuser.curbin0 -> 1086 bytes
-rw-r--r--src/core/stdclist/res/hyperlin.curbin0 -> 326 bytes
-rw-r--r--src/core/stdclist/res/resource.rc532
-rw-r--r--src/core/stdclist/res/version.rc56
-rw-r--r--src/core/stdclist/src/clc.h32
-rw-r--r--src/core/stdclist/src/clcfonts.cpp137
-rw-r--r--src/core/stdclist/src/clcopts.cpp479
-rw-r--r--src/core/stdclist/src/clcpaint.cpp596
-rw-r--r--src/core/stdclist/src/clistmenus.cpp36
-rw-r--r--src/core/stdclist/src/clistopts.cpp279
-rw-r--r--src/core/stdclist/src/cluiopts.cpp394
-rw-r--r--src/core/stdclist/src/commonheaders.h77
-rw-r--r--src/core/stdclist/src/init.cpp176
-rw-r--r--src/core/stdclist/src/resource.h163
-rw-r--r--src/core/stdclist/src/version.h14
-rw-r--r--src/core/stdemail/version.h4
-rw-r--r--src/core/stdfile/version.h4
-rw-r--r--src/core/stdhelp/version.h4
-rw-r--r--src/core/stdidle/version.h4
-rw-r--r--src/core/stdmsg/docs/srmm-license.txt340
-rw-r--r--src/core/stdmsg/docs/srmm-readme.txt130
-rw-r--r--src/core/stdmsg/docs/srmm-translation.txt141
-rw-r--r--src/core/stdmsg/res/dragcopy.curbin0 -> 326 bytes
-rw-r--r--src/core/stdmsg/res/dropuser.curbin0 -> 1086 bytes
-rw-r--r--src/core/stdmsg/res/hyperlin.curbin0 -> 326 bytes
-rw-r--r--src/core/stdmsg/res/incoming.icobin0 -> 1246 bytes
-rw-r--r--src/core/stdmsg/res/notice.icobin0 -> 1246 bytes
-rw-r--r--src/core/stdmsg/res/outgoing.icobin0 -> 1246 bytes
-rw-r--r--src/core/stdmsg/res/resource.rc361
-rw-r--r--src/core/stdmsg/res/version.rc54
-rw-r--r--src/core/stdmsg/src/cmdlist.cpp166
-rw-r--r--src/core/stdmsg/src/cmdlist.h51
-rw-r--r--src/core/stdmsg/src/commonheaders.h75
-rw-r--r--src/core/stdmsg/src/globals.cpp186
-rw-r--r--src/core/stdmsg/src/globals.h62
-rw-r--r--src/core/stdmsg/src/msgdialog.cpp2014
-rw-r--r--src/core/stdmsg/src/msglog.cpp645
-rw-r--r--src/core/stdmsg/src/msgoptions.cpp656
-rw-r--r--src/core/stdmsg/src/msgs.cpp567
-rw-r--r--src/core/stdmsg/src/msgs.h232
-rw-r--r--src/core/stdmsg/src/msgtimedout.cpp112
-rw-r--r--src/core/stdmsg/src/resource.h98
-rw-r--r--src/core/stdmsg/src/richutil.cpp269
-rw-r--r--src/core/stdmsg/src/richutil.h34
-rw-r--r--src/core/stdmsg/src/srmm.cpp70
-rw-r--r--src/core/stdmsg/src/statusicon.cpp221
-rw-r--r--src/core/stdmsg/src/statusicon.h14
-rw-r--r--src/core/stdmsg/src/version.h14
-rw-r--r--src/core/stdmsg/srmm_10.vcxproj221
-rw-r--r--src/core/stdmsg/srmm_10.vcxproj.filters80
-rw-r--r--src/core/stduihist/version.h4
-rw-r--r--src/core/stdurl/version.h4
-rw-r--r--src/core/stduserinfo/version.h4
-rw-r--r--src/core/stduseronline/version.h4
127 files changed, 22659 insertions, 32 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>stdchat</ProjectName>
+ <ProjectGuid>{268BD296-8DD3-4715-A386-CF120398EC98}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>chat.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/DLL %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>chat.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/DLL %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>chat.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalDependencies>Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;CHAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <WarningLevel>Level3</WarningLevel>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>chat.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ <AdditionalDependencies>Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clist.cpp" />
+ <ClCompile Include="src\colorchooser.cpp" />
+ <ClCompile Include="src\log.cpp" />
+ <ClCompile Include="src\main.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\manager.cpp" />
+ <ClCompile Include="src\message.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\richutil.cpp">
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\services.cpp" />
+ <ClCompile Include="src\tools.cpp" />
+ <ClCompile Include="src\window.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\chat.h" />
+ <ClInclude Include="src\richutil.h" />
+ <ClInclude Include="src\resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="docs\Chat_license.txt" />
+ <None Include="docs\Chat_Readme.txt" />
+ <None Include="docs\Chat_Translate.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Chat.rc" />
+ <ResourceCompile Include="res\version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{ce9c3130-07ac-478e-8752-265c31f3bc8f}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{b87dc5b7-8e8e-49a1-8291-b27797a443b7}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{ac500f7b-22cc-423c-a5e9-35da455c5e6a}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="Documentation">
+ <UniqueIdentifier>{6f7bae66-5f17-4ccb-8721-25f55e5c4e64}</UniqueIdentifier>
+ <Extensions>.txt</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\colorchooser.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\log.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\manager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\message.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\richutil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\services.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\tools.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\window.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\chat.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\richutil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="docs\Chat_license.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ <None Include="docs\Chat_Readme.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ <None Include="docs\Chat_Translate.txt">
+ <Filter>Documentation</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\Chat.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="res\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/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
--- /dev/null
+++ b/src/core/stdchat/res/1.ico
Binary files differ
diff --git a/src/core/stdchat/res/2.ico b/src/core/stdchat/res/2.ico
new file mode 100644
index 0000000000..819ecc1d7a
--- /dev/null
+++ b/src/core/stdchat/res/2.ico
Binary files differ
diff --git a/src/core/stdchat/res/3.ico b/src/core/stdchat/res/3.ico
new file mode 100644
index 0000000000..0928e257fe
--- /dev/null
+++ b/src/core/stdchat/res/3.ico
Binary files differ
diff --git a/src/core/stdchat/res/4.ico b/src/core/stdchat/res/4.ico
new file mode 100644
index 0000000000..5dcea114fa
--- /dev/null
+++ b/src/core/stdchat/res/4.ico
Binary files differ
diff --git a/src/core/stdchat/res/5.ico b/src/core/stdchat/res/5.ico
new file mode 100644
index 0000000000..6aa5806c53
--- /dev/null
+++ b/src/core/stdchat/res/5.ico
Binary files differ
diff --git a/src/core/stdchat/res/6.ico b/src/core/stdchat/res/6.ico
new file mode 100644
index 0000000000..c35cc39ebc
--- /dev/null
+++ b/src/core/stdchat/res/6.ico
Binary files differ
diff --git a/src/core/stdchat/res/action.ico b/src/core/stdchat/res/action.ico
new file mode 100644
index 0000000000..44816c42d7
--- /dev/null
+++ b/src/core/stdchat/res/action.ico
Binary files differ
diff --git a/src/core/stdchat/res/addmode.ico b/src/core/stdchat/res/addmode.ico
new file mode 100644
index 0000000000..a6a7e6f38c
--- /dev/null
+++ b/src/core/stdchat/res/addmode.ico
Binary files differ
diff --git a/src/core/stdchat/res/bkgcolor.ico b/src/core/stdchat/res/bkgcolor.ico
new file mode 100644
index 0000000000..e3322ef34b
--- /dev/null
+++ b/src/core/stdchat/res/bkgcolor.ico
Binary files differ
diff --git a/src/core/stdchat/res/blank.ico b/src/core/stdchat/res/blank.ico
new file mode 100644
index 0000000000..7845f62fed
--- /dev/null
+++ b/src/core/stdchat/res/blank.ico
Binary files differ
diff --git a/src/core/stdchat/res/bold.ico b/src/core/stdchat/res/bold.ico
new file mode 100644
index 0000000000..fc34113b6b
--- /dev/null
+++ b/src/core/stdchat/res/bold.ico
Binary files 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
--- /dev/null
+++ b/src/core/stdchat/res/close.ico
Binary files differ
diff --git a/src/core/stdchat/res/color.ico b/src/core/stdchat/res/color.ico
new file mode 100644
index 0000000000..689762edbb
--- /dev/null
+++ b/src/core/stdchat/res/color.ico
Binary files differ
diff --git a/src/core/stdchat/res/filter.ico b/src/core/stdchat/res/filter.ico
new file mode 100644
index 0000000000..7c99edb58c
--- /dev/null
+++ b/src/core/stdchat/res/filter.ico
Binary files differ
diff --git a/src/core/stdchat/res/filter2.ico b/src/core/stdchat/res/filter2.ico
new file mode 100644
index 0000000000..701890522b
--- /dev/null
+++ b/src/core/stdchat/res/filter2.ico
Binary files differ
diff --git a/src/core/stdchat/res/highlight.ico b/src/core/stdchat/res/highlight.ico
new file mode 100644
index 0000000000..552c912eaa
--- /dev/null
+++ b/src/core/stdchat/res/highlight.ico
Binary files differ
diff --git a/src/core/stdchat/res/history.ico b/src/core/stdchat/res/history.ico
new file mode 100644
index 0000000000..e757b93e54
--- /dev/null
+++ b/src/core/stdchat/res/history.ico
Binary files differ
diff --git a/src/core/stdchat/res/info.ico b/src/core/stdchat/res/info.ico
new file mode 100644
index 0000000000..1acdb7190b
--- /dev/null
+++ b/src/core/stdchat/res/info.ico
Binary files differ
diff --git a/src/core/stdchat/res/italics.ico b/src/core/stdchat/res/italics.ico
new file mode 100644
index 0000000000..5c61422a71
--- /dev/null
+++ b/src/core/stdchat/res/italics.ico
Binary files differ
diff --git a/src/core/stdchat/res/join.ico b/src/core/stdchat/res/join.ico
new file mode 100644
index 0000000000..151cd93211
--- /dev/null
+++ b/src/core/stdchat/res/join.ico
Binary files differ
diff --git a/src/core/stdchat/res/kick.ico b/src/core/stdchat/res/kick.ico
new file mode 100644
index 0000000000..c93e92dd77
--- /dev/null
+++ b/src/core/stdchat/res/kick.ico
Binary files differ
diff --git a/src/core/stdchat/res/message.ico b/src/core/stdchat/res/message.ico
new file mode 100644
index 0000000000..19957e4ac8
--- /dev/null
+++ b/src/core/stdchat/res/message.ico
Binary files differ
diff --git a/src/core/stdchat/res/messageout.ico b/src/core/stdchat/res/messageout.ico
new file mode 100644
index 0000000000..637196b745
--- /dev/null
+++ b/src/core/stdchat/res/messageout.ico
Binary files differ
diff --git a/src/core/stdchat/res/nick.ico b/src/core/stdchat/res/nick.ico
new file mode 100644
index 0000000000..3f199ffd50
--- /dev/null
+++ b/src/core/stdchat/res/nick.ico
Binary files differ
diff --git a/src/core/stdchat/res/nicklist.ico b/src/core/stdchat/res/nicklist.ico
new file mode 100644
index 0000000000..f2f611d6a4
--- /dev/null
+++ b/src/core/stdchat/res/nicklist.ico
Binary files differ
diff --git a/src/core/stdchat/res/nicklist2.ico b/src/core/stdchat/res/nicklist2.ico
new file mode 100644
index 0000000000..cba204fe5e
--- /dev/null
+++ b/src/core/stdchat/res/nicklist2.ico
Binary files differ
diff --git a/src/core/stdchat/res/notice.ico b/src/core/stdchat/res/notice.ico
new file mode 100644
index 0000000000..1ba34d7244
--- /dev/null
+++ b/src/core/stdchat/res/notice.ico
Binary files differ
diff --git a/src/core/stdchat/res/overlay.ico b/src/core/stdchat/res/overlay.ico
new file mode 100644
index 0000000000..28742d898d
--- /dev/null
+++ b/src/core/stdchat/res/overlay.ico
Binary files differ
diff --git a/src/core/stdchat/res/part.ico b/src/core/stdchat/res/part.ico
new file mode 100644
index 0000000000..39c24868aa
--- /dev/null
+++ b/src/core/stdchat/res/part.ico
Binary files differ
diff --git a/src/core/stdchat/res/quit.ico b/src/core/stdchat/res/quit.ico
new file mode 100644
index 0000000000..d7fbdaf4b7
--- /dev/null
+++ b/src/core/stdchat/res/quit.ico
Binary files differ
diff --git a/src/core/stdchat/res/removestatus.ico b/src/core/stdchat/res/removestatus.ico
new file mode 100644
index 0000000000..ea3cef3fef
--- /dev/null
+++ b/src/core/stdchat/res/removestatus.ico
Binary files differ
diff --git a/src/core/stdchat/res/smiley.ico b/src/core/stdchat/res/smiley.ico
new file mode 100644
index 0000000000..e0d066ce33
--- /dev/null
+++ b/src/core/stdchat/res/smiley.ico
Binary files differ
diff --git a/src/core/stdchat/res/smileyc.ico b/src/core/stdchat/res/smileyc.ico
new file mode 100644
index 0000000000..d5b8ab0d28
--- /dev/null
+++ b/src/core/stdchat/res/smileyc.ico
Binary files differ
diff --git a/src/core/stdchat/res/tag1.ico b/src/core/stdchat/res/tag1.ico
new file mode 100644
index 0000000000..1dc687becd
--- /dev/null
+++ b/src/core/stdchat/res/tag1.ico
Binary files differ
diff --git a/src/core/stdchat/res/tag2.ico b/src/core/stdchat/res/tag2.ico
new file mode 100644
index 0000000000..4fac50a4c8
--- /dev/null
+++ b/src/core/stdchat/res/tag2.ico
Binary files differ
diff --git a/src/core/stdchat/res/topic.ico b/src/core/stdchat/res/topic.ico
new file mode 100644
index 0000000000..e4bb7da7e0
--- /dev/null
+++ b/src/core/stdchat/res/topic.ico
Binary files differ
diff --git a/src/core/stdchat/res/topicbut.ico b/src/core/stdchat/res/topicbut.ico
new file mode 100644
index 0000000000..ddb72fb8ca
--- /dev/null
+++ b/src/core/stdchat/res/topicbut.ico
Binary files differ
diff --git a/src/core/stdchat/res/underline.ico b/src/core/stdchat/res/underline.ico
new file mode 100644
index 0000000000..01cf64a36a
--- /dev/null
+++ b/src/core/stdchat/res/underline.ico
Binary files 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 <afxres.h>
+#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
--- /dev/null
+++ b/src/core/stdchat/res/window.ico
Binary files 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 <m_stdhdr.h>
+
+#include <shlobj.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <ole2.h>
+#include <richole.h>
+#include <commdlg.h>
+#include <shellapi.h>
+#include <Initguid.h>
+#include <Oleacc.h>
+
+#include <time.h>
+
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_options.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_skin.h>
+#include <m_button.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_addcontact.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_message.h>
+#include <m_icolib.h>
+#include <m_popup.h>
+#include <m_chat.h>
+
+#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 <math.h>
+
+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 <math.h>
+
+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 <m_fontservice.h>
+
+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<nValues;i++) {
+ tvis.item.pszText = TranslateTS(branch[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ if (branch[i].iMode)
+ iState = ((DBGetContactSettingDword(NULL, "Chat", branch[i].szDBName, defaultval)&branch[i].iMode)&branch[i].iMode)!=0?2:1;
+ else
+ iState = DBGetContactSettingByte(NULL, "Chat", branch[i].szDBName, branch[i].bDefault)!=0?2:1;
+ tvis.item.state=INDEXTOSTATEIMAGEMASK(iState);
+ hItemB[i] = TreeView_InsertItem(hwndTree, &tvis);
+} }
+
+static void SaveBranch(HWND hwndTree, const struct branch_t *branch, HTREEITEM *hItemB, int nValues)
+{
+ TVITEM tvi;
+ BYTE bChecked;
+ int i;
+ int iState = 0;
+
+ tvi.mask=TVIF_HANDLE|TVIF_STATE;
+ for (i=0;i<nValues;i++) {
+ tvi.hItem = hItemB[i];
+ TreeView_GetItem(hwndTree,&tvi);
+ bChecked = ((tvi.state&TVIS_STATEIMAGEMASK)>>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; i<OPTIONS_FONTCOUNT; i++)
+ LoadMsgDlgFont(i, &aFonts[i].lf, &aFonts[i].color);
+}
+
+void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF* colour)
+{
+ char str[32];
+ int style;
+ DBVARIANT dbv;
+
+ if (colour) {
+ wsprintfA(str, "Font%dCol", i);
+ *colour = DBGetContactSettingDword(NULL, "ChatFonts", str, fontOptionsList[i].defColour);
+ }
+ if (lf) {
+ wsprintfA(str, "Font%dSize", i);
+ lf->lfHeight = (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 <windows.h>
+#include <stdio.h>
+#include <richedit.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.
+*/
+// 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)&gtl, 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 <m_version.h>
+
+#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)&gtl, (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)&gt, (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)&gtl, (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)&gtl, (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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>StdClist</ProjectName>
+ <ProjectGuid>{E71C1722-A41D-4475-87F4-29961A3654BB}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x6590000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x6590000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27X86%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x6590000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalManifestDependencies>type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x6590000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clcfonts.cpp" />
+ <ClCompile Include="src\clcopts.cpp" />
+ <ClCompile Include="src\clcpaint.cpp" />
+ <ClCompile Include="src\clistmenus.cpp" />
+ <ClCompile Include="src\clistopts.cpp" />
+ <ClCompile Include="src\cluiopts.cpp" />
+ <ClCompile Include="src\init.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\clc.h" />
+ <ClInclude Include="src\commonheaders.h" />
+ <ClInclude Include="src\resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\blank.ico" />
+ <None Include="res\dragcopy.cur" />
+ <None Include="res\dropuser.cur" />
+ <None Include="res\hyperlin.cur" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ <ResourceCompile Include="res\version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{63109169-73b5-4fd9-b189-bfe8ca62f233}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{952f01d3-995f-456b-98ff-785b549b289d}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{97bb8e2e-2508-4f05-bdcf-376efae7e97c}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\clcfonts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\clcopts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\clcpaint.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\clistmenus.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\clistopts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\cluiopts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\init.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\clc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\commonheaders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\blank.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\dragcopy.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\dropuser.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\hyperlin.cur">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="res\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/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
--- /dev/null
+++ b/src/core/stdclist/res/blank.ico
Binary files differ
diff --git a/src/core/stdclist/res/dragcopy.cur b/src/core/stdclist/res/dragcopy.cur
new file mode 100644
index 0000000000..89c7c960d5
--- /dev/null
+++ b/src/core/stdclist/res/dragcopy.cur
Binary files differ
diff --git a/src/core/stdclist/res/dropuser.cur b/src/core/stdclist/res/dropuser.cur
new file mode 100644
index 0000000000..a84b19e28b
--- /dev/null
+++ b/src/core/stdclist/res/dropuser.cur
Binary files differ
diff --git a/src/core/stdclist/res/hyperlin.cur b/src/core/stdclist/res/hyperlin.cur
new file mode 100644
index 0000000000..f0f548c828
--- /dev/null
+++ b/src/core/stdclist/res/hyperlin.cur
Binary files 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 <windows.h>
+#include <winres.h>
+#include <statusmodes.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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 <windows.h>\r\n"
+ "#include <winres.h>\r\n"
+ "#include <statusmodes.h>\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 <windows.h>
+#include <vssym32.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <time.h>
+#include <stddef.h>
+#include <process.h>
+#include <io.h>
+#include <string.h>
+#include <direct.h>
+
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_clistint.h>
+#include <m_clui.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_options.h>
+#include <m_modernopt.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_file.h>
+#include <m_addcontact.h>
+#include <m_icolib.h>
+
+#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 <m_version.h>
+
+#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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/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
--- /dev/null
+++ b/src/core/stdmsg/res/dragcopy.cur
Binary files differ
diff --git a/src/core/stdmsg/res/dropuser.cur b/src/core/stdmsg/res/dropuser.cur
new file mode 100644
index 0000000000..a84b19e28b
--- /dev/null
+++ b/src/core/stdmsg/res/dropuser.cur
Binary files differ
diff --git a/src/core/stdmsg/res/hyperlin.cur b/src/core/stdmsg/res/hyperlin.cur
new file mode 100644
index 0000000000..f0f548c828
--- /dev/null
+++ b/src/core/stdmsg/res/hyperlin.cur
Binary files differ
diff --git a/src/core/stdmsg/res/incoming.ico b/src/core/stdmsg/res/incoming.ico
new file mode 100644
index 0000000000..fabbf979cc
--- /dev/null
+++ b/src/core/stdmsg/res/incoming.ico
Binary files differ
diff --git a/src/core/stdmsg/res/notice.ico b/src/core/stdmsg/res/notice.ico
new file mode 100644
index 0000000000..23527a94d8
--- /dev/null
+++ b/src/core/stdmsg/res/notice.ico
Binary files differ
diff --git a/src/core/stdmsg/res/outgoing.ico b/src/core/stdmsg/res/outgoing.ico
new file mode 100644
index 0000000000..f772ab3f8d
--- /dev/null
+++ b/src/core/stdmsg/res/outgoing.ico
Binary files 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 <winres.h>
+#include <richedit.h>
+#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 <winres.h>\r\n"
+ "#include <richedit.h>\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 <m_stdhdr.h>
+
+#include <windows.h>
+#include <windowsx.h>
+#include <ole2.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <vssym32.h>
+
+#include <time.h>
+
+#include "resource.h"
+
+#include <win2k.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_icolib.h>
+#include <m_fontservice.h>
+#include <m_timezones.h>
+#include <m_avatars.h>
+
+#include "cmdlist.h"
+#include "msgs.h"
+#include "globals.h"
+#include "richutil.h"
+#include "version.h"
+
+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.top<dat->minEditBoxSize.cy) {
+ SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER));
+ }
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ break;
+
+ case DM_GETAVATAR:
+ {
+ PROTO_AVATAR_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 <richedit.h>
+#include <richole.h>
+
+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) &param);
+}
+
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 <m_version.h>
+
+#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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>StdMsg</ProjectName>
+ <ProjectGuid>{F47EAB99-C78F-4A92-87D5-B0E16FE5A133}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30128.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Core\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <ExceptionHandling>false</ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ <ExceptionHandling>false</ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ <AdditionalOptions>/PDBALTPATH:%_PDB%</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>false</StringPooling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>commonheaders.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..\include;..\..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(SolutionDir)\lib</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\cmdlist.cpp" />
+ <ClCompile Include="src\globals.cpp" />
+ <ClCompile Include="src\msgdialog.cpp" />
+ <ClCompile Include="src\msglog.cpp" />
+ <ClCompile Include="src\msgoptions.cpp" />
+ <ClCompile Include="src\msgs.cpp" />
+ <ClCompile Include="src\msgtimedout.cpp" />
+ <ClCompile Include="src\richutil.cpp" />
+ <ClCompile Include="src\srmm.cpp">
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\statusicon.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\cmdlist.h" />
+ <ClInclude Include="src\commonheaders.h" />
+ <ClInclude Include="src\globals.h" />
+ <ClInclude Include="src\msgs.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\richutil.h" />
+ <ClInclude Include="src\statusicon.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ <ResourceCompile Include="res\version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{8927e967-671b-4c16-8208-54dec5f31489}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{6ae44719-2dc0-4659-bb57-b80bc11f0eb2}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{ed6d6a77-6f3c-4512-afc9-7c872bee5ded}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\cmdlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\globals.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\msgdialog.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\msglog.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\msgoptions.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\msgs.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\msgtimedout.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\richutil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\srmm.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\statusicon.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\cmdlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\commonheaders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\globals.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\msgs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\richutil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\statusicon.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="res\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ 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"